diff --git a/test/disabled_test_subscribediff.py b/test/disabled_test_subscribediff.py index bf3cb46..3d946b4 100755 --- a/test/disabled_test_subscribediff.py +++ b/test/disabled_test_subscribediff.py @@ -1,201 +1,201 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # """This test will 1) SUBSCRIBE to xcap-diff event 2) read NOTIFY if any 3) delete the document, just in case 3) put a new document, remember ETag 4) read NOTIFY with that document url and new_etag=ETag 5) update the document, remember ETag 6) read NOTIFY with that document url, new_etag=ETag, old_etag=previous ETag 7) delete the document 8) read NOTIFY with that document url, old_etag=ETag, new_etag=Empty """ import re import time from queue import Queue, Empty from optparse import OptionValueError -from .common import * +from common import * from pypjua import * from xcap.xcapdiff import xml_document, xml_xcapdiff expires=20 event='xcap-diff' content_type='application/xcap-diff+xml' resource = 'resource-lists' body = """ Bill Doe Close Friends Joe Smith Nancy Gross Marketing """ def get_xcapdiff(xcap_root, resource, username, old_etag, new_etag): uri = xcap_root + '/' + resource + '/users/' + username + '/index.xml' return xml_xcapdiff(xcap_root, xml_document(uri, old_etag, new_etag)) queue = Queue() packet_count = 0 start_time = None is_subscribed = False def event_handler(event_name, **kwargs): global start_time, packet_count, is_subscribed if event_name == "Subscription_state": if kwargs["state"] == "ACTIVE": is_subscribed = True #elif kwargs["state"] == "TERMINATED": # if kwargs.has_key("code"): # print "Unsubscribed: %(code)d %(reason)s" % kwargs # else: # print "Unsubscribed" elif event_name == "Subscription_notify": queue.put(("NOTIFY", kwargs)) elif event_name == "siptrace": if start_time is None: start_time = kwargs["timestamp"] packet_count += 1 if kwargs["received"]: direction = "RECEIVED" else: direction = "SENDING" print("%s: Packet %d, +%s" % (direction, packet_count, (kwargs["timestamp"] - start_time))) print("%(timestamp)s: %(source_ip)s:%(source_port)d --> %(destination_ip)s:%(destination_port)d" % kwargs) print(kwargs["data"]) elif event_name=='log': pass else: print('UNHANDLED EVENT', event_name, kwargs) def get(queue, blocking=True, timeout=1): try: return queue.get(blocking, timeout) except Empty: return None class Test(XCAPTest): def assertContains(self, element, list): if element not in list: raise self.failureException("%s not in %s" % (element, list)) @classmethod def setupOptionParser(_cls, parser): parser.add_option("-p", "--outbound-proxy", type="string", action="callback", callback=parse_proxy_cb, help="Outbound SIP proxy to use. By default a lookup is performed based on SRV and A records.", metavar="IP[:PORT]") parser.add_option("-t", "--siptrace", default=False, action='store_true') setup_parser_client(parser) def test(self): opts = self.options self.delete(resource, status=[200,404]) initial_events = Engine.init_options_defaults["initial_events"] if content_type is not None: initial_events[event] = [content_type] e = Engine(event_handler, do_siptrace=opts.siptrace, auto_sound=False, initial_events=initial_events) e.start() try: if opts.outbound_proxy is None: route = None else: route = Route(opts.proxy_ip, opts.proxy_port) sub = Subscription(Credentials(SIPURI(user=opts.username, host=opts.domain), opts.password), SIPURI(user=opts.username, host=opts.domain), event, route=route, expires=expires) sub.subscribe() try: # wait for SUBSCRIBE to succeed AND absorb out-of-date NOTIFYs end = time.time() + 1.5 while time.time() < end: get(queue, timeout=0.1) self.assertTrue(is_subscribed, 'SUBSCRIBE failed') # try: # X = queue.get(True, timeout = 1) # except Empty: # pass # else: # self.assertEqual(X[0], 'NOTIFY') def get_notify(comment = ''): try: X = queue.get(True, timeout = 1) except Empty: self.fail("Didn't get a NOTIFY %s" % comment) self.assertEqual(X[0], 'NOTIFY') return X[1] r = self.put(resource, body) etag = r.headers['ETag'].strip('"') X = get_notify('after put') xcap_root = opts.xcap_root.replace(':8000', '') self.assertEqual(X['body'], get_xcapdiff(xcap_root, resource, opts.username, None, etag)) #print etag r = self.put(resource, body.replace('Close', 'Intimate')) new_etag = r.headers['ETag'].strip('"') X = get_notify() self.assertEqual(X['body'], get_xcapdiff(xcap_root, resource, opts.username, etag, new_etag)) #print etag, new_etag r = self.delete(resource) X = get_notify() self.assertEqual(X['body'], get_xcapdiff(xcap_root, resource, opts.username, new_etag, None)) #print new_etag, None finally: sub.unsubscribe() time.sleep(2) finally: e.stop() re_ip_port = re.compile("^(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(:(?P\d+))?$") def parse_proxy(value, parser): match = re_ip_port.match(value) if match is None: raise OptionValueError("Could not parse supplied outbound proxy address") parser.values.proxy_ip = match.group('proxy_ip') parser.values.proxy_port = int(match.group('proxy_port') or '5060') def parse_proxy_cb(_option, _opt_str, value, parser): return parse_proxy(value, parser) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test.py b/test/test.py index c636511..975a3f7 100755 --- a/test/test.py +++ b/test/test.py @@ -1,64 +1,64 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # import sys import os import traceback -from . import common as c +import common as c class TestHarness(object): """A test harness for OpenXCAP.""" def __init__(self, tests, option_parser): """Constructor to populate the TestHarness instance. tests should be a list of module names (strings). """ self.tests = tests self.option_parser = option_parser self.test_suites = [] self.import_errors = 0 for testmod in self.tests: try: self.import_errors += 1 m = __import__(testmod, globals(), locals()) suite = c.loadSuiteFromModule(m, option_parser) suite.modname = testmod self.test_suites.append(suite) self.import_errors -= 1 except Exception: traceback.print_exc() def run(self, options, args): c.run_suite(c.TestSuite(self.test_suites), options, args) def all_tests(): my_dir = os.path.dirname(os.path.abspath(__file__)) lst = [x.strip('.py') for x in os.listdir(my_dir) if x.startswith('test_') and x.endswith('.py')] return lst def run(): parser = c.prepare_optparser() parser.add_option("-l", "--list", action="store_true", help="Print list of all tests") t = TestHarness(all_tests(), parser) options, args = parser.parse_args() if options.list: for x in t.test_suites: print(x.modname) for i in x: print(' - ', i) print() return c.process_options(options) c.run_command(lambda : t.run(options, args), options) if t.import_errors: sys.exit('there were import errors!\n') if __name__ == '__main__': run() diff --git a/test/test_attribute.py b/test/test_attribute.py index 86b8773..2ae32d8 100755 --- a/test/test_attribute.py +++ b/test/test_attribute.py @@ -1,69 +1,69 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * resource_list_xml = """ Joe Smith Nancy Gross Petri Aukia """ class AttributeTest(XCAPTest): def test_get(self): self.put('resource-lists', resource_list_xml) self.get('resource-lists', '/resource-lists/list[@name="other"]/@some-attribute', status=404) r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/@name') self.assertBody(r, "friends") self.assertHeader(r, 'ETag') self.assertHeader(r, 'Content-type', 'application/xcap-att+xml') r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/external/@anchor') uri = 'http://xcap.example.org/resource-lists/users/sip:a@example.org/index/~~/resource-lists/list%5b@name=%22mkting%22%5d' self.assertBody(r, uri) print('WARNING: test with URI in att_value is disabled') # r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/external[@anchor="%s"]/@anchor' % uri) # self.assertBody(r, uri) r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/external[]/@anchor', status=400) def test_delete(self): self.put('resource-lists', resource_list_xml) self.delete('resource-lists', '/resource-lists/list[@name="other"]/@some-attribute', status=404) # XXX is it legal for parent selector (/resource-lists/list[@name="friends"]) to become invalid? # I don't think it is, check with RFC self.delete('resource-lists', '/resource-lists/list[@name="friends"]/@name', status=200) self.delete('resource-lists', '/resource-lists/list[@name="friends"]/@name', status=404) def test_put(self): self.put('resource-lists', resource_list_xml) self.put('resource-lists', 'coworkers', '/resource-lists/list[@name="friends"]/@some-attribute', status=409) # fails GET(PUT(x))==x test. must be rejected in the server #self.put('resource-lists', 'coworkers', '/resource-lists/list[@name="friends"]/@name', status=409) # XXX parent's selector becomes invalid r = self.client._put('resource-lists', 'coworkers', '/resource-lists/list[@name="friends"]/@name') self.assertStatus(r, 200) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_auth.py b/test/test_auth.py index 2ede9d2..b9bf154 100755 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -1,44 +1,44 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * class AuthTest(XCAPTest): def test_users_auth(self): self.get(self.app, status=[200,404]) self.options.password += 'x' self.update_client_options() self.get(self.app, status=[401]) def test_global_auth(self): self.get_global(self.app, status=[200,404]) #self.options.password += 'x' #self.update_client_options() #for app in apps: # self.get_global(app, status=401) # XXX test PUT/DELETE auth as well? # XXX test digest authentication # XXX test authorization #def test_authorization(self): ### the request cannot be authorized (we're trying to access someone else' resource) #account = self.account #self.account = "dummy" + self.account #r = self.get('resource-lists', status=401) #self.client.account = account for app in apps: exec("""class AuthTest_%s(AuthTest): app = %r """ % (app.replace('-', '_').replace('.', '_'), app)) del AuthTest if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_element.py b/test/test_element.py index 5455de8..9b80881 100755 --- a/test/test_element.py +++ b/test/test_element.py @@ -1,112 +1,112 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * xml = """ Joe Smith Nancy Gross Petri Aukia """ def index(s, sub, skip=0, start=0): while skip >= 0: found = s.index(sub, start) skip -= 1 start = found + 1 return found def eindex(s, sub, skip=0): return index(s, sub, skip)+len(sub) lst = xml[xml.index('')] nancy = xml[xml.index(' Alice """ external = xml[xml.index('')] class ElementTest(XCAPTest): def test_get(self): self.delete('resource-lists', status=[200,404]) self.put('resource-lists', xml) self.get('resource-lists', '/resource-lists/list[@name="other"]', status=404) self.get('resource-lists', '/resource-lists/list/entry[4]', status=404) r = self.get('resource-lists', '/resource-lists/list[@name="friends"]') self.assertBody(r, lst) self.assertHeader(r, 'ETag') self.assertHeader(r, 'Content-type', 'application/xcap-el+xml') r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/entry[2]') self.assertBody(r, nancy) self.assertHeader(r, 'ETag') self.assertHeader(r, 'Content-type', 'application/xcap-el+xml') r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/*[2]') self.assertBody(r, nancy) self.assertHeader(r, 'ETag') self.assertHeader(r, 'Content-type', 'application/xcap-el+xml') print('WARNING: test with URI in att_value is disabled') # r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/external[@anchor="http://xcap.example.org/resource-lists/users/sip:a@example.org/index/~~/resource-lists/list%5b@name="mkting"5d"]') # self.assertBody(r, external) # self.assertHeader(r, 'ETag') # self.assertHeader(r, 'Content-type', 'application/xcap-el+xml') def test_delete(self): self.put('resource-lists', xml) # cannot delete something in the middle self.delete('resource-lists', '/resource-lists/list[@name="friends"]/entry[2]', status=409) self.delete('resource-lists', '/resource-lists/list[@name="friends"]/*[3]', status=409) # it's ok to delete the last one though r = self.delete('resource-lists', '/resource-lists/list[@name="friends"]/*[4]') self.assertHeader(r, 'ETag') r = self.delete('resource-lists', '/resource-lists/list[@name="friends"]/*[3]') self.assertHeader(r, 'ETag') r = self.delete('resource-lists', '/resource-lists/list[@name="friends"]/*[2]') self.assertHeader(r, 'ETag') r = self.delete('resource-lists', '/resource-lists/list[@name="friends"]/entry') self.assertHeader(r, 'ETag') r = self.get('resource-lists', '/resource-lists/list') self.assertMatchesBody(r, '^\\s*$') self.delete('resource-lists', '/resource-lists/list[@name="friends"]/entry[@uri="sip:joe@example.com"]', status=404) def test_put_error(self): self.put('resource-lists', xml) # 415 content type not set self.put('resource-lists', nancy, '/resource-lists/list[@name="friends"]', headers={'Content-Type' : None},status=415) # 409 r = self.put('resource-lists', broken, '/resource-lists/list[@name="friends"]', status=409) # 409 r = self.put('resource-lists', nancy, '/resource-lists/list[@name="others"]/entry[2]', status=409) # 409 r = self.put('resource-lists', nancy, '/resource-lists/list[@name="friends"]/entry[1]', status=409) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_element_put.py b/test/test_element_put.py index f64ccd3..8efae4e 100755 --- a/test/test_element_put.py +++ b/test/test_element_put.py @@ -1,177 +1,177 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * app = 'test-app' start = ''' ''' # when changing to the document could be put, but # element GET respons with 404. # either GET should return what expected or a document without namespaces declaration # should be rejected class PutElementTest(XCAPTest): def reverse(self, node_selector): self.delete(app, node_selector) self.assertDocument(app, start) def test_creation(self): """Testing different ways of inserting an element as described in examples from Section 8.2.3 (http://tools.ietf.org/html/rfc4825#section-8.2.3) After each PUT, DELETE is executed on the same URI and the resulting document must be the same as before the insertion. """ self.put(app, start) for node_selector in ['/root/el1[@att="third"]', '/root/el1[3][@att="third"]', '/root/*[3][@att="third"]']: self.put_new(app, '', node_selector) self.assertDocument(app, ''' ''') self.reverse(node_selector) # out-of-bound positional index in node selector results in 409 (XXX or 404?) for node_selector in ['root/el1[4][@att="third"]', 'root/*[0][@att="third"]']: self.put_new(app, '', node_selector, status=409) self.assertDocument(app, start) # replace 500 with something more appropriate #for node_selector in ['root/*[-1][@att="third"]']: # self.put_new(app, '', node_selector, status=500) # self.assertDocument(app, start) # following request would fail idempotency requirement (GET(PUT(x))=>x) if succeeded for node_selector in ['root/el1[@att="third"]', 'root/el1[3][@att="third"]', 'root/*[3][@att="third"]']: r = self.put_new(app, '', node_selector, status=409) self.assertInBody(r, 'cannot-insert') self.assertDocument(app, start) self.put_new(app, '', 'root/el3') self.assertDocument(app, ''' ''') self.reverse('root/el3') for node_selector in ['root/el2[@att="2"]', 'root/el2[2][@att="2"]']: self.put_new(app, '', node_selector) self.assertDocument(app, ''' ''') self.reverse(node_selector) self.put_new(app, '', 'root/*[2][@att="2"]') self.assertDocument(app, ''' ''') self.reverse('root/*[2][@att="2"]') self.put_new(app, '', 'root/el2[1][@att="2"]') self.assertDocument(app, ''' ''') self.reverse('root/el2[1][@att="2"]') def test_creation_starattr(self): """Testing PUT requests of form '*[@att="some"]' which require looking into body of PUT""" self.put(app, start) for selector in ['root/*[@att="2"]', 'root/el1[@att="2"]']: self.put_new(app, '', selector) self.assertDocument(app, ''' ''') self.reverse(selector) # the same request - different body for selector in ['root/*[@att="2"]', 'root/el2[@att="2"]']: self.put_new(app, '', selector) self.assertDocument(app, ''' ''') self.reverse(selector) # the same request - different body for selector in ['root/*[@att="2"]', 'root/el3[@att="2"]']: self.put_new(app, '', selector) self.assertDocument(app, ''' ''') self.reverse(selector) def test_replacement(self): self.put(app, start) for node_selector in ['root/el1[@att="first"]', 'root/el1[1][@att="first"]', 'root/*[1][@att="first"]']: self.put(app, '', node_selector, status=409) self.assertDocument(app, start) for node_selector in ['root/el1[1]', 'root/*[1]']: self.put(app, start) self.put(app, '', node_selector, status=200) self.assertDocument(app, ''' ''') if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_errors.py b/test/test_errors.py index 0f9bfac..3816a69 100755 --- a/test/test_errors.py +++ b/test/test_errors.py @@ -1,73 +1,73 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from . import common as c +import common as c from urllib.parse import urlparse class ErrorsTest(c.XCAPTest): def communicate(self, data): s = c.socket.socket() x = urlparse(self.options.xcap_root) if x.port is None: port = {'http': 80, 'https': 443}.get(x.scheme) s.connect((x.hostname, x.port or port)) if x.scheme == 'https': s = c.socket.ssl(s) s.write(data) return s.read(1024*8) s.send(data) return s.recv(1024*8) def test_gibberish(self): response = self.communicate('\r\r\r\n\r\n') assert '400 Bad Request' in response, repr(response) def test409(self): self.put('resource-lists', 'xxx', status=409) def check(self, code, message, *uris): for uri in uris: r = self.client.con.request('GET', uri) self.assertEqual(r.status, code) self.assertInBody(r, message) def test400_1(self): self.get('resource-lists', '/resource-lists/list[@name="friends"]/external[]/@anchor', status=400) def test400_2(self): self.check(400, "to parse node", 'resource-lists/users/alice@example.com/index.xml~~') def test404(self): self.check(404, 'XCAP Root', '') self.check(404, 'context', 'xxx') self.check(404, "context", 'resource-lists/user/alice@example.com/index.xml') self.check(404, 'user id', 'resource-lists/users') self.check(404, "not contain ", 'resource-lists/users/alice@example.com', 'resource-lists/users/alice@example.com/') # XXX test for multiple matches def test405(self): r = self.client.con.request('POST', '') self.assertEqual(r.status, 405) r = self.client.con.request('XXX', '') self.assertEqual(r.status, 405) # but apache responds with 501 # 412: tested in test_etags.py if __name__ == '__main__': c.runSuiteFromModule() diff --git a/test/test_etags.py b/test/test_etags.py index d0bf860..ce5c9ea 100755 --- a/test/test_etags.py +++ b/test/test_etags.py @@ -1,113 +1,113 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * resource_list_xml = """ """ class ETagTest(XCAPTest): def test_conditional_GET(self): r = self.put('resource-lists', resource_list_xml) etag = self.assertHeader(r, 'ETag') # Test If-Match (both valid and invalid) self.get('resource-lists', headers={'If-Match': etag}) self.get('resource-lists', headers={'If-Match': '*'}) self.get('resource-lists', headers={'if-Match': "another-etag"}, status=412) # Test If-None-Match (both valid and invalid) self.get('resource-lists', headers={'If-None-Match': etag}, status=304) self.get('resource-lists', headers={'If-None-Match': '*'}, status=304) self.get('resource-lists', headers={'If-None-Match': "another-etag"}, status=200) def test_conditional_PUT(self): self.delete('resource-lists', status=[200,404]) self.get('resource-lists', status=404) # Test conditional PUT when document doesn't exist self.put('resource-lists', resource_list_xml, headers={'If-Match': '12345asdf'}, status=412) r = self.put('resource-lists', resource_list_xml) etag = self.assertHeader(r, 'ETag') # Test conditional PUT logic ## Alice and Bob initially share the same etag alice_etag = bob_etag = etag ## Bob modifies the resource r = self.put('resource-lists', resource_list_xml, headers={'If-Match': bob_etag}) bob_etag = self.assertHeader(r, 'ETag') ## now Alice tries to modify the resource self.put('resource-lists', resource_list_xml, headers={'If-Match': alice_etag}, status=412) ## the etag has changed so now she updates her in-memory document r = self.get('resource-lists') new_alice_etag = self.assertHeader(r, 'ETag') self.assertEqual(bob_etag, new_alice_etag) self.put('resource-lists', resource_list_xml, headers={'If-Match': new_alice_etag}) def test_conditional_PUT_2(self): self.delete('resource-lists', status=[200,404]) self.get('resource-lists', status=404) self.put('resource-lists', resource_list_xml, headers={'If-None-Match': '*'}, status=201) self.put('resource-lists', resource_list_xml, headers={'If-None-Match': '*'}, status=412) class ETagTest2(XCAPTest): # the same as prev, but using 'etag' param def test_conditional_GET(self): r = self.put('resource-lists', resource_list_xml) etag = self.assertHeader(r, 'ETag') # Test If-Match (both valid and invalid) self.get('resource-lists', etag=etag) self.get('resource-lists') self.get('resource-lists', etag="another-etag", status=412) def test_conditional_PUT(self): r = self.put('resource-lists', resource_list_xml) etag = self.assertETag(r) assert etag is not None, repr(etag) # Test conditional PUT logic ## Alice and Bob initially share the same etag alice_etag = bob_etag = etag ## Bob modifies the resource r = self.put('resource-lists', resource_list_xml, etag=bob_etag) bob_etag = self.assertETag(r) ## now Alice tries to modify the resource self.put('resource-lists', resource_list_xml, etag=alice_etag, status=412) ## the etag has changed so now she updates her in-memory document r = self.get('resource-lists') new_alice_etag = self.assertETag(r) self.assertEqual(bob_etag, new_alice_etag) self.put('resource-lists', resource_list_xml, etag=new_alice_etag) def test_etag_parsing(self): r = self.put('resource-lists', resource_list_xml) etag = self.assertETag(r) # no quotes r = self.put('resource-lists', resource_list_xml, headers = {'if-match' : 'xxx' }, status=412) r = self.put('resource-lists', resource_list_xml, headers = {'if-match' : etag }, status=200) etag = self.assertETag(r) r = self.put('resource-lists', resource_list_xml, headers = {'if-match' : '"' + etag + '"' }, status=200) etag = self.assertETag(r) self.put('resource-lists', resource_list_xml, headers = {'if-match' : '"' + etag + 'xx"' }, status=412) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_etags2.py b/test/test_etags2.py index aea4c74..c4b3516 100755 --- a/test/test_etags2.py +++ b/test/test_etags2.py @@ -1,53 +1,53 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * resource_list_xml = """ """ class ETagTest(XCAPTest): def test_conditional_PUT(self): self.delete('resource-lists', status=[200,404]) self.get('resource-lists', status=404) # Test conditional PUT when document doesn't exist self.put('resource-lists', resource_list_xml, headers={'If-Match': '12345asdf'}, status=412) # r = self.put('resource-lists', resource_list_xml) # etag = self.assertHeader(r, 'ETag') # # # Test conditional PUT logic # ## Alice and Bob initially share the same etag # alice_etag = bob_etag = etag # # ## Bob modifies the resource # r = self.put('resource-lists', resource_list_xml, headers={'If-Match': bob_etag}) # bob_etag = self.assertHeader(r, 'ETag') # # ## now Alice tries to modify the resource # self.put('resource-lists', resource_list_xml, headers={'If-Match': alice_etag}, status=412) # # ## the etag has changed so now she updates her in-memory document # r = self.get('resource-lists') # new_alice_etag = self.assertHeader(r, 'ETag') # self.assertEqual(bob_etag, new_alice_etag) # # self.put('resource-lists', resource_list_xml, headers={'If-Match': new_alice_etag}) # def test_conditional_PUT_2(self): self.delete('resource-lists', status=[200,404]) self.get('resource-lists', status=404) self.put('resource-lists', resource_list_xml, headers={'If-None-Match': '*'}, status=201) self.put('resource-lists', resource_list_xml, headers={'If-None-Match': '*'}, status=412) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_fragment.py b/test/test_fragment.py index 72268fa..168e4c9 100755 --- a/test/test_fragment.py +++ b/test/test_fragment.py @@ -1,50 +1,50 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from . import common +import common document = """ Foo """ # well-formed fragment that would've been rejected by XML parser because of # unbound namespace prefix fragment = """ Test """ node = '/resource-lists/list/entry[@uri="sip:xxx@yyyyy.net"]' class FragmentTest(common.XCAPTest): def test_success(self): self.put('resource-lists', document) self.put('resource-lists', fragment, node) def test_errors(self): self.put('resource-lists', document) r = self.put('resource-lists', "", node, status=409) self.assertInBody(r, 'mismatched tag') r = self.put('resource-lists', "", node, status=409) self.assertInBody(r, 'not well-formed (invalid token)') r = self.put('resource-lists', "", node, status=409) self.assertInBody(r, 'not well-formed (invalid token)') r = self.put('resource-lists', "", node, status=409) self.assertInBody(r, 'junk after document element') r = self.put('resource-lists', "", node, status=409) self.assertInBody(r, 'not well-formed (invalid token)') if __name__ == '__main__': common.runSuiteFromModule() diff --git a/test/test_global.py b/test/test_global.py index d472c5f..81454fd 100755 --- a/test/test_global.py +++ b/test/test_global.py @@ -1,32 +1,32 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * has_global = ['xcap-caps'] no_global = set(apps) - set(has_global) class TestGlobal(XCAPTest): def test_no_global(self): for app in no_global: self.get(app, status=404, globaltree=True) # at the moment, no one authorized to do that # NOTE, even though 404 would be also a valid response here, 401 should take priority # 404 or 401? # self.put(app, xml, status=401, globaltree=True) # self.delete(app, status=401, globaltree=True) def test_has_global(self): for app in has_global: self.get(app, status=200, globaltree=True) # # at the moment, no one authorized to do that # #self.put(app, xml, status=401, globaltree=True) # self.delete(app, status=401, globaltree=True) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_nsbindings.py b/test/test_nsbindings.py index e5a26c8..88d3560 100755 --- a/test/test_nsbindings.py +++ b/test/test_nsbindings.py @@ -1,33 +1,33 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * resource_list_xml = """ Joe Smith Nancy Gross Petri Aukia """ class NSBindingsTest(XCAPTest): def test_ns_bindings(self): self.put('resource-lists', resource_list_xml) r = self.get('resource-lists', '/resource-lists/list[@name="friends"]/namespace::*') self.assertHeader(r, 'ETag') self.assertHeader(r, 'Content-type', 'application/xcap-ns+xml') # add expected content if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_pidf.py b/test/test_pidf.py index 13d97a3..9164a87 100755 --- a/test/test_pidf.py +++ b/test/test_pidf.py @@ -1,31 +1,31 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * pidf_xml = """ open """ class PIDFTest(XCAPTest): def test_pidf_manipulation(self): self.getputdelete('pidf-manipulation', pidf_xml, 'application/pidf+xml') if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_presrules.py b/test/test_presrules.py index 1f1040a..94afed8 100755 --- a/test/test_presrules.py +++ b/test/test_presrules.py @@ -1,42 +1,42 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * pres_rules_xml = """ allow """ class PresenceRulesTest(XCAPTest): def test_pidf_manipulation(self): self.getputdelete('pres-rules', pres_rules_xml, 'application/auth-policy+xml') if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_resourcelists.py b/test/test_resourcelists.py index 3f23856..28a231a 100755 --- a/test/test_resourcelists.py +++ b/test/test_resourcelists.py @@ -1,131 +1,131 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * resource_lists_xml = """ Bill Doe Close Friends Joe Smith Nancy Gross Marketing """ resource_lists_xml_badformed = """ Bill Doe Close Friends Joe Smith Nancy Gross Marketing """ # well-formed, but fails to meet constraints resource_lists_xml_non_unique_list = """ Bill Doe Close Friends Joe Smith Nancy Gross Marketing """ resource_lists_xml_baduri = """ Bill Doe Close Friends Joe Smith Nancy Gross Marketing """ class DocumentTest(XCAPTest): def test_operations1(self): self.getputdelete('resource-lists', resource_lists_xml, 'application/resource-lists+xml') def test_operations2(self): self.getputdelete('resource-lists', resource_lists_xml.replace('UTF-8', 'utf-8'), 'application/resource-lists+xml') def test_operations3(self): r = self.put_rejected('resource-lists', resource_lists_xml_badformed) self.assertInBody(r, ' if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_rlsservices.py b/test/test_rlsservices.py index b769df1..38fb480 100755 --- a/test/test_rlsservices.py +++ b/test/test_rlsservices.py @@ -1,124 +1,124 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * rls_services_xml = """ http://xcap.example.com/resource-lists/users/sip:joe@example.com/index/~~/resource-lists/list%5b@name=%22l1%22%5d presence presence """ rls_services_xml_badformed = """ http://xcap.example.com/resource-lists/users/sip:joe@example.com/index/~~/resource-lists/list%5b@name=%22l1%22%5d presence presence """ # resource-lists constraints should be checked as well rls_services_xml_non_unique_list = """ http://xcap.example.com/resource-lists/users/sip:joe@example.com/index/~~/resource-lists/list%5b@name=%22l1%22%5d presence presence """ # this one is actually caught by schema validation, not by code rls_services_xml_non_unique_service = """ http://xcap.example.com/resource-lists/users/sip:joe@example.com/index/~~/resource-lists/list%5b@name=%22l1%22%5d presence presence """ # check for that service uniqueness is enforced across different users # check index class DocumentTest(XCAPTest): def test_operations1(self): self.getputdelete('rls-services', rls_services_xml, 'application/rls-services+xml') def test_operations2(self): self.put_rejected('rls-services', rls_services_xml_badformed) def test_operations3(self): self.put_rejected('rls-services', rls_services_xml_non_unique_list) def test_operations4(self): self.put_rejected('rls-services', rls_services_xml_non_unique_service) #self.account = 'test2@example.com' #self.delete_resource('rls-services') #self.assertStatus([200, 404]) ## we aint doing that ## rejected because the other user has the services with the same name ##self.put_rejected('rls-services', rls_services_xml) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_watchers.py b/test/test_watchers.py index 8ca4dc5..8d81ee3 100755 --- a/test/test_watchers.py +++ b/test/test_watchers.py @@ -1,33 +1,33 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import XCAPTest, runSuiteFromModule +from common import XCAPTest, runSuiteFromModule watchers = """ """ class Test(XCAPTest): def test_get(self): self.get('org.openxcap.watchers') self.get('org.openxcap.watchers', '/watchers') self.get('org.openxcap.watchers', globaltree=True, status=404) self.get('org.openxcap.watchers', '/watchers', globaltree=True, status=404) # def test_put_not_allowed(self): # self.put('watchers', watchers, status=405) # self.put('watchers', watchers, '/watchers', status=405) # self.put('watchers', watchers, globaltree=True, status=405) # self.put('watchers', watchers, '/watchers', globaltree=True, status=405) # def test_delete_not_allowed(self): # self.delete('watchers', status=405) # self.delete('watchers', '/watchers', status=405) # self.delete('watchers', globaltree=True, status=405) # self.delete('watchers', '/watchers', globaltree=True, status=405) if __name__ == '__main__': runSuiteFromModule() diff --git a/test/test_xcap_caps.py b/test/test_xcap_caps.py index ced3c0d..5a2654d 100755 --- a/test/test_xcap_caps.py +++ b/test/test_xcap_caps.py @@ -1,24 +1,24 @@ #!/usr/bin/env python3 # Copyright (C) 2007-2025 AG-Projects. # -from .common import * +from common import * class XCAPCaps(XCAPTest): def test_schema(self): r = self.get_global('xcap-caps') validate_xcapcaps_schema(r.body) # TODO: auto check schema for every get schema = load_schema('xcap-caps.xsd') def validate_xcapcaps_schema(document): xml = validate(document, schema) assert xml.find('{urn:ietf:params:xml:ns:xcap-caps}auids') is not None assert xml.find('{urn:ietf:params:xml:ns:xcap-caps}extensions') is not None assert xml.find('{urn:ietf:params:xml:ns:xcap-caps}namespaces') is not None if __name__ == '__main__': runSuiteFromModule()