# HG changeset patch # User Sebastien Jodogne # Date 1620233948 -7200 # Node ID 9528e2a03d3cf2896ccb31bb07cdf0f1bfc78e95 # Parent eb87ec525b5302fd5559a38c6dd9afff36557ac6 adapt DICOMweb tests following fix of issue 196 (STOW-RS: Should return 200 only when successfully stored all instances) diff -r eb87ec525b53 -r 9528e2a03d3c Database/Issue196.dcm Binary file Database/Issue196.dcm has changed diff -r eb87ec525b53 -r 9528e2a03d3c Database/Issue196.dump --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Database/Issue196.dump Wed May 05 18:59:08 2021 +0200 @@ -0,0 +1,4 @@ +# dump2dcm --write-xfer-little Issue196.dump Issue196.dcm + +(0008,0018) UI [1.2.840.113619.2.176.2025.1499492.7040.1171286242.109] # 54, 1 SOPInstanceUID +(0008,0016) UI =MRImageStorage # 26, 1 SOPClassUID diff -r eb87ec525b53 -r 9528e2a03d3c Database/Issue196.dump~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Database/Issue196.dump~ Wed May 05 18:59:08 2021 +0200 @@ -0,0 +1,5 @@ +# dump2dcm +Ug --write-xfer-little Issue111.dump Issue111.dcm + +(0010,0020) LO A # Patient ID +(0010,0010) PN HELLO^A # Patient Name +(0008,0050) SH (no value available) # AccessionNumber diff -r eb87ec525b53 -r 9528e2a03d3c Plugins/DicomWeb/DicomWeb.py --- a/Plugins/DicomWeb/DicomWeb.py Mon Apr 26 15:22:59 2021 +0200 +++ b/Plugins/DicomWeb/DicomWeb.py Wed May 05 18:59:08 2021 +0200 @@ -39,7 +39,7 @@ body += bytearray('\r\n', 'ascii') -def SendStow(orthanc, uri, dicom): +def SendStowRaw(orthanc, uri, dicom): # We do not use Python's "email" package, as it uses LF (\n) for line # endings instead of CRLF (\r\n) for binary messages, as required by # RFC 1341 @@ -65,7 +65,17 @@ 'Accept' : 'application/json', } - return DoPost(orthanc, uri, body, headers = headers) + (response, content) = DoPostRaw(orthanc, uri, body, headers = headers) + + return (response.status, DecodeJson(content)) + + +def SendStow(orthanc, uri, dicom): + (status, content) = SendStowRaw(orthanc, uri, dicom) + if not (status in [ 200 ]): + raise Exception('Bad status: %d' % status) + else: + return content def DoGetMultipart(orthanc, uri, headers = {}, returnHeaders = False): diff -r eb87ec525b53 -r 9528e2a03d3c Plugins/DicomWeb/Run.py --- a/Plugins/DicomWeb/Run.py Mon Apr 26 15:22:59 2021 +0200 +++ b/Plugins/DicomWeb/Run.py Wed May 05 18:59:08 2021 +0200 @@ -649,41 +649,60 @@ def test_stow_errors(self): + def CheckSequences(a): + self.assertEqual(3, len(a)) + self.assertTrue('00080005' in a) + self.assertTrue('00081198' in a) + self.assertTrue('00081199' in a) + self.assertEqual('CS', a['00080005']['vr']) + self.assertEqual('SQ', a['00081198']['vr']) + self.assertEqual('SQ', a['00081199']['vr']) + # Pushing an instance to a study that is not its parent - a = SendStow(ORTHANC, args.dicomweb + '/studies/nope', GetDatabasePath('Phenix/IM-0001-0001.dcm')) - self.assertEqual(3, len(a)) - self.assertTrue('00080005' in a) - self.assertEqual('CS', a['00080005']['vr']) - self.assertTrue('00081198' in a) - self.assertEqual('SQ', a['00081198']['vr']) - self.assertEqual(1, len(['00081198'])) - self.assertTrue('00081199' in a) - self.assertEqual('SQ', a['00081199']['vr']) - self.assertEqual(1, len(['00081199'])) + (status, a) = SendStowRaw(ORTHANC, args.dicomweb + '/studies/nope', GetDatabasePath('Phenix/IM-0001-0001.dcm')) + self.assertEqual(409, status) + CheckSequences(a) + + self.assertFalse('Value' in a['00081199']) # No success instance + + self.assertEqual(1, len(a['00081198']['Value'])) # One failed instance + self.assertEqual('1.2.840.10008.5.1.4.1.1.2', + a['00081198']['Value'][0]['00081150']['Value'][0]) + self.assertEqual('1.2.840.113704.7.1.1.6632.1127829031.2', + a['00081198']['Value'][0]['00081155']['Value'][0]) + self.assertEqual(0x0110, # Processing failure + a['00081198']['Value'][0]['00081197']['Value'][0]) # Pushing an instance with missing tags - a = SendStow(ORTHANC, args.dicomweb + '/studies', GetDatabasePath('Issue111.dcm')) - self.assertEqual(3, len(a)) - self.assertTrue('00080005' in a) - self.assertEqual('CS', a['00080005']['vr']) - self.assertTrue('00081198' in a) - self.assertEqual('SQ', a['00081198']['vr']) - self.assertEqual(1, len(['00081198'])) - self.assertTrue('00081199' in a) - self.assertEqual('SQ', a['00081199']['vr']) - self.assertEqual(1, len(['00081199'])) + (status, a) = SendStowRaw(ORTHANC, args.dicomweb + '/studies', GetDatabasePath('Issue111.dcm')) + self.assertEqual(400, status) + CheckSequences(a) + + self.assertFalse('Value' in a['00081198']) # No failed instance, as tags are missing + self.assertFalse('Value' in a['00081199']) # No success instance # Pushing a file that is not in the DICOM format - a = SendStow(ORTHANC, args.dicomweb + '/studies', GetDatabasePath('Issue111.dump')) - self.assertEqual(3, len(a)) - self.assertTrue('00080005' in a) - self.assertEqual('CS', a['00080005']['vr']) - self.assertTrue('00081198' in a) - self.assertEqual('SQ', a['00081198']['vr']) - self.assertEqual(1, len(['00081198'])) - self.assertTrue('00081199' in a) - self.assertEqual('SQ', a['00081199']['vr']) - self.assertEqual(1, len(['00081199'])) + (status, a) = SendStowRaw(ORTHANC, args.dicomweb + '/studies', GetDatabasePath('Issue111.dump')) + self.assertEqual(400, status) + CheckSequences(a) + + self.assertFalse('Value' in a['00081198']) # No failed instance, as non-DICOM + self.assertFalse('Value' in a['00081199']) # No success instance + + # Pushing a DICOM instance with only SOP class and instance UID + (status, a) = SendStowRaw(ORTHANC, args.dicomweb + '/studies', GetDatabasePath('Issue196.dcm')) + self.assertEqual(400, status) + CheckSequences(a) + + self.assertFalse('Value' in a['00081199']) # No success instance + + self.assertEqual(1, len(a['00081198']['Value'])) # One failed instance + self.assertEqual('1.2.840.10008.5.1.4.1.1.4', + a['00081198']['Value'][0]['00081150']['Value'][0]) + self.assertEqual('1.2.840.113619.2.176.2025.1499492.7040.1171286242.109', + a['00081198']['Value'][0]['00081155']['Value'][0]) + self.assertEqual(0xC000, # Error: Cannot understand (cannot understand certain Data Elements) + a['00081198']['Value'][0]['00081197']['Value'][0]) def test_allowed_methods(self): diff -r eb87ec525b53 -r 9528e2a03d3c Tests/Toolbox.py --- a/Tests/Toolbox.py Mon Apr 26 15:22:59 2021 +0200 +++ b/Tests/Toolbox.py Wed May 05 18:59:08 2021 +0200 @@ -56,7 +56,7 @@ from StringIO import StringIO -def _DecodeJson(s): +def DecodeJson(s): t = s if (sys.version_info >= (3, 0)): @@ -121,7 +121,7 @@ if not (resp.status in [ 200 ]): raise Exception(resp.status, resp) else: - return _DecodeJson(content) + return DecodeJson(content) def _DoPutOrPost(orthanc, uri, method, data, contentType, headers): http = httplib2.Http() @@ -156,7 +156,7 @@ if not (resp.status in [ 200 ]): raise Exception(resp.status, resp) else: - return _DecodeJson(content) + return DecodeJson(content) def DoPutRaw(orthanc, uri, data = {}, contentType = '', headers = {}): return _DoPutOrPost(orthanc, uri, 'PUT', data, contentType, headers) @@ -166,7 +166,7 @@ if not (resp.status in [ 200, 201, 302 ]): raise Exception(resp.status, resp) else: - return _DecodeJson(content) + return DecodeJson(content) def DoPostRaw(orthanc, uri, data = {}, contentType = '', headers = {}): return _DoPutOrPost(orthanc, uri, 'POST', data, contentType, headers) @@ -176,7 +176,7 @@ if not (resp.status in [ 200, 201, 302 ]): raise Exception(resp.status, resp) else: - return _DecodeJson(content) + return DecodeJson(content) def GetDatabasePath(filename): return os.path.join(os.path.dirname(__file__), '..', 'Database', filename)