summaryrefslogtreecommitdiff
path: root/auto_tests
diff options
context:
space:
mode:
Diffstat (limited to 'auto_tests')
-rw-r--r--auto_tests/CMakeLists.txt9
-rw-r--r--auto_tests/cmake/friends_test.cmake10
-rw-r--r--auto_tests/cmake/messenger_test.cmake10
-rwxr-xr-xauto_tests/friends_test.c217
-rw-r--r--auto_tests/messenger_test.c266
-rwxr-xr-xauto_tests/run_tests6
6 files changed, 518 insertions, 0 deletions
diff --git a/auto_tests/CMakeLists.txt b/auto_tests/CMakeLists.txt
new file mode 100644
index 00000000..480c2385
--- /dev/null
+++ b/auto_tests/CMakeLists.txt
@@ -0,0 +1,9 @@
1cmake_minimum_required(VERSION 2.6.0)
2
3cmake_policy(SET CMP0011 NEW)
4
5find_package(Check REQUIRED)
6include_directories(${CHECK_INCLUDE_DIRS})
7
8include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/messenger_test.cmake)
9include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/friends_test.cmake)
diff --git a/auto_tests/cmake/friends_test.cmake b/auto_tests/cmake/friends_test.cmake
new file mode 100644
index 00000000..0dcbb7ee
--- /dev/null
+++ b/auto_tests/cmake/friends_test.cmake
@@ -0,0 +1,10 @@
1cmake_minimum_required(VERSION 2.6.0)
2project(friends_test C)
3set(exe_name friends_test)
4
5add_executable(${exe_name}
6 friends_test.c)
7
8linkCoreLibraries(${exe_name})
9add_dependencies(${exe_name} Check)
10target_link_libraries(${exe_name} Check)
diff --git a/auto_tests/cmake/messenger_test.cmake b/auto_tests/cmake/messenger_test.cmake
new file mode 100644
index 00000000..1ce96d9e
--- /dev/null
+++ b/auto_tests/cmake/messenger_test.cmake
@@ -0,0 +1,10 @@
1cmake_minimum_required(VERSION 2.6.0)
2project(messenger_test C)
3set(exe_name messenger_test)
4
5add_executable(${exe_name}
6 messenger_test.c)
7
8linkCoreLibraries(${exe_name})
9add_dependencies(${exe_name} Check)
10target_link_libraries(${exe_name} Check)
diff --git a/auto_tests/friends_test.c b/auto_tests/friends_test.c
new file mode 100755
index 00000000..4f777ab5
--- /dev/null
+++ b/auto_tests/friends_test.c
@@ -0,0 +1,217 @@
1/* Unit testing for friend requests, statuses, and messages.
2 * Purpose: Check that messaging functions actually do what
3 * they're supposed to by setting up two local clients.
4 *
5 * Design: (Subject to change.)
6 * 1. Parent sends a friend request, and waits for a response.
7 * It it doesn't get one, it kills the child.
8 * 2. Child gets friend request, accepts, then waits for a status change.
9 * 3. The parent waits on a status change, killing the child if it takes
10 * too long.
11 * 4. The child gets the status change, then sends a message. After that,
12 * it returns. If if doesn't get the status change, it just loops forever.
13 * 5. After getting the status change, the parent waits for a message, on getting
14 * one, it waits on the child to return, then returns 0.
15 *
16 * Note about "waiting":
17 * Wait time is decided by WAIT_COUNT and WAIT_TIME. c_sleep(WAIT_TIME) WAIT_COUNT
18 * times. This is used both to ensure that we don't loop forever on a broken build,
19 * and that we don't get too slow with messaging. The current time is 15 seconds. */
20
21#include "../core/friend_requests.h"
22#include "../core/Messenger.h"
23#include <assert.h>
24#include <unistd.h>
25#include <sys/mman.h>
26#include <signal.h>
27#include <sys/wait.h>
28
29#define WAIT_COUNT 30
30#define WAIT_TIME 500
31
32/* first step, second step */
33#define FIRST_FLAG 0x1
34#define SECOND_FLAG 0x2
35
36/* ensure that we sleep in milliseconds */
37#ifdef WIN32
38#define c_sleep(x) Sleep(x)
39#else
40#define c_sleep(x) usleep(1000*x)
41#endif
42
43uint8_t *parent_id = NULL;
44uint8_t *child_id = NULL;
45
46pid_t child_pid = 0;
47int request_flags = 0;
48
49void do_tox(void)
50{
51 static int dht_on = 0;
52
53 if(!dht_on && DHT_isconnected()) {
54 dht_on = 1;
55 } else if(dht_on && !DHT_isconnected()) {
56 dht_on = 0;
57 }
58
59 doMessenger();
60}
61
62void parent_confirm_message(int num, uint8_t *data, uint16_t length)
63{
64 puts("OK");
65 request_flags |= SECOND_FLAG;
66}
67
68void parent_confirm_status(int num, USERSTATUS_KIND status, uint8_t *data, uint16_t length)
69{
70 puts("OK");
71 request_flags |= FIRST_FLAG;
72}
73
74int parent_friend_request(void)
75{
76 char *message = "Watson, come here, I need you.";
77 int len = strlen(message);
78 int i = 0;
79
80 fputs("Sending child request.", stdout);
81 fflush(stdout);
82
83 m_addfriend(child_id, (uint8_t *)message, len);
84
85 /* wait on the status change */
86 for(i = 0; i < WAIT_COUNT; i++) {
87 do_tox();
88 if(request_flags & FIRST_FLAG)
89 break;
90 fputs(".", stdout);
91 fflush(stdout);
92 c_sleep(WAIT_TIME);
93 }
94
95 if(!(request_flags & FIRST_FLAG)) {
96 fputs("\nfriends_test: The child took to long to respond!\n"
97 "Friend requests may be broken, failing build!\n", stderr);
98 kill(child_pid, SIGKILL);
99 return -1;
100 }
101
102 return 0;
103}
104
105void child_got_request(uint8_t *public_key, uint8_t *data, uint16_t length)
106{
107 fputs("OK\nsending status to parent", stdout);
108 fflush(stdout);
109 m_addfriend_norequest(public_key);
110 request_flags |= FIRST_FLAG;
111}
112
113void child_got_statuschange(int friend_num, USERSTATUS_KIND status, uint8_t *string, uint16_t length)
114{
115 request_flags |= SECOND_FLAG;
116}
117
118int parent_wait_for_message(void)
119{
120 int i = 0;
121
122 fputs("Parent waiting for message.", stdout);
123 fflush(stdout);
124
125 for(i = 0; i < WAIT_COUNT; i++) {
126 do_tox();
127 if(request_flags & SECOND_FLAG)
128 break;
129 fputs(".", stdout);
130 fflush(stdout);
131 c_sleep(WAIT_TIME);
132 }
133
134 if(!(request_flags & SECOND_FLAG)) {
135 fputs("\nParent hasn't recieved the message yet!\n"
136 "Messaging may be broken, failing the build!\n", stderr);
137 kill(child_pid, SIGKILL);
138 return -1;
139 }
140
141 return 0;
142}
143
144void cleanup(void)
145{
146 munmap(parent_id, crypto_box_PUBLICKEYBYTES);
147 munmap(child_id, crypto_box_PUBLICKEYBYTES);
148 puts("============= END TEST =============");
149}
150
151int main(int argc, char *argv[])
152{
153 puts("=========== FRIENDS_TEST ===========");
154
155 /* set up the global memory */
156 parent_id = mmap(NULL, crypto_box_PUBLICKEYBYTES, PROT_READ | PROT_WRITE,
157 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
158 child_id = mmap(NULL, crypto_box_PUBLICKEYBYTES, PROT_READ | PROT_WRITE,
159 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
160
161 fputs("friends_test: Starting test...\n", stdout);
162 if((child_pid = fork()) == 0) {
163 /* child */
164 int i = 0;
165 char *message = "Y-yes Mr. Watson?";
166
167 initMessenger();
168 Messenger_save(child_id);
169 msync(child_id, crypto_box_PUBLICKEYBYTES, MS_SYNC);
170
171 m_callback_friendrequest(child_got_request);
172 m_callback_userstatus(child_got_statuschange);
173
174 /* wait on the friend request */
175 while(!(request_flags & FIRST_FLAG))
176 do_tox();
177
178 /* wait for the status change */
179 while(!(request_flags & SECOND_FLAG))
180 do_tox();
181
182 for(i = 0; i < 6; i++) {
183 /* send the message six times, just to be sure */
184 m_sendmessage(0, (uint8_t *)message, strlen(message));
185 do_tox();
186 }
187
188 return 0;
189 }
190
191 /* parent */
192 if(atexit(cleanup) != 0) {
193 fputs("friends_test: atexit() failed!\nFailing build...\n", stderr);
194 kill(child_pid, SIGKILL);
195 return -1;
196 }
197
198 msync(parent_id, crypto_box_PUBLICKEYBYTES, MS_SYNC);
199 m_callback_userstatus(parent_confirm_status);
200 m_callback_friendmessage(parent_confirm_message);
201
202 /* hacky way to give the child time to set up */
203 c_sleep(50);
204
205 initMessenger();
206 Messenger_save(parent_id);
207
208 if(parent_friend_request() == -1)
209 return -1;
210
211 if(parent_wait_for_message() == -1)
212 return -1;
213
214 wait(NULL);
215 fputs("friends_test: Build passed!\n", stdout);
216 return 0;
217}
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c
new file mode 100644
index 00000000..42c14fa6
--- /dev/null
+++ b/auto_tests/messenger_test.c
@@ -0,0 +1,266 @@
1/* unit tests for /core/Messenger.c
2 * Design:
3 * Just call every non-static function in Messenger.c, checking that
4 * they return as they should with check calls. "Bad" calls of the type
5 * function(bad_data, good_length) are _not_ checked for, this type
6 * of call is the fault of the client code.
7 *
8 * Note:
9 * None of the functions here test things that rely on the network, i.e.
10 * checking that status changes are recieved, messages can be sent, etc.
11 * All of that is done in a separate test, with two local clients running. */
12
13#include "../core/Messenger.h"
14#include <sys/types.h>
15#include <stdint.h>
16#include <string.h>
17#include <check.h>
18
19#define REALLY_BIG_NUMBER ((1) << (sizeof(uint16_t) * 7))
20#define STRINGS_EQUAL(X, Y) (strcmp(X, Y) == 0)
21
22char *friend_id_str = "1145e295b0fbdc9330d5d74ec204a8bf23c315106040b4035d0d358d07ee3f7d";
23
24/* in case we need more than one ID for a test */
25char *good_id_a_str = "DB9B569D14850ED8364C3744CAC2C8FF78985D213E980C7C508D0E91E8E45441";
26char *good_id_b_str = "d3f14b6d384d8f5f2a66cff637e69f28f539c5de61bc29744785291fa4ef4d64";
27
28char *bad_id_str = "THIS_IS_A_BAD_IDTHIS_IS_A_BAD_IDTHIS_IS_A_BAD_IDTHIS_IS_A_BAD_ID";
29
30unsigned char *friend_id = NULL;
31unsigned char *good_id_a = NULL;
32unsigned char *good_id_b = NULL;
33unsigned char *bad_id = NULL;
34
35int friend_id_num = 0;
36
37unsigned char * hex_string_to_bin(char hex_string[])
38{
39 size_t len = strlen(hex_string);
40 unsigned char *val = calloc(1, len);
41 char *pos = hex_string;
42 int i = 0;
43 for(i = 0; i < len; ++i, pos+=2)
44 sscanf(pos,"%2hhx",&val[i]);
45 return val;
46}
47
48START_TEST(test_m_sendmesage)
49{
50 char *message = "h-hi :3";
51 int good_len = strlen(message);
52 int bad_len = MAX_DATA_SIZE;
53
54
55 ck_assert(m_sendmessage(-1, (uint8_t *)message, good_len) == 0);
56 ck_assert(m_sendmessage(REALLY_BIG_NUMBER, (uint8_t *)message, good_len) == 0);
57 ck_assert(m_sendmessage(17, (uint8_t *)message, good_len) == 0);
58 ck_assert(m_sendmessage(friend_id_num, (uint8_t *)message, bad_len) == 0);
59}
60END_TEST
61
62START_TEST(test_m_get_userstatus_size)
63{
64 int rc = 0;
65 ck_assert_msg((m_get_userstatus_size(-1) == -1),
66 "m_get_userstatus_size did NOT catch an argument of -1");
67 ck_assert_msg((m_get_userstatus_size(REALLY_BIG_NUMBER) == -1),
68 "m_get_userstatus_size did NOT catch the following argument: %d\n",
69 REALLY_BIG_NUMBER);
70 rc = m_get_userstatus_size(friend_id_num);
71
72 ck_assert_msg((rc > 0 && rc <= MAX_USERSTATUS_LENGTH),
73 "m_get_userstatus_size is returning out of range values!\n");
74}
75END_TEST
76
77START_TEST(test_m_set_userstatus)
78{
79 char *status = "online!";
80 uint16_t good_length = strlen(status);
81 uint16_t bad_length = REALLY_BIG_NUMBER;
82
83 if(m_set_userstatus(USERSTATUS_KIND_ONLINE,
84 (uint8_t *)status, bad_length) != -1)
85 ck_abort_msg("m_set_userstatus did NOT catch the following length: %d\n",
86 REALLY_BIG_NUMBER);
87
88 if((m_set_userstatus(USERSTATUS_KIND_RETAIN,
89 (uint8_t *)status, good_length)) != 0)
90 ck_abort_msg("m_set_userstatus did NOT return 0 on the following length: %d\n"
91 "MAX_USERSTATUS_LENGTH: %d\n", good_length, MAX_USERSTATUS_LENGTH);
92}
93END_TEST
94
95START_TEST(test_m_friendstatus)
96{
97 ck_assert_msg((m_friendstatus(-1) == NOFRIEND),
98 "m_friendstatus did NOT catch an argument of -1.\n");
99 ck_assert_msg((m_friendstatus(REALLY_BIG_NUMBER) == NOFRIEND),
100 "m_friendstatus did NOT catch an argument of %d.\n",
101 REALLY_BIG_NUMBER);
102}
103END_TEST
104
105START_TEST(test_m_delfriend)
106{
107 ck_assert_msg((m_delfriend(-1) == -1),
108 "m_delfriend did NOT catch an argument of -1\n");
109 ck_assert_msg((m_delfriend(REALLY_BIG_NUMBER) == -1),
110 "m_delfriend did NOT catch the following number: %d\n",
111 REALLY_BIG_NUMBER);
112}
113END_TEST
114
115START_TEST(test_m_addfriend)
116{
117 char *good_data = "test";
118 char *bad_data = "";
119
120 int good_len = strlen(good_data);
121 int bad_len = strlen(bad_data);
122 int really_bad_len = (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
123 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
124 + crypto_box_ZEROBYTES + 100);
125
126 if(m_addfriend((uint8_t *)friend_id, (uint8_t *)good_data, really_bad_len) != FAERR_TOOLONG)
127 ck_abort_msg("m_addfriend did NOT catch the following length: %d\n", really_bad_len);
128
129 if(m_addfriend((uint8_t *)friend_id, (uint8_t *)good_data, good_len) != FAERR_ALREADYSENT)
130 ck_abort_msg("m_addfriend did NOT catch adding a friend we already have.\n");
131
132 if(m_addfriend((uint8_t *)good_id_b, (uint8_t *)bad_data, bad_len) != FAERR_NOMESSAGE)
133 ck_abort_msg("m_addfriend did NOT catch the following length: %d\n", bad_len);
134
135 /* this should REALLY error */
136 if(m_addfriend((uint8_t *)bad_id, (uint8_t *)good_data, good_len) >= 0)
137 ck_abort_msg("The following ID passed through "
138 "m_addfriend without an error:\n'%s'\n", bad_id_str);
139}
140END_TEST
141
142START_TEST(test_setname)
143{
144 char *good_name = "consensualCorn";
145 int good_length = strlen(good_name);
146 int bad_length = REALLY_BIG_NUMBER;
147
148 if(setname((uint8_t *)good_name, bad_length) != -1)
149 ck_abort_msg("setname() did NOT error on %d as a length argument!\n",
150 bad_length);
151 if(setname((uint8_t *)good_name, good_length) != 0)
152 ck_abort_msg("setname() did NOT return 0 on good arguments!\n");
153}
154END_TEST
155
156START_TEST(test_getself_name)
157{
158 char *nickname = "testGallop";
159 int len = strlen(nickname);
160 char nick_check[len];
161
162 setname((uint8_t *)nickname, len);
163 getself_name((uint8_t *)nick_check);
164
165 ck_assert_msg((!STRINGS_EQUAL(nickname, nick_check)),
166 "getself_name failed to return the known name!\n"
167 "known name: %s\nreturned: %s\n", nickname, nick_check);
168}
169END_TEST
170
171/* this test is excluded for now, due to lack of a way
172 * to set a friend's status for now.
173 * ideas:
174 * if we have access to the friends list, we could
175 * just add a status manually ourselves. */
176/*
177START_TEST(test_m_copy_userstatus)
178{
179 assert(m_copy_userstatus(-1, buf, MAX_USERSTATUS_LENGTH) == -1);
180 assert(m_copy_userstatus(REALLY_BIG_NUMBER, buf, MAX_USERSTATUS_LENGTH) == -1);
181 m_copy_userstatus(friend_id_num, buf, MAX_USERSTATUS_LENGTH + 6);
182
183 assert(STRINGS_EQUAL(name_buf, friend_id_status));
184}
185END_TEST
186*/
187
188/* this test is excluded for now, due to lack of a way
189 * to set a friend's nickname for now.
190 * ideas:
191 * if we have access to the friends list, we could
192 * just add a name manually ourselves. */
193/*
194START_TEST(test_getname)
195{
196 uint8_t name_buf[MAX_NAME_LENGTH];
197
198 assert(getname(-1, name_buf) == -1);
199 assert(getname(REALLY_BIG_NUMBER, name_buf) == -1);
200
201 getname(friend_id_num, name_buf);
202 assert(name_buf[MAX_NAME_LENGTH] == '\0'); // something like this
203}
204END_TEST
205*/
206
207Suite *messenger_suite(void)
208{
209 Suite *s = suite_create("Messenger");
210
211 TCase *userstatus_size = tcase_create("userstatus_size");
212 TCase *set_userstatus = tcase_create("set_userstatus");
213 TCase *send_message = tcase_create("send_message");
214 TCase *friendstatus = tcase_create("friendstatus");
215 TCase *getself_name = tcase_create("getself_name");
216 TCase *delfriend = tcase_create("delfriend");
217 TCase *addfriend = tcase_create("addfriend");
218 TCase *setname = tcase_create("setname");
219
220 tcase_add_test(userstatus_size, test_m_get_userstatus_size);
221 tcase_add_test(set_userstatus, test_m_set_userstatus);
222 tcase_add_test(friendstatus, test_m_friendstatus);
223 tcase_add_test(getself_name, test_getself_name);
224 tcase_add_test(send_message, test_m_sendmesage);
225 tcase_add_test(delfriend, test_m_delfriend);
226 tcase_add_test(addfriend, test_m_addfriend);
227 tcase_add_test(setname, test_setname);
228
229 suite_add_tcase(s, userstatus_size);
230 suite_add_tcase(s, set_userstatus);
231 suite_add_tcase(s, friendstatus);
232 suite_add_tcase(s, send_message);
233 suite_add_tcase(s, getself_name);
234 suite_add_tcase(s, delfriend);
235 suite_add_tcase(s, addfriend);
236 suite_add_tcase(s, setname);
237
238 return s;
239}
240
241int main(int argc, char *argv[])
242{
243 Suite *messenger = messenger_suite();
244 SRunner *test_runner = srunner_create(messenger);
245 int number_failed = 0;
246
247 friend_id = hex_string_to_bin(friend_id_str);
248 good_id_a = hex_string_to_bin(good_id_a_str);
249 good_id_b = hex_string_to_bin(good_id_b_str);
250 bad_id = hex_string_to_bin(bad_id_str);
251
252 /* setup a default friend and friendnum */
253 m_addfriend_norequest((uint8_t *)friend_id);
254 friend_id_num = getfriend_id((uint8_t *)friend_id);
255
256 srunner_run_all(test_runner, CK_NORMAL);
257 number_failed = srunner_ntests_failed(test_runner);
258
259 srunner_free(test_runner);
260 free(friend_id);
261 free(good_id_a);
262 free(good_id_b);
263 free(bad_id);
264
265 return number_failed;
266}
diff --git a/auto_tests/run_tests b/auto_tests/run_tests
new file mode 100755
index 00000000..3b5c7f54
--- /dev/null
+++ b/auto_tests/run_tests
@@ -0,0 +1,6 @@
1#!/bin/bash
2# run_tests - run the current tests for tox core
3set -e
4
5make
6./messenger_test && ./friends_test