port: FreeBSD has no ENODATA, alias it to ENOATTR
[lttng-tools.git] / tests / unit / test_session.c
... / ...
CommitLineData
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
36static struct ltt_session_list *session_list;
37
38/* For error.h */
39int lttng_opt_quiet = 1;
40int lttng_opt_verbose = 0;
41int lttng_opt_mi;
42
43static const char alphanum[] =
44 "0123456789"
45 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
46 "abcdefghijklmnopqrstuvwxyz";
47static char random_string[RANDOM_STRING_LEN];
48
49/*
50 * Return random string of 10 characters.
51 * Not thread-safe.
52 */
53static 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 */
69static 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
82static 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 */
96static 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 */
113static 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 */
147static 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 */
173static 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 }
198end_unlock:
199 session_unlock_list();
200end:
201 return ret;
202}
203
204static void test_session_list(void)
205{
206 session_list = session_get_list();
207 ok(session_list != NULL, "Session list: not NULL");
208}
209
210static void test_create_one_session(void)
211{
212 ok(create_one_session(SESSION1) == 0,
213 "Create session: %s",
214 SESSION1);
215}
216
217static 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);
239end:
240 session_unlock_list();
241}
242
243static 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
263static void test_duplicate_session(void)
264{
265 ok(two_session_same_name() == 0,
266 "Duplicate session creation");
267}
268
269static 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);
289end:
290 session_put(session);
291 session_unlock_list();
292}
293
294static 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
332int 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.022737 seconds and 4 git commands to generate.