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