Mercurial > hg > orthanc
comparison OrthancServer/UnitTestsSources/ServerIndexTests.cpp @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | UnitTestsSources/ServerIndexTests.cpp@bd0af2e11325 |
children | 05b8fd21089c |
comparison
equal
deleted
inserted
replaced
4043:6c6239aec462 | 4044:d25f4c0fa160 |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #include "PrecompiledHeadersUnitTests.h" | |
35 #include "gtest/gtest.h" | |
36 | |
37 #include "../Core/Compatibility.h" | |
38 #include "../Core/FileStorage/FilesystemStorage.h" | |
39 #include "../Core/FileStorage/MemoryStorageArea.h" | |
40 #include "../Core/Logging.h" | |
41 #include "../OrthancServer/Database/SQLiteDatabaseWrapper.h" | |
42 #include "../OrthancServer/Search/DatabaseLookup.h" | |
43 #include "../OrthancServer/ServerContext.h" | |
44 #include "../OrthancServer/ServerToolbox.h" | |
45 | |
46 #include <ctype.h> | |
47 #include <algorithm> | |
48 | |
49 using namespace Orthanc; | |
50 | |
51 namespace | |
52 { | |
53 class TestDatabaseListener : public IDatabaseListener | |
54 { | |
55 public: | |
56 std::vector<std::string> deletedFiles_; | |
57 std::vector<std::string> deletedResources_; | |
58 std::string ancestorId_; | |
59 ResourceType ancestorType_; | |
60 | |
61 void Reset() | |
62 { | |
63 ancestorId_ = ""; | |
64 deletedFiles_.clear(); | |
65 } | |
66 | |
67 virtual void SignalRemainingAncestor(ResourceType type, | |
68 const std::string& publicId) | |
69 ORTHANC_OVERRIDE | |
70 { | |
71 ancestorId_ = publicId; | |
72 ancestorType_ = type; | |
73 } | |
74 | |
75 virtual void SignalFileDeleted(const FileInfo& info) ORTHANC_OVERRIDE | |
76 { | |
77 const std::string fileUuid = info.GetUuid(); | |
78 deletedFiles_.push_back(fileUuid); | |
79 LOG(INFO) << "A file must be removed: " << fileUuid; | |
80 } | |
81 | |
82 virtual void SignalChange(const ServerIndexChange& change) ORTHANC_OVERRIDE | |
83 { | |
84 if (change.GetChangeType() == ChangeType_Deleted) | |
85 { | |
86 deletedResources_.push_back(change.GetPublicId()); | |
87 } | |
88 | |
89 LOG(INFO) << "Change related to resource " << change.GetPublicId() << " of type " | |
90 << EnumerationToString(change.GetResourceType()) << ": " | |
91 << EnumerationToString(change.GetChangeType()); | |
92 } | |
93 }; | |
94 | |
95 | |
96 class DatabaseWrapperTest : public ::testing::Test | |
97 { | |
98 protected: | |
99 std::unique_ptr<TestDatabaseListener> listener_; | |
100 std::unique_ptr<SQLiteDatabaseWrapper> index_; | |
101 | |
102 public: | |
103 DatabaseWrapperTest() | |
104 { | |
105 } | |
106 | |
107 virtual void SetUp() ORTHANC_OVERRIDE | |
108 { | |
109 listener_.reset(new TestDatabaseListener); | |
110 index_.reset(new SQLiteDatabaseWrapper); | |
111 index_->SetListener(*listener_); | |
112 index_->Open(); | |
113 } | |
114 | |
115 virtual void TearDown() ORTHANC_OVERRIDE | |
116 { | |
117 index_->Close(); | |
118 index_.reset(NULL); | |
119 listener_.reset(NULL); | |
120 } | |
121 | |
122 void CheckTableRecordCount(uint32_t expected, const char* table) | |
123 { | |
124 ASSERT_EQ(expected, index_->GetTableRecordCount(table)); | |
125 } | |
126 | |
127 void CheckNoParent(int64_t id) | |
128 { | |
129 std::string s; | |
130 ASSERT_FALSE(index_->GetParentPublicId(s, id)); | |
131 } | |
132 | |
133 void CheckParentPublicId(const char* expected, int64_t id) | |
134 { | |
135 std::string s; | |
136 ASSERT_TRUE(index_->GetParentPublicId(s, id)); | |
137 ASSERT_EQ(expected, s); | |
138 } | |
139 | |
140 void CheckNoChild(int64_t id) | |
141 { | |
142 std::list<std::string> j; | |
143 index_->GetChildren(j, id); | |
144 ASSERT_EQ(0u, j.size()); | |
145 } | |
146 | |
147 void CheckOneChild(const char* expected, int64_t id) | |
148 { | |
149 std::list<std::string> j; | |
150 index_->GetChildren(j, id); | |
151 ASSERT_EQ(1u, j.size()); | |
152 ASSERT_EQ(expected, j.front()); | |
153 } | |
154 | |
155 void CheckTwoChildren(const char* expected1, | |
156 const char* expected2, | |
157 int64_t id) | |
158 { | |
159 std::list<std::string> j; | |
160 index_->GetChildren(j, id); | |
161 ASSERT_EQ(2u, j.size()); | |
162 ASSERT_TRUE((expected1 == j.front() && expected2 == j.back()) || | |
163 (expected1 == j.back() && expected2 == j.front())); | |
164 } | |
165 | |
166 void DoLookupIdentifier(std::list<std::string>& result, | |
167 ResourceType level, | |
168 const DicomTag& tag, | |
169 ConstraintType type, | |
170 const std::string& value) | |
171 { | |
172 assert(ServerToolbox::IsIdentifier(tag, level)); | |
173 | |
174 DicomTagConstraint c(tag, type, value, true, true); | |
175 | |
176 std::vector<DatabaseConstraint> lookup; | |
177 lookup.push_back(c.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); | |
178 | |
179 index_->ApplyLookupResources(result, NULL, lookup, level, 0 /* no limit */); | |
180 } | |
181 | |
182 void DoLookupIdentifier2(std::list<std::string>& result, | |
183 ResourceType level, | |
184 const DicomTag& tag, | |
185 ConstraintType type1, | |
186 const std::string& value1, | |
187 ConstraintType type2, | |
188 const std::string& value2) | |
189 { | |
190 assert(ServerToolbox::IsIdentifier(tag, level)); | |
191 | |
192 DicomTagConstraint c1(tag, type1, value1, true, true); | |
193 DicomTagConstraint c2(tag, type2, value2, true, true); | |
194 | |
195 std::vector<DatabaseConstraint> lookup; | |
196 lookup.push_back(c1.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); | |
197 lookup.push_back(c2.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); | |
198 | |
199 index_->ApplyLookupResources(result, NULL, lookup, level, 0 /* no limit */); | |
200 } | |
201 }; | |
202 } | |
203 | |
204 | |
205 TEST_F(DatabaseWrapperTest, Simple) | |
206 { | |
207 int64_t a[] = { | |
208 index_->CreateResource("a", ResourceType_Patient), // 0 | |
209 index_->CreateResource("b", ResourceType_Study), // 1 | |
210 index_->CreateResource("c", ResourceType_Series), // 2 | |
211 index_->CreateResource("d", ResourceType_Instance), // 3 | |
212 index_->CreateResource("e", ResourceType_Instance), // 4 | |
213 index_->CreateResource("f", ResourceType_Instance), // 5 | |
214 index_->CreateResource("g", ResourceType_Study) // 6 | |
215 }; | |
216 | |
217 ASSERT_EQ("a", index_->GetPublicId(a[0])); | |
218 ASSERT_EQ("b", index_->GetPublicId(a[1])); | |
219 ASSERT_EQ("c", index_->GetPublicId(a[2])); | |
220 ASSERT_EQ("d", index_->GetPublicId(a[3])); | |
221 ASSERT_EQ("e", index_->GetPublicId(a[4])); | |
222 ASSERT_EQ("f", index_->GetPublicId(a[5])); | |
223 ASSERT_EQ("g", index_->GetPublicId(a[6])); | |
224 | |
225 ASSERT_EQ(ResourceType_Patient, index_->GetResourceType(a[0])); | |
226 ASSERT_EQ(ResourceType_Study, index_->GetResourceType(a[1])); | |
227 ASSERT_EQ(ResourceType_Series, index_->GetResourceType(a[2])); | |
228 ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[3])); | |
229 ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[4])); | |
230 ASSERT_EQ(ResourceType_Instance, index_->GetResourceType(a[5])); | |
231 ASSERT_EQ(ResourceType_Study, index_->GetResourceType(a[6])); | |
232 | |
233 { | |
234 std::list<std::string> t; | |
235 index_->GetAllPublicIds(t, ResourceType_Patient); | |
236 | |
237 ASSERT_EQ(1u, t.size()); | |
238 ASSERT_EQ("a", t.front()); | |
239 | |
240 index_->GetAllPublicIds(t, ResourceType_Series); | |
241 ASSERT_EQ(1u, t.size()); | |
242 ASSERT_EQ("c", t.front()); | |
243 | |
244 index_->GetAllPublicIds(t, ResourceType_Study); | |
245 ASSERT_EQ(2u, t.size()); | |
246 | |
247 index_->GetAllPublicIds(t, ResourceType_Instance); | |
248 ASSERT_EQ(3u, t.size()); | |
249 } | |
250 | |
251 index_->SetGlobalProperty(GlobalProperty_FlushSleep, "World"); | |
252 | |
253 index_->AttachChild(a[0], a[1]); | |
254 index_->AttachChild(a[1], a[2]); | |
255 index_->AttachChild(a[2], a[3]); | |
256 index_->AttachChild(a[2], a[4]); | |
257 index_->AttachChild(a[6], a[5]); | |
258 | |
259 int64_t parent; | |
260 ASSERT_FALSE(index_->LookupParent(parent, a[0])); | |
261 ASSERT_TRUE(index_->LookupParent(parent, a[1])); ASSERT_EQ(a[0], parent); | |
262 ASSERT_TRUE(index_->LookupParent(parent, a[2])); ASSERT_EQ(a[1], parent); | |
263 ASSERT_TRUE(index_->LookupParent(parent, a[3])); ASSERT_EQ(a[2], parent); | |
264 ASSERT_TRUE(index_->LookupParent(parent, a[4])); ASSERT_EQ(a[2], parent); | |
265 ASSERT_TRUE(index_->LookupParent(parent, a[5])); ASSERT_EQ(a[6], parent); | |
266 ASSERT_FALSE(index_->LookupParent(parent, a[6])); | |
267 | |
268 std::string s; | |
269 | |
270 CheckNoParent(a[0]); | |
271 CheckNoParent(a[6]); | |
272 CheckParentPublicId("a", a[1]); | |
273 CheckParentPublicId("b", a[2]); | |
274 CheckParentPublicId("c", a[3]); | |
275 CheckParentPublicId("c", a[4]); | |
276 CheckParentPublicId("g", a[5]); | |
277 | |
278 std::list<std::string> l; | |
279 index_->GetChildrenPublicId(l, a[0]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("b", l.front()); | |
280 index_->GetChildrenPublicId(l, a[1]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("c", l.front()); | |
281 index_->GetChildrenPublicId(l, a[3]); ASSERT_EQ(0u, l.size()); | |
282 index_->GetChildrenPublicId(l, a[4]); ASSERT_EQ(0u, l.size()); | |
283 index_->GetChildrenPublicId(l, a[5]); ASSERT_EQ(0u, l.size()); | |
284 index_->GetChildrenPublicId(l, a[6]); ASSERT_EQ(1u, l.size()); ASSERT_EQ("f", l.front()); | |
285 | |
286 index_->GetChildrenPublicId(l, a[2]); ASSERT_EQ(2u, l.size()); | |
287 if (l.front() == "d") | |
288 { | |
289 ASSERT_EQ("e", l.back()); | |
290 } | |
291 else | |
292 { | |
293 ASSERT_EQ("d", l.back()); | |
294 ASSERT_EQ("e", l.front()); | |
295 } | |
296 | |
297 std::map<MetadataType, std::string> md; | |
298 index_->GetAllMetadata(md, a[4]); | |
299 ASSERT_EQ(0u, md.size()); | |
300 | |
301 index_->AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", | |
302 CompressionType_ZlibWithSize, 21, "compressedMD5")); | |
303 index_->AddAttachment(a[4], FileInfo("my dicom file", FileContentType_Dicom, 42, "md5")); | |
304 index_->AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5")); | |
305 index_->SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE"); | |
306 | |
307 index_->GetAllMetadata(md, a[4]); | |
308 ASSERT_EQ(1u, md.size()); | |
309 ASSERT_EQ("PINNACLE", md[MetadataType_Instance_RemoteAet]); | |
310 index_->SetMetadata(a[4], MetadataType_ModifiedFrom, "TUTU"); | |
311 index_->GetAllMetadata(md, a[4]); | |
312 ASSERT_EQ(2u, md.size()); | |
313 | |
314 std::map<MetadataType, std::string> md2; | |
315 index_->GetAllMetadata(md2, a[4]); | |
316 ASSERT_EQ(2u, md2.size()); | |
317 ASSERT_EQ("TUTU", md2[MetadataType_ModifiedFrom]); | |
318 ASSERT_EQ("PINNACLE", md2[MetadataType_Instance_RemoteAet]); | |
319 | |
320 index_->DeleteMetadata(a[4], MetadataType_ModifiedFrom); | |
321 index_->GetAllMetadata(md, a[4]); | |
322 ASSERT_EQ(1u, md.size()); | |
323 ASSERT_EQ("PINNACLE", md[MetadataType_Instance_RemoteAet]); | |
324 | |
325 index_->GetAllMetadata(md2, a[4]); | |
326 ASSERT_EQ(1u, md2.size()); | |
327 ASSERT_EQ("PINNACLE", md2[MetadataType_Instance_RemoteAet]); | |
328 | |
329 | |
330 ASSERT_EQ(21u + 42u + 44u, index_->GetTotalCompressedSize()); | |
331 ASSERT_EQ(42u + 42u + 44u, index_->GetTotalUncompressedSize()); | |
332 | |
333 index_->SetMainDicomTag(a[3], DicomTag(0x0010, 0x0010), "PatientName"); | |
334 | |
335 int64_t b; | |
336 ResourceType t; | |
337 ASSERT_TRUE(index_->LookupResource(b, t, "g")); | |
338 ASSERT_EQ(7, b); | |
339 ASSERT_EQ(ResourceType_Study, t); | |
340 | |
341 ASSERT_TRUE(index_->LookupMetadata(s, a[4], MetadataType_Instance_RemoteAet)); | |
342 ASSERT_FALSE(index_->LookupMetadata(s, a[4], MetadataType_Instance_IndexInSeries)); | |
343 ASSERT_EQ("PINNACLE", s); | |
344 | |
345 std::string u; | |
346 ASSERT_TRUE(index_->LookupMetadata(u, a[4], MetadataType_Instance_RemoteAet)); | |
347 ASSERT_EQ("PINNACLE", u); | |
348 ASSERT_FALSE(index_->LookupMetadata(u, a[4], MetadataType_Instance_IndexInSeries)); | |
349 | |
350 ASSERT_TRUE(index_->LookupGlobalProperty(s, GlobalProperty_FlushSleep)); | |
351 ASSERT_FALSE(index_->LookupGlobalProperty(s, static_cast<GlobalProperty>(42))); | |
352 ASSERT_EQ("World", s); | |
353 | |
354 FileInfo att; | |
355 ASSERT_TRUE(index_->LookupAttachment(att, a[4], FileContentType_DicomAsJson)); | |
356 ASSERT_EQ("my json file", att.GetUuid()); | |
357 ASSERT_EQ(21u, att.GetCompressedSize()); | |
358 ASSERT_EQ("md5", att.GetUncompressedMD5()); | |
359 ASSERT_EQ("compressedMD5", att.GetCompressedMD5()); | |
360 ASSERT_EQ(42u, att.GetUncompressedSize()); | |
361 ASSERT_EQ(CompressionType_ZlibWithSize, att.GetCompressionType()); | |
362 | |
363 ASSERT_TRUE(index_->LookupAttachment(att, a[6], FileContentType_Dicom)); | |
364 ASSERT_EQ("world", att.GetUuid()); | |
365 ASSERT_EQ(44u, att.GetCompressedSize()); | |
366 ASSERT_EQ("md5", att.GetUncompressedMD5()); | |
367 ASSERT_EQ("md5", att.GetCompressedMD5()); | |
368 ASSERT_EQ(44u, att.GetUncompressedSize()); | |
369 ASSERT_EQ(CompressionType_None, att.GetCompressionType()); | |
370 | |
371 ASSERT_EQ(0u, listener_->deletedFiles_.size()); | |
372 ASSERT_EQ(0u, listener_->deletedResources_.size()); | |
373 | |
374 CheckTableRecordCount(7, "Resources"); | |
375 CheckTableRecordCount(3, "AttachedFiles"); | |
376 CheckTableRecordCount(1, "Metadata"); | |
377 CheckTableRecordCount(1, "MainDicomTags"); | |
378 | |
379 index_->DeleteResource(a[0]); | |
380 ASSERT_EQ(5u, listener_->deletedResources_.size()); | |
381 ASSERT_EQ(2u, listener_->deletedFiles_.size()); | |
382 ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), | |
383 listener_->deletedFiles_.end(), | |
384 "my json file") == listener_->deletedFiles_.end()); | |
385 ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), | |
386 listener_->deletedFiles_.end(), | |
387 "my dicom file") == listener_->deletedFiles_.end()); | |
388 | |
389 CheckTableRecordCount(2, "Resources"); | |
390 CheckTableRecordCount(0, "Metadata"); | |
391 CheckTableRecordCount(1, "AttachedFiles"); | |
392 CheckTableRecordCount(0, "MainDicomTags"); | |
393 | |
394 index_->DeleteResource(a[5]); | |
395 ASSERT_EQ(7u, listener_->deletedResources_.size()); | |
396 | |
397 CheckTableRecordCount(0, "Resources"); | |
398 CheckTableRecordCount(0, "AttachedFiles"); | |
399 CheckTableRecordCount(3, "GlobalProperties"); | |
400 | |
401 std::string tmp; | |
402 ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_DatabaseSchemaVersion)); | |
403 ASSERT_EQ("6", tmp); | |
404 ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_FlushSleep)); | |
405 ASSERT_EQ("World", tmp); | |
406 ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast)); | |
407 ASSERT_EQ("1", tmp); | |
408 | |
409 ASSERT_EQ(3u, listener_->deletedFiles_.size()); | |
410 ASSERT_FALSE(std::find(listener_->deletedFiles_.begin(), | |
411 listener_->deletedFiles_.end(), | |
412 "world") == listener_->deletedFiles_.end()); | |
413 } | |
414 | |
415 | |
416 TEST_F(DatabaseWrapperTest, Upward) | |
417 { | |
418 int64_t a[] = { | |
419 index_->CreateResource("a", ResourceType_Patient), // 0 | |
420 index_->CreateResource("b", ResourceType_Study), // 1 | |
421 index_->CreateResource("c", ResourceType_Series), // 2 | |
422 index_->CreateResource("d", ResourceType_Instance), // 3 | |
423 index_->CreateResource("e", ResourceType_Instance), // 4 | |
424 index_->CreateResource("f", ResourceType_Study), // 5 | |
425 index_->CreateResource("g", ResourceType_Series), // 6 | |
426 index_->CreateResource("h", ResourceType_Series) // 7 | |
427 }; | |
428 | |
429 index_->AttachChild(a[0], a[1]); | |
430 index_->AttachChild(a[1], a[2]); | |
431 index_->AttachChild(a[2], a[3]); | |
432 index_->AttachChild(a[2], a[4]); | |
433 index_->AttachChild(a[1], a[6]); | |
434 index_->AttachChild(a[0], a[5]); | |
435 index_->AttachChild(a[5], a[7]); | |
436 | |
437 CheckTwoChildren("b", "f", a[0]); | |
438 CheckTwoChildren("c", "g", a[1]); | |
439 CheckTwoChildren("d", "e", a[2]); | |
440 CheckNoChild(a[3]); | |
441 CheckNoChild(a[4]); | |
442 CheckOneChild("h", a[5]); | |
443 CheckNoChild(a[6]); | |
444 CheckNoChild(a[7]); | |
445 | |
446 listener_->Reset(); | |
447 index_->DeleteResource(a[3]); | |
448 ASSERT_EQ("c", listener_->ancestorId_); | |
449 ASSERT_EQ(ResourceType_Series, listener_->ancestorType_); | |
450 | |
451 listener_->Reset(); | |
452 index_->DeleteResource(a[4]); | |
453 ASSERT_EQ("b", listener_->ancestorId_); | |
454 ASSERT_EQ(ResourceType_Study, listener_->ancestorType_); | |
455 | |
456 listener_->Reset(); | |
457 index_->DeleteResource(a[7]); | |
458 ASSERT_EQ("a", listener_->ancestorId_); | |
459 ASSERT_EQ(ResourceType_Patient, listener_->ancestorType_); | |
460 | |
461 listener_->Reset(); | |
462 index_->DeleteResource(a[6]); | |
463 ASSERT_EQ("", listener_->ancestorId_); // No more ancestor | |
464 } | |
465 | |
466 | |
467 TEST_F(DatabaseWrapperTest, PatientRecycling) | |
468 { | |
469 std::vector<int64_t> patients; | |
470 for (int i = 0; i < 10; i++) | |
471 { | |
472 std::string p = "Patient " + boost::lexical_cast<std::string>(i); | |
473 patients.push_back(index_->CreateResource(p, ResourceType_Patient)); | |
474 index_->AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, | |
475 "md5-" + boost::lexical_cast<std::string>(i))); | |
476 ASSERT_FALSE(index_->IsProtectedPatient(patients[i])); | |
477 } | |
478 | |
479 CheckTableRecordCount(10u, "Resources"); | |
480 CheckTableRecordCount(10u, "PatientRecyclingOrder"); | |
481 | |
482 listener_->Reset(); | |
483 ASSERT_EQ(0u, listener_->deletedResources_.size()); | |
484 | |
485 index_->DeleteResource(patients[5]); | |
486 index_->DeleteResource(patients[0]); | |
487 ASSERT_EQ(2u, listener_->deletedResources_.size()); | |
488 | |
489 CheckTableRecordCount(8u, "Resources"); | |
490 CheckTableRecordCount(8u, "PatientRecyclingOrder"); | |
491 | |
492 ASSERT_EQ(2u, listener_->deletedFiles_.size()); | |
493 ASSERT_EQ("Patient 5", listener_->deletedFiles_[0]); | |
494 ASSERT_EQ("Patient 0", listener_->deletedFiles_[1]); | |
495 | |
496 int64_t p; | |
497 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); | |
498 index_->DeleteResource(p); | |
499 ASSERT_EQ(3u, listener_->deletedResources_.size()); | |
500 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); | |
501 index_->DeleteResource(p); | |
502 ASSERT_EQ(4u, listener_->deletedResources_.size()); | |
503 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); | |
504 index_->DeleteResource(p); | |
505 ASSERT_EQ(5u, listener_->deletedResources_.size()); | |
506 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); | |
507 index_->DeleteResource(p); | |
508 ASSERT_EQ(6u, listener_->deletedResources_.size()); | |
509 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[6]); | |
510 index_->DeleteResource(p); | |
511 index_->DeleteResource(patients[8]); | |
512 ASSERT_EQ(8u, listener_->deletedResources_.size()); | |
513 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[7]); | |
514 index_->DeleteResource(p); | |
515 ASSERT_EQ(9u, listener_->deletedResources_.size()); | |
516 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[9]); | |
517 index_->DeleteResource(p); | |
518 ASSERT_FALSE(index_->SelectPatientToRecycle(p)); | |
519 ASSERT_EQ(10u, listener_->deletedResources_.size()); | |
520 | |
521 ASSERT_EQ(10u, listener_->deletedFiles_.size()); | |
522 | |
523 CheckTableRecordCount(0, "Resources"); | |
524 CheckTableRecordCount(0, "PatientRecyclingOrder"); | |
525 } | |
526 | |
527 | |
528 TEST_F(DatabaseWrapperTest, PatientProtection) | |
529 { | |
530 std::vector<int64_t> patients; | |
531 for (int i = 0; i < 5; i++) | |
532 { | |
533 std::string p = "Patient " + boost::lexical_cast<std::string>(i); | |
534 patients.push_back(index_->CreateResource(p, ResourceType_Patient)); | |
535 index_->AddAttachment(patients[i], FileInfo(p, FileContentType_Dicom, i + 10, | |
536 "md5-" + boost::lexical_cast<std::string>(i))); | |
537 ASSERT_FALSE(index_->IsProtectedPatient(patients[i])); | |
538 } | |
539 | |
540 CheckTableRecordCount(5, "Resources"); | |
541 CheckTableRecordCount(5, "PatientRecyclingOrder"); | |
542 | |
543 ASSERT_FALSE(index_->IsProtectedPatient(patients[2])); | |
544 index_->SetProtectedPatient(patients[2], true); | |
545 ASSERT_TRUE(index_->IsProtectedPatient(patients[2])); | |
546 CheckTableRecordCount(5, "Resources"); | |
547 CheckTableRecordCount(4, "PatientRecyclingOrder"); | |
548 | |
549 index_->SetProtectedPatient(patients[2], true); | |
550 ASSERT_TRUE(index_->IsProtectedPatient(patients[2])); | |
551 CheckTableRecordCount(4, "PatientRecyclingOrder"); | |
552 index_->SetProtectedPatient(patients[2], false); | |
553 ASSERT_FALSE(index_->IsProtectedPatient(patients[2])); | |
554 CheckTableRecordCount(5, "PatientRecyclingOrder"); | |
555 index_->SetProtectedPatient(patients[2], false); | |
556 ASSERT_FALSE(index_->IsProtectedPatient(patients[2])); | |
557 CheckTableRecordCount(5, "PatientRecyclingOrder"); | |
558 CheckTableRecordCount(5, "Resources"); | |
559 index_->SetProtectedPatient(patients[2], true); | |
560 ASSERT_TRUE(index_->IsProtectedPatient(patients[2])); | |
561 CheckTableRecordCount(4, "PatientRecyclingOrder"); | |
562 index_->SetProtectedPatient(patients[2], false); | |
563 ASSERT_FALSE(index_->IsProtectedPatient(patients[2])); | |
564 CheckTableRecordCount(5, "PatientRecyclingOrder"); | |
565 index_->SetProtectedPatient(patients[3], true); | |
566 ASSERT_TRUE(index_->IsProtectedPatient(patients[3])); | |
567 CheckTableRecordCount(4, "PatientRecyclingOrder"); | |
568 | |
569 CheckTableRecordCount(5, "Resources"); | |
570 ASSERT_EQ(0u, listener_->deletedFiles_.size()); | |
571 | |
572 // Unprotecting a patient puts it at the last position in the recycling queue | |
573 int64_t p; | |
574 ASSERT_EQ(0u, listener_->deletedResources_.size()); | |
575 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[0]); | |
576 index_->DeleteResource(p); | |
577 ASSERT_EQ(1u, listener_->deletedResources_.size()); | |
578 ASSERT_TRUE(index_->SelectPatientToRecycle(p, patients[1])); ASSERT_EQ(p, patients[4]); | |
579 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]); | |
580 index_->DeleteResource(p); | |
581 ASSERT_EQ(2u, listener_->deletedResources_.size()); | |
582 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]); | |
583 index_->DeleteResource(p); | |
584 ASSERT_EQ(3u, listener_->deletedResources_.size()); | |
585 ASSERT_FALSE(index_->SelectPatientToRecycle(p, patients[2])); | |
586 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]); | |
587 index_->DeleteResource(p); | |
588 ASSERT_EQ(4u, listener_->deletedResources_.size()); | |
589 // "patients[3]" is still protected | |
590 ASSERT_FALSE(index_->SelectPatientToRecycle(p)); | |
591 | |
592 ASSERT_EQ(4u, listener_->deletedFiles_.size()); | |
593 CheckTableRecordCount(1, "Resources"); | |
594 CheckTableRecordCount(0, "PatientRecyclingOrder"); | |
595 | |
596 index_->SetProtectedPatient(patients[3], false); | |
597 CheckTableRecordCount(1, "PatientRecyclingOrder"); | |
598 ASSERT_FALSE(index_->SelectPatientToRecycle(p, patients[3])); | |
599 ASSERT_TRUE(index_->SelectPatientToRecycle(p, patients[2])); | |
600 ASSERT_TRUE(index_->SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]); | |
601 index_->DeleteResource(p); | |
602 ASSERT_EQ(5u, listener_->deletedResources_.size()); | |
603 | |
604 ASSERT_EQ(5u, listener_->deletedFiles_.size()); | |
605 CheckTableRecordCount(0, "Resources"); | |
606 CheckTableRecordCount(0, "PatientRecyclingOrder"); | |
607 } | |
608 | |
609 | |
610 TEST(ServerIndex, Sequence) | |
611 { | |
612 const std::string path = "UnitTestsStorage"; | |
613 | |
614 SystemToolbox::RemoveFile(path + "/index"); | |
615 FilesystemStorage storage(path); | |
616 SQLiteDatabaseWrapper db; // The SQLite DB is in memory | |
617 db.Open(); | |
618 ServerContext context(db, storage, true /* running unit tests */, 10); | |
619 context.SetupJobsEngine(true, false); | |
620 | |
621 ServerIndex& index = context.GetIndex(); | |
622 | |
623 ASSERT_EQ(1u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); | |
624 ASSERT_EQ(2u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); | |
625 ASSERT_EQ(3u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); | |
626 ASSERT_EQ(4u, index.IncrementGlobalSequence(GlobalProperty_AnonymizationSequence)); | |
627 | |
628 context.Stop(); | |
629 db.Close(); | |
630 } | |
631 | |
632 | |
633 TEST_F(DatabaseWrapperTest, LookupIdentifier) | |
634 { | |
635 int64_t a[] = { | |
636 index_->CreateResource("a", ResourceType_Study), // 0 | |
637 index_->CreateResource("b", ResourceType_Study), // 1 | |
638 index_->CreateResource("c", ResourceType_Study), // 2 | |
639 index_->CreateResource("d", ResourceType_Series) // 3 | |
640 }; | |
641 | |
642 index_->SetIdentifierTag(a[0], DICOM_TAG_STUDY_INSTANCE_UID, "0"); | |
643 index_->SetIdentifierTag(a[1], DICOM_TAG_STUDY_INSTANCE_UID, "1"); | |
644 index_->SetIdentifierTag(a[2], DICOM_TAG_STUDY_INSTANCE_UID, "0"); | |
645 index_->SetIdentifierTag(a[3], DICOM_TAG_SERIES_INSTANCE_UID, "0"); | |
646 | |
647 std::list<std::string> s; | |
648 | |
649 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_Equal, "0"); | |
650 ASSERT_EQ(2u, s.size()); | |
651 ASSERT_TRUE(std::find(s.begin(), s.end(), "a") != s.end()); | |
652 ASSERT_TRUE(std::find(s.begin(), s.end(), "c") != s.end()); | |
653 | |
654 DoLookupIdentifier(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, ConstraintType_Equal, "0"); | |
655 ASSERT_EQ(1u, s.size()); | |
656 ASSERT_TRUE(std::find(s.begin(), s.end(), "d") != s.end()); | |
657 | |
658 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_Equal, "1"); | |
659 ASSERT_EQ(1u, s.size()); | |
660 ASSERT_TRUE(std::find(s.begin(), s.end(), "b") != s.end()); | |
661 | |
662 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_Equal, "1"); | |
663 ASSERT_EQ(1u, s.size()); | |
664 ASSERT_TRUE(std::find(s.begin(), s.end(), "b") != s.end()); | |
665 | |
666 DoLookupIdentifier(s, ResourceType_Series, DICOM_TAG_SERIES_INSTANCE_UID, ConstraintType_Equal, "1"); | |
667 ASSERT_EQ(0u, s.size()); | |
668 | |
669 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_GreaterOrEqual, "0"); | |
670 ASSERT_EQ(3u, s.size()); | |
671 | |
672 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_GreaterOrEqual, "1"); | |
673 ASSERT_EQ(1u, s.size()); | |
674 | |
675 DoLookupIdentifier(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, ConstraintType_GreaterOrEqual, "2"); | |
676 ASSERT_EQ(0u, s.size()); | |
677 | |
678 DoLookupIdentifier2(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, | |
679 ConstraintType_GreaterOrEqual, "0", ConstraintType_SmallerOrEqual, "0"); | |
680 ASSERT_EQ(2u, s.size()); | |
681 | |
682 DoLookupIdentifier2(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, | |
683 ConstraintType_GreaterOrEqual, "1", ConstraintType_SmallerOrEqual, "1"); | |
684 ASSERT_EQ(1u, s.size()); | |
685 | |
686 DoLookupIdentifier2(s, ResourceType_Study, DICOM_TAG_STUDY_INSTANCE_UID, | |
687 ConstraintType_GreaterOrEqual, "0", ConstraintType_SmallerOrEqual, "1"); | |
688 ASSERT_EQ(3u, s.size()); | |
689 } | |
690 | |
691 | |
692 TEST(ServerIndex, AttachmentRecycling) | |
693 { | |
694 const std::string path = "UnitTestsStorage"; | |
695 | |
696 SystemToolbox::RemoveFile(path + "/index"); | |
697 FilesystemStorage storage(path); | |
698 SQLiteDatabaseWrapper db; // The SQLite DB is in memory | |
699 db.Open(); | |
700 ServerContext context(db, storage, true /* running unit tests */, 10); | |
701 context.SetupJobsEngine(true, false); | |
702 ServerIndex& index = context.GetIndex(); | |
703 | |
704 index.SetMaximumStorageSize(10); | |
705 | |
706 uint64_t diskSize, uncompressedSize, countPatients, countStudies, countSeries, countInstances; | |
707 index.GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
708 countStudies, countSeries, countInstances); | |
709 | |
710 ASSERT_EQ(0u, countPatients); | |
711 ASSERT_EQ(0u, diskSize); | |
712 | |
713 ServerIndex::Attachments attachments; | |
714 | |
715 std::vector<std::string> ids; | |
716 for (int i = 0; i < 10; i++) | |
717 { | |
718 std::string id = boost::lexical_cast<std::string>(i); | |
719 DicomMap instance; | |
720 instance.SetValue(DICOM_TAG_PATIENT_ID, "patient-" + id, false); | |
721 instance.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "study-" + id, false); | |
722 instance.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "series-" + id, false); | |
723 instance.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "instance-" + id, false); | |
724 instance.SetValue(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.1", false); // CR image | |
725 | |
726 std::map<MetadataType, std::string> instanceMetadata; | |
727 DicomInstanceToStore toStore; | |
728 toStore.SetSummary(instance); | |
729 ASSERT_EQ(StoreStatus_Success, index.Store(instanceMetadata, toStore, attachments, | |
730 false /* don't overwrite */)); | |
731 ASSERT_EQ(5u, instanceMetadata.size()); | |
732 ASSERT_TRUE(instanceMetadata.find(MetadataType_Instance_RemoteAet) != instanceMetadata.end()); | |
733 ASSERT_TRUE(instanceMetadata.find(MetadataType_Instance_ReceptionDate) != instanceMetadata.end()); | |
734 ASSERT_TRUE(instanceMetadata.find(MetadataType_Instance_TransferSyntax) != instanceMetadata.end()); | |
735 ASSERT_TRUE(instanceMetadata.find(MetadataType_Instance_SopClassUid) != instanceMetadata.end()); | |
736 | |
737 // The default transfer syntax depends on the OS endianness | |
738 std::string s = instanceMetadata[MetadataType_Instance_TransferSyntax]; | |
739 ASSERT_TRUE(s == "1.2.840.10008.1.2.1" || | |
740 s == "1.2.840.10008.1.2.2"); | |
741 | |
742 ASSERT_EQ("1.2.840.10008.5.1.4.1.1.1", instanceMetadata[MetadataType_Instance_SopClassUid]); | |
743 | |
744 DicomInstanceHasher hasher(instance); | |
745 ids.push_back(hasher.HashPatient()); | |
746 ids.push_back(hasher.HashStudy()); | |
747 ids.push_back(hasher.HashSeries()); | |
748 ids.push_back(hasher.HashInstance()); | |
749 | |
750 ASSERT_EQ(hasher.HashPatient(), toStore.GetHasher().HashPatient()); | |
751 ASSERT_EQ(hasher.HashStudy(), toStore.GetHasher().HashStudy()); | |
752 ASSERT_EQ(hasher.HashSeries(), toStore.GetHasher().HashSeries()); | |
753 ASSERT_EQ(hasher.HashInstance(), toStore.GetHasher().HashInstance()); | |
754 } | |
755 | |
756 index.GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
757 countStudies, countSeries, countInstances); | |
758 ASSERT_EQ(10u, countPatients); | |
759 ASSERT_EQ(0u, diskSize); | |
760 | |
761 for (size_t i = 0; i < ids.size(); i++) | |
762 { | |
763 FileInfo info(Toolbox::GenerateUuid(), FileContentType_Dicom, 1, "md5"); | |
764 index.AddAttachment(info, ids[i]); | |
765 | |
766 index.GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
767 countStudies, countSeries, countInstances); | |
768 ASSERT_GE(10u, diskSize); | |
769 } | |
770 | |
771 // Because the DB is in memory, the SQLite index must not have been created | |
772 ASSERT_FALSE(SystemToolbox::IsRegularFile(path + "/index")); | |
773 | |
774 context.Stop(); | |
775 db.Close(); | |
776 } | |
777 | |
778 | |
779 TEST(ServerIndex, NormalizeIdentifier) | |
780 { | |
781 ASSERT_EQ("H^L.LO", ServerToolbox::NormalizeIdentifier(" Hé^l.LO %_ ")); | |
782 ASSERT_EQ("1.2.840.113619.2.176.2025", ServerToolbox::NormalizeIdentifier(" 1.2.840.113619.2.176.2025 ")); | |
783 } | |
784 | |
785 | |
786 TEST(ServerIndex, Overwrite) | |
787 { | |
788 for (unsigned int i = 0; i < 2; i++) | |
789 { | |
790 bool overwrite = (i == 0); | |
791 | |
792 MemoryStorageArea storage; | |
793 SQLiteDatabaseWrapper db; // The SQLite DB is in memory | |
794 db.Open(); | |
795 ServerContext context(db, storage, true /* running unit tests */, 10); | |
796 context.SetupJobsEngine(true, false); | |
797 context.SetCompressionEnabled(true); | |
798 | |
799 DicomMap instance; | |
800 instance.SetValue(DICOM_TAG_PATIENT_ID, "patient", false); | |
801 instance.SetValue(DICOM_TAG_PATIENT_NAME, "name", false); | |
802 instance.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "study", false); | |
803 instance.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "series", false); | |
804 instance.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "sop", false); | |
805 instance.SetValue(DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.1", false); // CR image | |
806 | |
807 DicomInstanceHasher hasher(instance); | |
808 std::string id = hasher.HashInstance(); | |
809 context.SetOverwriteInstances(overwrite); | |
810 | |
811 uint64_t diskSize, uncompressedSize, countPatients, countStudies, countSeries, countInstances; | |
812 context.GetIndex().GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
813 countStudies, countSeries, countInstances); | |
814 | |
815 ASSERT_EQ(0u, countInstances); | |
816 ASSERT_EQ(0u, diskSize); | |
817 | |
818 { | |
819 DicomInstanceToStore toStore; | |
820 toStore.SetSummary(instance); | |
821 toStore.SetOrigin(DicomInstanceOrigin::FromPlugins()); | |
822 ASSERT_EQ(id, toStore.GetHasher().HashInstance()); | |
823 | |
824 std::string id2; | |
825 ASSERT_EQ(StoreStatus_Success, context.Store(id2, toStore, StoreInstanceMode_Default)); | |
826 ASSERT_EQ(id, id2); | |
827 } | |
828 | |
829 FileInfo dicom1, json1; | |
830 ASSERT_TRUE(context.GetIndex().LookupAttachment(dicom1, id, FileContentType_Dicom)); | |
831 ASSERT_TRUE(context.GetIndex().LookupAttachment(json1, id, FileContentType_DicomAsJson)); | |
832 | |
833 context.GetIndex().GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
834 countStudies, countSeries, countInstances); | |
835 ASSERT_EQ(1u, countInstances); | |
836 ASSERT_EQ(dicom1.GetCompressedSize() + json1.GetCompressedSize(), diskSize); | |
837 ASSERT_EQ(dicom1.GetUncompressedSize() + json1.GetUncompressedSize(), uncompressedSize); | |
838 | |
839 Json::Value tmp; | |
840 context.ReadDicomAsJson(tmp, id); | |
841 ASSERT_EQ("name", tmp["0010,0010"]["Value"].asString()); | |
842 | |
843 { | |
844 ServerContext::DicomCacheLocker locker(context, id); | |
845 std::string tmp; | |
846 locker.GetDicom().GetTagValue(tmp, DICOM_TAG_PATIENT_NAME); | |
847 ASSERT_EQ("name", tmp); | |
848 } | |
849 | |
850 { | |
851 DicomMap instance2; | |
852 instance2.Assign(instance); | |
853 instance2.SetValue(DICOM_TAG_PATIENT_NAME, "overwritten", false); | |
854 | |
855 DicomInstanceToStore toStore; | |
856 toStore.SetSummary(instance2); | |
857 toStore.SetOrigin(DicomInstanceOrigin::FromPlugins()); | |
858 | |
859 std::string id2; | |
860 ASSERT_EQ(overwrite ? StoreStatus_Success : StoreStatus_AlreadyStored, | |
861 context.Store(id2, toStore, StoreInstanceMode_Default)); | |
862 ASSERT_EQ(id, id2); | |
863 } | |
864 | |
865 FileInfo dicom2, json2; | |
866 ASSERT_TRUE(context.GetIndex().LookupAttachment(dicom2, id, FileContentType_Dicom)); | |
867 ASSERT_TRUE(context.GetIndex().LookupAttachment(json2, id, FileContentType_DicomAsJson)); | |
868 | |
869 context.GetIndex().GetGlobalStatistics(diskSize, uncompressedSize, countPatients, | |
870 countStudies, countSeries, countInstances); | |
871 ASSERT_EQ(1u, countInstances); | |
872 ASSERT_EQ(dicom2.GetCompressedSize() + json2.GetCompressedSize(), diskSize); | |
873 ASSERT_EQ(dicom2.GetUncompressedSize() + json2.GetUncompressedSize(), uncompressedSize); | |
874 | |
875 if (overwrite) | |
876 { | |
877 ASSERT_NE(dicom1.GetUuid(), dicom2.GetUuid()); | |
878 ASSERT_NE(json1.GetUuid(), json2.GetUuid()); | |
879 ASSERT_NE(dicom1.GetUncompressedSize(), dicom2.GetUncompressedSize()); | |
880 ASSERT_NE(json1.GetUncompressedSize(), json2.GetUncompressedSize()); | |
881 | |
882 context.ReadDicomAsJson(tmp, id); | |
883 ASSERT_EQ("overwritten", tmp["0010,0010"]["Value"].asString()); | |
884 | |
885 { | |
886 ServerContext::DicomCacheLocker locker(context, id); | |
887 std::string tmp; | |
888 locker.GetDicom().GetTagValue(tmp, DICOM_TAG_PATIENT_NAME); | |
889 ASSERT_EQ("overwritten", tmp); | |
890 } | |
891 } | |
892 else | |
893 { | |
894 ASSERT_EQ(dicom1.GetUuid(), dicom2.GetUuid()); | |
895 ASSERT_EQ(json1.GetUuid(), json2.GetUuid()); | |
896 ASSERT_EQ(dicom1.GetUncompressedSize(), dicom2.GetUncompressedSize()); | |
897 ASSERT_EQ(json1.GetUncompressedSize(), json2.GetUncompressedSize()); | |
898 | |
899 context.ReadDicomAsJson(tmp, id); | |
900 ASSERT_EQ("name", tmp["0010,0010"]["Value"].asString()); | |
901 | |
902 { | |
903 ServerContext::DicomCacheLocker locker(context, id); | |
904 std::string tmp; | |
905 locker.GetDicom().GetTagValue(tmp, DICOM_TAG_PATIENT_NAME); | |
906 ASSERT_EQ("name", tmp); | |
907 } | |
908 } | |
909 | |
910 context.Stop(); | |
911 db.Close(); | |
912 } | |
913 } | |
914 | |
915 |