# HG changeset patch # User Sebastien Jodogne # Date 1606231289 -3600 # Node ID b96aedfa8cc18adfe25bd6f18667c637589a1c7d # Parent 433e94d08e36b76ddcecdc42adab85c2255b49f5 unit tests now running in WebAssembly diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake --- a/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake Tue Nov 24 16:21:29 2020 +0100 @@ -153,11 +153,15 @@ ${CMAKE_CURRENT_LIST_DIR}/../../Sources/EnumerationDictionary.h ${CMAKE_CURRENT_LIST_DIR}/../../Sources/Enumerations.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/FileStorage/MemoryStorageArea.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpContentNegociation.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpToolbox.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/MultipartStreamReader.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/StringMatcher.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/Logging.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/OrthancException.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/OrthancFramework.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiHierarchy.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiPath.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/SerializationToolbox.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/Toolbox.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/WebServiceParameters.cpp @@ -299,19 +303,15 @@ ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/BufferHttpSender.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/FilesystemHttpHandler.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/FilesystemHttpSender.cpp - ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpContentNegociation.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpFileSender.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpOutput.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpServer.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpStreamTranscoder.cpp - ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/HttpToolbox.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/HttpServer/StringHttpOutput.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApi.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiCall.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiGetCall.cpp - ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiHierarchy.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiOutput.cpp - ${CMAKE_CURRENT_LIST_DIR}/../../Sources/RestApi/RestApiPath.cpp ) if (ENABLE_PUGIXML) @@ -508,6 +508,7 @@ endif() set(ORTHANC_DICOM_SOURCES_INTERNAL + ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomFindAnswers.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomParsing/DicomModification.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomParsing/DicomWebJsonVisitor.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomParsing/FromDcmtkBridge.cpp @@ -531,7 +532,6 @@ ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomAssociation.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomAssociationParameters.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomControlUserConnection.cpp - ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomFindAnswers.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomServer.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/DicomStoreUserConnection.cpp ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomNetworking/Internals/CommandDispatcher.cpp diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Resources/CMake/UuidConfiguration.cmake --- a/OrthancFramework/Resources/CMake/UuidConfiguration.cmake Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/Resources/CMake/UuidConfiguration.cmake Tue Nov 24 16:21:29 2020 +0100 @@ -35,12 +35,13 @@ ## - ## Patch for OS X, in order to be compatible with Cocoa (used in Stone) + ## Patch for OS X, in order to be compatible with Cocoa, and for + ## WebAssembly (used in Stone) ## execute_process( COMMAND ${PATCH_EXECUTABLE} -p0 -N -i - ${CMAKE_CURRENT_LIST_DIR}/../Patches/e2fsprogs-1.44.5-apple.patch + ${CMAKE_CURRENT_LIST_DIR}/../Patches/e2fsprogs-1.44.5.patch WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure ) diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Resources/Patches/e2fsprogs-1.44.5-apple.patch --- a/OrthancFramework/Resources/Patches/e2fsprogs-1.44.5-apple.patch Tue Nov 24 12:37:52 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -diff -urEb e2fsprogs-1.44.5.orig/lib/uuid/uuid.h.in e2fsprogs-1.44.5/lib/uuid/uuid.h.in ---- e2fsprogs-1.44.5.orig/lib/uuid/uuid.h.in 2019-02-21 20:17:23.461402522 +0100 -+++ e2fsprogs-1.44.5/lib/uuid/uuid.h.in 2019-02-21 20:25:05.664540445 +0100 -@@ -35,6 +35,20 @@ - #ifndef _UUID_UUID_H - #define _UUID_UUID_H - -+ -+#if defined(__APPLE__) -+// This patch defines the "uuid_string_t" type on OS X, which is -+// required if linking against Cocoa (this occurs in Stone of Orthanc) -+#include -+#include -+ -+#ifndef _UUID_STRING_T -+#define _UUID_STRING_T -+typedef __darwin_uuid_string_t uuid_string_t; -+#endif /* _UUID_STRING_T */ -+#endif -+ -+ - #include - #ifndef _WIN32 - #include diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Resources/Patches/e2fsprogs-1.44.5.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Resources/Patches/e2fsprogs-1.44.5.patch Tue Nov 24 16:21:29 2020 +0100 @@ -0,0 +1,42 @@ +diff -urEb e2fsprogs-1.44.5.orig/lib/uuid/gen_uuid.c e2fsprogs-1.44.5/lib/uuid/gen_uuid.c +--- e2fsprogs-1.44.5.orig/lib/uuid/gen_uuid.c 2020-11-24 15:47:40.950897761 +0100 ++++ e2fsprogs-1.44.5/lib/uuid/gen_uuid.c 2020-11-24 15:48:51.234732050 +0100 +@@ -147,12 +147,14 @@ + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); ++#if !defined(__EMSCRIPTEN__) // By SJO for Stone + if (fd >= 0) { + i = fcntl(fd, F_GETFD); + if (i >= 0) + fcntl(fd, F_SETFD, i | FD_CLOEXEC); + } + #endif ++#endif + srand(((unsigned)getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); + #ifdef DO_JRAND_MIX + jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); +diff -urEb e2fsprogs-1.44.5.orig/lib/uuid/uuid.h.in e2fsprogs-1.44.5/lib/uuid/uuid.h.in +--- e2fsprogs-1.44.5.orig/lib/uuid/uuid.h.in 2020-11-24 15:47:40.950897761 +0100 ++++ e2fsprogs-1.44.5/lib/uuid/uuid.h.in 2020-11-24 15:48:00.946849227 +0100 +@@ -35,6 +35,20 @@ + #ifndef _UUID_UUID_H + #define _UUID_UUID_H + ++ ++#if defined(__APPLE__) ++// This patch defines the "uuid_string_t" type on OS X, which is ++// required if linking against Cocoa (this occurs in Stone of Orthanc) ++#include ++#include ++ ++#ifndef _UUID_STRING_T ++#define _UUID_STRING_T ++typedef __darwin_uuid_string_t uuid_string_t; ++#endif /* _UUID_STRING_T */ ++#endif ++ ++ + #include + #ifndef _WIN32 + #include diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Sources/Images/PamReader.cpp --- a/OrthancFramework/Sources/Images/PamReader.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/Sources/Images/PamReader.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -232,35 +232,31 @@ for (unsigned int w = 0; w < width; ++w, ++pixel) { -#if defined(__EMSCRIPTEN__) // For WebAssembly - /* - - crash (2019-08-05): - - Uncaught abort(alignment fault) at Error - at jsStackTrace - at stackTrace - at abort - at alignfault - at SAFE_HEAP_LOAD_i32_2_2 (wasm-function[251132]:39) - at __ZN7Orthanc9PamReader12ParseContentEv (wasm-function[11457]:8088) - - Web Assembly IS LITTLE ENDIAN! - - Perhaps in htobe16 ? - */ + /** + * This is Little-Endian computer, and PAM uses + * Big-Endian. Need to do a 16-bit swap. We DON'T use + * "htobe16()", as the latter only works if the "pixel" + * pointer is 16-bit aligned (which is not the case if + * "offset" is an odd number), and the trick that was used + * in Orthanc <= 1.8.0 (i.e. make a "memcpy()" to a local + * uint16_t variable) doesn't seem work for WebAssembly. We + * thus use a plain old C implementation. Check out issue + * #99: https://bugs.orthanc-server.com/show_bug.cgi?id=99 + * + * Here is the crash log on WebAssembly (2019-08-05): + * + * Uncaught abort(alignment fault) at Error + * at jsStackTrace + * at stackTrace + * at abort + * at alignfault + * at SAFE_HEAP_LOAD_i32_2_2 (wasm-function[251132]:39) + * at __ZN7Orthanc9PamReader12ParseContentEv (wasm-function[11457]:8088) + **/ uint8_t* srcdst = reinterpret_cast(pixel); uint8_t tmp = srcdst[0]; srcdst[0] = srcdst[1]; srcdst[1] = tmp; -#else - // memcpy() is necessary to avoid segmentation fault if the - // "pixel" pointer is not 16-bit aligned (which is the case - // if "offset" is an odd number). Check out issue #99: - // https://bitbucket.org/sjodogne/orthanc/issues/99 - uint16_t v = htobe16(*pixel); - memcpy(pixel, &v, sizeof(v)); -#endif } } } diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/Sources/Images/PamWriter.cpp --- a/OrthancFramework/Sources/Images/PamWriter.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/Sources/Images/PamWriter.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -117,16 +117,25 @@ (reinterpret_cast(buffer) + h * sourcePitch); uint16_t* q = reinterpret_cast (reinterpret_cast(&target[offset]) + h * targetPitch); - + for (unsigned int w = 0; w < width * channelCount; ++w) { - // memcpy() is necessary to avoid segmentation fault if the - // "pixel" pointer is not 16-bit aligned (which is the case - // if "offset" is an odd number). Check out issue #99: - // https://bitbucket.org/sjodogne/orthanc/issues/99 - uint16_t v = htobe16(*p); - memcpy(q, &v, sizeof(uint16_t)); - + /** + * This is Little-Endian computer, and PAM uses + * Big-Endian. Need to do a 16-bit swap. We DON'T use + * "htobe16()", as the latter only works if the "pixel" + * pointer is 16-bit aligned (which is not the case if + * "offset" is an odd number), and the trick that was used + * in Orthanc <= 1.8.0 (i.e. make a "memcpy()" to a local + * uint16_t variable) doesn't seem work for WebAssembly. We + * thus use a plain old C implementation. Check out issue + * #99: https://bugs.orthanc-server.com/show_bug.cgi?id=99 + **/ + const uint8_t* a = reinterpret_cast(p); + uint8_t* b = reinterpret_cast(q); + b[0] = a[1]; + b[1] = a[0]; + p++; q++; } diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/DicomMapTests.cpp --- a/OrthancFramework/UnitTestsSources/DicomMapTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/DicomMapTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -757,6 +757,8 @@ +#if ORTHANC_SANDBOXED != 1 + #include "../Sources/SystemToolbox.h" TEST(DicomMap, DISABLED_ParseDicomMetaInformation) @@ -1014,3 +1016,5 @@ printf("\n== SUCCESSES: %u ==\n\n", success); } + +#endif diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/FrameworkTests.cpp --- a/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -34,15 +34,18 @@ #include #include "../Sources/DicomFormat/DicomTag.h" -#include "../Sources/FileBuffer.h" #include "../Sources/HttpServer/HttpToolbox.h" #include "../Sources/Logging.h" -#include "../Sources/MetricsRegistry.h" #include "../Sources/OrthancException.h" -#include "../Sources/SystemToolbox.h" -#include "../Sources/TemporaryFile.h" #include "../Sources/Toolbox.h" +#if ORTHANC_SANDBOXED != 1 +# include "../Sources/FileBuffer.h" +# include "../Sources/MetricsRegistry.h" +# include "../Sources/SystemToolbox.h" +# include "../Sources/TemporaryFile.h" +#endif + #include @@ -298,6 +301,8 @@ ASSERT_TRUE(Toolbox::IsChildUri(c5, c5)); } + +#if ORTHANC_SANDBOXED != 1 TEST(Uri, AutodetectMimeType) { ASSERT_EQ(MimeType_Binary, SystemToolbox::AutodetectMimeType("../NOTES")); @@ -351,6 +356,8 @@ ASSERT_STREQ("text/css", EnumerationToString(SystemToolbox::AutodetectMimeType(".css"))); ASSERT_STREQ("text/html", EnumerationToString(SystemToolbox::AutodetectMimeType(".html"))); } +#endif + TEST(Toolbox, ComputeMD5) { @@ -374,11 +381,13 @@ ASSERT_EQ("da39a3ee-5e6b4b0d-3255bfef-95601890-afd80709", s); } +#if ORTHANC_SANDBOXED != 1 TEST(Toolbox, PathToExecutable) { printf("[%s]\n", SystemToolbox::GetPathToExecutable().c_str()); printf("[%s]\n", SystemToolbox::GetDirectoryOfExecutable().c_str()); } +#endif TEST(Toolbox, StripSpaces) { @@ -567,6 +576,7 @@ #endif +#if ORTHANC_SANDBOXED != 1 TEST(Toolbox, WriteFile) { std::string path; @@ -613,8 +623,10 @@ ASSERT_EQ(s, t); } } +#endif +#if ORTHANC_SANDBOXED != 1 TEST(Toolbox, FileBuffer) { FileBuffer f; @@ -628,6 +640,7 @@ ASSERT_THROW(f.Append("d", 1), OrthancException); // File is closed } +#endif TEST(Toolbox, Wildcard) @@ -820,8 +833,15 @@ ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); # endif + + /** + * WebAssembly is always little-endian. + **/ + +#elif defined(__EMSCRIPTEN__) + ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); #else -#error Support your platform here +# error Support your platform here #endif } @@ -1007,6 +1027,7 @@ } +#if ORTHANC_SANDBOXED != 1 TEST(Toolbox, Now) { LOG(WARNING) << "Local time: " << SystemToolbox::GetNowIsoString(false); @@ -1019,7 +1040,7 @@ SystemToolbox::GetNowDicom(date, time, true); LOG(WARNING) << "Universal DICOM time: [" << date << "] [" << time << "]"; } - +#endif #if ORTHANC_ENABLE_PUGIXML == 1 @@ -1040,7 +1061,7 @@ #endif -#if !defined(_WIN32) +#if !defined(_WIN32) && (ORTHANC_SANDBOXED != 1) TEST(Toolbox, ExecuteSystemCommand) { std::vector args(2); @@ -1200,6 +1221,7 @@ } +#if ORTHANC_SANDBOXED != 1 TEST(Toolbox, SubstituteVariables) { std::map env; @@ -1228,8 +1250,10 @@ ASSERT_EQ("AhelloB", Toolbox::SubstituteVariables("A${PATH}B", env)); } +#endif +#if ORTHANC_SANDBOXED != 1 TEST(MetricsRegistry, Basic) { { @@ -1342,3 +1366,4 @@ ASSERT_EQ(MetricsType_MinOver10Seconds, m.GetMetricsType("b")); } } +#endif diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp --- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -49,9 +49,12 @@ #include "../Sources/Images/PngWriter.h" #include "../Sources/Logging.h" #include "../Sources/OrthancException.h" -#include "../Sources/SystemToolbox.h" #include "../Resources/CodeGeneration/EncodingTests.h" +#if ORTHANC_SANDBOXED != 1 +# include "../Sources/SystemToolbox.h" +#endif + #include #include #include @@ -86,6 +89,7 @@ } +#if ORTHANC_SANDBOXED != 1 TEST(DicomModification, Basic) { DicomModification m; @@ -108,6 +112,7 @@ f->SaveToFile(b); } } +#endif TEST(DicomModification, Anonymization) @@ -182,18 +187,27 @@ ParsedDicomFile o(true); o.EmbedContent(s); + +#if ORTHANC_SANDBOXED != 1 o.SaveToFile("UnitTestsResults/png1.dcm"); +#endif // Red dot, without alpha channel s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gUGDTcIn2+8BgAAACJJREFUCNdj/P//PwMjIwME/P/P+J8BBTAxEOL/R9Lx/z8AynoKAXOeiV8AAAAASUVORK5CYII="; o.EmbedContent(s); + +#if ORTHANC_SANDBOXED != 1 o.SaveToFile("UnitTestsResults/png2.dcm"); +#endif // Check box in Graylevel8 s = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gUGDDcB53FulQAAAElJREFUGNNtj0sSAEEEQ1+U+185s1CtmRkblQ9CZldsKHJDk6DLGLJa6chjh0ooQmpjXMM86zPwydGEj6Ed/UGykkEM8X+p3u8/8LcOJIWLGeMAAAAASUVORK5CYII="; o.EmbedContent(s); //o.ReplacePlainString(DICOM_TAG_SOP_CLASS_UID, UID_DigitalXRayImageStorageForProcessing); + +#if ORTHANC_SANDBOXED != 1 o.SaveToFile("UnitTestsResults/png3.dcm"); +#endif { @@ -218,7 +232,10 @@ } o.EmbedImage(accessor); + +#if ORTHANC_SANDBOXED != 1 o.SaveToFile("UnitTestsResults/png4.dcm"); +#endif } } @@ -743,8 +760,6 @@ TEST(TestImages, PatternGrayscale8) { - static const char* PATH = "UnitTestsResults/PatternGrayscale8.dcm"; - Orthanc::Image image(Orthanc::PixelFormat_Grayscale8, 256, 256, false); for (int y = 0; y < 256; y++) @@ -764,6 +779,8 @@ image.GetRegion(r, 160, 32, 64, 192); Orthanc::ImageProcessing::Set(r, 255); + std::string saved; + { ParsedDicomFile f(true); f.ReplacePlainString(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.7"); @@ -774,13 +791,11 @@ f.ReplacePlainString(DICOM_TAG_SERIES_DESCRIPTION, "Grayscale8"); f.EmbedImage(image); - f.SaveToFile(PATH); + f.SaveToMemoryBuffer(saved); } { - std::string s; - Orthanc::SystemToolbox::ReadFile(s, PATH); - Orthanc::ParsedDicomFile f(s); + Orthanc::ParsedDicomFile f(saved); std::unique_ptr decoded(f.DecodeFrame(0)); ASSERT_EQ(256u, decoded->GetWidth()); @@ -799,8 +814,6 @@ TEST(TestImages, PatternRGB) { - static const char* PATH = "UnitTestsResults/PatternRGB24.dcm"; - Orthanc::Image image(Orthanc::PixelFormat_RGB24, 384, 256, false); for (int y = 0; y < 256; y++) @@ -826,6 +839,8 @@ } } + std::string saved; + { ParsedDicomFile f(true); f.ReplacePlainString(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.7"); @@ -836,13 +851,11 @@ f.ReplacePlainString(DICOM_TAG_SERIES_DESCRIPTION, "RGB24"); f.EmbedImage(image); - f.SaveToFile(PATH); + f.SaveToMemoryBuffer(saved); } { - std::string s; - Orthanc::SystemToolbox::ReadFile(s, PATH); - Orthanc::ParsedDicomFile f(s); + Orthanc::ParsedDicomFile f(saved); std::unique_ptr decoded(f.DecodeFrame(0)); ASSERT_EQ(384u, decoded->GetWidth()); @@ -861,8 +874,6 @@ TEST(TestImages, PatternUint16) { - static const char* PATH = "UnitTestsResults/PatternGrayscale16.dcm"; - Orthanc::Image image(Orthanc::PixelFormat_Grayscale16, 256, 256, false); uint16_t v = 0; @@ -883,6 +894,8 @@ image.GetRegion(r, 160, 32, 64, 192); Orthanc::ImageProcessing::Set(r, 65535); + std::string saved; + { ParsedDicomFile f(true); f.ReplacePlainString(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.7"); @@ -893,13 +906,11 @@ f.ReplacePlainString(DICOM_TAG_SERIES_DESCRIPTION, "Grayscale16"); f.EmbedImage(image); - f.SaveToFile(PATH); + f.SaveToMemoryBuffer(saved); } { - std::string s; - Orthanc::SystemToolbox::ReadFile(s, PATH); - Orthanc::ParsedDicomFile f(s); + Orthanc::ParsedDicomFile f(saved); std::unique_ptr decoded(f.DecodeFrame(0)); ASSERT_EQ(256u, decoded->GetWidth()); @@ -918,8 +929,6 @@ TEST(TestImages, PatternInt16) { - static const char* PATH = "UnitTestsResults/PatternSignedGrayscale16.dcm"; - Orthanc::Image image(Orthanc::PixelFormat_SignedGrayscale16, 256, 256, false); int16_t v = -32768; @@ -939,6 +948,8 @@ image.GetRegion(r, 160, 32, 64, 192); Orthanc::ImageProcessing::Set(r, 32767); + std::string saved; + { ParsedDicomFile f(true); f.ReplacePlainString(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.7"); @@ -949,13 +960,11 @@ f.ReplacePlainString(DICOM_TAG_SERIES_DESCRIPTION, "SignedGrayscale16"); f.EmbedImage(image); - f.SaveToFile(PATH); + f.SaveToMemoryBuffer(saved); } { - std::string s; - Orthanc::SystemToolbox::ReadFile(s, PATH); - Orthanc::ParsedDicomFile f(s); + Orthanc::ParsedDicomFile f(saved); std::unique_ptr decoded(f.DecodeFrame(0)); ASSERT_EQ(256u, decoded->GetWidth()); diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/ImageTests.cpp --- a/OrthancFramework/UnitTestsSources/ImageTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/ImageTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -36,9 +36,12 @@ #include "../Sources/Images/PngWriter.h" #include "../Sources/Images/PamReader.h" #include "../Sources/Images/PamWriter.h" -#include "../Sources/SystemToolbox.h" #include "../Sources/Toolbox.h" -#include "../Sources/TemporaryFile.h" + +#if ORTHANC_SANDBOXED != 1 +# include "../Sources/SystemToolbox.h" +# include "../Sources/TemporaryFile.h" +#endif #include @@ -65,14 +68,21 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_RGB24, width, height, pitch, &image[0]); - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/ColorPattern.png", accessor); + std::string f; - std::string f, md5; +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/ColorPattern.png", accessor); Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/ColorPattern.png"); +#endif + + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("604e785f53c99cae6ea4584870b2c41d", md5); } + TEST(PngWriter, Gray8Pattern) { Orthanc::PngWriter w; @@ -93,10 +103,16 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale8, width, height, pitch, &image[0]); + std::string f; + +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray8Pattern.png", accessor); + Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.png"); +#endif - std::string f, md5; - Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.png"); + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("5a9b98bea3d0a6d983980cc38bfbcdb3", md5); } @@ -122,10 +138,17 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]); - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray16Pattern.png", accessor); - std::string f, md5; + std::string f; + +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray16Pattern.png", accessor); Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray16Pattern.png"); +#endif + + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("0785866a08bf0a02d2eeff87f658571c", md5); } @@ -175,6 +198,7 @@ } } +#if ORTHANC_SANDBOXED != 1 { Orthanc::TemporaryFile tmp; tmp.Write(s); @@ -197,6 +221,7 @@ } } } +#endif } @@ -218,34 +243,51 @@ } Orthanc::JpegWriter w; - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/hello.jpg", img); + Orthanc::IImageWriter::WriteToMemory(w, s, img); - Orthanc::IImageWriter::WriteToMemory(w, s, img); +#if ORTHANC_SANDBOXED != 1 + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/hello.jpg", img); Orthanc::SystemToolbox::WriteFile(s, "UnitTestsResults/hello2.jpg"); std::string t; Orthanc::SystemToolbox::ReadFile(t, "UnitTestsResults/hello.jpg"); ASSERT_EQ(s.size(), t.size()); ASSERT_EQ(0, memcmp(s.c_str(), t.c_str(), s.size())); +#endif } { - Orthanc::JpegReader r1, r2; - r1.ReadFromFile("UnitTestsResults/hello.jpg"); + Orthanc::JpegReader r1; + r1.ReadFromMemory(s); ASSERT_EQ(16u, r1.GetWidth()); ASSERT_EQ(16u, r1.GetHeight()); - r2.ReadFromMemory(s); +#if ORTHANC_SANDBOXED != 1 + Orthanc::JpegReader r2; + r2.ReadFromFile("UnitTestsResults/hello.jpg"); ASSERT_EQ(16u, r2.GetWidth()); ASSERT_EQ(16u, r2.GetHeight()); +#endif + unsigned int value = 0; for (unsigned int y = 0; y < r1.GetHeight(); y++) { const uint8_t* p1 = reinterpret_cast(r1.GetConstRow(y)); +#if ORTHANC_SANDBOXED != 1 const uint8_t* p2 = reinterpret_cast(r2.GetConstRow(y)); - for (unsigned int x = 0; x < r1.GetWidth(); x++) +#endif + for (unsigned int x = 0; x < r1.GetWidth(); x++, value++) { + ASSERT_TRUE(*p1 == value || + *p1 == value - 1 || + *p1 == value + 1); // Be tolerant to differences of +-1 + +#if ORTHANC_SANDBOXED != 1 ASSERT_EQ(*p1, *p2); + p2++; +#endif + + p1++; } } } @@ -274,10 +316,16 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_RGB24, width, height, pitch, &image[0]); - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/ColorPattern.pam", accessor); + std::string f; - std::string f, md5; +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/ColorPattern.pam", accessor); Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/ColorPattern.pam"); +#endif + + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("81a3441754e88969ebbe53e69891e841", md5); } @@ -302,10 +350,16 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale8, width, height, pitch, &image[0]); - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray8Pattern.pam", accessor); + std::string f; - std::string f, md5; +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray8Pattern.pam", accessor); Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.pam"); +#endif + + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("7873c408d26a9d11dd1c1de5e69cc0a3", md5); } @@ -331,10 +385,17 @@ Orthanc::ImageAccessor accessor; accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]); - Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray16Pattern.pam", accessor); + + std::string f; - std::string f, md5; +#if ORTHANC_SANDBOXED == 1 + Orthanc::IImageWriter::WriteToMemory(w, f, accessor); +#else + Orthanc::IImageWriter::WriteToFile(w, "UnitTestsResults/Gray16Pattern.pam", accessor); Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray16Pattern.pam"); +#endif + + std::string md5; Orthanc::Toolbox::ComputeMD5(md5, f); ASSERT_EQ("b268772bf28f3b2b8520ff21c5e3dcb6", md5); } @@ -407,6 +468,7 @@ } } +#if ORTHANC_SANDBOXED != 1 { Orthanc::TemporaryFile tmp; tmp.Write(s); @@ -430,7 +492,9 @@ } } } +#endif +#if ORTHANC_SANDBOXED != 1 { Orthanc::TemporaryFile tmp; tmp.Write(s); @@ -455,5 +519,5 @@ } } } - +#endif } diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/LoggingTests.cpp --- a/OrthancFramework/UnitTestsSources/LoggingTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/LoggingTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -129,6 +129,7 @@ } +#if ORTHANC_ENABLE_LOGGING_STDIO == 0 TEST(FuncStreamBuf, BasicTest) { LoggingMementoScope loggingConfiguration; @@ -199,6 +200,7 @@ Orthanc::Logging::EnableTraceLevel(false); // Back to normal } +#endif diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/RestApiTests.cpp --- a/OrthancFramework/UnitTestsSources/RestApiTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/RestApiTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -28,15 +28,14 @@ #include #include "../Sources/ChunkedBuffer.h" -#include "../Sources/HttpClient.h" -#include "../Sources/Logging.h" -#include "../Sources/SystemToolbox.h" -#include "../Sources/RestApi/RestApi.h" -#include "../Sources/OrthancException.h" #include "../Sources/Compression/ZlibCompressor.h" -#include "../Sources/RestApi/RestApiHierarchy.h" #include "../Sources/HttpServer/HttpContentNegociation.h" #include "../Sources/HttpServer/MultipartStreamReader.h" +#include "../Sources/Logging.h" +#include "../Sources/OrthancException.h" +#include "../Sources/RestApi/RestApi.h" +#include "../Sources/RestApi/RestApiHierarchy.h" +#include "../Sources/WebServiceParameters.h" #include #include @@ -45,7 +44,7 @@ using namespace Orthanc; -#if !defined(UNIT_TESTS_WITH_HTTP_CONNEXIONS) +#if !defined(UNIT_TESTS_WITH_HTTP_CONNEXIONS) && (ORTHANC_SANDBOXED != 1) # error UNIT_TESTS_WITH_HTTP_CONNEXIONS is not defined #endif @@ -53,8 +52,13 @@ # error ORTHANC_ENABLE_SSL is not defined #endif +#if ORTHANC_SANDBOXED != 1 +# include "../Sources/HttpClient.h" +# include "../Sources/SystemToolbox.h" +#endif +#if ORTHANC_SANDBOXED != 1 TEST(HttpClient, Basic) { HttpClient c; @@ -78,9 +82,10 @@ ASSERT_TRUE(v.isMember("Description")); #endif } +#endif -#if UNIT_TESTS_WITH_HTTP_CONNEXIONS == 1 && ORTHANC_ENABLE_SSL == 1 +#if (UNIT_TESTS_WITH_HTTP_CONNEXIONS == 1) && (ORTHANC_ENABLE_SSL == 1) && (ORTHANC_SANDBOXED != 1) /** The HTTPS CA certificates for BitBucket were extracted as follows: @@ -969,6 +974,8 @@ +#if ORTHANC_SANDBOXED != 1 + namespace { class TotoBody : public HttpClient::IRequestBody @@ -1059,6 +1066,7 @@ } + #include "../Sources/HttpServer/HttpServer.h" TEST(HttpClient, DISABLED_Issue156_Slow) @@ -1117,3 +1125,4 @@ server.Stop(); } +#endif diff -r 433e94d08e36 -r b96aedfa8cc1 OrthancFramework/UnitTestsSources/StreamTests.cpp --- a/OrthancFramework/UnitTestsSources/StreamTests.cpp Tue Nov 24 12:37:52 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/StreamTests.cpp Tue Nov 24 16:21:29 2020 +0100 @@ -27,15 +27,18 @@ #include -#include "../Sources/SystemToolbox.h" #include "../Sources/Toolbox.h" #include "../Sources/OrthancException.h" #include "../Sources/HttpServer/BufferHttpSender.h" -#include "../Sources/HttpServer/FilesystemHttpSender.h" #include "../Sources/HttpServer/HttpStreamTranscoder.h" #include "../Sources/Compression/ZlibCompressor.h" #include "../Sources/Compression/GzipCompressor.h" +#if ORTHANC_SANDBOXED != 1 +# include "../Sources/HttpServer/FilesystemHttpSender.h" +# include "../Sources/SystemToolbox.h" +#endif + using namespace Orthanc; @@ -171,6 +174,7 @@ } +#if ORTHANC_SANDBOXED != 1 static bool ReadAllStream(std::string& result, IHttpStreamAnswer& stream, bool allowGzip = false, @@ -195,8 +199,10 @@ return pos == result.size(); } +#endif +#if ORTHANC_SANDBOXED != 1 TEST(BufferHttpSender, Basic) { const std::string s = "Hello world"; @@ -218,8 +224,10 @@ ASSERT_EQ(s, t); } } +#endif +#if ORTHANC_SANDBOXED != 1 TEST(FilesystemHttpSender, Basic) { const std::string& path = "UnitTestsResults/stream"; @@ -240,8 +248,10 @@ ASSERT_EQ(0u, t.size()); } } +#endif +#if ORTHANC_SANDBOXED != 1 TEST(HttpStreamTranscoder, Basic) { ZlibCompressor compressor; @@ -322,3 +332,4 @@ ASSERT_EQ(0u, u.size()); } } +#endif