1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <algorithm>
22 
23 #include <sal/types.h>
24 #include <cppunit/TestAssert.h>
25 #include <cppunit/TestFixture.h>
26 #include <cppunit/extensions/HelperMacros.h>
27 #include <cppunit/plugin/TestPlugIn.h>
28 
29 #include <rtl/random.h>
30 
31 #include <string.h>
32 
33 namespace rtl_random
34 {
35 
36 class createPool : public CppUnit::TestFixture
37 {
38 public:
39     // insert your test code here.
40     // this is only demonstration code
createPool_001()41     void createPool_001()
42     {
43         // this is demonstration code
44 
45         rtlRandomPool aPool = rtl_random_createPool();
46 
47         // LLA: seems to be that another test is not possible for createPool()
48         CPPUNIT_ASSERT_MESSAGE("create failed", aPool != nullptr);
49 
50         rtl_random_destroyPool(aPool);
51     }
52 
53     // Change the following lines only, if you add, remove or rename
54     // member functions of the current class,
55     // because these macros are need by auto register mechanism.
56 
57     CPPUNIT_TEST_SUITE(createPool);
58     CPPUNIT_TEST(createPool_001);
59     CPPUNIT_TEST_SUITE_END();
60 }; // class createPool
61 
62 class destroyPool : public CppUnit::TestFixture
63 {
64 public:
65     // insert your test code here.
destroyPool_000()66     void destroyPool_000()
67     {
68         // GPF, if failed
69         rtl_random_destroyPool(nullptr);
70     }
71 
destroyPool_001()72     void destroyPool_001()
73     {
74         rtlRandomPool aPool = rtl_random_createPool();
75 
76         // LLA: seems to be that another test is not possible for createPool()
77         CPPUNIT_ASSERT_MESSAGE("create failed", aPool != nullptr);
78 
79         rtl_random_destroyPool(aPool);
80     }
81     // Change the following lines only, if you add, remove or rename
82     // member functions of the current class,
83     // because these macros are need by auto register mechanism.
84 
85     CPPUNIT_TEST_SUITE(destroyPool);
86     CPPUNIT_TEST(destroyPool_000);
87     CPPUNIT_TEST(destroyPool_001);
88     CPPUNIT_TEST_SUITE_END();
89 }; // class destroyPool
90 
91 class addBytes : public CppUnit::TestFixture
92 {
93 public:
94     // insert your test code here.
95     // this is only demonstration code
addBytes_000()96     void addBytes_000()
97     {
98         rtlRandomPool aPool = rtl_random_createPool();
99 
100         sal_uInt32  nBufLen = 4;
101         std::unique_ptr<sal_uInt8[]>  pBuffer( new sal_uInt8[ nBufLen ] );
102         memset(pBuffer.get(), 0, nBufLen);
103 
104         rtlRandomError aError = rtl_random_addBytes(nullptr, nullptr, 0);
105         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_Argument, aError);
106 
107         /* rtlRandomError */ aError = rtl_random_addBytes(aPool, nullptr, 0);
108         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_Argument, aError);
109 
110         /* rtlRandomError */ aError = rtl_random_addBytes(aPool, pBuffer.get(), nBufLen);
111         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_None, aError);
112 
113         rtl_random_destroyPool(aPool);
114     }
115 
addBytes_001()116     void addBytes_001()
117         {
118             rtlRandomPool aPool = rtl_random_createPool();
119 
120             sal_uInt32  nBufLen = 4;
121             std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nBufLen ] );
122 
123             memset(pBuffer.get(), 0, nBufLen);
124 
125             rtl_random_addBytes(aPool, pBuffer.get(), nBufLen);
126 
127             printf("%2x %2x %2x %2x\n", pBuffer[0], pBuffer[1], pBuffer[2], pBuffer[3]);
128 
129             rtl_random_destroyPool(aPool);
130         }
131 
132     // Change the following lines only, if you add, remove or rename
133     // member functions of the current class,
134     // because these macros are need by auto register mechanism.
135 
136     CPPUNIT_TEST_SUITE(addBytes);
137     CPPUNIT_TEST(addBytes_000);
138     CPPUNIT_TEST(addBytes_001);
139     CPPUNIT_TEST_SUITE_END();
140 }; // class addBytes
141 
142 namespace {
143 
144 class Statistics
145 {
146     int m_nDispensation[256];
147 
148     int m_nMin;
149     int m_nMax;
150     int m_nAverage;
151     int m_nMinDeviation;
152     int m_nMaxDeviation;
153 
154 public:
clearDispensation()155     void clearDispensation()
156     {
157         for (int i = 0;i < 256;++i)                        // clear array
158         {
159             m_nDispensation[i] = 0;
160         }
161     }
Statistics()162     Statistics()
163     : m_nMin(0)
164     , m_nMax(0)
165     , m_nAverage(0)
166     , m_nMinDeviation(0)
167     , m_nMaxDeviation(0)
168     {
169         clearDispensation();
170     }
171 
addValue(sal_uInt8 _nIndex,sal_Int32 _nValue)172     void addValue(sal_uInt8 _nIndex, sal_Int32 _nValue)
173     {
174         m_nDispensation[_nIndex] += _nValue;
175     }
176 
build(sal_Int32 _nCountMax)177     void build(sal_Int32 _nCountMax)
178     {
179         m_nMin = _nCountMax;
180         m_nMax = 0;
181 
182         m_nAverage = _nCountMax / 256;
183 
184         m_nMinDeviation = _nCountMax;
185         m_nMaxDeviation = 0;
186 
187         for (int i = 0;i < 256;++i)                        // show dispensation
188         {
189             m_nMin = std::min(m_nMin, m_nDispensation[i]);
190             m_nMax = std::max(m_nMax, m_nDispensation[i]);
191 
192             m_nMinDeviation = std::min(m_nMinDeviation, abs(m_nAverage - m_nDispensation[i]));
193             m_nMaxDeviation = std::max(m_nMaxDeviation, abs(m_nAverage - m_nDispensation[i]));
194         }
195     }
196 
print()197     void print()
198     {
199         // LLA: these are only info values
200         printf("\nSome statistics\n");
201         printf("Min: %d\n", m_nMin);
202         printf("Max: %d\n", m_nMax);
203         printf("Average: %d\n", m_nAverage);
204         printf("Min abs deviation: %d\n", m_nMinDeviation);
205         printf("Max abs deviation: %d\n", m_nMaxDeviation);
206     }
207 
getAverage() const208     sal_Int32 getAverage() const {return m_nAverage;}
getMaxDeviation() const209     sal_Int32 getMaxDeviation() const {return m_nMaxDeviation;}
210 
211 };
212 
213 }
214 
215 class getBytes : public CppUnit::TestFixture
216 {
217 public:
218     // insert your test code here.
getBytes_000()219     void getBytes_000()
220     {
221         rtlRandomPool aPool = rtl_random_createPool();
222 
223         sal_uInt32  nBufLen = 4;
224         std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nBufLen ] );
225         memset(pBuffer.get(), 0, nBufLen);
226 
227         rtlRandomError aError = rtl_random_getBytes(nullptr, nullptr, 0);
228         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_Argument, aError);
229 
230         /* rtlRandomError */ aError = rtl_random_getBytes(aPool, nullptr, 0);
231         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_Argument, aError);
232 
233         /* rtlRandomError */ aError = rtl_random_getBytes(aPool, pBuffer.get(), nBufLen);
234         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_None, aError);
235 
236         rtl_random_destroyPool(aPool);
237     }
238 
getBytes_001()239     void getBytes_001()
240     {
241         rtlRandomPool aPool = rtl_random_createPool();
242 
243         sal_uInt32  nBufLen = 4;
244         std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nBufLen ] );
245         memset(pBuffer.get(), 0, nBufLen);
246 
247         rtlRandomError aError = rtl_random_getBytes(aPool, pBuffer.get(), nBufLen);
248         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_None, aError);
249 
250         printf("%2x %2x %2x %2x\n", pBuffer[0], pBuffer[1], pBuffer[2], pBuffer[3]);
251 
252         rtl_random_destroyPool(aPool);
253     }
254 
getBytes_002()255     void getBytes_002()
256     {
257         rtlRandomPool aPool = rtl_random_createPool();
258 
259         sal_uInt32  nBufLen = 4;
260         std::unique_ptr<sal_uInt8[]>  pBuffer( new sal_uInt8[ nBufLen << 1 ] );
261         memset(pBuffer.get(), 0, nBufLen << 1);
262 
263         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", sal_uInt8(0), pBuffer[4]);
264         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", sal_uInt8(0), pBuffer[5]);
265         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", sal_uInt8(0), pBuffer[6]);
266         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", sal_uInt8(0), pBuffer[7]);
267 
268         rtlRandomError aError = rtl_random_getBytes(aPool, pBuffer.get(), nBufLen);
269         CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong parameter", rtl_Random_E_None, aError);
270 
271         printf("%2x %2x %2x %2x %2x %2x %2x %2x\n", pBuffer[0], pBuffer[1], pBuffer[2], pBuffer[3], pBuffer[4], pBuffer[5], pBuffer[6], pBuffer[7]);
272 
273         CPPUNIT_ASSERT_EQUAL_MESSAGE("internal memory overwrite", sal_uInt8(0), pBuffer[4]);
274         CPPUNIT_ASSERT_EQUAL_MESSAGE("internal memory overwrite", sal_uInt8(0), pBuffer[5]);
275         CPPUNIT_ASSERT_EQUAL_MESSAGE("internal memory overwrite", sal_uInt8(0), pBuffer[6]);
276         CPPUNIT_ASSERT_EQUAL_MESSAGE("internal memory overwrite", sal_uInt8(0), pBuffer[7]);
277 
278         rtl_random_destroyPool(aPool);
279     }
280 
getBytes_003()281     void getBytes_003()
282     {
283         rtlRandomPool aPool = rtl_random_createPool();
284 
285         sal_uInt32  nBufLen = 1;
286         std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nBufLen ] );
287         memset(pBuffer.get(), 0, nBufLen);
288 
289         Statistics aStat;
290 
291         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", static_cast<sal_uInt8>(0), pBuffer[0]);
292 
293         int nCount = 0;
294 
295         int nCountMax = 1000000;
296         for(nCount = 0;nCount < nCountMax; ++nCount)                  // run 100000000 through getBytes(...)
297         {
298             /* rtlRandomError aError = */ rtl_random_getBytes(aPool, pBuffer.get(), nBufLen);
299             /* CPPUNIT_ASSERT_MESSAGE("wrong parameter", aError == rtl_Random_E_None); */
300 
301             aStat.addValue(pBuffer[0], 1);
302         }
303 
304         aStat.build(nCountMax);
305         aStat.print();
306 
307         CPPUNIT_ASSERT_MESSAGE("deviation should be less average", aStat.getMaxDeviation() < aStat.getAverage());
308 
309         rtl_random_destroyPool(aPool);
310     }
311 
getBytes_003_1()312     void getBytes_003_1()
313     {
314         rtlRandomPool aPool = rtl_random_createPool();
315 
316         sal_uInt32  nBufLen = 256;
317         std::unique_ptr<sal_uInt8[]> pBuffer( new sal_uInt8[ nBufLen ] );
318         memset(pBuffer.get(), 0, nBufLen);
319 
320         Statistics aStat;
321 
322         CPPUNIT_ASSERT_EQUAL_MESSAGE("memset failed", static_cast<sal_uInt8>(0), pBuffer[0]);
323 
324         int nCount = 0;
325 
326         int nCountMax = 10000;
327         for(nCount = 0;nCount < nCountMax; ++nCount)                  // run 100000000 through getBytes(...)
328         {
329             /* rtlRandomError aError = */ rtl_random_getBytes(aPool, pBuffer.get(), nBufLen);
330             // CPPUNIT_ASSERT_MESSAGE("wrong parameter", aError == rtl_Random_E_None);
331 
332             for (sal_uInt32 i=0;i<nBufLen;++i)
333                 aStat.addValue(pBuffer[i], 1);
334         }
335 
336         aStat.build(nCountMax * nBufLen);
337         aStat.print();
338 
339         CPPUNIT_ASSERT_MESSAGE("deviation should be less average", aStat.getMaxDeviation() < aStat.getAverage());
340 
341         rtl_random_destroyPool(aPool);
342     }
343 
344     // Change the following lines only, if you add, remove or rename
345     // member functions of the current class,
346     // because these macros are need by auto register mechanism.
347 
348     CPPUNIT_TEST_SUITE(getBytes);
349     CPPUNIT_TEST(getBytes_000);
350     CPPUNIT_TEST(getBytes_001);
351     CPPUNIT_TEST(getBytes_002);
352     CPPUNIT_TEST(getBytes_003);
353     CPPUNIT_TEST(getBytes_003_1);
354     CPPUNIT_TEST_SUITE_END();
355 }; // class getBytes
356 
357 CPPUNIT_TEST_SUITE_REGISTRATION(rtl_random::createPool);
358 CPPUNIT_TEST_SUITE_REGISTRATION(rtl_random::destroyPool);
359 CPPUNIT_TEST_SUITE_REGISTRATION(rtl_random::addBytes);
360 CPPUNIT_TEST_SUITE_REGISTRATION(rtl_random::getBytes);
361 } // namespace rtl_random
362 
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
364