OSDN Git Service

Improved hash function tests.
[mutilities/MUtilities.git] / test / src / HashTest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 #include "MUtilsTest.h"
23
24 //MUtils
25 #include <MUtils/Hash.h>
26
27 //Qt
28 #include <QSet>
29
30 //===========================================================================
31 // HELPER METHODS
32 //===========================================================================
33
34 static _inline void fisherYatesShuffle(QByteArray &arr)
35 {
36         char *const ptr = arr.data();
37         for (int k = arr.size() - 1; k > 0; k--)
38         {
39                 qSwap(ptr[k], ptr[qrand() % (k + 1)]);
40         }
41 }
42
43 //===========================================================================
44 // TESTBED CLASS
45 //===========================================================================
46
47 class HashTest : public Testbed
48 {
49 protected:
50         virtual void SetUp()
51         {
52         }
53
54         virtual void TearDown()
55         {
56         }
57 };
58
59 //===========================================================================
60 // TEST METHODS
61 //===========================================================================
62
63 static const char *const TEST_MESSAGE_ORG = "The quick brown fox jumps over the lazy dog";
64 static const char *const TEST_MESSAGE_ALT = "The quick brown fox jumps over the lazy fog";
65
66 static const char* const SEED_KEY = "S73_iT6BTdgNc?kL";
67
68 #define TEST_HASH_DIRECT(ID, INPUT, DIGEST) do \
69 { \
70         QScopedPointer<MUtils::Hash::Hash> test_1(MUtils::Hash::create(MUtils::Hash::HASH_##ID)); \
71         QScopedPointer<MUtils::Hash::Hash> test_2(MUtils::Hash::create(MUtils::Hash::HASH_##ID, SEED_KEY)); \
72         ASSERT_TRUE(test_1->update(QByteArray(INPUT))); \
73         ASSERT_TRUE(test_2->update(QByteArray(INPUT))); \
74         const QByteArray result_1 = test_1->digest(); \
75         const QByteArray result_2 = test_2->digest(); \
76         ASSERT_STRCASENE(result_1.constData(), result_2.constData()); \
77         ASSERT_STRCASEEQ(result_1.constData(), (DIGEST)); \
78 } \
79 while(0)
80
81 #define TEST_HASH_FILEIO(ID, INPUT, DIGEST) do \
82 { \
83         const QString workDir = makeTempFolder(__FUNCTION__); \
84         ASSERT_FALSE(workDir.isEmpty()); \
85         const QString fileName = QString("%1/message.txt").arg(workDir); \
86         { \
87                 QFile file(fileName); \
88                 ASSERT_TRUE(file.open(QIODevice::WriteOnly | QIODevice::Truncate)); \
89                 file.write((INPUT), qstrlen((INPUT))); \
90                 file.close(); \
91         } \
92         { \
93                 QScopedPointer<MUtils::Hash::Hash> test(MUtils::Hash::create(MUtils::Hash::HASH_##ID)); \
94                 QFile file(fileName); \
95                 ASSERT_TRUE(file.open(QIODevice::ReadOnly)); \
96                 ASSERT_TRUE(test->update(file)); \
97                 file.close(); \
98                 ASSERT_STRCASEEQ(test->digest(), (DIGEST)); \
99         } \
100         QFile::remove(fileName); \
101 } \
102 while(0)
103
104 #define TEST_HASH_STRESS(ID, HASHMAP, INPUT) do \
105 { \
106         QByteArray message((INPUT)); \
107         const int initialSize = (HASHMAP).size(); \
108         qsrand(time(NULL)); \
109         for (size_t i = 0; i < 1299827; i++) \
110         { \
111                 fisherYatesShuffle(message); \
112                 QScopedPointer<MUtils::Hash::Hash> hash(MUtils::Hash::create(MUtils::Hash::HASH_##ID)); \
113                 ASSERT_TRUE(hash->update(message)); \
114                 (HASHMAP).insert(hash->digest(false)); \
115                 ASSERT_GT(((size_t)(HASHMAP).count()), initialSize + i); \
116         } \
117 } \
118 while (0)
119
120 //-----------------------------------------------------------------
121 // Keccak
122 //-----------------------------------------------------------------
123
124 TEST_F(HashTest, TestKeccak224Direct)
125 {
126         TEST_HASH_DIRECT(KECCAK_224, "",               "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd");
127         TEST_HASH_DIRECT(KECCAK_224, TEST_MESSAGE_ORG, "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe");
128         TEST_HASH_DIRECT(KECCAK_224, TEST_MESSAGE_ALT, "6db4cb22fe56606394880043ce4917a1803ad73b2e2b782768ea713b");
129 }
130
131 TEST_F(HashTest, TestKeccak224FileIO)
132 {
133         TEST_HASH_FILEIO(KECCAK_224, TEST_MESSAGE_ORG, "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe");
134         TEST_HASH_FILEIO(KECCAK_224, TEST_MESSAGE_ALT, "6db4cb22fe56606394880043ce4917a1803ad73b2e2b782768ea713b");
135 }
136
137 TEST_F(HashTest, TestKeccak256Direct)
138 {
139         TEST_HASH_DIRECT(KECCAK_256, "",               "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
140         TEST_HASH_DIRECT(KECCAK_256, TEST_MESSAGE_ORG, "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15");
141         TEST_HASH_DIRECT(KECCAK_256, TEST_MESSAGE_ALT, "4cc2957d93a4a88251a40c48a42225364157567bc81d4aec9389ee7065c042d4");
142 }
143
144 TEST_F(HashTest, TestKeccak256FileIO)
145 {
146         TEST_HASH_FILEIO(KECCAK_256, TEST_MESSAGE_ORG, "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15");
147         TEST_HASH_FILEIO(KECCAK_256, TEST_MESSAGE_ALT, "4cc2957d93a4a88251a40c48a42225364157567bc81d4aec9389ee7065c042d4");
148 }
149
150 TEST_F(HashTest, TestKeccak384Direct)
151 {
152         TEST_HASH_DIRECT(KECCAK_384, "",               "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff");
153         TEST_HASH_DIRECT(KECCAK_384, TEST_MESSAGE_ORG, "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3");
154         TEST_HASH_DIRECT(KECCAK_384, TEST_MESSAGE_ALT, "4e16433a5e0cdc2d88a21714a040c92999230a1c3d165a4e9670702b2df26f3587b4d721b6faaf348228f616dd921578");
155 }
156
157 TEST_F(HashTest, TestKeccak384FileIO)
158 {
159         TEST_HASH_FILEIO(KECCAK_384, TEST_MESSAGE_ORG, "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3");
160         TEST_HASH_FILEIO(KECCAK_384, TEST_MESSAGE_ALT, "4e16433a5e0cdc2d88a21714a040c92999230a1c3d165a4e9670702b2df26f3587b4d721b6faaf348228f616dd921578");
161 }
162
163 TEST_F(HashTest, TestKeccak512Direct)
164 {
165         TEST_HASH_DIRECT(KECCAK_512, "",               "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e");
166         TEST_HASH_DIRECT(KECCAK_512, TEST_MESSAGE_ORG, "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609");
167         TEST_HASH_DIRECT(KECCAK_512, TEST_MESSAGE_ALT, "0b46f421465ec602262e0a1044e59b36fbdb5f63f84e712963d2bc61bcb46ab0ebf86e59c14c253717ea558929c251695663226ffa5660ff7a29a5acbdaea901");
168 }
169
170 TEST_F(HashTest, TestKeccak512FileIO)
171 {
172         TEST_HASH_FILEIO(KECCAK_512, TEST_MESSAGE_ORG, "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609");
173         TEST_HASH_FILEIO(KECCAK_512, TEST_MESSAGE_ALT, "0b46f421465ec602262e0a1044e59b36fbdb5f63f84e712963d2bc61bcb46ab0ebf86e59c14c253717ea558929c251695663226ffa5660ff7a29a5acbdaea901");
174 }
175
176 TEST_F(HashTest, TestKeccak512Stress)
177 {
178         QSet<QByteArray> test;
179         TEST_HASH_STRESS(KECCAK_512, test, TEST_MESSAGE_ORG);
180         TEST_HASH_STRESS(KECCAK_512, test, TEST_MESSAGE_ALT);
181 }
182
183 //-----------------------------------------------------------------
184 // BLAKE2
185 //-----------------------------------------------------------------
186
187 TEST_F(HashTest, TestBlake2Direct)
188 {
189         TEST_HASH_DIRECT(BLAKE2_512, "",               "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce");
190         TEST_HASH_DIRECT(BLAKE2_512, TEST_MESSAGE_ORG, "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918");
191         TEST_HASH_DIRECT(BLAKE2_512, TEST_MESSAGE_ALT, "a5b8a16391f8e34e16901fc2fd5754523b0c95354c2f22d3efc327c53070504ea062e219c502561f77a4933c18d36633e5f3ecf1f11506159f4b1875abb767c1");
192 }
193
194 TEST_F(HashTest, TestBlake2FileIO)
195 {
196         TEST_HASH_FILEIO(BLAKE2_512, TEST_MESSAGE_ORG, "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918");
197         TEST_HASH_FILEIO(BLAKE2_512, TEST_MESSAGE_ALT, "a5b8a16391f8e34e16901fc2fd5754523b0c95354c2f22d3efc327c53070504ea062e219c502561f77a4933c18d36633e5f3ecf1f11506159f4b1875abb767c1");
198 }
199
200 TEST_F(HashTest, TestBlake2Stress)
201 {
202         QSet<QByteArray> test;
203         TEST_HASH_STRESS(BLAKE2_512, test, TEST_MESSAGE_ORG);
204         TEST_HASH_STRESS(BLAKE2_512, test, TEST_MESSAGE_ALT);
205 }
206
207 #undef TEST_HASH_DIRECT
208 #undef TEST_HASH_FILEIO