3 * Test driver for universal hashing
5 * (c) 2009 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the mLib utilities library.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
31 #include "tvec-bench.h"
32 #include "tvec-types.h"
38 /*----- Register allocation -----------------------------------------------*/
45 /*----- Testing utilities -------------------------------------------------*/
47 struct step { size_t s; };
49 static void run_step(struct tvec_state *tv, tvec_testfn *fn, void *ctx)
51 static const size_t steps[] = { 1, 5, 6, 7, 8, 23 };
55 fn(tv->in, tv->out, 0);
56 tvec_check(tv, "whole buffer");
58 for (i = 0; i < N(steps); i++) {
60 fn(tv->in, tv->out, &step);
61 tvec_check(tv, "step = %lu", (unsigned long)steps[i]);
65 static const struct tvec_env step_testenv = { 0, 0, 0, 0, run_step, 0, 0 };
67 static void before_hash(struct tvec_state *tv, void *ctx)
68 { tvec_allocbuffer(&tv->in[RM].v); }
70 /*----- CRC32 -------------------------------------------------------------*/
72 static const struct tvec_regdef bench_regs[] = {
73 { "msz", &tvty_buffer, RM, TVRF_ID },
77 static const struct tvec_regdef crc32_regs[] = {
78 { "m", &tvty_bytes, RM, 0 },
79 { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
83 static void test_crc32(const struct tvec_reg *in, struct tvec_reg *out,
86 const struct step *step = ctx;
87 const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
91 out[RH].v.u = crc32(0, p, sz);
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);
99 static const struct tvec_test crc32_test =
100 { "crc32", crc32_regs, &step_testenv, test_crc32 };
102 static void bench_crc32(const struct tvec_reg *in, struct tvec_reg *out,
104 { crc32(0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
106 static const struct tvec_env crc32_benchenv =
107 { 0, 0, 0, before_hash };
108 static const struct tvec_benchenv crc32_bench =
109 { TVEC_BENCHINIT, 1, -1, RM, &crc32_benchenv };
110 static const struct tvec_test crc32_benchtest =
111 { "crc32-bench", bench_regs, &crc32_bench._env, bench_crc32 };
113 /*----- SipHash -----------------------------------------------------------*/
115 static const struct tvec_urange
116 siphash_keyrange = { SIPHASH_KEYSZ, SIPHASH_KEYSZ },
117 siphash_hashrange = { 8, 8 };
119 static 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 } },
126 #define TEST_SIPHASH(nr0, nr1) \
128 static void test_siphash##nr0##nr1(const struct tvec_reg *in, \
129 struct tvec_reg *out, \
132 const struct step *step = ctx; \
133 const unsigned char *p = in[RM].v.bytes.p; \
134 size_t sz = in[RM].v.bytes.sz; \
135 struct siphash_key k; \
136 struct siphash##nr0##nr1 s; \
139 siphash_setkey(&k, in[RK].v.bytes.p); \
141 h = siphash##nr0##nr1(&k, p, sz); \
143 siphash##nr0##nr1##_init(&s, &k); \
144 for (; sz > step->s; p += step->s, sz -= step->s) \
145 siphash##nr0##nr1##_hash(&s, p, step->s); \
146 siphash##nr0##nr1##_hash(&s, p, sz); \
147 h = siphash##nr0##nr1##_done(&s); \
149 tvec_allocbytes(&out[RH].v, 8); STORE64_L_(out[RH].v.bytes.p, h); \
152 static const struct tvec_test siphash##nr0##nr1##_test = \
153 { "siphash" #nr0 #nr1, siphash_regs, \
154 &step_testenv, test_siphash##nr0##nr1 };
156 SIPHASH_VARIANTS(TEST_SIPHASH)
158 #define SIPHASH_TEST(nr0, nr1) &siphash##nr0##nr1##_test,
160 static void setup_siphash(struct tvec_state *tv,
161 const struct tvec_env *env, void *pctx, void *ctx)
163 struct siphash_key *k = ctx;
164 ASSIGN64(k->k0, 0); ASSIGN64(k->k1, 0);
167 static const struct tvec_env siphash_benchenv =
168 { sizeof(struct siphash_key), setup_siphash, 0, before_hash };
169 static const struct tvec_benchenv siphash_bench =
170 { TVEC_BENCHINIT, 1, -1, RM, &siphash_benchenv };
172 #define BENCH_SIPHASH(nr0, nr1) \
174 static void bench_siphash##nr0##nr1(const struct tvec_reg *in, \
175 struct tvec_reg *out, \
177 { siphash##nr0##nr1(ctx, in[RM].v.bytes.p, in[RM].v.bytes.sz); } \
179 static const struct tvec_test siphash##nr0##nr1##_benchtest = \
180 { "siphash" #nr0 #nr1 "-bench", bench_regs, \
181 &siphash_bench._env, bench_siphash##nr0##nr1 };
183 SIPHASH_VARIANTS(BENCH_SIPHASH)
185 #define SIPHASH_BENCH(nr0, nr1) &siphash##nr0##nr1##_benchtest,
187 /*----- Unihash -----------------------------------------------------------*/
189 static const struct tvec_regdef unihash_regs[] = {
190 { "k", &tvty_uint, RK, 0, { &tvrange_u32 } },
191 { "m", &tvty_bytes, RM, 0 },
192 { "h", &tvty_uint, RH, 0, { &tvrange_u32 } },
196 static void test_unihash(const struct tvec_reg *in, struct tvec_reg *out,
199 const struct step *step = ctx;
201 const unsigned char *p = in[RM].v.bytes.p; size_t sz = in[RM].v.bytes.sz;
204 unihash_setkey(&ui, in[RK].v.u);
206 out[RH].v.u = unihash(&ui, p, sz);
208 for (h = UNIHASH_INIT(&ui); sz > step->s; p += step->s, sz -= step->s)
209 h = unihash_hash(&ui, h, p, step->s);
210 out[RH].v.u = unihash_hash(&ui, h, p, sz);
214 static const struct tvec_test unihash_test =
215 { "unihash", unihash_regs, &step_testenv, test_unihash };
217 static void setup_unihash(struct tvec_state *tv,
218 const struct tvec_env *env, void *pctx, void *ctx)
219 { unihash_setkey(ctx, 0); }
221 static void bench_unihash(const struct tvec_reg *in, struct tvec_reg *out,
223 { unihash_hash(ctx, 0, in[RM].v.bytes.p, in[RM].v.bytes.sz); }
225 static const struct tvec_env unihash_benchenv =
226 { sizeof(unihash_info), setup_unihash, 0, before_hash };
227 static const struct tvec_benchenv unihash_bench =
228 { TVEC_BENCHINIT, 1, -1, RM, &unihash_benchenv };
229 static const struct tvec_test unihash_benchtest =
230 { "unihash-bench", bench_regs, &unihash_bench._env, bench_unihash };
232 /*----- Main program ------------------------------------------------------*/
234 static const struct tvec_test *const tests[] = {
235 &crc32_test, &crc32_benchtest,
236 SIPHASH_VARIANTS(SIPHASH_TEST) SIPHASH_VARIANTS(SIPHASH_BENCH)
237 &unihash_test, &unihash_benchtest,
241 static const struct tvec_config testconfig =
242 { tests, NROUT, NREG, sizeof(struct tvec_reg) };
244 int main(int argc, char *argv[])
245 { return (tvec_main(argc, argv, &testconfig, 0)); }
247 /*----- That's all, folks -------------------------------------------------*/