1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2014-2018 Xiph.Org Foundation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdio.h>
24
25 #include "FLAC/assert.h"
26 #include "share/compat.h"
27 #include "private/crc.h"
28 #include "crc.h"
29
30 static FLAC__uint8 crc8_update_ref(FLAC__byte byte, FLAC__uint8 crc);
31 static FLAC__uint16 crc16_update_ref(FLAC__byte byte, FLAC__uint16 crc);
32
33 static FLAC__bool test_crc8(const FLAC__byte *data, size_t size);
34 static FLAC__bool test_crc16(const FLAC__byte *data, size_t size);
35 static FLAC__bool test_crc16_update(const FLAC__byte *data, size_t size);
36 static FLAC__bool test_crc16_32bit_words(const FLAC__uint32 *words, size_t size);
37 static FLAC__bool test_crc16_64bit_words(const FLAC__uint64 *words, size_t size);
38
39 #define DATA_SIZE 32768
40
test_crc(void)41 FLAC__bool test_crc(void)
42 {
43 uint32_t i;
44 FLAC__byte data[DATA_SIZE] = { 0 };
45
46 /* Initialize data reproducibly with pseudo-random values. */
47 for (i = 1; i < DATA_SIZE; i++)
48 data[i] = crc8_update_ref(i % 256, data[i - 1]);
49
50 printf("\n+++ libFLAC unit test: crc\n\n");
51
52 if (! test_crc8(data, DATA_SIZE))
53 return false;
54
55 if (! test_crc16(data, DATA_SIZE))
56 return false;
57
58 if (! test_crc16_update(data, DATA_SIZE))
59 return false;
60
61 if (! test_crc16_32bit_words((FLAC__uint32 *)data, DATA_SIZE / 4))
62 return false;
63
64 if (! test_crc16_64bit_words((FLAC__uint64 *)data, DATA_SIZE / 8))
65 return false;
66
67 printf("\nPASSED!\n");
68 return true;
69 }
70
71 /*----------------------------------------------------------------------------*/
72
73 /* Reference implementations of CRC-8 and CRC-16 to check against. */
74
75 #define CRC8_POLYNOMIAL 0x07
76
crc8_update_ref(FLAC__byte byte,FLAC__uint8 crc)77 static FLAC__uint8 crc8_update_ref(FLAC__byte byte, FLAC__uint8 crc)
78 {
79 uint32_t i;
80
81 crc ^= byte;
82
83 for (i = 0; i < 8; i++) {
84 crc = (crc << 1) ^ ((crc >> 7) ? CRC8_POLYNOMIAL : 0);
85 }
86
87 return crc;
88 }
89
90 #define CRC16_POLYNOMIAL 0x8005
91
crc16_update_ref(FLAC__byte byte,FLAC__uint16 crc)92 static FLAC__uint16 crc16_update_ref(FLAC__byte byte, FLAC__uint16 crc)
93 {
94 uint32_t i;
95
96 crc ^= byte << 8;
97
98 for (i = 0; i < 8; i++) {
99 crc = (crc << 1) ^ ((crc >> 15) ? CRC16_POLYNOMIAL : 0);
100 }
101
102 return crc;
103 }
104
105 /*----------------------------------------------------------------------------*/
106
test_crc8(const FLAC__byte * data,size_t size)107 static FLAC__bool test_crc8(const FLAC__byte *data, size_t size)
108 {
109 uint32_t i;
110 FLAC__uint8 crc0,crc1;
111
112 printf("testing FLAC__crc8 ... ");
113
114 crc0 = 0;
115 crc1 = FLAC__crc8(data, 0);
116
117 if (crc1 != crc0) {
118 printf("FAILED, FLAC__crc8 returned non-zero CRC for zero bytes of data\n");
119 return false;
120 }
121
122 for (i = 0; i < size; i++) {
123 crc0 = crc8_update_ref(data[i], crc0);
124 crc1 = FLAC__crc8(data, i + 1);
125
126 if (crc1 != crc0) {
127 printf("FAILED, FLAC__crc8 result did not match reference CRC for %u bytes of test data\n", i + 1);
128 return false;
129 }
130 }
131
132 printf("OK\n");
133
134 return true;
135 }
136
test_crc16(const FLAC__byte * data,size_t size)137 static FLAC__bool test_crc16(const FLAC__byte *data, size_t size)
138 {
139 uint32_t i;
140 FLAC__uint16 crc0,crc1;
141
142 printf("testing FLAC__crc16 ... ");
143
144 crc0 = 0;
145 crc1 = FLAC__crc16(data, 0);
146
147 if (crc1 != crc0) {
148 printf("FAILED, FLAC__crc16 returned non-zero CRC for zero bytes of data\n");
149 return false;
150 }
151
152 for (i = 0; i < size; i++) {
153 crc0 = crc16_update_ref(data[i], crc0);
154 crc1 = FLAC__crc16(data, i + 1);
155
156 if (crc1 != crc0) {
157 printf("FAILED, FLAC__crc16 result did not match reference CRC for %u bytes of test data\n", i + 1);
158 return false;
159 }
160 }
161
162 printf("OK\n");
163
164 return true;
165 }
166
test_crc16_update(const FLAC__byte * data,size_t size)167 static FLAC__bool test_crc16_update(const FLAC__byte *data, size_t size)
168 {
169 uint32_t i;
170 FLAC__uint16 crc0,crc1;
171
172 printf("testing FLAC__CRC16_UPDATE macro ... ");
173
174 crc0 = 0;
175 crc1 = 0;
176
177 for (i = 0; i < size; i++) {
178 crc0 = crc16_update_ref(data[i], crc0);
179 crc1 = FLAC__CRC16_UPDATE(data[i], crc1);
180
181 if (crc1 != crc0) {
182 printf("FAILED, FLAC__CRC16_UPDATE result did not match reference CRC after %u bytes of test data\n", i + 1);
183 return false;
184 }
185 }
186
187 printf("OK\n");
188
189 return true;
190 }
191
test_crc16_32bit_words(const FLAC__uint32 * words,size_t size)192 static FLAC__bool test_crc16_32bit_words(const FLAC__uint32 *words, size_t size)
193 {
194 uint32_t n,i,k;
195 FLAC__uint16 crc0,crc1;
196
197 for (n = 1; n <= 16; n++) {
198 printf("testing FLAC__crc16_update_words32 (length=%i) ... ", n);
199
200 crc0 = 0;
201 crc1 = 0;
202
203 for (i = 0; i <= size - n; i += n) {
204 for (k = 0; k < n; k++) {
205 crc0 = crc16_update_ref( words[i + k] >> 24, crc0);
206 crc0 = crc16_update_ref((words[i + k] >> 16) & 0xFF, crc0);
207 crc0 = crc16_update_ref((words[i + k] >> 8) & 0xFF, crc0);
208 crc0 = crc16_update_ref( words[i + k] & 0xFF, crc0);
209 }
210
211 crc1 = FLAC__crc16_update_words32(words + i, n, crc1);
212
213 if (crc1 != crc0) {
214 printf("FAILED, FLAC__crc16_update_words32 result did not match reference CRC after %u words of test data\n", i + n);
215 return false;
216 }
217 }
218
219 crc1 = FLAC__crc16_update_words32(words, 0, crc1);
220
221 if (crc1 != crc0) {
222 printf("FAILED, FLAC__crc16_update_words32 called with zero bytes changed CRC value\n");
223 return false;
224 }
225
226 printf("OK\n");
227 }
228
229 return true;
230 }
231
test_crc16_64bit_words(const FLAC__uint64 * words,size_t size)232 static FLAC__bool test_crc16_64bit_words(const FLAC__uint64 *words, size_t size)
233 {
234 uint32_t n,i,k;
235 FLAC__uint16 crc0,crc1;
236
237 for (n = 1; n <= 16; n++) {
238 printf("testing FLAC__crc16_update_words64 (length=%i) ... ", n);
239
240 crc0 = 0;
241 crc1 = 0;
242
243 for (i = 0; i <= size - n; i += n) {
244 for (k = 0; k < n; k++) {
245 crc0 = crc16_update_ref( words[i + k] >> 56, crc0);
246 crc0 = crc16_update_ref((words[i + k] >> 48) & 0xFF, crc0);
247 crc0 = crc16_update_ref((words[i + k] >> 40) & 0xFF, crc0);
248 crc0 = crc16_update_ref((words[i + k] >> 32) & 0xFF, crc0);
249 crc0 = crc16_update_ref((words[i + k] >> 24) & 0xFF, crc0);
250 crc0 = crc16_update_ref((words[i + k] >> 16) & 0xFF, crc0);
251 crc0 = crc16_update_ref((words[i + k] >> 8) & 0xFF, crc0);
252 crc0 = crc16_update_ref( words[i + k] & 0xFF, crc0);
253 }
254
255 crc1 = FLAC__crc16_update_words64(words + i, n, crc1);
256
257 if (crc1 != crc0) {
258 printf("FAILED, FLAC__crc16_update_words64 result did not match reference CRC after %u words of test data\n", i + n);
259 return false;
260 }
261 }
262
263 crc1 = FLAC__crc16_update_words64(words, 0, crc1);
264
265 if (crc1 != crc0) {
266 printf("FAILED, FLAC__crc16_update_words64 called with zero bytes changed CRC value\n");
267 return false;
268 }
269
270 printf("OK\n");
271 }
272
273 return true;
274 }
275