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