# HG changeset patch # User Sebastien Jodogne # Date 1392809957 -3600 # Node ID edffcf3ce7ab364fce07ab68917eca856b6cb3f6 # Parent ef4569ae79527e21ec8928bb9ccf12dc362be1a5 sonar diff -r ef4569ae7952 -r edffcf3ce7ab CMakeLists.txt --- a/CMakeLists.txt Wed Feb 19 11:01:55 2014 +0100 +++ b/CMakeLists.txt Wed Feb 19 12:39:17 2014 +0100 @@ -259,12 +259,12 @@ UnitTestsSources/RestApi.cpp UnitTestsSources/SQLite.cpp UnitTestsSources/SQLiteChromium.cpp - UnitTestsSources/ServerIndex.cpp + UnitTestsSources/ServerIndexTests.cpp UnitTestsSources/Versions.cpp UnitTestsSources/Zip.cpp UnitTestsSources/Lua.cpp UnitTestsSources/MultiThreading.cpp - UnitTestsSources/main.cpp + UnitTestsSources/UnitTestsMain.cpp ) target_link_libraries(UnitTests ServerLibrary CoreLibrary) diff -r ef4569ae7952 -r edffcf3ce7ab UnitTestsSources/ServerIndex.cpp --- a/UnitTestsSources/ServerIndex.cpp Wed Feb 19 11:01:55 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,556 +0,0 @@ -#include "gtest/gtest.h" - -#include "../OrthancServer/DatabaseWrapper.h" -#include "../OrthancServer/ServerContext.h" -#include "../OrthancServer/ServerIndex.h" -#include "../Core/Uuid.h" -#include "../Core/DicomFormat/DicomNullValue.h" - -#include -#include -#include - -using namespace Orthanc; - -namespace -{ - class ServerIndexListener : public IServerIndexListener - { - public: - std::vector deletedFiles_; - std::string ancestorId_; - ResourceType ancestorType_; - - void Reset() - { - ancestorId_ = ""; - deletedFiles_.clear(); - } - - virtual void SignalRemainingAncestor(ResourceType type, - const std::string& publicId) - { - ancestorId_ = publicId; - ancestorType_ = type; - } - - virtual void SignalFileDeleted(const FileInfo& info) - { - const std::string fileUuid = info.GetUuid(); - deletedFiles_.push_back(fileUuid); - LOG(INFO) << "A file must be removed: " << fileUuid; - } - }; -} - - -TEST(DatabaseWrapper, Simple) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - int64_t a[] = { - index.CreateResource("a", ResourceType_Patient), // 0 - index.CreateResource("b", ResourceType_Study), // 1 - index.CreateResource("c", ResourceType_Series), // 2 - index.CreateResource("d", ResourceType_Instance), // 3 - index.CreateResource("e", ResourceType_Instance), // 4 - index.CreateResource("f", ResourceType_Instance), // 5 - index.CreateResource("g", ResourceType_Study) // 6 - }; - - ASSERT_EQ("a", index.GetPublicId(a[0])); - ASSERT_EQ("b", index.GetPublicId(a[1])); - ASSERT_EQ("c", index.GetPublicId(a[2])); - ASSERT_EQ("d", index.GetPublicId(a[3])); - ASSERT_EQ("e", index.GetPublicId(a[4])); - ASSERT_EQ("f", index.GetPublicId(a[5])); - ASSERT_EQ("g", index.GetPublicId(a[6])); - - ASSERT_EQ(ResourceType_Patient, index.GetResourceType(a[0])); - ASSERT_EQ(ResourceType_Study, index.GetResourceType(a[1])); - ASSERT_EQ(ResourceType_Series, index.GetResourceType(a[2])); - ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[3])); - ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[4])); - ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[5])); - ASSERT_EQ(ResourceType_Study, index.GetResourceType(a[6])); - - { - Json::Value t; - index.GetAllPublicIds(t, ResourceType_Patient); - - ASSERT_EQ(1u, t.size()); - ASSERT_EQ("a", t[0u].asString()); - - index.GetAllPublicIds(t, ResourceType_Series); - ASSERT_EQ(1u, t.size()); - ASSERT_EQ("c", t[0u].asString()); - - index.GetAllPublicIds(t, ResourceType_Study); - ASSERT_EQ(2u, t.size()); - - index.GetAllPublicIds(t, ResourceType_Instance); - ASSERT_EQ(3u, t.size()); - } - - index.SetGlobalProperty(GlobalProperty_FlushSleep, "World"); - - index.AttachChild(a[0], a[1]); - index.AttachChild(a[1], a[2]); - index.AttachChild(a[2], a[3]); - index.AttachChild(a[2], a[4]); - index.AttachChild(a[6], a[5]); - - int64_t parent; - ASSERT_FALSE(index.LookupParent(parent, a[0])); - ASSERT_TRUE(index.LookupParent(parent, a[1])); ASSERT_EQ(a[0], parent); - ASSERT_TRUE(index.LookupParent(parent, a[2])); ASSERT_EQ(a[1], parent); - ASSERT_TRUE(index.LookupParent(parent, a[3])); ASSERT_EQ(a[2], parent); - ASSERT_TRUE(index.LookupParent(parent, a[4])); ASSERT_EQ(a[2], parent); - ASSERT_TRUE(index.LookupParent(parent, a[5])); ASSERT_EQ(a[6], parent); - ASSERT_FALSE(index.LookupParent(parent, a[6])); - - std::string s; - - ASSERT_FALSE(index.GetParentPublicId(s, a[0])); - ASSERT_FALSE(index.GetParentPublicId(s, a[6])); - ASSERT_TRUE(index.GetParentPublicId(s, a[1])); ASSERT_EQ("a", s); - ASSERT_TRUE(index.GetParentPublicId(s, a[2])); ASSERT_EQ("b", s); - ASSERT_TRUE(index.GetParentPublicId(s, a[3])); ASSERT_EQ("c", s); - ASSERT_TRUE(index.GetParentPublicId(s, a[4])); ASSERT_EQ("c", s); - ASSERT_TRUE(index.GetParentPublicId(s, a[5])); ASSERT_EQ("g", s); - - std::list l; - index.GetChildrenPublicId(l, a[0]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("b", l.front()); - index.GetChildrenPublicId(l, a[1]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("c", l.front()); - index.GetChildrenPublicId(l, a[3]); ASSERT_EQ(0u, l.size()); - index.GetChildrenPublicId(l, a[4]); ASSERT_EQ(0u, l.size()); - index.GetChildrenPublicId(l, a[5]); ASSERT_EQ(0u, l.size()); - index.GetChildrenPublicId(l, a[6]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("f", l.front()); - - index.GetChildrenPublicId(l, a[2]); ASSERT_EQ(2u, l.size()); - if (l.front() == "d") - { - ASSERT_EQ("e", l.back()); - } - else - { - ASSERT_EQ("d", l.back()); - ASSERT_EQ("e", l.front()); - } - - std::list md; - index.ListAvailableMetadata(md, a[4]); - ASSERT_EQ(0u, md.size()); - - index.AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", - CompressionType_Zlib, 21, "compressedMD5")); - index.AddAttachment(a[4], FileInfo("my dicom file", FileContentType_Dicom, 42, "md5")); - index.AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5")); - index.SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE"); - - index.ListAvailableMetadata(md, a[4]); - ASSERT_EQ(1u, md.size()); - ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); - index.SetMetadata(a[4], MetadataType_ModifiedFrom, "TUTU"); - index.ListAvailableMetadata(md, a[4]); - ASSERT_EQ(2u, md.size()); - index.DeleteMetadata(a[4], MetadataType_ModifiedFrom); - index.ListAvailableMetadata(md, a[4]); - ASSERT_EQ(1u, md.size()); - ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); - - ASSERT_EQ(21u + 42u + 44u, index.GetTotalCompressedSize()); - ASSERT_EQ(42u + 42u + 44u, index.GetTotalUncompressedSize()); - - DicomMap m; - m.SetValue(0x0010, 0x0010, "PatientName"); - index.SetMainDicomTags(a[3], m); - - int64_t b; - ResourceType t; - ASSERT_TRUE(index.LookupResource("g", b, t)); - ASSERT_EQ(7, b); - ASSERT_EQ(ResourceType_Study, t); - - ASSERT_TRUE(index.LookupMetadata(s, a[4], MetadataType_Instance_RemoteAet)); - ASSERT_FALSE(index.LookupMetadata(s, a[4], MetadataType_Instance_IndexInSeries)); - ASSERT_EQ("PINNACLE", s); - ASSERT_EQ("PINNACLE", index.GetMetadata(a[4], MetadataType_Instance_RemoteAet)); - ASSERT_EQ("None", index.GetMetadata(a[4], MetadataType_Instance_IndexInSeries, "None")); - - ASSERT_TRUE(index.LookupGlobalProperty(s, GlobalProperty_FlushSleep)); - ASSERT_FALSE(index.LookupGlobalProperty(s, static_cast(42))); - ASSERT_EQ("World", s); - ASSERT_EQ("World", index.GetGlobalProperty(GlobalProperty_FlushSleep)); - ASSERT_EQ("None", index.GetGlobalProperty(static_cast(42), "None")); - - FileInfo att; - ASSERT_TRUE(index.LookupAttachment(att, a[4], FileContentType_DicomAsJson)); - ASSERT_EQ("my json file", att.GetUuid()); - ASSERT_EQ(21u, att.GetCompressedSize()); - ASSERT_EQ("md5", att.GetUncompressedMD5()); - ASSERT_EQ("compressedMD5", att.GetCompressedMD5()); - ASSERT_EQ(42u, att.GetUncompressedSize()); - ASSERT_EQ(CompressionType_Zlib, att.GetCompressionType()); - - ASSERT_TRUE(index.LookupAttachment(att, a[6], FileContentType_Dicom)); - ASSERT_EQ("world", att.GetUuid()); - ASSERT_EQ(44u, att.GetCompressedSize()); - ASSERT_EQ("md5", att.GetUncompressedMD5()); - ASSERT_EQ("md5", att.GetCompressedMD5()); - ASSERT_EQ(44u, att.GetUncompressedSize()); - ASSERT_EQ(CompressionType_None, att.GetCompressionType()); - - ASSERT_EQ(0u, listener.deletedFiles_.size()); - ASSERT_EQ(7u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(3u, index.GetTableRecordCount("AttachedFiles")); - ASSERT_EQ(1u, index.GetTableRecordCount("Metadata")); - ASSERT_EQ(1u, index.GetTableRecordCount("MainDicomTags")); - index.DeleteResource(a[0]); - - ASSERT_EQ(2u, listener.deletedFiles_.size()); - ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), - listener.deletedFiles_.end(), - "my json file") == listener.deletedFiles_.end()); - ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), - listener.deletedFiles_.end(), - "my dicom file") == listener.deletedFiles_.end()); - - ASSERT_EQ(2u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, index.GetTableRecordCount("Metadata")); - ASSERT_EQ(1u, index.GetTableRecordCount("AttachedFiles")); - ASSERT_EQ(0u, index.GetTableRecordCount("MainDicomTags")); - index.DeleteResource(a[5]); - ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, index.GetTableRecordCount("AttachedFiles")); - ASSERT_EQ(2u, index.GetTableRecordCount("GlobalProperties")); - - ASSERT_EQ(3u, listener.deletedFiles_.size()); - ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), - listener.deletedFiles_.end(), - "world") == listener.deletedFiles_.end()); -} - - - - -TEST(DatabaseWrapper, Upward) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - int64_t a[] = { - index.CreateResource("a", ResourceType_Patient), // 0 - index.CreateResource("b", ResourceType_Study), // 1 - index.CreateResource("c", ResourceType_Series), // 2 - index.CreateResource("d", ResourceType_Instance), // 3 - index.CreateResource("e", ResourceType_Instance), // 4 - index.CreateResource("f", ResourceType_Study), // 5 - index.CreateResource("g", ResourceType_Series), // 6 - index.CreateResource("h", ResourceType_Series) // 7 - }; - - index.AttachChild(a[0], a[1]); - index.AttachChild(a[1], a[2]); - index.AttachChild(a[2], a[3]); - index.AttachChild(a[2], a[4]); - index.AttachChild(a[1], a[6]); - index.AttachChild(a[0], a[5]); - index.AttachChild(a[5], a[7]); - - { - Json::Value j; - index.GetChildren(j, a[0]); - ASSERT_EQ(2u, j.size()); - ASSERT_TRUE((j[0u] == "b" && j[1u] == "f") || - (j[1u] == "b" && j[0u] == "f")); - - index.GetChildren(j, a[1]); - ASSERT_EQ(2u, j.size()); - ASSERT_TRUE((j[0u] == "c" && j[1u] == "g") || - (j[1u] == "c" && j[0u] == "g")); - - index.GetChildren(j, a[2]); - ASSERT_EQ(2u, j.size()); - ASSERT_TRUE((j[0u] == "d" && j[1u] == "e") || - (j[1u] == "d" && j[0u] == "e")); - - index.GetChildren(j, a[3]); ASSERT_EQ(0u, j.size()); - index.GetChildren(j, a[4]); ASSERT_EQ(0u, j.size()); - index.GetChildren(j, a[5]); ASSERT_EQ(1u, j.size()); ASSERT_EQ("h", j[0u].asString()); - index.GetChildren(j, a[6]); ASSERT_EQ(0u, j.size()); - index.GetChildren(j, a[7]); ASSERT_EQ(0u, j.size()); - } - - listener.Reset(); - index.DeleteResource(a[3]); - ASSERT_EQ("c", listener.ancestorId_); - ASSERT_EQ(ResourceType_Series, listener.ancestorType_); - - listener.Reset(); - index.DeleteResource(a[4]); - ASSERT_EQ("b", listener.ancestorId_); - ASSERT_EQ(ResourceType_Study, listener.ancestorType_); - - listener.Reset(); - index.DeleteResource(a[7]); - ASSERT_EQ("a", listener.ancestorId_); - ASSERT_EQ(ResourceType_Patient, listener.ancestorType_); - - listener.Reset(); - index.DeleteResource(a[6]); - ASSERT_EQ("", listener.ancestorId_); // No more ancestor -} - - -TEST(DatabaseWrapper, PatientRecycling) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - std::vector patients; - for (int i = 0; i < 10; i++) - { - std::string p = "Patient " + boost::lexical_cast(i); - patients.push_back(index.CreateResource(p, ResourceType_Patient)); - index.AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, - "md5-" + boost::lexical_cast(i))); - ASSERT_FALSE(index.IsProtectedPatient(patients[i])); - } - - ASSERT_EQ(10u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(10u, index.GetTableRecordCount("PatientRecyclingOrder")); - - listener.Reset(); - - index.DeleteResource(patients[5]); - index.DeleteResource(patients[0]); - ASSERT_EQ(8u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(8u, index.GetTableRecordCount("PatientRecyclingOrder")); - - ASSERT_EQ(2u, listener.deletedFiles_.size()); - ASSERT_EQ("Patient 5", listener.deletedFiles_[0]); - ASSERT_EQ("Patient 0", listener.deletedFiles_[1]); - - int64_t p; - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[6]); - index.DeleteResource(p); - index.DeleteResource(patients[8]); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[7]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[9]); - index.DeleteResource(p); - ASSERT_FALSE(index.SelectPatientToRecycle(p)); - - ASSERT_EQ(10u, listener.deletedFiles_.size()); - ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); -} - - -TEST(DatabaseWrapper, PatientProtection) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - std::vector patients; - for (int i = 0; i < 5; i++) - { - std::string p = "Patient " + boost::lexical_cast(i); - patients.push_back(index.CreateResource(p, ResourceType_Patient)); - index.AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, - "md5-" + boost::lexical_cast(i))); - ASSERT_FALSE(index.IsProtectedPatient(patients[i])); - } - - ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); - - ASSERT_FALSE(index.IsProtectedPatient(patients[2])); - index.SetProtectedPatient(patients[2], true); - ASSERT_TRUE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); - ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); - - index.SetProtectedPatient(patients[2], true); - ASSERT_TRUE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); - index.SetProtectedPatient(patients[2], false); - ASSERT_FALSE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); - index.SetProtectedPatient(patients[2], false); - ASSERT_FALSE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); - - ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); - index.SetProtectedPatient(patients[2], true); - ASSERT_TRUE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); - index.SetProtectedPatient(patients[2], false); - ASSERT_FALSE(index.IsProtectedPatient(patients[2])); - ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); - index.SetProtectedPatient(patients[3], true); - ASSERT_TRUE(index.IsProtectedPatient(patients[3])); - ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); - - ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, listener.deletedFiles_.size()); - - // Unprotecting a patient puts it at the last position in the recycling queue - int64_t p; - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[0]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[1])); ASSERT_EQ(p, patients[4]); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); - index.DeleteResource(p); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); - index.DeleteResource(p); - ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[2])); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); - index.DeleteResource(p); - // "patients[3]" is still protected - ASSERT_FALSE(index.SelectPatientToRecycle(p)); - - ASSERT_EQ(4u, listener.deletedFiles_.size()); - ASSERT_EQ(1u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); - - index.SetProtectedPatient(patients[3], false); - ASSERT_EQ(1u, index.GetTableRecordCount("PatientRecyclingOrder")); - ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[3])); - ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[2])); - ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); - index.DeleteResource(p); - - ASSERT_EQ(5u, listener.deletedFiles_.size()); - ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); - ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); -} - - - -TEST(DatabaseWrapper, Sequence) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - ASSERT_EQ(1u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); - ASSERT_EQ(2u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); - ASSERT_EQ(3u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); - ASSERT_EQ(4u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); -} - - - -TEST(DatabaseWrapper, LookupTagValue) -{ - ServerIndexListener listener; - DatabaseWrapper index(listener); - - int64_t a[] = { - index.CreateResource("a", ResourceType_Study), // 0 - index.CreateResource("b", ResourceType_Study), // 1 - index.CreateResource("c", ResourceType_Study), // 2 - index.CreateResource("d", ResourceType_Series) // 3 - }; - - DicomMap m; - m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "0"); index.SetMainDicomTags(a[0], m); - m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1"); index.SetMainDicomTags(a[1], m); - m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "0"); index.SetMainDicomTags(a[2], m); - m.Clear(); m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "0"); index.SetMainDicomTags(a[3], m); - - std::list s; - - index.LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "0"); - ASSERT_EQ(2u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end()); - - index.LookupTagValue(s, "0"); - ASSERT_EQ(3u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[3]) != s.end()); - - index.LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1"); - ASSERT_EQ(1u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); - - index.LookupTagValue(s, "1"); - ASSERT_EQ(1u, s.size()); - ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); - - - /*{ - std::list s; - context.GetIndex().LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1.2.250.1.74.20130819132500.29000036381059"); - for (std::list::iterator i = s.begin(); i != s.end(); i++) - { - std::cout << "*** " << *i << std::endl;; - } - }*/ -} - - - -TEST(ServerIndex, AttachmentRecycling) -{ - const std::string path = "OrthancStorageUnitTests"; - Toolbox::RemoveFile(path + "/index"); - ServerContext context(path, ":memory:"); // The SQLite DB is in memory - ServerIndex& index = context.GetIndex(); - - index.SetMaximumStorageSize(10); - - Json::Value tmp; - index.ComputeStatistics(tmp); - ASSERT_EQ(0, tmp["CountPatients"].asInt()); - ASSERT_EQ(0, boost::lexical_cast(tmp["TotalDiskSize"].asString())); - - ServerIndex::Attachments attachments; - - std::vector ids; - for (int i = 0; i < 10; i++) - { - std::string id = boost::lexical_cast(i); - DicomMap instance; - instance.SetValue(DICOM_TAG_PATIENT_ID, "patient-" + id); - instance.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "study-" + id); - instance.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "series-" + id); - instance.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "instance-" + id); - ASSERT_EQ(StoreStatus_Success, index.Store(instance, attachments, "")); - - DicomInstanceHasher hasher(instance); - ids.push_back(hasher.HashPatient()); - ids.push_back(hasher.HashStudy()); - ids.push_back(hasher.HashSeries()); - ids.push_back(hasher.HashInstance()); - } - - index.ComputeStatistics(tmp); - ASSERT_EQ(10, tmp["CountPatients"].asInt()); - ASSERT_EQ(0, boost::lexical_cast(tmp["TotalDiskSize"].asString())); - - for (size_t i = 0; i < ids.size(); i++) - { - FileInfo info(Toolbox::GenerateUuid(), FileContentType_Dicom, 1, "md5"); - index.AddAttachment(info, ids[i]); - - index.ComputeStatistics(tmp); - ASSERT_GE(10, boost::lexical_cast(tmp["TotalDiskSize"].asString())); - } - - // Because the DB is in memory, the SQLite index must not have been created - ASSERT_THROW(Toolbox::GetFileSize(path + "/index"), OrthancException); -} diff -r ef4569ae7952 -r edffcf3ce7ab UnitTestsSources/ServerIndexTests.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/ServerIndexTests.cpp Wed Feb 19 12:39:17 2014 +0100 @@ -0,0 +1,556 @@ +#include "gtest/gtest.h" + +#include "../OrthancServer/DatabaseWrapper.h" +#include "../OrthancServer/ServerContext.h" +#include "../OrthancServer/ServerIndex.h" +#include "../Core/Uuid.h" +#include "../Core/DicomFormat/DicomNullValue.h" + +#include +#include +#include + +using namespace Orthanc; + +namespace +{ + class ServerIndexListener : public IServerIndexListener + { + public: + std::vector deletedFiles_; + std::string ancestorId_; + ResourceType ancestorType_; + + void Reset() + { + ancestorId_ = ""; + deletedFiles_.clear(); + } + + virtual void SignalRemainingAncestor(ResourceType type, + const std::string& publicId) + { + ancestorId_ = publicId; + ancestorType_ = type; + } + + virtual void SignalFileDeleted(const FileInfo& info) + { + const std::string fileUuid = info.GetUuid(); + deletedFiles_.push_back(fileUuid); + LOG(INFO) << "A file must be removed: " << fileUuid; + } + }; +} + + +TEST(DatabaseWrapper, Simple) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + int64_t a[] = { + index.CreateResource("a", ResourceType_Patient), // 0 + index.CreateResource("b", ResourceType_Study), // 1 + index.CreateResource("c", ResourceType_Series), // 2 + index.CreateResource("d", ResourceType_Instance), // 3 + index.CreateResource("e", ResourceType_Instance), // 4 + index.CreateResource("f", ResourceType_Instance), // 5 + index.CreateResource("g", ResourceType_Study) // 6 + }; + + ASSERT_EQ("a", index.GetPublicId(a[0])); + ASSERT_EQ("b", index.GetPublicId(a[1])); + ASSERT_EQ("c", index.GetPublicId(a[2])); + ASSERT_EQ("d", index.GetPublicId(a[3])); + ASSERT_EQ("e", index.GetPublicId(a[4])); + ASSERT_EQ("f", index.GetPublicId(a[5])); + ASSERT_EQ("g", index.GetPublicId(a[6])); + + ASSERT_EQ(ResourceType_Patient, index.GetResourceType(a[0])); + ASSERT_EQ(ResourceType_Study, index.GetResourceType(a[1])); + ASSERT_EQ(ResourceType_Series, index.GetResourceType(a[2])); + ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[3])); + ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[4])); + ASSERT_EQ(ResourceType_Instance, index.GetResourceType(a[5])); + ASSERT_EQ(ResourceType_Study, index.GetResourceType(a[6])); + + { + Json::Value t; + index.GetAllPublicIds(t, ResourceType_Patient); + + ASSERT_EQ(1u, t.size()); + ASSERT_EQ("a", t[0u].asString()); + + index.GetAllPublicIds(t, ResourceType_Series); + ASSERT_EQ(1u, t.size()); + ASSERT_EQ("c", t[0u].asString()); + + index.GetAllPublicIds(t, ResourceType_Study); + ASSERT_EQ(2u, t.size()); + + index.GetAllPublicIds(t, ResourceType_Instance); + ASSERT_EQ(3u, t.size()); + } + + index.SetGlobalProperty(GlobalProperty_FlushSleep, "World"); + + index.AttachChild(a[0], a[1]); + index.AttachChild(a[1], a[2]); + index.AttachChild(a[2], a[3]); + index.AttachChild(a[2], a[4]); + index.AttachChild(a[6], a[5]); + + int64_t parent; + ASSERT_FALSE(index.LookupParent(parent, a[0])); + ASSERT_TRUE(index.LookupParent(parent, a[1])); ASSERT_EQ(a[0], parent); + ASSERT_TRUE(index.LookupParent(parent, a[2])); ASSERT_EQ(a[1], parent); + ASSERT_TRUE(index.LookupParent(parent, a[3])); ASSERT_EQ(a[2], parent); + ASSERT_TRUE(index.LookupParent(parent, a[4])); ASSERT_EQ(a[2], parent); + ASSERT_TRUE(index.LookupParent(parent, a[5])); ASSERT_EQ(a[6], parent); + ASSERT_FALSE(index.LookupParent(parent, a[6])); + + std::string s; + + ASSERT_FALSE(index.GetParentPublicId(s, a[0])); + ASSERT_FALSE(index.GetParentPublicId(s, a[6])); + ASSERT_TRUE(index.GetParentPublicId(s, a[1])); ASSERT_EQ("a", s); + ASSERT_TRUE(index.GetParentPublicId(s, a[2])); ASSERT_EQ("b", s); + ASSERT_TRUE(index.GetParentPublicId(s, a[3])); ASSERT_EQ("c", s); + ASSERT_TRUE(index.GetParentPublicId(s, a[4])); ASSERT_EQ("c", s); + ASSERT_TRUE(index.GetParentPublicId(s, a[5])); ASSERT_EQ("g", s); + + std::list l; + index.GetChildrenPublicId(l, a[0]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("b", l.front()); + index.GetChildrenPublicId(l, a[1]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("c", l.front()); + index.GetChildrenPublicId(l, a[3]); ASSERT_EQ(0u, l.size()); + index.GetChildrenPublicId(l, a[4]); ASSERT_EQ(0u, l.size()); + index.GetChildrenPublicId(l, a[5]); ASSERT_EQ(0u, l.size()); + index.GetChildrenPublicId(l, a[6]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("f", l.front()); + + index.GetChildrenPublicId(l, a[2]); ASSERT_EQ(2u, l.size()); + if (l.front() == "d") + { + ASSERT_EQ("e", l.back()); + } + else + { + ASSERT_EQ("d", l.back()); + ASSERT_EQ("e", l.front()); + } + + std::list md; + index.ListAvailableMetadata(md, a[4]); + ASSERT_EQ(0u, md.size()); + + index.AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", + CompressionType_Zlib, 21, "compressedMD5")); + index.AddAttachment(a[4], FileInfo("my dicom file", FileContentType_Dicom, 42, "md5")); + index.AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5")); + index.SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE"); + + index.ListAvailableMetadata(md, a[4]); + ASSERT_EQ(1u, md.size()); + ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); + index.SetMetadata(a[4], MetadataType_ModifiedFrom, "TUTU"); + index.ListAvailableMetadata(md, a[4]); + ASSERT_EQ(2u, md.size()); + index.DeleteMetadata(a[4], MetadataType_ModifiedFrom); + index.ListAvailableMetadata(md, a[4]); + ASSERT_EQ(1u, md.size()); + ASSERT_EQ(MetadataType_Instance_RemoteAet, md.front()); + + ASSERT_EQ(21u + 42u + 44u, index.GetTotalCompressedSize()); + ASSERT_EQ(42u + 42u + 44u, index.GetTotalUncompressedSize()); + + DicomMap m; + m.SetValue(0x0010, 0x0010, "PatientName"); + index.SetMainDicomTags(a[3], m); + + int64_t b; + ResourceType t; + ASSERT_TRUE(index.LookupResource("g", b, t)); + ASSERT_EQ(7, b); + ASSERT_EQ(ResourceType_Study, t); + + ASSERT_TRUE(index.LookupMetadata(s, a[4], MetadataType_Instance_RemoteAet)); + ASSERT_FALSE(index.LookupMetadata(s, a[4], MetadataType_Instance_IndexInSeries)); + ASSERT_EQ("PINNACLE", s); + ASSERT_EQ("PINNACLE", index.GetMetadata(a[4], MetadataType_Instance_RemoteAet)); + ASSERT_EQ("None", index.GetMetadata(a[4], MetadataType_Instance_IndexInSeries, "None")); + + ASSERT_TRUE(index.LookupGlobalProperty(s, GlobalProperty_FlushSleep)); + ASSERT_FALSE(index.LookupGlobalProperty(s, static_cast(42))); + ASSERT_EQ("World", s); + ASSERT_EQ("World", index.GetGlobalProperty(GlobalProperty_FlushSleep)); + ASSERT_EQ("None", index.GetGlobalProperty(static_cast(42), "None")); + + FileInfo att; + ASSERT_TRUE(index.LookupAttachment(att, a[4], FileContentType_DicomAsJson)); + ASSERT_EQ("my json file", att.GetUuid()); + ASSERT_EQ(21u, att.GetCompressedSize()); + ASSERT_EQ("md5", att.GetUncompressedMD5()); + ASSERT_EQ("compressedMD5", att.GetCompressedMD5()); + ASSERT_EQ(42u, att.GetUncompressedSize()); + ASSERT_EQ(CompressionType_Zlib, att.GetCompressionType()); + + ASSERT_TRUE(index.LookupAttachment(att, a[6], FileContentType_Dicom)); + ASSERT_EQ("world", att.GetUuid()); + ASSERT_EQ(44u, att.GetCompressedSize()); + ASSERT_EQ("md5", att.GetUncompressedMD5()); + ASSERT_EQ("md5", att.GetCompressedMD5()); + ASSERT_EQ(44u, att.GetUncompressedSize()); + ASSERT_EQ(CompressionType_None, att.GetCompressionType()); + + ASSERT_EQ(0u, listener.deletedFiles_.size()); + ASSERT_EQ(7u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(3u, index.GetTableRecordCount("AttachedFiles")); + ASSERT_EQ(1u, index.GetTableRecordCount("Metadata")); + ASSERT_EQ(1u, index.GetTableRecordCount("MainDicomTags")); + index.DeleteResource(a[0]); + + ASSERT_EQ(2u, listener.deletedFiles_.size()); + ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), + listener.deletedFiles_.end(), + "my json file") == listener.deletedFiles_.end()); + ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), + listener.deletedFiles_.end(), + "my dicom file") == listener.deletedFiles_.end()); + + ASSERT_EQ(2u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, index.GetTableRecordCount("Metadata")); + ASSERT_EQ(1u, index.GetTableRecordCount("AttachedFiles")); + ASSERT_EQ(0u, index.GetTableRecordCount("MainDicomTags")); + index.DeleteResource(a[5]); + ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, index.GetTableRecordCount("AttachedFiles")); + ASSERT_EQ(2u, index.GetTableRecordCount("GlobalProperties")); + + ASSERT_EQ(3u, listener.deletedFiles_.size()); + ASSERT_FALSE(std::find(listener.deletedFiles_.begin(), + listener.deletedFiles_.end(), + "world") == listener.deletedFiles_.end()); +} + + + + +TEST(DatabaseWrapper, Upward) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + int64_t a[] = { + index.CreateResource("a", ResourceType_Patient), // 0 + index.CreateResource("b", ResourceType_Study), // 1 + index.CreateResource("c", ResourceType_Series), // 2 + index.CreateResource("d", ResourceType_Instance), // 3 + index.CreateResource("e", ResourceType_Instance), // 4 + index.CreateResource("f", ResourceType_Study), // 5 + index.CreateResource("g", ResourceType_Series), // 6 + index.CreateResource("h", ResourceType_Series) // 7 + }; + + index.AttachChild(a[0], a[1]); + index.AttachChild(a[1], a[2]); + index.AttachChild(a[2], a[3]); + index.AttachChild(a[2], a[4]); + index.AttachChild(a[1], a[6]); + index.AttachChild(a[0], a[5]); + index.AttachChild(a[5], a[7]); + + { + Json::Value j; + index.GetChildren(j, a[0]); + ASSERT_EQ(2u, j.size()); + ASSERT_TRUE((j[0u] == "b" && j[1u] == "f") || + (j[1u] == "b" && j[0u] == "f")); + + index.GetChildren(j, a[1]); + ASSERT_EQ(2u, j.size()); + ASSERT_TRUE((j[0u] == "c" && j[1u] == "g") || + (j[1u] == "c" && j[0u] == "g")); + + index.GetChildren(j, a[2]); + ASSERT_EQ(2u, j.size()); + ASSERT_TRUE((j[0u] == "d" && j[1u] == "e") || + (j[1u] == "d" && j[0u] == "e")); + + index.GetChildren(j, a[3]); ASSERT_EQ(0u, j.size()); + index.GetChildren(j, a[4]); ASSERT_EQ(0u, j.size()); + index.GetChildren(j, a[5]); ASSERT_EQ(1u, j.size()); ASSERT_EQ("h", j[0u].asString()); + index.GetChildren(j, a[6]); ASSERT_EQ(0u, j.size()); + index.GetChildren(j, a[7]); ASSERT_EQ(0u, j.size()); + } + + listener.Reset(); + index.DeleteResource(a[3]); + ASSERT_EQ("c", listener.ancestorId_); + ASSERT_EQ(ResourceType_Series, listener.ancestorType_); + + listener.Reset(); + index.DeleteResource(a[4]); + ASSERT_EQ("b", listener.ancestorId_); + ASSERT_EQ(ResourceType_Study, listener.ancestorType_); + + listener.Reset(); + index.DeleteResource(a[7]); + ASSERT_EQ("a", listener.ancestorId_); + ASSERT_EQ(ResourceType_Patient, listener.ancestorType_); + + listener.Reset(); + index.DeleteResource(a[6]); + ASSERT_EQ("", listener.ancestorId_); // No more ancestor +} + + +TEST(DatabaseWrapper, PatientRecycling) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + std::vector patients; + for (int i = 0; i < 10; i++) + { + std::string p = "Patient " + boost::lexical_cast(i); + patients.push_back(index.CreateResource(p, ResourceType_Patient)); + index.AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, + "md5-" + boost::lexical_cast(i))); + ASSERT_FALSE(index.IsProtectedPatient(patients[i])); + } + + ASSERT_EQ(10u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(10u, index.GetTableRecordCount("PatientRecyclingOrder")); + + listener.Reset(); + + index.DeleteResource(patients[5]); + index.DeleteResource(patients[0]); + ASSERT_EQ(8u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(8u, index.GetTableRecordCount("PatientRecyclingOrder")); + + ASSERT_EQ(2u, listener.deletedFiles_.size()); + ASSERT_EQ("Patient 5", listener.deletedFiles_[0]); + ASSERT_EQ("Patient 0", listener.deletedFiles_[1]); + + int64_t p; + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[6]); + index.DeleteResource(p); + index.DeleteResource(patients[8]); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[7]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[9]); + index.DeleteResource(p); + ASSERT_FALSE(index.SelectPatientToRecycle(p)); + + ASSERT_EQ(10u, listener.deletedFiles_.size()); + ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); +} + + +TEST(DatabaseWrapper, PatientProtection) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + std::vector patients; + for (int i = 0; i < 5; i++) + { + std::string p = "Patient " + boost::lexical_cast(i); + patients.push_back(index.CreateResource(p, ResourceType_Patient)); + index.AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, + "md5-" + boost::lexical_cast(i))); + ASSERT_FALSE(index.IsProtectedPatient(patients[i])); + } + + ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); + + ASSERT_FALSE(index.IsProtectedPatient(patients[2])); + index.SetProtectedPatient(patients[2], true); + ASSERT_TRUE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); + ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); + + index.SetProtectedPatient(patients[2], true); + ASSERT_TRUE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); + index.SetProtectedPatient(patients[2], false); + ASSERT_FALSE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); + index.SetProtectedPatient(patients[2], false); + ASSERT_FALSE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); + + ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); + index.SetProtectedPatient(patients[2], true); + ASSERT_TRUE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); + index.SetProtectedPatient(patients[2], false); + ASSERT_FALSE(index.IsProtectedPatient(patients[2])); + ASSERT_EQ(5u, index.GetTableRecordCount("PatientRecyclingOrder")); + index.SetProtectedPatient(patients[3], true); + ASSERT_TRUE(index.IsProtectedPatient(patients[3])); + ASSERT_EQ(4u, index.GetTableRecordCount("PatientRecyclingOrder")); + + ASSERT_EQ(5u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, listener.deletedFiles_.size()); + + // Unprotecting a patient puts it at the last position in the recycling queue + int64_t p; + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[0]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[1])); ASSERT_EQ(p, patients[4]); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); + index.DeleteResource(p); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); + index.DeleteResource(p); + ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[2])); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); + index.DeleteResource(p); + // "patients[3]" is still protected + ASSERT_FALSE(index.SelectPatientToRecycle(p)); + + ASSERT_EQ(4u, listener.deletedFiles_.size()); + ASSERT_EQ(1u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); + + index.SetProtectedPatient(patients[3], false); + ASSERT_EQ(1u, index.GetTableRecordCount("PatientRecyclingOrder")); + ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[3])); + ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[2])); + ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); + index.DeleteResource(p); + + ASSERT_EQ(5u, listener.deletedFiles_.size()); + ASSERT_EQ(0u, index.GetTableRecordCount("Resources")); + ASSERT_EQ(0u, index.GetTableRecordCount("PatientRecyclingOrder")); +} + + + +TEST(DatabaseWrapper, Sequence) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + ASSERT_EQ(1u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(2u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(3u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); + ASSERT_EQ(4u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); +} + + + +TEST(DatabaseWrapper, LookupTagValue) +{ + ServerIndexListener listener; + DatabaseWrapper index(listener); + + int64_t a[] = { + index.CreateResource("a", ResourceType_Study), // 0 + index.CreateResource("b", ResourceType_Study), // 1 + index.CreateResource("c", ResourceType_Study), // 2 + index.CreateResource("d", ResourceType_Series) // 3 + }; + + DicomMap m; + m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "0"); index.SetMainDicomTags(a[0], m); + m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1"); index.SetMainDicomTags(a[1], m); + m.Clear(); m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "0"); index.SetMainDicomTags(a[2], m); + m.Clear(); m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "0"); index.SetMainDicomTags(a[3], m); + + std::list s; + + index.LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "0"); + ASSERT_EQ(2u, s.size()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end()); + + index.LookupTagValue(s, "0"); + ASSERT_EQ(3u, s.size()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[0]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[2]) != s.end()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[3]) != s.end()); + + index.LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1"); + ASSERT_EQ(1u, s.size()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); + + index.LookupTagValue(s, "1"); + ASSERT_EQ(1u, s.size()); + ASSERT_TRUE(std::find(s.begin(), s.end(), a[1]) != s.end()); + + + /*{ + std::list s; + context.GetIndex().LookupTagValue(s, DICOM_TAG_STUDY_INSTANCE_UID, "1.2.250.1.74.20130819132500.29000036381059"); + for (std::list::iterator i = s.begin(); i != s.end(); i++) + { + std::cout << "*** " << *i << std::endl;; + } + }*/ +} + + + +TEST(ServerIndex, AttachmentRecycling) +{ + const std::string path = "OrthancStorageUnitTests"; + Toolbox::RemoveFile(path + "/index"); + ServerContext context(path, ":memory:"); // The SQLite DB is in memory + ServerIndex& index = context.GetIndex(); + + index.SetMaximumStorageSize(10); + + Json::Value tmp; + index.ComputeStatistics(tmp); + ASSERT_EQ(0, tmp["CountPatients"].asInt()); + ASSERT_EQ(0, boost::lexical_cast(tmp["TotalDiskSize"].asString())); + + ServerIndex::Attachments attachments; + + std::vector ids; + for (int i = 0; i < 10; i++) + { + std::string id = boost::lexical_cast(i); + DicomMap instance; + instance.SetValue(DICOM_TAG_PATIENT_ID, "patient-" + id); + instance.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "study-" + id); + instance.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "series-" + id); + instance.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "instance-" + id); + ASSERT_EQ(StoreStatus_Success, index.Store(instance, attachments, "")); + + DicomInstanceHasher hasher(instance); + ids.push_back(hasher.HashPatient()); + ids.push_back(hasher.HashStudy()); + ids.push_back(hasher.HashSeries()); + ids.push_back(hasher.HashInstance()); + } + + index.ComputeStatistics(tmp); + ASSERT_EQ(10, tmp["CountPatients"].asInt()); + ASSERT_EQ(0, boost::lexical_cast(tmp["TotalDiskSize"].asString())); + + for (size_t i = 0; i < ids.size(); i++) + { + FileInfo info(Toolbox::GenerateUuid(), FileContentType_Dicom, 1, "md5"); + index.AddAttachment(info, ids[i]); + + index.ComputeStatistics(tmp); + ASSERT_GE(10, boost::lexical_cast(tmp["TotalDiskSize"].asString())); + } + + // Because the DB is in memory, the SQLite index must not have been created + ASSERT_THROW(Toolbox::GetFileSize(path + "/index"), OrthancException); +} diff -r ef4569ae7952 -r edffcf3ce7ab UnitTestsSources/UnitTestsMain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/UnitTestsMain.cpp Wed Feb 19 12:39:17 2014 +0100 @@ -0,0 +1,610 @@ +#include "../Core/EnumerationDictionary.h" + +#include "gtest/gtest.h" + +#include + +#include "../Core/Compression/ZlibCompressor.h" +#include "../Core/DicomFormat/DicomTag.h" +#include "../Core/HttpServer/HttpHandler.h" +#include "../Core/OrthancException.h" +#include "../Core/Toolbox.h" +#include "../Core/Uuid.h" +#include "../OrthancServer/FromDcmtkBridge.h" +#include "../OrthancServer/OrthancInitialization.h" + +using namespace Orthanc; + + +TEST(Uuid, Generation) +{ + for (int i = 0; i < 10; i++) + { + std::string s = Toolbox::GenerateUuid(); + ASSERT_TRUE(Toolbox::IsUuid(s)); + } +} + +TEST(Uuid, Test) +{ + ASSERT_FALSE(Toolbox::IsUuid("")); + ASSERT_FALSE(Toolbox::IsUuid("012345678901234567890123456789012345")); + ASSERT_TRUE(Toolbox::IsUuid("550e8400-e29b-41d4-a716-446655440000")); + ASSERT_FALSE(Toolbox::IsUuid("550e8400-e29b-41d4-a716-44665544000_")); + ASSERT_FALSE(Toolbox::IsUuid("01234567890123456789012345678901234_")); + ASSERT_FALSE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-44665544000")); + ASSERT_TRUE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000")); + ASSERT_TRUE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000 ok")); + ASSERT_FALSE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000ok")); +} + +TEST(Toolbox, IsSHA1) +{ + ASSERT_FALSE(Toolbox::IsSHA1("")); + ASSERT_FALSE(Toolbox::IsSHA1("01234567890123456789012345678901234567890123")); + ASSERT_FALSE(Toolbox::IsSHA1("012345678901234567890123456789012345678901234")); + ASSERT_TRUE(Toolbox::IsSHA1("b5ed549f-956400ce-69a8c063-bf5b78be-2732a4b9")); + + std::string s; + Toolbox::ComputeSHA1(s, "The quick brown fox jumps over the lazy dog"); + ASSERT_TRUE(Toolbox::IsSHA1(s)); + ASSERT_EQ("2fd4e1c6-7a2d28fc-ed849ee1-bb76e739-1b93eb12", s); + + ASSERT_FALSE(Toolbox::IsSHA1("b5ed549f-956400ce-69a8c063-bf5b78be-2732a4b_")); +} + +static void StringToVector(std::vector& v, + const std::string& s) +{ + v.resize(s.size()); + for (size_t i = 0; i < s.size(); i++) + v[i] = s[i]; +} + + +TEST(Zlib, Basic) +{ + std::string s = Toolbox::GenerateUuid(); + s = s + s + s + s; + + std::string compressed, compressed2; + ZlibCompressor c; + c.Compress(compressed, s); + + std::vector v, vv; + StringToVector(v, s); + c.Compress(compressed2, v); + ASSERT_EQ(compressed, compressed2); + + std::string uncompressed; + c.Uncompress(uncompressed, compressed); + ASSERT_EQ(s.size(), uncompressed.size()); + ASSERT_EQ(0, memcmp(&s[0], &uncompressed[0], s.size())); + + StringToVector(vv, compressed); + c.Uncompress(uncompressed, vv); + ASSERT_EQ(s.size(), uncompressed.size()); + ASSERT_EQ(0, memcmp(&s[0], &uncompressed[0], s.size())); +} + + +TEST(Zlib, Level) +{ + std::string s = Toolbox::GenerateUuid(); + s = s + s + s + s; + + std::string compressed, compressed2; + ZlibCompressor c; + c.SetCompressionLevel(9); + c.Compress(compressed, s); + + c.SetCompressionLevel(0); + c.Compress(compressed2, s); + + ASSERT_TRUE(compressed.size() < compressed2.size()); +} + + +TEST(Zlib, Corrupted) +{ + std::string s = Toolbox::GenerateUuid(); + s = s + s + s + s; + + std::string compressed; + ZlibCompressor c; + c.Compress(compressed, s); + + compressed[compressed.size() - 1] = 'a'; + std::string u; + + ASSERT_THROW(c.Uncompress(u, compressed), OrthancException); +} + + +TEST(Zlib, Empty) +{ + std::string s = ""; + std::vector v, vv; + + std::string compressed, compressed2; + ZlibCompressor c; + c.Compress(compressed, s); + c.Compress(compressed2, v); + ASSERT_EQ(compressed, compressed2); + + std::string uncompressed; + c.Uncompress(uncompressed, compressed); + ASSERT_EQ(0u, uncompressed.size()); + + StringToVector(vv, compressed); + c.Uncompress(uncompressed, vv); + ASSERT_EQ(0u, uncompressed.size()); +} + + +TEST(ParseGetQuery, Basic) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa=baaa&bb=a&aa=c"); + ASSERT_EQ(3u, a.size()); + ASSERT_EQ(a["aaa"], "baaa"); + ASSERT_EQ(a["bb"], "a"); + ASSERT_EQ(a["aa"], "c"); +} + +TEST(ParseGetQuery, BasicEmpty) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa&bb=aa&aa"); + ASSERT_EQ(3u, a.size()); + ASSERT_EQ(a["aaa"], ""); + ASSERT_EQ(a["bb"], "aa"); + ASSERT_EQ(a["aa"], ""); +} + +TEST(ParseGetQuery, Single) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa=baaa"); + ASSERT_EQ(1u, a.size()); + ASSERT_EQ(a["aaa"], "baaa"); +} + +TEST(ParseGetQuery, SingleEmpty) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa"); + ASSERT_EQ(1u, a.size()); + ASSERT_EQ(a["aaa"], ""); +} + +TEST(DicomFormat, Tag) +{ + ASSERT_EQ("PatientName", FromDcmtkBridge::GetName(DicomTag(0x0010, 0x0010))); + + DicomTag t = FromDcmtkBridge::ParseTag("SeriesDescription"); + ASSERT_EQ(0x0008, t.GetGroup()); + ASSERT_EQ(0x103E, t.GetElement()); + + t = FromDcmtkBridge::ParseTag("0020-e040"); + ASSERT_EQ(0x0020, t.GetGroup()); + ASSERT_EQ(0xe040, t.GetElement()); + + // Test ==() and !=() operators + ASSERT_TRUE(DICOM_TAG_PATIENT_ID == DicomTag(0x0010, 0x0020)); + ASSERT_FALSE(DICOM_TAG_PATIENT_ID != DicomTag(0x0010, 0x0020)); +} + + +TEST(Uri, SplitUriComponents) +{ + UriComponents c; + Toolbox::SplitUriComponents(c, "/cou/hello/world"); + ASSERT_EQ(3u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + + Toolbox::SplitUriComponents(c, "/cou/hello/world/"); + ASSERT_EQ(3u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + + Toolbox::SplitUriComponents(c, "/cou/hello/world/a"); + ASSERT_EQ(4u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + ASSERT_EQ("a", c[3]); + + Toolbox::SplitUriComponents(c, "/"); + ASSERT_EQ(0u, c.size()); + + Toolbox::SplitUriComponents(c, "/hello"); + ASSERT_EQ(1u, c.size()); + ASSERT_EQ("hello", c[0]); + + Toolbox::SplitUriComponents(c, "/hello/"); + ASSERT_EQ(1u, c.size()); + ASSERT_EQ("hello", c[0]); + + ASSERT_THROW(Toolbox::SplitUriComponents(c, ""), OrthancException); + ASSERT_THROW(Toolbox::SplitUriComponents(c, "a"), OrthancException); + ASSERT_THROW(Toolbox::SplitUriComponents(c, "/coucou//coucou"), OrthancException); + + c.clear(); + c.push_back("test"); + ASSERT_EQ("/", Toolbox::FlattenUri(c, 10)); +} + + +TEST(Uri, Child) +{ + UriComponents c1; Toolbox::SplitUriComponents(c1, "/hello/world"); + UriComponents c2; Toolbox::SplitUriComponents(c2, "/hello/hello"); + UriComponents c3; Toolbox::SplitUriComponents(c3, "/hello"); + UriComponents c4; Toolbox::SplitUriComponents(c4, "/world"); + UriComponents c5; Toolbox::SplitUriComponents(c5, "/"); + + ASSERT_TRUE(Toolbox::IsChildUri(c1, c1)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c5)); + + ASSERT_FALSE(Toolbox::IsChildUri(c2, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c2, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c5)); + + ASSERT_TRUE(Toolbox::IsChildUri(c3, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c3, c2)); + ASSERT_TRUE(Toolbox::IsChildUri(c3, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c3, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c3, c5)); + + ASSERT_FALSE(Toolbox::IsChildUri(c4, c1)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c3)); + ASSERT_TRUE(Toolbox::IsChildUri(c4, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c5)); + + ASSERT_TRUE(Toolbox::IsChildUri(c5, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c2)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c3)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c4)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c5)); +} + +TEST(Uri, AutodetectMimeType) +{ + ASSERT_EQ("", Toolbox::AutodetectMimeType("../NOTES")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("/")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("a/a")); + + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../NOTES.txt")); + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../coucou.xml/NOTES.txt")); + ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("../.xml")); + + ASSERT_EQ("application/javascript", Toolbox::AutodetectMimeType("NOTES.js")); + ASSERT_EQ("application/json", Toolbox::AutodetectMimeType("NOTES.json")); + ASSERT_EQ("application/pdf", Toolbox::AutodetectMimeType("NOTES.pdf")); + ASSERT_EQ("text/css", Toolbox::AutodetectMimeType("NOTES.css")); + ASSERT_EQ("text/html", Toolbox::AutodetectMimeType("NOTES.html")); + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("NOTES.txt")); + ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("NOTES.xml")); + ASSERT_EQ("image/gif", Toolbox::AutodetectMimeType("NOTES.gif")); + ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpg")); + ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpeg")); + ASSERT_EQ("image/png", Toolbox::AutodetectMimeType("NOTES.png")); +} + +TEST(Toolbox, ComputeMD5) +{ + std::string s; + + // # echo -n "Hello" | md5sum + + Toolbox::ComputeMD5(s, "Hello"); + ASSERT_EQ("8b1a9953c4611296a827abf8c47804d7", s); + Toolbox::ComputeMD5(s, ""); + ASSERT_EQ("d41d8cd98f00b204e9800998ecf8427e", s); +} + +TEST(Toolbox, ComputeSHA1) +{ + std::string s; + + Toolbox::ComputeSHA1(s, "The quick brown fox jumps over the lazy dog"); + ASSERT_EQ("2fd4e1c6-7a2d28fc-ed849ee1-bb76e739-1b93eb12", s); + Toolbox::ComputeSHA1(s, ""); + ASSERT_EQ("da39a3ee-5e6b4b0d-3255bfef-95601890-afd80709", s); +} + + +TEST(Toolbox, Base64) +{ + ASSERT_EQ("", Toolbox::EncodeBase64("")); + ASSERT_EQ("YQ==", Toolbox::EncodeBase64("a")); + + const std::string hello = "SGVsbG8gd29ybGQ="; + ASSERT_EQ(hello, Toolbox::EncodeBase64("Hello world")); + ASSERT_EQ("Hello world", Toolbox::DecodeBase64(hello)); +} + +TEST(Toolbox, PathToExecutable) +{ + printf("[%s]\n", Toolbox::GetPathToExecutable().c_str()); + printf("[%s]\n", Toolbox::GetDirectoryOfExecutable().c_str()); +} + +TEST(Toolbox, StripSpaces) +{ + ASSERT_EQ("", Toolbox::StripSpaces(" \t \r \n ")); + ASSERT_EQ("coucou", Toolbox::StripSpaces(" coucou \t \r \n ")); + ASSERT_EQ("cou cou", Toolbox::StripSpaces(" cou cou \n ")); + ASSERT_EQ("c", Toolbox::StripSpaces(" \n\t c\r \n ")); +} + +TEST(Toolbox, Case) +{ + std::string s = "CoU"; + std::string ss; + + Toolbox::ToUpperCase(ss, s); + ASSERT_EQ("COU", ss); + Toolbox::ToLowerCase(ss, s); + ASSERT_EQ("cou", ss); + + s = "CoU"; + Toolbox::ToUpperCase(s); + ASSERT_EQ("COU", s); + + s = "CoU"; + Toolbox::ToLowerCase(s); + ASSERT_EQ("cou", s); +} + + +#include + +TEST(Logger, Basic) +{ + LOG(INFO) << "I say hello"; +} + +TEST(Toolbox, ConvertFromLatin1) +{ + // This is a Latin-1 test string + const unsigned char data[10] = { 0xe0, 0xe9, 0xea, 0xe7, 0x26, 0xc6, 0x61, 0x62, 0x63, 0x00 }; + + /*FILE* f = fopen("/tmp/tutu", "w"); + fwrite(&data[0], 9, 1, f); + fclose(f);*/ + + std::string s((char*) &data[0], 10); + ASSERT_EQ("&abc", Toolbox::ConvertToAscii(s)); + + // Open in Emacs, then save with UTF-8 encoding, then "hexdump -C" + std::string utf8 = Toolbox::ConvertToUtf8(s, "ISO-8859-1"); + ASSERT_EQ(15u, utf8.size()); + ASSERT_EQ(0xc3, static_cast(utf8[0])); + ASSERT_EQ(0xa0, static_cast(utf8[1])); + ASSERT_EQ(0xc3, static_cast(utf8[2])); + ASSERT_EQ(0xa9, static_cast(utf8[3])); + ASSERT_EQ(0xc3, static_cast(utf8[4])); + ASSERT_EQ(0xaa, static_cast(utf8[5])); + ASSERT_EQ(0xc3, static_cast(utf8[6])); + ASSERT_EQ(0xa7, static_cast(utf8[7])); + ASSERT_EQ(0x26, static_cast(utf8[8])); + ASSERT_EQ(0xc3, static_cast(utf8[9])); + ASSERT_EQ(0x86, static_cast(utf8[10])); + ASSERT_EQ(0x61, static_cast(utf8[11])); + ASSERT_EQ(0x62, static_cast(utf8[12])); + ASSERT_EQ(0x63, static_cast(utf8[13])); + ASSERT_EQ(0x00, static_cast(utf8[14])); // Null-terminated string +} + +TEST(Toolbox, UrlDecode) +{ + std::string s; + + s = "Hello%20World"; + Toolbox::UrlDecode(s); + ASSERT_EQ("Hello World", s); + + s = "%21%23%24%26%27%28%29%2A%2B%2c%2f%3A%3b%3d%3f%40%5B%5D%90%ff"; + Toolbox::UrlDecode(s); + std::string ss = "!#$&'()*+,/:;=?@[]"; + ss.push_back((char) 144); + ss.push_back((char) 255); + ASSERT_EQ(ss, s); + + s = "(2000%2C00A4)+Other"; + Toolbox::UrlDecode(s); + ASSERT_EQ("(2000,00A4) Other", s); +} + + +#if defined(__linux) +TEST(OrthancInitialization, AbsoluteDirectory) +{ + ASSERT_EQ("/tmp/hello", InterpretRelativePath("/tmp", "hello")); + ASSERT_EQ("/tmp", InterpretRelativePath("/tmp", "/tmp")); +} +#endif + + + +#include "../OrthancServer/ServerEnumerations.h" + +TEST(EnumerationDictionary, Simple) +{ + Toolbox::EnumerationDictionary d; + + ASSERT_THROW(d.Translate("ReceptionDate"), OrthancException); + ASSERT_EQ(MetadataType_ModifiedFrom, d.Translate("5")); + ASSERT_EQ(256, d.Translate("256")); + + d.Add(MetadataType_Instance_ReceptionDate, "ReceptionDate"); + + ASSERT_EQ(MetadataType_Instance_ReceptionDate, d.Translate("ReceptionDate")); + ASSERT_EQ(MetadataType_Instance_ReceptionDate, d.Translate("2")); + ASSERT_EQ("ReceptionDate", d.Translate(MetadataType_Instance_ReceptionDate)); + + ASSERT_THROW(d.Add(MetadataType_Instance_ReceptionDate, "Hello"), OrthancException); + ASSERT_THROW(d.Add(MetadataType_ModifiedFrom, "ReceptionDate"), OrthancException); // already used + ASSERT_THROW(d.Add(MetadataType_ModifiedFrom, "1024"), OrthancException); // cannot register numbers + d.Add(MetadataType_ModifiedFrom, "ModifiedFrom"); // ok +} + + +TEST(EnumerationDictionary, ServerEnumerations) +{ + ASSERT_STREQ("Patient", EnumerationToString(ResourceType_Patient)); + ASSERT_STREQ("Study", EnumerationToString(ResourceType_Study)); + ASSERT_STREQ("Series", EnumerationToString(ResourceType_Series)); + ASSERT_STREQ("Instance", EnumerationToString(ResourceType_Instance)); + + ASSERT_STREQ("ModifiedSeries", EnumerationToString(ChangeType_ModifiedSeries)); + + ASSERT_STREQ("Failure", EnumerationToString(StoreStatus_Failure)); + ASSERT_STREQ("Success", EnumerationToString(StoreStatus_Success)); + + ASSERT_STREQ("CompletedSeries", EnumerationToString(ChangeType_CompletedSeries)); + + ASSERT_EQ("IndexInSeries", EnumerationToString(MetadataType_Instance_IndexInSeries)); + ASSERT_EQ("LastUpdate", EnumerationToString(MetadataType_LastUpdate)); + + ASSERT_EQ(ResourceType_Patient, StringToResourceType("PATienT")); + ASSERT_EQ(ResourceType_Study, StringToResourceType("STudy")); + ASSERT_EQ(ResourceType_Series, StringToResourceType("SeRiEs")); + ASSERT_EQ(ResourceType_Instance, StringToResourceType("INStance")); + ASSERT_EQ(ResourceType_Instance, StringToResourceType("IMagE")); + ASSERT_THROW(StringToResourceType("heLLo"), OrthancException); + + ASSERT_EQ(2047, StringToMetadata("2047")); + ASSERT_THROW(StringToMetadata("Ceci est un test"), OrthancException); + ASSERT_THROW(RegisterUserMetadata(128, ""), OrthancException); // too low (< 1024) + ASSERT_THROW(RegisterUserMetadata(128000, ""), OrthancException); // too high (> 65535) + RegisterUserMetadata(2047, "Ceci est un test"); + ASSERT_EQ(2047, StringToMetadata("2047")); + ASSERT_EQ(2047, StringToMetadata("Ceci est un test")); +} + + + +TEST(Toolbox, WriteFile) +{ + std::string path; + + { + Toolbox::TemporaryFile tmp; + path = tmp.GetPath(); + + std::string s; + s.append("Hello"); + s.push_back('\0'); + s.append("World"); + ASSERT_EQ(11u, s.size()); + + Toolbox::WriteFile(s, path.c_str()); + + std::string t; + Toolbox::ReadFile(t, path.c_str()); + + ASSERT_EQ(11u, t.size()); + ASSERT_EQ(0, t[5]); + ASSERT_EQ(0, memcmp(s.c_str(), t.c_str(), s.size())); + } + + std::string u; + ASSERT_THROW(Toolbox::ReadFile(u, path.c_str()), OrthancException); +} + + +TEST(Toolbox, Wildcard) +{ + ASSERT_EQ("abcd", Toolbox::WildcardToRegularExpression("abcd")); + ASSERT_EQ("ab.*cd", Toolbox::WildcardToRegularExpression("ab*cd")); + ASSERT_EQ("ab..cd", Toolbox::WildcardToRegularExpression("ab??cd")); + ASSERT_EQ("a.*b.c.*d", Toolbox::WildcardToRegularExpression("a*b?c*d")); + ASSERT_EQ("a\\{b\\]", Toolbox::WildcardToRegularExpression("a{b]")); +} + + +TEST(Toolbox, Tokenize) +{ + std::vector t; + + Toolbox::TokenizeString(t, "", ','); + ASSERT_EQ(1, t.size()); + ASSERT_EQ("", t[0]); + + Toolbox::TokenizeString(t, "abc", ','); + ASSERT_EQ(1, t.size()); + ASSERT_EQ("abc", t[0]); + + Toolbox::TokenizeString(t, "ab,cd,ef,", ','); + ASSERT_EQ(4, t.size()); + ASSERT_EQ("ab", t[0]); + ASSERT_EQ("cd", t[1]); + ASSERT_EQ("ef", t[2]); + ASSERT_EQ("", t[3]); +} + + + +#if defined(__linux) +#include +#endif + +TEST(Toolbox, Endianness) +{ + // Parts of this test come from Adam Conrad + // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=728822#5 + +#if defined(_WIN32) + ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); + +#elif defined(__linux) + +#if !defined(__BYTE_ORDER) +# error Support your platform here +#endif + +# if __BYTE_ORDER == __BIG_ENDIAN + ASSERT_EQ(Endianness_Big, Toolbox::DetectEndianness()); +# else // __LITTLE_ENDIAN + ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); +# endif + +#else +#error Support your platform here +#endif +} + + + +int main(int argc, char **argv) +{ + // Initialize Google's logging library. + FLAGS_logtostderr = true; + FLAGS_minloglevel = 0; + + // Go to trace-level verbosity + //FLAGS_v = 1; + + Toolbox::DetectEndianness(); + + google::InitGoogleLogging("Orthanc"); + + OrthancInitialize(); + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + OrthancFinalize(); + return result; +} diff -r ef4569ae7952 -r edffcf3ce7ab UnitTestsSources/main.cpp --- a/UnitTestsSources/main.cpp Wed Feb 19 11:01:55 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,610 +0,0 @@ -#include "../Core/EnumerationDictionary.h" - -#include "gtest/gtest.h" - -#include - -#include "../Core/Compression/ZlibCompressor.h" -#include "../Core/DicomFormat/DicomTag.h" -#include "../Core/HttpServer/HttpHandler.h" -#include "../Core/OrthancException.h" -#include "../Core/Toolbox.h" -#include "../Core/Uuid.h" -#include "../OrthancServer/FromDcmtkBridge.h" -#include "../OrthancServer/OrthancInitialization.h" - -using namespace Orthanc; - - -TEST(Uuid, Generation) -{ - for (int i = 0; i < 10; i++) - { - std::string s = Toolbox::GenerateUuid(); - ASSERT_TRUE(Toolbox::IsUuid(s)); - } -} - -TEST(Uuid, Test) -{ - ASSERT_FALSE(Toolbox::IsUuid("")); - ASSERT_FALSE(Toolbox::IsUuid("012345678901234567890123456789012345")); - ASSERT_TRUE(Toolbox::IsUuid("550e8400-e29b-41d4-a716-446655440000")); - ASSERT_FALSE(Toolbox::IsUuid("550e8400-e29b-41d4-a716-44665544000_")); - ASSERT_FALSE(Toolbox::IsUuid("01234567890123456789012345678901234_")); - ASSERT_FALSE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-44665544000")); - ASSERT_TRUE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000")); - ASSERT_TRUE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000 ok")); - ASSERT_FALSE(Toolbox::StartsWithUuid("550e8400-e29b-41d4-a716-446655440000ok")); -} - -TEST(Toolbox, IsSHA1) -{ - ASSERT_FALSE(Toolbox::IsSHA1("")); - ASSERT_FALSE(Toolbox::IsSHA1("01234567890123456789012345678901234567890123")); - ASSERT_FALSE(Toolbox::IsSHA1("012345678901234567890123456789012345678901234")); - ASSERT_TRUE(Toolbox::IsSHA1("b5ed549f-956400ce-69a8c063-bf5b78be-2732a4b9")); - - std::string s; - Toolbox::ComputeSHA1(s, "The quick brown fox jumps over the lazy dog"); - ASSERT_TRUE(Toolbox::IsSHA1(s)); - ASSERT_EQ("2fd4e1c6-7a2d28fc-ed849ee1-bb76e739-1b93eb12", s); - - ASSERT_FALSE(Toolbox::IsSHA1("b5ed549f-956400ce-69a8c063-bf5b78be-2732a4b_")); -} - -static void StringToVector(std::vector& v, - const std::string& s) -{ - v.resize(s.size()); - for (size_t i = 0; i < s.size(); i++) - v[i] = s[i]; -} - - -TEST(Zlib, Basic) -{ - std::string s = Toolbox::GenerateUuid(); - s = s + s + s + s; - - std::string compressed, compressed2; - ZlibCompressor c; - c.Compress(compressed, s); - - std::vector v, vv; - StringToVector(v, s); - c.Compress(compressed2, v); - ASSERT_EQ(compressed, compressed2); - - std::string uncompressed; - c.Uncompress(uncompressed, compressed); - ASSERT_EQ(s.size(), uncompressed.size()); - ASSERT_EQ(0, memcmp(&s[0], &uncompressed[0], s.size())); - - StringToVector(vv, compressed); - c.Uncompress(uncompressed, vv); - ASSERT_EQ(s.size(), uncompressed.size()); - ASSERT_EQ(0, memcmp(&s[0], &uncompressed[0], s.size())); -} - - -TEST(Zlib, Level) -{ - std::string s = Toolbox::GenerateUuid(); - s = s + s + s + s; - - std::string compressed, compressed2; - ZlibCompressor c; - c.SetCompressionLevel(9); - c.Compress(compressed, s); - - c.SetCompressionLevel(0); - c.Compress(compressed2, s); - - ASSERT_TRUE(compressed.size() < compressed2.size()); -} - - -TEST(Zlib, Corrupted) -{ - std::string s = Toolbox::GenerateUuid(); - s = s + s + s + s; - - std::string compressed; - ZlibCompressor c; - c.Compress(compressed, s); - - compressed[compressed.size() - 1] = 'a'; - std::string u; - - ASSERT_THROW(c.Uncompress(u, compressed), OrthancException); -} - - -TEST(Zlib, Empty) -{ - std::string s = ""; - std::vector v, vv; - - std::string compressed, compressed2; - ZlibCompressor c; - c.Compress(compressed, s); - c.Compress(compressed2, v); - ASSERT_EQ(compressed, compressed2); - - std::string uncompressed; - c.Uncompress(uncompressed, compressed); - ASSERT_EQ(0u, uncompressed.size()); - - StringToVector(vv, compressed); - c.Uncompress(uncompressed, vv); - ASSERT_EQ(0u, uncompressed.size()); -} - - -TEST(ParseGetQuery, Basic) -{ - HttpHandler::Arguments a; - HttpHandler::ParseGetQuery(a, "aaa=baaa&bb=a&aa=c"); - ASSERT_EQ(3u, a.size()); - ASSERT_EQ(a["aaa"], "baaa"); - ASSERT_EQ(a["bb"], "a"); - ASSERT_EQ(a["aa"], "c"); -} - -TEST(ParseGetQuery, BasicEmpty) -{ - HttpHandler::Arguments a; - HttpHandler::ParseGetQuery(a, "aaa&bb=aa&aa"); - ASSERT_EQ(3u, a.size()); - ASSERT_EQ(a["aaa"], ""); - ASSERT_EQ(a["bb"], "aa"); - ASSERT_EQ(a["aa"], ""); -} - -TEST(ParseGetQuery, Single) -{ - HttpHandler::Arguments a; - HttpHandler::ParseGetQuery(a, "aaa=baaa"); - ASSERT_EQ(1u, a.size()); - ASSERT_EQ(a["aaa"], "baaa"); -} - -TEST(ParseGetQuery, SingleEmpty) -{ - HttpHandler::Arguments a; - HttpHandler::ParseGetQuery(a, "aaa"); - ASSERT_EQ(1u, a.size()); - ASSERT_EQ(a["aaa"], ""); -} - -TEST(DicomFormat, Tag) -{ - ASSERT_EQ("PatientName", FromDcmtkBridge::GetName(DicomTag(0x0010, 0x0010))); - - DicomTag t = FromDcmtkBridge::ParseTag("SeriesDescription"); - ASSERT_EQ(0x0008, t.GetGroup()); - ASSERT_EQ(0x103E, t.GetElement()); - - t = FromDcmtkBridge::ParseTag("0020-e040"); - ASSERT_EQ(0x0020, t.GetGroup()); - ASSERT_EQ(0xe040, t.GetElement()); - - // Test ==() and !=() operators - ASSERT_TRUE(DICOM_TAG_PATIENT_ID == DicomTag(0x0010, 0x0020)); - ASSERT_FALSE(DICOM_TAG_PATIENT_ID != DicomTag(0x0010, 0x0020)); -} - - -TEST(Uri, SplitUriComponents) -{ - UriComponents c; - Toolbox::SplitUriComponents(c, "/cou/hello/world"); - ASSERT_EQ(3u, c.size()); - ASSERT_EQ("cou", c[0]); - ASSERT_EQ("hello", c[1]); - ASSERT_EQ("world", c[2]); - - Toolbox::SplitUriComponents(c, "/cou/hello/world/"); - ASSERT_EQ(3u, c.size()); - ASSERT_EQ("cou", c[0]); - ASSERT_EQ("hello", c[1]); - ASSERT_EQ("world", c[2]); - - Toolbox::SplitUriComponents(c, "/cou/hello/world/a"); - ASSERT_EQ(4u, c.size()); - ASSERT_EQ("cou", c[0]); - ASSERT_EQ("hello", c[1]); - ASSERT_EQ("world", c[2]); - ASSERT_EQ("a", c[3]); - - Toolbox::SplitUriComponents(c, "/"); - ASSERT_EQ(0u, c.size()); - - Toolbox::SplitUriComponents(c, "/hello"); - ASSERT_EQ(1u, c.size()); - ASSERT_EQ("hello", c[0]); - - Toolbox::SplitUriComponents(c, "/hello/"); - ASSERT_EQ(1u, c.size()); - ASSERT_EQ("hello", c[0]); - - ASSERT_THROW(Toolbox::SplitUriComponents(c, ""), OrthancException); - ASSERT_THROW(Toolbox::SplitUriComponents(c, "a"), OrthancException); - ASSERT_THROW(Toolbox::SplitUriComponents(c, "/coucou//coucou"), OrthancException); - - c.clear(); - c.push_back("test"); - ASSERT_EQ("/", Toolbox::FlattenUri(c, 10)); -} - - -TEST(Uri, Child) -{ - UriComponents c1; Toolbox::SplitUriComponents(c1, "/hello/world"); - UriComponents c2; Toolbox::SplitUriComponents(c2, "/hello/hello"); - UriComponents c3; Toolbox::SplitUriComponents(c3, "/hello"); - UriComponents c4; Toolbox::SplitUriComponents(c4, "/world"); - UriComponents c5; Toolbox::SplitUriComponents(c5, "/"); - - ASSERT_TRUE(Toolbox::IsChildUri(c1, c1)); - ASSERT_FALSE(Toolbox::IsChildUri(c1, c2)); - ASSERT_FALSE(Toolbox::IsChildUri(c1, c3)); - ASSERT_FALSE(Toolbox::IsChildUri(c1, c4)); - ASSERT_FALSE(Toolbox::IsChildUri(c1, c5)); - - ASSERT_FALSE(Toolbox::IsChildUri(c2, c1)); - ASSERT_TRUE(Toolbox::IsChildUri(c2, c2)); - ASSERT_FALSE(Toolbox::IsChildUri(c2, c3)); - ASSERT_FALSE(Toolbox::IsChildUri(c2, c4)); - ASSERT_FALSE(Toolbox::IsChildUri(c2, c5)); - - ASSERT_TRUE(Toolbox::IsChildUri(c3, c1)); - ASSERT_TRUE(Toolbox::IsChildUri(c3, c2)); - ASSERT_TRUE(Toolbox::IsChildUri(c3, c3)); - ASSERT_FALSE(Toolbox::IsChildUri(c3, c4)); - ASSERT_FALSE(Toolbox::IsChildUri(c3, c5)); - - ASSERT_FALSE(Toolbox::IsChildUri(c4, c1)); - ASSERT_FALSE(Toolbox::IsChildUri(c4, c2)); - ASSERT_FALSE(Toolbox::IsChildUri(c4, c3)); - ASSERT_TRUE(Toolbox::IsChildUri(c4, c4)); - ASSERT_FALSE(Toolbox::IsChildUri(c4, c5)); - - ASSERT_TRUE(Toolbox::IsChildUri(c5, c1)); - ASSERT_TRUE(Toolbox::IsChildUri(c5, c2)); - ASSERT_TRUE(Toolbox::IsChildUri(c5, c3)); - ASSERT_TRUE(Toolbox::IsChildUri(c5, c4)); - ASSERT_TRUE(Toolbox::IsChildUri(c5, c5)); -} - -TEST(Uri, AutodetectMimeType) -{ - ASSERT_EQ("", Toolbox::AutodetectMimeType("../NOTES")); - ASSERT_EQ("", Toolbox::AutodetectMimeType("")); - ASSERT_EQ("", Toolbox::AutodetectMimeType("/")); - ASSERT_EQ("", Toolbox::AutodetectMimeType("a/a")); - - ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../NOTES.txt")); - ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../coucou.xml/NOTES.txt")); - ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("../.xml")); - - ASSERT_EQ("application/javascript", Toolbox::AutodetectMimeType("NOTES.js")); - ASSERT_EQ("application/json", Toolbox::AutodetectMimeType("NOTES.json")); - ASSERT_EQ("application/pdf", Toolbox::AutodetectMimeType("NOTES.pdf")); - ASSERT_EQ("text/css", Toolbox::AutodetectMimeType("NOTES.css")); - ASSERT_EQ("text/html", Toolbox::AutodetectMimeType("NOTES.html")); - ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("NOTES.txt")); - ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("NOTES.xml")); - ASSERT_EQ("image/gif", Toolbox::AutodetectMimeType("NOTES.gif")); - ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpg")); - ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpeg")); - ASSERT_EQ("image/png", Toolbox::AutodetectMimeType("NOTES.png")); -} - -TEST(Toolbox, ComputeMD5) -{ - std::string s; - - // # echo -n "Hello" | md5sum - - Toolbox::ComputeMD5(s, "Hello"); - ASSERT_EQ("8b1a9953c4611296a827abf8c47804d7", s); - Toolbox::ComputeMD5(s, ""); - ASSERT_EQ("d41d8cd98f00b204e9800998ecf8427e", s); -} - -TEST(Toolbox, ComputeSHA1) -{ - std::string s; - - Toolbox::ComputeSHA1(s, "The quick brown fox jumps over the lazy dog"); - ASSERT_EQ("2fd4e1c6-7a2d28fc-ed849ee1-bb76e739-1b93eb12", s); - Toolbox::ComputeSHA1(s, ""); - ASSERT_EQ("da39a3ee-5e6b4b0d-3255bfef-95601890-afd80709", s); -} - - -TEST(Toolbox, Base64) -{ - ASSERT_EQ("", Toolbox::EncodeBase64("")); - ASSERT_EQ("YQ==", Toolbox::EncodeBase64("a")); - - const std::string hello = "SGVsbG8gd29ybGQ="; - ASSERT_EQ(hello, Toolbox::EncodeBase64("Hello world")); - ASSERT_EQ("Hello world", Toolbox::DecodeBase64(hello)); -} - -TEST(Toolbox, PathToExecutable) -{ - printf("[%s]\n", Toolbox::GetPathToExecutable().c_str()); - printf("[%s]\n", Toolbox::GetDirectoryOfExecutable().c_str()); -} - -TEST(Toolbox, StripSpaces) -{ - ASSERT_EQ("", Toolbox::StripSpaces(" \t \r \n ")); - ASSERT_EQ("coucou", Toolbox::StripSpaces(" coucou \t \r \n ")); - ASSERT_EQ("cou cou", Toolbox::StripSpaces(" cou cou \n ")); - ASSERT_EQ("c", Toolbox::StripSpaces(" \n\t c\r \n ")); -} - -TEST(Toolbox, Case) -{ - std::string s = "CoU"; - std::string ss; - - Toolbox::ToUpperCase(ss, s); - ASSERT_EQ("COU", ss); - Toolbox::ToLowerCase(ss, s); - ASSERT_EQ("cou", ss); - - s = "CoU"; - Toolbox::ToUpperCase(s); - ASSERT_EQ("COU", s); - - s = "CoU"; - Toolbox::ToLowerCase(s); - ASSERT_EQ("cou", s); -} - - -#include - -TEST(Logger, Basic) -{ - LOG(INFO) << "I say hello"; -} - -TEST(Toolbox, ConvertFromLatin1) -{ - // This is a Latin-1 test string - const unsigned char data[10] = { 0xe0, 0xe9, 0xea, 0xe7, 0x26, 0xc6, 0x61, 0x62, 0x63, 0x00 }; - - /*FILE* f = fopen("/tmp/tutu", "w"); - fwrite(&data[0], 9, 1, f); - fclose(f);*/ - - std::string s((char*) &data[0], 10); - ASSERT_EQ("&abc", Toolbox::ConvertToAscii(s)); - - // Open in Emacs, then save with UTF-8 encoding, then "hexdump -C" - std::string utf8 = Toolbox::ConvertToUtf8(s, "ISO-8859-1"); - ASSERT_EQ(15u, utf8.size()); - ASSERT_EQ(0xc3, static_cast(utf8[0])); - ASSERT_EQ(0xa0, static_cast(utf8[1])); - ASSERT_EQ(0xc3, static_cast(utf8[2])); - ASSERT_EQ(0xa9, static_cast(utf8[3])); - ASSERT_EQ(0xc3, static_cast(utf8[4])); - ASSERT_EQ(0xaa, static_cast(utf8[5])); - ASSERT_EQ(0xc3, static_cast(utf8[6])); - ASSERT_EQ(0xa7, static_cast(utf8[7])); - ASSERT_EQ(0x26, static_cast(utf8[8])); - ASSERT_EQ(0xc3, static_cast(utf8[9])); - ASSERT_EQ(0x86, static_cast(utf8[10])); - ASSERT_EQ(0x61, static_cast(utf8[11])); - ASSERT_EQ(0x62, static_cast(utf8[12])); - ASSERT_EQ(0x63, static_cast(utf8[13])); - ASSERT_EQ(0x00, static_cast(utf8[14])); // Null-terminated string -} - -TEST(Toolbox, UrlDecode) -{ - std::string s; - - s = "Hello%20World"; - Toolbox::UrlDecode(s); - ASSERT_EQ("Hello World", s); - - s = "%21%23%24%26%27%28%29%2A%2B%2c%2f%3A%3b%3d%3f%40%5B%5D%90%ff"; - Toolbox::UrlDecode(s); - std::string ss = "!#$&'()*+,/:;=?@[]"; - ss.push_back((char) 144); - ss.push_back((char) 255); - ASSERT_EQ(ss, s); - - s = "(2000%2C00A4)+Other"; - Toolbox::UrlDecode(s); - ASSERT_EQ("(2000,00A4) Other", s); -} - - -#if defined(__linux) -TEST(OrthancInitialization, AbsoluteDirectory) -{ - ASSERT_EQ("/tmp/hello", InterpretRelativePath("/tmp", "hello")); - ASSERT_EQ("/tmp", InterpretRelativePath("/tmp", "/tmp")); -} -#endif - - - -#include "../OrthancServer/ServerEnumerations.h" - -TEST(EnumerationDictionary, Simple) -{ - Toolbox::EnumerationDictionary d; - - ASSERT_THROW(d.Translate("ReceptionDate"), OrthancException); - ASSERT_EQ(MetadataType_ModifiedFrom, d.Translate("5")); - ASSERT_EQ(256, d.Translate("256")); - - d.Add(MetadataType_Instance_ReceptionDate, "ReceptionDate"); - - ASSERT_EQ(MetadataType_Instance_ReceptionDate, d.Translate("ReceptionDate")); - ASSERT_EQ(MetadataType_Instance_ReceptionDate, d.Translate("2")); - ASSERT_EQ("ReceptionDate", d.Translate(MetadataType_Instance_ReceptionDate)); - - ASSERT_THROW(d.Add(MetadataType_Instance_ReceptionDate, "Hello"), OrthancException); - ASSERT_THROW(d.Add(MetadataType_ModifiedFrom, "ReceptionDate"), OrthancException); // already used - ASSERT_THROW(d.Add(MetadataType_ModifiedFrom, "1024"), OrthancException); // cannot register numbers - d.Add(MetadataType_ModifiedFrom, "ModifiedFrom"); // ok -} - - -TEST(EnumerationDictionary, ServerEnumerations) -{ - ASSERT_STREQ("Patient", EnumerationToString(ResourceType_Patient)); - ASSERT_STREQ("Study", EnumerationToString(ResourceType_Study)); - ASSERT_STREQ("Series", EnumerationToString(ResourceType_Series)); - ASSERT_STREQ("Instance", EnumerationToString(ResourceType_Instance)); - - ASSERT_STREQ("ModifiedSeries", EnumerationToString(ChangeType_ModifiedSeries)); - - ASSERT_STREQ("Failure", EnumerationToString(StoreStatus_Failure)); - ASSERT_STREQ("Success", EnumerationToString(StoreStatus_Success)); - - ASSERT_STREQ("CompletedSeries", EnumerationToString(ChangeType_CompletedSeries)); - - ASSERT_EQ("IndexInSeries", EnumerationToString(MetadataType_Instance_IndexInSeries)); - ASSERT_EQ("LastUpdate", EnumerationToString(MetadataType_LastUpdate)); - - ASSERT_EQ(ResourceType_Patient, StringToResourceType("PATienT")); - ASSERT_EQ(ResourceType_Study, StringToResourceType("STudy")); - ASSERT_EQ(ResourceType_Series, StringToResourceType("SeRiEs")); - ASSERT_EQ(ResourceType_Instance, StringToResourceType("INStance")); - ASSERT_EQ(ResourceType_Instance, StringToResourceType("IMagE")); - ASSERT_THROW(StringToResourceType("heLLo"), OrthancException); - - ASSERT_EQ(2047, StringToMetadata("2047")); - ASSERT_THROW(StringToMetadata("Ceci est un test"), OrthancException); - ASSERT_THROW(RegisterUserMetadata(128, ""), OrthancException); // too low (< 1024) - ASSERT_THROW(RegisterUserMetadata(128000, ""), OrthancException); // too high (> 65535) - RegisterUserMetadata(2047, "Ceci est un test"); - ASSERT_EQ(2047, StringToMetadata("2047")); - ASSERT_EQ(2047, StringToMetadata("Ceci est un test")); -} - - - -TEST(Toolbox, WriteFile) -{ - std::string path; - - { - Toolbox::TemporaryFile tmp; - path = tmp.GetPath(); - - std::string s; - s.append("Hello"); - s.push_back('\0'); - s.append("World"); - ASSERT_EQ(11u, s.size()); - - Toolbox::WriteFile(s, path.c_str()); - - std::string t; - Toolbox::ReadFile(t, path.c_str()); - - ASSERT_EQ(11u, t.size()); - ASSERT_EQ(0, t[5]); - ASSERT_EQ(0, memcmp(s.c_str(), t.c_str(), s.size())); - } - - std::string u; - ASSERT_THROW(Toolbox::ReadFile(u, path.c_str()), OrthancException); -} - - -TEST(Toolbox, Wildcard) -{ - ASSERT_EQ("abcd", Toolbox::WildcardToRegularExpression("abcd")); - ASSERT_EQ("ab.*cd", Toolbox::WildcardToRegularExpression("ab*cd")); - ASSERT_EQ("ab..cd", Toolbox::WildcardToRegularExpression("ab??cd")); - ASSERT_EQ("a.*b.c.*d", Toolbox::WildcardToRegularExpression("a*b?c*d")); - ASSERT_EQ("a\\{b\\]", Toolbox::WildcardToRegularExpression("a{b]")); -} - - -TEST(Toolbox, Tokenize) -{ - std::vector t; - - Toolbox::TokenizeString(t, "", ','); - ASSERT_EQ(1, t.size()); - ASSERT_EQ("", t[0]); - - Toolbox::TokenizeString(t, "abc", ','); - ASSERT_EQ(1, t.size()); - ASSERT_EQ("abc", t[0]); - - Toolbox::TokenizeString(t, "ab,cd,ef,", ','); - ASSERT_EQ(4, t.size()); - ASSERT_EQ("ab", t[0]); - ASSERT_EQ("cd", t[1]); - ASSERT_EQ("ef", t[2]); - ASSERT_EQ("", t[3]); -} - - - -#if defined(__linux) -#include -#endif - -TEST(Toolbox, Endianness) -{ - // Parts of this test come from Adam Conrad - // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=728822#5 - -#if defined(_WIN32) - ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); - -#elif defined(__linux) - -#if !defined(__BYTE_ORDER) -# error Support your platform here -#endif - -# if __BYTE_ORDER == __BIG_ENDIAN - ASSERT_EQ(Endianness_Big, Toolbox::DetectEndianness()); -# else // __LITTLE_ENDIAN - ASSERT_EQ(Endianness_Little, Toolbox::DetectEndianness()); -# endif - -#else -#error Support your platform here -#endif -} - - - -int main(int argc, char **argv) -{ - // Initialize Google's logging library. - FLAGS_logtostderr = true; - FLAGS_minloglevel = 0; - - // Go to trace-level verbosity - //FLAGS_v = 1; - - Toolbox::DetectEndianness(); - - google::InitGoogleLogging("Orthanc"); - - OrthancInitialize(); - ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - OrthancFinalize(); - return result; -}