mirror of
https://github.com/cryb-to/cryb-to.git
synced 2024-11-22 05:35:46 +00:00
Rewrite unit tests for the Fletcher and Adler checksums to exercise
boundary conditions (low and high word overflow).
This commit is contained in:
parent
8351719b84
commit
0961e4b2e0
2 changed files with 257 additions and 111 deletions
113
t/t_adler.c
113
t/t_adler.c
|
@ -30,97 +30,95 @@
|
|||
#include "cryb/impl.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cryb/endian.h>
|
||||
#include <cryb/hash.h>
|
||||
|
||||
#include "t.h"
|
||||
|
||||
#define ADLER32_INVALID 0xffffffffLU
|
||||
|
||||
#define TRI(n) (n * (n + 1) / 2)
|
||||
|
||||
static uint8_t ones8[65536];
|
||||
|
||||
struct t_case {
|
||||
const char *desc;
|
||||
const char *data;
|
||||
const void *data;
|
||||
size_t len;
|
||||
uint32_t sum;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Test cases
|
||||
*
|
||||
* Most of these test cases use input sequences where each word has the
|
||||
* value 1. To understand the test cases, it helps to realize that (until
|
||||
* it overflows) the low word of the Adler checksum of such a sequence of
|
||||
* length n is equal to n + 1, while the high word is equal to the nth
|
||||
* triangular number plus n, i.e. (n*(n+1))/2+n. Also, unlike Fletcher32,
|
||||
* the input width for Adler32 is always 8 bits.
|
||||
*/
|
||||
#define TRIpN(n) ((n * (n + 1) / 2) + n)
|
||||
static struct t_case t_cases[] = {
|
||||
/* trivial cases */
|
||||
{
|
||||
.desc = "len == 0",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "all-zeroes message",
|
||||
.data = t_zero,
|
||||
.len = sizeof t_zero,
|
||||
.sum = sizeof t_zero << 16 | 0x0001U,
|
||||
},
|
||||
{
|
||||
.desc = "length 0",
|
||||
.data = ones8,
|
||||
.len = 0,
|
||||
.sum = 0x00000001,
|
||||
},
|
||||
|
||||
/* overflow */
|
||||
{
|
||||
.desc = "len == 1",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 1,
|
||||
.sum = 0x00020002,
|
||||
.desc = "high overflow - 1",
|
||||
.data = ones8,
|
||||
.len = 359,
|
||||
.sum = (TRIpN(359U) % 65521U) << 16 | 360U,
|
||||
},
|
||||
{
|
||||
.desc = "len == 2",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 2,
|
||||
.sum = 0x00060004,
|
||||
.desc = "high overflow",
|
||||
.data = ones8,
|
||||
.len = 363,
|
||||
.sum = (TRIpN(363U) % 65521U) << 16 | 364U,
|
||||
},
|
||||
{
|
||||
.desc = "len == 3",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 3,
|
||||
.sum = 0x000d0007,
|
||||
.desc = "low overflow - 1",
|
||||
.data = ones8,
|
||||
.len = 65519,
|
||||
.sum = (TRIpN(65519U) % 65521U) << 16 | 65520U,
|
||||
},
|
||||
{
|
||||
.desc = "len == 4",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 4,
|
||||
.sum = 0x0018000b,
|
||||
.desc = "low overflow",
|
||||
.data = ones8,
|
||||
.len = 65520,
|
||||
.sum = (TRIpN(65520U) % 65521U) << 16 | 0U,
|
||||
},
|
||||
{
|
||||
.desc = "len == 5",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 5,
|
||||
.sum = 0x00280010,
|
||||
.desc = "low overflow + 1",
|
||||
.data = ones8,
|
||||
.len = 65521,
|
||||
.sum = ((TRIpN(65520U) + 1) % 65521U) << 16 | 1U,
|
||||
},
|
||||
{
|
||||
.desc = "len == 6",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 6,
|
||||
.sum = 0x003e0016,
|
||||
},
|
||||
{
|
||||
.desc = "len == 7",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 7,
|
||||
.sum = 0x005b001d,
|
||||
},
|
||||
{
|
||||
.desc = "len == 8",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 8,
|
||||
.sum = 0x00800025,
|
||||
},
|
||||
{
|
||||
.desc = "zeroes",
|
||||
.data = (const char *)t_zero,
|
||||
.len = sizeof t_zero,
|
||||
.sum = (sizeof t_zero << 16) | 1,
|
||||
},
|
||||
/* XXX need non-zero cases which exercise modulo */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Test function
|
||||
*/
|
||||
static int
|
||||
t_adler(char **desc CRYB_UNUSED, void *arg)
|
||||
t_adler32(char **desc CRYB_UNUSED, void *arg)
|
||||
{
|
||||
struct t_case *t = arg;
|
||||
int ret;
|
||||
|
||||
ret = t_compare_x32(t->sum, adler32_hash(t->data, t->len));
|
||||
return (ret);
|
||||
return (t_compare_x32(t->sum, adler32_hash(t->data, t->len)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,13 +129,20 @@ t_adler(char **desc CRYB_UNUSED, void *arg)
|
|||
int
|
||||
t_prepare(int argc, char *argv[])
|
||||
{
|
||||
int i, n;
|
||||
unsigned int i, n;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
ones8[0] = 1;
|
||||
be16enc(&ones16[0], 1);
|
||||
for (i = 1; i < 65536; ++i) {
|
||||
ones8[i] = ones8[0];
|
||||
ones16[i] = ones16[0];
|
||||
}
|
||||
n = sizeof t_cases / sizeof t_cases[0];
|
||||
for (i = 0; i < n; ++i)
|
||||
t_add_test(t_adler, &t_cases[i], t_cases[i].desc);
|
||||
if (t_cases[i].sum != 0xffffffffLU)
|
||||
t_add_test(t_adler32, &t_cases[i], t_cases[i].desc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
255
t/t_fletcher.c
255
t/t_fletcher.c
|
@ -30,15 +30,25 @@
|
|||
#include "cryb/impl.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cryb/endian.h>
|
||||
#include <cryb/hash.h>
|
||||
|
||||
#include "t.h"
|
||||
|
||||
#define FLETCHER16_INVALID 0xffffU
|
||||
#define FLETCHER32_INVALID 0xffffffffLU
|
||||
#define FLETCHER64_INVALID 0xffffffffffffffffLLU
|
||||
|
||||
static uint8_t ones8[65536];
|
||||
static uint16_t ones16[65536];
|
||||
static uint32_t ones32[65536];
|
||||
|
||||
struct t_case {
|
||||
const char *desc;
|
||||
const char *data;
|
||||
const void *data;
|
||||
size_t len;
|
||||
uint16_t sum16;
|
||||
uint32_t sum32;
|
||||
|
@ -47,105 +57,221 @@ struct t_case {
|
|||
|
||||
/***************************************************************************
|
||||
* Test cases
|
||||
*
|
||||
* Most of these test cases use input sequences where each word has the
|
||||
* value 1. To understand the test cases, it helps to realize that (until
|
||||
* it overflows) the low word of the Fletcher checksum of such a sequence
|
||||
* of length n is equal to n, while the high word is equal to the nth
|
||||
* triangular number, i.e. (n*(n+1))/2+n. Also, remember that the input
|
||||
* width for Fletcher is half the checksum width.
|
||||
*/
|
||||
#define TRI(n) (n * (n + 1) / 2)
|
||||
static struct t_case t_cases[] = {
|
||||
/* trivial cases */
|
||||
{
|
||||
.desc = "len == 0",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.len = 0,
|
||||
.desc = "all-zeroes message",
|
||||
.data = t_zero,
|
||||
.len = sizeof t_zero,
|
||||
.sum16 = 0x00,
|
||||
.sum32 = 0x0000,
|
||||
.sum64 = 0x00000000,
|
||||
},
|
||||
{
|
||||
.desc = "len == 1",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 0",
|
||||
.data = ones8,
|
||||
.len = 0,
|
||||
.sum16 = 0x00,
|
||||
.sum32 = 0x0000,
|
||||
.sum64 = 0x00000000,
|
||||
},
|
||||
|
||||
/* padding */
|
||||
{
|
||||
.desc = "length 1",
|
||||
.data = ones8,
|
||||
.len = 1,
|
||||
.sum16 = 0x0101,
|
||||
.sum32 = 0x01000100,
|
||||
.sum64 = 0x0100000001000000,
|
||||
},
|
||||
{
|
||||
.desc = "len == 2",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 2",
|
||||
.data = ones8,
|
||||
.len = 2,
|
||||
.sum16 = 0x0403,
|
||||
.sum32 = 0x01020102,
|
||||
.sum64 = 0x0102000001020000,
|
||||
.sum16 = 0x0302,
|
||||
.sum32 = 0x01010101,
|
||||
.sum64 = 0x0101000001010000,
|
||||
},
|
||||
{
|
||||
.desc = "len == 3",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 3",
|
||||
.data = ones8,
|
||||
.len = 3,
|
||||
.sum16 = 0x0a06,
|
||||
.sum32 = 0x05040402,
|
||||
.sum64 = 0x102030001020300,
|
||||
.sum16 = 0x0603,
|
||||
.sum32 = 0x03020201,
|
||||
.sum64 = 0x0101010001010100,
|
||||
},
|
||||
{
|
||||
.desc = "len == 4",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 4",
|
||||
.data = ones8,
|
||||
.len = 4,
|
||||
.sum16 = 0x140a,
|
||||
.sum32 = 0x05080406,
|
||||
.sum64 = 0x0102030401020304,
|
||||
.sum16 = 0x0a04,
|
||||
.sum32 = 0x03030202,
|
||||
.sum64 = 0x0101010101010101,
|
||||
},
|
||||
{
|
||||
.desc = "len == 5",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 5",
|
||||
.data = ones8,
|
||||
.len = 5,
|
||||
.sum16 = 0x230f,
|
||||
.sum32 = 0x0e0e0906,
|
||||
.sum64 = 0x0704060806020304,
|
||||
.sum16 = 0x0f05,
|
||||
.sum32 = 0x06050302,
|
||||
.sum64 = 0x0302020202010101,
|
||||
},
|
||||
{
|
||||
.desc = "len == 6",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 6",
|
||||
.data = ones8,
|
||||
.len = 6,
|
||||
.sum16 = 0x3815,
|
||||
.sum32 = 0x0e14090c,
|
||||
.sum64 = 0x070a060806080304,
|
||||
.sum16 = 0x1506,
|
||||
.sum32 = 0x06060303,
|
||||
.sum64 = 0x0303020202020101,
|
||||
},
|
||||
{
|
||||
.desc = "len == 7",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 7",
|
||||
.data = ones8,
|
||||
.len = 7,
|
||||
.sum16 = 0x541c,
|
||||
.sum32 = 0x1e20100c,
|
||||
.sum64 = 0x070a0d0806080a04,
|
||||
.sum16 = 0x1c07,
|
||||
.sum32 = 0x0a090403,
|
||||
.sum64 = 0x0303030202020201,
|
||||
},
|
||||
{
|
||||
.desc = "len == 8",
|
||||
.data = "\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
.desc = "length 8",
|
||||
.data = ones8,
|
||||
.len = 8,
|
||||
.sum16 = 0x7824,
|
||||
.sum32 = 0x1e281014,
|
||||
.sum64 = 0x070a0d1006080a0c,
|
||||
.sum16 = 0x2408,
|
||||
.sum32 = 0x0a0a0404,
|
||||
.sum64 = 0x0303030302020202,
|
||||
},
|
||||
/* not really useful... */
|
||||
|
||||
/* overflow (16-bit checksum) */
|
||||
{
|
||||
.desc = "zeroes",
|
||||
.data = (const char *)t_zero,
|
||||
.len = sizeof t_zero,
|
||||
.sum16 = 0x00,
|
||||
.sum32 = 0x0000,
|
||||
.sum64 = 0x00000000,
|
||||
.desc = "high overflow - 1",
|
||||
.data = ones8,
|
||||
.len = 22,
|
||||
.sum16 = (TRI(22) % 255) << 8 | 22,
|
||||
.sum32 = FLETCHER32_INVALID,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
/* XXX need non-zero cases which exercise modulo */
|
||||
{
|
||||
.desc = "high overflow",
|
||||
.data = ones8,
|
||||
.len = 23,
|
||||
.sum16 = (TRI(23) % 255) << 8 | 23,
|
||||
.sum32 = FLETCHER32_INVALID,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow - 1",
|
||||
.data = ones8,
|
||||
.len = 254,
|
||||
.sum16 = (TRI(254) % 255) << 8 | 254,
|
||||
.sum32 = FLETCHER32_INVALID,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow",
|
||||
.data = ones8,
|
||||
.len = 255,
|
||||
.sum16 = (TRI(254) % 255) << 8 | 0,
|
||||
.sum32 = FLETCHER32_INVALID,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow + 1",
|
||||
.data = ones8,
|
||||
.len = 256,
|
||||
.sum16 = ((TRI(254) + 1) % 255) << 8 | 1,
|
||||
.sum32 = FLETCHER32_INVALID,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
|
||||
/* overflow (32-bit checksum) */
|
||||
{
|
||||
.desc = "high overflow - 1",
|
||||
.data = ones16,
|
||||
.len = 362 * sizeof ones16[0],
|
||||
.sum16 = FLETCHER16_INVALID,
|
||||
.sum32 = (TRI(362U) % 65535U) << 16 | 362U,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "high overflow",
|
||||
.data = ones16,
|
||||
.len = 363 * sizeof ones16[0],
|
||||
.sum16 = FLETCHER16_INVALID,
|
||||
.sum32 = (TRI(363U) % 65535U) << 16 | 363U,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow - 1",
|
||||
.data = ones16,
|
||||
.len = 65534 * sizeof ones16[0],
|
||||
.sum16 = FLETCHER16_INVALID,
|
||||
.sum32 = (TRI(65534U) % 65535U) << 16 | 65534U,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow",
|
||||
.data = ones16,
|
||||
.len = 65535 * sizeof ones16[0],
|
||||
.sum16 = FLETCHER16_INVALID,
|
||||
.sum32 = (TRI(65534U) % 65535U) << 16 | 0U,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
{
|
||||
.desc = "low overflow + 1",
|
||||
.data = ones16,
|
||||
.len = 65536 * sizeof ones16[0],
|
||||
.sum16 = FLETCHER16_INVALID,
|
||||
.sum32 = ((TRI(65534U) + 1) % 65535U) << 16 | 1U,
|
||||
.sum64 = FLETCHER64_INVALID,
|
||||
},
|
||||
|
||||
/* overflow (64-bit checksum */
|
||||
/*
|
||||
* This is currently not realistic. We need to change the
|
||||
* fletcher*() API to take a seed so it can do partial /
|
||||
* incremental checksums, and provide a precomputed seed just
|
||||
* below the overflow point.
|
||||
*/
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Test function
|
||||
*/
|
||||
static int
|
||||
t_fletcher(char **desc CRYB_UNUSED, void *arg)
|
||||
t_fletcher16(char **desc, void *arg)
|
||||
{
|
||||
struct t_case *t = arg;
|
||||
int ret;
|
||||
|
||||
ret = t_compare_x16(t->sum16, fletcher16_hash(t->data, t->len)) &
|
||||
t_compare_x32(t->sum32, fletcher32_hash(t->data, t->len)) &
|
||||
t_compare_x64(t->sum64, fletcher64_hash(t->data, t->len));
|
||||
return (ret);
|
||||
asprintf(desc, "(16-bit) %s", t->desc);
|
||||
return (t_compare_x16(t->sum16, fletcher16_hash(t->data, t->len)));
|
||||
}
|
||||
|
||||
static int
|
||||
t_fletcher32(char **desc, void *arg)
|
||||
{
|
||||
struct t_case *t = arg;
|
||||
|
||||
asprintf(desc, "(32-bit) %s", t->desc);
|
||||
return (t_compare_x32(t->sum32, fletcher32_hash(t->data, t->len)));
|
||||
}
|
||||
|
||||
static int
|
||||
t_fletcher64(char **desc, void *arg)
|
||||
{
|
||||
struct t_case *t = arg;
|
||||
|
||||
asprintf(desc, "(64-bit) %s", t->desc);
|
||||
return (t_compare_x64(t->sum64, fletcher64_hash(t->data, t->len)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -156,13 +282,28 @@ t_fletcher(char **desc CRYB_UNUSED, void *arg)
|
|||
int
|
||||
t_prepare(int argc, char *argv[])
|
||||
{
|
||||
int i, n;
|
||||
unsigned int i, n;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
ones8[0] = 1;
|
||||
be16enc(&ones16[0], 1);
|
||||
be32enc(&ones32[0], 1);
|
||||
for (i = 1; i < 65536; ++i) {
|
||||
ones8[i] = ones8[0];
|
||||
ones16[i] = ones16[0];
|
||||
ones32[i] = ones32[0];
|
||||
}
|
||||
n = sizeof t_cases / sizeof t_cases[0];
|
||||
for (i = 0; i < n; ++i)
|
||||
t_add_test(t_fletcher, &t_cases[i], t_cases[i].desc);
|
||||
if (t_cases[i].sum16 != 0xffffU)
|
||||
t_add_test(t_fletcher16, &t_cases[i], t_cases[i].desc);
|
||||
for (i = 0; i < n; ++i)
|
||||
if (t_cases[i].sum32 != 0xffffffffLU)
|
||||
t_add_test(t_fletcher32, &t_cases[i], t_cases[i].desc);
|
||||
for (i = 0; i < n; ++i)
|
||||
if (t_cases[i].sum64 != 0xffffffffffffffffLLU)
|
||||
t_add_test(t_fletcher64, &t_cases[i], t_cases[i].desc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue