1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17// Just the tracing portion of the harness.
18//
19// This header defines TRACE and TRACENL macros, which use REPORT like syntax and
20// are useful for duplicating trace output to the standard debug output on Windows.
21// It is possible to add the ability of automatic extending messages with additional
22// info (file, line, function, time, thread ID, ...).
23//
24// Macros output nothing when test app runs in non-verbose mode (default).
25//
26
27#ifndef tbb_tests_harness_report_H
28#define tbb_tests_harness_report_H
29
30#if defined(MAX_TRACE_SIZE) && MAX_TRACE_SIZE < 1024
31 #undef MAX_TRACE_SIZE
32#endif
33#ifndef MAX_TRACE_SIZE
34 #define MAX_TRACE_SIZE 1024
35#endif
36
37#if __SUNPRO_CC
38#include <stdio.h>
39#else
40#include <cstdio>
41#endif
42
43#include <cstdarg>
44
45// Need to include "tbb/tbb_config.h" to obtain the definition of __TBB_DEFINE_MIC.
46#include "tbb/tbb_config.h"
47
48#if __TBB_DEFINE_MIC
49#include "harness_mic.h"
50#endif
51
52#ifdef HARNESS_INCOMPLETE_SOURCES
53#error Source files are not complete. Check the build environment
54#endif
55
56#if _MSC_VER
57 #define snprintf _snprintf
58#if _MSC_VER<=1400
59 #define vsnprintf _vsnprintf
60#endif
61#endif
62
63namespace Harness {
64 namespace internal {
65
66#ifndef TbbHarnessReporter
67 struct TbbHarnessReporter {
68 void Report ( const char* msg ) {
69 printf( "%s", msg );
70 fflush(stdout);
71#ifdef _WINDOWS_
72 OutputDebugStringA(msg);
73#endif
74 }
75 }; // struct TbbHarnessReporter
76#endif /* !TbbHarnessReporter */
77
78 class Tracer {
79 int m_flags;
80 const char *m_file;
81 const char *m_func;
82 size_t m_line;
83
84 TbbHarnessReporter m_reporter;
85
86 public:
87 enum {
88 prefix = 1,
89 need_lf = 2
90 };
91
92 Tracer(): m_flags(0), m_file(NULL), m_func(NULL), m_line(0) {}
93
94 Tracer* set_trace_info ( int flags, const char *file, size_t line, const char *func ) {
95 m_flags = flags;
96 m_line = line;
97 m_file = file;
98 m_func = func;
99 return this;
100 }
101
102 void trace ( const char* fmt, ... ) {
103 char msg[MAX_TRACE_SIZE];
104 char msg_fmt_buf[MAX_TRACE_SIZE];
105 const char *msg_fmt = fmt;
106 if ( m_flags & prefix ) {
107 snprintf (msg_fmt_buf, MAX_TRACE_SIZE, "[%s] %s", m_func, fmt);
108 msg_fmt = msg_fmt_buf;
109 }
110 std::va_list argptr;
111 va_start (argptr, fmt);
112 int len = vsnprintf (msg, MAX_TRACE_SIZE, msg_fmt, argptr);
113 va_end (argptr);
114 if ( m_flags & need_lf &&
115 len < MAX_TRACE_SIZE - 1 && msg_fmt[len-1] != '\n' )
116 {
117 msg[len] = '\n';
118 msg[len + 1] = 0;
119 }
120 m_reporter.Report(msg);
121 }
122 }; // class Tracer
123
124 static Tracer tracer;
125
126 template<int>
127 bool not_the_first_call () {
128 static bool first_call = false;
129 bool res = first_call;
130 first_call = true;
131 return res;
132 }
133
134 } // namespace internal
135} // namespace Harness
136
137#if defined(_MSC_VER) && _MSC_VER >= 1300 || defined(__GNUC__) || defined(__GNUG__)
138 #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, __FUNCTION__
139#else
140 #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, ""
141 #define __FUNCTION__ ""
142#endif
143
144
145//! printf style tracing macro
146/** This variant of TRACE adds trailing line-feed (new line) character, if it is absent. **/
147#define TRACE Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace
148
149//! printf style tracing macro without automatic new line character adding
150#define TRACENL Harness::internal::tracer.set_trace_info(0, HARNESS_TRACE_ORIG_INFO)->trace
151
152//! printf style tracing macro with additional information prefix (e.g. current function name)
153#define TRACEP Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::prefix | \
154 Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace
155
156//! printf style remark macro
157/** Produces output only when the test is run with the -v (verbose) option. **/
158#define REMARK !Verbose ? (void)0 : TRACENL
159
160//! printf style remark macro
161/** Produces output only when invoked first time.
162 Only one instance of this macro is allowed per source code line. **/
163#define REMARK_ONCE (!Verbose || Harness::internal::not_the_first_call<__LINE__>()) ? (void)0 : TRACE
164
165//! printf style reporting macro
166/** On heterogeneous platforms redirects its output to the host side. **/
167#define REPORT TRACENL
168
169//! printf style reporting macro
170/** Produces output only when invoked first time.
171 Only one instance of this macro is allowed per source code line. **/
172#define REPORT_ONCE (Harness::internal::not_the_first_call<__LINE__>()) ? (void)0 : TRACENL
173
174#endif /* tbb_tests_harness_report_H */
175