progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / math / group-test.c
1 /* -*-c-*-
2 *
3 * Testing group operations
4 *
5 * (c) 2004 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb 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 * Catacomb 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 Catacomb; 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
30 #include <stdarg.h>
31
32 #include <mLib/macros.h>
33 #include <mLib/testrig.h>
34
35 #include "group.h"
36 #include "fibrand.h"
37 #include "ec.h"
38 #include "ec-test.h"
39
40 /*----- Main code ---------------------------------------------------------*/
41
42 static group *getgroup(const char *p) {
43 group *g; qd_parse qd;
44 qd.p = p; qd.e = 0; g = group_parse(&qd);
45 if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; }
46 if (!g) {
47 fprintf(stderr, "bad group string `%.*s|%s': %s\n",
48 (int)(qd.p - p), p, qd.p, qd.e);
49 exit(1);
50 }
51 return (g);
52 }
53
54 static ge *getge(group *g, const char *p) {
55 ge *x = G_CREATE(g);
56 if (group_readstring(g, x, p, 0)) {
57 fprintf(stderr, "bad group element `%s'\n", p);
58 exit(1);
59 }
60 return (x);
61 }
62
63 static void show(group *g, const char *p, ge *x) {
64 fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
65 putc('\n', stderr);
66 }
67
68 static void showec(const char *p, ec *q) {
69 fprintf(stderr, "*** %s = ", p);
70 if (EC_ATINF(q)) fprintf(stderr, "inf\n");
71 else {
72 mp_writefile(q->x, stderr, 16); fputs(", ", stderr);
73 mp_writefile(q->x, stderr, 16); putchar('\n');
74 }
75 }
76
77 static void showmp(const char *p, mp *x, int r) {
78 fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r);
79 putc('\n', stderr);
80 }
81
82 static int EXECL_LIKE(0)
83 check(const char *op, const char *gd, group *g, ge *r, ge *c, ...)
84 {
85 va_list ap;
86
87 if (G_EQ(g, r, c)) return (1);
88 fprintf(stderr, "\n*** %s failed\n", op);
89 fprintf(stderr, "*** group: %s\n", gd);
90 va_start(ap, c);
91 for (;;) {
92 const char *p; ge *x;
93 p = va_arg(ap, const char *); if (!p) break;
94 x = va_arg(ap, ge *); show(g, p, x);
95 }
96 show(g, "expected", r);
97 show(g, "computed", c);
98 return (0);
99 }
100
101 /*----- Actual tests ------------------------------------------------------*/
102
103 static int vcheck(dstr *v)
104 {
105 group *g = getgroup(v[0].buf);
106 grand *gr = fibrand_create(0);
107 const char *e = G_CHECK(g, gr);
108 int ok = 1;
109 gr->ops->destroy(gr);
110 if (!e) e = "ok";
111 G_DESTROYGROUP(g);
112 if (STRCMP(e, !=, v[1].buf)) {
113 ok = 0;
114 fprintf(stderr, "*** check failed\n");
115 fprintf(stderr, "*** group: %s\n", v[0].buf);
116 fprintf(stderr, "*** expected: %s\n", v[1].buf);
117 fprintf(stderr, "*** returned: %s\n", e);
118 }
119 assert(mparena_count(MPARENA_GLOBAL) == 0);
120 return (ok);
121 }
122
123 static int vcheckelt(dstr *v)
124 {
125 group *g = getgroup(v[0].buf);
126 ge *x = getge(g, v[1].buf);
127 int ir = *(int *)v[2].buf;
128 int ic = group_check(g, x);
129 int ok = 1;
130 if (ir != ic) {
131 ok = 0;
132 fprintf(stderr, "*** check failed\n");
133 fprintf(stderr, "*** group: %s\n", v[0].buf);
134 show(g, "x", x);
135 fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success");
136 }
137 G_DESTROY(g, x);
138 G_DESTROYGROUP(g);
139 assert(mparena_count(MPARENA_GLOBAL) == 0);
140 return (ok);
141 }
142
143 static int vmul(dstr *v)
144 {
145 group *g = getgroup(v[0].buf);
146 ge *x = getge(g, v[1].buf);
147 ge *y = getge(g, v[2].buf);
148 ge *r = getge(g, v[3].buf);
149 ge *c = G_CREATE(g);
150 int ok = 1;
151 G_MUL(g, c, x, y);
152 ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
153 G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
154 G_DESTROYGROUP(g);
155 assert(mparena_count(MPARENA_GLOBAL) == 0);
156 return (ok);
157 }
158
159 static int vsqr(dstr *v)
160 {
161 group *g = getgroup(v[0].buf);
162 ge *x = getge(g, v[1].buf);
163 ge *r = getge(g, v[2].buf);
164 ge *c = G_CREATE(g);
165 int ok = 1;
166 G_SQR(g, c, x);
167 ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0);
168 G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
169 G_DESTROYGROUP(g);
170 assert(mparena_count(MPARENA_GLOBAL) == 0);
171 return (ok);
172 }
173
174 static int vinv(dstr *v)
175 {
176 group *g = getgroup(v[0].buf);
177 ge *x = getge(g, v[1].buf);
178 ge *r = getge(g, v[2].buf);
179 ge *c = G_CREATE(g);
180 int ok = 1;
181 G_INV(g, c, x);
182 ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0);
183 G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
184 G_DESTROYGROUP(g);
185 assert(mparena_count(MPARENA_GLOBAL) == 0);
186 return (ok);
187 }
188
189 static int vdiv(dstr *v)
190 {
191 group *g = getgroup(v[0].buf);
192 ge *x = getge(g, v[1].buf);
193 ge *y = getge(g, v[2].buf);
194 ge *r = getge(g, v[3].buf);
195 ge *c = G_CREATE(g);
196 int ok = 1;
197 G_DIV(g, c, x, y);
198 ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
199 group_stddiv(g, c, x, y);
200 ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
201 G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
202 G_DESTROYGROUP(g);
203 assert(mparena_count(MPARENA_GLOBAL) == 0);
204 return (ok);
205 }
206
207 static int vexp(dstr *v)
208 {
209 group *g = getgroup(v[0].buf);
210 ge *x = getge(g, v[1].buf);
211 mp *n = *(mp **)v[2].buf;
212 ge *r = getge(g, v[3].buf);
213 ge *c = G_CREATE(g);
214 int ok = 1;
215 G_EXP(g, c, x, n);
216 if (!G_EQ(g, r, c)) {
217 ok = 0;
218 fprintf(stderr, "\n*** exp failed\n");
219 fprintf(stderr, "*** group: %s\n", v[0].buf);
220 show(g, "x", x); showmp("n", n, 10);
221 show(g, "expected", r); show(g, "computed", c);
222 }
223 group_stdexp(g, c, x, n);
224 if (!G_EQ(g, r, c)) {
225 ok = 0;
226 fprintf(stderr, "\n*** stdexp failed\n");
227 fprintf(stderr, "*** group: %s\n", v[0].buf);
228 show(g, "x", x); showmp("n", n, 10);
229 show(g, "expected", r); show(g, "computed", c);
230 }
231 G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c);
232 G_DESTROYGROUP(g);
233 assert(mparena_count(MPARENA_GLOBAL) == 0);
234 return (ok);
235 }
236
237 static int vmexp(size_t n, dstr *v)
238 {
239 group *g = getgroup(v[0].buf);
240 ge *c, *r;
241 group_expfactor *f = xmalloc(n * sizeof(group_expfactor));
242 int ok = 1;
243 size_t i;
244 for (i = 0; i < n; i++) {
245 f[i].base = getge(g, v[1 + 2 * i].buf);
246 f[i].exp = *(mp **)v[2 + 2 * i].buf;
247 }
248 r = getge(g, v[1 + 2 * n].buf);
249 c = G_CREATE(g);
250 G_MEXP(g, c, f, n);
251 if (!G_EQ(g, r, c)) {
252 ok = 0;
253 fprintf(stderr, "\n*** mexp failed\n");
254 fprintf(stderr, "*** group: %s\n", v[0].buf);
255 for (i = 0; i < n; i++) {
256 show(g, "base", f[i].base);
257 showmp("exp", f[i].exp, 10);
258 }
259 show(g, "expected", r); show(g, "computed", c);
260 }
261 group_stdmexp(g, c, f, n);
262 if (!G_EQ(g, r, c)) {
263 ok = 0;
264 fprintf(stderr, "\n*** stdmexp failed\n");
265 fprintf(stderr, "*** group: %s\n", v[0].buf);
266 for (i = 0; i < n; i++) {
267 show(g, "base", f[i].base);
268 showmp("exp", f[i].exp, 10);
269 }
270 show(g, "expected", r); show(g, "computed", c);
271 }
272 for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); }
273 G_DESTROY(g, r); G_DESTROY(g, c);
274 G_DESTROYGROUP(g);
275 assert(mparena_count(MPARENA_GLOBAL) == 0);
276 return (ok);
277 }
278
279 static int vmexp1(dstr *v) { return vmexp(1, v); }
280 static int vmexp2(dstr *v) { return vmexp(2, v); }
281 static int vmexp3(dstr *v) { return vmexp(3, v); }
282 static int vmexp4(dstr *v) { return vmexp(4, v); }
283
284 static int vtoint(dstr *v)
285 {
286 group *g = getgroup(v[0].buf);
287 ge *x = getge(g, v[1].buf);
288 int ir = *(int *)v[2].buf;
289 mp *r = *(mp **)v[3].buf;
290 mp *c;
291 int ic;
292 int ok = 1;
293 c = G_TOINT(g, MP_NEW, x);
294 ic = c ? 0 : -1;
295 if (ir != ic || (!ic && !MP_EQ(r, c))) {
296 ok = 0;
297 fprintf(stderr, "\n*** toint failed\n");
298 fprintf(stderr, "*** group: %s\n", v[0].buf);
299 if (ir) fprintf(stderr, "*** expected failure\n");
300 else { show(g, "x", x); showmp("expected", r, 16);
301 showmp("computed", c, 16); }
302 }
303 G_DESTROY(g, x); mp_drop(r); mp_drop(c);
304 G_DESTROYGROUP(g);
305 assert(mparena_count(MPARENA_GLOBAL) == 0);
306 return (ok);
307 }
308
309 static int vfromint(dstr *v)
310 {
311 group *g = getgroup(v[0].buf);
312 mp *x = *(mp **)v[1].buf;
313 int ir = *(int *)v[2].buf;
314 ge *r = getge(g, v[3].buf);
315 int ic;
316 ge *c = G_CREATE(g);
317 int ok = 1;
318 ic = G_FROMINT(g, c, x);
319 if (ir != ic || (!ic && !G_EQ(g, r, c))) {
320 ok = 0;
321 fprintf(stderr, "\n*** fromint failed\n");
322 fprintf(stderr, "*** group: %s\n", v[0].buf);
323 showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n");
324 else { show(g, "expected", r); show(g, "computed", c); }
325 }
326 MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c);
327 G_DESTROYGROUP(g);
328 assert(mparena_count(MPARENA_GLOBAL) == 0);
329 return (ok);
330 }
331
332 static int vtoec(dstr *v)
333 {
334 group *g = getgroup(v[0].buf);
335 ge *x = getge(g, v[1].buf);
336 int ir = *(int *)v[2].buf;
337 ec *r = (ec *)v[3].buf;
338 int ic;
339 ec c = EC_INIT;
340 int ok = 1;
341 ic = G_TOEC(g, &c, x);
342 if (ir != ic || (!ic && !EC_EQ(r, &c))) {
343 ok = 0;
344 fprintf(stderr, "\n*** toec failed\n");
345 fprintf(stderr, "*** group: %s\n", v[0].buf);
346 show(g, "x", x);
347 if (ir) fprintf(stderr, "*** should have failed\n");
348 else { showec("expected", r); showec("computed", &c); }
349 }
350 G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r);
351 G_DESTROYGROUP(g);
352 assert(mparena_count(MPARENA_GLOBAL) == 0);
353 return (ok);
354 }
355
356 static int vfromec(dstr *v)
357 {
358 group *g = getgroup(v[0].buf);
359 ec *p = (ec *)v[1].buf;
360 int ir = *(int *)v[2].buf;
361 ge *r = getge(g, v[3].buf);
362 int ic;
363 ge *c = G_CREATE(g);
364 int ok = 1;
365 ic = G_FROMEC(g, c, p);
366 if (ir != ic || (!ic && !G_EQ(g, r, c))) {
367 ok = 0;
368 fprintf(stderr, "\n*** fromec failed\n");
369 fprintf(stderr, "*** group: %s\n", v[0].buf);
370 showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n");
371 else { show(g, "expected", r); show(g, "computed", c); }
372 }
373 EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c);
374 G_DESTROYGROUP(g);
375 assert(mparena_count(MPARENA_GLOBAL) == 0);
376 return (ok);
377 }
378
379 static int vtobuf(dstr *v)
380 {
381 group *g = getgroup(v[0].buf);
382 ge *x = getge(g, v[1].buf);
383 int ir = *(int *)v[2].buf;
384 dstr c = DSTR_INIT;
385 int ic;
386 buf b;
387 int ok = 1;
388
389 dstr_ensure(&c, v[3].len);
390 buf_init(&b, c.buf, v[3].len);
391 ic = G_TOBUF(g, &b, x);
392 c.len = BLEN(&b);
393 if (ic != ir || (!ic && (c.len != v[3].len ||
394 MEMCMP(c.buf, !=, v[3].buf, c.len)))) {
395 ok = 0;
396 fprintf(stderr, "*** tobuf failed\n");
397 fprintf(stderr, "*** group: %s\n", v[0].buf);
398 show(g, "x", x);
399 if (ir) fprintf(stderr, "*** expected failure\n");
400 else {
401 fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
402 fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
403 fputc('\n', stderr);
404 }
405 }
406 G_DESTROY(g, x); dstr_destroy(&c);
407 G_DESTROYGROUP(g);
408 assert(mparena_count(MPARENA_GLOBAL) == 0);
409 return (ok);
410 }
411
412 static int vfrombuf(dstr *v)
413 {
414 group *g = getgroup(v[0].buf);
415 int ir = *(int *)v[2].buf;
416 ge *r = getge(g, v[3].buf);
417 int ic;
418 ge *c = G_CREATE(g);
419 buf b;
420 int ok = 1;
421
422 buf_init(&b, v[1].buf, v[1].len);
423 ic = G_FROMBUF(g, &b, c);
424 if ((ic < 0) != (ir < 0) || (ir >= 0 &&
425 (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
426 ok = 0;
427 fprintf(stderr, "*** frombuf failed\n");
428 fprintf(stderr, "*** group: %s\n", v[0].buf);
429 fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
430 fputc('\n', stderr);
431 if (ir < 0) fprintf(stderr, "*** expected failure\n");
432 else {
433 show(g, "expected", r); show(g, "computed", c);
434 fprintf(stderr, "*** expected used = %d\n", ir);
435 fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
436 }
437 }
438 G_DESTROY(g, r); G_DESTROY(g, c);
439 G_DESTROYGROUP(g);
440 assert(mparena_count(MPARENA_GLOBAL) == 0);
441 return (ok);
442 }
443
444 static int vtoraw(dstr *v)
445 {
446 group *g = getgroup(v[0].buf);
447 ge *x = getge(g, v[1].buf);
448 int ir = *(int *)v[2].buf;
449 dstr c = DSTR_INIT;
450 int ic;
451 buf b;
452 int ok = 1;
453
454 dstr_ensure(&c, v[3].len);
455 buf_init(&b, c.buf, v[3].len);
456 ic = G_TORAW(g, &b, x);
457 c.len = BLEN(&b);
458 if (ic != ir || (!ic && (c.len != v[3].len ||
459 MEMCMP(c.buf, !=, v[3].buf, c.len)))) {
460 ok = 0;
461 fprintf(stderr, "*** toraw failed\n");
462 fprintf(stderr, "*** group: %s\n", v[0].buf);
463 show(g, "x", x);
464 if (ir) fprintf(stderr, "*** expected failure\n");
465 else {
466 fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
467 fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
468 fputc('\n', stderr);
469 }
470 }
471 G_DESTROY(g, x); dstr_destroy(&c);
472 G_DESTROYGROUP(g);
473 assert(mparena_count(MPARENA_GLOBAL) == 0);
474 return (ok);
475 }
476
477 static int vfromraw(dstr *v)
478 {
479 group *g = getgroup(v[0].buf);
480 int ir = *(int *)v[2].buf;
481 ge *r = getge(g, v[3].buf);
482 int ic;
483 ge *c = G_CREATE(g);
484 buf b;
485 int ok = 1;
486
487 buf_init(&b, v[1].buf, v[1].len);
488 ic = G_FROMRAW(g, &b, c);
489 if ((ic < 0) != (ir < 0) || (ir >= 0 &&
490 (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
491 ok = 0;
492 fprintf(stderr, "*** fromraw failed\n");
493 fprintf(stderr, "*** group: %s\n", v[0].buf);
494 fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
495 fputc('\n', stderr);
496 if (ir < 0) fprintf(stderr, "*** expected failure\n");
497 else {
498 show(g, "expected", r); show(g, "computed", c);
499 fprintf(stderr, "*** expected used = %d\n", ir);
500 fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
501 }
502 }
503 G_DESTROY(g, r); G_DESTROY(g, c);
504 G_DESTROYGROUP(g);
505 assert(mparena_count(MPARENA_GLOBAL) == 0);
506 return (ok);
507 }
508
509 static const test_chunk tests[] = {
510 { "check", vcheck, { &type_string, &type_string } },
511 { "checkelt", vcheckelt, { &type_string, &type_string, &type_int } },
512 { "mul", vmul, { &type_string, &type_string,
513 &type_string, &type_string } },
514 { "sqr", vsqr, { &type_string, &type_string,
515 &type_string } },
516 { "inv", vinv, { &type_string, &type_string,
517 &type_string } },
518 { "div", vdiv, { &type_string, &type_string,
519 &type_string, &type_string } },
520 { "exp", vexp, { &type_string, &type_string,
521 &type_mp, &type_string } },
522 { "mexp-1", vmexp1, { &type_string,
523 &type_string, &type_mp,
524 &type_string } },
525 { "mexp-2", vmexp2, { &type_string,
526 &type_string, &type_mp,
527 &type_string, &type_mp,
528 &type_string } },
529 { "mexp-3", vmexp3, { &type_string,
530 &type_string, &type_mp,
531 &type_string, &type_mp,
532 &type_string, &type_mp,
533 &type_string } },
534 { "mexp-4", vmexp4, { &type_string,
535 &type_string, &type_mp,
536 &type_string, &type_mp,
537 &type_string, &type_mp,
538 &type_string, &type_mp,
539 &type_string } },
540 { "toint", vtoint, { &type_string, &type_string,
541 &type_int, &type_mp } },
542 { "fromint", vfromint, { &type_string, &type_mp,
543 &type_int, &type_string } },
544 { "toec", vtoec, { &type_string, &type_string,
545 &type_int, &type_ec } },
546 { "fromec", vfromec, { &type_string, &type_ec,
547 &type_int, &type_string } },
548 { "tobuf", vtobuf, { &type_string, &type_string,
549 &type_int, &type_hex } },
550 { "frombuf", vfrombuf, { &type_string, &type_hex,
551 &type_int, &type_string } },
552 { "toraw", vtoraw, { &type_string, &type_string,
553 &type_int, &type_hex } },
554 { "fromraw", vfromraw, { &type_string, &type_hex,
555 &type_int, &type_string } },
556 { 0 }
557 };
558
559 int main(int argc, char *argv[])
560 {
561 sub_init();
562 test_run(argc, argv, tests, SRCDIR "/t/group");
563 return (0);
564 }
565
566 /*----- That's all, folks -------------------------------------------------*/