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