Mercurial > hg > orthanc
comparison OrthancServer/UnitTestsSources/ServerJobsTests.cpp @ 4060:149172a06b4d framework
splitting MultiThreadingTests.cpp into JobsTests.cpp and ServerJobsTests.cpp
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 11 Jun 2020 14:29:14 +0200 |
parents | OrthancServer/UnitTestsSources/MultiThreadingTests.cpp@05b8fd21089c |
children | 0953b3dc3261 |
comparison
equal
deleted
inserted
replaced
4059:e241e5f3f088 | 4060:149172a06b4d |
---|---|
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 "../../OrthancFramework/Sources/Compatibility.h" | |
38 #include "../../OrthancFramework/Sources/FileStorage/MemoryStorageArea.h" | |
39 #include "../../OrthancFramework/Sources/SerializationToolbox.h" | |
40 | |
41 #include "../Sources/Database/SQLiteDatabaseWrapper.h" | |
42 #include "../Sources/ServerContext.h" | |
43 #include "../Sources/ServerJobs/LuaJobManager.h" | |
44 #include "../Sources/ServerJobs/OrthancJobUnserializer.h" | |
45 | |
46 #include "../../OrthancFramework/Sources/JobsEngine/Operations/LogJobOperation.h" | |
47 #include "../Sources/ServerJobs/Operations/DicomInstanceOperationValue.h" | |
48 #include "../Sources/ServerJobs/Operations/DeleteResourceOperation.h" | |
49 #include "../Sources/ServerJobs/Operations/ModifyInstanceOperation.h" | |
50 #include "../Sources/ServerJobs/Operations/StorePeerOperation.h" | |
51 #include "../Sources/ServerJobs/Operations/StoreScuOperation.h" | |
52 #include "../Sources/ServerJobs/Operations/SystemCallOperation.h" | |
53 | |
54 #include "../Sources/ServerJobs/ArchiveJob.h" | |
55 #include "../Sources/ServerJobs/DicomModalityStoreJob.h" | |
56 #include "../Sources/ServerJobs/DicomMoveScuJob.h" | |
57 #include "../Sources/ServerJobs/MergeStudyJob.h" | |
58 #include "../Sources/ServerJobs/OrthancPeerStoreJob.h" | |
59 #include "../Sources/ServerJobs/ResourceModificationJob.h" | |
60 #include "../Sources/ServerJobs/SplitStudyJob.h" | |
61 | |
62 | |
63 using namespace Orthanc; | |
64 | |
65 namespace | |
66 { | |
67 class DummyJob : public IJob | |
68 { | |
69 private: | |
70 bool fails_; | |
71 unsigned int count_; | |
72 unsigned int steps_; | |
73 | |
74 public: | |
75 DummyJob() : | |
76 fails_(false), | |
77 count_(0), | |
78 steps_(4) | |
79 { | |
80 } | |
81 | |
82 explicit DummyJob(bool fails) : | |
83 fails_(fails), | |
84 count_(0), | |
85 steps_(4) | |
86 { | |
87 } | |
88 | |
89 virtual void Start() ORTHANC_OVERRIDE | |
90 { | |
91 } | |
92 | |
93 virtual void Reset() ORTHANC_OVERRIDE | |
94 { | |
95 } | |
96 | |
97 virtual JobStepResult Step(const std::string& jobId) ORTHANC_OVERRIDE | |
98 { | |
99 if (fails_) | |
100 { | |
101 return JobStepResult::Failure(ErrorCode_ParameterOutOfRange, NULL); | |
102 } | |
103 else if (count_ == steps_ - 1) | |
104 { | |
105 return JobStepResult::Success(); | |
106 } | |
107 else | |
108 { | |
109 count_++; | |
110 return JobStepResult::Continue(); | |
111 } | |
112 } | |
113 | |
114 virtual void Stop(JobStopReason reason) ORTHANC_OVERRIDE | |
115 { | |
116 } | |
117 | |
118 virtual float GetProgress() ORTHANC_OVERRIDE | |
119 { | |
120 return static_cast<float>(count_) / static_cast<float>(steps_ - 1); | |
121 } | |
122 | |
123 virtual void GetJobType(std::string& type) ORTHANC_OVERRIDE | |
124 { | |
125 type = "DummyJob"; | |
126 } | |
127 | |
128 virtual bool Serialize(Json::Value& value) ORTHANC_OVERRIDE | |
129 { | |
130 value = Json::objectValue; | |
131 value["Type"] = "DummyJob"; | |
132 return true; | |
133 } | |
134 | |
135 virtual void GetPublicContent(Json::Value& value) ORTHANC_OVERRIDE | |
136 { | |
137 value["hello"] = "world"; | |
138 } | |
139 | |
140 virtual bool GetOutput(std::string& output, | |
141 MimeType& mime, | |
142 const std::string& key) ORTHANC_OVERRIDE | |
143 { | |
144 return false; | |
145 } | |
146 }; | |
147 | |
148 | |
149 class DummyInstancesJob : public SetOfInstancesJob | |
150 { | |
151 private: | |
152 bool trailingStepDone_; | |
153 | |
154 protected: | |
155 virtual bool HandleInstance(const std::string& instance) ORTHANC_OVERRIDE | |
156 { | |
157 return (instance != "nope"); | |
158 } | |
159 | |
160 virtual bool HandleTrailingStep() ORTHANC_OVERRIDE | |
161 { | |
162 if (HasTrailingStep()) | |
163 { | |
164 if (trailingStepDone_) | |
165 { | |
166 throw OrthancException(ErrorCode_InternalError); | |
167 } | |
168 else | |
169 { | |
170 trailingStepDone_ = true; | |
171 return true; | |
172 } | |
173 } | |
174 else | |
175 { | |
176 throw OrthancException(ErrorCode_InternalError); | |
177 } | |
178 } | |
179 | |
180 public: | |
181 DummyInstancesJob() : | |
182 trailingStepDone_(false) | |
183 { | |
184 } | |
185 | |
186 DummyInstancesJob(const Json::Value& value) : | |
187 SetOfInstancesJob(value) | |
188 { | |
189 if (HasTrailingStep()) | |
190 { | |
191 trailingStepDone_ = (GetPosition() == GetCommandsCount()); | |
192 } | |
193 else | |
194 { | |
195 trailingStepDone_ = false; | |
196 } | |
197 } | |
198 | |
199 bool IsTrailingStepDone() const | |
200 { | |
201 return trailingStepDone_; | |
202 } | |
203 | |
204 virtual void Stop(JobStopReason reason) ORTHANC_OVERRIDE | |
205 { | |
206 } | |
207 | |
208 virtual void GetJobType(std::string& s) ORTHANC_OVERRIDE | |
209 { | |
210 s = "DummyInstancesJob"; | |
211 } | |
212 }; | |
213 | |
214 | |
215 class DummyUnserializer : public GenericJobUnserializer | |
216 { | |
217 public: | |
218 virtual IJob* UnserializeJob(const Json::Value& value) ORTHANC_OVERRIDE | |
219 { | |
220 if (SerializationToolbox::ReadString(value, "Type") == "DummyInstancesJob") | |
221 { | |
222 return new DummyInstancesJob(value); | |
223 } | |
224 else if (SerializationToolbox::ReadString(value, "Type") == "DummyJob") | |
225 { | |
226 return new DummyJob; | |
227 } | |
228 else | |
229 { | |
230 return GenericJobUnserializer::UnserializeJob(value); | |
231 } | |
232 } | |
233 }; | |
234 | |
235 | |
236 class DynamicInteger : public IDynamicObject | |
237 { | |
238 private: | |
239 int value_; | |
240 std::set<int>& target_; | |
241 | |
242 public: | |
243 DynamicInteger(int value, std::set<int>& target) : | |
244 value_(value), target_(target) | |
245 { | |
246 } | |
247 | |
248 int GetValue() const | |
249 { | |
250 return value_; | |
251 } | |
252 }; | |
253 } | |
254 | |
255 | |
256 TEST(JobsEngine, DISABLED_Lua) | |
257 { | |
258 JobsEngine engine(10); | |
259 engine.SetThreadSleep(10); | |
260 engine.SetWorkersCount(2); | |
261 engine.Start(); | |
262 | |
263 LuaJobManager lua; | |
264 lua.SetMaxOperationsPerJob(5); | |
265 lua.SetTrailingOperationTimeout(200); | |
266 | |
267 for (size_t i = 0; i < 30; i++) | |
268 { | |
269 boost::this_thread::sleep(boost::posix_time::milliseconds(150)); | |
270 | |
271 LuaJobManager::Lock lock(lua, engine); | |
272 size_t a = lock.AddLogOperation(); | |
273 size_t b = lock.AddLogOperation(); | |
274 size_t c = lock.AddSystemCallOperation("echo"); | |
275 lock.AddStringInput(a, boost::lexical_cast<std::string>(i)); | |
276 lock.AddNullInput(a); | |
277 lock.Connect(a, b); | |
278 lock.Connect(a, c); | |
279 } | |
280 | |
281 boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); | |
282 | |
283 engine.Stop(); | |
284 } | |
285 | |
286 | |
287 static bool CheckSameJson(const Json::Value& a, | |
288 const Json::Value& b) | |
289 { | |
290 std::string s = a.toStyledString(); | |
291 std::string t = b.toStyledString(); | |
292 | |
293 if (s == t) | |
294 { | |
295 return true; | |
296 } | |
297 else | |
298 { | |
299 LOG(ERROR) << "Expected serialization: " << s; | |
300 LOG(ERROR) << "Actual serialization: " << t; | |
301 return false; | |
302 } | |
303 } | |
304 | |
305 | |
306 static bool CheckIdempotentSetOfInstances(IJobUnserializer& unserializer, | |
307 SetOfInstancesJob& job) | |
308 { | |
309 Json::Value a = 42; | |
310 | |
311 if (!job.Serialize(a)) | |
312 { | |
313 return false; | |
314 } | |
315 else | |
316 { | |
317 std::unique_ptr<SetOfInstancesJob> unserialized | |
318 (dynamic_cast<SetOfInstancesJob*>(unserializer.UnserializeJob(a))); | |
319 | |
320 Json::Value b = 43; | |
321 if (unserialized->Serialize(b)) | |
322 { | |
323 return (CheckSameJson(a, b) && | |
324 job.HasTrailingStep() == unserialized->HasTrailingStep() && | |
325 job.GetPosition() == unserialized->GetPosition() && | |
326 job.GetInstancesCount() == unserialized->GetInstancesCount() && | |
327 job.GetCommandsCount() == unserialized->GetCommandsCount()); | |
328 } | |
329 else | |
330 { | |
331 return false; | |
332 } | |
333 } | |
334 } | |
335 | |
336 | |
337 static bool CheckIdempotentSerialization(IJobUnserializer& unserializer, | |
338 IJobOperation& operation) | |
339 { | |
340 Json::Value a = 42; | |
341 operation.Serialize(a); | |
342 | |
343 std::unique_ptr<IJobOperation> unserialized(unserializer.UnserializeOperation(a)); | |
344 | |
345 Json::Value b = 43; | |
346 unserialized->Serialize(b); | |
347 | |
348 return CheckSameJson(a, b); | |
349 } | |
350 | |
351 | |
352 static bool CheckIdempotentSerialization(IJobUnserializer& unserializer, | |
353 JobOperationValue& value) | |
354 { | |
355 Json::Value a = 42; | |
356 value.Serialize(a); | |
357 | |
358 std::unique_ptr<JobOperationValue> unserialized(unserializer.UnserializeValue(a)); | |
359 | |
360 Json::Value b = 43; | |
361 unserialized->Serialize(b); | |
362 | |
363 return CheckSameJson(a, b); | |
364 } | |
365 | |
366 | |
367 TEST(JobsSerialization, GenericOperations) | |
368 { | |
369 DummyUnserializer unserializer; | |
370 Json::Value s; | |
371 | |
372 { | |
373 LogJobOperation operation; | |
374 | |
375 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
376 operation.Serialize(s); | |
377 } | |
378 | |
379 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException); | |
380 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException); | |
381 | |
382 { | |
383 std::unique_ptr<IJobOperation> operation; | |
384 operation.reset(unserializer.UnserializeOperation(s)); | |
385 | |
386 // Make sure that we have indeed unserialized a log operation | |
387 Json::Value dummy; | |
388 ASSERT_THROW(dynamic_cast<DeleteResourceOperation&>(*operation).Serialize(dummy), std::bad_cast); | |
389 dynamic_cast<LogJobOperation&>(*operation).Serialize(dummy); | |
390 } | |
391 } | |
392 | |
393 | |
394 TEST(JobsSerialization, DicomInstanceOrigin) | |
395 { | |
396 Json::Value s; | |
397 std::string t; | |
398 | |
399 { | |
400 DicomInstanceOrigin origin; | |
401 | |
402 s = 42; | |
403 origin.Serialize(s); | |
404 } | |
405 | |
406 { | |
407 DicomInstanceOrigin origin(s); | |
408 ASSERT_EQ(RequestOrigin_Unknown, origin.GetRequestOrigin()); | |
409 ASSERT_EQ("", std::string(origin.GetRemoteAetC())); | |
410 ASSERT_FALSE(origin.LookupRemoteIp(t)); | |
411 ASSERT_FALSE(origin.LookupRemoteAet(t)); | |
412 ASSERT_FALSE(origin.LookupCalledAet(t)); | |
413 ASSERT_FALSE(origin.LookupHttpUsername(t)); | |
414 } | |
415 | |
416 { | |
417 DicomInstanceOrigin origin(DicomInstanceOrigin::FromDicomProtocol("host", "aet", "called")); | |
418 | |
419 s = 42; | |
420 origin.Serialize(s); | |
421 } | |
422 | |
423 { | |
424 DicomInstanceOrigin origin(s); | |
425 ASSERT_EQ(RequestOrigin_DicomProtocol, origin.GetRequestOrigin()); | |
426 ASSERT_EQ("aet", std::string(origin.GetRemoteAetC())); | |
427 ASSERT_TRUE(origin.LookupRemoteIp(t)); ASSERT_EQ("host", t); | |
428 ASSERT_TRUE(origin.LookupRemoteAet(t)); ASSERT_EQ("aet", t); | |
429 ASSERT_TRUE(origin.LookupCalledAet(t)); ASSERT_EQ("called", t); | |
430 ASSERT_FALSE(origin.LookupHttpUsername(t)); | |
431 } | |
432 | |
433 { | |
434 DicomInstanceOrigin origin(DicomInstanceOrigin::FromHttp("host", "username")); | |
435 | |
436 s = 42; | |
437 origin.Serialize(s); | |
438 } | |
439 | |
440 { | |
441 DicomInstanceOrigin origin(s); | |
442 ASSERT_EQ(RequestOrigin_RestApi, origin.GetRequestOrigin()); | |
443 ASSERT_EQ("", std::string(origin.GetRemoteAetC())); | |
444 ASSERT_TRUE(origin.LookupRemoteIp(t)); ASSERT_EQ("host", t); | |
445 ASSERT_FALSE(origin.LookupRemoteAet(t)); | |
446 ASSERT_FALSE(origin.LookupCalledAet(t)); | |
447 ASSERT_TRUE(origin.LookupHttpUsername(t)); ASSERT_EQ("username", t); | |
448 } | |
449 | |
450 { | |
451 DicomInstanceOrigin origin(DicomInstanceOrigin::FromLua()); | |
452 | |
453 s = 42; | |
454 origin.Serialize(s); | |
455 } | |
456 | |
457 { | |
458 DicomInstanceOrigin origin(s); | |
459 ASSERT_EQ(RequestOrigin_Lua, origin.GetRequestOrigin()); | |
460 ASSERT_FALSE(origin.LookupRemoteIp(t)); | |
461 ASSERT_FALSE(origin.LookupRemoteAet(t)); | |
462 ASSERT_FALSE(origin.LookupCalledAet(t)); | |
463 ASSERT_FALSE(origin.LookupHttpUsername(t)); | |
464 } | |
465 | |
466 { | |
467 DicomInstanceOrigin origin(DicomInstanceOrigin::FromPlugins()); | |
468 | |
469 s = 42; | |
470 origin.Serialize(s); | |
471 } | |
472 | |
473 { | |
474 DicomInstanceOrigin origin(s); | |
475 ASSERT_EQ(RequestOrigin_Plugins, origin.GetRequestOrigin()); | |
476 ASSERT_FALSE(origin.LookupRemoteIp(t)); | |
477 ASSERT_FALSE(origin.LookupRemoteAet(t)); | |
478 ASSERT_FALSE(origin.LookupCalledAet(t)); | |
479 ASSERT_FALSE(origin.LookupHttpUsername(t)); | |
480 } | |
481 } | |
482 | |
483 | |
484 namespace | |
485 { | |
486 class OrthancJobsSerialization : public testing::Test | |
487 { | |
488 private: | |
489 MemoryStorageArea storage_; | |
490 SQLiteDatabaseWrapper db_; // The SQLite DB is in memory | |
491 std::unique_ptr<ServerContext> context_; | |
492 | |
493 public: | |
494 OrthancJobsSerialization() | |
495 { | |
496 db_.Open(); | |
497 context_.reset(new ServerContext(db_, storage_, true /* running unit tests */, 10)); | |
498 context_->SetupJobsEngine(true, false); | |
499 } | |
500 | |
501 virtual ~OrthancJobsSerialization() ORTHANC_OVERRIDE | |
502 { | |
503 context_->Stop(); | |
504 context_.reset(NULL); | |
505 db_.Close(); | |
506 } | |
507 | |
508 ServerContext& GetContext() | |
509 { | |
510 return *context_; | |
511 } | |
512 | |
513 bool CreateInstance(std::string& id) | |
514 { | |
515 // Create a sample DICOM file | |
516 ParsedDicomFile dicom(true); | |
517 dicom.Replace(DICOM_TAG_PATIENT_NAME, std::string("JODOGNE"), | |
518 false, DicomReplaceMode_InsertIfAbsent, ""); | |
519 | |
520 DicomInstanceToStore toStore; | |
521 toStore.SetParsedDicomFile(dicom); | |
522 | |
523 return (context_->Store(id, toStore, StoreInstanceMode_Default) == StoreStatus_Success); | |
524 } | |
525 }; | |
526 } | |
527 | |
528 | |
529 TEST_F(OrthancJobsSerialization, Values) | |
530 { | |
531 std::string id; | |
532 ASSERT_TRUE(CreateInstance(id)); | |
533 | |
534 Json::Value s; | |
535 OrthancJobUnserializer unserializer(GetContext()); | |
536 | |
537 { | |
538 DicomInstanceOperationValue instance(GetContext(), id); | |
539 | |
540 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, instance)); | |
541 instance.Serialize(s); | |
542 } | |
543 | |
544 std::unique_ptr<JobOperationValue> value; | |
545 value.reset(unserializer.UnserializeValue(s)); | |
546 ASSERT_EQ(JobOperationValue::Type_DicomInstance, value->GetType()); | |
547 ASSERT_EQ(id, dynamic_cast<DicomInstanceOperationValue&>(*value).GetId()); | |
548 | |
549 { | |
550 std::string content; | |
551 dynamic_cast<DicomInstanceOperationValue&>(*value).ReadDicom(content); | |
552 | |
553 ParsedDicomFile dicom(content); | |
554 ASSERT_TRUE(dicom.GetTagValue(content, DICOM_TAG_PATIENT_NAME)); | |
555 ASSERT_EQ("JODOGNE", content); | |
556 } | |
557 } | |
558 | |
559 | |
560 TEST_F(OrthancJobsSerialization, Operations) | |
561 { | |
562 std::string id; | |
563 ASSERT_TRUE(CreateInstance(id)); | |
564 | |
565 Json::Value s; | |
566 OrthancJobUnserializer unserializer(GetContext()); | |
567 | |
568 // DeleteResourceOperation | |
569 | |
570 { | |
571 DeleteResourceOperation operation(GetContext()); | |
572 | |
573 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
574 operation.Serialize(s); | |
575 } | |
576 | |
577 std::unique_ptr<IJobOperation> operation; | |
578 | |
579 { | |
580 operation.reset(unserializer.UnserializeOperation(s)); | |
581 | |
582 Json::Value dummy; | |
583 ASSERT_THROW(dynamic_cast<LogJobOperation&>(*operation).Serialize(dummy), std::bad_cast); | |
584 dynamic_cast<DeleteResourceOperation&>(*operation).Serialize(dummy); | |
585 } | |
586 | |
587 // StorePeerOperation | |
588 | |
589 { | |
590 WebServiceParameters peer; | |
591 peer.SetUrl("http://localhost/"); | |
592 peer.SetCredentials("username", "password"); | |
593 peer.SetPkcs11Enabled(true); | |
594 | |
595 StorePeerOperation operation(peer); | |
596 | |
597 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
598 operation.Serialize(s); | |
599 } | |
600 | |
601 { | |
602 operation.reset(unserializer.UnserializeOperation(s)); | |
603 | |
604 const StorePeerOperation& tmp = dynamic_cast<StorePeerOperation&>(*operation); | |
605 ASSERT_EQ("http://localhost/", tmp.GetPeer().GetUrl()); | |
606 ASSERT_EQ("username", tmp.GetPeer().GetUsername()); | |
607 ASSERT_EQ("password", tmp.GetPeer().GetPassword()); | |
608 ASSERT_TRUE(tmp.GetPeer().IsPkcs11Enabled()); | |
609 } | |
610 | |
611 // StoreScuOperation | |
612 | |
613 { | |
614 TimeoutDicomConnectionManager luaManager; | |
615 | |
616 { | |
617 RemoteModalityParameters modality; | |
618 modality.SetApplicationEntityTitle("REMOTE"); | |
619 modality.SetHost("192.168.1.1"); | |
620 modality.SetPortNumber(1000); | |
621 modality.SetManufacturer(ModalityManufacturer_StoreScp); | |
622 | |
623 StoreScuOperation operation(GetContext(), luaManager, "TEST", modality); | |
624 | |
625 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
626 operation.Serialize(s); | |
627 } | |
628 | |
629 { | |
630 operation.reset(unserializer.UnserializeOperation(s)); | |
631 | |
632 const StoreScuOperation& tmp = dynamic_cast<StoreScuOperation&>(*operation); | |
633 ASSERT_EQ("REMOTE", tmp.GetRemoteModality().GetApplicationEntityTitle()); | |
634 ASSERT_EQ("192.168.1.1", tmp.GetRemoteModality().GetHost()); | |
635 ASSERT_EQ(1000, tmp.GetRemoteModality().GetPortNumber()); | |
636 ASSERT_EQ(ModalityManufacturer_StoreScp, tmp.GetRemoteModality().GetManufacturer()); | |
637 ASSERT_EQ("TEST", tmp.GetLocalAet()); | |
638 } | |
639 } | |
640 | |
641 // SystemCallOperation | |
642 | |
643 { | |
644 SystemCallOperation operation(std::string("echo")); | |
645 operation.AddPreArgument("a"); | |
646 operation.AddPreArgument("b"); | |
647 operation.AddPostArgument("c"); | |
648 | |
649 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
650 operation.Serialize(s); | |
651 } | |
652 | |
653 { | |
654 operation.reset(unserializer.UnserializeOperation(s)); | |
655 | |
656 const SystemCallOperation& tmp = dynamic_cast<SystemCallOperation&>(*operation); | |
657 ASSERT_EQ("echo", tmp.GetCommand()); | |
658 ASSERT_EQ(2u, tmp.GetPreArgumentsCount()); | |
659 ASSERT_EQ(1u, tmp.GetPostArgumentsCount()); | |
660 ASSERT_EQ("a", tmp.GetPreArgument(0)); | |
661 ASSERT_EQ("b", tmp.GetPreArgument(1)); | |
662 ASSERT_EQ("c", tmp.GetPostArgument(0)); | |
663 } | |
664 | |
665 // ModifyInstanceOperation | |
666 | |
667 { | |
668 std::unique_ptr<DicomModification> modification(new DicomModification); | |
669 modification->SetupAnonymization(DicomVersion_2008); | |
670 | |
671 ModifyInstanceOperation operation(GetContext(), RequestOrigin_Lua, modification.release()); | |
672 | |
673 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, operation)); | |
674 operation.Serialize(s); | |
675 } | |
676 | |
677 { | |
678 operation.reset(unserializer.UnserializeOperation(s)); | |
679 | |
680 const ModifyInstanceOperation& tmp = dynamic_cast<ModifyInstanceOperation&>(*operation); | |
681 ASSERT_EQ(RequestOrigin_Lua, tmp.GetRequestOrigin()); | |
682 ASSERT_TRUE(tmp.GetModification().IsRemoved(DICOM_TAG_STUDY_DESCRIPTION)); | |
683 } | |
684 } | |
685 | |
686 | |
687 TEST_F(OrthancJobsSerialization, Jobs) | |
688 { | |
689 Json::Value s; | |
690 | |
691 // ArchiveJob | |
692 | |
693 { | |
694 ArchiveJob job(GetContext(), false, false); | |
695 ASSERT_FALSE(job.Serialize(s)); // Cannot serialize this | |
696 } | |
697 | |
698 // DicomModalityStoreJob | |
699 | |
700 OrthancJobUnserializer unserializer(GetContext()); | |
701 | |
702 { | |
703 RemoteModalityParameters modality; | |
704 modality.SetApplicationEntityTitle("REMOTE"); | |
705 modality.SetHost("192.168.1.1"); | |
706 modality.SetPortNumber(1000); | |
707 modality.SetManufacturer(ModalityManufacturer_StoreScp); | |
708 | |
709 DicomModalityStoreJob job(GetContext()); | |
710 job.SetLocalAet("LOCAL"); | |
711 job.SetRemoteModality(modality); | |
712 job.SetMoveOriginator("MOVESCU", 42); | |
713 | |
714 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
715 ASSERT_TRUE(job.Serialize(s)); | |
716 } | |
717 | |
718 { | |
719 std::unique_ptr<IJob> job; | |
720 job.reset(unserializer.UnserializeJob(s)); | |
721 | |
722 DicomModalityStoreJob& tmp = dynamic_cast<DicomModalityStoreJob&>(*job); | |
723 ASSERT_EQ("LOCAL", tmp.GetParameters().GetLocalApplicationEntityTitle()); | |
724 ASSERT_EQ("REMOTE", tmp.GetParameters().GetRemoteModality().GetApplicationEntityTitle()); | |
725 ASSERT_EQ("192.168.1.1", tmp.GetParameters().GetRemoteModality().GetHost()); | |
726 ASSERT_EQ(1000, tmp.GetParameters().GetRemoteModality().GetPortNumber()); | |
727 ASSERT_EQ(ModalityManufacturer_StoreScp, tmp.GetParameters().GetRemoteModality().GetManufacturer()); | |
728 ASSERT_TRUE(tmp.HasMoveOriginator()); | |
729 ASSERT_EQ("MOVESCU", tmp.GetMoveOriginatorAet()); | |
730 ASSERT_EQ(42, tmp.GetMoveOriginatorId()); | |
731 } | |
732 | |
733 // OrthancPeerStoreJob | |
734 | |
735 { | |
736 WebServiceParameters peer; | |
737 peer.SetUrl("http://localhost/"); | |
738 peer.SetCredentials("username", "password"); | |
739 peer.SetPkcs11Enabled(true); | |
740 | |
741 OrthancPeerStoreJob job(GetContext()); | |
742 job.SetPeer(peer); | |
743 | |
744 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
745 ASSERT_TRUE(job.Serialize(s)); | |
746 } | |
747 | |
748 { | |
749 std::unique_ptr<IJob> job; | |
750 job.reset(unserializer.UnserializeJob(s)); | |
751 | |
752 OrthancPeerStoreJob& tmp = dynamic_cast<OrthancPeerStoreJob&>(*job); | |
753 ASSERT_EQ("http://localhost/", tmp.GetPeer().GetUrl()); | |
754 ASSERT_EQ("username", tmp.GetPeer().GetUsername()); | |
755 ASSERT_EQ("password", tmp.GetPeer().GetPassword()); | |
756 ASSERT_TRUE(tmp.GetPeer().IsPkcs11Enabled()); | |
757 ASSERT_FALSE(tmp.IsTranscode()); | |
758 ASSERT_THROW(tmp.GetTransferSyntax(), OrthancException); | |
759 } | |
760 | |
761 { | |
762 OrthancPeerStoreJob job(GetContext()); | |
763 ASSERT_THROW(job.SetTranscode("nope"), OrthancException); | |
764 job.SetTranscode("1.2.840.10008.1.2.4.50"); | |
765 | |
766 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
767 ASSERT_TRUE(job.Serialize(s)); | |
768 } | |
769 | |
770 { | |
771 std::unique_ptr<IJob> job; | |
772 job.reset(unserializer.UnserializeJob(s)); | |
773 | |
774 OrthancPeerStoreJob& tmp = dynamic_cast<OrthancPeerStoreJob&>(*job); | |
775 ASSERT_EQ("http://127.0.0.1:8042/", tmp.GetPeer().GetUrl()); | |
776 ASSERT_EQ("", tmp.GetPeer().GetUsername()); | |
777 ASSERT_EQ("", tmp.GetPeer().GetPassword()); | |
778 ASSERT_FALSE(tmp.GetPeer().IsPkcs11Enabled()); | |
779 ASSERT_TRUE(tmp.IsTranscode()); | |
780 ASSERT_EQ(DicomTransferSyntax_JPEGProcess1, tmp.GetTransferSyntax()); | |
781 } | |
782 | |
783 // ResourceModificationJob | |
784 | |
785 { | |
786 std::unique_ptr<DicomModification> modification(new DicomModification); | |
787 modification->SetupAnonymization(DicomVersion_2008); | |
788 | |
789 ResourceModificationJob job(GetContext()); | |
790 job.SetModification(modification.release(), ResourceType_Patient, true); | |
791 job.SetOrigin(DicomInstanceOrigin::FromLua()); | |
792 | |
793 job.AddTrailingStep(); // Necessary since 1.7.0 | |
794 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
795 ASSERT_TRUE(job.Serialize(s)); | |
796 } | |
797 | |
798 { | |
799 std::unique_ptr<IJob> job; | |
800 job.reset(unserializer.UnserializeJob(s)); | |
801 | |
802 ResourceModificationJob& tmp = dynamic_cast<ResourceModificationJob&>(*job); | |
803 ASSERT_TRUE(tmp.IsAnonymization()); | |
804 ASSERT_FALSE(tmp.IsTranscode()); | |
805 ASSERT_THROW(tmp.GetTransferSyntax(), OrthancException); | |
806 ASSERT_EQ(RequestOrigin_Lua, tmp.GetOrigin().GetRequestOrigin()); | |
807 ASSERT_TRUE(tmp.GetModification().IsRemoved(DICOM_TAG_STUDY_DESCRIPTION)); | |
808 } | |
809 | |
810 { | |
811 ResourceModificationJob job(GetContext()); | |
812 ASSERT_THROW(job.SetTranscode("nope"), OrthancException); | |
813 job.SetTranscode(DicomTransferSyntax_JPEGProcess1); | |
814 | |
815 job.AddTrailingStep(); // Necessary since 1.7.0 | |
816 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
817 ASSERT_TRUE(job.Serialize(s)); | |
818 } | |
819 | |
820 { | |
821 std::unique_ptr<IJob> job; | |
822 job.reset(unserializer.UnserializeJob(s)); | |
823 | |
824 ResourceModificationJob& tmp = dynamic_cast<ResourceModificationJob&>(*job); | |
825 ASSERT_FALSE(tmp.IsAnonymization()); | |
826 ASSERT_TRUE(tmp.IsTranscode()); | |
827 ASSERT_EQ(DicomTransferSyntax_JPEGProcess1, tmp.GetTransferSyntax()); | |
828 ASSERT_EQ(RequestOrigin_Unknown, tmp.GetOrigin().GetRequestOrigin()); | |
829 } | |
830 | |
831 // SplitStudyJob | |
832 | |
833 std::string instance; | |
834 ASSERT_TRUE(CreateInstance(instance)); | |
835 | |
836 std::string study, series; | |
837 | |
838 { | |
839 ServerContext::DicomCacheLocker lock(GetContext(), instance); | |
840 study = lock.GetDicom().GetHasher().HashStudy(); | |
841 series = lock.GetDicom().GetHasher().HashSeries(); | |
842 } | |
843 | |
844 { | |
845 std::list<std::string> tmp; | |
846 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Study); | |
847 ASSERT_EQ(1u, tmp.size()); | |
848 ASSERT_EQ(study, tmp.front()); | |
849 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Series); | |
850 ASSERT_EQ(1u, tmp.size()); | |
851 ASSERT_EQ(series, tmp.front()); | |
852 } | |
853 | |
854 std::string study2; | |
855 | |
856 { | |
857 std::string a, b; | |
858 | |
859 { | |
860 ASSERT_THROW(SplitStudyJob(GetContext(), std::string("nope")), OrthancException); | |
861 | |
862 SplitStudyJob job(GetContext(), study); | |
863 job.SetKeepSource(true); | |
864 job.AddSourceSeries(series); | |
865 ASSERT_THROW(job.AddSourceSeries("nope"), OrthancException); | |
866 job.SetOrigin(DicomInstanceOrigin::FromLua()); | |
867 job.Replace(DICOM_TAG_PATIENT_NAME, "hello"); | |
868 job.Remove(DICOM_TAG_PATIENT_BIRTH_DATE); | |
869 ASSERT_THROW(job.Replace(DICOM_TAG_SERIES_DESCRIPTION, "nope"), OrthancException); | |
870 ASSERT_THROW(job.Remove(DICOM_TAG_SERIES_DESCRIPTION), OrthancException); | |
871 | |
872 ASSERT_TRUE(job.GetTargetStudy().empty()); | |
873 a = job.GetTargetStudyUid(); | |
874 ASSERT_TRUE(job.LookupTargetSeriesUid(b, series)); | |
875 | |
876 job.AddTrailingStep(); | |
877 job.Start(); | |
878 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode()); | |
879 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode()); | |
880 | |
881 study2 = job.GetTargetStudy(); | |
882 ASSERT_FALSE(study2.empty()); | |
883 | |
884 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
885 ASSERT_TRUE(job.Serialize(s)); | |
886 } | |
887 | |
888 { | |
889 std::unique_ptr<IJob> job; | |
890 job.reset(unserializer.UnserializeJob(s)); | |
891 | |
892 SplitStudyJob& tmp = dynamic_cast<SplitStudyJob&>(*job); | |
893 ASSERT_TRUE(tmp.IsKeepSource()); | |
894 ASSERT_EQ(study, tmp.GetSourceStudy()); | |
895 ASSERT_EQ(a, tmp.GetTargetStudyUid()); | |
896 ASSERT_EQ(RequestOrigin_Lua, tmp.GetOrigin().GetRequestOrigin()); | |
897 | |
898 std::string s; | |
899 ASSERT_EQ(study2, tmp.GetTargetStudy()); | |
900 ASSERT_FALSE(tmp.LookupTargetSeriesUid(s, "nope")); | |
901 ASSERT_TRUE(tmp.LookupTargetSeriesUid(s, series)); | |
902 ASSERT_EQ(b, s); | |
903 | |
904 ASSERT_FALSE(tmp.LookupReplacement(s, DICOM_TAG_STUDY_DESCRIPTION)); | |
905 ASSERT_TRUE(tmp.LookupReplacement(s, DICOM_TAG_PATIENT_NAME)); | |
906 ASSERT_EQ("hello", s); | |
907 ASSERT_FALSE(tmp.IsRemoved(DICOM_TAG_PATIENT_NAME)); | |
908 ASSERT_TRUE(tmp.IsRemoved(DICOM_TAG_PATIENT_BIRTH_DATE)); | |
909 } | |
910 } | |
911 | |
912 { | |
913 std::list<std::string> tmp; | |
914 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Study); | |
915 ASSERT_EQ(2u, tmp.size()); | |
916 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Series); | |
917 ASSERT_EQ(2u, tmp.size()); | |
918 } | |
919 | |
920 // MergeStudyJob | |
921 | |
922 { | |
923 ASSERT_THROW(SplitStudyJob(GetContext(), std::string("nope")), OrthancException); | |
924 | |
925 MergeStudyJob job(GetContext(), study); | |
926 job.SetKeepSource(true); | |
927 job.AddSource(study2); | |
928 ASSERT_THROW(job.AddSourceSeries("nope"), OrthancException); | |
929 ASSERT_THROW(job.AddSourceStudy("nope"), OrthancException); | |
930 ASSERT_THROW(job.AddSource("nope"), OrthancException); | |
931 job.SetOrigin(DicomInstanceOrigin::FromLua()); | |
932 | |
933 ASSERT_EQ(job.GetTargetStudy(), study); | |
934 | |
935 job.AddTrailingStep(); | |
936 job.Start(); | |
937 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode()); | |
938 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode()); | |
939 | |
940 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job)); | |
941 ASSERT_TRUE(job.Serialize(s)); | |
942 } | |
943 | |
944 { | |
945 std::list<std::string> tmp; | |
946 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Study); | |
947 ASSERT_EQ(2u, tmp.size()); | |
948 GetContext().GetIndex().GetAllUuids(tmp, ResourceType_Series); | |
949 ASSERT_EQ(3u, tmp.size()); | |
950 } | |
951 | |
952 { | |
953 std::unique_ptr<IJob> job; | |
954 job.reset(unserializer.UnserializeJob(s)); | |
955 | |
956 MergeStudyJob& tmp = dynamic_cast<MergeStudyJob&>(*job); | |
957 ASSERT_TRUE(tmp.IsKeepSource()); | |
958 ASSERT_EQ(study, tmp.GetTargetStudy()); | |
959 ASSERT_EQ(RequestOrigin_Lua, tmp.GetOrigin().GetRequestOrigin()); | |
960 } | |
961 } | |
962 | |
963 | |
964 | |
965 TEST_F(OrthancJobsSerialization, DicomAssociationParameters) | |
966 { | |
967 Json::Value v; | |
968 | |
969 { | |
970 v = Json::objectValue; | |
971 DicomAssociationParameters p; | |
972 p.SerializeJob(v); | |
973 } | |
974 | |
975 { | |
976 DicomAssociationParameters p = DicomAssociationParameters::UnserializeJob(v); | |
977 ASSERT_EQ("ORTHANC", p.GetLocalApplicationEntityTitle()); | |
978 ASSERT_EQ("ANY-SCP", p.GetRemoteModality().GetApplicationEntityTitle()); | |
979 ASSERT_EQ(104u, p.GetRemoteModality().GetPortNumber()); | |
980 ASSERT_EQ(ModalityManufacturer_Generic, p.GetRemoteModality().GetManufacturer()); | |
981 ASSERT_EQ("127.0.0.1", p.GetRemoteModality().GetHost()); | |
982 ASSERT_EQ(DicomAssociationParameters::GetDefaultTimeout(), p.GetTimeout()); | |
983 } | |
984 | |
985 { | |
986 v = Json::objectValue; | |
987 DicomAssociationParameters p; | |
988 p.SetLocalApplicationEntityTitle("HELLO"); | |
989 p.SetRemoteApplicationEntityTitle("WORLD"); | |
990 p.SetRemotePort(42); | |
991 p.SetRemoteHost("MY_HOST"); | |
992 p.SetTimeout(43); | |
993 p.SerializeJob(v); | |
994 } | |
995 | |
996 { | |
997 DicomAssociationParameters p = DicomAssociationParameters::UnserializeJob(v); | |
998 ASSERT_EQ("HELLO", p.GetLocalApplicationEntityTitle()); | |
999 ASSERT_EQ("WORLD", p.GetRemoteModality().GetApplicationEntityTitle()); | |
1000 ASSERT_EQ(42u, p.GetRemoteModality().GetPortNumber()); | |
1001 ASSERT_EQ(ModalityManufacturer_Generic, p.GetRemoteModality().GetManufacturer()); | |
1002 ASSERT_EQ("MY_HOST", p.GetRemoteModality().GetHost()); | |
1003 ASSERT_EQ(43u, p.GetTimeout()); | |
1004 } | |
1005 | |
1006 { | |
1007 DicomModalityStoreJob job(GetContext()); | |
1008 job.Serialize(v); | |
1009 } | |
1010 | |
1011 { | |
1012 OrthancJobUnserializer unserializer(GetContext()); | |
1013 std::unique_ptr<DicomModalityStoreJob> job( | |
1014 dynamic_cast<DicomModalityStoreJob*>(unserializer.UnserializeJob(v))); | |
1015 ASSERT_EQ("ORTHANC", job->GetParameters().GetLocalApplicationEntityTitle()); | |
1016 ASSERT_EQ("ANY-SCP", job->GetParameters().GetRemoteModality().GetApplicationEntityTitle()); | |
1017 ASSERT_EQ("127.0.0.1", job->GetParameters().GetRemoteModality().GetHost()); | |
1018 ASSERT_EQ(104u, job->GetParameters().GetRemoteModality().GetPortNumber()); | |
1019 ASSERT_EQ(ModalityManufacturer_Generic, job->GetParameters().GetRemoteModality().GetManufacturer()); | |
1020 ASSERT_EQ(DicomAssociationParameters::GetDefaultTimeout(), job->GetParameters().GetTimeout()); | |
1021 ASSERT_FALSE(job->HasMoveOriginator()); | |
1022 ASSERT_THROW(job->GetMoveOriginatorAet(), OrthancException); | |
1023 ASSERT_THROW(job->GetMoveOriginatorId(), OrthancException); | |
1024 ASSERT_FALSE(job->HasStorageCommitment()); | |
1025 } | |
1026 | |
1027 { | |
1028 RemoteModalityParameters r; | |
1029 r.SetApplicationEntityTitle("HELLO"); | |
1030 r.SetPortNumber(42); | |
1031 r.SetHost("MY_HOST"); | |
1032 | |
1033 DicomModalityStoreJob job(GetContext()); | |
1034 job.SetLocalAet("WORLD"); | |
1035 job.SetRemoteModality(r); | |
1036 job.SetTimeout(43); | |
1037 job.SetMoveOriginator("ORIGINATOR", 100); | |
1038 job.EnableStorageCommitment(true); | |
1039 job.Serialize(v); | |
1040 } | |
1041 | |
1042 { | |
1043 OrthancJobUnserializer unserializer(GetContext()); | |
1044 std::unique_ptr<DicomModalityStoreJob> job( | |
1045 dynamic_cast<DicomModalityStoreJob*>(unserializer.UnserializeJob(v))); | |
1046 ASSERT_EQ("WORLD", job->GetParameters().GetLocalApplicationEntityTitle()); | |
1047 ASSERT_EQ("HELLO", job->GetParameters().GetRemoteModality().GetApplicationEntityTitle()); | |
1048 ASSERT_EQ("MY_HOST", job->GetParameters().GetRemoteModality().GetHost()); | |
1049 ASSERT_EQ(42u, job->GetParameters().GetRemoteModality().GetPortNumber()); | |
1050 ASSERT_EQ(ModalityManufacturer_Generic, job->GetParameters().GetRemoteModality().GetManufacturer()); | |
1051 ASSERT_EQ(43u, job->GetParameters().GetTimeout()); | |
1052 ASSERT_TRUE(job->HasMoveOriginator()); | |
1053 ASSERT_EQ("ORIGINATOR", job->GetMoveOriginatorAet()); | |
1054 ASSERT_EQ(100, job->GetMoveOriginatorId()); | |
1055 ASSERT_TRUE(job->HasStorageCommitment()); | |
1056 } | |
1057 | |
1058 { | |
1059 DicomMoveScuJob job(GetContext()); | |
1060 job.Serialize(v); | |
1061 } | |
1062 | |
1063 { | |
1064 OrthancJobUnserializer unserializer(GetContext()); | |
1065 std::unique_ptr<DicomMoveScuJob> job( | |
1066 dynamic_cast<DicomMoveScuJob*>(unserializer.UnserializeJob(v))); | |
1067 ASSERT_EQ("ORTHANC", job->GetParameters().GetLocalApplicationEntityTitle()); | |
1068 ASSERT_EQ("ANY-SCP", job->GetParameters().GetRemoteModality().GetApplicationEntityTitle()); | |
1069 ASSERT_EQ("127.0.0.1", job->GetParameters().GetRemoteModality().GetHost()); | |
1070 ASSERT_EQ(104u, job->GetParameters().GetRemoteModality().GetPortNumber()); | |
1071 ASSERT_EQ(ModalityManufacturer_Generic, job->GetParameters().GetRemoteModality().GetManufacturer()); | |
1072 ASSERT_EQ(DicomAssociationParameters::GetDefaultTimeout(), job->GetParameters().GetTimeout()); | |
1073 } | |
1074 | |
1075 { | |
1076 RemoteModalityParameters r; | |
1077 r.SetApplicationEntityTitle("HELLO"); | |
1078 r.SetPortNumber(42); | |
1079 r.SetHost("MY_HOST"); | |
1080 | |
1081 DicomMoveScuJob job(GetContext()); | |
1082 job.SetLocalAet("WORLD"); | |
1083 job.SetRemoteModality(r); | |
1084 job.SetTimeout(43); | |
1085 job.Serialize(v); | |
1086 } | |
1087 | |
1088 { | |
1089 OrthancJobUnserializer unserializer(GetContext()); | |
1090 std::unique_ptr<DicomMoveScuJob> job( | |
1091 dynamic_cast<DicomMoveScuJob*>(unserializer.UnserializeJob(v))); | |
1092 ASSERT_EQ("WORLD", job->GetParameters().GetLocalApplicationEntityTitle()); | |
1093 ASSERT_EQ("HELLO", job->GetParameters().GetRemoteModality().GetApplicationEntityTitle()); | |
1094 ASSERT_EQ("MY_HOST", job->GetParameters().GetRemoteModality().GetHost()); | |
1095 ASSERT_EQ(42u, job->GetParameters().GetRemoteModality().GetPortNumber()); | |
1096 ASSERT_EQ(ModalityManufacturer_Generic, job->GetParameters().GetRemoteModality().GetManufacturer()); | |
1097 ASSERT_EQ(43u, job->GetParameters().GetTimeout()); | |
1098 } | |
1099 } |