d5295f0bf71ca55158ef98a68a2b0ea5829b9ec0
[alexxy/gromacs-domains.git] / src / domaintests.cpp
1 #include "domaintype.h"
2 #include "newfit.h"
3
4 #include "gtest/gtest.h"
5
6 #include <iostream>
7
8 // https://habr.com/ru/post/119090/
9
10 TEST( fitTests, fitTest_F )
11 {
12     DVec a, b, angl;
13
14     // расстояние по осям для направляющих векторов
15     ASSERT_NEAR(F({1, 0., 0.}, {-1, 0., 0.}, {0., 0., 0.}), 2, 0.000001);
16     ASSERT_NEAR(F({0., 1, 0.}, {0., -1, 0.}, {0., 0., 0.}), 2, 0.000001);
17     ASSERT_NEAR(F({0., 0., 1}, {0., 0., -1}, {0., 0., 0.}), 2, 0.000001);
18
19     // расстояние по осям + повороты по осям для направляющих векторов
20     ASSERT_NEAR(F({1, 0., 0.}, {-1, 0., 0.}, {M_PI, 0., 0.}), 2, 0.000001);
21     ASSERT_NEAR(F({1, 0., 0.}, {-1, 0., 0.}, {0., M_PI, 0.}), 0., 0.000001);
22     ASSERT_NEAR(F({1, 0., 0.}, {-1, 0., 0.}, {0., 0., M_PI}), 0., 0.000001);
23
24     ASSERT_NEAR(F({0., 1, 0.}, {0., -1, 0.}, {0., M_PI, 0.}), 2, 0.000001);
25     ASSERT_NEAR(F({0., 1, 0.}, {0., -1, 0.}, {M_PI, 0., 0.}), 0., 0.000001);
26     ASSERT_NEAR(F({0., 1, 0.}, {0., -1, 0.}, {0., 0., M_PI}), 0., 0.000001);
27
28     ASSERT_NEAR(F({0., 0., 1}, {0., 0., -1}, {0., 0., M_PI}), 2, 0.000001);
29     ASSERT_NEAR(F({0., 0., 1}, {0., 0., -1}, {0., M_PI, 0.}), 0., 0.000001);
30     ASSERT_NEAR(F({0., 0., 1}, {0., 0., -1}, {M_PI, 0., 0.}), 0., 0.000001);
31
32     // расстояние для сложного вектора
33     ASSERT_NEAR(F({1, 1, 1}, {-1, -1, -1}, {0., 0., 0.}), std::sqrt(3) * 2, 0.000001);
34     ASSERT_NEAR(F({1, 1, 1}, {-1, 1, 1}, {0., 0., 0.}), 2, 0.000001);
35     ASSERT_NEAR(F({1, 1, 1}, {-1, -1, 1}, {0., 0., 0.}), std::sqrt(2) * 2, 0.000001);
36
37     // расстояния для сложного вектора + повороты
38     ASSERT_NEAR(F({1, 1, 1}, {-1, -1, -1}, {M_PI, M_PI / 2, 0.}), 0., 0.000001);
39     ASSERT_NEAR(F({1, 1, 1}, {-1, 1, 1}, {0., 0., -M_PI / 2}), 0., 0.000001);
40 }
41
42 TEST( fitTests, fitTest_searchF0xyzabc)
43 {
44     // шаблон - ещё под вопросом нужно ли и как сделать если да
45 }
46
47 void ApplyFitRoutine(const std::vector< RVec > &fr1, const std::vector< RVec > &fr2, const std::vector< std::pair< size_t, size_t > > &testPairs, const DVec &R, const DVec &angl, DVec &md1, DVec &md2) {
48     std::vector< RVec > fr3;
49     fr3.resize(0);
50     fr3 = fr2;
51     ApplyFit(fr3, R, angl);
52     CalcMid(fr1, fr3, md1, md2, testPairs);
53 }
54
55 TEST( fitTests, fitTest_ApplyFit)
56 {
57     RVec x1(1, 0, 0), y1(0, 1, 0), z1(0, 0, 1), x2(-1, 0, 0), y2(0, -1, 0), z2(0, 0, -1);
58     DVec mid1(0., 0., 0.), mid2(0., 0., 0.), angl(0., 0., 0.);
59
60     std::vector< RVec > testFrame1, testFrame2, testFrame3;
61     testFrame1.resize(0);
62     testFrame2.resize(0);
63     std::vector< std::pair< size_t, size_t > > testPairs;
64     testPairs.resize(0);
65
66     for (size_t i {0}; i < 27; i++) {
67         testFrame1.push_back(x1 * static_cast< float >(i % 3) + y1 * static_cast< float >((i % 9) / 3) + z1 * static_cast< float >(i / 9));
68         testFrame2.push_back(x2 * static_cast< float >(i % 3) + y2 * static_cast< float >((i % 9) / 3) + z2 * static_cast< float >(i / 9));
69         testPairs.push_back(std::make_pair(i, i));
70     }
71
72     ApplyFitRoutine(testFrame1, testFrame2, testPairs, {2, 2, 2}, {0., 0., 0.}, mid1, mid2);
73     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
74
75     ApplyFitRoutine(testFrame2, testFrame1, testPairs, {0., 0., 0.}, {M_PI, 0., -M_PI / 2}, mid1, mid2);
76     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
77
78     ApplyFitRoutine(testFrame2, testFrame1, testPairs, {0., 0., 0.}, {0., M_PI, M_PI / 2}, mid1, mid2);
79     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
80
81     ApplyFitRoutine(testFrame2, testFrame1, testPairs, {0., 0., 0.}, {M_PI, M_PI / 2, 0.}, mid1, mid2);
82     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
83
84     ApplyFitRoutine(testFrame2, testFrame1, testPairs, {0., 0., 0.}, {3 * M_PI / 2, M_PI / 2, M_PI / 2}, mid1, mid2);
85     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
86
87     testFrame3.resize(0);
88     testFrame3 = testFrame1;
89     ApplyFit(testFrame1, {-1, -1, -1}, {M_PI, 0., -M_PI / 2});
90     ApplyFit(testFrame3, {0., 0., 0.}, {M_PI, 0., -M_PI / 2});
91     ApplyFit(testFrame3, {1, 1, 1}, {0., 0., 0.});
92     ApplyFit(testFrame1, {2, 4, 8}, {M_PI / 6, M_PI / 6, M_PI / 6});
93     ApplyFit(testFrame3, {2, 4, 8}, {M_PI / 6, M_PI / 6, M_PI / 6});
94     CalcMid(testFrame1, testFrame3, mid1, mid2, testPairs);
95     ASSERT_NEAR((mid1 - mid2).norm(), 0., 0.000001);
96     double testF {0};
97     for (size_t i {0}; i < testFrame1.size(); i++) {
98         testF += F(testFrame1[i].toDVec(), testFrame3[i].toDVec(), angl);
99     }
100     ASSERT_NEAR(testF, 0., 0.000001);
101 }
102
103 TEST( fitTests, fitTest_CalcMid)
104 {
105     RVec x1(1, 0, 0), y1(0, 1, 0), z1(0, 0, 1), x2(-1, 0, 0), y2(0, -1, 0), z2(0, 0, -1);
106     DVec mid1(0., 0., 0.), mid2(0., 0., 0.), angl(0., 0., 0.);
107
108     std::vector< RVec > testFrame1, testFrame2;
109     testFrame1.resize(0);
110     testFrame2.resize(0);
111     std::vector< std::pair< size_t, size_t > > testPairs;
112     testPairs.resize(0);
113
114     for (size_t i {0}; i < 27; i++) {
115         testFrame1.push_back(x1 * static_cast< float >(i % 3) + y1 * static_cast< float >((i % 9) / 3) + z1 * static_cast< float >(i / 9));
116         testFrame2.push_back(x2 * static_cast< float >(i % 3) + y2 * static_cast< float >((i % 9) / 3) + z2 * static_cast< float >(i / 9));
117         testPairs.push_back(std::make_pair(i, i));
118     }
119
120     CalcMid(testFrame1, testFrame1, mid1, mid2, testPairs);
121     ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000'001);
122
123     CalcMid(testFrame2, testFrame2, mid1, mid2, testPairs);
124     ASSERT_NEAR((mid1 - mid2).norm(), 0, 0.000'001);
125
126     CalcMid(testFrame1, testFrame2, mid1, mid2, testPairs);
127     ASSERT_NEAR((mid1 - mid2).norm(), 2 * std::sqrt(3), 0.000'001);
128 }
129
130 void myFitNewRoutine(const std::vector< RVec > &fr1, std::vector< RVec > fr2, const std::vector< std::pair< size_t, size_t > > &testPairs, double prc, double &tF) {
131     MyFitNew(fr1, fr2, testPairs, prc);
132     tF = 0;
133     DVec angl(0., 0., 0.);
134     for (size_t i {0}; i < fr1.size(); i++) {
135         tF += F(fr1[i].toDVec(), fr2[i].toDVec(), angl);
136     }
137 }
138
139 TEST( fitTests, fitTest_MyFitNew)
140 {
141     RVec a(-2, -2, -2);
142     RVec x1(1, 0, 0), y1(0, 1, 0), z1(0, 0, 1);
143     RVec x2(10, 0, 0), y2(0, 10, 0), z2(0, 0, 10);
144     RVec x3(11, 0, 0), y3(0, 11, 0), z3(0, 0, 11);
145
146     std::vector< RVec > testFrame1, testFrame2;
147     testFrame1.resize(0);
148     testFrame2.resize(0);
149     std::vector< std::pair< size_t, size_t > > testPairs;
150     testPairs.resize(0);
151
152     /*
153      * optimal 3x3x3 cubes fitting
154     */
155
156     for (size_t i {0}; i < 27; i++) {
157         testFrame1.push_back(x1 * static_cast< float >(i % 3) + y1 * static_cast< float >((i % 9) / 3) + z1 * static_cast< float >(i / 9));
158         testFrame2.push_back(testFrame1.back() + a);
159         testPairs.push_back(std::make_pair(i, i));
160     }
161
162     double testF {0};
163
164     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF);
165     ASSERT_NEAR(testF, 0, 0.000'001);
166
167     ApplyFit(testFrame2, {7.153'4, 0.559'1, -3.141'5}, {M_PI / 23, M_PI / 17, M_PI / 2.2});
168
169     myFitNewRoutine(testFrame1, testFrame2, testPairs, 1, testF);
170     ASSERT_NEAR(testF, 0, 38.305);
171
172     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.1, testF);
173     ASSERT_NEAR(testF, 0, 2.313);
174
175     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.01, testF);
176     ASSERT_NEAR(testF, 0, 2.119);
177
178     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.001, testF);
179     ASSERT_NEAR(testF, 0, 0.026);
180
181     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'1, testF);
182     ASSERT_NEAR(testF, 0, 0.019'76);
183
184     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'01, testF);
185     ASSERT_NEAR(testF, 0, 0.019'76);
186
187     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF);
188     ASSERT_NEAR(testF, 0, 0.000'054);
189
190     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'1, testF);
191     ASSERT_NEAR(testF, 0, 0.000'054);
192
193     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'01, testF);
194     ASSERT_NEAR(testF, 0, 0.000'054);
195
196     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'001, testF);
197     ASSERT_NEAR(testF, 0, 0.000'054);
198
199     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'1, testF);
200     ASSERT_NEAR(testF, 0, 0.000'054);
201
202     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'01, testF);
203     ASSERT_NEAR(testF, 0, 0.000'054);
204
205     /*
206      * different sized 3x3x3 cubes fitting
207     */
208
209     testFrame1.resize(0);
210     testFrame2.resize(0);
211     for (size_t i {0}; i < 27; i++) {
212         testFrame1.push_back(x2 * static_cast< float >(i % 3) + y2 * static_cast< float >((i % 9) / 3) + z2 * static_cast< float >(i / 9));
213         testFrame2.push_back(x3 * static_cast< float >(i % 3) + y3 * static_cast< float >((i % 9) / 3) + z3 * static_cast< float >(i / 9));
214     }
215
216     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF);
217     ASSERT_NEAR(testF, 0, 36.827);
218
219     ApplyFit(testFrame2, {7.1534, 0.5591, -3.1415}, {M_PI / 23, M_PI / 17, M_PI / 2.2});
220
221     myFitNewRoutine(testFrame1, testFrame2, testPairs, 1, testF);
222     ASSERT_NEAR(testF, 0, 250.665);
223
224     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.1, testF);
225     ASSERT_NEAR(testF, 0, 249.856);
226
227     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.01, testF);
228     ASSERT_NEAR(testF, 0, 248.364);
229
230     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.001, testF);
231     ASSERT_NEAR(testF, 0, 246.780);
232
233     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'1, testF);
234     ASSERT_NEAR(testF, 0, 227.930);
235
236     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'01, testF);
237     ASSERT_NEAR(testF, 0, 36.953);
238
239     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'001, testF);
240     ASSERT_NEAR(testF, 0, 36.953);
241
242     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'1, testF);
243     ASSERT_NEAR(testF, 0, 36.885);
244
245     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'01, testF);
246     ASSERT_NEAR(testF, 0, 36.884'71);
247
248     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'001, testF);
249     ASSERT_NEAR(testF, 0, 36.884'71);
250
251     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'1, testF);
252     ASSERT_NEAR(testF, 0, 36.884'71);
253
254     myFitNewRoutine(testFrame1, testFrame2, testPairs, 0.000'000'000'01, testF);
255     ASSERT_NEAR(testF, 0, 36.884'71);
256
257 }
258
259 // т.к. домены это класс с кучей приватных функций ещё под вопросом как их тестить
260 // https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#testing-private-code
261 // FRIEND_TEST
262
263 //
264 // public API tests
265 //
266
267 TEST( domainTests, domainTest_setDefaults)
268 {
269     domainType testDomain;
270     std::vector< size_t > testIndex;
271     testIndex.resize(0);
272     std::vector< RVec > testRef;
273     testRef.resize(0);
274
275     RVec testA(0., 0., 0.), testB(1., 1., 1.);
276     for (size_t i {0}; i < 100; i++) {
277         testIndex.push_back(i);
278         testRef.push_back(testA + testB * static_cast< float >(i));
279     }
280
281     int testWindowSize {500};
282     int testDomainMinimumSize {5};
283     int testDomainSearchAlgorythm {1};
284     int testTimeStepBetweenWindows {100};
285     size_t testSliceNum {testIndex.size() - testDomainMinimumSize + 1};
286     double testEpsilon {1.5};
287     double testDelta {0.98};
288     std::string testOutPutFileName {"testString"};
289
290     testDomain.setDefaults(testIndex, testRef, testWindowSize, testDomainMinimumSize, testDomainSearchAlgorythm, testTimeStepBetweenWindows, testSliceNum, testEpsilon, testDelta, testOutPutFileName);
291
292     ASSERT_EQ(testDomain.graph.size(), 0);
293     ASSERT_EQ(testDomain.structIndex, testIndex);
294
295     ASSERT_EQ(testDomain.refTable.size(), testRef.size());
296     for (size_t j {0}; j < testRef.size(); j++) {
297         for (size_t i {0}; i < testRef.size(); i++) {
298             ASSERT_NEAR(testDomain.refTable[j][i].norm(), (testRef[i] - testRef[j]).norm(), 0.000'01);
299         }
300     }
301
302     ASSERT_EQ(testDomain.eps, testEpsilon);
303     ASSERT_EQ(testDomain.dlt, testDelta);
304     ASSERT_EQ(testDomain.window, testWindowSize);
305     ASSERT_EQ(testDomain.dms, testDomainMinimumSize);
306     ASSERT_EQ(testDomain.dsa, testDomainSearchAlgorythm);
307     ASSERT_EQ(testDomain.ts, testTimeStepBetweenWindows);
308     ASSERT_EQ(testDomain.outPut, testOutPutFileName);
309     ASSERT_EQ(testDomain.domsizes.size(), testSliceNum);
310     ASSERT_EQ(testDomain.updateCount, 0);
311 }
312
313 TEST( domainTests, domainTest_update)
314 {
315     std::vector< std::vector< RVec > > testTraj1, testTraj2, testTraj3;
316     testTraj1.resize(0);
317     testTraj2.resize(0);
318     testTraj3.resize(0);
319     RVec testA(1, 2, 3), testB(1, 0, 0), testC(0, 1, 0);
320     for (size_t i0 {0}; i0 < 1000; i0++) {
321         testTraj1.resize(testTraj1.size() + 1);
322         testTraj2.resize(testTraj2.size() + 1);
323         testTraj3.resize(testTraj3.size() + 1);
324         for (size_t i1 {0}; i1 < 10; i1++) {
325             testTraj1.back().push_back(static_cast< float >(i1) * testA + static_cast< float >(i0) * testB);
326             testTraj2.back().push_back(static_cast< float >(i1) * testA + static_cast< float >(i0) * testB);
327             testTraj3.back().push_back(static_cast< float >(i1) * testA + static_cast< float >(i0) * testB + static_cast< float >(i0) * testC);
328         }
329         for (size_t i1 {0}; i1 < 10; i1++) {
330             testTraj1.back().push_back(static_cast< float >(i1) * testA - static_cast< float >(i0) * testB);
331             testTraj2.back().push_back(static_cast< float >(i1) * testA + static_cast< float >(i0) * testC);
332             testTraj3.back().push_back(static_cast< float >(i1) * testA + static_cast< float >(i0) * testB - static_cast< float >(i0) * testC);
333         }
334     }
335     std::vector< size_t > testIndex;
336     testIndex.resize(0);
337     std::vector< RVec > testRef;
338     testRef.resize(0);
339     for (size_t i {0}; i < 20; i++) {
340         testIndex.push_back(i);
341         testRef.push_back(static_cast< float >(i % 10) * testA);
342     }
343     int testWindowSize {500};
344     int testDomainMinimumSize {4};
345     int testDomainSearchAlgorythm {0};
346     int testTimeStepBetweenWindows {100};
347     size_t testSliceNum {testIndex.size() - testDomainMinimumSize + 1};
348     double testEpsilon {1.5};
349     double testDelta {0.98};
350     std::string testOutPutFileName1 {"testString1.ndx"}, testOutPutFileName2 {"testString2.ndx"}, testOutPutFileName3 {"testString3.ndx"};
351
352     domainType testDomain1, testDomain2, testDomain3;
353     testDomain1.setDefaults(testIndex, testRef, testWindowSize, testDomainMinimumSize, testDomainSearchAlgorythm, testTimeStepBetweenWindows, testSliceNum, testEpsilon, testDelta, testOutPutFileName1);
354     testDomain2.setDefaults(testIndex, testRef, testWindowSize, testDomainMinimumSize, testDomainSearchAlgorythm, testTimeStepBetweenWindows, testSliceNum, testEpsilon, testDelta, testOutPutFileName2);
355     testDomain3.setDefaults(testIndex, testRef, testWindowSize, testDomainMinimumSize, testDomainSearchAlgorythm, testTimeStepBetweenWindows, testSliceNum, testEpsilon, testDelta, testOutPutFileName3);
356
357     std::vector< std::vector< RVec > > testTemp1, testTemp2, testTemp3;
358     for (size_t i {0}; i < 1000; i++) {
359         testTemp1.resize(0);
360         testTemp2.resize(0);
361         testTemp3.resize(0);
362         testTemp1.resize(testSliceNum, testTraj1[i]);
363         testTemp2.resize(testSliceNum, testTraj2[i]);
364         testTemp3.resize(testSliceNum, testTraj3[i]);
365         testDomain1.update(testTemp1, i);
366         testDomain2.update(testTemp2, i);
367         testDomain3.update(testTemp3, i);
368     }
369 }
370
371 //
372 // private API tests
373 //
374
375 TEST( domainTests, domainTest_setGraph)
376 {
377     // данную функцию тестировать смысла нет, слишком простой функционал
378 }
379
380 TEST( domainTests, domainTest_deleteDomainFromGraph)
381 {
382     // данную функцию тестировать смысла нет, слишком простой функционал
383 }
384
385 TEST( domainTests, domainTest_searchDomainSizes)
386 {
387     // данную функцию тестировать смысла нет, слишком простой функционал
388 }
389
390 TEST( domainTests, domainTest_getDomains)
391 {
392     domainType testDomain;
393     std::vector< unsigned long > testIndex;
394     testIndex.resize(0);
395     std::vector< RVec > testRef;
396     testRef.resize(0);
397
398     RVec testA(0, 0, 0), testB(1, 1, 1);
399     for (size_t i {0}; i < 100; i++) {
400         testIndex.push_back(i);
401         testRef.push_back(testA + testB * static_cast< float >(i));
402     }
403
404     int testWindowSize {100};
405     int testDomainMinimumSize {5};
406     int testDomainSearchAlgorythm {0};
407     int testTimeStepBetweenWindows {100};
408     size_t testSliceNum {testIndex.size() - testDomainMinimumSize + 1};
409     double testEpsilon {1.5};
410     double testDelta {0.98};
411     std::string testOutPutFileName {"testString"};
412
413     testDomain.setDefaults(testIndex, testRef, testWindowSize, testDomainMinimumSize, testDomainSearchAlgorythm, testTimeStepBetweenWindows, testSliceNum, testEpsilon, testDelta, testOutPutFileName);
414
415     testDomain.graph.resize(1);
416     testDomain.graph.front().resize(testSliceNum);
417     for (size_t i1 {0}; i1 < testSliceNum; i1++) {
418         testDomain.setGraph(testDomain.graph.front()[i1]);
419         for (size_t i2 {0}; i2 < testIndex.size(); i2++) {
420             for (size_t i3 {0}; i3 < testIndex.size(); i3++) {
421                 testDomain.graph.front()[i1][i2][i3].num = 4;
422             }
423         }
424     }
425     testDomain.getDomains();
426     ASSERT_EQ(testDomain.domains.size(), 0);
427
428     for (int i0 {0}; i0 < 3; i0++) {
429         testDomain.graph.resize(1);
430         testDomain.graph.front().resize(testSliceNum);
431         for (size_t i1 {0}; i1 < testSliceNum; i1++) {
432             testDomain.setGraph(testDomain.graph.front()[i1]);
433             for (size_t i2 {0}; i2 < testIndex.size(); i2++) {
434                 for (size_t i3 {0}; i3 < testIndex.size(); i3++) {
435                     testDomain.graph.front()[i1][i2][i3].num = 100;
436                 }
437             }
438         }
439         testDomain.dsa = i0;
440         testDomain.getDomains();
441         ASSERT_EQ(testDomain.domains.size(), 1);
442     }
443
444     // шаблон
445     // сделать непересекающиеся - выделить
446     // пересекающиеся - выделить
447     // ещё подумать что это такое и как это выделяется
448 }
449
450 TEST( domainTests, domainTest_print)
451 {
452     // данную функцию тестировать смысла нет, слишком простой функционал
453     // или в целом не сильно понятно имеется ли смысл в этом
454 }
455
456 int main(int argc, char *argv[]) {
457     ::testing::InitGoogleTest( &argc, argv );
458     return RUN_ALL_TESTS();
459 }