1 // REQUIRES: darwin || linux
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 -mllvm -instrprof-atomic-counter-update-all=1 -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 // MERGE: Counters:
22 // MERGE: coverage_test:
23 // MERGE: Hash: {{.*}}
24 // MERGE: Counters: 1
25 // MERGE: Function count: 32
26 // MERGE: Block counts: []
27 // MERGE: Instrumentation level: Front-end
28
29 // ZERO: Counters:
30 // ZERO: coverage_test:
31 // ZERO: Hash: {{.*}}
32 // ZERO: Counters: 1
33 // ZERO: Function count: 0
34 // ZERO: Block counts: []
35 // ZERO: Instrumentation level: Front-end
36
37 #include <spawn.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <sys/types.h>
42 #include <sys/wait.h>
43
44 const int num_child_procs_to_spawn = 32;
45
46 extern int __llvm_profile_is_continuous_mode_enabled(void);
47 extern int __llvm_profile_set_file_object(FILE *, int);
48
coverage_test()49 int coverage_test() {
50 return 0;
51 }
52
main(int argc,char ** argv)53 int main(int argc, char **argv) {
54 char *file_name = argv[2];
55 FILE *file = fopen(file_name, "a+b");
56 if (strcmp(argv[1], "nomerge") == 0)
57 __llvm_profile_set_file_object(file, 0);
58 else if (strcmp(argv[1], "merge") == 0) {
59 // Parent process.
60 int I;
61 pid_t child_pids[num_child_procs_to_spawn];
62 char *const child_argv[] = {argv[0], "set", file_name, NULL};
63 char *const child_envp[] = {argv[3], NULL};
64 for (I = 0; I < num_child_procs_to_spawn; ++I) {
65 int ret =
66 posix_spawn(&child_pids[I], argv[0], NULL, NULL, child_argv, child_envp);
67 if (ret != 0) {
68 fprintf(stderr, "Child %d could not be spawned: ret = %d, msg = %s\n",
69 I, ret, strerror(ret));
70 return 1;
71 }
72 }
73 for (I = 0; I < num_child_procs_to_spawn; ++I) {
74 int status;
75 pid_t waited_pid = waitpid(child_pids[I], &status, 0);
76 if (waited_pid != child_pids[I]) {
77 fprintf(stderr, "Failed to wait on child %d\n", I);
78 return 1;
79 }
80 if (!WIFEXITED(status)) {
81 fprintf(stderr, "Child %d did not terminate normally\n", I);
82 return 1;
83 }
84 int return_status = WEXITSTATUS(status);
85 if (return_status != 0) {
86 fprintf(stderr, "Child %d exited with non zero status %d\n", I,
87 return_status);
88 return 1;
89 }
90 }
91 } else if (strcmp(argv[1], "set") == 0) {
92 // Child processes.
93 if (!__llvm_profile_is_continuous_mode_enabled()) {
94 fprintf(stderr, "Continuous mode disabled\n");
95 return 1;
96 }
97 if (__llvm_profile_set_file_object(file, 1)) {
98 fprintf(stderr, "Call to __llvm_profile_set_file_object failed\n");
99 return 1;
100 }
101 // After set file object, counter should be written into new file.
102 coverage_test();
103 }
104 return 0;
105 }
106