1#include "test/jemalloc_test.h"
2
3#include "jemalloc/internal/log.h"
4
5static void
6expect_no_logging(const char *names) {
7	log_var_t log_l1 = LOG_VAR_INIT("l1");
8	log_var_t log_l2 = LOG_VAR_INIT("l2");
9	log_var_t log_l2_a = LOG_VAR_INIT("l2.a");
10
11	strcpy(log_var_names, names);
12
13	int count = 0;
14
15	for (int i = 0; i < 10; i++) {
16		log_do_begin(log_l1)
17			count++;
18		log_do_end(log_l1)
19
20		log_do_begin(log_l2)
21			count++;
22		log_do_end(log_l2)
23
24		log_do_begin(log_l2_a)
25			count++;
26		log_do_end(log_l2_a)
27	}
28	assert_d_eq(count, 0, "Disabled logging not ignored!");
29}
30
31TEST_BEGIN(test_log_disabled) {
32	test_skip_if(!config_log);
33	atomic_store_b(&log_init_done, true, ATOMIC_RELAXED);
34	expect_no_logging("");
35	expect_no_logging("abc");
36	expect_no_logging("a.b.c");
37	expect_no_logging("l12");
38	expect_no_logging("l123|a456|b789");
39	expect_no_logging("|||");
40}
41TEST_END
42
43TEST_BEGIN(test_log_enabled_direct) {
44	test_skip_if(!config_log);
45	atomic_store_b(&log_init_done, true, ATOMIC_RELAXED);
46	log_var_t log_l1 = LOG_VAR_INIT("l1");
47	log_var_t log_l1_a = LOG_VAR_INIT("l1.a");
48	log_var_t log_l2 = LOG_VAR_INIT("l2");
49
50	int count;
51
52	count = 0;
53	strcpy(log_var_names, "l1");
54	for (int i = 0; i < 10; i++) {
55		log_do_begin(log_l1)
56			count++;
57		log_do_end(log_l1)
58	}
59	assert_d_eq(count, 10, "Mis-logged!");
60
61	count = 0;
62	strcpy(log_var_names, "l1.a");
63	for (int i = 0; i < 10; i++) {
64		log_do_begin(log_l1_a)
65			count++;
66		log_do_end(log_l1_a)
67	}
68	assert_d_eq(count, 10, "Mis-logged!");
69
70	count = 0;
71	strcpy(log_var_names, "l1.a|abc|l2|def");
72	for (int i = 0; i < 10; i++) {
73		log_do_begin(log_l1_a)
74			count++;
75		log_do_end(log_l1_a)
76
77		log_do_begin(log_l2)
78			count++;
79		log_do_end(log_l2)
80	}
81	assert_d_eq(count, 20, "Mis-logged!");
82}
83TEST_END
84
85TEST_BEGIN(test_log_enabled_indirect) {
86	test_skip_if(!config_log);
87	atomic_store_b(&log_init_done, true, ATOMIC_RELAXED);
88	strcpy(log_var_names, "l0|l1|abc|l2.b|def");
89
90	/* On. */
91	log_var_t log_l1 = LOG_VAR_INIT("l1");
92	/* Off. */
93	log_var_t log_l1a = LOG_VAR_INIT("l1a");
94	/* On. */
95	log_var_t log_l1_a = LOG_VAR_INIT("l1.a");
96	/* Off. */
97	log_var_t log_l2_a = LOG_VAR_INIT("l2.a");
98	/* On. */
99	log_var_t log_l2_b_a = LOG_VAR_INIT("l2.b.a");
100	/* On. */
101	log_var_t log_l2_b_b = LOG_VAR_INIT("l2.b.b");
102
103	/* 4 are on total, so should sum to 40. */
104	int count = 0;
105	for (int i = 0; i < 10; i++) {
106		log_do_begin(log_l1)
107			count++;
108		log_do_end(log_l1)
109
110		log_do_begin(log_l1a)
111			count++;
112		log_do_end(log_l1a)
113
114		log_do_begin(log_l1_a)
115			count++;
116		log_do_end(log_l1_a)
117
118		log_do_begin(log_l2_a)
119			count++;
120		log_do_end(log_l2_a)
121
122		log_do_begin(log_l2_b_a)
123			count++;
124		log_do_end(log_l2_b_a)
125
126		log_do_begin(log_l2_b_b)
127			count++;
128		log_do_end(log_l2_b_b)
129	}
130
131	assert_d_eq(count, 40, "Mis-logged!");
132}
133TEST_END
134
135TEST_BEGIN(test_log_enabled_global) {
136	test_skip_if(!config_log);
137	atomic_store_b(&log_init_done, true, ATOMIC_RELAXED);
138	strcpy(log_var_names, "abc|.|def");
139
140	log_var_t log_l1 = LOG_VAR_INIT("l1");
141	log_var_t log_l2_a_a = LOG_VAR_INIT("l2.a.a");
142
143	int count = 0;
144	for (int i = 0; i < 10; i++) {
145		log_do_begin(log_l1)
146		    count++;
147		log_do_end(log_l1)
148
149		log_do_begin(log_l2_a_a)
150		    count++;
151		log_do_end(log_l2_a_a)
152	}
153	assert_d_eq(count, 20, "Mis-logged!");
154}
155TEST_END
156
157TEST_BEGIN(test_logs_if_no_init) {
158	test_skip_if(!config_log);
159	atomic_store_b(&log_init_done, false, ATOMIC_RELAXED);
160
161	log_var_t l = LOG_VAR_INIT("definitely.not.enabled");
162
163	int count = 0;
164	for (int i = 0; i < 10; i++) {
165		log_do_begin(l)
166			count++;
167		log_do_end(l)
168	}
169	assert_d_eq(count, 0, "Logging shouldn't happen if not initialized.");
170}
171TEST_END
172
173/*
174 * This really just checks to make sure that this usage compiles; we don't have
175 * any test code to run.
176 */
177TEST_BEGIN(test_log_only_format_string) {
178	if (false) {
179		LOG("log_str", "No arguments follow this format string.");
180	}
181}
182TEST_END
183
184int
185main(void) {
186	return test(
187	    test_log_disabled,
188	    test_log_enabled_direct,
189	    test_log_enabled_indirect,
190	    test_log_enabled_global,
191	    test_logs_if_no_init,
192	    test_log_only_format_string);
193}
194