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