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 | // 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(s1: argv[1], s2: "nomerge" ) == 0) { |
64 | file = fopen(filename: file_name, modes: "a+b" ); |
65 | __llvm_profile_set_file_object(file, 0); |
66 | } |
67 | else if (strcmp(s1: argv[1], s2: "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(filename: file_name, modes: "w+" ); |
74 | fclose(stream: file); |
75 | for (I = 0; I < num_child_procs_to_spawn; ++I) { |
76 | int ret = |
77 | posix_spawn(pid: &child_pids[I], path: argv[0], NULL, NULL, argv: child_argv, envp: child_envp); |
78 | if (ret != 0) { |
79 | fprintf(stderr, format: "Child %d could not be spawned: ret = %d, msg = %s\n" , |
80 | I, ret, strerror(errnum: 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(pid: child_pids[I], stat_loc: &status, options: 0); |
87 | if (waited_pid != child_pids[I]) { |
88 | fprintf(stderr, format: "Failed to wait on child %d\n" , I); |
89 | return 1; |
90 | } |
91 | if (!WIFEXITED(status)) { |
92 | fprintf(stderr, format: "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, format: "Child %d exited with non zero status %d\n" , I, |
98 | return_status); |
99 | return 1; |
100 | } |
101 | } |
102 | } else if (strcmp(s1: argv[1], s2: "set" ) == 0) { |
103 | // Child processes. |
104 | file = fopen(filename: file_name, modes: "r+b" ); |
105 | if (__llvm_profile_set_file_object(file, 1)) { |
106 | fprintf(stderr, format: "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 | |