port: FreeBSD has no ENODATA, alias it to ENOATTR
[lttng-tools.git] / tests / unit / test_session.c
1 /*
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <sys/types.h>
15 #include <urcu.h>
16
17 #include <tap/tap.h>
18
19 #include <common/compat/errno.h>
20 #include <bin/lttng-sessiond/session.h>
21 #include <bin/lttng-sessiond/ust-app.h>
22 #include <bin/lttng-sessiond/ht-cleanup.h>
23 #include <bin/lttng-sessiond/health-sessiond.h>
24 #include <bin/lttng-sessiond/thread.h>
25 #include <common/sessiond-comm/sessiond-comm.h>
26 #include <common/common.h>
27
28 #define SESSION1 "test1"
29
30 #define MAX_SESSIONS 10000
31 #define RANDOM_STRING_LEN 11
32
33 /* Number of TAP tests in this file */
34 #define NUM_TESTS 11
35
36 static struct ltt_session_list *session_list;
37
38 /* For error.h */
39 int lttng_opt_quiet = 1;
40 int lttng_opt_verbose = 0;
41 int lttng_opt_mi;
42
43 static const char alphanum[] =
44 "0123456789"
45 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
46 "abcdefghijklmnopqrstuvwxyz";
47 static char random_string[RANDOM_STRING_LEN];
48
49 /*
50 * Return random string of 10 characters.
51 * Not thread-safe.
52 */
53 static char *get_random_string(void)
54 {
55 int i;
56
57 for (i = 0; i < RANDOM_STRING_LEN - 1; i++) {
58 random_string[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
59 }
60
61 random_string[RANDOM_STRING_LEN - 1] = '\0';
62
63 return random_string;
64 }
65
66 /*
67 * Return 0 if session name is found, else -1
68 */
69 static int find_session_name(const char *name)
70 {
71 struct ltt_session *iter;
72
73 cds_list_for_each_entry(iter, &session_list->head, list) {
74 if (strcmp(iter->name, name) == 0) {
75 return 0;
76 }
77 }
78
79 return -1;
80 }
81
82 static int session_list_count(void)
83 {
84 int count = 0;
85 struct ltt_session *iter;
86
87 cds_list_for_each_entry(iter, &session_list->head, list) {
88 count++;
89 }
90 return count;
91 }
92
93 /*
94 * Empty session list manually.
95 */
96 static void empty_session_list(void)
97 {
98 struct ltt_session *iter, *tmp;
99
100 session_lock_list();
101 cds_list_for_each_entry_safe(iter, tmp, &session_list->head, list) {
102 session_destroy(iter);
103 }
104 session_unlock_list();
105
106 /* Session list must be 0 */
107 assert(!session_list_count());
108 }
109
110 /*
111 * Test creation of 1 session
112 */
113 static int create_one_session(const char *name)
114 {
115 int ret;
116 enum lttng_error_code ret_code;
117 struct ltt_session *session = NULL;
118
119 session_lock_list();
120 ret_code = session_create(name, geteuid(), getegid(), &session);
121 session_put(session);
122 if (ret_code == LTTNG_OK) {
123 /* Validate */
124 ret = find_session_name(name);
125 if (ret < 0) {
126 /* Session not found by name */
127 printf("session not found after creation\n");
128 ret = -1;
129 } else {
130 /* Success */
131 ret = 0;
132 }
133 } else {
134 if (ret_code == LTTNG_ERR_EXIST_SESS) {
135 printf("(session already exists) ");
136 }
137 ret = -1;
138 }
139
140 session_unlock_list();
141 return ret;
142 }
143
144 /*
145 * Test deletion of 1 session
146 */
147 static int destroy_one_session(struct ltt_session *session)
148 {
149 int ret;
150 char session_name[NAME_MAX];
151
152 strncpy(session_name, session->name, sizeof(session_name));
153 session_name[sizeof(session_name) - 1] = '\0';
154
155 session_destroy(session);
156 session_put(session);
157
158 ret = find_session_name(session_name);
159 if (ret < 0) {
160 /* Success, -1 means that the sesion is NOT found */
161 ret = 0;
162 } else {
163 /* Fail */
164 ret = -1;
165 }
166 return ret;
167 }
168
169 /*
170 * This test is supposed to fail at the second create call. If so, return 0 for
171 * test success, else -1.
172 */
173 static int two_session_same_name(void)
174 {
175 int ret;
176 struct ltt_session *sess;
177
178 ret = create_one_session(SESSION1);
179 if (ret < 0) {
180 /* Fail */
181 ret = -1;
182 goto end;
183 }
184
185 session_lock_list();
186 sess = session_find_by_name(SESSION1);
187 if (sess) {
188 /* Success */
189 session_put(sess);
190 session_unlock_list();
191 ret = 0;
192 goto end_unlock;
193 } else {
194 /* Fail */
195 ret = -1;
196 goto end_unlock;
197 }
198 end_unlock:
199 session_unlock_list();
200 end:
201 return ret;
202 }
203
204 static void test_session_list(void)
205 {
206 session_list = session_get_list();
207 ok(session_list != NULL, "Session list: not NULL");
208 }
209
210 static void test_create_one_session(void)
211 {
212 ok(create_one_session(SESSION1) == 0,
213 "Create session: %s",
214 SESSION1);
215 }
216
217 static void test_validate_session(void)
218 {
219 struct ltt_session *tmp;
220
221 session_lock_list();
222 tmp = session_find_by_name(SESSION1);
223
224 ok(tmp != NULL,
225 "Validating session: session found");
226
227 if (tmp) {
228 ok(tmp->kernel_session == NULL &&
229 strlen(tmp->name),
230 "Validating session: basic sanity check");
231 } else {
232 skip(1, "Skipping session validation check as session was not found");
233 goto end;
234 }
235
236 session_lock(tmp);
237 session_unlock(tmp);
238 session_put(tmp);
239 end:
240 session_unlock_list();
241 }
242
243 static void test_destroy_session(void)
244 {
245 struct ltt_session *tmp;
246
247 session_lock_list();
248 tmp = session_find_by_name(SESSION1);
249
250 ok(tmp != NULL,
251 "Destroying session: session found");
252
253 if (tmp) {
254 ok(destroy_one_session(tmp) == 0,
255 "Destroying session: %s destroyed",
256 SESSION1);
257 } else {
258 skip(1, "Skipping session destruction as it was not found");
259 }
260 session_unlock_list();
261 }
262
263 static void test_duplicate_session(void)
264 {
265 ok(two_session_same_name() == 0,
266 "Duplicate session creation");
267 }
268
269 static void test_session_name_generation(void)
270 {
271 struct ltt_session *session = NULL;
272 enum lttng_error_code ret_code;
273 const char *expected_session_name_prefix = DEFAULT_SESSION_NAME;
274
275 session_lock_list();
276 ret_code = session_create(NULL, geteuid(), getegid(), &session);
277 ok(ret_code == LTTNG_OK,
278 "Create session with a NULL name (auto-generate a name)");
279 if (!session) {
280 skip(1, "Skipping session name generation tests as session_create() failed.");
281 goto end;
282 }
283 diag("Automatically-generated session name: %s", *session->name ?
284 session->name : "ERROR");
285 ok(*session->name && !strncmp(expected_session_name_prefix, session->name,
286 sizeof(DEFAULT_SESSION_NAME) - 1),
287 "Auto-generated session name starts with %s",
288 DEFAULT_SESSION_NAME);
289 end:
290 session_put(session);
291 session_unlock_list();
292 }
293
294 static void test_large_session_number(void)
295 {
296 int ret, i, failed = 0;
297 struct ltt_session *iter, *tmp;
298
299 for (i = 0; i < MAX_SESSIONS; i++) {
300 char *tmp_name = get_random_string();
301 ret = create_one_session(tmp_name);
302 if (ret < 0) {
303 diag("session %d (name: %s) creation failed", i, tmp_name);
304 ++failed;
305 }
306 }
307
308 ok(failed == 0,
309 "Large sessions number: created %u sessions",
310 MAX_SESSIONS);
311
312 failed = 0;
313
314 session_lock_list();
315 for (i = 0; i < MAX_SESSIONS; i++) {
316 cds_list_for_each_entry_safe(iter, tmp, &session_list->head, list) {
317 assert(session_get(iter));
318 ret = destroy_one_session(iter);
319 if (ret < 0) {
320 diag("session %d destroy failed", i);
321 ++failed;
322 }
323 }
324 }
325 session_unlock_list();
326
327 ok(failed == 0 && session_list_count() == 0,
328 "Large sessions number: destroyed %u sessions",
329 MAX_SESSIONS);
330 }
331
332 int main(int argc, char **argv)
333 {
334 struct lttng_thread *ht_cleanup_thread;
335
336 plan_tests(NUM_TESTS);
337
338 health_sessiond = health_app_create(NR_HEALTH_SESSIOND_TYPES);
339 ht_cleanup_thread = launch_ht_cleanup_thread();
340 assert(ht_cleanup_thread);
341 lttng_thread_put(ht_cleanup_thread);
342
343 diag("Sessions unit tests");
344
345 rcu_register_thread();
346
347 test_session_list();
348
349 test_create_one_session();
350
351 test_validate_session();
352
353 test_destroy_session();
354
355 test_duplicate_session();
356
357 empty_session_list();
358
359 test_session_name_generation();
360
361 test_large_session_number();
362
363 rcu_unregister_thread();
364 lttng_thread_list_shutdown_orphans();
365
366 return exit_status();
367 }
This page took 0.054169 seconds and 4 git commands to generate.