1 #include "clar_libgit2_trace.h"
2 #include "clar_libgit2.h"
3 #include "clar_libgit2_timer.h"
8 void (*git_trace_cb
)(git_trace_level_t level
, const char *msg
);
12 static const char *message_prefix(git_trace_level_t level
)
34 static void _git_trace_cb__printf(git_trace_level_t level
, const char *msg
)
36 printf("%s%s\n", message_prefix(level
), msg
);
39 #if defined(GIT_WIN32)
40 static void _git_trace_cb__debug(git_trace_level_t level
, const char *msg
)
42 OutputDebugString(message_prefix(level
));
43 OutputDebugString(msg
);
44 OutputDebugString("\n");
46 printf("%s%s\n", message_prefix(level
), msg
);
49 #define _git_trace_cb__debug _git_trace_cb__printf
53 static void _trace_printf_close(void)
58 #define _trace_debug_close _trace_printf_close
61 static struct method s_methods
[] = {
62 { "printf", _git_trace_cb__printf
, _trace_printf_close
},
63 { "debug", _git_trace_cb__debug
, _trace_debug_close
},
64 /* TODO add file method */
69 static int s_trace_loaded
= 0;
70 static int s_trace_level
= GIT_TRACE_NONE
;
71 static struct method
*s_trace_method
= NULL
;
72 static int s_trace_tests
= 0;
74 static int set_method(const char *name
)
81 for (k
=0; (s_methods
[k
].name
); k
++) {
82 if (strcmp(name
, s_methods
[k
].name
) == 0) {
83 s_trace_method
= &s_methods
[k
];
87 fprintf(stderr
, "Unknown CLAR_TRACE_METHOD: '%s'\n", name
);
93 * Lookup CLAR_TRACE_LEVEL and CLAR_TRACE_METHOD from
94 * the environment and set the above s_trace_* fields.
96 * If CLAR_TRACE_LEVEL is not set, we disable tracing.
98 * TODO If set, we assume GIT_TRACE_TRACE level, which
99 * logs everything. Later, we may want to parse the
100 * value of the environment variable and set a specific
103 * We assume the "printf" method. This can be changed
104 * with the CLAR_TRACE_METHOD environment variable.
105 * Currently, this is only needed on Windows for a "debug"
106 * version which also writes to the debug output window
109 * TODO add a "file" method that would open and write
110 * to a well-known file. This would help keep trace
111 * output and clar output separate.
114 static void _load_trace_params(void)
122 sz_level
= cl_getenv("CLAR_TRACE_LEVEL");
123 if (!sz_level
|| !*sz_level
) {
124 s_trace_level
= GIT_TRACE_NONE
;
125 s_trace_method
= NULL
;
129 /* TODO Parse sz_level and set s_trace_level. */
130 s_trace_level
= GIT_TRACE_TRACE
;
132 sz_method
= cl_getenv("CLAR_TRACE_METHOD");
133 if (set_method(sz_method
) < 0)
136 sz_tests
= cl_getenv("CLAR_TRACE_TESTS");
137 if (sz_tests
!= NULL
)
141 #define HR "================================================================"
144 * Timer to report the take spend in a test's run() method.
146 static cl_perf_timer s_timer_run
= CL_PERF_TIMER_INIT
;
149 * Timer to report total time in a test (init, run, cleanup).
151 static cl_perf_timer s_timer_test
= CL_PERF_TIMER_INIT
;
153 void _cl_trace_cb__event_handler(
155 const char *suite_name
,
156 const char *test_name
,
165 case CL_TRACE__SUITE_BEGIN
:
166 git_trace(GIT_TRACE_TRACE
, "\n\n%s\n%s: Begin Suite", HR
, suite_name
);
167 #if 0 && defined(GIT_WIN32_LEAKCHECK)
168 git_win32__crtdbg_stacktrace__dump(
169 GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK
,
174 case CL_TRACE__SUITE_END
:
175 #if 0 && defined(GIT_WIN32_LEAKCHECK)
176 /* As an example of checkpointing, dump leaks within this suite.
177 * This may generate false positives for things like the global
178 * TLS error state and maybe the odb cache since they aren't
179 * freed until the global shutdown and outside the scope of this
182 * This may under-report if the test itself uses a checkpoint.
183 * See tests/trace/windows/stacktrace.c
185 git_win32__crtdbg_stacktrace__dump(
186 GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK
,
189 git_trace(GIT_TRACE_TRACE
, "\n\n%s: End Suite\n%s", suite_name
, HR
);
192 case CL_TRACE__TEST__BEGIN
:
193 git_trace(GIT_TRACE_TRACE
, "\n%s::%s: Begin Test", suite_name
, test_name
);
194 cl_perf_timer__init(&s_timer_test
);
195 cl_perf_timer__start(&s_timer_test
);
198 case CL_TRACE__TEST__END
:
199 cl_perf_timer__stop(&s_timer_test
);
200 git_trace(GIT_TRACE_TRACE
, "%s::%s: End Test (%.3f %.3f)", suite_name
, test_name
,
201 cl_perf_timer__last(&s_timer_run
),
202 cl_perf_timer__last(&s_timer_test
));
205 case CL_TRACE__TEST__RUN_BEGIN
:
206 git_trace(GIT_TRACE_TRACE
, "%s::%s: Begin Run", suite_name
, test_name
);
207 cl_perf_timer__init(&s_timer_run
);
208 cl_perf_timer__start(&s_timer_run
);
211 case CL_TRACE__TEST__RUN_END
:
212 cl_perf_timer__stop(&s_timer_run
);
213 git_trace(GIT_TRACE_TRACE
, "%s::%s: End Run", suite_name
, test_name
);
216 case CL_TRACE__TEST__LONGJMP
:
217 cl_perf_timer__stop(&s_timer_run
);
218 git_trace(GIT_TRACE_TRACE
, "%s::%s: Aborted", suite_name
, test_name
);
227 * Setup/Enable git_trace() based upon settings user's environment.
229 void cl_global_trace_register(void)
232 _load_trace_params();
234 if (s_trace_level
== GIT_TRACE_NONE
)
236 if (s_trace_method
== NULL
)
238 if (s_trace_method
->git_trace_cb
== NULL
)
241 git_trace_set(s_trace_level
, s_trace_method
->git_trace_cb
);
242 cl_trace_register(_cl_trace_cb__event_handler
, NULL
);
246 * If we turned on git_trace() earlier, turn it off.
248 * This is intended to let us close/flush any buffered
252 void cl_global_trace_disable(void)
254 cl_trace_register(NULL
, NULL
);
255 git_trace_set(GIT_TRACE_NONE
, NULL
);
256 if (s_trace_method
&& s_trace_method
->close
)
257 s_trace_method
->close();
259 /* Leave s_trace_ vars set so they can restart tracing
260 * since we only want to hit the environment variables