]> begriffs open source - libpw/blob - test/test.c
Switch to Meson build system
[libpw] / test / test.c
1 #include "pw.h"
2 #include "tap.h"
3
4 // posix for clock/timer functions
5 #define _POSIX_C_SOURCE 200112L
6
7 #include <math.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <time.h>
12
13 bool get_monotonic_timestamp(double *ts);
14
15 int main(int argc, char **argv){
16         sqlite3 *db = NULL;
17         int rc;
18
19         if (argc != 2)
20         {
21                 fprintf(stderr, "Usage: %s DATABASE\n", argv[0]);
22                 goto fail;
23         }
24         rc = sqlite3_open(argv[1], &db);
25         if( rc ){
26                 fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
27                 goto fail;
28         }
29
30         pw_context *ctx;
31         pw_init_context(db, &ctx);
32
33         char *u1  = "foo@example.com", *p1 = "password123",
34                  *u1c = "FOO@EXAMPLE.COM";
35
36         plan(9);
37
38         ok(PW_OK == pw_set(ctx, u1, p1), "pw_set");
39
40         ok(PW_OK == pw_check(ctx, u1, p1),
41                 "pw_check accepts the same credentials");
42
43         ok(PW_OK == pw_check(ctx, u1c, p1),
44                 "pw_check also accepts mixed case user");
45         ok(PW_BAD_PASS == pw_check(ctx, u1, "wrong"),
46                 "pw_check fails for wrong pass");
47         ok(PW_NO_USER == pw_check(ctx, "fake", "wrong"),
48                 "pw_check fails for missing user");
49
50         unsigned char *tok;
51         unsigned int tok_len;
52
53         ok(PW_OK == pw_token_create(ctx, u1, &tok, &tok_len),
54                 "pw_token_create can build one");
55         cmp_ok(tok_len, "==", 16,
56                 "token has expected length");
57
58         int i;
59         double start, end,
60                t_found, t_notfound,
61                    pct_diff;
62
63         diag("check password 100 times");
64         get_monotonic_timestamp(&start);
65         for (i = 0; i < 100; i++)
66                 pw_check(ctx, u1, p1);
67         get_monotonic_timestamp(&end);
68         t_found = end - start;
69
70         diag("check 100 times for missing user");
71         get_monotonic_timestamp(&start);
72         for (i = 0; i < 100; i++)
73                 pw_check(ctx, "fake", "wrong");
74         get_monotonic_timestamp(&end);
75         t_notfound = end - start;
76
77         pct_diff = 100.0 *
78                 fabs( (t_found - t_notfound) / ((t_found + t_notfound)/2) );
79
80         cmp_ok(pct_diff, "<", 1.0, "less than 1%% time difference");
81
82         free(ctx);
83         sqlite3_close(db);
84         return 0;
85
86 fail:
87         sqlite3_close(db);
88         return EXIT_FAILURE;
89 }
90
91 // idea for using double representation taken from
92 // https://github.com/solemnwarning/timespec
93 #define NSEC_PER_SEC 1000000000
94 bool get_monotonic_timestamp(double *ts)
95 {
96         struct timespec now;
97         int rc = clock_gettime(CLOCK_MONOTONIC, &now);
98         if (rc != 0)
99                 return false;
100         *ts = (
101                  ((double)now.tv_sec) +
102                 (((double)now.tv_nsec) / NSEC_PER_SEC)
103         );
104         return true;
105 }