From 4fab7cabce83a2761956cab44e91d88486044882 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Fri, 11 Mar 2011 14:26:24 +0100 Subject: [PATCH] QA: Add tests for queries via RAPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: RenΓ© Nussbaumer <rn@google.com> --- qa/ganeti-qa.py | 1 + qa/qa_rapi.py | 126 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py index b2a7158f4..ecd7ee4d6 100755 --- a/qa/ganeti-qa.py +++ b/qa/ganeti-qa.py @@ -173,6 +173,7 @@ def RunClusterTests(): ("cluster-oob", qa_cluster.TestClusterOob), ("rapi", qa_rapi.TestVersion), ("rapi", qa_rapi.TestEmptyCluster), + ("rapi", qa_rapi.TestRapiQuery), ]: RunTestIf(test, fn) diff --git a/qa/qa_rapi.py b/qa/qa_rapi.py index a9c9ef828..fbcf98057 100644 --- a/qa/qa_rapi.py +++ b/qa/qa_rapi.py @@ -23,6 +23,7 @@ """ import tempfile +import random from ganeti import utils from ganeti import constants @@ -30,6 +31,9 @@ from ganeti import errors from ganeti import cli from ganeti import rapi from ganeti import objects +from ganeti import query +from ganeti import compat +from ganeti import qlang import ganeti.rapi.client # pylint: disable-msg=W0611 import ganeti.rapi.client_utils @@ -220,6 +224,122 @@ def TestEmptyCluster(): raise qa_error.Error("Non-implemented method didn't fail") +def TestRapiQuery(): + """Testing resource queries via remote API. + + """ + master_name = qa_utils.ResolveNodeName(qa_config.GetMasterNode()) + rnd = random.Random(7818) + + for what in constants.QR_VIA_RAPI: + all_fields = query.ALL_FIELDS[what].keys() + rnd.shuffle(all_fields) + + # No fields, should return everything + result = _rapi_client.QueryFields(what) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), len(all_fields)) + + # One field + result = _rapi_client.QueryFields(what, fields=["name"]) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), 1) + + # Specify all fields, order must be correct + result = _rapi_client.QueryFields(what, fields=all_fields) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), len(all_fields)) + AssertEqual([fdef.name for fdef in qresult.fields], all_fields) + + # Unknown field + result = _rapi_client.QueryFields(what, fields=["_unknown!"]) + qresult = objects.QueryFieldsResponse.FromDict(result) + AssertEqual(len(qresult.fields), 1) + AssertEqual(qresult.fields[0].name, "_unknown!") + AssertEqual(qresult.fields[0].kind, constants.QFT_UNKNOWN) + + # Try once more, this time without the client + _DoTests([ + ("/2/query/%s/fields" % what, None, "GET", None), + ("/2/query/%s/fields?fields=name,name,%s" % (what, all_fields[0]), + None, "GET", None), + ]) + + # Try missing query argument + try: + _DoTests([ + ("/2/query/%s" % what, None, "GET", None), + ]) + except rapi.client.GanetiApiError, err: + AssertEqual(err.code, 400) + else: + raise qa_error.Error("Request missing 'fields' parameter didn't fail") + + def _Check(exp_fields, data): + qresult = objects.QueryResponse.FromDict(data) + AssertEqual([fdef.name for fdef in qresult.fields], exp_fields) + if not isinstance(qresult.data, list): + raise qa_error.Error("Query did not return a list") + + _DoTests([ + # Specify fields in query + ("/2/query/%s?fields=%s" % (what, ",".join(all_fields)), + compat.partial(_Check, all_fields), "GET", None), + + ("/2/query/%s?fields=name" % what, + compat.partial(_Check, ["name"]), "GET", None), + + # Note the spaces + ("/2/query/%s?fields=name,%%20name%%09,name%%20" % what, + compat.partial(_Check, ["name"] * 3), "GET", None), + + # PUT with fields in query + ("/2/query/%s?fields=name" % what, + compat.partial(_Check, ["name"]), "PUT", {}), + + # Fields in body + ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", { + "fields": all_fields, + }), + + ("/2/query/%s" % what, compat.partial(_Check, ["name"] * 4), "PUT", { + "fields": ["name"] * 4, + }), + ]) + + def _CheckFilter(): + _DoTests([ + # With filter + ("/2/query/%s" % what, compat.partial(_Check, all_fields), "PUT", { + "fields": all_fields, + "filter": [qlang.OP_TRUE, "name"], + }), + ]) + + if what == constants.QR_LOCK: + # Locks can't be filtered + try: + _CheckFilter() + except rapi.client.GanetiApiError, err: + AssertEqual(err.code, 500) + else: + raise qa_error.Error("Filtering locks didn't fail") + else: + _CheckFilter() + + if what == constants.QR_NODE: + # Test with filter + (nodes, ) = _DoTests([("/2/query/%s" % what, + compat.partial(_Check, ["name", "master"]), "PUT", { + "fields": ["name", "master"], + "filter": [qlang.OP_TRUE, "master"], + })]) + qresult = objects.QueryResponse.FromDict(nodes) + AssertEqual(qresult.data, [ + [[constants.RS_NORMAL, master_name], [constants.RS_NORMAL, True]], + ]) + + def TestInstance(instance): """Testing getting instance(s) info via remote API. @@ -301,11 +421,11 @@ def TestTags(kind, name, tags): def _VerifyTags(data): AssertEqual(sorted(tags), sorted(data)) - query = "&".join("tag=%s" % i for i in tags) + queryargs = "&".join("tag=%s" % i for i in tags) # Add tags (job_id, ) = _DoTests([ - ("%s?%s" % (uri, query), _VerifyReturnsJob, "PUT", None), + ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "PUT", None), ]) _WaitForRapiJob(job_id) @@ -316,7 +436,7 @@ def TestTags(kind, name, tags): # Remove tags (job_id, ) = _DoTests([ - ("%s?%s" % (uri, query), _VerifyReturnsJob, "DELETE", None), + ("%s?%s" % (uri, queryargs), _VerifyReturnsJob, "DELETE", None), ]) _WaitForRapiJob(job_id) -- GitLab