# HG changeset patch # User Sebastien Jodogne # Date 1602776041 -7200 # Node ID bf8369ea3ff15f52150176960861234830879d43 # Parent 66a36befb208e8dca433f2d5d8776fac84f54057 more tests of webdav diff -r 66a36befb208 -r bf8369ea3ff1 Plugins/WebDav/Run.py --- a/Plugins/WebDav/Run.py Wed Oct 14 19:55:26 2020 +0200 +++ b/Plugins/WebDav/Run.py Thu Oct 15 17:34:01 2020 +0200 @@ -158,6 +158,9 @@ self.assertEqual(0, patients[0].size) self.assertEqual('', patients[0].contenttype) + self.assertRaises(Exception, lambda: WEBDAV.delete('/webdav/nope')) + self.assertRaises(Exception, lambda: WEBDAV.delete('/webdav/by-uids')) + def test_upload(self): self.assertEqual(0, len(ListFiles('/webdav/uploads/', True))) @@ -221,6 +224,11 @@ self.assertTrue(('/webdav/by-uids/%s/%s/series.json' % (studyUid, seriesUid)) in content) self.assertTrue(('/webdav/by-uids/%s/%s/%s.dcm' % (studyUid, seriesUid, sopUid)) in content) + # Deleting the virtual files "study|series.json" has no + # effect, but is needed for recursive DELETE in some file explorers + WEBDAV.delete('/webdav/by-uids/%s/study.json' % studyUid) + WEBDAV.delete('/webdav/by-uids/%s/%s/series.json' % (studyUid, seriesUid)) + info = GetFileInfo('/webdav/by-uids/%s/study.json' % studyUid) self.assertEqual(info.contenttype, 'application/json') @@ -377,6 +385,31 @@ self.assertEqual(0, len(DoGet(ORTHANC, '/instances'))) self.assertEqual(0, len(ListFiles('/webdav/by-dates/', True))) + + def test_delete_folder(self): + # These deletes should have no effect + UploadInstance(ORTHANC, 'DummyCT.dcm') + self.assertEqual(1, len(DoGet(ORTHANC, '/instances'))) + WEBDAV.delete('/webdav/by-uids/1.2.840.113619.2.176.2025.1499492.7391.1171285944.390/study.json') + WEBDAV.delete('/webdav/by-uids/1.2.840.113619.2.176.2025.1499492.7391.1171285944.390/1.2.840.113619.2.176.2025.1499492.7391.1171285944.394/series.json') + WEBDAV.delete('/webdav/by-dates/2007/2007-02') + WEBDAV.delete('/webdav/by-dates/2006') + self.assertEqual(1, len(DoGet(ORTHANC, '/instances'))) + + for path in [ + '/webdav/by-uids/1.2.840.113619.2.176.2025.1499492.7391.1171285944.390/1.2.840.113619.2.176.2025.1499492.7391.1171285944.394/1.2.840.113619.2.176.2025.1499492.7040.1171286242.109.dcm', + '/webdav/by-patients/ozp00SjY2xG - KNIX/20070101 - Knee (R)/MR - AX. FSE PD/66a662ce-7430e543-bad44d47-0dc5a943-ec7a538d.dcm', + '/webdav/by-studies/ozp00SjY2xG - KNIX - Knee (R)/MR - AX. FSE PD/66a662ce-7430e543-bad44d47-0dc5a943-ec7a538d.dcm', + '/webdav/by-dates/2007/2007-01/ozp00SjY2xG - KNIX - Knee (R)/MR - AX. FSE PD/66a662ce-7430e543-bad44d47-0dc5a943-ec7a538d.dcm', + ]: + tokens = path.split('/') + for i in range(4, len(tokens) + 1): + p = '/'.join(tokens[0:i]) + UploadInstance(ORTHANC, 'DummyCT.dcm') + self.assertEqual(1, len(DoGet(ORTHANC, '/instances'))) + WEBDAV.delete(p) + self.assertEqual(0, len(DoGet(ORTHANC, '/instances'))) + try: print('\nStarting the tests...') diff -r 66a36befb208 -r bf8369ea3ff1 Tests/Run.py --- a/Tests/Run.py Wed Oct 14 19:55:26 2020 +0200 +++ b/Tests/Run.py Thu Oct 15 17:34:01 2020 +0200 @@ -59,6 +59,9 @@ action = 'store_true') parser.add_argument('--docker', help = 'These tests are run from Docker', action = 'store_true') +parser.add_argument('--orthanc', + default = 'Orthanc', + help = 'Path to the executable of Orthanc') parser.add_argument('options', metavar = 'N', nargs = '*', help='Arguments to Python unittest') @@ -83,7 +86,7 @@ ## CONFIG = '/tmp/IntegrationTestsConfiguration.json' -subprocess.check_call([ Toolbox.FindExecutable('Orthanc'), +subprocess.check_call([ Toolbox.FindExecutable(args.orthanc), '--config=%s' % CONFIG ]) with open(CONFIG, 'rt') as f: @@ -113,8 +116,8 @@ f.write(config) localOrthanc = ExternalCommandThread([ - 'Orthanc', - CONFIG, + Toolbox.FindExecutable(args.orthanc), + CONFIG, #'--verbose', #'--no-jobs' #'/home/jodogne/Subversion/Orthanc/i/Orthanc', CONFIG, '--verbose' diff -r 66a36befb208 -r bf8369ea3ff1 Tests/Tests.py --- a/Tests/Tests.py Wed Oct 14 19:55:26 2020 +0200 +++ b/Tests/Tests.py Thu Oct 15 17:34:01 2020 +0200 @@ -5330,7 +5330,7 @@ if s['Status'] != 'Pending': return s else: - time.sleep(0.1) + time.sleep(0.01) instance = UploadInstance(_REMOTE, 'DummyCT.dcm') sopClassUid = '1.2.840.10008.5.1.4.1.1.4' @@ -5414,7 +5414,7 @@ if s['Status'] != 'Pending': return s else: - time.sleep(0.1) + time.sleep(0.01) i = UploadInstance(_REMOTE, 'DummyCT.dcm')['ID'] self.assertEqual(1, len(DoGet(_REMOTE, '/instances'))) @@ -6017,16 +6017,43 @@ def test_webdav(self): self.assertRaises(Exception, lambda: DoPropFind(_REMOTE, '/webdav/', 2)) - xml = DoPropFind(_REMOTE, '/webdav/', 1) - pprint.pprint(xml.keys()) - print(xml['/webdav/'].toprettyxml()) + for suffix in [ '', '/' ]: + f = DoPropFind(_REMOTE, '/webdav' + suffix, 0) + self.assertEqual(1, len(f)) + self.assertTrue('/webdav/' in f.keys()) + self.assertTrue(f['/webdav/']['folder']) + self.assertEqual('webdav', f['/webdav/']['displayname']) + + f = DoPropFind(_REMOTE, '/webdav' + suffix, 1) + self.assertEqual(6, len(f)) + self.assertTrue(f['/webdav/']['folder']) + self.assertEqual('webdav', f['/webdav/']['displayname']) + + for i in [ 'by-dates', 'by-patients', 'by-studies', 'by-uids', 'uploads' ]: + self.assertTrue(f['/webdav/%s' % i]['folder']) + self.assertEqual(i, f['/webdav/%s' % i]['displayname']) + + for depth in [ 0, 1 ]: + for suffix2 in [ '', '/' ]: + g = DoPropFind(_REMOTE, '/webdav/%s%s' % (i, suffix2), depth) + + if i == 'uploads': + # Empty folders might still exist in "/uploads/" + self.assertTrue('/webdav/uploads/' in g) + self.assertEqual('uploads', g['/webdav/uploads/']['displayname']) + for j in g.items(): + self.assertTrue(g.items()[0][1]['folder']) + else: + self.assertEqual(1, len(g)) + self.assertEqual('/webdav/%s/' % i, g.items()[0][0]) + self.assertTrue(g.items()[0][1]['folder']) + self.assertEqual(i, g.items()[0][1]['displayname']) - #print(xml.toprettyxml()) - #for i in xml.getElementsByTagName('D:response'): - # print(i.getElementsByTagName('D:href')[0].childNodes[0].data) - # print(i.getElementsByTagName('D:prop')[0].toprettyxml()) - - + self.assertEqual(0, len(DoGet(_REMOTE, '/patients'))) + with open(GetDatabasePath('DummyCT.dcm'), 'rb') as f: + DoPut(_REMOTE, '/webdav/uploads/dummy', f.read(), 'text/plain') + + while len(DoGet(_REMOTE, '/patients')) == 0: + time.sleep(0.01) + self.assertEqual(1, len(DoGet(_REMOTE, '/patients'))) - self.assertEqual(0, len(DoGet(_REMOTE, '/patients'))) - UploadInstance(_REMOTE, 'Comunix/Ct/IM-0001-0001.dcm') diff -r 66a36befb208 -r bf8369ea3ff1 Tests/Toolbox.py --- a/Tests/Toolbox.py Wed Oct 14 19:55:26 2020 +0200 +++ b/Tests/Toolbox.py Thu Oct 15 17:34:01 2020 +0200 @@ -141,7 +141,7 @@ resp, content = http.request(orthanc['Url'] + uri, method, body = body, headers = headers) - if not (resp.status in [ 200, 302 ]): + if not (resp.status in [ 200, 201, 302 ]): raise Exception(resp.status, resp) else: return _DecodeJson(content) @@ -241,7 +241,7 @@ while True: if len(DoGet(orthanc, '/instances')) == 0: return - time.sleep(0.1) + time.sleep(0.01) def WaitJobDone(orthanc, job): while True: @@ -252,7 +252,7 @@ elif s == 'Failure': return False - time.sleep(0.1) + time.sleep(0.01) def MonitorJob(orthanc, func): # "func" is a lambda a = set(DoGet(orthanc, '/jobs')) @@ -479,7 +479,22 @@ raise Exception() if href == None or prop == None: raise Exception() - result[href] = prop + + info = {} + + for j in prop.childNodes: + if j.nodeType == minidom.Node.ELEMENT_NODE: + if j.nodeName == 'D:displayname': + info['displayname'] = j.firstChild.nodeValue if j.firstChild != None else '' + elif j.nodeName == 'D:creationdate': + info['creationdate'] = j.firstChild.nodeValue + elif j.nodeName == 'D:getlastmodified': + info['lastmodified'] = j.firstChild.nodeValue + elif j.nodeName == 'D:resourcetype': + k = j.getElementsByTagName('D:collection') + info['folder'] = (len(k) == 1) + + result[href] = info elif i.nodeType != minidom.Node.TEXT_NODE: raise Exception()