Split initial state machine to separate class

Move OBS simulation to separate class, should be eventually moved to separate
file as well. And converted test_dispatch_open_requests to use new and shiny
testing infrastructure.
This commit is contained in:
Michal Hrusecky 2014-02-24 15:52:30 +01:00 committed by Michal Hrusecky
parent ac1114b878
commit dbb0632977
3 changed files with 159 additions and 306 deletions

View File

@ -32,17 +32,31 @@ if PY3:
else:
string_types = basestring,
class TestApiCalls(unittest.TestCase):
class OBS:
"""
Tests for various api calls to ensure we return expected content
Class trying to simulate a simple OBS
"""
responses = { 'GET': {}, 'PUT': {}, 'POST': {}, 'ALL': {} }
responses = { }
def __init__(self):
"""
Initialize the configuration and create basic OBS instance
"""
self.reset_config()
def reset_config(self):
self._clear_responses()
def _clear_responses(self):
"""
Reset predefined responses
"""
self.responses = { 'GET': {}, 'PUT': {}, 'POST': {}, 'ALL': {} }
# Add methods to manipulate reviews
self._request_review()
# Add methods to search requests
self._request_search()
def _pretty_callback(self, request, uri, headers):
"""
@ -55,31 +69,147 @@ class TestApiCalls(unittest.TestCase):
:param uri: uri as provided to callback function by HTTPretty
:param headers: headers as provided to callback function by HTTPretty
"""
# Get path
path = re.match( r'.*localhost([^?]*)(\?.*)?',uri).group(1)
reply = None
# Try to find a fallback
if self.responses['ALL'].has_key(path):
reply = self.responses['ALL'][path]
# Try to find a specific method
if self.responses[request.method].has_key(path):
reply = self.responses[request.method][path]
# We have something to reply with
if reply:
# It's a list, so take the first
if isinstance(reply, list):
reply = reply.pop(0)
# It's string
if isinstance(reply, string_types):
return (200, headers, reply)
# It's XML
if reply.startswith('<'):
return (200, headers, reply)
# It's fixture
else:
return (200, headers, _get_fixture_content(reply))
# All is left is callback function
else:
return (200, headers, reply(self.responses, request, uri))
# No possible response found
else:
if len(path) == 0:
path = uri
raise BaseException("No response for {0} on {1} provided".format(request.method,path))
def _register_pretty(self):
# Initial request data
requests_data = { '123': { 'request': 'new', 'review': 'accepted',
'who': 'Admin', 'by': 'group', 'id': '123',
'by_who': 'opensuse-review-team',
'package': 'gcc' },
'321': { 'request': 'review', 'review': 'new',
'who': 'Admin', 'by': 'group', 'id': '321',
'by_who': 'factory-staging',
'package': 'puppet' }
}
def _request_review(self):
"""
Register requests methods
"""
# Load template
tmpl = Template(self._get_fixture_content('request_review.xml'))
# What happens when we try to change the review
def review_change(responses, request, uri):
rq_id = re.match( r'.*/([0-9]+)',uri).group(1)
args = self.requests_data[rq_id]
# Adding review
if request.querystring.has_key(u'cmd') and request.querystring[u'cmd'] == [u'addreview']:
self.requests_data[rq_id]['request'] = 'review'
self.requests_data[rq_id]['review'] = 'new'
# Changing review
if request.querystring.has_key(u'cmd') and request.querystring[u'cmd'] == [u'changereviewstate']:
self.requests_data[rq_id]['request'] = 'new'
self.requests_data[rq_id]['review'] = request.querystring[u'newstate'][0]
# Project review
if request.querystring.has_key(u'by_project'):
self.requests_data[rq_id]['by'] = 'project'
self.requests_data[rq_id]['by_who'] = request.querystring[u'by_project'][0]
# Group review
if request.querystring.has_key(u'by_group'):
self.requests_data[rq_id]['by'] = 'group'
self.requests_data[rq_id]['by_who'] = request.querystring[u'by_group'][0]
responses['GET']['/request/' + rq_id] = tmpl.substitute(self.requests_data[rq_id])
return responses['GET']['/request/' + rq_id]
# Register methods for all requests
for rq in self.requests_data:
self.responses['GET']['/request/' + rq] = tmpl.substitute(self.requests_data[rq])
self.responses['ALL']['/request/' + rq] = review_change
def _request_search(self):
"""
Allows searching for requests
"""
def request_search(responses, request, uri):
# Searching for requests that has open review for staging group
if request.querystring.has_key(u'match') and request.querystring[u'match'][0] == u"state/@name='review' and review[@by_group='factory-staging' and @state='new']":
rqs = []
# Itereate through all requests
for rq in self.requests_data:
# Find the ones matching the condition
if self.requests_data[rq]['request'] == 'review' and self.requests_data[rq]['review'] == 'new' and self.requests_data[rq]['by'] == 'group' and self.requests_data[rq]['by_who'] == 'factory-staging':
rqs.append(rq)
# Create response
ret_str = '<collection matches="' + str(len(rqs)) + '">'
for rq in rqs:
ret_str += responses['GET']['/request/' + rq]
ret_str += '</collection>'
return ret_str
# We are searching for something else, we don't know the answer
raise BaseException("No search results defined for " + pprint.pformat(request.querystring))
self.responses['GET']['/search/request'] = request_search
def register_obs(self):
"""
Register custom callback for HTTPretty
"""
httpretty.register_uri(httpretty.GET,re.compile(r'/.*localhost.*/'),body=self._pretty_callback)
httpretty.register_uri(httpretty.PUT,re.compile(r'/.*localhost.*/'),body=self._pretty_callback)
httpretty.register_uri(httpretty.POST,re.compile(r'/.*localhost.*/'),body=self._pretty_callback)
self.reset_config()
# Initiate the api with mocked rings
with mock_generate_ring_packages():
self.api = oscs.StagingAPI('http://localhost')
def _get_fixtures_dir(self):
"""
Return path for fixtures
"""
return os.path.join(os.getcwd(), 'tests/fixtures')
def _get_fixture_path(self, filename):
"""
Return path for fixture
"""
return os.path.join(self._get_fixtures_dir(), filename)
def _get_fixture_content(self, filename):
"""
Return content of fixture
"""
response = open(self._get_fixture_path(filename), 'r')
content = response.read()
response.close()
return content
class TestApiCalls(unittest.TestCase):
"""
Tests for various api calls to ensure we return expected content
"""
obs = OBS()
def _get_fixtures_dir(self):
"""
@ -165,22 +295,17 @@ class TestApiCalls(unittest.TestCase):
Test dispatching and closure of non-ring packages
"""
# Initiate the pretty overrides
self._register_pretty_url_get('http://localhost/search/request?match=state/@name=\'review\'+and+review[@by_group=\'factory-staging\'+and+@state=\'new\']',
'open-requests.xml')
# There should be just one request that gets closed
# We don't care about the return so just reuse the above :P
# If there is bug in the function we get assertion about closing more issues than we should
self._register_pretty_url_post('http://localhost/request/220956?comment=No+need+for+staging%2C+not+in+tested+ring+project.&newstate=accepted&by_group=factory-staging&cmd=changereviewstate',
'open-requests.xml')
# Initiate the api with mocked rings
with mock_generate_ring_packages():
api = oscs.StagingAPI('http://localhost')
# get the open requests
requests = api.dispatch_open_requests()
# Register OBS
self.obs.register_obs()
# Get rid of open requests
self.obs.api.dispatch_open_requests()
# Check that we tried to close it
self.assertEqual(httpretty.last_request().method, 'POST')
self.assertEqual(httpretty.last_request().querystring[u'cmd'], [u'changereviewstate'])
# Try it again
self.obs.api.dispatch_open_requests()
# This time there should be nothing to close
self.assertEqual(httpretty.last_request().method, 'GET')
@httpretty.activate
def test_pseudometa_get_prj(self):
@ -306,41 +431,25 @@ class TestApiCalls(unittest.TestCase):
Test whether accepting/creating reviews behaves correctly
"""
with mock_generate_ring_packages():
api = oscs.StagingAPI('http://localhost')
tmpl = Template(self._get_fixture_content('request_review.xml'))
self._clear_responses()
self.responses['GET']['/request/123'] = tmpl.substitute(request='new', review='accepted', review_project="openSUSE:Factory")
def review_change(responses, request, uri):
if request.querystring.has_key(u'cmd') and request.querystring[u'cmd'] == [u'addreview']:
responses['GET']['/request/123'] = tmpl.substitute(request='review', review='new', review_project=request.querystring[u'by_project'][0])
if request.querystring.has_key(u'cmd') and request.querystring[u'cmd'] == [u'changereviewstate']:
responses['GET']['/request/123'] = tmpl.substitute(request='new', review=request.querystring[u'newstate'][0], review_project=request.querystring[u'by_project'][0])
return responses['GET']['/request/123']
self.responses['ALL']['/request/123'] = review_change
self._register_pretty()
# Register OBS
self.obs.register_obs()
# Add review
api.add_review('123', 'openSUSE:Factory:Staging:A')
self.obs.api.add_review('123', 'openSUSE:Factory:Staging:A')
self.assertEqual(httpretty.last_request().method, 'POST')
self.assertEqual(httpretty.last_request().querystring[u'cmd'], [u'addreview'])
# Try to readd, should do anything
api.add_review('123', 'openSUSE:Factory:Staging:A')
self.obs.api.add_review('123', 'openSUSE:Factory:Staging:A')
self.assertEqual(httpretty.last_request().method, 'GET')
# Accept review
api.set_review('123', 'openSUSE:Factory:Staging:A')
self.obs.api.set_review('123', 'openSUSE:Factory:Staging:A')
self.assertEqual(httpretty.last_request().method, 'POST')
self.assertEqual(httpretty.last_request().querystring[u'cmd'], [u'changereviewstate'])
# Try to accept it again should do anything
api.set_review('123', 'openSUSE:Factory:Staging:A')
self.obs.api.set_review('123', 'openSUSE:Factory:Staging:A')
self.assertEqual(httpretty.last_request().method, 'GET')
# But we should be able to reopen it
api.add_review('123', 'openSUSE:Factory:Staging:A')
self.obs.api.add_review('123', 'openSUSE:Factory:Staging:A')
self.assertEqual(httpretty.last_request().method, 'POST')
self.assertEqual(httpretty.last_request().querystring[u'cmd'], [u'addreview'])

View File

@ -1,255 +0,0 @@
<collection matches="2">
<request id="220956">
<action type="submit">
<source project="devel:languages:python:Factory" package="python3" rev="125"/>
<target project="openSUSE:Factory" package="python3"/>
</action>
<state name="review" who="factory-auto" when="2014-02-05T10:13:08">
<comment>Check Staging Project</comment>
</state>
<review state="accepted" when="2014-02-05T10:09:55" who="licensedigger" by_group="legal-auto">
<comment>{"approve": "preliminary, version number changed"} &lt;!-- {
"dest": {
"ldb": {
"prodonly": "",
"review": "done",
"rpm_license": "{\"python3.spec\":{\"curses\":[\"Python-2.0\"],\"python3\":[\"Python-2.0\"],\"dbm\":[\"Python-2.0\"],\"tk\":[\"Python-2.0\"]},\"python3-base.spec\":{\"-n python3-tools\":[\"Python-2.0\"],\"-n python3-idle\":[\"Python-2.0\"],\"python3-base\":[\"Python-2.0\"],\"-n python3-testsuite\":[\"Python-2.0\"],\"-n libpython%{so_version}\":[\"Python-2.0\"],\"-n python3-devel\":[\"Python-2.0\"]},\"python3-doc.spec\":{\"python3-doc\":[\"Python-2.0\"],\"pdf\":[\"Python-2.0\"]}}",
"status": "production",
"version": "3.3.3"
},
"license": {
"python3-base.spec": {
"-n libpython%{so_version}": [
"Python-2.0"
],
"-n python3-devel": [
"Python-2.0"
],
"-n python3-idle": [
"Python-2.0"
],
"-n python3-testsuite": [
"Python-2.0"
],
"-n python3-tools": [
"Python-2.0"
],
"python3-base": [
"Python-2.0"
]
},
"python3-doc.spec": {
"pdf": [
"Python-2.0"
],
"python3-doc": [
"Python-2.0"
]
},
"python3.spec": {
"curses": [
"Python-2.0"
],
"dbm": [
"Python-2.0"
],
"python3": [
"Python-2.0"
],
"tk": [
"Python-2.0"
]
}
},
"version": "3.3.3"
},
"hint": [
"version changed: src('3.3.3') differs from dest('3.4.0~b3')"
],
"plugin": "0.60",
"src": {
"auto-co": "/api.opensuse.org/devel:languages:python:Factory/python3%3.4.0~b3%r125",
"kiwi_only": false,
"license": {
"python3-base.spec": {
"-n libpython%{so_version}": [
"Python-2.0"
],
"-n python3-devel": [
"Python-2.0"
],
"-n python3-idle": [
"Python-2.0"
],
"-n python3-testsuite": [
"Python-2.0"
],
"-n python3-tools": [
"Python-2.0"
],
"python3-base": [
"Python-2.0"
]
},
"python3-doc.spec": {
"pdf": [
"Python-2.0"
],
"python3-doc": [
"Python-2.0"
]
},
"python3.spec": {
"curses": [
"Python-2.0"
],
"dbm": [
"Python-2.0"
],
"python3": [
"Python-2.0"
],
"tk": [
"Python-2.0"
]
}
},
"rev": "125",
"version": "3.4.0~b3",
"version_diff": "src('3.3.3') differs from dest('3.4.0~b3')"
}
} --&gt;</comment>
</review>
<review state="accepted" when="2014-02-05T10:09:55" who="factory-auto" by_group="factory-auto">
<comment>Check script succeeded</comment>
</review>
<review state="accepted" when="2014-02-05T10:13:07" who="a_jaeger" by_group="opensuse-review-team">
<comment>ok</comment>
</review>
<review state="accepted" when="2014-02-05T10:13:08" who="factory-repo-checker" by_user="factory-repo-checker">
<comment>Builds for repo openSUSE_Factory</comment>
</review>
<review state="new" by_group="factory-staging">
<comment>Check Staging Project</comment>
</review>
<history name="review" who="saschpe" when="2014-02-05T10:09:55"/>
<history name="review" who="factory-auto" when="2014-02-05T10:13:07">
<comment>Please review sources</comment>
</history>
<history name="review" who="factory-auto" when="2014-02-05T10:13:08">
<comment>Please review build success</comment>
</history>
<description>- initial commit of 3.4.0 beta 3
* new stdlib modules: pathlib, enum, statistics, tracemalloc
* asynchronous IO with new asyncio module
* introspection data for builtins
* subprocesses no longer inherit open file descriptors
* standardized metadata for packages
* internal hashing changed to SipHash
* new pickle protocol
* improved handling of codecs
* TLS 1.2 support
* major speed improvements for internal unicode handling
* many bugfixes and optimizations
- see porting guide at:
http://docs.python.org/3.4/whatsnew/3.4.html#porting-to-python-3-4
- moved several modules to -testsuite subpackage
- updated list of binary extensions, refreshed patches
- tracemalloc_gcov.patch fixes profile-based optimization build
- updated packages and pre_checkin.sh to use ~-version notation
for prereleases
- fix-shebangs part of build process moved to common %prep
- drop python-3.3.2-no-REUSEPORT.patch (upstreamed)
- update baselibs for new soname
- TODOs:
* require python-pip, make ensurepip work with zypper
- initial commit of 3.4.0 beta2
* for full changelog, see python3-base
- initial commit of 3.4.0 beta 3
* for full changelog, see python3-base</description>
</request>
<request id="221625">
<action type="submit">
<source project="X11:XOrg" package="elem-ring-0" rev="110"/>
<target project="openSUSE:Factory" package="elem-ring-0"/>
</action>
<state name="review" who="factory-auto" when="2014-02-10T12:03:29">
<comment>Check Staging Project</comment>
</state>
<review state="accepted" when="2014-02-10T12:00:13" who="licensedigger" by_group="legal-auto">
<comment>{"approve": "preliminary, version number changed"} &lt;!-- {
"dest": {
"ldb": {
"review": "never",
"rpm_license": "{\"xf86-video-intel.spec\":{\"xf86-video-intel\":[\"MIT\"]}}",
"status": "production",
"version": "2.99.909"
},
"license": {
"xf86-video-intel.spec": {
"xf86-video-intel": [
"MIT"
]
}
},
"version": "2.99.909"
},
"hint": [
"no ldb.risk defined, okay as per bnc#771677. ",
"ldb.review was (apparently) never done"
],
"plugin": "0.60",
"src": {
"auto-co": "/api.opensuse.org/X11:XOrg/xf86-video-intel%2.99.910%r110",
"kiwi_only": false,
"license": {
"xf86-video-intel.spec": {
"xf86-video-intel": [
"MIT"
]
}
},
"rev": "110",
"version": "2.99.910",
"version_diff": null
}
} --&gt;</comment>
</review>
<review state="accepted" when="2014-02-10T12:00:13" who="factory-auto" by_group="factory-auto">
<comment>Check script succeeded</comment>
</review>
<review state="new" by_group="opensuse-review-team">
<comment>Please review sources</comment>
</review>
<review state="new" by_user="factory-repo-checker">
<comment>Please review build success</comment>
</review>
<review state="new" by_group="factory-staging">
<comment>Check Staging Project</comment>
</review>
<history name="review" who="sndirsch" when="2014-02-10T12:00:13"/>
<history name="review" who="factory-auto" when="2014-02-10T12:03:28">
<comment>Please review sources</comment>
</history>
<history name="review" who="factory-auto" when="2014-02-10T12:03:29">
<comment>Please review build success</comment>
</history>
<description>- Update to 3.0 prerelease 2.99.910
* Only discard damage when overwriting the dirty CPU bo, instead
of discarding damage that will be shown!
* Reset operation state when switching between glyph caches.
https://bugs.freedesktop.org/show_bug.cgi?id=74494
* Fully reinitialise pixmaps allocated from the freed cache. Fixes
a potential issue (crash or misrendering) when using some compositors.
https://bugs.freedesktop.org/show_bug.cgi?id=74550
* Do not expose the TexturedVideo adaptor in UXA when it is disabled
either due to a hung GPU or explicitly disabled by the user.
* Restore the pipe stall when changing CC state on gen6, otherwise
the GPU may not flush intermediate results from all EU resulting
in render corruption (usually the occasional black box).
Regression from 2.99.906
https://bugs.freedesktop.org/show_bug.cgi?id=7237</description>
</request>
</collection>

View File

@ -1,14 +1,13 @@
<?xml version="1.0"?>
<request id="123">
<request id="${id}">
<action type="submit">
<source project="home:Admin" package="puppet" rev="59f0f46262d7b57b9cdc720c06d5e317"/>
<target project="openSUSE:Factory" package="puppet"/>
<source project="home:Admin" package="${package}" rev="59f0f46262d7b57b9cdc720c06d5e317"/>
<target project="openSUSE:Factory" package="${package}"/>
</action>
<state name="${request}" who="Admin" when="2014-02-17T12:38:52">
<comment>Passed staging project "openSUSE:Factory:Staging:test"</comment>
<comment>...</comment>
</state>
<review state="${review}" when="2014-02-17T12:34:10" who="Admin" by_project="${review_project}">
<comment>Passed staging project "openSUSE:Factory:Staging:test"</comment>
<review state="${review}" when="2014-02-17T12:34:10" who="${who}" by_${by}="${by_who}">
<comment>...</comment>
</review>
<description>test</description>
</request>