def test_xml_validation_with_xsd(self): """Tests for XML validation with XSD. If lxml is not installed, this tests would be skipped.""" def request_xsd(): url_path = stats_httpd.XSD_URL_PATH url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() xsd_doc = self.client.getresponse() xsd_doc = lxml_etree.parse(xsd_doc) return lxml_etree.XMLSchema(xsd_doc) def request_xmldoc(path=''): url_path = '%s/%s' % (stats_httpd.XML_URL_PATH, path) url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() xml_doc = self.client.getresponse() return lxml_etree.parse(xml_doc) # request XSD and XML xsd = request_xsd() xml_doc = request_xmldoc() # do validation self.assertTrue(xsd.validate(xml_doc)) # validate each paths in DUMMY_DATA for path in stats_httpd.item_name_list(DUMMY_DATA, ''): # request XML xml_doc = request_xmldoc(path) # do validation self.assertTrue(xsd.validate(xml_doc))
def check_XML_URL_PATH(path=''): url_path = '%s/%s' % (stats_httpd.XML_URL_PATH, path) url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.getheader("Content-type"), "text/xml") self.assertGreater(int(response.getheader("Content-Length")), 0) self.assertEqual(response.status, 200) xml_doctype = response.readline().decode() xsl_doctype = response.readline().decode() self.assertGreater(len(xml_doctype), 0) self.assertGreater(len(xsl_doctype), 0) root = xml.etree.ElementTree.parse(response).getroot() self.assertGreater(root.tag.find('statistics'), 0) schema_loc = '{%s}schemaLocation' % XMLNS_XSI # check the path of XSD self.assertEqual(root.attrib[schema_loc], stats_httpd.XSD_NAMESPACE + ' ' + stats_httpd.XSD_URL_PATH) # check the path of XSL self.assertTrue(xsl_doctype.startswith( '<?xml-stylesheet type="text/xsl" href="' + stats_httpd.XSL_URL_PATH + '"?>')) # check whether the list of 'identifier' attributes in # root is same as the list of item names in DUMMY_DATA id_list = [ elm.attrib['identifier'] for elm in root ] item_list = [ it for it in \ stats_httpd.item_name_list(DUMMY_DATA, path) \ if len(it.split('/')) > 1 ] self.assertEqual(id_list, item_list) for elem in root: attr = elem.attrib value = isc.cc.data.find(DUMMY_DATA, attr['identifier']) # No 'value' attribute should be found in the 'item' # element when datatype of the value is list or dict. if type(value) is list or type(value) is dict: self.assertFalse('value' in attr) # The value of the 'value' attribute should be checked # after casting it to string type if datatype of the # value is int or float. Because attr['value'] returns # string type even if its value is int or float. elif type(value) is int or type(value) is float: self.assertEqual(attr['value'], str(value)) else: self.assertEqual(attr['value'], value)
def test_xml_handler(self): self.stats_httpd = MyStatsHttpd(get_availaddr()) module_name = 'Dummy' stats_spec = \ { module_name : [{ "item_name": "foo", "item_type": "string", "item_optional": False, "item_default": "bar", "item_description": "foo is bar", "item_title": "Foo" }, { "item_name": "foo2", "item_type": "list", "item_optional": False, "item_default": [ { "zonename" : "test1", "queries.udp" : 1, "queries.tcp" : 2 }, { "zonename" : "test2", "queries.udp" : 3, "queries.tcp" : 4 } ], "item_title": "Foo bar", "item_description": "Foo bar", "list_item_spec": { "item_name": "foo2-1", "item_type": "map", "item_optional": False, "item_default": {}, "map_item_spec": [ { "item_name": "foo2-1-1", "item_type": "string", "item_optional": False, "item_default": "", "item_title": "Foo2 1 1", "item_description": "Foo bar" }, { "item_name": "foo2-1-2", "item_type": "integer", "item_optional": False, "item_default": 0, "item_title": "Foo2 1 2", "item_description": "Foo bar" }, { "item_name": "foo2-1-3", "item_type": "integer", "item_optional": False, "item_default": 0, "item_title": "Foo2 1 3", "item_description": "Foo bar" } ] } }] } stats_data = \ { module_name : { 'foo':'bar', 'foo2': [ { "foo2-1-1" : "bar1", "foo2-1-2" : 10, "foo2-1-3" : 9 }, { "foo2-1-1" : "bar2", "foo2-1-2" : 8, "foo2-1-3" : 7 } ] } } self.stats_httpd.get_stats_spec = lambda x,y: stats_spec self.stats_httpd.get_stats_data = lambda x,y: stats_data xml_string = self.stats_httpd.xml_handler() stats_xml = xml.etree.ElementTree.fromstring(xml_string) schema_loc = '{%s}schemaLocation' % XMLNS_XSI self.assertEqual(stats_xml.attrib[schema_loc], stats_httpd.XML_ROOT_ATTRIB['xsi:schemaLocation']) stats_data = stats_data[module_name] stats_spec = stats_spec[module_name] names = stats_httpd.item_name_list(stats_data, '') for i in range(0, len(names)): self.assertEqual('%s/%s' % (module_name, names[i]), stats_xml[i].attrib['identifier']) value = isc.cc.data.find(stats_data, names[i]) if type(value) is int: value = str(value) if type(value) is dict or type(value) is list: self.assertFalse('value' in stats_xml[i].attrib) else: self.assertEqual(value, stats_xml[i].attrib['value']) self.assertEqual(module_name, stats_xml[i].attrib['owner']) self.assertEqual(urllib.parse.quote('%s/%s/%s' % (stats_httpd.XML_URL_PATH, module_name, names[i])), stats_xml[i].attrib['uri']) spec = isc.config.find_spec_part(stats_spec, names[i]) self.assertEqual(spec['item_name'], stats_xml[i].attrib['name']) self.assertEqual(spec['item_type'], stats_xml[i].attrib['type']) self.assertEqual(spec['item_description'], stats_xml[i].attrib['description']) self.assertEqual(spec['item_title'], stats_xml[i].attrib['title']) self.assertEqual(str(spec['item_optional']).lower(), stats_xml[i].attrib['optional']) default = spec['item_default'] if type(default) is int: default = str(default) if type(default) is dict or type(default) is list: self.assertFalse('default' in stats_xml[i].attrib) else: self.assertEqual(default, stats_xml[i].attrib['default']) self.assertFalse('item_format' in spec) self.assertFalse('format' in stats_xml[i].attrib)
def test_do_GET(self): self.assertTrue(type(self.stats_httpd.httpd) is list) self.assertEqual(len(self.stats_httpd.httpd), 1) self.assertEqual((self.address, self.port), self.stats_httpd.http_addrs[0]) def check_XML_URL_PATH(path=''): url_path = '%s/%s' % (stats_httpd.XML_URL_PATH, path) url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.getheader("Content-type"), "text/xml") self.assertGreater(int(response.getheader("Content-Length")), 0) self.assertEqual(response.status, 200) xml_doctype = response.readline().decode() xsl_doctype = response.readline().decode() self.assertGreater(len(xml_doctype), 0) self.assertGreater(len(xsl_doctype), 0) root = xml.etree.ElementTree.parse(response).getroot() self.assertGreater(root.tag.find('statistics'), 0) schema_loc = '{%s}schemaLocation' % XMLNS_XSI # check the path of XSD self.assertEqual(root.attrib[schema_loc], stats_httpd.XSD_NAMESPACE + ' ' + stats_httpd.XSD_URL_PATH) # check the path of XSL self.assertTrue(xsl_doctype.startswith( '<?xml-stylesheet type="text/xsl" href="' + stats_httpd.XSL_URL_PATH + '"?>')) # check whether the list of 'identifier' attributes in # root is same as the list of item names in DUMMY_DATA id_list = [ elm.attrib['identifier'] for elm in root ] item_list = [ it for it in \ stats_httpd.item_name_list(DUMMY_DATA, path) \ if len(it.split('/')) > 1 ] self.assertEqual(id_list, item_list) for elem in root: attr = elem.attrib value = isc.cc.data.find(DUMMY_DATA, attr['identifier']) # No 'value' attribute should be found in the 'item' # element when datatype of the value is list or dict. if type(value) is list or type(value) is dict: self.assertFalse('value' in attr) # The value of the 'value' attribute should be checked # after casting it to string type if datatype of the # value is int or float. Because attr['value'] returns # string type even if its value is int or float. elif type(value) is int or type(value) is float: self.assertEqual(attr['value'], str(value)) else: self.assertEqual(attr['value'], value) # URL is '/bind10/statistics/xml' check_XML_URL_PATH() for path in stats_httpd.item_name_list(DUMMY_DATA, ''): check_XML_URL_PATH(path) def check_XSD_URL_PATH(): url_path = stats_httpd.XSD_URL_PATH url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.getheader("Content-type"), "text/xml") self.assertGreater(int(response.getheader("Content-Length")), 0) self.assertEqual(response.status, 200) root = xml.etree.ElementTree.parse(response).getroot() url_xmlschema = '{%s}' % XMLNS_XSD self.assertGreater(root.tag.find('schema'), 0) self.assertTrue(hasattr(root, 'attrib')) self.assertTrue('targetNamespace' in root.attrib) self.assertEqual(root.attrib['targetNamespace'], stats_httpd.XSD_NAMESPACE) # URL is '/bind10/statistics/xsd' check_XSD_URL_PATH() def check_XSL_URL_PATH(): url_path = stats_httpd.XSL_URL_PATH url_path = urllib.parse.quote(url_path) self.client.putrequest('GET', url_path) self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.getheader("Content-type"), "text/xml") self.assertGreater(int(response.getheader("Content-Length")), 0) self.assertEqual(response.status, 200) root = xml.etree.ElementTree.parse(response).getroot() url_trans = '{%s}' % XMLNS_XSL url_xhtml = '{%s}' % XMLNS_XHTML self.assertEqual(root.tag, url_trans + 'stylesheet') # URL is '/bind10/statistics/xsl' check_XSL_URL_PATH() # 302 redirect self.client._http_vsn_str = 'HTTP/1.1' self.client.putrequest('GET', '/') self.client.putheader('Host', self.address) self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 302) self.assertEqual(response.getheader('Location'), "http://%s:%d%s/" % (self.address, self.port, stats_httpd.XML_URL_PATH)) # 404 NotFound (random path) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', '/path/to/foo/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', '/bind10/foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', '/bind10/statistics/foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + 'Auth') # with no slash self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) # 200 ok self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 200) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/#foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 200) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/?foo=bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 200) # 404 NotFound (too long path) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/Init/boot_time/a') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) # 404 NotFound (nonexistent module name) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/Foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSD_URL_PATH + '/Foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSL_URL_PATH + '/Foo') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) # 404 NotFound (nonexistent item name) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/Foo/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSD_URL_PATH + '/Foo/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSL_URL_PATH + '/Foo/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) # 404 NotFound (existent module but nonexistent item name) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XML_URL_PATH + '/Auth/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSD_URL_PATH + '/Auth/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404) self.client._http_vsn_str = 'HTTP/1.0' self.client.putrequest('GET', stats_httpd.XSL_URL_PATH + '/Auth/bar') self.client.endheaders() response = self.client.getresponse() self.assertEqual(response.status, 404)
def test_item_name_list(self): # for a one-element list self.assertEqual(['a'], stats_httpd.item_name_list({'a':1}, 'a')) # for a dict under a dict self.assertEqual(['a','a/b'], stats_httpd.item_name_list({'a':{'b':1}}, 'a')) self.assertEqual(['a/b'], stats_httpd.item_name_list({'a':{'b':1}}, 'a/b')) self.assertEqual(['a','a/b','a/b/c'], stats_httpd.item_name_list({'a':{'b':{'c':1}}}, 'a')) self.assertEqual(['a/b','a/b/c'], stats_httpd.item_name_list({'a':{'b':{'c':1}}}, 'a/b')) self.assertEqual(['a/b/c'], stats_httpd.item_name_list({'a':{'b':{'c':1}}}, 'a/b/c')) # for a list under a dict self.assertEqual(['a[2]'], stats_httpd.item_name_list({'a':[1,2,3]}, 'a[2]')) self.assertEqual(['a', 'a[0]', 'a[1]', 'a[2]'], stats_httpd.item_name_list({'a':[1,2,3]}, 'a')) self.assertEqual(['a', 'a[0]', 'a[1]', 'a[2]'], stats_httpd.item_name_list({'a':[1,2,3]}, '')) # for a list under a dict under a dict self.assertEqual(['a', 'a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'], stats_httpd.item_name_list({'a':{'b':[1,2,3]}}, 'a')) self.assertEqual(['a', 'a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'], stats_httpd.item_name_list({'a':{'b':[1,2,3]}}, '')) self.assertEqual(['a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'], stats_httpd.item_name_list({'a':{'b':[1,2,3]}}, 'a/b')) # for a mixed case of the above self.assertEqual(['a', 'a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]', 'a/c'], stats_httpd.item_name_list( {'a':{'b':[1,2,3], 'c':1}}, 'a')) self.assertEqual(['a/b', 'a/b[0]', 'a/b[1]', 'a/b[2]'], stats_httpd.item_name_list( {'a':{'b':[1,2,3], 'c':1}}, 'a/b')) self.assertEqual(['a/c'], stats_httpd.item_name_list( {'a':{'b':[1,2,3], 'c':1}}, 'a/c')) # for specifying a wrong identifier which is not found in # element self.assertRaises(isc.cc.data.DataNotFoundError, stats_httpd.item_name_list, {'x':1}, 'a') # for specifying a string in element and an empty string in # identifier self.assertEqual([], stats_httpd.item_name_list('a', '')) # for specifying empty strings in element and identifier self.assertEqual([], stats_httpd.item_name_list('', '')) # for specifying wrong element, which is an non-empty string, # and an non-empty string in identifier self.assertRaises(isc.cc.data.DataTypeError, stats_httpd.item_name_list, 'a', 'a') # for specifying None in element and identifier self.assertRaises(isc.cc.data.DataTypeError, stats_httpd.item_name_list, None, None) # for specifying non-dict in element self.assertRaises(isc.cc.data.DataTypeError, stats_httpd.item_name_list, [1,2,3], 'a') self.assertRaises(isc.cc.data.DataTypeError, stats_httpd.item_name_list, [1,2,3], '') # for checking key names sorted which consist of element num = 11 keys = [ 'a', 'aa', 'b' ] keys.sort(reverse=True) dictlist = dict([ (k, list(range(num))) for k in keys ]) keys.sort() ans = [] for k in keys: ans += [k] + [ '%s[%d]' % (k, i) for i in range(num) ] self.assertEqual(ans, stats_httpd.item_name_list(dictlist, ''))