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-2021 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 Lesser General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program. If not, see
19 * <http://www.gnu.org/licenses/>.
20 **/
21
22
23 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
24 // Must be the first to be sure to use the Orthanc framework shared library
25 # include <OrthancFramework.h>
26 #endif
27
28 #include <gtest/gtest.h>
29
30 #include "../Sources/Compatibility.h"
31 #include "../Sources/IDynamicObject.h"
32 #include "../Sources/OrthancException.h"
33 #include "../Sources/Toolbox.h"
34
35 using namespace Orthanc;
36
TEST(Toolbox,Json)37 TEST(Toolbox, Json)
38 {
39 Json::Value a = Json::objectValue;
40 a["hello"] = "world";
41
42 std::string b = "{\"hello\" : \"world\"}";
43
44 Json::Value c;
45 ASSERT_TRUE(Toolbox::ReadJson(c, b));
46
47 std::string d, e;
48 Toolbox::WriteFastJson(d, a);
49 Toolbox::WriteFastJson(e, c);
50 ASSERT_EQ(d, e);
51
52 std::string f, g;
53 Toolbox::WriteStyledJson(f, a);
54 Toolbox::WriteStyledJson(g, c);
55 ASSERT_EQ(f, g);
56
57 /**
58 * Check compatibility with the serialized string generated by
59 * JsonCpp 1.7.4 (Ubuntu 18.04). "StripSpaces()" removes the
60 * trailing end-of-line character that was not present in the
61 * deprecated serialization classes of JsonCpp.
62 **/
63 ASSERT_EQ(Toolbox::StripSpaces(d), "{\"hello\":\"world\"}");
64 ASSERT_EQ(Toolbox::StripSpaces(f), "{\n \"hello\" : \"world\"\n}");
65 }
66
TEST(Toolbox,JsonComments)67 TEST(Toolbox, JsonComments)
68 {
69 std::string a = "/* a */ { /* b */ \"hello\" : /* c */ \"world\" /* d */ } // e";
70
71 Json::Value b;
72 ASSERT_TRUE(Toolbox::ReadJsonWithoutComments(b, a));
73
74 std::string c;
75 Toolbox::WriteFastJson(c, b);
76 ASSERT_EQ(Toolbox::StripSpaces(c), "{\"hello\":\"world\"}");
77
78 Toolbox::WriteStyledJson(c, b);
79 ASSERT_EQ(Toolbox::StripSpaces(c), "{\n \"hello\" : \"world\"\n}");
80 }
81
TEST(Toolbox,Base64_allByteValues)82 TEST(Toolbox, Base64_allByteValues)
83 {
84 std::string toEncode;
85 std::string base64Result;
86 std::string decodedResult;
87
88 size_t size = 2*256;
89 toEncode.reserve(size);
90 for (size_t i = 0; i < size; i++)
91 toEncode.push_back(i % 256);
92
93 Toolbox::EncodeBase64(base64Result, toEncode);
94 Toolbox::DecodeBase64(decodedResult, base64Result);
95
96 ASSERT_EQ(toEncode, decodedResult);
97 }
98
TEST(Toolbox,Base64_multipleSizes)99 TEST(Toolbox, Base64_multipleSizes)
100 {
101 std::string toEncode;
102 std::string base64Result;
103 std::string decodedResult;
104
105 for (size_t size = 0; size <= 5; size++)
106 {
107 printf("base64, testing size %zu\n", size);
108 toEncode.clear();
109 toEncode.reserve(size);
110 for (size_t i = 0; i < size; i++)
111 toEncode.push_back(i % 256);
112
113 Toolbox::EncodeBase64(base64Result, toEncode);
114 Toolbox::DecodeBase64(decodedResult, base64Result);
115
116 ASSERT_EQ(toEncode, decodedResult);
117 }
118 }
119
EncodeBase64Bis(const std::string & s)120 static std::string EncodeBase64Bis(const std::string& s)
121 {
122 std::string result;
123 Toolbox::EncodeBase64(result, s);
124 return result;
125 }
126
127
TEST(Toolbox,Base64)128 TEST(Toolbox, Base64)
129 {
130 ASSERT_EQ("", EncodeBase64Bis(""));
131 ASSERT_EQ("YQ==", EncodeBase64Bis("a"));
132
133 const std::string hello = "SGVsbG8gd29ybGQ=";
134 ASSERT_EQ(hello, EncodeBase64Bis("Hello world"));
135
136 std::string decoded;
137 Toolbox::DecodeBase64(decoded, hello);
138 ASSERT_EQ("Hello world", decoded);
139
140 // Invalid character
141 ASSERT_THROW(Toolbox::DecodeBase64(decoded, "?"), OrthancException);
142
143 // All the allowed characters
144 Toolbox::DecodeBase64(decoded, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");
145 }
146
147
148 #if 0 // enable only when compiling in Release with a C++ 11 compiler
149 #include <chrono> // I had troubles to link with boost::chrono ...
150
151 TEST(Toolbox, Base64_largeString)
152 {
153 std::string toEncode;
154 std::string base64Result;
155 std::string decodedResult;
156
157 size_t size = 10 * 1024 * 1024;
158 toEncode.reserve(size);
159 for (size_t i = 0; i < size; i++)
160 toEncode.push_back(i % 256);
161
162 std::chrono::high_resolution_clock::time_point start;
163 std::chrono::high_resolution_clock::time_point afterEncoding;
164 std::chrono::high_resolution_clock::time_point afterDecoding;
165
166 start = std::chrono::high_resolution_clock::now();
167 Orthanc::Toolbox::EncodeBase64(base64Result, toEncode);
168 afterEncoding = std::chrono::high_resolution_clock::now();
169 Orthanc::Toolbox::DecodeBase64(decodedResult, base64Result);
170 afterDecoding = std::chrono::high_resolution_clock::now();
171
172 ASSERT_EQ(toEncode, decodedResult);
173
174 printf("encoding took %zu ms\n", (std::chrono::duration_cast<std::chrono::milliseconds>(afterEncoding - start)));
175 printf("decoding took %zu ms\n", (std::chrono::duration_cast<std::chrono::milliseconds>(afterDecoding - afterEncoding)));
176 }
177 #endif
178
179
TEST(Toolbox,LargeHexadecimalToDecimal)180 TEST(Toolbox, LargeHexadecimalToDecimal)
181 {
182 // https://stackoverflow.com/a/16967286/881731
183 ASSERT_EQ(
184 "166089946137986168535368849184301740204613753693156360462575217560130904921953976324839782808018277000296027060873747803291797869684516494894741699267674246881622658654267131250470956587908385447044319923040838072975636163137212887824248575510341104029461758594855159174329892125993844566497176102668262139513",
185 Toolbox::LargeHexadecimalToDecimal("EC851A69B8ACD843164E10CFF70CF9E86DC2FEE3CF6F374B43C854E3342A2F1AC3E30C741CC41E679DF6D07CE6FA3A66083EC9B8C8BF3AF05D8BDBB0AA6Cb3ef8c5baa2a5e531ba9e28592f99e0fe4f95169a6c63f635d0197e325c5ec76219b907e4ebdcd401fb1986e4e3ca661ff73e7e2b8fd9988e753b7042b2bbca76679"));
186
187 ASSERT_EQ("0", Toolbox::LargeHexadecimalToDecimal(""));
188 ASSERT_EQ("0", Toolbox::LargeHexadecimalToDecimal("0"));
189 ASSERT_EQ("0", Toolbox::LargeHexadecimalToDecimal("0000"));
190 ASSERT_EQ("255", Toolbox::LargeHexadecimalToDecimal("00000ff"));
191
192 ASSERT_THROW(Toolbox::LargeHexadecimalToDecimal("g"), Orthanc::OrthancException);
193 }
194
195
TEST(Toolbox,GenerateDicomPrivateUniqueIdentifier)196 TEST(Toolbox, GenerateDicomPrivateUniqueIdentifier)
197 {
198 std::string s = Toolbox::GenerateDicomPrivateUniqueIdentifier();
199 ASSERT_EQ("2.25.", s.substr(0, 5));
200 }
201
202
TEST(Toolbox,UniquePtr)203 TEST(Toolbox, UniquePtr)
204 {
205 std::unique_ptr<int> i(new int(42));
206 ASSERT_EQ(42, *i);
207
208 std::unique_ptr<SingleValueObject<int> > j(new SingleValueObject<int>(42));
209 ASSERT_EQ(42, j->GetValue());
210 }
211