xref: /llvm-project/compiler-rt/test/profile/ContinuousSyncMode/set-file-object.c (revision 45e1a38a10371b3ccf2a2199a0c16c6112751a3d)
1 // REQUIRES: target={{.*(darwin|linux|solaris|aix).*}}
2 
3 // Test using __llvm_profile_set_file_object in continuous mode (%c).
4 // Create & cd into a temporary directory.
5 // RUN: rm -rf %t.dir && mkdir -p %t.dir && cd %t.dir
6 
7 // The -mllvm -runtime-counter-relocation=true flag has effect only on linux.
8 // RUN: %clang -fprofile-instr-generate -fcoverage-mapping -fprofile-update=atomic -mllvm -runtime-counter-relocation=true -o main.exe %s
9 
10 // Test continuous mode with __llvm_profile_set_file_object with mergin disabled.
11 // RUN: env LLVM_PROFILE_FILE="%t.dir/profdir/%c%mprofraw.old" %run  %t.dir/main.exe nomerge %t.dir/profdir/profraw.new 2>&1 | FileCheck %s -check-prefix=WARN
12 // WARN: LLVM Profile Warning: __llvm_profile_set_file_object(fd={{[0-9]+}}) not supported in continuous sync mode when merging is disabled
13 
14 // Test continuous mode with __llvm_profile_set_file_object with mergin enabled.
15 // RUN: rm -rf %t.dir/profdir/
16 // RUN: env LLVM_PROFILE_FILE="%t.dir/profdir/%c%mprofraw.old" %run  %t.dir/main.exe merge %t.dir/profdir/profraw.new 'LLVM_PROFILE_FILE=%t.dir/profdir/%c%m.profraw'
17 // RUN: llvm-profdata merge -o %t.dir/profdir/profdata %t.dir/profdir/profraw.new
18 // RUN: llvm-profdata show --counts --all-functions %t.dir/profdir/profdata | FileCheck %s -check-prefix=MERGE
19 // RUN: llvm-profdata show --counts --all-functions %t.dir/profdir/*profraw.old | FileCheck %s -check-prefix=ZERO
20 
21 // Test __llvm_profile_set_file_object with mergin enabled and continuous mode disabled.
22 // RUN: rm -rf %t.dir/profdir/
23 // RUN: env LLVM_PROFILE_FILE="%t.dir/profdir/%mprofraw.old" %run  %t.dir/main.exe merge %t.dir/profdir/profraw.new 'LLVM_PROFILE_FILE=%t.dir/profdir/%m.profraw'
24 // RUN: llvm-profdata merge -o %t.dir/profdir/profdata %t.dir/profdir/profraw.new
25 // RUN: llvm-profdata show --counts --all-functions %t.dir/profdir/profdata | FileCheck %s -check-prefix=MERGE
26 // RUN: llvm-profdata show --counts --all-functions %t.dir/profdir/*profraw.old | FileCheck %s -check-prefix=ZERO
27 
28 // MERGE: Counters:
29 // MERGE:   coverage_test:
30 // MERGE:     Hash: {{.*}}
31 // MERGE:     Counters: 1
32 // MERGE:     Function count: 32
33 // MERGE:     Block counts: []
34 // MERGE: Instrumentation level: Front-end
35 
36 // ZERO: Counters:
37 // ZERO:   coverage_test:
38 // ZERO:     Hash: {{.*}}
39 // ZERO:     Counters: 1
40 // ZERO:     Function count: 0
41 // ZERO:     Block counts: []
42 // ZERO: Instrumentation level: Front-end
43 
44 #include <spawn.h>
45 #include <stdio.h>
46 #include <string.h>
47 
48 #include <sys/types.h>
49 #include <sys/wait.h>
50 
51 const int num_child_procs_to_spawn = 32;
52 
53 extern int __llvm_profile_is_continuous_mode_enabled(void);
54 extern int __llvm_profile_set_file_object(FILE *, int);
55 
56 int coverage_test() {
57   return 0;
58 }
59 
60 int main(int argc, char **argv) {
61   char *file_name = argv[2];
62   FILE *file = NULL;
63   if (strcmp(argv[1], "nomerge") == 0) {
64     file = fopen(file_name, "a+b");
65     __llvm_profile_set_file_object(file, 0);
66   }
67   else if (strcmp(argv[1], "merge") == 0) {
68     // Parent process.
69     int I;
70     pid_t child_pids[num_child_procs_to_spawn];
71     char *const child_argv[] = {argv[0], "set", file_name, NULL};
72     char *const child_envp[] = {argv[3], NULL};
73     FILE *file = fopen(file_name, "w+");
74     fclose(file);
75     for (I = 0; I < num_child_procs_to_spawn; ++I) {
76       int ret =
77           posix_spawn(&child_pids[I], argv[0], NULL, NULL, child_argv, child_envp);
78       if (ret != 0) {
79         fprintf(stderr, "Child %d could not be spawned: ret = %d, msg = %s\n",
80                 I, ret, strerror(ret));
81         return 1;
82       }
83     }
84     for (I = 0; I < num_child_procs_to_spawn; ++I) {
85       int status;
86       pid_t waited_pid = waitpid(child_pids[I], &status, 0);
87       if (waited_pid != child_pids[I]) {
88         fprintf(stderr, "Failed to wait on child %d\n", I);
89         return 1;
90       }
91       if (!WIFEXITED(status)) {
92         fprintf(stderr, "Child %d did not terminate normally\n", I);
93         return 1;
94       }
95       int return_status = WEXITSTATUS(status);
96       if (return_status != 0) {
97         fprintf(stderr, "Child %d exited with non zero status %d\n", I,
98                 return_status);
99         return 1;
100       }
101     }
102   } else if (strcmp(argv[1], "set") == 0) {
103     // Child processes.
104     file = fopen(file_name, "r+b");
105     if (__llvm_profile_set_file_object(file, 1)) {
106       fprintf(stderr, "Call to __llvm_profile_set_file_object failed\n");
107       return 1;
108     }
109     // After set file object, counter should be written into new file.
110     coverage_test();
111   }
112   return 0;
113 }
114