1 /*
2     Copyright (c) 2005-2020 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 
63 namespace Harness {
64     namespace internal {
65 
66 #ifndef TbbHarnessReporter
67     struct TbbHarnessReporter {
ReportTbbHarnessReporter68         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 
Tracer()92         Tracer(): m_flags(0), m_file(NULL), m_func(NULL), m_line(0) {}
93 
set_trace_info(int flags,const char * file,size_t line,const char * func)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 
trace(const char * fmt,...)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>
not_the_first_call()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