1 /*
2 * Copyright (C) 2014 - Julien Voisin <julien.voisin@dustri.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #include <gcrypt.h>
19 #include <limits.h>
20 #include <pthread.h>
21 #include <unistd.h>
22
23 #include <proto.h>
24 #include <auth.h>
25 #include <context.h>
26
27 #include <tap/tap.h>
28 #include <utils.h>
29
30 GCRY_THREAD_OPTION_PTHREAD_IMPL;
31
32 #define NUM_TESTS 13
33
34 /* Current directory of this executable. */
35 static char curdir[PATH_MAX];
36 static char instag_filepath[PATH_MAX];
37
test_otrl_instag_forget(void)38 static void test_otrl_instag_forget(void)
39 {
40 OtrlInsTag *instag1 = calloc(1, sizeof(OtrlInsTag));
41 OtrlInsTag *instag2 = calloc(1, sizeof(OtrlInsTag));
42
43 instag1->tous = &instag1;
44 instag1->accountname = strdup("name one");
45 instag1->protocol = strdup("protocol one");
46 instag1->next = instag2;
47 instag1->next->tous = &(instag1->next);
48 instag2->accountname = strdup("name two");
49 instag2->protocol = strdup("protocol two");
50
51 otrl_instag_forget(NULL);
52 ok(1, "Forget on NULL didn't segfault");
53
54 otrl_instag_forget(instag2);
55 ok(instag1->next == NULL, "Instag forgotten without segfault");
56 }
57
test_otrl_instag_forget_all(void)58 static void test_otrl_instag_forget_all(void)
59 {
60 OtrlUserState us = otrl_userstate_create();
61 OtrlInsTag *p = malloc(sizeof(OtrlInsTag));
62 p->accountname = strdup("account name");
63 p->protocol = strdup("protocol name");
64 p->instag = otrl_instag_get_new();
65
66 otrl_instag_forget_all(us);
67 ok(1, "Forget all on empty user state");
68
69 p->next = us->instag_root;
70 p->tous = &(us->instag_root);
71 us->instag_root = p;
72
73 otrl_instag_forget_all(us);
74 ok(1, "Forget all on a non-empty user state");
75 }
76
test_otrl_instag_find(void)77 static void test_otrl_instag_find(void)
78 {
79 OtrlUserState us = otrl_userstate_create();
80 OtrlInsTag *p1 = malloc(sizeof(OtrlInsTag));
81 OtrlInsTag *p2 = malloc(sizeof(OtrlInsTag));
82
83 p1->accountname = strdup("account one");
84 p1->protocol = strdup("protocol one");
85 p1->instag = otrl_instag_get_new();
86 p1->next = us->instag_root;
87 p1->tous = &(us->instag_root);
88 us->instag_root = p1;
89
90 p2->accountname = strdup("account two");
91 p2->protocol = strdup("protocol two");
92 p2->instag = otrl_instag_get_new();
93 p2->next = us->instag_root;
94 p2->next->tous = &(p2->next);
95 p2->tous = &(us->instag_root);
96 us->instag_root = p2;
97
98 ok(otrl_instag_find(us, "account two", "protocol two") == p2,
99 "Found instag");
100 ok(otrl_instag_find(us, "account one", "protocol two") == NULL,
101 "Instag not found");
102 ok(otrl_instag_find(us, "account three", "protocol three") == NULL,
103 "Instag not found");
104 }
105
test_otrl_instag_read(void)106 static void test_otrl_instag_read(void)
107 {
108 OtrlUserState us = otrl_userstate_create();
109 OtrlInsTag *one, *two, *three, *four;
110 char sone[9] = {0}, stwo[9] = {0}, sfour[9] = {0};
111 one = two = three = four = NULL;
112 ok(otrl_instag_read(us, "/non_existent_file") ==
113 gcry_error_from_errno(ENOENT),
114 "Non-existent file detected");
115
116 ok(otrl_instag_read(us, instag_filepath) == GPG_ERR_NO_ERROR,
117 "Instag called with success");
118
119 one = otrl_instag_find(us, "alice_xmpp", "XMPP");
120 snprintf(sone, sizeof(sone), "%08x", one->instag);
121
122 two = otrl_instag_find(us, "alice_irc", "IRC");
123 snprintf(stwo, sizeof(stwo), "%08x", two->instag);
124
125 three = otrl_instag_find(us, "alice_inv", "IRC");
126
127 four = otrl_instag_find(us, "alice_icq", "ICQ");
128 snprintf(sfour, sizeof(sfour), "%08x", four->instag);
129
130 ok(one && two && !three && four &&
131 strcmp(sone, "01234567") == 0 &&
132 strcmp(stwo, "9abcdef0") == 0 &&
133 strcmp(sfour, "98765432") == 0,
134 "Instag succesfully read");
135 }
136
test_otrl_instag_read_FILEp(void)137 static void test_otrl_instag_read_FILEp(void)
138 {
139 FILE* instf = fopen(instag_filepath, "rb");
140 OtrlUserState us = otrl_userstate_create();
141 OtrlInsTag* one, *two, *three, *four;
142 char sone[9] = {0}, stwo[9] = {0}, sfour[9] = {0};
143 one = two = three = four = NULL;
144
145 ok(otrl_instag_read_FILEp(us, instf) == gcry_error(GPG_ERR_NO_ERROR),
146 "Instead read from FILEp");
147 fclose(instf);
148
149 one = otrl_instag_find(us, "alice_xmpp", "XMPP");
150 snprintf(sone, sizeof(sone), "%08x", one->instag);
151
152 two = otrl_instag_find(us, "alice_irc", "IRC");
153 snprintf(stwo, sizeof(stwo), "%08x", two->instag);
154
155 three = otrl_instag_find(us, "alice_inv", "IRC");
156
157 four = otrl_instag_find(us, "alice_icq", "ICQ");
158 snprintf(sfour, sizeof(sfour), "%08x", four->instag);
159
160 ok(one && two && !three && four &&
161 strcmp(sone, "01234567") == 0 &&
162 strcmp(stwo, "9abcdef0") == 0 &&
163 strcmp(sfour, "98765432") == 0,
164 "Instag succesfully read");
165 }
166
test_otrl_instag_get_new(void)167 static void test_otrl_instag_get_new(void)
168 {
169 ok(otrl_instag_get_new() != 0, "New instag generated");
170 }
171
get_exe_path(char * buf,size_t len)172 static ssize_t get_exe_path(char *buf, size_t len)
173 {
174 char *path_end;
175
176 if (readlink("/proc/self/exe", buf, len) < 0) {
177 return -ENOMEM;
178 }
179
180 /*
181 * Workaround to handle libtool path of the binary that is actually in the
182 * $(buildir)/.libs. This is to make sure unit test works outside of tree.
183 */
184 path_end = strstr(buf, ".libs/");
185 if (!path_end) {
186 path_end = strrchr(buf, '/');
187 if (!path_end) {
188 return -errno;
189 }
190 *(++path_end) = '\0';
191 } else {
192 *path_end = '\0';
193 }
194
195 return path_end - buf;
196 }
197
main(int argc,char ** argv)198 int main(int argc, char **argv)
199 {
200 /* Libtap call for the number of tests planned. */
201 plan_tests(NUM_TESTS);
202
203 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
204 OTRL_INIT;
205
206 if (get_exe_path(curdir, sizeof(curdir)) < 0) {
207 return -ENOMEM;
208 }
209
210 /* Build the full path of the instag.txt file. */
211 (void) snprintf(instag_filepath, sizeof(instag_filepath), "%s%s", curdir,
212 "instag.txt");
213
214 test_otrl_instag_forget();
215 test_otrl_instag_forget_all();
216 test_otrl_instag_find();
217 test_otrl_instag_read();
218 test_otrl_instag_read_FILEp();
219 test_otrl_instag_get_new();
220
221 return 0;
222 }
223