10ac341f1SConrad Meyer 
20ac341f1SConrad Meyer #ifndef __CMPTEST_H__
30ac341f1SConrad Meyer #define __CMPTEST_H__
40ac341f1SConrad Meyer 
50ac341f1SConrad Meyer #ifdef NDEBUG
60ac341f1SConrad Meyer #/**/undef/**/ NDEBUG
70ac341f1SConrad Meyer #endif
80ac341f1SConrad Meyer 
90ac341f1SConrad Meyer #include <assert.h>
100ac341f1SConrad Meyer #include <errno.h>
110ac341f1SConrad Meyer #include <limits.h>
120ac341f1SConrad Meyer #include <stdio.h>
130ac341f1SConrad Meyer #include <stdint.h>
140ac341f1SConrad Meyer #include <stdlib.h>
150ac341f1SConrad Meyer #include <string.h>
160ac341f1SConrad Meyer 
170ac341f1SConrad Meyer #include "sodium.h"
180ac341f1SConrad Meyer #include "quirks.h"
190ac341f1SConrad Meyer 
200ac341f1SConrad Meyer #ifdef __EMSCRIPTEN__
210ac341f1SConrad Meyer # undef TEST_SRCDIR
220ac341f1SConrad Meyer # define TEST_SRCDIR "/test-data"
230ac341f1SConrad Meyer #endif
240ac341f1SConrad Meyer #ifndef TEST_SRCDIR
250ac341f1SConrad Meyer # define TEST_SRCDIR "."
260ac341f1SConrad Meyer #endif
270ac341f1SConrad Meyer 
280ac341f1SConrad Meyer #define TEST_NAME_RES TEST_NAME ".res"
290ac341f1SConrad Meyer #define TEST_NAME_OUT TEST_SRCDIR "/" TEST_NAME ".exp"
300ac341f1SConrad Meyer 
310ac341f1SConrad Meyer #ifdef HAVE_ARC4RANDOM
320ac341f1SConrad Meyer # undef rand
330ac341f1SConrad Meyer # define rand(X) arc4random(X)
340ac341f1SConrad Meyer #endif
350ac341f1SConrad Meyer 
360ac341f1SConrad Meyer int xmain(void);
370ac341f1SConrad Meyer 
380ac341f1SConrad Meyer #ifdef BENCHMARKS
390ac341f1SConrad Meyer 
400ac341f1SConrad Meyer # include <sys/time.h>
410ac341f1SConrad Meyer 
420ac341f1SConrad Meyer # ifndef ITERATIONS
430ac341f1SConrad Meyer #  define ITERATIONS 128
440ac341f1SConrad Meyer # endif
450ac341f1SConrad Meyer 
460ac341f1SConrad Meyer struct {
470ac341f1SConrad Meyer     void   *pnt;
480ac341f1SConrad Meyer     size_t  size;
490ac341f1SConrad Meyer } mempool[1024];
500ac341f1SConrad Meyer 
510ac341f1SConrad Meyer static size_t mempool_idx;
520ac341f1SConrad Meyer 
mempool_alloc(size_t size)530ac341f1SConrad Meyer static __attribute__((malloc)) void *mempool_alloc(size_t size)
540ac341f1SConrad Meyer {
550ac341f1SConrad Meyer     size_t i;
560ac341f1SConrad Meyer     if (size >= (size_t) 0x80000000 - (size_t) 0x00000fff) {
570ac341f1SConrad Meyer         return NULL;
580ac341f1SConrad Meyer     }
590ac341f1SConrad Meyer     size = (size + (size_t) 0x00000fff) & ~ (size_t) 0x00000fff;
600ac341f1SConrad Meyer     for (i = 0U; i < mempool_idx; i++) {
610ac341f1SConrad Meyer         if (mempool[i].size >= (size | (size_t) 0x80000000)) {
620ac341f1SConrad Meyer             mempool[i].size &= ~ (size_t) 0x80000000;
630ac341f1SConrad Meyer             return mempool[i].pnt;
640ac341f1SConrad Meyer         }
650ac341f1SConrad Meyer     }
660ac341f1SConrad Meyer     if (mempool_idx >= sizeof mempool / sizeof mempool[0]) {
670ac341f1SConrad Meyer         return NULL;
680ac341f1SConrad Meyer     }
690ac341f1SConrad Meyer     mempool[mempool_idx].size = size;
700ac341f1SConrad Meyer     return (mempool[mempool_idx++].pnt = (void *) malloc(size));
710ac341f1SConrad Meyer }
720ac341f1SConrad Meyer 
mempool_free(void * pnt)730ac341f1SConrad Meyer static void mempool_free(void *pnt)
740ac341f1SConrad Meyer {
750ac341f1SConrad Meyer     size_t i;
760ac341f1SConrad Meyer     for (i = 0U; i < mempool_idx; i++) {
770ac341f1SConrad Meyer         if (mempool[i].pnt == pnt) {
780ac341f1SConrad Meyer             if ((mempool[i].size & (size_t) 0x80000000) != (size_t) 0x0) {
790ac341f1SConrad Meyer                 break;
800ac341f1SConrad Meyer             }
810ac341f1SConrad Meyer             mempool[i].size |= (size_t) 0x80000000;
820ac341f1SConrad Meyer             return;
830ac341f1SConrad Meyer         }
840ac341f1SConrad Meyer     }
850ac341f1SConrad Meyer     abort();
860ac341f1SConrad Meyer }
870ac341f1SConrad Meyer 
mempool_allocarray(size_t count,size_t size)880ac341f1SConrad Meyer static __attribute__((malloc)) void *mempool_allocarray(size_t count, size_t size)
890ac341f1SConrad Meyer {
900ac341f1SConrad Meyer     if (count > (size_t) 0U && size >= (size_t) SIZE_MAX / count) {
910ac341f1SConrad Meyer         return NULL;
920ac341f1SConrad Meyer     }
930ac341f1SConrad Meyer     return mempool_alloc(count * size);
940ac341f1SConrad Meyer }
950ac341f1SConrad Meyer 
mempool_free_all(void)960ac341f1SConrad Meyer static int mempool_free_all(void)
970ac341f1SConrad Meyer {
980ac341f1SConrad Meyer     size_t i;
990ac341f1SConrad Meyer     int    ret = 0;
1000ac341f1SConrad Meyer 
1010ac341f1SConrad Meyer     for (i = 0U; i < mempool_idx; i++) {
1020ac341f1SConrad Meyer         if ((mempool[i].size & (size_t) 0x80000000) == (size_t) 0x0) {
1030ac341f1SConrad Meyer             ret = -1;
1040ac341f1SConrad Meyer         }
1050ac341f1SConrad Meyer         free(mempool[i].pnt);
1060ac341f1SConrad Meyer         mempool[i].pnt = NULL;
1070ac341f1SConrad Meyer     }
1080ac341f1SConrad Meyer     mempool_idx = (size_t) 0U;
1090ac341f1SConrad Meyer 
1100ac341f1SConrad Meyer     return ret;
1110ac341f1SConrad Meyer }
1120ac341f1SConrad Meyer 
1130ac341f1SConrad Meyer #define sodium_malloc(X)        mempool_alloc(X)
1140ac341f1SConrad Meyer #define sodium_free(X)          mempool_free(X)
1150ac341f1SConrad Meyer #define sodium_allocarray(X, Y) mempool_allocarray((X), (Y))
1160ac341f1SConrad Meyer 
now(void)1170ac341f1SConrad Meyer static unsigned long long now(void)
1180ac341f1SConrad Meyer {
1190ac341f1SConrad Meyer     struct             timeval tp;
1200ac341f1SConrad Meyer     unsigned long long now;
1210ac341f1SConrad Meyer 
1220ac341f1SConrad Meyer     if (gettimeofday(&tp, NULL) != 0) {
1230ac341f1SConrad Meyer         abort();
1240ac341f1SConrad Meyer     }
1250ac341f1SConrad Meyer     now = ((unsigned long long) tp.tv_sec * 1000000ULL) +
1260ac341f1SConrad Meyer         (unsigned long long) tp.tv_usec;
1270ac341f1SConrad Meyer 
1280ac341f1SConrad Meyer     return now;
1290ac341f1SConrad Meyer }
1300ac341f1SConrad Meyer 
main(void)1310ac341f1SConrad Meyer int main(void)
1320ac341f1SConrad Meyer {
1330ac341f1SConrad Meyer     unsigned long long ts_start;
1340ac341f1SConrad Meyer     unsigned long long ts_end;
1350ac341f1SConrad Meyer     unsigned int       i;
1360ac341f1SConrad Meyer 
1370ac341f1SConrad Meyer     if (sodium_init() != 0) {
1380ac341f1SConrad Meyer         return 99;
1390ac341f1SConrad Meyer     }
1400ac341f1SConrad Meyer 
1410ac341f1SConrad Meyer #ifndef __EMSCRIPTEN__
1420ac341f1SConrad Meyer     randombytes_set_implementation(&randombytes_salsa20_implementation);
1430ac341f1SConrad Meyer #endif
1440ac341f1SConrad Meyer     ts_start = now();
1450ac341f1SConrad Meyer     for (i = 0; i < ITERATIONS; i++) {
1460ac341f1SConrad Meyer         if (xmain() != 0) {
1470ac341f1SConrad Meyer             abort();
1480ac341f1SConrad Meyer         }
1490ac341f1SConrad Meyer     }
1500ac341f1SConrad Meyer     ts_end = now();
1510ac341f1SConrad Meyer     printf("%llu\n", 1000000ULL * (ts_end - ts_start) / ITERATIONS);
1520ac341f1SConrad Meyer     if (mempool_free_all() != 0) {
1530ac341f1SConrad Meyer         fprintf(stderr, "** memory leaks detected **\n");
1540ac341f1SConrad Meyer         return 99;
1550ac341f1SConrad Meyer     }
1560ac341f1SConrad Meyer     return 0;
1570ac341f1SConrad Meyer }
1580ac341f1SConrad Meyer 
1590ac341f1SConrad Meyer #undef  printf
1600ac341f1SConrad Meyer #define printf(...) do { } while(0)
1610ac341f1SConrad Meyer 
1620ac341f1SConrad Meyer #elif !defined(BROWSER_TESTS)
1630ac341f1SConrad Meyer 
1640ac341f1SConrad Meyer static FILE *fp_res;
1650ac341f1SConrad Meyer 
main(void)1660ac341f1SConrad Meyer int main(void)
1670ac341f1SConrad Meyer {
1680ac341f1SConrad Meyer     FILE *fp_out;
1690ac341f1SConrad Meyer     int   c;
1700ac341f1SConrad Meyer 
1710ac341f1SConrad Meyer     if ((fp_res = fopen(TEST_NAME_RES, "w+")) == NULL) {
1720ac341f1SConrad Meyer         perror("fopen(" TEST_NAME_RES ")");
1730ac341f1SConrad Meyer         return 99;
1740ac341f1SConrad Meyer     }
1750ac341f1SConrad Meyer     if (sodium_init() != 0) {
1760ac341f1SConrad Meyer         return 99;
1770ac341f1SConrad Meyer     }
1780ac341f1SConrad Meyer     if (xmain() != 0) {
1790ac341f1SConrad Meyer         return 99;
1800ac341f1SConrad Meyer     }
1810ac341f1SConrad Meyer     rewind(fp_res);
1820ac341f1SConrad Meyer     if ((fp_out = fopen(TEST_NAME_OUT, "r")) == NULL) {
1830ac341f1SConrad Meyer         perror("fopen(" TEST_NAME_OUT ")");
1840ac341f1SConrad Meyer         return 99;
1850ac341f1SConrad Meyer     }
1860ac341f1SConrad Meyer     do {
1870ac341f1SConrad Meyer         if ((c = fgetc(fp_res)) != fgetc(fp_out)) {
1880ac341f1SConrad Meyer             return 99;
1890ac341f1SConrad Meyer         }
1900ac341f1SConrad Meyer     } while (c != EOF);
1910ac341f1SConrad Meyer 
1920ac341f1SConrad Meyer     return 0;
1930ac341f1SConrad Meyer }
1940ac341f1SConrad Meyer 
1950ac341f1SConrad Meyer #undef  printf
1960ac341f1SConrad Meyer #define printf(...) fprintf(fp_res, __VA_ARGS__)
1970ac341f1SConrad Meyer 
1980ac341f1SConrad Meyer #else
1990ac341f1SConrad Meyer 
main(void)2000ac341f1SConrad Meyer int main(void)
2010ac341f1SConrad Meyer {
2020ac341f1SConrad Meyer     if (sodium_init() != 0) {
2030ac341f1SConrad Meyer         return 99;
2040ac341f1SConrad Meyer     }
2050ac341f1SConrad Meyer     if (xmain() != 0) {
2060ac341f1SConrad Meyer         return 99;
2070ac341f1SConrad Meyer     }
2080ac341f1SConrad Meyer     printf("--- SUCCESS ---\n");
2090ac341f1SConrad Meyer 
2100ac341f1SConrad Meyer     return 0;
2110ac341f1SConrad Meyer }
2120ac341f1SConrad Meyer 
2130ac341f1SConrad Meyer #endif
2140ac341f1SConrad Meyer 
2150ac341f1SConrad Meyer #define main xmain
2160ac341f1SConrad Meyer 
2170ac341f1SConrad Meyer #endif
218