2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
15 #include <sys/types.h>
22 #include <sys/types.h>
26 #include <common/compat/directory-handle.h>
27 #include <common/error.h>
28 #include <common/fd-tracker/fd-tracker.h>
31 int lttng_opt_quiet
= 1;
32 int lttng_opt_verbose
;
35 /* Number of TAP tests in this file */
37 /* 3 for stdin, stdout, and stderr */
38 #define STDIO_FD_COUNT 3
39 #define TRACKER_FD_LIMIT 50
40 #define TMP_DIR_PATTERN "/tmp/fd-tracker-XXXXXX"
41 #define TEST_UNLINK_DIRECTORY_NAME "unlinked_files"
44 * Count of fds, beyond stdin, stderr, stdout that were open
45 * at the launch of the test. This allows the test to succeed when
46 * run by automake's test runner or valgrind which both open
47 * fds behind our back.
49 int unknown_fds_count
;
51 const char file_contents
[] = "Bacon ipsum dolor amet jerky drumstick sirloin "
52 "strip steak venison boudin filet mignon picanha doner shoulder. "
53 "Strip steak brisket alcatra, venison beef chuck cupim pastrami. "
54 "Landjaeger tri-tip salami leberkas ball tip, ham hock chuck sausage "
55 "flank jerky cupim. Pig bacon chuck pancetta andouille.";
57 void get_temporary_directories(char **_test_directory
, char **_unlink_directory
)
60 char tmp_path_pattern
[] = TMP_DIR_PATTERN
;
63 output_dir
= mkdtemp(tmp_path_pattern
);
65 diag("Failed to create temporary path of the form %s",
70 *_test_directory
= strdup(output_dir
);
71 assert(*_test_directory
);
72 ret
= asprintf(_unlink_directory
, "%s/%s", output_dir
,
73 TEST_UNLINK_DIRECTORY_NAME
);
85 dir
= opendir("/proc/self/fd");
87 perror("# Failed to enumerate /proc/self/fd/ to count the number of used file descriptors");
92 while ((entry
= readdir(dir
)) != NULL
) {
93 if (!strcmp(entry
->d_name
, ".") || !strcmp(entry
->d_name
, "..")) {
98 /* Don't account for the file descriptor opened by opendir(). */
101 perror("# Failed to close test program's self/fd directory file descriptor");
108 void check_fd_count(int expected_count
)
113 ok(count
== expected_count
, "Expected %d open file descriptors (%d are open)",
114 expected_count
, count
);
118 int noop_open(void *data
, int *fds
)
120 *fds
= *((int *) data
);
125 int noop_close(void *data
, int *fds
)
131 void track_std_fds(struct fd_tracker
*tracker
)
134 struct { int fd
; const char *name
; } files
[] = {
135 { .fd
= fileno(stdin
), .name
= "stdin" },
136 { .fd
= fileno(stdout
), .name
= "stdout" },
137 { .fd
= fileno(stderr
), .name
= "stderr" },
140 for (i
= 0; i
< sizeof(files
) / sizeof(*files
); i
++) {
143 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
144 &files
[i
].name
, 1, noop_open
, &files
[i
].fd
);
145 assert(out_fd
== files
[i
].fd
);
147 ok(ret
== 0, "Track unsuspendable fd %d (%s)", files
[i
].fd
,
153 void untrack_std_fds(struct fd_tracker
*tracker
)
156 struct { int fd
; const char *name
; } files
[] = {
157 { .fd
= fileno(stdin
), .name
= "stdin" },
158 { .fd
= fileno(stdout
), .name
= "stdout" },
159 { .fd
= fileno(stderr
), .name
= "stderr" },
161 unsigned int fds_set_to_minus_1
= 0;
163 for (i
= 0; i
< sizeof(files
) / sizeof(*files
); i
++) {
164 int fd
= files
[i
].fd
;
165 int ret
= fd_tracker_close_unsuspendable_fd(tracker
,
166 &files
[i
].fd
, 1, noop_close
, NULL
);
168 ok(ret
== 0, "Untrack unsuspendable fd %d (%s)", fd
,
170 fds_set_to_minus_1
+= (files
[i
].fd
== -1);
175 * Basic test opening and closing three unsuspendable fds.
178 void test_unsuspendable_basic(void)
181 struct fd_tracker
*tracker
;
182 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
184 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
186 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
187 ok(tracker
, "Created an fd tracker with a limit of %d simulateously opened file descriptors",
193 track_std_fds(tracker
);
194 untrack_std_fds(tracker
);
196 fd_tracker_destroy(tracker
);
197 ret
= rmdir(test_directory
);
198 ok(ret
== 0, "Test directory is empty");
199 free(test_directory
);
200 free(unlinked_files_directory
);
204 int error_open(void *data
, int *fds
)
206 return *((int *) data
);
210 int error_close(void *data
, int *fds
)
212 return *((int *) data
);
216 * Validate that user callback return values are returned to the
217 * caller of the fd tracker.
220 void test_unsuspendable_cb_return(void)
222 int ret
, stdout_fd
= fileno(stdout
), out_fd
= 42;
223 struct fd_tracker
*tracker
;
224 int expected_error
= -ENETDOWN
;
225 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
227 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
229 tracker
= fd_tracker_create(test_directory
, TRACKER_FD_LIMIT
);
232 /* The error_open callback should fail and return 'expected_error'. */
233 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
234 NULL
, 1, error_open
, &expected_error
);
235 ok(ret
== expected_error
, "fd_tracker_open_unsuspendable_fd() forwards the user callback's error code");
236 ok(out_fd
== 42, "Output fd parameter is unaffected on error of fd_tracker_open_unsuspendable_fd()");
239 * Track a valid fd since we don't want the tracker to fail with an
240 * invalid fd error for this test.
242 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
243 NULL
, 1, noop_open
, &stdout_fd
);
244 ok(out_fd
== stdout_fd
, "fd_tracker_open_unsuspendable_fd() sets the output fd parameter to the newly-tracked fd's value");
247 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
248 &stdout_fd
, 1, error_close
, &expected_error
);
249 ok(ret
== expected_error
, "fd_tracker_close_unsuspendable_fd() forwards the user callback's error code");
250 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
251 &stdout_fd
, 1, noop_close
, &expected_error
);
254 fd_tracker_destroy(tracker
);
255 ret
= rmdir(test_directory
);
256 ok(ret
== 0, "Test directory is empty");
257 free(test_directory
);
258 free(unlinked_files_directory
);
262 * Validate that the tracker refuses to track two identical unsuspendable
266 void test_unsuspendable_duplicate(void)
268 int ret
, stdout_fd
= fileno(stdout
), out_fd
;
269 struct fd_tracker
*tracker
;
270 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
272 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
274 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
277 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
278 NULL
, 1, noop_open
, &stdout_fd
);
280 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
281 NULL
, 1, noop_open
, &stdout_fd
);
282 ok(ret
== -EEXIST
, "EEXIST reported on open of an already tracked file descriptor");
284 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
285 &stdout_fd
, 1, noop_close
, NULL
);
288 fd_tracker_destroy(tracker
);
289 ret
= rmdir(test_directory
);
290 ok(ret
== 0, "Test directory is empty");
291 free(test_directory
);
292 free(unlinked_files_directory
);
296 int open_pipes(void *data
, int *out_fds
)
299 const unsigned int pipe_count
= TRACKER_FD_LIMIT
/ 2;
301 for (i
= 0; i
< pipe_count
; i
++) {
302 int ret
= pipe(&out_fds
[i
* 2]);
312 int close_pipes(void *data
, int *fds
)
317 for (i
= 0; i
< TRACKER_FD_LIMIT
; i
++) {
318 int ret
= close(pipes
[i
]);
328 * Validate that the tracker enforces the open file descriptor limit
329 * when unsuspendable file descritptors are being opened.
332 void test_unsuspendable_limit(void)
334 struct fd_tracker
*tracker
;
335 int ret
, stdout_fd
= fileno(stdout
), out_fd
;
336 int fds
[TRACKER_FD_LIMIT
];
337 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
339 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
341 /* This test assumes TRACKER_FD_LIMIT is a multiple of 2. */
342 assert((TRACKER_FD_LIMIT
% 2 == 0) && TRACKER_FD_LIMIT
);
344 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
347 ret
= fd_tracker_open_unsuspendable_fd(tracker
, fds
,
348 NULL
, TRACKER_FD_LIMIT
, open_pipes
, NULL
);
349 ok(ret
== 0, "File descriptor tracker allowed the user to meet its limit with unsuspendable file descritptors (%d)",
352 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
353 NULL
, 1, noop_open
, &stdout_fd
);
354 ok(ret
== -EMFILE
, "EMFILE reported when exceeding the file descriptor limit while opening an unsuspendable fd");
356 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
357 fds
, TRACKER_FD_LIMIT
, close_pipes
, NULL
);
360 fd_tracker_destroy(tracker
);
361 ret
= rmdir(test_directory
);
362 ok(ret
== 0, "Test directory is empty");
363 free(test_directory
);
364 free(unlinked_files_directory
);
368 * Validate that the tracker refuses to track two identical unsuspendable
372 void test_unsuspendable_close_untracked(void)
374 int ret
, stdout_fd
= fileno(stdout
), unknown_fds
[2], out_fd
;
375 struct fd_tracker
*tracker
;
376 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
378 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
380 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
385 ret
= pipe(unknown_fds
);
387 assert(close(unknown_fds
[0]) == 0);
388 assert(close(unknown_fds
[1]) == 0);
390 ret
= fd_tracker_open_unsuspendable_fd(tracker
, &out_fd
,
391 NULL
, 1, noop_open
, &stdout_fd
);
394 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
395 unknown_fds
, 1, noop_close
, NULL
);
396 ok(ret
== -EINVAL
, "EINVAL reported on close of an untracked file descriptor");
398 ret
= fd_tracker_close_unsuspendable_fd(tracker
,
399 &stdout_fd
, 1, noop_close
, NULL
);
402 fd_tracker_destroy(tracker
);
403 ret
= rmdir(test_directory
);
404 ok(ret
== 0, "Test directory is empty");
405 free(test_directory
);
406 free(unlinked_files_directory
);
409 static int open_files(struct fd_tracker
*tracker
,
410 struct lttng_directory_handle
*directory
,
412 struct fs_handle
**handles
,
418 for (i
= 0; i
< count
; i
++) {
421 struct fs_handle
*handle
;
422 mode_t mode
= S_IWUSR
| S_IRUSR
;
424 p_ret
= asprintf(&file_path
, "file-%u", i
);
426 file_paths
[i
] = file_path
;
428 handle
= fd_tracker_open_fs_handle(tracker
, directory
, file_path
,
429 O_RDWR
| O_CREAT
, &mode
);
439 static int open_same_file(struct fd_tracker
*tracker
,
440 struct lttng_directory_handle
*directory
,
443 struct fs_handle
**handles
)
448 for (i
= 0; i
< count
; i
++) {
449 struct fs_handle
*handle
;
450 mode_t mode
= S_IWUSR
| S_IRUSR
;
452 handle
= fd_tracker_open_fs_handle(tracker
, directory
, file
,
453 O_RDWR
| O_CREAT
, &mode
);
464 int cleanup_files(struct fd_tracker
*tracker
, const char *dir
,
465 unsigned int count
, struct fs_handle
**handles
,
471 for (i
= 0; i
< count
; i
++) {
472 char *file_path
= file_paths
[i
];
477 if (fs_handle_unlink(handles
[i
])) {
478 diag("Failed to unlink fs_handle to file %s", file_path
);
481 if (fs_handle_close(handles
[i
])) {
482 diag("Failed to close fs_handle to file %s", file_path
);
491 void test_suspendable_limit(void)
494 const int files_to_create
= TRACKER_FD_LIMIT
* 10;
495 struct fd_tracker
*tracker
;
496 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
497 char *output_files
[files_to_create
];
498 struct fs_handle
*handles
[files_to_create
];
499 struct lttng_directory_handle
*dir_handle
= NULL
;
500 int dir_handle_fd_count
;
502 memset(output_files
, 0, sizeof(output_files
));
503 memset(handles
, 0, sizeof(handles
));
505 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
507 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
512 dir_handle
= lttng_directory_handle_create(test_directory
);
514 dir_handle_fd_count
= !!lttng_directory_handle_uses_fd(dir_handle
);
516 ret
= open_files(tracker
, dir_handle
, files_to_create
, handles
,
518 ok(!ret
, "Created %d files with a limit of %d simultaneously-opened file descriptor",
519 files_to_create
, TRACKER_FD_LIMIT
);
520 check_fd_count(TRACKER_FD_LIMIT
+ STDIO_FD_COUNT
+ unknown_fds_count
+
521 dir_handle_fd_count
);
523 ret
= cleanup_files(tracker
, test_directory
, files_to_create
, handles
,
525 ok(!ret
, "Close all opened filesystem handles");
526 ret
= rmdir(test_directory
);
527 ok(ret
== 0, "Test directory is empty");
528 fd_tracker_destroy(tracker
);
529 lttng_directory_handle_put(dir_handle
);
530 free(test_directory
);
531 free(unlinked_files_directory
);
535 void test_mixed_limit(void)
538 const int files_to_create
= TRACKER_FD_LIMIT
;
539 struct fd_tracker
*tracker
;
540 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
541 char *output_files
[files_to_create
];
542 struct fs_handle
*handles
[files_to_create
];
543 struct lttng_directory_handle
*dir_handle
= NULL
;
544 int dir_handle_fd_count
;
546 memset(output_files
, 0, sizeof(output_files
));
547 memset(handles
, 0, sizeof(handles
));
549 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
551 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
556 dir_handle
= lttng_directory_handle_create(test_directory
);
558 dir_handle_fd_count
= !!lttng_directory_handle_uses_fd(dir_handle
);
560 ret
= open_files(tracker
, dir_handle
, files_to_create
, handles
,
562 ok(!ret
, "Created %d files with a limit of %d simultaneously-opened file descriptor",
563 files_to_create
, TRACKER_FD_LIMIT
);
564 diag("Check file descriptor count after opening %u files", files_to_create
);
565 check_fd_count(TRACKER_FD_LIMIT
+ STDIO_FD_COUNT
+ unknown_fds_count
+
566 dir_handle_fd_count
);
569 * Open unsuspendable fds (stdin, stdout, stderr) and verify that the fd
570 * cap is still respected.
572 diag("Check file descriptor count after adding %d unsuspendable fds",
574 track_std_fds(tracker
);
575 check_fd_count(TRACKER_FD_LIMIT
+ unknown_fds_count
+
576 dir_handle_fd_count
);
577 diag("Untrack unsuspendable file descriptors");
578 untrack_std_fds(tracker
);
579 check_fd_count(TRACKER_FD_LIMIT
+ unknown_fds_count
+
580 dir_handle_fd_count
);
582 ret
= cleanup_files(tracker
, test_directory
, files_to_create
, handles
,
584 ok(!ret
, "Close all opened filesystem handles");
585 ret
= rmdir(test_directory
);
586 ok(ret
== 0, "Test directory is empty");
587 fd_tracker_destroy(tracker
);
588 lttng_directory_handle_put(dir_handle
);
589 free(test_directory
);
590 free(unlinked_files_directory
);
594 * Open more files than allowed by the fd tracker's cap and write,
595 * byte-by-byte, and in round-robin, a string. The goal is to force
596 * the fd tracker to suspend and resume the fs_handles often and
597 * verify that the fd cap is always respected.
599 * The content of the files is also verified at the end.
602 void test_suspendable_restore(void)
605 const int files_to_create
= TRACKER_FD_LIMIT
* 10;
606 struct fd_tracker
*tracker
;
607 char *output_files
[files_to_create
];
608 struct fs_handle
*handles
[files_to_create
];
609 size_t content_index
;
611 bool write_success
= true;
612 bool fd_cap_respected
= true;
613 bool content_ok
= true;
614 struct lttng_directory_handle
*dir_handle
= NULL
;
615 int dir_handle_fd_count
;
616 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
618 memset(output_files
, 0, sizeof(output_files
));
619 memset(handles
, 0, sizeof(handles
));
621 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
623 tracker
= fd_tracker_create(unlinked_files_directory
, TRACKER_FD_LIMIT
);
628 dir_handle
= lttng_directory_handle_create(test_directory
);
630 dir_handle_fd_count
= !!lttng_directory_handle_uses_fd(dir_handle
);
632 ret
= open_files(tracker
, dir_handle
, files_to_create
, handles
,
634 ok(!ret
, "Created %d files with a limit of %d simultaneously-opened file descriptor",
635 files_to_create
, TRACKER_FD_LIMIT
);
636 diag("Check file descriptor count after opening %u files", files_to_create
);
637 check_fd_count(TRACKER_FD_LIMIT
+ STDIO_FD_COUNT
+ unknown_fds_count
+
638 dir_handle_fd_count
);
640 for (content_index
= 0; content_index
< sizeof(file_contents
); content_index
++) {
641 for (handle_index
= 0; handle_index
< files_to_create
; handle_index
++) {
643 struct fs_handle
*handle
= handles
[handle_index
];
644 const char *path
= output_files
[handle_index
];
646 fd
= fs_handle_get_fd(handle
);
648 write_success
= false;
649 diag("Failed to restore fs_handle to %s",
655 ret
= write(fd
, file_contents
+ content_index
, 1);
656 } while (ret
< 0 && errno
== EINTR
);
659 write_success
= false;
660 PERROR("write() to %s failed", path
);
664 if (fd_count() > (TRACKER_FD_LIMIT
+ STDIO_FD_COUNT
+
666 dir_handle_fd_count
)) {
667 fd_cap_respected
= false;
670 fs_handle_put_fd(handle
);
674 ok(write_success
, "Wrote reference string to %d files",
676 ok(fd_cap_respected
, "FD tracker enforced the file descriptor cap");
678 /* Validate the contents of the files. */
679 for (handle_index
= 0; handle_index
< files_to_create
; handle_index
++) {
681 const char *path
= output_files
[handle_index
];
682 char read_buf
[sizeof(file_contents
)];
684 size_t to_read
= sizeof(read_buf
);
687 fd
= lttng_directory_handle_open_file(
688 dir_handle
, path
, O_RDONLY
, 0);
690 ret
= fstat(fd
, &fd_stat
);
692 if (fd_stat
.st_size
!= sizeof(file_contents
)) {
693 diag("Content size of file %s doesn't match, got %" PRId64
", expected %zu",
694 path
, (int64_t) fd_stat
.st_size
,
695 sizeof(file_contents
));
703 ret
= read(fd
, read_pos
, to_read
);
708 } while (to_read
&& (ret
< 0 && errno
== EINTR
));
711 PERROR("Failed to read file %s", path
);
716 if (strcmp(file_contents
, read_buf
)) {
718 diag("File content doesn't match the expectated string");
724 ok(content_ok
, "Files contain the expected content");
725 ret
= cleanup_files(tracker
, test_directory
, files_to_create
, handles
,
727 ok(!ret
, "Close all opened filesystem handles");
728 ret
= rmdir(test_directory
);
729 ok(ret
== 0, "Test directory is empty");
730 fd_tracker_destroy(tracker
);
731 lttng_directory_handle_put(dir_handle
);
732 free(test_directory
);
733 free(unlinked_files_directory
);
737 void test_unlink(void)
740 struct fd_tracker
*tracker
;
741 const int handles_to_open
= 2;
742 struct fs_handle
*handles
[handles_to_open
];
743 struct fs_handle
*new_handle
= NULL
;
745 struct lttng_directory_handle
*dir_handle
= NULL
;
746 const char file_name
[] = "my_file";
747 char *test_directory
= NULL
, *unlinked_files_directory
= NULL
;
748 char *unlinked_file_zero
= NULL
, *unlinked_file_one
= NULL
;
751 get_temporary_directories(&test_directory
, &unlinked_files_directory
);
752 ret
= asprintf(&unlinked_file_zero
, "%s/%u", unlinked_files_directory
,
755 ret
= asprintf(&unlinked_file_one
, "%s/%u", unlinked_files_directory
,
759 tracker
= fd_tracker_create(unlinked_files_directory
, 1);
764 dir_handle
= lttng_directory_handle_create(test_directory
);
767 /* Open two handles to the same file. */
768 ret
= open_same_file(tracker
, dir_handle
, file_name
, handles_to_open
,
770 ok(!ret
, "Successfully opened %i handles to %s/%s", handles_to_open
,
771 test_directory
, file_name
);
777 * Unlinking the first handle should cause the file to be renamed
780 ret
= fs_handle_unlink(handles
[0]);
781 ok(!ret
, "Successfully unlinked the first handle to %s/%s",
782 test_directory
, file_name
);
785 * The original file should no longer exist on the file system, and a
786 * new file named '0' should exist.
788 ok(lttng_directory_handle_stat(dir_handle
, file_name
, &statbuf
) == -1 &&
790 "%s no longer present on file system after unlink",
792 ok(lttng_directory_handle_stat(
793 dir_handle
, unlinked_file_zero
, &statbuf
) == 0,
794 "%s exists on file system after unlink",
798 * It should be possible to use the file descriptors of both handles.
799 * Since only one file descriptor can be opened at once, this should
800 * force the fd_tracker to suspend and restore the handles.
802 fd
= fs_handle_get_fd(handles
[0]);
803 ok(fd
>= 0, "Got fd from first handle");
805 fd
= fs_handle_get_fd(handles
[1]);
806 ok (fd
< 0, "fd tracker does not allow two fds to be used at once");
808 fs_handle_put_fd(handles
[0]);
809 fd
= fs_handle_get_fd(handles
[1]);
810 ok(fd
>= 0, "Got fd from second handle");
811 fs_handle_put_fd(handles
[1]);
813 /* The second unlink should fail with -ENOENT. */
814 ret
= fs_handle_unlink(handles
[1]);
816 "ENOENT is reported when attempting to unlink the second handle to %s/%s",
817 test_directory
, file_name
);
820 * Opening a new handle to 'my_file' should succeed.
822 ret
= open_same_file(tracker
, dir_handle
, file_name
, 1, &new_handle
);
823 ok(!ret
, "Successfully opened a new handle to previously unlinked file %s/%s",
824 test_directory
, file_name
);
828 * Unlinking the new handle should cause the file to be renamed
829 * to '1' since '0' already exists.
831 ret
= fs_handle_unlink(new_handle
);
832 ok(!ret
, "Successfully unlinked the new handle handle to %s/%s",
833 test_directory
, file_name
);
834 ok(stat(unlinked_file_one
, &statbuf
) == 0,
835 "%s exists on file system after unlink",
838 ret
= fs_handle_close(handles
[0]);
839 ok(!ret
, "Successfully closed the first handle");
840 ret
= fs_handle_close(handles
[1]);
841 ok(!ret
, "Successfully closed the second handle");
842 ret
= fs_handle_close(new_handle
);
843 ok(!ret
, "Successfully closed the third handle");
845 ok(lttng_directory_handle_stat(dir_handle
, file_name
, &statbuf
) == -1 &&
847 "%s no longer present on file system after handle close",
849 ok(lttng_directory_handle_stat(
850 dir_handle
, unlinked_file_zero
, &statbuf
) == -1 &&
852 "%s no longer present on file system after handle close",
854 ok(lttng_directory_handle_stat(dir_handle
, unlinked_file_one
,
857 "%s no longer present on file system after handle close",
860 ret
= rmdir(test_directory
);
861 ok(ret
== 0, "Test directory is empty");
862 fd_tracker_destroy(tracker
);
863 free(test_directory
);
864 free(unlinked_files_directory
);
865 free(unlinked_file_zero
);
866 free(unlinked_file_one
);
867 lttng_directory_handle_put(dir_handle
);
870 int main(int argc
, char **argv
)
872 plan_tests(NUM_TESTS
);
873 diag("File descriptor tracker unit tests");
875 rcu_register_thread();
877 unknown_fds_count
= fd_count() - STDIO_FD_COUNT
;
878 assert(unknown_fds_count
>= 0);
880 diag("Unsuspendable - basic");
881 test_unsuspendable_basic();
882 diag("Unsuspendable - callback return values");
883 test_unsuspendable_cb_return();
884 diag("Unsuspendable - duplicate file descriptors");
885 test_unsuspendable_duplicate();
886 diag("Unsuspendable - closing an untracked file descriptor");
887 test_unsuspendable_close_untracked();
888 diag("Unsuspendable - check that file descritptor limit is enforced");
889 test_unsuspendable_limit();
891 diag("Suspendable - check that file descritptor limit is enforced");
892 test_suspendable_limit();
893 diag("Suspendable - restoration test");
894 test_suspendable_restore();
896 diag("Mixed - check that file descritptor limit is enforced");
899 diag("Suspendable - Unlinking test");
903 rcu_unregister_thread();
904 return exit_status();