Add System Tests
This patch adds the System level testing framework & the initial set of tests for Marconi.This will allow developers to run the system tests (regression suite for Marconi system level tests), against local Marconi server. Refer tests/system/README.rst file for details on how to add new tests and run the existing tests. Change-Id: I2f47e03091acc260293b19edad69ff5c83888ec3 Implements: blueprint system-tests
This commit is contained in:
parent
a556f392c5
commit
5477b646cc
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,8 +9,10 @@ build
|
||||
cover
|
||||
venv
|
||||
.venv
|
||||
output.xml
|
||||
*.sublime-workspace
|
||||
*.sqlite
|
||||
*.html
|
||||
.*.swp
|
||||
.DS_Store
|
||||
.testrepository
|
||||
|
32
README.rst
32
README.rst
@ -1 +1,31 @@
|
||||
Marconi - Queue and Notification service for OpenStack
|
||||
**Marconi - Queue and Notification service for OpenStack**
|
||||
|
||||
*Steps to run Marconi server locally with MongoDB*
|
||||
|
||||
1. `Install mongodb`_ locally
|
||||
2. Start your local MongoDB instance::
|
||||
|
||||
mongod
|
||||
3. Clone the Marconi repo::
|
||||
|
||||
git clone https://github.com/stackforge/marconi.git
|
||||
4. cd to your local copy of the repo
|
||||
5. Copy the Marconi config files to the directory ~/.marconi::
|
||||
|
||||
cp -r marconi/etc/*.conf-sample ~/.marconi
|
||||
6. Update the [drivers:storage:mongodb] section in ~/.marconi/marconi.conf
|
||||
|
||||
6a. Comment out the uri pointing to replicaset::
|
||||
|
||||
;uri = mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test&ssl=true&w=majority
|
||||
6b. Add a new line with uri pointing to the local mongoDB instance::
|
||||
|
||||
uri = mongodb://localhost
|
||||
7. Run the following command::
|
||||
|
||||
python setup.py develop
|
||||
8. Start the marconi server::
|
||||
|
||||
marconi-server
|
||||
|
||||
.. _`Install mongodb` : http://docs.mongodb.org/manual/installation/
|
63
marconi/tests/system/README.rst
Normal file
63
marconi/tests/system/README.rst
Normal file
@ -0,0 +1,63 @@
|
||||
**Marconi System Tests**
|
||||
|
||||
The System tests treat Marconi as a black box.
|
||||
The API calls are made similar to how an user would make them.
|
||||
Unlike unit tests, the system tests do not use mock endpoints.
|
||||
|
||||
**Running the System Tests**
|
||||
|
||||
1. Setup the Marconi server, to run the tests against.
|
||||
Refer to the Marconi `README`_ on how to run Marconi locally.
|
||||
(If you are running the tests against an existing server, skip this step.)
|
||||
|
||||
2. System tests require the `requests`_ & `robot`_ packages. Run the following to install them ::
|
||||
|
||||
pip install -r tools/system-test-requires
|
||||
|
||||
3. cd to the marconi/tests/system directory
|
||||
|
||||
4. Copy etc/system-tests.conf-sample to one of the following locations::
|
||||
|
||||
~/.marconi/system-tests.conf
|
||||
/etc/marconi/system-tests.conf
|
||||
|
||||
5. Update the config file to point to the Marconi server you want to run the tests against
|
||||
|
||||
6. If keystone auth is enabled, update system-tests.conf with the credentials.
|
||||
|
||||
7. To run tests use the pybot commands,
|
||||
|
||||
Run all test suites ::
|
||||
|
||||
pybot marconi/tests/system/queue/queue_tests.txt marconi/tests/system/messages/messages_tests.txt marconi/tests/system/claim/claim_tests.txt
|
||||
|
||||
Run a specific test suite ::
|
||||
|
||||
pybot marconi/tests/system/queue/queue_tests.txt
|
||||
|
||||
pybot marconi/tests/system/messages/messages_tests.txt
|
||||
|
||||
pybot marconi/tests/system/claim/claim_tests.txt
|
||||
|
||||
pybot will generate report.html & log.html after the test run is complete.
|
||||
|
||||
|
||||
**To Add new tests**
|
||||
|
||||
|
||||
1. Add test case definition to the robot test case file (queue/queue_tests.txt, messages/messages_tests.txt, claim/claim_tests.txt)
|
||||
See `here`_ for more details on writing test cases.
|
||||
|
||||
2. Add test data to the test_data.csv in the same directory as the test case file you updated above (eg. queue/test_data.csv)
|
||||
|
||||
3. Add any validation logic you might need, to one of the following:
|
||||
|
||||
* corresponing \*fnlib.py (eg. queue/queuefnlib.py)
|
||||
* common/functionlib.py (If the code can be used across multiple test suites)
|
||||
|
||||
.. _README : https://github.com/stackforge/marconi/blob/master/README.rst
|
||||
.. _requests : https://pypi.python.org/pypi/requests
|
||||
.. _robot : https://pypi.python.org/pypi/robotframework
|
||||
.. _here : http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.7#creating-test-cases
|
||||
|
||||
|
0
marconi/tests/system/__init__.py
Normal file
0
marconi/tests/system/__init__.py
Normal file
0
marconi/tests/system/claim/__init__.py
Normal file
0
marconi/tests/system/claim/__init__.py
Normal file
66
marconi/tests/system/claim/claim_tests.txt
Executable file
66
marconi/tests/system/claim/claim_tests.txt
Executable file
@ -0,0 +1,66 @@
|
||||
| *Setting* | *Value* |
|
||||
| Documentation | Marconi - Queue Test Suite |
|
||||
| Library | ../common/http.py |
|
||||
| Library | ../common/functionlib.py |
|
||||
| Library | ../messages/msgfnlib.py |
|
||||
| Library | Collections |
|
||||
| Library | claimfnlib.py |
|
||||
| Variables | getdata.py |
|
||||
| Force Tags | CLAIM |
|
||||
| Suite Setup | executetests | ${API_TEST_DATA[6]} | # Test Suite Setup - Creates a Queue
|
||||
| Suite Teardown | executetests | ${API_TEST_DATA[8]} | # Test Suite Teardown - Deletes the queue created by setup
|
||||
|
||||
|
||||
| *Test Case* | *Action* | *Argument* | *Argument* | *Argument* | # Comment
|
||||
| 0:SUITE SETUP | [DOCUMENTATION] | | Post 500 messages | | #SUITE SETUP - POST MULTIPLE MESSAGES
|
||||
| | [Tags] | INSERT_MESSAGE | | | #(Robot allows only one keyword in setup)
|
||||
| | ${reqparam}= | Create Dictionary | messagecount | ${50} | # Specify count of messages to be posted
|
||||
| | | ... | ttl | ${300} | # Specify count of messages to be posted
|
||||
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # Gets the message body to post
|
||||
| | Set To Dictionary | ${API_TEST_DATA[7]} | body | ${msgbody} | # Set the POST body
|
||||
| | :FOR | ${index} | IN RANGE | 10 | # Loop to post 50 messages * 10 times
|
||||
| | | executetests | ${API_TEST_DATA[7]} | | # postresponse = [httpheaders,httpresponsebod]
|
||||
| 1:CLAIM 2 MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 1 - CLAIM 2 MESSAGES
|
||||
| | ... | with limit = 2 | |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[0]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
|
||||
| | verifyclaimmsg | ${2} | @{postresponse} |
|
||||
| 2:CLAIM 5 MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 2 - CLAIM 5 MESSAGES
|
||||
| | ... | with limit = 5 | |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
|
||||
| | verifyclaimmsg | ${5} | @{postresponse} |
|
||||
| 3:CLAIM MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 3 - CLAIM DEFAULT # OF MESSAGES
|
||||
| | ... | with no params | | (currently 10)
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[2]} | # postresponse = [httpheaders, httpresponsebody]
|
||||
| | verifyclaimmsg | ${10} | @{postresponse} |
|
||||
| 4:CLAIM 15 MESSAGE | [DOCUMENTATION] | Claim messages | | #TEST CASE 4 - CLAIM 15 MESSAGES
|
||||
| | ... | with limit = 15 | |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[3]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
|
||||
| | verifyclaimmsg | ${15} | @{postresponse} |
|
||||
| 5:CLAIM 55 MESSAGE | [DOCUMENTATION] | Claim messages | | #TEST CASE 5 - CLAIM 55 MESSAGES
|
||||
| | ... | with limit = 55 | |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[4]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
|
||||
| | verifyclaimmsg | ${50} | @{postresponse} | # MAXIMUM MESSAGES RETURNED IS CURRENTLY 50
|
||||
| 6: PATCH CLAIM | [DOCUMENTATION] | Patch a claim | | # TEST CASE 6 - UPDATE CLAIM
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[5]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
|
||||
| | patchclaim | @{postresponse} | | # Patch the above claim
|
||||
| 7: DELETE MESSAGE | [DOCUMENTATION] | Delete message | | # TEST CASE 7 - DELETE A CLAIMED MESSAGE
|
||||
| | ... | with claim id | |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[5]} | # Post a claim
|
||||
| | deleteclaimedmsgs | @{postresponse} | | # Delete messages returned in the above claim
|
||||
| 8: PATCH EXPIRED CLAIM | [DOCUMENTATION] | Patch expired claim | | # TEST CASE 8 - UPDATE EXPIRED CLAIM
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[9]} | # Post a claim with TTL= 1 sec
|
||||
| | Sleep | 3s | |
|
||||
| | patchclaim | @{postresponse} | | # Patch the above claim
|
||||
| 9: DELETE MESSAGE ON EXPIRED CLAIM | [DOCUMENTATION] | Delete message | # TEST CASE 9 - DELETE MESSAGE ON AN EXPIRED CLAIM
|
||||
| | ... | on expired claim |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[10]} | # Post a claim with TTL= 1 sec
|
||||
| | Sleep | 3s | |
|
||||
| | deleteclaimedmsgs | @{postresponse} | | # Delete message returned in the above claim
|
||||
| 10: RELEASE CLAIM | [DOCUMENTATION] | Release claim | | # TEST CASE 10 - RELEASE CLAIM
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[11]} | # Post a claim with TTL= 1 sec
|
||||
| | releaseclaim | @{postresponse} | | # Patch the above claim
|
||||
| 11: GET MESSAGE FROM EXPIRED CLAIM | [DOCUMENTATION] | Get message | # TEST CASE 11 - GET MESSAGE FROM EXPIRED CLAIM
|
||||
| | ... | from expired claim |
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[12]} | # Post a claim with TTL= 1 sec
|
||||
| | Sleep | 3s | |
|
||||
| | getclaimedmsgs | @{postresponse} | | # Delete message returned in the above claim
|
239
marconi/tests/system/claim/claimfnlib.py
Normal file
239
marconi/tests/system/claim/claimfnlib.py
Normal file
@ -0,0 +1,239 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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
|
||||
|
||||
from marconi.tests.system.common import functionlib
|
||||
from marconi.tests.system.common import http
|
||||
|
||||
|
||||
def verify_claim_msg(count, *claim_response):
|
||||
"""Verifies claim messages.
|
||||
|
||||
Validation steps include - verifying the
|
||||
1. number of messages returned is <= limit specified
|
||||
2. query claim & verifying the response
|
||||
:param count: limit specified in the claim request
|
||||
:param claim_response : response returned for the claim request
|
||||
"""
|
||||
msg_length_flag = False
|
||||
|
||||
headers = claim_response[0]
|
||||
body = claim_response[1]
|
||||
|
||||
msg_length_flag = verify_claim_msglength(count, body)
|
||||
if msg_length_flag:
|
||||
query_claim(headers, body)
|
||||
else:
|
||||
assert msg_length_flag, "More msgs returned than specified in limit"
|
||||
|
||||
|
||||
def verify_claim_msglength(count, *body):
|
||||
"""Validates that number of messages returned is <= limit specified."""
|
||||
msg_list = body
|
||||
msg_list = json.loads(msg_list[0])
|
||||
return (len(msg_list) <= count)
|
||||
|
||||
|
||||
def query_claim(headers, *body):
|
||||
"""Verifies the response of post claim.
|
||||
|
||||
Does a Query Claim using the href in post claim.
|
||||
Compares the messages returned in Query claim with the messages
|
||||
returned on Post Claim.
|
||||
"""
|
||||
test_result_flag = False
|
||||
|
||||
msg_list = body[0]
|
||||
msg_list = json.loads(msg_list)
|
||||
|
||||
location = headers["Location"]
|
||||
url = functionlib.create_url_from_appender(location)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
get_msg = http.get(url, header)
|
||||
if get_msg.status_code == 200:
|
||||
query_body = json.loads(get_msg.text)
|
||||
query_msgs = query_body["messages"]
|
||||
test_result_flag = verify_query_msgs(query_msgs, msg_list)
|
||||
|
||||
if test_result_flag:
|
||||
return test_result_flag
|
||||
else:
|
||||
print "URL"
|
||||
print url
|
||||
print "HEADER"
|
||||
print header
|
||||
print "Messages returned by Query Claim"
|
||||
print query_msgs
|
||||
print "# of Messages returned by Query Claim", len(query_msgs)
|
||||
print 'Messages returned by Claim Messages'
|
||||
print msg_list
|
||||
print "# of Messages returned by Claim messages", len(msg_list)
|
||||
assert test_result_flag, "Query Claim Failed"
|
||||
|
||||
|
||||
def verify_query_msgs(querymsgs, msg_list):
|
||||
"""Verifies response from Query claim.
|
||||
|
||||
Compares the messages returned in Query Claim with the messages
|
||||
returned when the claim was posted.
|
||||
"""
|
||||
test_result_flag = True
|
||||
idx = 0
|
||||
|
||||
for msg in querymsgs:
|
||||
if ((msg["body"] != msg_list[idx]["body"]) or
|
||||
(msg["href"] != msg_list[idx]["href"]) or
|
||||
(msg["ttl"] != msg_list[idx]["ttl"])):
|
||||
test_result_flag = False
|
||||
idx = idx + 1
|
||||
|
||||
return test_result_flag
|
||||
|
||||
|
||||
def patch_claim(*claim_response):
|
||||
"""Patches a claim & verifies the results.
|
||||
|
||||
Extracts claim id from the POST response input & updates the claim.
|
||||
If PATCH claim succeeds, verifies that the claim TTL is extended.
|
||||
"""
|
||||
test_result_flag = False
|
||||
|
||||
headers = claim_response[0]
|
||||
location = headers["Location"]
|
||||
url = functionlib.create_url_from_appender(location)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
ttl_value = 300
|
||||
payload = '{ "ttl": ttlvalue }'
|
||||
payload = payload.replace("ttlvalue", str(ttl_value))
|
||||
|
||||
patch_response = http.patch(url, header, body=payload)
|
||||
if patch_response.status_code == 204:
|
||||
test_result_flag = verify_patch_claim(url, header, ttl_value)
|
||||
else:
|
||||
print "Patch HTTP Response code: {}".format(patch_response.status_code)
|
||||
print patch_response.headers
|
||||
print patch_response.text
|
||||
assert test_result_flag, "Patch Claim Failed"
|
||||
|
||||
if not test_result_flag:
|
||||
assert test_result_flag, "Query claim after the patch failed"
|
||||
|
||||
|
||||
def verify_patch_claim(url, header, ttl_extended):
|
||||
"""Verifies if patch claim was successful.
|
||||
|
||||
The following steps are performed for the verification.
|
||||
1. GETs the claim
|
||||
2. Checks tht the actual claim TTL value is > TTL in the patch request
|
||||
|
||||
:param ttl_extended : TTL posted in the patch request.
|
||||
"""
|
||||
test_result_flag = True
|
||||
|
||||
get_claim = http.get(url, header)
|
||||
response_body = json.loads(get_claim.text)
|
||||
|
||||
ttl = response_body["ttl"]
|
||||
if ttl < ttl_extended:
|
||||
print get_claim.status_code
|
||||
print get_claim.headers
|
||||
print get_claim.text
|
||||
test_result_flag = False
|
||||
|
||||
return test_result_flag
|
||||
|
||||
|
||||
def create_urllist_fromhref(*response):
|
||||
"""EXtracts href & creates a url list.
|
||||
|
||||
:param *response : http response text with the list of messages.
|
||||
"""
|
||||
rspbody = json.loads(response[1])
|
||||
urllist = [functionlib.create_url_from_appender(item["href"])
|
||||
for item in rspbody]
|
||||
return urllist
|
||||
|
||||
|
||||
def delete_claimed_msgs(*claim_response):
|
||||
"""Deletes claimed messages.
|
||||
|
||||
Verifies that the deletes were successful with a GET on the deleted msg.
|
||||
"""
|
||||
test_result_flag = False
|
||||
|
||||
urllist = create_urllist_fromhref(*claim_response)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
for url in urllist:
|
||||
delete_response = http.delete(url, header)
|
||||
if delete_response.status_code == 204:
|
||||
test_result_flag = functionlib.verify_delete(url, header)
|
||||
else:
|
||||
print "DELETE message with claim ID: {}".format(url)
|
||||
print delete_response.status_code
|
||||
print delete_response.headers
|
||||
print delete_response.text
|
||||
assert test_result_flag, "Delete Claimed Message Failed"
|
||||
|
||||
if not test_result_flag:
|
||||
assert test_result_flag, "Get message after DELETE did not return 404"
|
||||
|
||||
|
||||
def get_claimed_msgs(*claim_response):
|
||||
"""Does get on all messages returned in the claim."""
|
||||
test_result_flag = True
|
||||
|
||||
urllist = create_urllist_fromhref(*claim_response)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
for url in urllist:
|
||||
get_response = http.get(url, header)
|
||||
if get_response.status_code != 200:
|
||||
print url
|
||||
print header
|
||||
print "Get Response Code: {}".format(get_response.status_code)
|
||||
test_result_flag = False
|
||||
|
||||
if not test_result_flag:
|
||||
assert test_result_flag, "Get Claimed message Failed"
|
||||
|
||||
|
||||
def release_claim(*claim_response):
|
||||
"""Deletes claim & verifies the delete was successful.
|
||||
|
||||
Extracts claim id from the POST response input & deletes the claim.
|
||||
If DELETE claim succeeds, verifies that a GET claim returns 404.
|
||||
"""
|
||||
test_result_flag = False
|
||||
|
||||
headers = claim_response[0]
|
||||
location = headers["Location"]
|
||||
url = functionlib.create_url_from_appender(location)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
release_response = http.delete(url, header)
|
||||
if release_response.status_code == 204:
|
||||
test_result_flag = functionlib.verify_delete(url, header)
|
||||
else:
|
||||
print "Release Claim HTTP code:{}".format(release_response.status_code)
|
||||
print release_response.headers
|
||||
print release_response.text
|
||||
assert test_result_flag, "Release Claim Failed"
|
||||
|
||||
if not test_result_flag:
|
||||
assert test_result_flag, "Get claim after the release failed"
|
37
marconi/tests/system/claim/getdata.py
Executable file
37
marconi/tests/system/claim/getdata.py
Executable file
@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 csv
|
||||
|
||||
from marconi.tests.system.common import config
|
||||
from marconi.tests.system.common import functionlib
|
||||
|
||||
|
||||
cfg = config.Config()
|
||||
|
||||
|
||||
def get_data():
|
||||
"""Reads the test data from claim/test_data.csv."""
|
||||
DATA = []
|
||||
with open('marconi/tests/system/claim/test_data.csv', 'rb') as datafile:
|
||||
testdata = csv.DictReader(datafile, delimiter='|')
|
||||
for row in testdata:
|
||||
DATA.append(row)
|
||||
for row in DATA:
|
||||
row['header'] = functionlib.get_headers(row['header'])
|
||||
row['url'] = row['url'].replace("<BASE_URL>", cfg.base_url)
|
||||
return DATA
|
||||
|
||||
API_TEST_DATA = get_data()
|
15
marconi/tests/system/claim/test_data.csv
Executable file
15
marconi/tests/system/claim/test_data.csv
Executable file
@ -0,0 +1,15 @@
|
||||
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
|
||||
1|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 50, "grace": 60}||200|
|
||||
2|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=5||{"ttl": 50, "grace": 60}||200|
|
||||
3|POST |<BASE_URL>/queues/claimtestqueue/claims||{"ttl": 50, "grace": 60}||200|
|
||||
4|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=15||{"ttl": 50, "grace": 60}||200|
|
||||
5|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=55||{"ttl": 50, "grace": 60}||200|
|
||||
6|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=4||{"ttl": 50, "grace": 60}||200|
|
||||
7|PUT |<BASE_URL>/queues/claimtestqueue||{"ttl": 50, "grace": 60}||201|
|
||||
0|POST |<BASE_URL>/queues/claimtestqueue/messages||||201|
|
||||
0|DELETE |<BASE_URL>/queues/claimtestqueue||||204|
|
||||
8|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200|
|
||||
9|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200|
|
||||
10|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 50, "grace": 60}||200|
|
||||
11|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200
|
||||
11|GET |||||200
|
Can't render this file because it contains an unexpected character in line 2 and column 60.
|
0
marconi/tests/system/common/__init__.py
Normal file
0
marconi/tests/system/common/__init__.py
Normal file
71
marconi/tests/system/common/config.py
Normal file
71
marconi/tests/system/common/config.py
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 ConfigParser
|
||||
import os
|
||||
import uuid
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self, config_path=None):
|
||||
if config_path is None:
|
||||
if os.path.exists('/etc/marconi/system-tests.conf'):
|
||||
config_path = '/etc/marconi/system-tests.conf'
|
||||
else:
|
||||
config_path = os.path.expanduser('~/.marconi'
|
||||
'/system-tests.conf')
|
||||
self.parser = ConfigParser.SafeConfigParser()
|
||||
self.parser.read(config_path)
|
||||
|
||||
@property
|
||||
def auth_enabled(self):
|
||||
return self.parser.getboolean('auth', 'auth_on')
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self.parser.get('auth', 'username')
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
return self.parser.get('auth', 'password')
|
||||
|
||||
@property
|
||||
def base_server(self):
|
||||
return self.parser.get('marconi_env', 'marconi_url')
|
||||
|
||||
@property
|
||||
def marconi_version(self):
|
||||
return self.parser.get('marconi_env', 'marconi_version')
|
||||
|
||||
@property
|
||||
def tenant_id(self):
|
||||
return self.parser.get('marconi_env', 'tenant_id')
|
||||
|
||||
@property
|
||||
def base_url(self):
|
||||
return (self.base_server + '/' + self.marconi_version +
|
||||
'/' + self.tenant_id)
|
||||
|
||||
@property
|
||||
def uuid(self):
|
||||
return str(uuid.uuid1())
|
||||
|
||||
@property
|
||||
def user_agent(self):
|
||||
return self.parser.get('header_values', 'useragent')
|
||||
|
||||
@property
|
||||
def host(self):
|
||||
return self.parser.get('header_values', 'host')
|
200
marconi/tests/system/common/functionlib.py
Normal file
200
marconi/tests/system/common/functionlib.py
Normal file
@ -0,0 +1,200 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 binascii
|
||||
import json
|
||||
import os
|
||||
|
||||
from marconi.tests.system.common import config
|
||||
from marconi.tests.system.common import http
|
||||
|
||||
|
||||
cfg = config.Config()
|
||||
|
||||
|
||||
def get_keystone_token():
|
||||
"""Gets Keystone Auth token."""
|
||||
req_json = {
|
||||
"auth": {
|
||||
"passwordCredentials": {
|
||||
"username": cfg.username,
|
||||
"password": cfg.password
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
header = '{"Host": "identity.api.rackspacecloud.com",'
|
||||
header += '"Content-Type": "application/json","Accept":"application/json"}'
|
||||
url = cfg.auth_url
|
||||
|
||||
response = http.post(url=url, header=header, body=req_json)
|
||||
response_body = json.loads(response.text)
|
||||
|
||||
auth_token = response_body["access"]["token"]["id"]
|
||||
return auth_token
|
||||
|
||||
|
||||
def get_auth_token():
|
||||
"""Returns a valid auth token if auth is turned on."""
|
||||
if cfg.auth_enabled == "true":
|
||||
auth_token = get_keystone_token()
|
||||
else:
|
||||
auth_token = "notrealtoken"
|
||||
return auth_token
|
||||
|
||||
|
||||
def create_marconi_headers():
|
||||
"""Returns headers to be used for all Marconi requests."""
|
||||
auth_token = get_auth_token()
|
||||
|
||||
headers = '{"Host": "<HOST>","User-Agent": "<USER-AGENT>","Date":"<DATE>",'
|
||||
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
|
||||
headers += '"X-Auth-Token": "<auth_token>","Client-ID": "<UUID>"}'
|
||||
headers = headers.replace("<auth_token>", auth_token)
|
||||
headers = headers.replace("<HOST>", cfg.host)
|
||||
headers = headers.replace("<USER-AGENT>", cfg.user_agent)
|
||||
headers = headers.replace("<UUID>", cfg.uuid)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def invalid_auth_token_header():
|
||||
"""Returns a header with invalid auth token."""
|
||||
auth_token = get_auth_token()
|
||||
|
||||
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
|
||||
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
|
||||
headers += '"X-Auth-Token": "<auth_token>"}'
|
||||
headers = headers.replace("<auth_token>", auth_token)
|
||||
headers = headers.replace("<HOST>", cfg.host)
|
||||
headers = headers.replace("<USER-AGENT>", cfg.user_agent)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def missing_header_fields():
|
||||
"""Returns a header with missing USER_AGENT header."""
|
||||
auth_token = get_auth_token()
|
||||
|
||||
headers = '{"Host": "<HOST>","Date": "<DATE>",'
|
||||
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
|
||||
headers += '"X-Auth-Token": "<auth_token>"}'
|
||||
headers = headers.replace("<auth_token>", auth_token)
|
||||
headers = headers.replace("<HOST>", cfg.host)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def plain_text_in_header():
|
||||
"""Returns headers to be used for all Marconi requests."""
|
||||
auth_token = get_auth_token()
|
||||
|
||||
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
|
||||
headers += '"Accept": "text/plain","Accept-Encoding": "gzip",'
|
||||
headers += '"X-Auth-Token": "<auth_token>"}'
|
||||
headers = headers.replace("<auth_token>", auth_token)
|
||||
headers = headers.replace("<HOST>", cfg.host)
|
||||
headers = headers.replace("<USER-AGENT>", cfg.user_agent)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def asterisk_in_header():
|
||||
"""Returns headers to be used for all Marconi requests."""
|
||||
auth_token = get_auth_token()
|
||||
|
||||
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
|
||||
headers += '"Accept": "*/*","Accept-Encoding": "gzip",'
|
||||
headers += '"X-Auth-Token": "<auth_token>"}'
|
||||
headers = headers.replace("<auth_token>", auth_token)
|
||||
headers = headers.replace("<HOST>", cfg.host)
|
||||
headers = headers.replace("<USER-AGENT>", cfg.user_agent)
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def get_headers(input_header):
|
||||
"""Creates http request headers.
|
||||
|
||||
1. If header value is specified in the test_data.csv, that will be used.
|
||||
2. Headers can also be substituted in the Robot test case definition
|
||||
file (*_tests.txt)
|
||||
3. If 1. & 2. is not true -->
|
||||
Replaces the header data with generic Marconi headers.
|
||||
"""
|
||||
if input_header:
|
||||
header = input_header
|
||||
else:
|
||||
header = create_marconi_headers()
|
||||
return header
|
||||
|
||||
|
||||
def get_custom_body(kwargs):
|
||||
"""Returns a custom request body."""
|
||||
req_body = {"data": "<DATA>"}
|
||||
if "metadatasize" in kwargs.keys():
|
||||
random_data = binascii.b2a_hex(os.urandom(kwargs["metadatasize"]))
|
||||
req_body["data"] = random_data
|
||||
return json.dumps(req_body)
|
||||
|
||||
|
||||
def create_url_from_appender(appender):
|
||||
"""Returns complete url using the appender (with a a preceding '/')."""
|
||||
next_url = str(cfg.base_server + appender)
|
||||
return(next_url)
|
||||
|
||||
|
||||
def get_url_from_location(header):
|
||||
"""returns : the complete url referring to the location."""
|
||||
location = header["location"]
|
||||
url = create_url_from_appender(location)
|
||||
return url
|
||||
|
||||
|
||||
def verify_metadata(get_data, posted_body):
|
||||
"""@todo(malini) - Really verify the metadata."""
|
||||
test_result_flag = False
|
||||
|
||||
get_data = str(get_data)
|
||||
posted_body = str(posted_body)
|
||||
print(get_data, type(get_data))
|
||||
print(posted_body, type(posted_body))
|
||||
if get_data in posted_body:
|
||||
print("AYYY")
|
||||
else:
|
||||
test_result_flag = False
|
||||
print("NAYYY")
|
||||
|
||||
return test_result_flag
|
||||
|
||||
|
||||
def verify_delete(url, header):
|
||||
"""Verifies the DELETE was successful, with a GET on the deleted item."""
|
||||
test_result_flag = False
|
||||
|
||||
getmsg = http.get(url, header)
|
||||
if getmsg.status_code == 404:
|
||||
test_result_flag = True
|
||||
else:
|
||||
print("GET after DELETE failed")
|
||||
print("URL")
|
||||
print url
|
||||
print("headers")
|
||||
print header
|
||||
print("Response Body")
|
||||
print getmsg.text
|
||||
assert test_result_flag, "GET Code {}".format(getmsg.status_code)
|
||||
|
||||
return test_result_flag
|
176
marconi/tests/system/common/http.py
Executable file
176
marconi/tests/system/common/http.py
Executable file
@ -0,0 +1,176 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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
|
||||
import requests
|
||||
|
||||
|
||||
def get(url, header='', param=''):
|
||||
"""Does http GET."""
|
||||
if header:
|
||||
header = json.loads(header)
|
||||
try:
|
||||
response = requests.get(url, headers=header, params=param)
|
||||
except requests.ConnectionError as detail:
|
||||
print("ConnectionError: Exception in http.get {}".format(detail))
|
||||
except requests.HTTPError as detail:
|
||||
print("HTTPError: Exception in http.get {}".format(detail))
|
||||
except requests.Timeout as detail:
|
||||
print("Timeout: Exception in http.get {}".format(detail))
|
||||
except requests.TooManyRedirects as detail:
|
||||
print("TooManyRedirects: Exception in http.get {}".format(detail))
|
||||
return response
|
||||
|
||||
|
||||
def post(url, header='', body='', param=''):
|
||||
"""Does http POST."""
|
||||
if header:
|
||||
header = json.loads(header)
|
||||
body = str(body)
|
||||
body = body.replace("'", '"')
|
||||
try:
|
||||
response = requests.post(url, headers=header, data=body,
|
||||
params=param)
|
||||
except requests.ConnectionError as detail:
|
||||
print("ConnectionError: Exception in http.post {}".format(detail))
|
||||
except requests.HTTPError as detail:
|
||||
print("HTTPError: Exception in http.post {}".format(detail))
|
||||
except requests.Timeout as detail:
|
||||
print("Timeout: Exception in http.post {}".format(detail))
|
||||
except requests.TooManyRedirects as detail:
|
||||
print("TooManyRedirects: Exception in http.post {}".format(detail))
|
||||
return response
|
||||
|
||||
|
||||
def put(url, header='', body='', param=''):
|
||||
"""Does http PUT."""
|
||||
response = None
|
||||
if header:
|
||||
header = json.loads(header)
|
||||
|
||||
try:
|
||||
response = requests.put(url, headers=header, data=body,
|
||||
params=param)
|
||||
except requests.ConnectionError as detail:
|
||||
print("ConnectionError: Exception in http.put {}".format(detail))
|
||||
except requests.HTTPError as detail:
|
||||
print("HTTPError: Exception in http.put {}".format(detail))
|
||||
except requests.Timeout as detail:
|
||||
print("Timeout: Exception in http.put {}".format(detail))
|
||||
except requests.TooManyRedirects as detail:
|
||||
print("TooManyRedirects: Exception in http.put {}".format(detail))
|
||||
return response
|
||||
|
||||
|
||||
def delete(url, header='', param=''):
|
||||
"""Does http DELETE."""
|
||||
response = None
|
||||
if header:
|
||||
header = json.loads(header)
|
||||
|
||||
try:
|
||||
response = requests.delete(url, headers=header, params=param)
|
||||
except requests.ConnectionError as detail:
|
||||
print("ConnectionError: Exception in http.delete {}".format(detail))
|
||||
except requests.HTTPError as detail:
|
||||
print("HTTPError: Exception in http.delete {}".format(detail))
|
||||
except requests.Timeout as detail:
|
||||
print("Timeout: Exception in http.delete {}".format(detail))
|
||||
except requests.TooManyRedirects as detail:
|
||||
print("TooManyRedirects: Exception in http.delete {}".format(detail))
|
||||
return response
|
||||
|
||||
|
||||
def patch(url, header='', body='', param=''):
|
||||
"""Does http PATCH."""
|
||||
response = None
|
||||
if header:
|
||||
header = json.loads(header)
|
||||
|
||||
try:
|
||||
response = requests.patch(url, headers=header, data=body,
|
||||
params=param)
|
||||
except requests.ConnectionError as detail:
|
||||
print("ConnectionError: Exception in http.patch {}".format(detail))
|
||||
except requests.HTTPError as detail:
|
||||
print("HTTPError: Exception in http.patch {}".format(detail))
|
||||
except requests.Timeout as detail:
|
||||
print("Timeout: Exception in http.patch {}".format(detail))
|
||||
except requests.TooManyRedirects as detail:
|
||||
print("TooManyRedirects: Exception in http.patch {}".format(detail))
|
||||
return response
|
||||
|
||||
|
||||
def executetests(row):
|
||||
"""Entry Point for all tests.
|
||||
|
||||
Executes the tests defined in the *_tests.txt,
|
||||
using the test data from *_data.csv.
|
||||
"""
|
||||
http_verb = row['httpverb'].strip()
|
||||
url = row['url']
|
||||
header = row['header']
|
||||
params = row['params']
|
||||
body = row['body']
|
||||
expected_RC = row['expectedRC']
|
||||
expected_RC = int(expected_RC)
|
||||
expected_response_body = row['expectedResponseBody']
|
||||
|
||||
response = None
|
||||
|
||||
if http_verb == 'GET':
|
||||
response = get(url, header, params)
|
||||
elif http_verb == 'POST':
|
||||
response = post(url, header, body, params)
|
||||
elif http_verb == 'PUT':
|
||||
response = put(url, header, body, params)
|
||||
elif http_verb == 'DELETE':
|
||||
response = delete(url, header, params)
|
||||
elif http_verb == 'PATCH':
|
||||
response = patch(url, header, body, params)
|
||||
|
||||
if response is not None:
|
||||
test_result_flag = verify_response(response, expected_RC)
|
||||
else:
|
||||
test_result_flag = False
|
||||
|
||||
if test_result_flag:
|
||||
return response.headers, response.text
|
||||
else:
|
||||
print http_verb
|
||||
print url
|
||||
print header
|
||||
print body
|
||||
print "Actual Response: {}".format(response.status_code)
|
||||
print "Actual Response Headers"
|
||||
print response.headers
|
||||
print"Actual Response Body"
|
||||
print response.text
|
||||
print"ExpectedRC: {}".format(expected_RC)
|
||||
print"expectedresponsebody: {}".format(expected_response_body)
|
||||
assert test_result_flag, "Actual Response does not match the Expected"
|
||||
|
||||
|
||||
def verify_response(response, expected_RC):
|
||||
"""Compares the http Response code with the expected Response code."""
|
||||
test_result_flag = True
|
||||
actual_RC = response.status_code
|
||||
actual_response_body = response.text
|
||||
if actual_RC != expected_RC:
|
||||
test_result_flag = False
|
||||
print("Unexpected http Response code {}".format(actual_RC))
|
||||
print "Response Body returned"
|
||||
print actual_response_body
|
||||
return test_result_flag
|
0
marconi/tests/system/etc/__init__.py
Normal file
0
marconi/tests/system/etc/__init__.py
Normal file
15
marconi/tests/system/etc/system-tests.conf-sample
Normal file
15
marconi/tests/system/etc/system-tests.conf-sample
Normal file
@ -0,0 +1,15 @@
|
||||
[auth]
|
||||
auth_on = true
|
||||
#auth endpoint - url to get the auth token
|
||||
url = https://identity.xxx.xxxx.com/v2.0/tokens
|
||||
username = user
|
||||
password = secret
|
||||
|
||||
[marconi_env]
|
||||
marconi_url = http://166.78.143.130:80
|
||||
marconi_version = v1
|
||||
tenant_id = 1
|
||||
|
||||
[header_values]
|
||||
host = marconi.test.com
|
||||
useragent = systemtests
|
0
marconi/tests/system/messages/__init__.py
Normal file
0
marconi/tests/system/messages/__init__.py
Normal file
38
marconi/tests/system/messages/getdata.py
Executable file
38
marconi/tests/system/messages/getdata.py
Executable file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 csv
|
||||
|
||||
from marconi.tests.system.common import config
|
||||
from marconi.tests.system.common import functionlib
|
||||
|
||||
|
||||
cfg = config.Config()
|
||||
|
||||
|
||||
def get_data():
|
||||
"""Gets Test Data from a csv file."""
|
||||
DATA = []
|
||||
with open('marconi/tests/system/messages/test_data.csv', 'rb') as datafile:
|
||||
test_data = csv.DictReader(datafile, delimiter='|')
|
||||
for row in test_data:
|
||||
DATA.append(row)
|
||||
for row in DATA:
|
||||
row['header'] = functionlib.get_headers(row['header'])
|
||||
row['url'] = row['url'].replace("<BASE_URL>", cfg.base_url)
|
||||
return DATA
|
||||
|
||||
|
||||
API_TEST_DATA = get_data()
|
53
marconi/tests/system/messages/messages_tests.txt
Executable file
53
marconi/tests/system/messages/messages_tests.txt
Executable file
@ -0,0 +1,53 @@
|
||||
| *Setting* | *Value* |
|
||||
| Documentation | Marconi - Message Test Suite |
|
||||
| Library | ../common/http.py |
|
||||
| Library | ../common/functionlib.py |
|
||||
| Library | msgfnlib.py |
|
||||
| Library | Collections |
|
||||
| Variables | getdata.py |
|
||||
| Force Tags | MESSAGES |
|
||||
| Suite Setup | executetests | ${API_TEST_DATA[0]} | # Test Suite Setup - Creates a Queue
|
||||
| Suite Teardown | executetests | ${API_TEST_DATA[7]} | # Test Suite Teardown - Deletes the queue created by setup
|
||||
|
||||
| *Test Case* | *Action* | *Argument* | *Argument* | *Argument* | # Comment
|
||||
| 1:POST SINGLE MESSAGE | [DOCUMENTATION] | | Post single message | | #TEST CASE 1 - POST SINGLE MESSAGE
|
||||
| | [Tags] | INSERT_MESSAGE | | |
|
||||
| | ${reqparam}= | Create Dictionary | messagecount | ${1} | # test Setup- Specify count of messages to be posted
|
||||
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
|
||||
| | Set To Dictionary | ${API_TEST_DATA[1]} | body | ${msgbody} | # test Setup -Set the POST body
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | | # postresponse = [httpheaders, httpresponsebody] |
|
||||
| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[1]["body"]} | | # GET the posted message & verify metadata
|
||||
| |
|
||||
| 2:POST MULTIPLE MESSAGES | [DOCUMENTATION] | | Post 50 messages | | #TEST CASE 2 - POST MULTIPLE MESSAGES
|
||||
| | [Tags] | INSERT_MESSAGE | | |
|
||||
| | ${reqparam}= | Create Dictionary | messagecount | ${50} | # Specify count of messages to be posted
|
||||
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # Gets the message body to post
|
||||
| | Set To Dictionary | ${API_TEST_DATA[2]} | body | ${msgbody} | # Set the POST body
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[2]} | | # postresponse = [httpheaders, httpresponsebody]
|
||||
#| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[2]["body"]} | | # GET the posted messages & verify metadata
|
||||
| |
|
||||
| 3:GET MESSAGES-no params | [DOCUMENTATION] | Get message with no params | | # TEST CASE 3 - GET MESSAGE WITH NO PARAMS
|
||||
| | @{getresponse}= | executetests | ${API_TEST_DATA[3]} |
|
||||
| | verifygetmsgs | ${10} | @{getresponse} | # Verifies that number of messages returned is <= 10
|
||||
| |
|
||||
| 4:GET MESSAGES-limit=5 | [DOCUMENTATION] | Get message with limit = 5 | | # TEST CASE 4 - GET MESSAGE WITH limit = 5
|
||||
| | @{getresponse}= | executetests | ${API_TEST_DATA[4]} |
|
||||
| | verifygetmsgs | ${5} | @{getresponse} | # Verifies that number of messages returned is <= 5
|
||||
| 5:GET MESSAGES-echo=False | [DOCUMENTATION] | Get message with echo=False | | # TEST CASE 5 - GET MESSAGE WITH echo = False
|
||||
| | @{getresponse}= | executetests | ${API_TEST_DATA[5]} |
|
||||
| | verifygetmsgs | ${10} | @{getresponse} | # Verifies that number of messages returned is <= 10
|
||||
| 6:DELETE MESSAGE | [DOCUMENTATION] | | Delete message | | #TEST CASE 6 - DELETE MESSAGE
|
||||
| | [Tags] | INSERT_MESSAGE | | |
|
||||
| | ${reqparam}= | Create Dictionary | messagecount | ${1} | # test Setup- Specify count of messages to be posted
|
||||
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
|
||||
| | Set To Dictionary | ${API_TEST_DATA[1]} | body | ${msgbody} | # test Setup -Set the POST body
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | | # postresponse = [httpheaders, httpresponsebody] |
|
||||
| | deletemsg | ${postresponse[0]} | | | # GET the posted message & verify metadata
|
||||
| 7:POST 60 MESSAGES | [DOCUMENTATION] | POST > MAX NUMBER OF MESSAGES | | | #TEST CASE 7 - POST > 50 MESSAGES
|
||||
| | ... | ALLOWED PER POST (currently 50) | | |
|
||||
| | [Tags] | INSERT_MESSAGE | | |
|
||||
| | ${reqparam}= | Create Dictionary | messagecount | ${60} | # test Setup- Specify count of messages to be posted
|
||||
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
|
||||
| | Set To Dictionary | ${API_TEST_DATA[6]} | body | ${msgbody} | # test Setup -Set the POST body
|
||||
| | @{postresponse}= | executetests | ${API_TEST_DATA[6]} | | # postresponse = [httpheaders, httpresponsebody] |
|
||||
| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[6]["body"]} | | # GET the posted message & verify metadata
|
201
marconi/tests/system/messages/msgfnlib.py
Normal file
201
marconi/tests/system/messages/msgfnlib.py
Normal file
@ -0,0 +1,201 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 __future__ import with_statement
|
||||
import json
|
||||
import random
|
||||
|
||||
from marconi.tests.system.common import config
|
||||
from marconi.tests.system.common import functionlib
|
||||
from marconi.tests.system.common import http
|
||||
|
||||
|
||||
cfg = config.Config()
|
||||
|
||||
|
||||
def generate_dict(dict_length):
|
||||
"""Returns dictionary of specified length. Key:Value is random data."""
|
||||
with open('/usr/share/dict/words', 'rt') as f:
|
||||
words = f.readlines()
|
||||
words = [w.rstrip() for w in words]
|
||||
|
||||
dict = {}
|
||||
while len(dict) < dict_length:
|
||||
key, value = random.sample(words, 2)
|
||||
dict.update({key: value})
|
||||
return dict
|
||||
|
||||
|
||||
def single_message_body(**kwargs):
|
||||
"""Returns message body for one message .
|
||||
|
||||
The ttl will be a random value (60 <= TTL <= 1209600).
|
||||
The message body will be random dict.
|
||||
:param **kwargs can be {messagesize: x} , where x is message size
|
||||
:param **kwargs can be {ttl: x} , where x is ttl in seconds
|
||||
"""
|
||||
valid_ttl = random.randint(60, 1209600)
|
||||
|
||||
if "messagesize" in kwargs.keys():
|
||||
body = generate_dict(kwargs["messagesize"])
|
||||
else:
|
||||
body = generate_dict(2)
|
||||
|
||||
if "ttl" in kwargs.keys():
|
||||
ttl = kwargs["ttl"]
|
||||
else:
|
||||
ttl = valid_ttl
|
||||
|
||||
message_body = {"ttl": ttl, "body": body}
|
||||
return message_body
|
||||
|
||||
|
||||
def get_message_body(**kwargs):
|
||||
"""Returns request body for post message tests.
|
||||
|
||||
:param **kwargs can be {messagecount: x} , where x is the # of messages.
|
||||
"""
|
||||
message_count = kwargs["messagecount"]
|
||||
multiple_message_body = []
|
||||
i = 0
|
||||
while i < message_count:
|
||||
message_body = single_message_body(**kwargs)
|
||||
multiple_message_body.append(message_body)
|
||||
i = i + 1
|
||||
return multiple_message_body
|
||||
|
||||
|
||||
def dummyget_message_body(dict):
|
||||
"""Dummy function since Robot framework does not support **kwargs."""
|
||||
dict = get_message_body(**dict)
|
||||
return dict
|
||||
|
||||
|
||||
def create_url(base_url=cfg.base_url, *msg_id_list):
|
||||
"""Creates url list for retrieving messages with message id."""
|
||||
url = [(base_url + msg_id) for msg_id in msg_id_list]
|
||||
return url
|
||||
|
||||
|
||||
def verify_msg_length(count=10, *msg_list):
|
||||
"""Verifies the number of messages returned.
|
||||
|
||||
:param count: limit specified in the GET url.
|
||||
:param *msg_list : list of message returned in the GET.
|
||||
"""
|
||||
test_result_flag = False
|
||||
msg_body = json.loads(msg_list[0])
|
||||
msg_list = msg_body["messages"]
|
||||
msg_count = len(msg_list)
|
||||
if (msg_count <= count):
|
||||
test_result_flag = True
|
||||
else:
|
||||
return test_result_flag
|
||||
return test_result_flag
|
||||
|
||||
|
||||
def get_href(*msg_list):
|
||||
"""Extracts href."""
|
||||
msg_body = json.loads(msg_list[0])
|
||||
link = msg_body["links"]
|
||||
href = link[0]["href"]
|
||||
return href
|
||||
|
||||
|
||||
def verify_post_msg(msg_headers, posted_body):
|
||||
"""Verifies the response of POST Message(s).
|
||||
|
||||
Retrieves the posted Message(s) & validates the message metadata.
|
||||
"""
|
||||
test_result_flag = False
|
||||
|
||||
location = msg_headers['location']
|
||||
url = functionlib.create_url_from_appender(location)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
getmsg = http.get(url, header)
|
||||
if getmsg.status_code == 200:
|
||||
test_result_flag = functionlib.verify_metadata(getmsg.text,
|
||||
posted_body)
|
||||
else:
|
||||
print("Failed to GET {}".format(url))
|
||||
print("Request Header")
|
||||
print header
|
||||
print("Response Headers")
|
||||
print getmsg.headers
|
||||
print("Response Body")
|
||||
print getmsg.text
|
||||
assert test_result_flag, "HTTP code {}".format(getmsg.status_code)
|
||||
|
||||
|
||||
def get_next_msgset(responsetext):
|
||||
"""Follows the href path & GETs the next batch of messages recursively."""
|
||||
test_result_flag = False
|
||||
|
||||
href = get_href(responsetext)
|
||||
url = functionlib.create_url_from_appender(href)
|
||||
header = functionlib.create_marconi_headers()
|
||||
|
||||
getmsg = http.get(url, header)
|
||||
if getmsg.status_code == 200:
|
||||
return get_next_msgset(getmsg.text)
|
||||
elif getmsg.status_code == 204:
|
||||
test_result_flag = True
|
||||
return test_result_flag
|
||||
else:
|
||||
test_result_flag = False
|
||||
print("Failed to GET {}".format(url))
|
||||
print(getmsg.text)
|
||||
assert test_result_flag, "HTTP code {}".format(getmsg.status_code)
|
||||
|
||||
|
||||
def verify_get_msgs(count, *getresponse):
|
||||
"""Verifies GET message & does a recursive GET if needed."""
|
||||
test_result_flag = False
|
||||
|
||||
body = getresponse[1]
|
||||
|
||||
msglengthflag = verify_msg_length(count, body)
|
||||
if msglengthflag:
|
||||
test_result_flag = get_next_msgset(body)
|
||||
else:
|
||||
print("Messages returned exceed requested number of messages")
|
||||
test_result_flag = False
|
||||
|
||||
if not test_result_flag:
|
||||
assert test_result_flag, "Recursive Get Messages Failed"
|
||||
|
||||
|
||||
def delete_msg(*postresponse):
|
||||
"""Post DELETE message & verifies that a subsequent GET returns 404."""
|
||||
test_result_flag = False
|
||||
headers = str(postresponse[0])
|
||||
headers = headers.replace("'", '"')
|
||||
headers = json.loads(headers)
|
||||
location = headers['location']
|
||||
url = functionlib.create_url_from_appender(location)
|
||||
header = functionlib.create_marconi_headers()
|
||||
deletemsg = http.delete(url, header)
|
||||
if deletemsg.status_code == 204:
|
||||
test_result_flag = functionlib.verify_delete(url, header)
|
||||
else:
|
||||
print("DELETE message failed")
|
||||
print("URL")
|
||||
print url
|
||||
print("headers")
|
||||
print header
|
||||
print("Response Body")
|
||||
print deletemsg.text
|
||||
assert test_result_flag, "DELETE Code {}".format(deletemsg.status_code)
|
9
marconi/tests/system/messages/test_data.csv
Executable file
9
marconi/tests/system/messages/test_data.csv
Executable file
@ -0,0 +1,9 @@
|
||||
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
|
||||
0|PUT |<BASE_URL>/queues/msgtestqueue||{"messages":{"ttl": 86400}}||201|
|
||||
1|POST |<BASE_URL>/queues/msgtestqueue/messages||||201|
|
||||
2|POST |<BASE_URL>/queues/msgtestqueue/messages||||201|
|
||||
3|GET |<BASE_URL>/queues/msgtestqueue/messages?echo=true||||200|
|
||||
4|GET |<BASE_URL>/queues/msgtestqueue/messages?limit=5&echo=true||||200|
|
||||
5|GET |<BASE_URL>/queues/msgtestqueue/messages?limit=5&echo=true||||200|
|
||||
6|POST |<BASE_URL>/queues/msgtestqueue/messages||{"messages":{"ttl": 86400}}||201|
|
||||
0|DELETE |<BASE_URL>/queues/msgtestqueue||||204|
|
Can't render this file because it contains an unexpected character in line 2 and column 44.
|
0
marconi/tests/system/queue/__init__.py
Normal file
0
marconi/tests/system/queue/__init__.py
Normal file
38
marconi/tests/system/queue/getdata.py
Executable file
38
marconi/tests/system/queue/getdata.py
Executable file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 csv
|
||||
|
||||
from marconi.tests.system.common import config
|
||||
from marconi.tests.system.common import functionlib
|
||||
|
||||
|
||||
cfg = config.Config()
|
||||
|
||||
|
||||
def get_data():
|
||||
"""Gets Test Data from a csv file."""
|
||||
DATA = []
|
||||
with open('marconi/tests/system/queue/test_data.csv', 'rb') as datafile:
|
||||
test_data = csv.DictReader(datafile, delimiter='|')
|
||||
for row in test_data:
|
||||
DATA.append(row)
|
||||
for row in DATA:
|
||||
row['header'] = functionlib.get_headers(row['header'])
|
||||
row['url'] = row['url'].replace("<BASE_URL>", cfg.base_url)
|
||||
return DATA
|
||||
|
||||
|
||||
API_TEST_DATA = get_data()
|
106
marconi/tests/system/queue/queue_tests.txt
Executable file
106
marconi/tests/system/queue/queue_tests.txt
Executable file
@ -0,0 +1,106 @@
|
||||
| *Setting* | *Value* |
|
||||
| Documentation | Marconi - Queue Test Suite |
|
||||
| Library | ../common/http.py |
|
||||
| Library | queuefnlib.py |
|
||||
| Library | ../common/functionlib.py |
|
||||
| Library | Collections |
|
||||
| Variables | getdata.py |
|
||||
| Force Tags | QUEUE |
|
||||
|
||||
| *Test Case* | *Action* | *Argument* | *Argument* |
|
||||
| 1: PUT QUEUE | [DOCUMENTATION] | Creates, gets & verifies | |
|
||||
| | ... | Queue | |
|
||||
| | @{putresponse}= | executetests | ${API_TEST_DATA[0]} |
|
||||
| | ${url}= | geturlfromlocation | ${putresponse[0]} |
|
||||
| | ${getresponse}= | executetests | ${API_TEST_DATA[1]} |
|
||||
| | verifymetadata | ${API_TEST_DATA[0]["body"]} | ${getresponse} |
|
||||
| 2: PUT QUEUE | [DOCUMENTATION] | Verifies that queue name | |
|
||||
| | ... | are NOT case sensitive | |
|
||||
| | ${putresponse}= | executetests | ${API_TEST_DATA[2]} |
|
||||
| | ${getresponse}= | executetests | ${API_TEST_DATA[3]} |
|
||||
| | verifymetadata | ${API_TEST_DATA[2]["body"]} | ${getresponse} |
|
||||
| 3: UPDATE QUEUE | [DOCUMENTATION] | Updates an existing queue | |
|
||||
| | ${putresponse}= | executetests | ${API_TEST_DATA[4]} |
|
||||
| | ${getresponse}= | executetests | ${API_TEST_DATA[5]} |
|
||||
| | verifymetadata | ${API_TEST_DATA[4]["body"]} | ${getresponse} |
|
||||
| 4: PUT QUEUE | [DOCUMENTATION] | Create Queue with no request | |
|
||||
| | ... | body | |
|
||||
| | executetests | ${API_TEST_DATA[6]} | |
|
||||
| 5: PUT QUEUE | [DOCUMENTATION] | Create Queue with invalid | |
|
||||
| | ... | Authtoken | |
|
||||
| | ${header}= | invalidauthtokenheader | |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[7]} | header | ${header} | # test Setup -Set the POST header
|
||||
| | executetests | ${API_TEST_DATA[7]} | |
|
||||
| 6: PUT QUEUE | [DOCUMENTATION] | Create Queue with missing | |
|
||||
| | ... | header field USERAGENT | |
|
||||
| | ${header}= | missingheaderfields | |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[8]} | header | ${header} | # test Setup -Set the POST header
|
||||
| | executetests | ${API_TEST_DATA[8]} | |
|
||||
| 7: PUT QUEUE | [DOCUMENTATION] | Verifies metadata toplevel | |
|
||||
| | ... | field do not start with _ | |
|
||||
| | executetests | ${API_TEST_DATA[9]} | |
|
||||
| 8: PUT QUEUE | [DOCUMENTATION] | Header has Accept value that | |
|
||||
| | ... | is not "application/json" | |
|
||||
| | ${header}= | plaintextinheader | |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[10]} | header | ${header} | # test Setup -Set the POST header
|
||||
| | executetests | ${API_TEST_DATA[10]} | |
|
||||
| 9: PUT QUEUE | [DOCUMENTATION] | Header has Accept value that | |
|
||||
| | ... | is "\*/\*" | |
|
||||
| | ${header}= | asteriskinheader | |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[11]} | header | ${header} | # test Setup -Set the POST header
|
||||
| | executetests | ${API_TEST_DATA[11]} | |
|
||||
| 10: PUT QUEUE | [DOCUMENTATION] | Create queue with Non ASCII | |
|
||||
| | ... | characters in name | |
|
||||
| | executetests | ${API_TEST_DATA[12]} | |
|
||||
| 11: PUT QUEUE | [DOCUMENTATION] | Create queue with Non ASCII | |
|
||||
| | ... | characters in body | |
|
||||
| | executetests | ${API_TEST_DATA[13]} | |
|
||||
| 12: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
|
||||
| | ... | size = 4KB | |
|
||||
| | ${reqdata}= | Create Dictionary | metadatasize | ${4096} |
|
||||
| | ${body}= | getcustombody | ${reqdata} |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[14]} | body | ${body} | # test Setup -Set the POST body
|
||||
| | executetests | ${API_TEST_DATA[14]} | |
|
||||
| 13: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
|
||||
| | ... | size = 4KB + 1 | |
|
||||
| | ${reqdata}= | Create Dictionary | metadatasize | ${4097} |
|
||||
| | ${body}= | getcustombody | ${reqdata} |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[15]} | body | ${body} | # test Setup -Set the POST body
|
||||
| | executetests | ${API_TEST_DATA[15]} | |
|
||||
| 14: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
|
||||
| | ... | size = 4KB - 1 | |
|
||||
| | ${reqdata}= | Create Dictionary | metadatasize | ${4095} |
|
||||
| | ${body}= | getcustombody | ${reqdata} |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[16]} | body | ${body} | # test Setup -Set the POST body
|
||||
| | executetests | ${API_TEST_DATA[16]} | |
|
||||
| 15: PUT QUEUE | [DOCUMENTATION] | Create queue with name | |
|
||||
| | ... | longer than 64 char | |
|
||||
| | ${url}= | getqueuename | |
|
||||
| | Set To Dictionary | ${API_TEST_DATA[17]} | url | ${url} | # test Setup -Set the PUT url
|
||||
| | executetests | ${API_TEST_DATA[17]} | |
|
||||
| 16: GET QUEUE STATS | [DOCUMENTATION] | Get Queue Stats | |
|
||||
| | @{getresponse}= | executetests | ${API_TEST_DATA[18]} |
|
||||
| | verifyqueuestats | @{getresponse} | |
|
||||
| 17: LIST QUEUES | [DOCUMENTATION] | List queues with no params | |
|
||||
| | @{listqueues}= | executetests | ${API_TEST_DATA[19]} |
|
||||
| | verifylistqueues | @{listqueues} | |
|
||||
| 18: LIST QUEUES DETAILED | [DOCUMENTATION] | List queues ?detailed=true | |
|
||||
| | @{listqueues}= | executetests | ${API_TEST_DATA[20]} |
|
||||
| | verifylistqueues | @{listqueues} | |
|
||||
| 19: DELETE QUEUE | [DOCUMENTATION] | Delete a queue | |
|
||||
| | executetests | ${API_TEST_DATA[21]} | |
|
||||
| 20: PUT QUEUE | [DOCUMENTATION] | Creates a queue with same | |
|
||||
| | ... | name as deleted | |
|
||||
| | @{putresponse}= | executetests | ${API_TEST_DATA[22]} |
|
||||
| | ${url}= | geturlfromlocation | ${putresponse[0]} |
|
||||
| | ${getresponse}= | executetests | ${API_TEST_DATA[23]} |
|
||||
| | verifymetadata | ${API_TEST_DATA[22]["body"]} | ${getresponse} |
|
||||
| 21: PUT QUEUE | [DOCUMENTATION] | Create Queue with invalid | |
|
||||
| | ... | char in metadata | |
|
||||
| | executetests | ${API_TEST_DATA[24]} | |
|
||||
| 22: DELETE QUEUE | [DOCUMENTATION] | Delete a queue | |
|
||||
| | executetests | ${API_TEST_DATA[25]} | |
|
||||
| 23: GET QUEUE - 404 | [DOCUMENTATION] | Get non existing queue | |
|
||||
| | executetests | ${API_TEST_DATA[26]} | |
|
||||
|
||||
|
110
marconi/tests/system/queue/queuefnlib.py
Normal file
110
marconi/tests/system/queue/queuefnlib.py
Normal file
@ -0,0 +1,110 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 binascii
|
||||
import json
|
||||
import os
|
||||
|
||||
from marconi.tests.system.common import functionlib
|
||||
|
||||
|
||||
def verify_queue_stats(*get_response):
|
||||
"""Verifies GET queue/stats response.
|
||||
|
||||
Verification Steps:
|
||||
1. stats json body has the keys - action & messages.
|
||||
2. messages json has the keys - claimed & free.
|
||||
3. claimed & free key values are int.
|
||||
"""
|
||||
|
||||
test_result_flag = True
|
||||
headers = get_response[0]
|
||||
body = json.loads(get_response[1])
|
||||
|
||||
keys_in_body = body.keys()
|
||||
keys_in_body.sort()
|
||||
|
||||
if (keys_in_body == ["actions", "messages"]):
|
||||
stats = body["messages"]
|
||||
keys_in_stats = stats.keys()
|
||||
keys_in_stats.sort()
|
||||
if (keys_in_stats == ["claimed", "free"]):
|
||||
try:
|
||||
int(stats["claimed"])
|
||||
int(stats["free"])
|
||||
except Exception:
|
||||
test_result_flag = False
|
||||
else:
|
||||
test_result_flag = False
|
||||
else:
|
||||
test_result_flag = False
|
||||
|
||||
if test_result_flag:
|
||||
return test_result_flag
|
||||
else:
|
||||
print headers
|
||||
print body
|
||||
assert test_result_flag, "Get Request stats failed"
|
||||
|
||||
|
||||
def get_queue_name(namelength=65):
|
||||
"""Returns a queuename of specified length.
|
||||
|
||||
By default, a name longer than Marconi allows - currently 64 char.
|
||||
"""
|
||||
|
||||
appender = "/queues/" + binascii.b2a_hex(os.urandom(namelength))
|
||||
url = functionlib.create_url_from_appender(appender)
|
||||
return url
|
||||
|
||||
|
||||
def verify_list_queues(*list_queue_response):
|
||||
"""Verifies the response of list queues."""
|
||||
response_body = json.loads(list_queue_response[1])
|
||||
|
||||
links = response_body['links']
|
||||
href = links[0]['href']
|
||||
detail_enabled = 'detailed=true' in href
|
||||
|
||||
queue_list = response_body['queues']
|
||||
test_result_flags = [verify_listed(queue, detail_enabled)
|
||||
for queue in queue_list]
|
||||
|
||||
if False in test_result_flags:
|
||||
test_result_flag = False
|
||||
print 'List Queue API response: {}'.format(response_body)
|
||||
assert test_result_flag, 'List Queue failed'
|
||||
|
||||
|
||||
def verify_listed(queue, detail_enabled):
|
||||
'''Verifies the listed queues.'''
|
||||
test_result_flag = True
|
||||
|
||||
keys = queue.keys()
|
||||
keys.sort()
|
||||
|
||||
if detail_enabled:
|
||||
expected_keys = ['href', 'metadata', 'name']
|
||||
else:
|
||||
expected_keys = ['href', 'name']
|
||||
|
||||
if keys == expected_keys:
|
||||
return test_result_flag
|
||||
else:
|
||||
print 'list_queue response does not match expected response'
|
||||
print queue
|
||||
test_result_flag = False
|
||||
|
||||
return test_result_flag
|
28
marconi/tests/system/queue/test_data.csv
Executable file
28
marconi/tests/system/queue/test_data.csv
Executable file
@ -0,0 +1,28 @@
|
||||
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
|
||||
1|PUT |<BASE_URL>/queues/qtestqueue||{"messages":{"ttl": 86400}}||201|
|
||||
1|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
|
||||
2|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||204|
|
||||
2|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
|
||||
3|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||204|
|
||||
3|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
|
||||
4|PUT |<BASE_URL>/queues/qtestqueue||||400|{"title": "Bad request","description": "Missing queue metadata."}
|
||||
5|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||401|
|
||||
6|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||400|
|
||||
7|PUT |<BASE_URL>/queues/qtestqueue||{"_TOPLEVEL": {"ttl": 86400}}||400|
|
||||
8|PUT |<BASE_URL>/queues/qtestqueue||{"TOPLEVEL": {"ttl": 86400}}||406|
|
||||
9|PUT |<BASE_URL>/queues/qtestqueue||{"TOPLEVEL": {"ttl": 86400}}||200|
|
||||
10|PUT |<BASE_URL>/queues/汉字/漢字||{"messages": {"ttl": 86400}}||201|
|
||||
11|PUT |<BASE_URL>/queues/qtestqueue||{"汉字": {"ttl": 86400}}||201|
|
||||
12|PUT |<BASE_URL>/queues/qtestqueue||||201|
|
||||
13|PUT |<BASE_URL>/queues/qtestqueue||||400|
|
||||
14|PUT |<BASE_URL>/queues/qtestqueue||||204|
|
||||
15|PUT |||{"messages":{"ttl": 86400}}||400|
|
||||
16|GET |<BASE_URL>/queues/qtestqueue/stats||||200|
|
||||
17|GET |<BASE_URL>/queues||||200|
|
||||
18|GET |<BASE_URL>/queues?detailed=true||||200|
|
||||
19|DELETE |<BASE_URL>/queues/qtestqueue||||204|
|
||||
20|PUT |<BASE_URL>/queues/qtestqueue||{"messages":{"ttl": 86400}}||201|
|
||||
20|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
|
||||
21|PUT |<BASE_URL>/queues/qtestqueue||{"mess~&%^":{"ttl": 86400}}||400|
|
||||
22|DELETE |<BASE_URL>/queues/qtestqueue||||204|
|
||||
23|GET |<BASE_URL>/queues/nonexistingqueue||||404|
|
Can't render this file because it contains an unexpected character in line 2 and column 43.
|
@ -1,6 +1,7 @@
|
||||
[nosetests]
|
||||
where=marconi/tests
|
||||
verbosity=2
|
||||
exclude=system/*
|
||||
|
||||
with-doctest = true
|
||||
|
||||
|
2
tools/system-test-requires
Normal file
2
tools/system-test-requires
Normal file
@ -0,0 +1,2 @@
|
||||
robotframework
|
||||
requests
|
Loading…
Reference in New Issue
Block a user