Merge "moving readiness checks into stream"

This commit is contained in:
Jenkins 2014-01-16 21:11:36 +00:00 committed by Gerrit Code Review
commit 9a195644d1
9 changed files with 563 additions and 307 deletions

View File

@ -144,8 +144,7 @@ class RecheckWatch(threading.Thread):
change_id = "%s,%s" % (change, rev) change_id = "%s,%s" % (change, rev)
project = event['change']['project'] project = event['change']['project']
try: try:
bug_numbers = classifier.classify(change, rev, bug_numbers = classifier.classify(change, rev)
event['comment'])
if not bug_numbers: if not bug_numbers:
self._read(event) self._read(event)
else: else:

View File

@ -17,7 +17,6 @@
import gerritlib.gerrit import gerritlib.gerrit
import pyelasticsearch import pyelasticsearch
import urllib2
import ConfigParser import ConfigParser
import logging import logging
@ -32,16 +31,24 @@ from elastic_recheck import results
logging.basicConfig() logging.basicConfig()
ES_URL = "http://logstash.openstack.org/elasticsearch"
REQUIRED_FILES = [
'console.html', def required_files(job):
files = ['console.html']
if re.match("tempest-dsvm", job):
files.extend([
'logs/screen-n-api.txt', 'logs/screen-n-api.txt',
'logs/screen-n-cpu.txt', 'logs/screen-n-cpu.txt',
'logs/screen-n-sch.txt', 'logs/screen-n-sch.txt',
'logs/screen-c-api.txt', 'logs/screen-c-api.txt',
'logs/screen-c-vol.txt', 'logs/screen-c-vol.txt',
'logs/syslog.txt', 'logs/syslog.txt'])
] return files
class ResultNotReady(Exception):
pass
class Stream(object): class Stream(object):
@ -55,6 +62,7 @@ class Stream(object):
def __init__(self, user, host, key, thread=True): def __init__(self, user, host, key, thread=True):
port = 29418 port = 29418
self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key) self.gerrit = gerritlib.gerrit.Gerrit(host, user, port, key)
self.es = results.SearchEngine(ES_URL)
if thread: if thread:
self.gerrit.startWatching() self.gerrit.startWatching()
@ -79,40 +87,82 @@ class Stream(object):
failed_tests[m.group(1)] = m.group(2) failed_tests[m.group(1)] = m.group(2)
return failed_tests return failed_tests
def _failed_unit_tests(self, line): def _job_console_uploaded(self, change, patch, name):
"""Did we fail unit tests? If so not a valid failure.""" query = qb.result_ready(change, patch, name)
fail = ("FAILURE" in line and ("python2" in line or "pep8" in line)) r = self.es.search(query, size='10')
if fail: if len(r) == 0:
self.log.debug("Failed unit tests, skipping this result") raise ResultNotReady()
return fail
def _valid_failure(self, line): def _has_required_files(self, change, patch, name):
"""Is this the kind of failure we track.""" query = qb.files_ready(change, patch)
return "FAILURE" in line and "tempest" in line r = self.es.search(query, size='80')
files = [x['term'] for x in r.terms]
required = required_files(name)
missing_files = [x for x in required if x not in files]
if len(missing_files) != 0:
raise ResultNotReady()
def _does_es_have_data(self, change_number, patch_number, job_fails):
"""Wait till ElasticSearch is ready, but return False if timeout."""
NUMBER_OF_RETRIES = 20
SLEEP_TIME = 40
# this checks that we've got the console log uploaded, need to retry
# in case ES goes bonkers on cold data, which it does some times.
for i in range(NUMBER_OF_RETRIES):
try:
for job_name in job_fails:
self._job_console_uploaded(
change_number, patch_number, job_name)
break
except ResultNotReady:
time.sleep(SLEEP_TIME)
continue
except pyelasticsearch.exceptions.InvalidJsonResponseError:
# If ElasticSearch returns an error code, sleep and retry
# TODO(jogo): if this works pull out search into a helper
# function that does this.
self.log.exception(
"Elastic Search not responding on attempt %d" % i)
time.sleep(NUMBER_OF_RETRIES)
continue
if i == NUMBER_OF_RETRIES - 1:
return False
self.log.debug(
"Found hits for change_number: %s, patch_number: %s"
% (change_number, patch_number))
for i in range(NUMBER_OF_RETRIES):
try:
for job_name in job_fails:
self._has_required_files(
change_number, patch_number, job_name)
self.log.debug(
"All files present for change_number: %s, patch_number: %s"
% (change_number, patch_number))
time.sleep(10)
return True
except ResultNotReady:
time.sleep(SLEEP_TIME)
# if we get to the end, we're broken
return False
def get_failed_tempest(self): def get_failed_tempest(self):
self.log.debug("entering get_failed_tempest") self.log.debug("entering get_failed_tempest")
while True: while True:
event = self.gerrit.getEvent() event = self.gerrit.getEvent()
failed_jobs = Stream.parse_jenkin_failure(event) failed_jobs = Stream.parse_jenkins_failure(event)
if not failed_jobs: if not failed_jobs:
# nothing to see here, lets try the next event # nothing to see here, lets try the next event
continue continue
self.log.debug("potential failed_tempest") change = event['change']['number']
found = False rev = event['patchSet']['number']
for line in event['comment'].split('\n'): if self._does_es_have_data(change, rev, failed_jobs):
if self._failed_unit_tests(line):
found = False
break
if self._valid_failure(line):
url = [x for x in line.split() if "http" in x][0]
if RequiredFiles.files_at_url(url):
self.log.debug("All file present")
found = True
if found:
return event return event
continue
def leave_comment(self, project, commit, bugs=None): def leave_comment(self, project, commit, bugs=None):
if bugs: if bugs:
@ -147,12 +197,11 @@ class Classifier():
that are mapped to specific bugs. that are mapped to specific bugs.
""" """
log = logging.getLogger("recheckwatchbot") log = logging.getLogger("recheckwatchbot")
ES_URL = "http://logstash.openstack.org/elasticsearch"
queries = None queries = None
def __init__(self, queries_dir): def __init__(self, queries_dir):
self.es = results.SearchEngine(self.ES_URL) self.es = results.SearchEngine(ES_URL)
self.queries_dir = queries_dir self.queries_dir = queries_dir
self.queries = loader.load(self.queries_dir) self.queries = loader.load(self.queries_dir)
@ -160,20 +209,11 @@ class Classifier():
es_query = qb.generic(query, facet=facet) es_query = qb.generic(query, facet=facet)
return self.es.search(es_query, size=size) return self.es.search(es_query, size=size)
def classify(self, change_number, patch_number, comment, def classify(self, change_number, patch_number, skip_resolved=True):
skip_resolved=True):
"""Returns either empty list or list with matched bugs.""" """Returns either empty list or list with matched bugs."""
self.log.debug("Entering classify") self.log.debug("Entering classify")
#Reload each time #Reload each time
self.queries = loader.load(self.queries_dir, skip_resolved) self.queries = loader.load(self.queries_dir, skip_resolved)
#Wait till Elastic search is ready
self.log.debug("checking if ElasticSearch is ready")
if not self._is_ready(change_number, patch_number, comment):
self.log.error(
"something went wrong, ElasticSearch is still not ready, "
"giving up and trying next failure")
return None
self.log.debug("ElasticSearch is ready, starting to classify")
bug_matches = [] bug_matches = []
for x in self.queries: for x in self.queries:
self.log.debug( self.log.debug(
@ -181,89 +221,10 @@ class Classifier():
% x['bug']) % x['bug'])
query = qb.single_patch(x['query'], change_number, patch_number) query = qb.single_patch(x['query'], change_number, patch_number)
results = self.es.search(query, size='10') results = self.es.search(query, size='10')
if self._urls_match(comment, results): if len(results) > 0:
bug_matches.append(x['bug']) bug_matches.append(x['bug'])
return bug_matches return bug_matches
def _is_ready(self, change_number, patch_number, comment):
"""Wait till ElasticSearch is ready, but return False if timeout."""
NUMBER_OF_RETRIES = 20
SLEEP_TIME = 40
query = qb.result_ready(change_number, patch_number)
for i in range(NUMBER_OF_RETRIES):
try:
results = self.es.search(query, size='10')
except pyelasticsearch.exceptions.InvalidJsonResponseError:
# If ElasticSearch returns an error code, sleep and retry
# TODO(jogo): if this works pull out search into a helper
# function that does this.
print "UHUH hit InvalidJsonResponseError"
time.sleep(NUMBER_OF_RETRIES)
continue
if (len(results) > 0 and self._urls_match(comment, results)):
break
else:
time.sleep(SLEEP_TIME)
if i == NUMBER_OF_RETRIES - 1:
return False
self.log.debug(
"Found hits for change_number: %s, patch_number: %s"
% (change_number, patch_number))
query = qb.files_ready(change_number, patch_number)
for i in range(NUMBER_OF_RETRIES):
results = self.es.search(query, size='80')
files = [x['term'] for x in results.terms]
missing_files = [x for x in REQUIRED_FILES if x not in files]
if len(missing_files) is 0:
break
else:
time.sleep(SLEEP_TIME)
if i == NUMBER_OF_RETRIES - 1:
return False
self.log.debug(
"All files present for change_number: %s, patch_number: %s"
% (change_number, patch_number))
# Just because one file is parsed doesn't mean all are, so wait a
# bit
time.sleep(10)
return True
def _urls_match(self, comment, results):
for result in results:
url = result.log_url
if RequiredFiles.prep_url(url) in comment:
return True
return False
class RequiredFiles(object):
log = logging.getLogger("recheckwatchbot")
@staticmethod
def prep_url(url):
if isinstance(url, list):
# The url is sometimes a list of one value
url = url[0]
if "/logs/" in url:
return '/'.join(url.split('/')[:-2])
return '/'.join(url.split('/')[:-1])
@staticmethod
def files_at_url(url):
for f in REQUIRED_FILES:
try:
urllib2.urlopen(url + '/' + f)
except urllib2.HTTPError:
try:
urllib2.urlopen(url + '/' + f + '.gz')
except urllib2.HTTPError:
# File does not exist at URL
RequiredFiles.log.debug("missing file %s" % f)
return False
return True
def main(): def main():
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
@ -285,7 +246,7 @@ def main():
rev = event['patchSet']['number'] rev = event['patchSet']['number']
print "=======================" print "======================="
print "https://review.openstack.org/#/c/%(change)s/%(rev)s" % locals() print "https://review.openstack.org/#/c/%(change)s/%(rev)s" % locals()
bug_numbers = classifier.classify(change, rev, event['comment']) bug_numbers = classifier.classify(change, rev)
if not bug_numbers: if not bug_numbers:
print "unable to classify failure" print "unable to classify failure"
else: else:

View File

@ -59,7 +59,7 @@ def generic(raw_query, facet=None):
return query return query
def result_ready(review=None, patch=None): def result_ready(review=None, patch=None, name=None):
"""A query to determine if we have a failure for a particular patch. """A query to determine if we have a failure for a particular patch.
This is looking for a particular FAILURE line in the console log, which This is looking for a particular FAILURE line in the console log, which
@ -70,8 +70,9 @@ def result_ready(review=None, patch=None):
'OR message:"[SCP] Copying console log") ' 'OR message:"[SCP] Copying console log") '
'AND build_status:"FAILURE" ' 'AND build_status:"FAILURE" '
'AND build_change:"%s" ' 'AND build_change:"%s" '
'AND build_patchset:"%s"' % 'AND build_patchset:"%s" '
(review, patch)) 'AND build_name:"%s"' %
(review, patch, name))
def files_ready(review, patch): def files_ready(review, patch):

View File

@ -0,0 +1,35 @@
# Copyright 2014 Samsung Electronics. 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 json
class GerritDone(Exception):
pass
class Gerrit(object):
"""A fake gerrit libobject that emits a bunch of events."""
def __init__(self, *args):
with open("elastic_recheck/tests/unit/gerrit/events.json") as f:
self.events = json.load(f)
def startWatching(self):
pass
def getEvent(self):
if len(self.events) > 0:
return self.events.pop()
else:
raise GerritDone()

View File

@ -0,0 +1,402 @@
[
{
"comment": "Build succeeded.\n\n- gate-keystone-pep8 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-pep8\/5ef9f24 : SUCCESS in 1m 40s\n- gate-keystone-docs http:\/\/docs-draft.openstack.org\/44\/60244\/12\/check\/gate-keystone-docs\/60c7b1b\/doc\/build\/html\/ : SUCCESS in 4m 01s\n- gate-keystone-python26 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-python26\/d66253a : SUCCESS in 18m 02s\n- gate-keystone-python27 http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-keystone-python27\/04102a5 : SUCCESS in 13m 57s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-full\/0893acf : SUCCESS in 42m 30s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-postgres-full\/671d371 : SUCCESS in 49m 30s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-tempest-dsvm-neutron\/4981e54 : SUCCESS in 35m 09s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-tempest-dsvm-large-ops\/9e825fb : SUCCESS in 13m 11s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/44\/60244\/12\/check\/gate-tempest-dsvm-neutron-large-ops\/286d887 : SUCCESS in 13m 22s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-grenade-dsvm\/b3b7478 : SUCCESS in 32m 01s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/44\/60244\/12\/check\/check-swift-dsvm-functional\/350f34c : SUCCESS in 13m 12s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "1"
}
],
"patchSet": {
"createdOn": 1389371115,
"ref": "refs\/changes\/44\/60244\/12",
"number": "12",
"uploader": {
"username": "stevemar",
"name": "Steve Martinelli",
"email": "stevemar@ca.ibm.com"
},
"revision": "74d75a1050c96eef498e9daaa80fcb9652003a20"
},
"type": "comment-added",
"change": {
"topic": "bp\/mapping",
"url": "https:\/\/review.openstack.org\/60244",
"number": "60244",
"project": "openstack\/keystone",
"branch": "master",
"owner": {
"username": "marek-denis",
"name": "Marek Denis",
"email": "marek.denis@cern.ch"
},
"id": "I0ce62e720e797718dbfde6bfcd4b22a213985867",
"subject": "Identity Providers CRUD operations."
}
},
{
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-requirements-pep8 http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-pep8\/e8429d9 : SUCCESS in 25s\n- gate-requirements-python27 http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-python27\/fb66d97 : SUCCESS in 1m 09s\n- gate-requirements-pypy http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-requirements-pypy\/592002c : SUCCESS in 2m 09s\n- check-requirements-integration-dsvm http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-requirements-integration-dsvm\/8209fb4 : FAILURE in 9m 44s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-full\/0db6b3f : SUCCESS in 48m 02s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-postgres-full\/4a0c319 : SUCCESS in 45m 10s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-tempest-dsvm-neutron\/f4323cc : SUCCESS in 36m 49s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-tempest-dsvm-large-ops\/1e625fc : SUCCESS in 17m 31s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/61\/65361\/2\/check\/gate-tempest-dsvm-neutron-large-ops\/ffa7ae8 : SUCCESS in 14m 24s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-grenade-dsvm\/c416726 : SUCCESS in 31m 26s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/61\/65361\/2\/check\/check-swift-dsvm-functional\/d027be3 : SUCCESS in 14m 30s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "-1"
}
],
"patchSet": {
"createdOn": 1389384794,
"ref": "refs\/changes\/61\/65361\/2",
"number": "2",
"uploader": {
"username": "jaegerandi",
"name": "Andreas Jaeger",
"email": "jaegerandi@gmail.com"
},
"revision": "10d31584a0696cd77200a8fee45900d2343e295e"
},
"type": "comment-added",
"change": {
"topic": "65361",
"url": "https:\/\/review.openstack.org\/65361",
"number": "65361",
"project": "openstack\/requirements",
"branch": "master",
"owner": {
"username": "jaegerandi",
"name": "Andreas Jaeger",
"email": "jaegerandi@gmail.com"
},
"id": "Id6a79d3596c6cfaab92cfb8fc89d4298db61b7f0",
"subject": "Add openstack-doc-tools"
}
},
{
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-horizon-pep8 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-pep8\/37c96e0 : SUCCESS in 2m 54s\n- gate-horizon-docs http:\/\/docs-draft.openstack.org\/78\/63078\/19\/check\/gate-horizon-docs\/53f3535\/doc\/build\/html\/ : SUCCESS in 7m 10s\n- gate-horizon-python26 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python26\/1006347 : SUCCESS in 4m 15s\n- gate-horizon-python27 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python27\/a9fb840 : SUCCESS in 4m 07s\n- gate-horizon-python27-django14 http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-python27-django14\/1f9c8e5 : SUCCESS in 5m 18s\n- gate-horizon-selenium http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-horizon-selenium\/b215898 : SUCCESS in 3m 08s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-full\/ab07162 : FAILURE in 54m 09s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-postgres-full\/9bed62d : SUCCESS in 52m 49s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-tempest-dsvm-neutron\/06a24c0 : SUCCESS in 36m 00s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-tempest-dsvm-large-ops\/a522f39 : SUCCESS in 13m 33s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/78\/63078\/19\/check\/gate-tempest-dsvm-neutron-large-ops\/bcbe1da : SUCCESS in 13m 38s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/78\/63078\/19\/check\/check-grenade-dsvm\/9c5b5d0 : SUCCESS in 27m 49s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "-1"
}
],
"patchSet": {
"createdOn": 1389383805,
"ref": "refs\/changes\/78\/63078\/19",
"number": "19",
"uploader": {
"username": "yves",
"name": "Yves-Gwenael Bourhis",
"email": "yves-gwenael.bourhis@cloudwatt.com"
},
"revision": "2e5a51c3f4e0121dbaf47c13b12809f6e7820d09"
},
"type": "comment-added",
"change": {
"topic": "bp\/image-flavor-selection-ux-enhancement",
"url": "https:\/\/review.openstack.org\/63078",
"number": "63078",
"project": "openstack\/horizon",
"branch": "master",
"owner": {
"username": "yves",
"name": "Yves-Gwenael Bourhis",
"email": "yves-gwenael.bourhis@cloudwatt.com"
},
"id": "I6674ed1983904334c98a7b7d71c58a393858cbc4",
"subject": "Changed LaunchInstance workflow to wizard mode"
}
},
{
"comment": "Build succeeded.\n\n- check-dg-tempest-dsvm-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-dg-tempest-dsvm-full\/6762ddb : SUCCESS in 51m 22s\n- check-dg-tempest-dsvm-full-reexec http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-dg-tempest-dsvm-full-reexec\/e97d803 : SUCCESS in 55m 24s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full\/9181576 : SUCCESS in 1h 04m 35s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full\/74b4386 : SUCCESS in 1h 29m 32s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron\/54850dd : SUCCESS in 39m 48s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/05\/65805\/1\/check\/gate-tempest-dsvm-large-ops\/18d9e01 : SUCCESS in 13m 58s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/05\/65805\/1\/check\/gate-tempest-dsvm-neutron-large-ops\/ee4b7eb : SUCCESS in 14m 12s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-grenade-dsvm\/d1e83f8 : SUCCESS in 35m 05s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-swift-dsvm-functional\/5f30c9f : SUCCESS in 15m 23s\n- check-tempest-dsvm-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full-grizzly\/1b8d155 : FAILURE in 57m 18s (non-voting)\n- check-tempest-dsvm-neutron-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron-grizzly\/70ee0a6 : SUCCESS in 22m 14s (non-voting)\n- check-tempest-dsvm-postgres-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full-grizzly\/fa497b2 : FAILURE in 46m 51s (non-voting)\n- check-devstack-dsvm-cells-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-devstack-dsvm-cells-grizzly\/5318390 : FAILURE in 13m 30s (non-voting)\n- check-tempest-dsvm-cells-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-grizzly\/c01c8a0 : FAILURE in 28m 36s (non-voting)\n- check-tempest-dsvm-cells-full-grizzly http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-full-grizzly\/78b0d12 : FAILURE in 42m 59s (non-voting)\n- check-tempest-dsvm-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-full-havana\/183d433 : SUCCESS in 51m 17s (non-voting)\n- check-tempest-dsvm-neutron-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-neutron-havana\/85453e1 : SUCCESS in 31m 06s (non-voting)\n- check-tempest-dsvm-postgres-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-postgres-full-havana\/5243bb4 : SUCCESS in 41m 37s (non-voting)\n- check-devstack-dsvm-cells-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-devstack-dsvm-cells-havana\/9432a96 : SUCCESS in 11m 11s (non-voting)\n- check-tempest-dsvm-cells-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-havana\/d856118 : FAILURE in 15m 25s (non-voting)\n- check-tempest-dsvm-cells-full-havana http:\/\/logs.openstack.org\/05\/65805\/1\/check\/check-tempest-dsvm-cells-full-havana\/cc09d3c : FAILURE in 25m 32s (non-voting)\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "1"
}
],
"patchSet": {
"createdOn": 1389306576,
"ref": "refs\/changes\/05\/65805\/1",
"number": "1",
"uploader": {
"username": "russellb",
"name": "Russell Bryant",
"email": "rbryant@redhat.com"
},
"revision": "3ca110f8dc6a552e951074faaca3a11ce65e40f3"
},
"type": "comment-added",
"change": {
"topic": "slow-down-there-cowboy",
"url": "https:\/\/review.openstack.org\/65805",
"number": "65805",
"project": "openstack-infra\/devstack-gate",
"branch": "master",
"owner": {
"username": "russellb",
"name": "Russell Bryant",
"email": "rbryant@redhat.com"
},
"id": "I2338ebf5df8bced935e9ed9b0ebd2d4e859b5dbe",
"subject": "Cut tempest concurrency in half"
}
},
{
"comment": "Build succeeded.\n\n- gate-noop http:\/\/logs.openstack.org\/78\/65378\/15\/check\/gate-noop\/05e95c4 : SUCCESS in 0s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "1"
}
],
"patchSet": {
"createdOn": 1389391347,
"ref": "refs\/changes\/78\/65378\/15",
"number": "15",
"uploader": {
"username": "diane-fleming",
"name": "Diane Fleming",
"email": "diane.fleming@rackspace.com"
},
"revision": "4fe4f8b6dda390c432b2c6d2f6cff2152d3475f3"
},
"type": "comment-added",
"change": {
"topic": "1187119-a",
"url": "https:\/\/review.openstack.org\/65378",
"number": "65378",
"project": "openstack\/api-site",
"branch": "master",
"owner": {
"username": "diane-fleming",
"name": "Diane Fleming",
"email": "diane.fleming@rackspace.com"
},
"id": "I82331b1c3cfc5b19f91f7ac1379476e6a9e6806d",
"subject": "Update object-api wadl with comments from Donagh"
}
},
{
"comment": "Build failed. For information on how to proceed, see https:\/\/wiki.openstack.org\/wiki\/GerritJenkinsGit#Test_Failures\n\n- gate-keystone-pep8 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-pep8\/16e0b97 : SUCCESS in 2m 25s\n- gate-keystone-docs http:\/\/docs-draft.openstack.org\/49\/64749\/6\/check\/gate-keystone-docs\/77c8f7a\/doc\/build\/html\/ : SUCCESS in 5m 25s\n- gate-keystone-python26 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-python26\/d3fd328 : FAILURE in 18m 04s\n- gate-keystone-python27 http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-keystone-python27\/5dd41fe : FAILURE in 10m 01s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-full\/fce905d : SUCCESS in 46m 00s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-postgres-full\/e5cd968 : SUCCESS in 53m 30s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-tempest-dsvm-neutron\/0673b30 : SUCCESS in 37m 25s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-tempest-dsvm-large-ops\/bdc661a : SUCCESS in 13m 21s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/49\/64749\/6\/check\/gate-tempest-dsvm-neutron-large-ops\/991887c : SUCCESS in 12m 28s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-grenade-dsvm\/d098069 : SUCCESS in 31m 05s\n- check-swift-dsvm-functional http:\/\/logs.openstack.org\/49\/64749\/6\/check\/check-swift-dsvm-functional\/2f9377b : SUCCESS in 11m 56s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "-1"
}
],
"patchSet": {
"createdOn": 1389378289,
"ref": "refs\/changes\/49\/64749\/6",
"number": "6",
"uploader": {
"username": "blk-u",
"name": "Brant Knudson",
"email": "bknudson@us.ibm.com"
},
"revision": "06b14616cb2a11514b0c151cc213c1ab5cea324b"
},
"type": "comment-added",
"change": {
"topic": "bug\/1265108",
"url": "https:\/\/review.openstack.org\/64749",
"number": "64749",
"project": "openstack\/keystone",
"branch": "master",
"owner": {
"username": "blk-u",
"name": "Brant Knudson",
"email": "bknudson@us.ibm.com"
},
"id": "I890a1c798d7f4a8a345404cd7754708ab0d36651",
"subject": "Enhance auth tests for non-default default_domain_id"
}
},
{
"comment": "Build succeeded.\n\n- gate-neutron-pep8 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-pep8\/0ef123c : SUCCESS in 2m 13s\n- gate-neutron-docs http:\/\/docs-draft.openstack.org\/02\/65902\/3\/check\/gate-neutron-docs\/4a7a2ce\/doc\/build\/html\/ : SUCCESS in 1m 43s\n- gate-neutron-python26 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-python26\/d3e596e : SUCCESS in 43m 38s\n- gate-neutron-python27 http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-neutron-python27\/525acec : SUCCESS in 27m 10s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron\/469682a : SUCCESS in 35m 59s\n- check-tempest-dsvm-neutron-pg http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-pg\/91e8f4f : SUCCESS in 37m 11s\n- check-tempest-dsvm-neutron-isolated http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-isolated\/90021b9 : SUCCESS in 41m 27s\n- check-tempest-dsvm-neutron-pg-isolated http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-tempest-dsvm-neutron-pg-isolated\/7bc809a : SUCCESS in 45m 35s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/02\/65902\/3\/check\/gate-tempest-dsvm-neutron-large-ops\/aea24f9 : SUCCESS in 15m 01s\n- check-grenade-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-grenade-dsvm-neutron\/59354b6 : FAILURE in 20m 16s (non-voting)\n- check-devstack-dsvm-neutron http:\/\/logs.openstack.org\/02\/65902\/3\/check\/check-devstack-dsvm-neutron\/d347313 : FAILURE in 17m 10s (non-voting)\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "1"
}
],
"patchSet": {
"createdOn": 1389387264,
"ref": "refs\/changes\/02\/65902\/3",
"number": "3",
"uploader": {
"username": "nanjj",
"name": "Jun Jie Nan",
"email": "nanjj@cn.ibm.com"
},
"revision": "8044bcbfe8f10aa3f965992e30e9548258d6c736"
},
"type": "comment-added",
"change": {
"topic": "bugs\/1267682",
"url": "https:\/\/review.openstack.org\/65902",
"number": "65902",
"project": "openstack\/neutron",
"branch": "master",
"owner": {
"username": "nanjj",
"name": "Jun Jie Nan",
"email": "nanjj@cn.ibm.com"
},
"id": "Id52c04b4739d2d11fe52d4b1631cb4f39e6b577f",
"subject": "Check vxlan enablement via modinfo"
}
},
{
"comment": "Build succeeded.\n\n- gate-glance-pep8 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-pep8\/250a70c : SUCCESS in 1m 50s\n- gate-glance-docs http:\/\/docs-draft.openstack.org\/64\/66064\/1\/check\/gate-glance-docs\/c641b72\/doc\/build\/html\/ : SUCCESS in 1m 55s\n- gate-glance-python26 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-python26\/c36e87a : SUCCESS in 8m 57s\n- gate-glance-python27 http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-glance-python27\/fb29142 : SUCCESS in 12m 30s\n- check-tempest-dsvm-full http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-full\/21c38f3 : SUCCESS in 43m 54s\n- check-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-postgres-full\/958323e : SUCCESS in 42m 43s\n- check-tempest-dsvm-neutron http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-tempest-dsvm-neutron\/3824a0d : SUCCESS in 35m 09s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-tempest-dsvm-large-ops\/3f113a8 : SUCCESS in 13m 20s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/64\/66064\/1\/check\/gate-tempest-dsvm-neutron-large-ops\/f527f8c : SUCCESS in 12m 49s\n- check-grenade-dsvm http:\/\/logs.openstack.org\/64\/66064\/1\/check\/check-grenade-dsvm\/ab6a585 : SUCCESS in 28m 47s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "1"
}
],
"patchSet": {
"createdOn": 1389388172,
"ref": "refs\/changes\/64\/66064\/1",
"number": "1",
"uploader": {
"username": "arnaud",
"name": "Arnaud Legendre",
"email": "arnaudleg@gmail.com"
},
"revision": "b05c9313f6873239897d7c88babdfa8ebe5fefed"
},
"type": "comment-added",
"change": {
"topic": "bug\/1253497",
"url": "https:\/\/review.openstack.org\/66064",
"number": "66064",
"project": "openstack\/glance",
"branch": "master",
"owner": {
"username": "arnaud",
"name": "Arnaud Legendre",
"email": "arnaudleg@gmail.com"
},
"id": "I657e20ac39fbace60f230652912a4bf792836206",
"subject": "Update `openstack\/common\/context.py' from Oslo"
}
},
{
"comment": "Build succeeded.\n\n- gate-savanna-docs http:\/\/docs-draft.openstack.org\/25\/65925\/1\/gate\/gate-savanna-docs\/412dd7e\/doc\/build\/html\/ : SUCCESS in 2m 19s\n- gate-savanna-pep8 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-pep8\/0e076e8 : SUCCESS in 2m 40s\n- gate-savanna-python26 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-python26\/6f15ba8 : SUCCESS in 1m 57s\n- gate-savanna-python27 http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-savanna-python27\/e0545bd : SUCCESS in 2m 12s\n- gate-tempest-dsvm-savanna-full http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-full\/04a5c22 : SUCCESS in 53m 34s (non-voting)\n- gate-tempest-dsvm-savanna-postgres-full http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-postgres-full\/0143007 : SUCCESS in 43m 15s (non-voting)\n- gate-tempest-dsvm-savanna-neutron http:\/\/logs.openstack.org\/25\/65925\/1\/gate\/gate-tempest-dsvm-savanna-neutron\/350d103 : SUCCESS in 39m 27s (non-voting)\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "2"
}
],
"patchSet": {
"createdOn": 1389354908,
"ref": "refs\/changes\/25\/65925\/1",
"number": "1",
"uploader": {
"username": "sreshetniak",
"name": "Sergey Reshetnyak",
"email": "sreshetniak@mirantis.com"
},
"revision": "fd9bee400259d370e837799236b0a4a6f0343438"
},
"type": "comment-added",
"change": {
"topic": "del-param",
"url": "https:\/\/review.openstack.org\/65925",
"number": "65925",
"project": "openstack\/savanna",
"branch": "master",
"owner": {
"username": "sreshetniak",
"name": "Sergey Reshetnyak",
"email": "sreshetniak@mirantis.com"
},
"id": "I3e48e344b079c8eef81a18176147b8aec3c9f3b1",
"subject": "Remove unused node_group parameter in get_config_value"
}
},
{
"comment": "Build succeeded.\n\n- gate-heat-docs http:\/\/docs-draft.openstack.org\/74\/61074\/12\/gate\/gate-heat-docs\/6afb5bb\/doc\/build\/html\/ : SUCCESS in 2m 20s\n- gate-heat-pep8 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-pep8\/9e7f091 : SUCCESS in 2m 33s\n- gate-heat-python26 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-python26\/011dd18 : SUCCESS in 2m 50s\n- gate-heat-python27 http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-heat-python27\/c883c86 : SUCCESS in 1m 54s\n- gate-tempest-dsvm-full http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-full\/f228dfb : SUCCESS in 42m 46s\n- gate-tempest-dsvm-postgres-full http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-postgres-full\/6f05326 : SUCCESS in 1h 21m 14s\n- gate-tempest-dsvm-neutron http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-neutron\/3b361dc : SUCCESS in 43m 33s\n- gate-tempest-dsvm-large-ops http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-large-ops\/47d0217 : SUCCESS in 14m 39s\n- gate-tempest-dsvm-neutron-large-ops http:\/\/logs.openstack.org\/74\/61074\/12\/gate\/gate-tempest-dsvm-neutron-large-ops\/cb67ba1 : SUCCESS in 15m 26s\n",
"author": {
"username": "jenkins",
"name": "Jenkins"
},
"approvals": [
{
"type": "VRIF",
"description": "Verified",
"value": "2"
}
],
"patchSet": {
"createdOn": 1387806669,
"ref": "refs\/changes\/74\/61074\/12",
"number": "12",
"uploader": {
"username": "smelikyan",
"name": "Serg Melikyan",
"email": "smelikyan@mirantis.com"
},
"revision": "af064c7a5304c672f7d71e4c8df5f69c195c739a"
},
"type": "comment-added",
"change": {
"topic": "bug\/1259078",
"url": "https:\/\/review.openstack.org\/61074",
"number": "61074",
"project": "openstack\/heat",
"branch": "master",
"owner": {
"username": "smelikyan",
"name": "Serg Melikyan",
"email": "smelikyan@mirantis.com"
},
"id": "I9afd1a8c222110899a90a940e7a549278c4467b7",
"subject": "Added session_persistence property to VIP"
}
}
]

View File

@ -1,116 +0,0 @@
# 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.
from elastic_recheck import elasticRecheck
from elastic_recheck import loader
from elastic_recheck import results
from elastic_recheck import tests
def fake_queries(directory='queries', skip_resolved=True):
queries = [
{'query': '@message:"fake query" AND @fields.filename:"fake"\n',
'bug': 1226337},
{'query': 'magic query',
'bug': 1234567},
{'query': '@message:"fake_query3" AND @fields.filename:"fake"\n',
'bug': 1235437}]
if not skip_resolved:
queries.append({'query': 'magic query',
'bug': 1252514,
'resolved_at': 'Tue Dec 10 12:08:42 EST 2013'})
return queries
def _fake_search(query, size=None):
files = ['console.html', 'logs/screen-n-api.txt',
'logs/screen-n-cpu.txt', 'logs/screen-n-sch.txt',
'logs/screen-c-api.txt', 'logs/screen-c-vol.txt',
'logs/syslog.txt']
file_list = []
for f in files:
file_list.append({'term': f})
log_url = ('http://logs.openstack.org/57/51057/1/gate/gate-tempest-'
'devstack-vm-full/f8965ee/console.html')
hit_dict = {'_source': {'@fields': {'log_url': log_url}}}
if 'magic query' in query['query']['query_string']['query']:
fake_result = results.ResultSet(
{'hits': {'total': 2, 'hits': [hit_dict, hit_dict]},
'facets': {'tag': {'terms': file_list}}})
else:
fake_result = results.ResultSet(
{'hits': {'total': 1, 'hits': [hit_dict]},
'facets': {'tag': {'terms': file_list}}})
return fake_result
def _fake_urls_match(comment, results):
# TODO(sdague): this is not a good fake url work around, however it will
# get us through the merge in of the new result sets. We'll eventually
# make this actual life like data.
if len(results) == 2:
return True
else:
return False
def _fake_is_ready_urls_match(comment, results):
return True
def _fake_is_ready(change_number, patch_number, comment):
return True
class TestClassifier(tests.TestCase):
def setUp(self):
super(TestClassifier, self).setUp()
self.stubs.Set(loader, 'load', fake_queries)
self.classifier = elasticRecheck.Classifier('queries.yaml')
def test_is_ready(self):
self.stubs.Set(self.classifier.es, 'search', _fake_search)
result = self.classifier._is_ready(
'49282',
'3',
'BLAH http://logs.openstack.org/57/51057/1/gate/'
'gate-tempest-devstack-vm-full/f8965ee'
)
self.assertTrue(result)
def test_classify(self):
self.stubs.Set(self.classifier.es, 'search', _fake_search)
self.stubs.Set(self.classifier, '_urls_match', _fake_urls_match)
self.stubs.Set(self.classifier, '_is_ready', _fake_is_ready)
bug_numbers = self.classifier.classify(
'47463',
'3',
' blah http://logs.openstack.org/63/47463/3/gate/gate-tempest'
'-devstack-vm-postgres-full/99bb8f6'
)
self.assertEqual(bug_numbers, [1234567])
def test_classify_without_skipping_resolved_bugs(self):
self.stubs.Set(self.classifier.es, 'search', _fake_search)
self.stubs.Set(self.classifier, '_urls_match', _fake_urls_match)
self.stubs.Set(self.classifier, '_is_ready', _fake_is_ready)
bug_numbers = self.classifier.classify(
'47463',
'3',
' blah http://logs.openstack.org/63/47463/3/gate/gate-tempest'
'-devstack-vm-postgres-full/99bb8f6',
False
)
self.assertEqual(bug_numbers, [1234567, 1252514])

View File

@ -1,51 +0,0 @@
# 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 urllib2
from elastic_recheck import elasticRecheck
from elastic_recheck import tests
class TestRequiredFiles(tests.TestCase):
def test_url(self):
url = elasticRecheck.RequiredFiles.prep_url(
'http://logs.openstack.org/13/46613/2/check/'
'gate-tempest-devstack-vm-full/864bf44/console.html')
self.assertEqual(
url,
'http://logs.openstack.org/13/46613/2/check/'
'gate-tempest-devstack-vm-full/864bf44')
def _fake_urlopen(self, url):
pass
def test_files_at_url_pass(self):
self.stubs.Set(urllib2, 'urlopen', self._fake_urlopen)
result = elasticRecheck.RequiredFiles.files_at_url(
'http://logs.openstack.org/13/46613/2/check/'
'gate-tempest-devstack-vm-full/864bf44')
self.assertTrue(result)
def _invalid_url_open(self, url):
raise urllib2.HTTPError(url, 404, 'NotFound', '', None)
def test_files_at_url_fail(self):
self.stubs.Set(urllib2, 'urlopen', self._invalid_url_open)
self.assertFalse(elasticRecheck.RequiredFiles.files_at_url(
'http://logs.openstack.org/02/44502/7/check/'
'gate-tempest-devstack-vm-neutron/4f386e5'))
self.assertFalse(elasticRecheck.RequiredFiles.files_at_url(
'http://logs.openstack.org/45/47445/3/check/'
'gate-tempest-devstack-vm-full/0e43e09/'))

View File

@ -14,26 +14,50 @@
import json import json
import fixtures
import mock
from elastic_recheck import elasticRecheck from elastic_recheck import elasticRecheck
from elastic_recheck import tests from elastic_recheck import tests
import elastic_recheck.tests.unit.fake_gerrit as fg
class TestStream(tests.TestCase): class TestStream(tests.TestCase):
def setUp(self): def setUp(self):
super(TestStream, self).setUp() super(TestStream, self).setUp()
with open("elastic_recheck/tests/unit/jenkins/events.json") as f: self.useFixture(fixtures.MonkeyPatch(
j = json.load(f) 'gerritlib.gerrit.Gerrit',
self.events = j['events'] fg.Gerrit))
def test_gerrit_parsing_none(self): def test_gerrit_stream(self):
self.assertFalse( """Tests that we can use our mock gerrit to process events."""
elasticRecheck.Stream.parse_jenkins_failure(self.events[1])) with mock.patch.object(
self.assertFalse( elasticRecheck.Stream, '_does_es_have_data') as mock_data:
elasticRecheck.Stream.parse_jenkins_failure(self.events[2])) mock_data.return_value = True
stream = elasticRecheck.Stream("", "", "")
# there are currently 10 events in the stream, 3 are
# failures
for i in xrange(3):
event = stream.get_failed_tempest()
self.assertEqual(event['author']['username'], 'jenkins')
self.assertIn('Build failed', event['comment'])
self.assertRaises(
fg.GerritDone,
stream.get_failed_tempest)
def test_gerrit_parsing(self): def test_gerrit_parsing(self):
jobs = elasticRecheck.Stream.parse_jenkins_failure(self.events[0]) with open("elastic_recheck/tests/unit/jenkins/events.json") as f:
j = json.load(f)
events = j['events']
self.assertFalse(
elasticRecheck.Stream.parse_jenkins_failure(events[1]))
self.assertFalse(
elasticRecheck.Stream.parse_jenkins_failure(events[2]))
jobs = elasticRecheck.Stream.parse_jenkins_failure(events[0])
self.assertIn('check-requirements-integration-dsvm', jobs) self.assertIn('check-requirements-integration-dsvm', jobs)
self.assertIn('check-tempest-dsvm-full', jobs) self.assertIn('check-tempest-dsvm-full', jobs)
self.assertIn('check-tempest-dsvm-postgres-full', jobs) self.assertIn('check-tempest-dsvm-postgres-full', jobs)

View File

@ -10,3 +10,4 @@ testrepository>=0.0.17
testscenarios>=0.4,<0.5 testscenarios>=0.4,<0.5
testtools>=0.9.32 testtools>=0.9.32
mox>=0.5.3 mox>=0.5.3
mock>=1.0