comparison OrthancFramework/UnitTestsSources/JobsTests.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 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
35 # include <OrthancFramework.h>
36 #endif
37
38 #include "gtest/gtest.h"
39
40 #include "../../OrthancFramework/Sources/Compatibility.h"
41 #include "../../OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h"
42 #include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
43 #include "../../OrthancFramework/Sources/DicomParsing/ParsedDicomFile.h"
44 #include "../../OrthancFramework/Sources/JobsEngine/GenericJobUnserializer.h"
45 #include "../../OrthancFramework/Sources/JobsEngine/JobsEngine.h"
46 #include "../../OrthancFramework/Sources/JobsEngine/Operations/JobOperationValues.h"
47 #include "../../OrthancFramework/Sources/JobsEngine/Operations/LogJobOperation.h"
48 #include "../../OrthancFramework/Sources/JobsEngine/Operations/NullOperationValue.h"
49 #include "../../OrthancFramework/Sources/JobsEngine/Operations/SequenceOfOperationsJob.h"
50 #include "../../OrthancFramework/Sources/JobsEngine/Operations/StringOperationValue.h"
51 #include "../../OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.h"
52 #include "../../OrthancFramework/Sources/Logging.h"
53 #include "../../OrthancFramework/Sources/MultiThreading/SharedMessageQueue.h"
54 #include "../../OrthancFramework/Sources/OrthancException.h"
55 #include "../../OrthancFramework/Sources/SerializationToolbox.h"
56
57
58 using namespace Orthanc;
59
60 namespace
61 {
62 class DummyJob : public IJob
63 {
64 private:
65 bool fails_;
66 unsigned int count_;
67 unsigned int steps_;
68
69 public:
70 DummyJob() :
71 fails_(false),
72 count_(0),
73 steps_(4)
74 {
75 }
76
77 explicit DummyJob(bool fails) :
78 fails_(fails),
79 count_(0),
80 steps_(4)
81 {
82 }
83
84 virtual void Start() ORTHANC_OVERRIDE
85 {
86 }
87
88 virtual void Reset() ORTHANC_OVERRIDE
89 {
90 }
91
92 virtual JobStepResult Step(const std::string& jobId) ORTHANC_OVERRIDE
93 {
94 if (fails_)
95 {
96 return JobStepResult::Failure(ErrorCode_ParameterOutOfRange, NULL);
97 }
98 else if (count_ == steps_ - 1)
99 {
100 return JobStepResult::Success();
101 }
102 else
103 {
104 count_++;
105 return JobStepResult::Continue();
106 }
107 }
108
109 virtual void Stop(JobStopReason reason) ORTHANC_OVERRIDE
110 {
111 }
112
113 virtual float GetProgress() ORTHANC_OVERRIDE
114 {
115 return static_cast<float>(count_) / static_cast<float>(steps_ - 1);
116 }
117
118 virtual void GetJobType(std::string& type) ORTHANC_OVERRIDE
119 {
120 type = "DummyJob";
121 }
122
123 virtual bool Serialize(Json::Value& value) ORTHANC_OVERRIDE
124 {
125 value = Json::objectValue;
126 value["Type"] = "DummyJob";
127 return true;
128 }
129
130 virtual void GetPublicContent(Json::Value& value) ORTHANC_OVERRIDE
131 {
132 value["hello"] = "world";
133 }
134
135 virtual bool GetOutput(std::string& output,
136 MimeType& mime,
137 const std::string& key) ORTHANC_OVERRIDE
138 {
139 return false;
140 }
141 };
142
143
144 class DummyInstancesJob : public SetOfInstancesJob
145 {
146 private:
147 bool trailingStepDone_;
148
149 protected:
150 virtual bool HandleInstance(const std::string& instance) ORTHANC_OVERRIDE
151 {
152 return (instance != "nope");
153 }
154
155 virtual bool HandleTrailingStep() ORTHANC_OVERRIDE
156 {
157 if (HasTrailingStep())
158 {
159 if (trailingStepDone_)
160 {
161 throw OrthancException(ErrorCode_InternalError);
162 }
163 else
164 {
165 trailingStepDone_ = true;
166 return true;
167 }
168 }
169 else
170 {
171 throw OrthancException(ErrorCode_InternalError);
172 }
173 }
174
175 public:
176 DummyInstancesJob() :
177 trailingStepDone_(false)
178 {
179 }
180
181 DummyInstancesJob(const Json::Value& value) :
182 SetOfInstancesJob(value)
183 {
184 if (HasTrailingStep())
185 {
186 trailingStepDone_ = (GetPosition() == GetCommandsCount());
187 }
188 else
189 {
190 trailingStepDone_ = false;
191 }
192 }
193
194 bool IsTrailingStepDone() const
195 {
196 return trailingStepDone_;
197 }
198
199 virtual void Stop(JobStopReason reason) ORTHANC_OVERRIDE
200 {
201 }
202
203 virtual void GetJobType(std::string& s) ORTHANC_OVERRIDE
204 {
205 s = "DummyInstancesJob";
206 }
207 };
208
209
210 class DummyUnserializer : public GenericJobUnserializer
211 {
212 public:
213 virtual IJob* UnserializeJob(const Json::Value& value) ORTHANC_OVERRIDE
214 {
215 if (SerializationToolbox::ReadString(value, "Type") == "DummyInstancesJob")
216 {
217 return new DummyInstancesJob(value);
218 }
219 else if (SerializationToolbox::ReadString(value, "Type") == "DummyJob")
220 {
221 return new DummyJob;
222 }
223 else
224 {
225 return GenericJobUnserializer::UnserializeJob(value);
226 }
227 }
228 };
229
230
231 class DynamicInteger : public IDynamicObject
232 {
233 private:
234 int value_;
235 std::set<int>& target_;
236
237 public:
238 DynamicInteger(int value, std::set<int>& target) :
239 value_(value), target_(target)
240 {
241 }
242
243 int GetValue() const
244 {
245 return value_;
246 }
247 };
248 }
249
250
251 TEST(MultiThreading, SharedMessageQueueBasic)
252 {
253 std::set<int> s;
254
255 SharedMessageQueue q;
256 ASSERT_TRUE(q.WaitEmpty(0));
257 q.Enqueue(new DynamicInteger(10, s));
258 ASSERT_FALSE(q.WaitEmpty(1));
259 q.Enqueue(new DynamicInteger(20, s));
260 q.Enqueue(new DynamicInteger(30, s));
261 q.Enqueue(new DynamicInteger(40, s));
262
263 std::unique_ptr<DynamicInteger> i;
264 i.reset(dynamic_cast<DynamicInteger*>(q.Dequeue(1))); ASSERT_EQ(10, i->GetValue());
265 i.reset(dynamic_cast<DynamicInteger*>(q.Dequeue(1))); ASSERT_EQ(20, i->GetValue());
266 i.reset(dynamic_cast<DynamicInteger*>(q.Dequeue(1))); ASSERT_EQ(30, i->GetValue());
267 ASSERT_FALSE(q.WaitEmpty(1));
268 i.reset(dynamic_cast<DynamicInteger*>(q.Dequeue(1))); ASSERT_EQ(40, i->GetValue());
269 ASSERT_TRUE(q.WaitEmpty(0));
270 ASSERT_EQ(NULL, q.Dequeue(1));
271 }
272
273
274 TEST(MultiThreading, SharedMessageQueueClean)
275 {
276 std::set<int> s;
277
278 try
279 {
280 SharedMessageQueue q;
281 q.Enqueue(new DynamicInteger(10, s));
282 q.Enqueue(new DynamicInteger(20, s));
283 throw OrthancException(ErrorCode_InternalError);
284 }
285 catch (OrthancException&)
286 {
287 }
288 }
289
290
291
292
293 static bool CheckState(JobsRegistry& registry,
294 const std::string& id,
295 JobState state)
296 {
297 JobState s;
298 if (registry.GetState(s, id))
299 {
300 return state == s;
301 }
302 else
303 {
304 return false;
305 }
306 }
307
308
309 static bool CheckErrorCode(JobsRegistry& registry,
310 const std::string& id,
311 ErrorCode code)
312 {
313 JobInfo s;
314 if (registry.GetJobInfo(s, id))
315 {
316 return code == s.GetStatus().GetErrorCode();
317 }
318 else
319 {
320 return false;
321 }
322 }
323
324
325 TEST(JobsRegistry, Priority)
326 {
327 JobsRegistry registry(10);
328
329 std::string i1, i2, i3, i4;
330 registry.Submit(i1, new DummyJob(), 10);
331 registry.Submit(i2, new DummyJob(), 30);
332 registry.Submit(i3, new DummyJob(), 20);
333 registry.Submit(i4, new DummyJob(), 5);
334
335 registry.SetMaxCompletedJobs(2);
336
337 std::set<std::string> id;
338 registry.ListJobs(id);
339
340 ASSERT_EQ(4u, id.size());
341 ASSERT_TRUE(id.find(i1) != id.end());
342 ASSERT_TRUE(id.find(i2) != id.end());
343 ASSERT_TRUE(id.find(i3) != id.end());
344 ASSERT_TRUE(id.find(i4) != id.end());
345
346 ASSERT_TRUE(CheckState(registry, i2, JobState_Pending));
347
348 {
349 JobsRegistry::RunningJob job(registry, 0);
350 ASSERT_TRUE(job.IsValid());
351 ASSERT_EQ(30, job.GetPriority());
352 ASSERT_EQ(i2, job.GetId());
353
354 ASSERT_TRUE(CheckState(registry, i2, JobState_Running));
355 }
356
357 ASSERT_TRUE(CheckState(registry, i2, JobState_Failure));
358 ASSERT_TRUE(CheckState(registry, i3, JobState_Pending));
359
360 {
361 JobsRegistry::RunningJob job(registry, 0);
362 ASSERT_TRUE(job.IsValid());
363 ASSERT_EQ(20, job.GetPriority());
364 ASSERT_EQ(i3, job.GetId());
365
366 job.MarkSuccess();
367
368 ASSERT_TRUE(CheckState(registry, i3, JobState_Running));
369 }
370
371 ASSERT_TRUE(CheckState(registry, i3, JobState_Success));
372
373 {
374 JobsRegistry::RunningJob job(registry, 0);
375 ASSERT_TRUE(job.IsValid());
376 ASSERT_EQ(10, job.GetPriority());
377 ASSERT_EQ(i1, job.GetId());
378 }
379
380 {
381 JobsRegistry::RunningJob job(registry, 0);
382 ASSERT_TRUE(job.IsValid());
383 ASSERT_EQ(5, job.GetPriority());
384 ASSERT_EQ(i4, job.GetId());
385 }
386
387 {
388 JobsRegistry::RunningJob job(registry, 1);
389 ASSERT_FALSE(job.IsValid());
390 }
391
392 JobState s;
393 ASSERT_TRUE(registry.GetState(s, i1));
394 ASSERT_FALSE(registry.GetState(s, i2)); // Removed because oldest
395 ASSERT_FALSE(registry.GetState(s, i3)); // Removed because second oldest
396 ASSERT_TRUE(registry.GetState(s, i4));
397
398 registry.SetMaxCompletedJobs(1); // (*)
399 ASSERT_FALSE(registry.GetState(s, i1)); // Just discarded by (*)
400 ASSERT_TRUE(registry.GetState(s, i4));
401 }
402
403
404 TEST(JobsRegistry, Simultaneous)
405 {
406 JobsRegistry registry(10);
407
408 std::string i1, i2;
409 registry.Submit(i1, new DummyJob(), 20);
410 registry.Submit(i2, new DummyJob(), 10);
411
412 ASSERT_TRUE(CheckState(registry, i1, JobState_Pending));
413 ASSERT_TRUE(CheckState(registry, i2, JobState_Pending));
414
415 {
416 JobsRegistry::RunningJob job1(registry, 0);
417 JobsRegistry::RunningJob job2(registry, 0);
418
419 ASSERT_TRUE(job1.IsValid());
420 ASSERT_TRUE(job2.IsValid());
421
422 job1.MarkFailure();
423 job2.MarkSuccess();
424
425 ASSERT_TRUE(CheckState(registry, i1, JobState_Running));
426 ASSERT_TRUE(CheckState(registry, i2, JobState_Running));
427 }
428
429 ASSERT_TRUE(CheckState(registry, i1, JobState_Failure));
430 ASSERT_TRUE(CheckState(registry, i2, JobState_Success));
431 }
432
433
434 TEST(JobsRegistry, Resubmit)
435 {
436 JobsRegistry registry(10);
437
438 std::string id;
439 registry.Submit(id, new DummyJob(), 10);
440
441 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
442
443 registry.Resubmit(id);
444 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
445
446 {
447 JobsRegistry::RunningJob job(registry, 0);
448 ASSERT_TRUE(job.IsValid());
449 job.MarkFailure();
450
451 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
452
453 registry.Resubmit(id);
454 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
455 }
456
457 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
458
459 registry.Resubmit(id);
460 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
461
462 {
463 JobsRegistry::RunningJob job(registry, 0);
464 ASSERT_TRUE(job.IsValid());
465 ASSERT_EQ(id, job.GetId());
466
467 job.MarkSuccess();
468 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
469 }
470
471 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
472
473 registry.Resubmit(id);
474 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
475 }
476
477
478 TEST(JobsRegistry, Retry)
479 {
480 JobsRegistry registry(10);
481
482 std::string id;
483 registry.Submit(id, new DummyJob(), 10);
484
485 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
486
487 {
488 JobsRegistry::RunningJob job(registry, 0);
489 ASSERT_TRUE(job.IsValid());
490 job.MarkRetry(0);
491
492 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
493 }
494
495 ASSERT_TRUE(CheckState(registry, id, JobState_Retry));
496
497 registry.Resubmit(id);
498 ASSERT_TRUE(CheckState(registry, id, JobState_Retry));
499
500 registry.ScheduleRetries();
501 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
502
503 {
504 JobsRegistry::RunningJob job(registry, 0);
505 ASSERT_TRUE(job.IsValid());
506 job.MarkSuccess();
507
508 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
509 }
510
511 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
512 }
513
514
515 TEST(JobsRegistry, PausePending)
516 {
517 JobsRegistry registry(10);
518
519 std::string id;
520 registry.Submit(id, new DummyJob(), 10);
521
522 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
523
524 registry.Pause(id);
525 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
526
527 registry.Pause(id);
528 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
529
530 registry.Resubmit(id);
531 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
532
533 registry.Resume(id);
534 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
535 }
536
537
538 TEST(JobsRegistry, PauseRunning)
539 {
540 JobsRegistry registry(10);
541
542 std::string id;
543 registry.Submit(id, new DummyJob(), 10);
544
545 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
546
547 {
548 JobsRegistry::RunningJob job(registry, 0);
549 ASSERT_TRUE(job.IsValid());
550
551 registry.Resubmit(id);
552 job.MarkPause();
553 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
554 }
555
556 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
557
558 registry.Resubmit(id);
559 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
560
561 registry.Resume(id);
562 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
563
564 {
565 JobsRegistry::RunningJob job(registry, 0);
566 ASSERT_TRUE(job.IsValid());
567
568 job.MarkSuccess();
569 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
570 }
571
572 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
573 }
574
575
576 TEST(JobsRegistry, PauseRetry)
577 {
578 JobsRegistry registry(10);
579
580 std::string id;
581 registry.Submit(id, new DummyJob(), 10);
582
583 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
584
585 {
586 JobsRegistry::RunningJob job(registry, 0);
587 ASSERT_TRUE(job.IsValid());
588
589 job.MarkRetry(0);
590 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
591 }
592
593 ASSERT_TRUE(CheckState(registry, id, JobState_Retry));
594
595 registry.Pause(id);
596 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
597
598 registry.Resume(id);
599 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
600
601 {
602 JobsRegistry::RunningJob job(registry, 0);
603 ASSERT_TRUE(job.IsValid());
604
605 job.MarkSuccess();
606 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
607 }
608
609 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
610 }
611
612
613 TEST(JobsRegistry, Cancel)
614 {
615 JobsRegistry registry(10);
616
617 std::string id;
618 registry.Submit(id, new DummyJob(), 10);
619
620 ASSERT_FALSE(registry.Cancel("nope"));
621
622 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
623 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
624
625 ASSERT_TRUE(registry.Cancel(id));
626 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
627 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
628
629 ASSERT_TRUE(registry.Cancel(id));
630 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
631 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
632
633 ASSERT_TRUE(registry.Resubmit(id));
634 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
635 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
636
637 {
638 JobsRegistry::RunningJob job(registry, 0);
639 ASSERT_TRUE(job.IsValid());
640
641 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
642
643 job.MarkSuccess();
644 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
645 }
646
647 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
648 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
649
650 ASSERT_TRUE(registry.Cancel(id));
651 ASSERT_TRUE(CheckState(registry, id, JobState_Success));
652 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
653
654 registry.Submit(id, new DummyJob(), 10);
655
656 {
657 JobsRegistry::RunningJob job(registry, 0);
658 ASSERT_TRUE(job.IsValid());
659 ASSERT_EQ(id, job.GetId());
660
661 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
662 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
663
664 job.MarkCanceled();
665 }
666
667 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
668 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
669
670 ASSERT_TRUE(registry.Resubmit(id));
671 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
672 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
673
674 ASSERT_TRUE(registry.Pause(id));
675 ASSERT_TRUE(CheckState(registry, id, JobState_Paused));
676 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
677
678 ASSERT_TRUE(registry.Cancel(id));
679 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
680 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
681
682 ASSERT_TRUE(registry.Resubmit(id));
683 ASSERT_TRUE(CheckState(registry, id, JobState_Pending));
684 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
685
686 {
687 JobsRegistry::RunningJob job(registry, 0);
688 ASSERT_TRUE(job.IsValid());
689 ASSERT_EQ(id, job.GetId());
690
691 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
692 ASSERT_TRUE(CheckState(registry, id, JobState_Running));
693
694 job.MarkRetry(500);
695 }
696
697 ASSERT_TRUE(CheckState(registry, id, JobState_Retry));
698 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_Success));
699
700 ASSERT_TRUE(registry.Cancel(id));
701 ASSERT_TRUE(CheckState(registry, id, JobState_Failure));
702 ASSERT_TRUE(CheckErrorCode(registry, id, ErrorCode_CanceledJob));
703 }
704
705
706
707 TEST(JobsEngine, SubmitAndWait)
708 {
709 JobsEngine engine(10);
710 engine.SetThreadSleep(10);
711 engine.SetWorkersCount(3);
712 engine.Start();
713
714 Json::Value content = Json::nullValue;
715 engine.GetRegistry().SubmitAndWait(content, new DummyJob(), rand() % 10);
716 ASSERT_EQ(Json::objectValue, content.type());
717 ASSERT_EQ("world", content["hello"].asString());
718
719 content = Json::nullValue;
720 ASSERT_THROW(engine.GetRegistry().SubmitAndWait(content, new DummyJob(true), rand() % 10), OrthancException);
721 ASSERT_EQ(Json::nullValue, content.type());
722
723 engine.Stop();
724 }
725
726
727 TEST(JobsEngine, DISABLED_SequenceOfOperationsJob)
728 {
729 JobsEngine engine(10);
730 engine.SetThreadSleep(10);
731 engine.SetWorkersCount(3);
732 engine.Start();
733
734 std::string id;
735 SequenceOfOperationsJob* job = NULL;
736
737 {
738 std::unique_ptr<SequenceOfOperationsJob> a(new SequenceOfOperationsJob);
739 job = a.get();
740 engine.GetRegistry().Submit(id, a.release(), 0);
741 }
742
743 boost::this_thread::sleep(boost::posix_time::milliseconds(500));
744
745 {
746 SequenceOfOperationsJob::Lock lock(*job);
747 size_t i = lock.AddOperation(new LogJobOperation);
748 size_t j = lock.AddOperation(new LogJobOperation);
749 size_t k = lock.AddOperation(new LogJobOperation);
750
751 StringOperationValue a("Hello");
752 StringOperationValue b("World");
753 lock.AddInput(i, a);
754 lock.AddInput(i, b);
755
756 lock.Connect(i, j);
757 lock.Connect(j, k);
758 }
759
760 boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
761
762 engine.Stop();
763
764 }
765
766
767 static bool CheckSameJson(const Json::Value& a,
768 const Json::Value& b)
769 {
770 std::string s = a.toStyledString();
771 std::string t = b.toStyledString();
772
773 if (s == t)
774 {
775 return true;
776 }
777 else
778 {
779 LOG(ERROR) << "Expected serialization: " << s;
780 LOG(ERROR) << "Actual serialization: " << t;
781 return false;
782 }
783 }
784
785
786 static bool CheckIdempotentSerialization(IJobUnserializer& unserializer,
787 IJob& job)
788 {
789 Json::Value a = 42;
790
791 if (!job.Serialize(a))
792 {
793 return false;
794 }
795 else
796 {
797 std::unique_ptr<IJob> unserialized(unserializer.UnserializeJob(a));
798
799 Json::Value b = 43;
800 if (unserialized->Serialize(b))
801 {
802 return (CheckSameJson(a, b));
803 }
804 else
805 {
806 return false;
807 }
808 }
809 }
810
811
812 static bool CheckIdempotentSetOfInstances(IJobUnserializer& unserializer,
813 SetOfInstancesJob& job)
814 {
815 Json::Value a = 42;
816
817 if (!job.Serialize(a))
818 {
819 return false;
820 }
821 else
822 {
823 std::unique_ptr<SetOfInstancesJob> unserialized
824 (dynamic_cast<SetOfInstancesJob*>(unserializer.UnserializeJob(a)));
825
826 Json::Value b = 43;
827 if (unserialized->Serialize(b))
828 {
829 return (CheckSameJson(a, b) &&
830 job.HasTrailingStep() == unserialized->HasTrailingStep() &&
831 job.GetPosition() == unserialized->GetPosition() &&
832 job.GetInstancesCount() == unserialized->GetInstancesCount() &&
833 job.GetCommandsCount() == unserialized->GetCommandsCount());
834 }
835 else
836 {
837 return false;
838 }
839 }
840 }
841
842
843 static bool CheckIdempotentSerialization(IJobUnserializer& unserializer,
844 JobOperationValue& value)
845 {
846 Json::Value a = 42;
847 value.Serialize(a);
848
849 std::unique_ptr<JobOperationValue> unserialized(unserializer.UnserializeValue(a));
850
851 Json::Value b = 43;
852 unserialized->Serialize(b);
853
854 return CheckSameJson(a, b);
855 }
856
857
858 TEST(JobsSerialization, BadFileFormat)
859 {
860 GenericJobUnserializer unserializer;
861
862 Json::Value s;
863
864 s = Json::objectValue;
865 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
866 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
867 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
868
869 s = Json::arrayValue;
870 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
871 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
872 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
873
874 s = "hello";
875 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
876 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
877 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
878
879 s = 42;
880 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
881 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
882 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
883 }
884
885
886 TEST(JobsSerialization, JobOperationValues)
887 {
888 Json::Value s;
889
890 {
891 JobOperationValues values;
892 values.Append(new NullOperationValue);
893 values.Append(new StringOperationValue("hello"));
894 values.Append(new StringOperationValue("world"));
895
896 s = 42;
897 values.Serialize(s);
898 }
899
900 {
901 GenericJobUnserializer unserializer;
902 std::unique_ptr<JobOperationValues> values(JobOperationValues::Unserialize(unserializer, s));
903 ASSERT_EQ(3u, values->GetSize());
904 ASSERT_EQ(JobOperationValue::Type_Null, values->GetValue(0).GetType());
905 ASSERT_EQ(JobOperationValue::Type_String, values->GetValue(1).GetType());
906 ASSERT_EQ(JobOperationValue::Type_String, values->GetValue(2).GetType());
907
908 ASSERT_EQ("hello", dynamic_cast<const StringOperationValue&>(values->GetValue(1)).GetContent());
909 ASSERT_EQ("world", dynamic_cast<const StringOperationValue&>(values->GetValue(2)).GetContent());
910 }
911 }
912
913
914 TEST(JobsSerialization, GenericValues)
915 {
916 GenericJobUnserializer unserializer;
917 Json::Value s;
918
919 {
920 NullOperationValue null;
921
922 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, null));
923 null.Serialize(s);
924 }
925
926 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
927 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
928
929 std::unique_ptr<JobOperationValue> value;
930 value.reset(unserializer.UnserializeValue(s));
931
932 ASSERT_EQ(JobOperationValue::Type_Null, value->GetType());
933
934 {
935 StringOperationValue str("Hello");
936
937 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, str));
938 str.Serialize(s);
939 }
940
941 ASSERT_THROW(unserializer.UnserializeJob(s), OrthancException);
942 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
943 value.reset(unserializer.UnserializeValue(s));
944
945 ASSERT_EQ(JobOperationValue::Type_String, value->GetType());
946 ASSERT_EQ("Hello", dynamic_cast<StringOperationValue&>(*value).GetContent());
947 }
948
949
950 TEST(JobsSerialization, GenericJobs)
951 {
952 Json::Value s;
953
954 // This tests SetOfInstancesJob
955
956 {
957 DummyInstancesJob job;
958 job.SetDescription("description");
959 job.AddInstance("hello");
960 job.AddInstance("nope");
961 job.AddInstance("world");
962 job.SetPermissive(true);
963 ASSERT_THROW(job.Step("jobId"), OrthancException); // Not started yet
964 ASSERT_FALSE(job.HasTrailingStep());
965 ASSERT_FALSE(job.IsTrailingStepDone());
966 job.Start();
967 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode());
968 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode());
969
970 {
971 DummyUnserializer unserializer;
972 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
973 }
974
975 ASSERT_TRUE(job.Serialize(s));
976 }
977
978 {
979 DummyUnserializer unserializer;
980 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
981 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
982
983 std::unique_ptr<IJob> job;
984 job.reset(unserializer.UnserializeJob(s));
985
986 const DummyInstancesJob& tmp = dynamic_cast<const DummyInstancesJob&>(*job);
987 ASSERT_FALSE(tmp.IsStarted());
988 ASSERT_TRUE(tmp.IsPermissive());
989 ASSERT_EQ("description", tmp.GetDescription());
990 ASSERT_EQ(3u, tmp.GetInstancesCount());
991 ASSERT_EQ(2u, tmp.GetPosition());
992 ASSERT_EQ(1u, tmp.GetFailedInstances().size());
993 ASSERT_EQ("hello", tmp.GetInstance(0));
994 ASSERT_EQ("nope", tmp.GetInstance(1));
995 ASSERT_EQ("world", tmp.GetInstance(2));
996 ASSERT_TRUE(tmp.IsFailedInstance("nope"));
997 }
998
999 // SequenceOfOperationsJob
1000
1001 {
1002 SequenceOfOperationsJob job;
1003 job.SetDescription("hello");
1004
1005 {
1006 SequenceOfOperationsJob::Lock lock(job);
1007 size_t a = lock.AddOperation(new LogJobOperation);
1008 size_t b = lock.AddOperation(new LogJobOperation);
1009 lock.Connect(a, b);
1010
1011 StringOperationValue s1("hello");
1012 StringOperationValue s2("world");
1013 lock.AddInput(a, s1);
1014 lock.AddInput(a, s2);
1015 lock.SetTrailingOperationTimeout(300);
1016 }
1017
1018 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode());
1019
1020 {
1021 GenericJobUnserializer unserializer;
1022 ASSERT_TRUE(CheckIdempotentSerialization(unserializer, job));
1023 }
1024
1025 ASSERT_TRUE(job.Serialize(s));
1026 }
1027
1028 {
1029 GenericJobUnserializer unserializer;
1030 ASSERT_THROW(unserializer.UnserializeValue(s), OrthancException);
1031 ASSERT_THROW(unserializer.UnserializeOperation(s), OrthancException);
1032
1033 std::unique_ptr<IJob> job;
1034 job.reset(unserializer.UnserializeJob(s));
1035
1036 std::string tmp;
1037 dynamic_cast<SequenceOfOperationsJob&>(*job).GetDescription(tmp);
1038 ASSERT_EQ("hello", tmp);
1039 }
1040 }
1041
1042
1043 static bool IsSameTagValue(ParsedDicomFile& dicom1,
1044 ParsedDicomFile& dicom2,
1045 DicomTag tag)
1046 {
1047 std::string a, b;
1048 return (dicom1.GetTagValue(a, tag) &&
1049 dicom2.GetTagValue(b, tag) &&
1050 (a == b));
1051 }
1052
1053
1054
1055 TEST(JobsSerialization, DicomModification)
1056 {
1057 Json::Value s;
1058
1059 ParsedDicomFile source(true);
1060 source.Insert(DICOM_TAG_STUDY_DESCRIPTION, "Test 1", false, "");
1061 source.Insert(DICOM_TAG_SERIES_DESCRIPTION, "Test 2", false, "");
1062 source.Insert(DICOM_TAG_PATIENT_NAME, "Test 3", false, "");
1063
1064 std::unique_ptr<ParsedDicomFile> modified(source.Clone(true));
1065
1066 {
1067 DicomModification modification;
1068 modification.SetLevel(ResourceType_Series);
1069 modification.Clear(DICOM_TAG_STUDY_DESCRIPTION);
1070 modification.Remove(DICOM_TAG_SERIES_DESCRIPTION);
1071 modification.Replace(DICOM_TAG_PATIENT_NAME, "Test 4", true);
1072
1073 modification.Apply(*modified);
1074
1075 s = 42;
1076 modification.Serialize(s);
1077 }
1078
1079 {
1080 DicomModification modification(s);
1081 ASSERT_EQ(ResourceType_Series, modification.GetLevel());
1082
1083 std::unique_ptr<ParsedDicomFile> second(source.Clone(true));
1084 modification.Apply(*second);
1085
1086 std::string s;
1087 ASSERT_TRUE(second->GetTagValue(s, DICOM_TAG_STUDY_DESCRIPTION));
1088 ASSERT_TRUE(s.empty());
1089 ASSERT_FALSE(second->GetTagValue(s, DICOM_TAG_SERIES_DESCRIPTION));
1090 ASSERT_TRUE(second->GetTagValue(s, DICOM_TAG_PATIENT_NAME));
1091 ASSERT_EQ("Test 4", s);
1092
1093 ASSERT_TRUE(IsSameTagValue(source, *modified, DICOM_TAG_STUDY_INSTANCE_UID));
1094 ASSERT_TRUE(IsSameTagValue(source, *second, DICOM_TAG_STUDY_INSTANCE_UID));
1095
1096 ASSERT_FALSE(IsSameTagValue(source, *second, DICOM_TAG_SERIES_INSTANCE_UID));
1097 ASSERT_TRUE(IsSameTagValue(*modified, *second, DICOM_TAG_SERIES_INSTANCE_UID));
1098 }
1099 }
1100
1101
1102 TEST(JobsSerialization, Registry)
1103 {
1104 Json::Value s;
1105 std::string i1, i2;
1106
1107 {
1108 JobsRegistry registry(10);
1109 registry.Submit(i1, new DummyJob(), 10);
1110 registry.Submit(i2, new SequenceOfOperationsJob(), 30);
1111 registry.Serialize(s);
1112 }
1113
1114 {
1115 DummyUnserializer unserializer;
1116 JobsRegistry registry(unserializer, s, 10);
1117
1118 Json::Value t;
1119 registry.Serialize(t);
1120 ASSERT_TRUE(CheckSameJson(s, t));
1121 }
1122 }
1123
1124
1125 TEST(JobsSerialization, TrailingStep)
1126 {
1127 {
1128 Json::Value s;
1129
1130 DummyInstancesJob job;
1131 ASSERT_EQ(0u, job.GetCommandsCount());
1132 ASSERT_EQ(0u, job.GetInstancesCount());
1133
1134 job.Start();
1135 ASSERT_EQ(0u, job.GetPosition());
1136 ASSERT_FALSE(job.HasTrailingStep());
1137 ASSERT_FALSE(job.IsTrailingStepDone());
1138
1139 {
1140 DummyUnserializer unserializer;
1141 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1142 }
1143
1144 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode());
1145 ASSERT_EQ(1u, job.GetPosition());
1146 ASSERT_FALSE(job.IsTrailingStepDone());
1147
1148 {
1149 DummyUnserializer unserializer;
1150 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1151 }
1152
1153 ASSERT_THROW(job.Step("jobId"), OrthancException);
1154 }
1155
1156 {
1157 Json::Value s;
1158
1159 DummyInstancesJob job;
1160 job.AddInstance("hello");
1161 job.AddInstance("world");
1162 ASSERT_EQ(2u, job.GetCommandsCount());
1163 ASSERT_EQ(2u, job.GetInstancesCount());
1164
1165 job.Start();
1166 ASSERT_EQ(0u, job.GetPosition());
1167 ASSERT_FALSE(job.HasTrailingStep());
1168 ASSERT_FALSE(job.IsTrailingStepDone());
1169
1170 {
1171 DummyUnserializer unserializer;
1172 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1173 }
1174
1175 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode());
1176 ASSERT_EQ(1u, job.GetPosition());
1177 ASSERT_FALSE(job.IsTrailingStepDone());
1178
1179 {
1180 DummyUnserializer unserializer;
1181 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1182 }
1183
1184 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode());
1185 ASSERT_EQ(2u, job.GetPosition());
1186 ASSERT_FALSE(job.IsTrailingStepDone());
1187
1188 {
1189 DummyUnserializer unserializer;
1190 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1191 }
1192
1193 ASSERT_THROW(job.Step("jobId"), OrthancException);
1194 }
1195
1196 {
1197 Json::Value s;
1198
1199 DummyInstancesJob job;
1200 ASSERT_EQ(0u, job.GetInstancesCount());
1201 ASSERT_EQ(0u, job.GetCommandsCount());
1202 job.AddTrailingStep();
1203 ASSERT_EQ(0u, job.GetInstancesCount());
1204 ASSERT_EQ(1u, job.GetCommandsCount());
1205
1206 job.Start(); // This adds the trailing step
1207 ASSERT_EQ(0u, job.GetPosition());
1208 ASSERT_TRUE(job.HasTrailingStep());
1209 ASSERT_FALSE(job.IsTrailingStepDone());
1210
1211 {
1212 DummyUnserializer unserializer;
1213 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1214 }
1215
1216 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode());
1217 ASSERT_EQ(1u, job.GetPosition());
1218 ASSERT_TRUE(job.IsTrailingStepDone());
1219
1220 {
1221 DummyUnserializer unserializer;
1222 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1223 }
1224
1225 ASSERT_THROW(job.Step("jobId"), OrthancException);
1226 }
1227
1228 {
1229 Json::Value s;
1230
1231 DummyInstancesJob job;
1232 job.AddInstance("hello");
1233 ASSERT_EQ(1u, job.GetInstancesCount());
1234 ASSERT_EQ(1u, job.GetCommandsCount());
1235 job.AddTrailingStep();
1236 ASSERT_EQ(1u, job.GetInstancesCount());
1237 ASSERT_EQ(2u, job.GetCommandsCount());
1238
1239 job.Start();
1240 ASSERT_EQ(2u, job.GetCommandsCount());
1241 ASSERT_EQ(0u, job.GetPosition());
1242 ASSERT_TRUE(job.HasTrailingStep());
1243 ASSERT_FALSE(job.IsTrailingStepDone());
1244
1245 {
1246 DummyUnserializer unserializer;
1247 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1248 }
1249
1250 ASSERT_EQ(JobStepCode_Continue, job.Step("jobId").GetCode());
1251 ASSERT_EQ(1u, job.GetPosition());
1252 ASSERT_FALSE(job.IsTrailingStepDone());
1253
1254 {
1255 DummyUnserializer unserializer;
1256 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1257 }
1258
1259 ASSERT_EQ(JobStepCode_Success, job.Step("jobId").GetCode());
1260 ASSERT_EQ(2u, job.GetPosition());
1261 ASSERT_TRUE(job.IsTrailingStepDone());
1262
1263 {
1264 DummyUnserializer unserializer;
1265 ASSERT_TRUE(CheckIdempotentSetOfInstances(unserializer, job));
1266 }
1267
1268 ASSERT_THROW(job.Step("jobId"), OrthancException);
1269 }
1270 }
1271
1272
1273 TEST(JobsSerialization, RemoteModalityParameters)
1274 {
1275 Json::Value s;
1276
1277 {
1278 RemoteModalityParameters modality;
1279 ASSERT_FALSE(modality.IsAdvancedFormatNeeded());
1280 modality.Serialize(s, false);
1281 ASSERT_EQ(Json::arrayValue, s.type());
1282 }
1283
1284 {
1285 RemoteModalityParameters modality(s);
1286 ASSERT_EQ("ORTHANC", modality.GetApplicationEntityTitle());
1287 ASSERT_EQ("127.0.0.1", modality.GetHost());
1288 ASSERT_EQ(104u, modality.GetPortNumber());
1289 ASSERT_EQ(ModalityManufacturer_Generic, modality.GetManufacturer());
1290 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Echo));
1291 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Find));
1292 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Get));
1293 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Store));
1294 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Move));
1295 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NAction));
1296 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NEventReport));
1297 ASSERT_TRUE(modality.IsTranscodingAllowed());
1298 }
1299
1300 s = Json::nullValue;
1301
1302 {
1303 RemoteModalityParameters modality;
1304 ASSERT_FALSE(modality.IsAdvancedFormatNeeded());
1305 ASSERT_THROW(modality.SetPortNumber(0), OrthancException);
1306 ASSERT_THROW(modality.SetPortNumber(65535), OrthancException);
1307 modality.SetApplicationEntityTitle("HELLO");
1308 modality.SetHost("world");
1309 modality.SetPortNumber(45);
1310 modality.SetManufacturer(ModalityManufacturer_GenericNoWildcardInDates);
1311 modality.Serialize(s, true);
1312 ASSERT_EQ(Json::objectValue, s.type());
1313 }
1314
1315 {
1316 RemoteModalityParameters modality(s);
1317 ASSERT_EQ("HELLO", modality.GetApplicationEntityTitle());
1318 ASSERT_EQ("world", modality.GetHost());
1319 ASSERT_EQ(45u, modality.GetPortNumber());
1320 ASSERT_EQ(ModalityManufacturer_GenericNoWildcardInDates, modality.GetManufacturer());
1321 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Echo));
1322 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Find));
1323 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Get));
1324 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Store));
1325 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_Move));
1326 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NAction));
1327 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NEventReport));
1328 ASSERT_TRUE(modality.IsTranscodingAllowed());
1329 }
1330
1331 s["Port"] = "46";
1332
1333 {
1334 RemoteModalityParameters modality(s);
1335 ASSERT_EQ(46u, modality.GetPortNumber());
1336 }
1337
1338 s["Port"] = -1; ASSERT_THROW(RemoteModalityParameters m(s), OrthancException);
1339 s["Port"] = 65535; ASSERT_THROW(RemoteModalityParameters m(s), OrthancException);
1340 s["Port"] = "nope"; ASSERT_THROW(RemoteModalityParameters m(s), OrthancException);
1341
1342 std::set<DicomRequestType> operations;
1343 operations.insert(DicomRequestType_Echo);
1344 operations.insert(DicomRequestType_Find);
1345 operations.insert(DicomRequestType_Get);
1346 operations.insert(DicomRequestType_Move);
1347 operations.insert(DicomRequestType_Store);
1348 operations.insert(DicomRequestType_NAction);
1349 operations.insert(DicomRequestType_NEventReport);
1350
1351 ASSERT_EQ(7u, operations.size());
1352
1353 for (std::set<DicomRequestType>::const_iterator
1354 it = operations.begin(); it != operations.end(); ++it)
1355 {
1356 {
1357 RemoteModalityParameters modality;
1358 modality.SetRequestAllowed(*it, false);
1359 ASSERT_TRUE(modality.IsAdvancedFormatNeeded());
1360
1361 modality.Serialize(s, false);
1362 ASSERT_EQ(Json::objectValue, s.type());
1363 }
1364
1365 {
1366 RemoteModalityParameters modality(s);
1367
1368 ASSERT_FALSE(modality.IsRequestAllowed(*it));
1369
1370 for (std::set<DicomRequestType>::const_iterator
1371 it2 = operations.begin(); it2 != operations.end(); ++it2)
1372 {
1373 if (*it2 != *it)
1374 {
1375 ASSERT_TRUE(modality.IsRequestAllowed(*it2));
1376 }
1377 }
1378 }
1379 }
1380
1381 {
1382 Json::Value s;
1383 s["AllowStorageCommitment"] = false;
1384 s["AET"] = "AET";
1385 s["Host"] = "host";
1386 s["Port"] = "104";
1387
1388 RemoteModalityParameters modality(s);
1389 ASSERT_TRUE(modality.IsAdvancedFormatNeeded());
1390 ASSERT_EQ("AET", modality.GetApplicationEntityTitle());
1391 ASSERT_EQ("host", modality.GetHost());
1392 ASSERT_EQ(104u, modality.GetPortNumber());
1393 ASSERT_FALSE(modality.IsRequestAllowed(DicomRequestType_NAction));
1394 ASSERT_FALSE(modality.IsRequestAllowed(DicomRequestType_NEventReport));
1395 ASSERT_TRUE(modality.IsTranscodingAllowed());
1396 }
1397
1398 {
1399 Json::Value s;
1400 s["AllowNAction"] = false;
1401 s["AllowNEventReport"] = true;
1402 s["AET"] = "AET";
1403 s["Host"] = "host";
1404 s["Port"] = "104";
1405 s["AllowTranscoding"] = false;
1406
1407 RemoteModalityParameters modality(s);
1408 ASSERT_TRUE(modality.IsAdvancedFormatNeeded());
1409 ASSERT_EQ("AET", modality.GetApplicationEntityTitle());
1410 ASSERT_EQ("host", modality.GetHost());
1411 ASSERT_EQ(104u, modality.GetPortNumber());
1412 ASSERT_FALSE(modality.IsRequestAllowed(DicomRequestType_NAction));
1413 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NEventReport));
1414 ASSERT_FALSE(modality.IsTranscodingAllowed());
1415 }
1416
1417 {
1418 Json::Value s;
1419 s["AllowNAction"] = true;
1420 s["AllowNEventReport"] = true;
1421 s["AET"] = "AET";
1422 s["Host"] = "host";
1423 s["Port"] = "104";
1424
1425 RemoteModalityParameters modality(s);
1426 ASSERT_FALSE(modality.IsAdvancedFormatNeeded());
1427 ASSERT_EQ("AET", modality.GetApplicationEntityTitle());
1428 ASSERT_EQ("host", modality.GetHost());
1429 ASSERT_EQ(104u, modality.GetPortNumber());
1430 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NAction));
1431 ASSERT_TRUE(modality.IsRequestAllowed(DicomRequestType_NEventReport));
1432 ASSERT_TRUE(modality.IsTranscodingAllowed());
1433 }
1434 }