@@@ fltfmt mess
[mLib] / hash / t / hash-test.c
CommitLineData
b64eb60f
MW
1/* -*-c-*-
2 *
3 * Test driver for universal hashing
4 *
5 * (c) 2009 Straylight/Edgeware
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the mLib utilities library.
11 *
12 * mLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * mLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28/*----- Header files ------------------------------------------------------*/
29
b1a20bee
MW
30#include "tvec.h"
31#include "tvec-bench.h"
32#include "tvec-types.h"
33
b64eb60f 34#include "crc32.h"
b1a20bee 35#include "siphash.h"
b64eb60f 36#include "unihash.h"
b64eb60f 37
b1a20bee 38/*----- Register allocation -----------------------------------------------*/
b64eb60f
MW
39
40enum {
41 RH, NROUT,
42 RK = NROUT, RM, NREG
43};
44
b1a20bee
MW
45/*----- Testing utilities -------------------------------------------------*/
46
b64eb60f
MW
47struct step { size_t s; };
48
b1a20bee
MW
49static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
50{
51 static const size_t steps[] = { 1, 5, 6, 7, 8, 23 };
52 struct step step;
53 size_t i;
54
55 fn(tv->in, tv->out, 0);
56 tvec_check(tv, "whole buffer");
57
58 for (i = 0; i < N(steps); i++) {
59 step.s = steps[i];
60 fn(tv->in, tv->out, &step);
61 tvec_check(tv, "step = %lu", (unsigned long)steps[i]);
62 }
63}
64
65static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 };
66
67static void before_hash(struct tvec_state *tv, void *ctx)
68 { tvec_allocbuffer(&tv->in[RM].v); }
69
70/*----- CRC32 -------------------------------------------------------------*/
71
72static const struct tvec_regdef bench_regs[] = {
73 { "msz", &tvty_buffer, RM, TVRF_ID },
74 TVEC_ENDREGS
75};
76
77static const struct tvec_regdef crc32_regs[] = {
78 { "m", &tvty_bytes, RM, 0 },
79 { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
80 TVEC_ENDREGS
81};
82
b64eb60f
MW
83static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out,
84 void *ctx)
85{
86 const struct step *step = ctx;
87 const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
88 uint32 h;
89
90 if (!step)
91 out[RH].v.u = crc32(0, p, sz);
92 else {
93 for (h = 0; sz > step->s; p += step->s, sz -= step->s)
94 h = crc32(h, p, step->s);
95 out[RH].v.u = crc32(h, p, sz);
96 }
97}
98
b1a20bee
MW
99static const struct tvec_test crc32_test =
100 { "crc32", crc32_regs, &step_testenv, test_crc32 };
adec5584 101
b64eb60f
MW
102static void bench_crc32(const struct tvec_reg *in, struct tvec_reg *out,
103 void *ctx)
104 { crc32(0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
b1a20bee 105
adec5584
MW
106static const struct tvec_env crc32_benchenv =
107 { 0, 0, 0, before_hash };
b1a20bee
MW
108static const struct tvec_benchenv crc32_bench =
109 { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv };
110static const struct tvec_test crc32_benchtest =
111 { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 };
b64eb60f 112
b1a20bee
MW
113/*----- SipHash -----------------------------------------------------------*/
114
115static const struct tvec_urange
116 siphash_keyrange = { SIPHASH_KEYSZ, SIPHASH_KEYSZ },
117 siphash_hashrange = { 8, 8 };
118
119static const struct tvec_regdef siphash_regs[] = {
120 { "k", &tvty_bytes, RK, 0, { &siphash_keyrange } },
121 { "m", &tvty_bytes, RM, 0 },
122 { "h", &tvty_bytes, RH, 0, { &siphash_hashrange } },
123 TVEC_ENDREGS
124};
125
126static void test_siphash(const struct tvec_reg *in, struct tvec_reg *out,
b64eb60f
MW
127 void *ctx)
128{
129 const struct step *step = ctx;
b64eb60f 130 const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
b1a20bee
MW
131 struct siphash_key k;
132 struct siphash s;
133 kludge64 h;
b64eb60f 134
b1a20bee 135 siphash_setkey(&k, in[RK].v.bytes.p);
b64eb60f 136 if (!step)
b1a20bee 137 h = siphash(&k, p, sz);
b64eb60f 138 else {
b1a20bee
MW
139 siphash_init(&s, &k);
140 for (; sz > step->s; p += step->s, sz -= step->s)
141 siphash_hash(&s, p, step->s);
142 siphash_hash(&s, p, sz);
143 h = siphash_done(&s);
b64eb60f 144 }
b1a20bee 145 tvec_allocbytes(&out[RH].v, 8); STORE64_L_(out[RH].v.bytes.p, h);
b64eb60f
MW
146}
147
b1a20bee
MW
148static const struct tvec_test siphash_test =
149 { "siphash", siphash_regs, &step_testenv, test_siphash };
b64eb60f 150
b1a20bee
MW
151static void setup_siphash(struct tvec_state *tv,
152 const struct tvec_env *env, void *pctx, void *ctx)
b64eb60f 153{
b1a20bee
MW
154 struct siphash_key *k = ctx;
155 ASSIGN64(k->k0, 0); ASSIGN64(k->k1, 0);
156}
b64eb60f 157
b1a20bee
MW
158static void bench_siphash(const struct tvec_reg *in, struct tvec_reg *out,
159 void *ctx)
160 { siphash(ctx, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
b64eb60f 161
b1a20bee
MW
162static const struct tvec_env siphash_benchenv =
163 { sizeof(struct siphash_key), setup_siphash, 0, before_hash };
164static const struct tvec_benchenv siphash_bench =
165 { TVEC_BENCHINIT, 1, -1, RM, &siphash_benchenv };
166static const struct tvec_test siphash_benchtest =
167 { "siphash-bench", bench_regs, &siphash_bench._env, bench_siphash };
b64eb60f 168
b1a20bee 169/*----- Unihash -----------------------------------------------------------*/
e63124bc 170
b64eb60f 171static const struct tvec_regdef unihash_regs[] = {
d056fbdf
MW
172 { "k", &tvty_uint, RK, 0, { &tvrange_u32 } },
173 { "m", &tvty_bytes, RM, 0 },
174 { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
db2bf411 175 TVEC_ENDREGS
b64eb60f
MW
176};
177
b1a20bee
MW
178static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out,
179 void *ctx)
180{
181 const struct step *step = ctx;
182 unihash_info ui;
183 const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
184 uint32 h;
b64eb60f 185
b1a20bee
MW
186 unihash_setkey(&ui, in[RK].v.u);
187 if (!step)
188 out[RH].v.u = unihash(&ui, p, sz);
189 else {
190 for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s)
191 h = unihash_hash(&ui, h, p, step->s);
192 out[RH].v.u = unihash_hash(&ui, h, p, sz);
193 }
194}
b64eb60f 195
b1a20bee
MW
196static const struct tvec_test unihash_test =
197 { "unihash", unihash_regs, &step_testenv, test_unihash };
198
199static void setup_unihash(struct tvec_state *tv,
200 const struct tvec_env *env, void *pctx, void *ctx)
201 { unihash_setkey(ctx, 0); }
202
203static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out,
204 void *ctx)
205 { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
206
207static const struct tvec_env unihash_benchenv =
208 { sizeof(unihash_info), setup_unihash, 0, before_hash };
c91413e6 209static const struct tvec_benchenv unihash_bench =
e63124bc 210 { TVEC_BENCHINIT, 1, -1, RM, &unihash_benchenv };
b1a20bee
MW
211static const struct tvec_test unihash_benchtest =
212 { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash };
213
214/*----- Main program ------------------------------------------------------*/
b64eb60f 215
b1a20bee
MW
216static const struct tvec_test *const tests[] = {
217 &crc32_test, &crc32_benchtest,
218 &siphash_test, &siphash_benchtest,
219 &unihash_test, &unihash_benchtest,
220 0
b64eb60f
MW
221};
222
c5e0e403 223static const struct tvec_config testconfig =
b64eb60f
MW
224 { tests, NROUT, NREG, sizeof(struct tvec_reg) };
225
226int main(int argc, char *argv[])
c5e0e403 227 { return (tvec_main(argc, argv, &testconfig, 0)); }
b64eb60f
MW
228
229/*----- That's all, folks -------------------------------------------------*/