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