1*7c3d14c8STreehugger Robot // Test caller-callee coverage with large number of threads
2*7c3d14c8STreehugger Robot // and various numbers of callers and callees.
3*7c3d14c8STreehugger Robot
4*7c3d14c8STreehugger Robot // RUN: %clangxx_asan -fsanitize-coverage=edge,indirect-calls %s -o %t
5*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
6*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 9 2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
7*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 7 3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
8*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
9*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
10*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 18 3 2>&1 | FileCheck %s --check-prefix=CHECK-18-3
11*7c3d14c8STreehugger Robot // RUN: rm -f caller-callee*.sancov
12*7c3d14c8STreehugger Robot //
13*7c3d14c8STreehugger Robot // REQUIRES: asan-64-bits
14*7c3d14c8STreehugger Robot // UNSUPPORTED: android
15*7c3d14c8STreehugger Robot //
16*7c3d14c8STreehugger Robot // CHECK-10-1: CovDump: 10 caller-callee pairs written
17*7c3d14c8STreehugger Robot // CHECK-9-2: CovDump: 18 caller-callee pairs written
18*7c3d14c8STreehugger Robot // CHECK-7-3: CovDump: 21 caller-callee pairs written
19*7c3d14c8STreehugger Robot // CHECK-17-1: CovDump: 14 caller-callee pairs written
20*7c3d14c8STreehugger Robot // CHECK-15-2: CovDump: 28 caller-callee pairs written
21*7c3d14c8STreehugger Robot // CHECK-18-3: CovDump: 42 caller-callee pairs written
22*7c3d14c8STreehugger Robot
23*7c3d14c8STreehugger Robot #include <stdio.h>
24*7c3d14c8STreehugger Robot #include <stdlib.h>
25*7c3d14c8STreehugger Robot #include <pthread.h>
26*7c3d14c8STreehugger Robot int P = 0;
fFoo27*7c3d14c8STreehugger Robot struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
fFoo128*7c3d14c8STreehugger Robot struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo229*7c3d14c8STreehugger Robot struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo330*7c3d14c8STreehugger Robot struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo431*7c3d14c8STreehugger Robot struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo532*7c3d14c8STreehugger Robot struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo633*7c3d14c8STreehugger Robot struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo734*7c3d14c8STreehugger Robot struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo835*7c3d14c8STreehugger Robot struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo936*7c3d14c8STreehugger Robot struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1037*7c3d14c8STreehugger Robot struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1138*7c3d14c8STreehugger Robot struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1239*7c3d14c8STreehugger Robot struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1340*7c3d14c8STreehugger Robot struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1441*7c3d14c8STreehugger Robot struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1542*7c3d14c8STreehugger Robot struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1643*7c3d14c8STreehugger Robot struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1744*7c3d14c8STreehugger Robot struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1845*7c3d14c8STreehugger Robot struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
fFoo1946*7c3d14c8STreehugger Robot struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
47*7c3d14c8STreehugger Robot
48*7c3d14c8STreehugger Robot Foo *foo[20] = {
49*7c3d14c8STreehugger Robot new Foo, new Foo1, new Foo2, new Foo3, new Foo4, new Foo5, new Foo6,
50*7c3d14c8STreehugger Robot new Foo7, new Foo8, new Foo9, new Foo10, new Foo11, new Foo12, new Foo13,
51*7c3d14c8STreehugger Robot new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
52*7c3d14c8STreehugger Robot };
53*7c3d14c8STreehugger Robot
54*7c3d14c8STreehugger Robot int n_functions = 10;
55*7c3d14c8STreehugger Robot int n_callers = 2;
56*7c3d14c8STreehugger Robot
Thread(void * arg)57*7c3d14c8STreehugger Robot void *Thread(void *arg) {
58*7c3d14c8STreehugger Robot if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
59*7c3d14c8STreehugger Robot if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
60*7c3d14c8STreehugger Robot if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
61*7c3d14c8STreehugger Robot return arg;
62*7c3d14c8STreehugger Robot }
63*7c3d14c8STreehugger Robot
main(int argc,char ** argv)64*7c3d14c8STreehugger Robot int main(int argc, char **argv) {
65*7c3d14c8STreehugger Robot if (argc >= 2)
66*7c3d14c8STreehugger Robot n_functions = atoi(argv[1]);
67*7c3d14c8STreehugger Robot if (argc >= 3)
68*7c3d14c8STreehugger Robot n_callers = atoi(argv[2]);
69*7c3d14c8STreehugger Robot const int kNumThreads = 16;
70*7c3d14c8STreehugger Robot pthread_t t[kNumThreads];
71*7c3d14c8STreehugger Robot for (int i = 0; i < kNumThreads; i++)
72*7c3d14c8STreehugger Robot pthread_create(&t[i], 0, Thread, 0);
73*7c3d14c8STreehugger Robot for (int i = 0; i < kNumThreads; i++)
74*7c3d14c8STreehugger Robot pthread_join(t[i], 0);
75*7c3d14c8STreehugger Robot }
76