elastic-recheck/elastic_recheck/tests/unit/test_results.py
Ramy Asselin de437439ad Wait until the most recent index is available
When elastic search indexing is behind, and the day has
progressed forward to a new day,  the latest
index is not yet available for use. Exclude it from searches
until it is ready in order to avoid the ElasticHttpNotFoundError.

Add Unit tests for this case as well as for when multiple days
are specified for the search.

Change-Id: Ifd27d1ab21bebcb63b48ea164f425c4a2ac8759c
2016-10-20 10:48:55 -07:00

187 lines
7.6 KiB
Python

# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import json
import mock
import pyelasticsearch
from elastic_recheck import results
from elastic_recheck import tests
def load_sample(bug):
with open("elastic_recheck/tests/unit/samples/bug-%s.json" % bug) as f:
return json.load(f)
class TestBasicParsing(tests.TestCase):
def test_basic_parse(self):
data = load_sample(1191960)
result_set = results.ResultSet(data)
self.assertEqual(len(result_set), 144)
self.assertEqual(result_set.took, 45)
hit1 = result_set[0]
self.assertEqual(hit1.build_status, "SUCCESS")
self.assertEqual(hit1.build_patchset, "3")
self.assertEqual(hit1.project, "openstack/tempest")
self.assertEqual(hit1.timestamp, "2013-10-18T17:39:43.966Z")
def test_full_iteration(self):
data = load_sample(1240256)
result_set = results.ResultSet(data)
self.assertEqual(len(result_set), 95)
self.assertEqual(result_set.took, 78)
for result in result_set:
self.assertEqual(result.build_status, "FAILURE")
def test_facet_one_level(self):
data = load_sample(1218391)
result_set = results.ResultSet(data)
facets = results.FacetSet()
facets.detect_facets(result_set, ["build_uuid"])
self.assertEqual(len(facets.keys()), 20)
facets = results.FacetSet()
facets.detect_facets(result_set, ["build_status"])
self.assertEqual(facets.keys(), ['FAILURE'])
data = load_sample(1226337)
result_set = results.ResultSet(data)
facets = results.FacetSet()
facets.detect_facets(result_set, ["build_status"])
self.assertEqual(len(facets.keys()), 2)
self.assertIn('FAILURE', facets.keys())
self.assertIn('SUCCESS', facets.keys())
self.assertEqual(len(facets['FAILURE']), 202)
self.assertEqual(len(facets['SUCCESS']), 27)
def test_facet_multi_level(self):
data = load_sample(1226337)
result_set = results.ResultSet(data)
facets = results.FacetSet()
facets.detect_facets(result_set, ["build_status", "build_uuid"])
self.assertEqual(len(facets.keys()), 2)
self.assertEqual(len(facets['FAILURE'].keys()), 12)
self.assertEqual(len(facets['SUCCESS'].keys()), 3)
def test_facet_histogram(self):
data = load_sample(1226337)
result_set = results.ResultSet(data)
facets = results.FacetSet()
facets.detect_facets(result_set,
["timestamp", "build_status", "build_uuid"])
self.assertEqual(len(facets.keys()), 14)
print facets[1382104800000].keys()
self.assertEqual(facets[1382104800000].keys(), ["FAILURE"])
self.assertEqual(len(facets[1382104800000]["FAILURE"]), 2)
self.assertEqual(facets[1382101200000].keys(), ["FAILURE"])
# NOTE(mriedem): We can't mock built-ins so we have to override utcnow().
class MockDatetimeToday(datetime.datetime):
def __init__(self, *args):
super(MockDatetimeToday, self).__init__(*args)
@classmethod
def utcnow(cls):
# One hour and one second into today.
return datetime.datetime.strptime('2014-06-12T01:00:01',
'%Y-%m-%dT%H:%M:%S')
class MockDatetimeYesterday(datetime.datetime):
def __init__(self, *args):
super(MockDatetimeYesterday, self).__init__(*args)
@classmethod
def utcnow(cls):
# 59 minutes and 59 seconds into today.
return datetime.datetime.strptime('2014-06-12T00:59:59',
'%Y-%m-%dT%H:%M:%S')
@mock.patch.object(pyelasticsearch.ElasticSearch, 'search', return_value={})
class TestSearchEngine(tests.TestCase):
"""Tests that the elastic search API is called correctly."""
def setUp(self):
super(TestSearchEngine, self).setUp()
self.engine = results.SearchEngine('http://fake-url')
self.query = 'message:"foo" AND tags:"console"'
def test_search_not_recent(self, search_mock):
# Tests a basic search with recent=False.
result_set = self.engine.search(self.query, size=10)
self.assertEqual(0, len(result_set))
search_mock.assert_called_once_with(self.query, size=10)
def _test_search_recent(self, search_mock, datetime_mock,
expected_indexes):
datetime.datetime = datetime_mock
result_set = self.engine.search(self.query, size=10, recent=True)
self.assertEqual(0, len(result_set))
search_mock.assert_called_once_with(
self.query, size=10, index=expected_indexes)
def test_search_recent_current_index_only(self, search_mock):
# The search index comparison goes back one hour and cuts off by day,
# so test that we're one hour and one second into today so we only have
# one index in the search call.
with mock.patch.object(
pyelasticsearch.ElasticSearch, 'status') as mock_data:
mock_data.return_value = "Not an exception"
self._test_search_recent(search_mock, MockDatetimeToday,
expected_indexes=['logstash-2014.06.12'])
def test_search_recent_multiple_indexes(self, search_mock):
# The search index comparison goes back one hour and cuts off by day,
# so test that we're 59 minutes and 59 seconds into today so that we
# have an index for today and yesterday in the search call.
with mock.patch.object(
pyelasticsearch.ElasticSearch, 'status') as mock_data:
mock_data.return_value = "Not an exception"
self._test_search_recent(search_mock, MockDatetimeYesterday,
expected_indexes=['logstash-2014.06.12',
'logstash-2014.06.11'])
def test_search_no_indexes(self, search_mock):
# Test when no indexes are valid
with mock.patch.object(
pyelasticsearch.ElasticSearch, 'status') as mock_data:
mock_data.side_effect = pyelasticsearch.exceptions.\
ElasticHttpNotFoundError()
self._test_search_recent(search_mock, MockDatetimeYesterday,
expected_indexes=[])
def test_search_days(self, search_mock):
# Test when specific days are used.
with mock.patch.object(
pyelasticsearch.ElasticSearch, 'status') as mock_data:
mock_data.return_value = "Not an exception"
datetime.datetime = MockDatetimeYesterday
result_set = self.engine.search(self.query, size=10, days=3,
recent=False)
self.assertEqual(0, len(result_set))
search_mock.assert_called_once_with(self.query, size=10,
index=['logstash-2014.06.12',
'logstash-2014.06.11',
'logstash-2014.06.10'])