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#include "tbb/tbb_stddef.h"
18
19#if __TBB_WIN8UI_SUPPORT
20// TODO: figure out how the test can be enabled for win8ui
21#define HARNESS_NO_PARSE_COMMAND_LINE 1
22#include "harness.h"
23int TestMain() {
24 return Harness::Skipped;
25}
26#else
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <vector>
31#include <string>
32#include <utility>
33
34#include "tbb/task_scheduler_init.h"
35
36#define HARNESS_CUSTOM_MAIN 1
37#define HARNESS_NO_PARSE_COMMAND_LINE 1
38#define HARNESS_NO_MAIN_ARGS 0
39#include "harness.h"
40
41#if defined (_WIN32) || defined (_WIN64)
42#define TEST_SYSTEM_COMMAND "test_tbb_version.exe @"
43#elif __APPLE__
44// DYLD_LIBRARY_PATH is purged for OS X 10.11, set it again
45#define TEST_SYSTEM_COMMAND "DYLD_LIBRARY_PATH=. ./test_tbb_version.exe @"
46#else
47#define TEST_SYSTEM_COMMAND "./test_tbb_version.exe @"
48#endif
49
50enum string_required {
51 required,
52 optional,
53 optional_multiple
54 };
55
56typedef std::pair <std::string, string_required> string_pair;
57
58void initialize_strings_vector(std::vector <string_pair>* vector);
59
60const char stderr_stream[] = "version_test.err";
61const char stdout_stream[] = "version_test.out";
62
63HARNESS_EXPORT
64int main(int argc, char *argv[] ) {
65 const size_t psBuffer_len = 2048;
66 char psBuffer[psBuffer_len];
67/* We first introduced runtime version identification in 3014 */
68#if TBB_INTERFACE_VERSION>=3014
69 // For now, just test that run-time TBB version matches the compile-time version,
70 // since otherwise the subsequent test of "TBB: INTERFACE VERSION" string will fail anyway.
71 // We need something more clever in future.
72 if ( tbb::TBB_runtime_interface_version()!=TBB_INTERFACE_VERSION ){
73 snprintf( psBuffer, psBuffer_len,
74 "%s %s %d %s %d.",
75 "Running with the library of different version than the test was compiled against.",
76 "Expected",
77 TBB_INTERFACE_VERSION,
78 "- got",
79 tbb::TBB_runtime_interface_version()
80 );
81 ASSERT( tbb::TBB_runtime_interface_version()==TBB_INTERFACE_VERSION, psBuffer );
82 }
83#endif
84#if __TBB_MIC_OFFLOAD
85 // Skip the test in offload mode.
86 // Run the test in 'true' native mode (because 'system()' works in 'true' native mode).
87 (argc, argv);
88 REPORT("skip\n");
89#elif __TBB_MPI_INTEROP || __bg__
90 (void) argc; // unused
91 (void) argv; // unused
92 REPORT("skip\n");
93#else
94 __TBB_TRY {
95 FILE *stream_out;
96 FILE *stream_err;
97
98 if(argc>1 && argv[1][0] == '@' ) {
99 stream_err = freopen( stderr_stream, "w", stderr );
100 if( stream_err == NULL ){
101 REPORT( "Internal test error (freopen)\n" );
102 exit( 1 );
103 }
104 stream_out = freopen( stdout_stream, "w", stdout );
105 if( stream_out == NULL ){
106 REPORT( "Internal test error (freopen)\n" );
107 exit( 1 );
108 }
109 {
110 tbb::task_scheduler_init init(1);
111 }
112 fclose( stream_out );
113 fclose( stream_err );
114 exit(0);
115 }
116 //1st step check that output is empty if TBB_VERSION is not defined.
117 if ( getenv("TBB_VERSION") ){
118 REPORT( "TBB_VERSION defined, skipping step 1 (empty output check)\n" );
119 }else{
120 if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){
121 REPORT( "Error (step 1): Internal test error\n" );
122 exit( 1 );
123 }
124 //Checking output streams - they should be empty
125 stream_err = fopen( stderr_stream, "r" );
126 if( stream_err == NULL ){
127 REPORT( "Error (step 1):Internal test error (stderr open)\n" );
128 exit( 1 );
129 }
130 while( !feof( stream_err ) ) {
131 if( fgets( psBuffer, psBuffer_len, stream_err ) != NULL ){
132 REPORT( "Error (step 1): stderr should be empty\n" );
133 exit( 1 );
134 }
135 }
136 fclose( stream_err );
137 stream_out = fopen( stdout_stream, "r" );
138 if( stream_out == NULL ){
139 REPORT( "Error (step 1):Internal test error (stdout open)\n" );
140 exit( 1 );
141 }
142 while( !feof( stream_out ) ) {
143 if( fgets( psBuffer, psBuffer_len, stream_out ) != NULL ){
144 REPORT( "Error (step 1): stdout should be empty\n" );
145 exit( 1 );
146 }
147 }
148 fclose( stream_out );
149 }
150
151 //Setting TBB_VERSION in case it is not set
152 if ( !getenv("TBB_VERSION") ){
153 Harness::SetEnv("TBB_VERSION","1");
154 }
155
156 if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){
157 REPORT( "Error (step 2):Internal test error\n" );
158 exit( 1 );
159 }
160 //Checking pipe - it should contain version data
161 std::vector <string_pair> strings_vector;
162 std::vector <string_pair>::iterator strings_iterator;
163
164 initialize_strings_vector( &strings_vector );
165 strings_iterator = strings_vector.begin();
166
167 stream_out = fopen( stdout_stream, "r" );
168 if( stream_out == NULL ){
169 REPORT( "Error (step 2):Internal test error (stdout open)\n" );
170 exit( 1 );
171 }
172 while( !feof( stream_out ) ) {
173 if( fgets( psBuffer, psBuffer_len, stream_out ) != NULL ){
174 REPORT( "Error (step 2): stdout should be empty\n" );
175 exit( 1 );
176 }
177 }
178 fclose( stream_out );
179
180 stream_err = fopen( stderr_stream, "r" );
181 if( stream_err == NULL ){
182 REPORT( "Error (step 1):Internal test error (stderr open)\n" );
183 exit( 1 );
184 }
185
186 while( !feof( stream_err ) ) {
187 if( fgets( psBuffer, psBuffer_len, stream_err ) != NULL ){
188 if (strstr( psBuffer, "TBBmalloc: " )) {
189 // TBB allocator might or might not be here, ignore it
190 continue;
191 }
192 bool match_found = false;
193 do{
194 if ( strings_iterator == strings_vector.end() ){
195 REPORT( "Error: version string dictionary ended prematurely.\n" );
196 REPORT( "No match for: \t%s", psBuffer );
197 exit( 1 );
198 }
199 if ( strstr( psBuffer, strings_iterator->first.c_str() ) == NULL ){ // mismatch
200 if( strings_iterator->second == required ){
201 REPORT( "Error: version strings do not match.\n" );
202 REPORT( "Expected \"%s\" not found in:\n\t%s", strings_iterator->first.c_str(), psBuffer );
203 exit( 1 );
204 }
205 ++strings_iterator;
206 }else{
207 match_found = true;
208 if( strings_iterator->second != optional_multiple )
209 ++strings_iterator;
210 }
211 }while( !match_found );
212 }
213 }
214 fclose( stream_err );
215 } __TBB_CATCH(...) {
216 ASSERT( 0,"unexpected exception" );
217 }
218 REPORT("done\n");
219#endif //__TBB_MIC_OFFLOAD, __TBB_MPI_INTEROP etc
220 return 0;
221}
222
223
224// Fill dictionary with version strings for platforms
225void initialize_strings_vector(std::vector <string_pair>* vector)
226{
227 vector->push_back(string_pair("TBB: VERSION\t\t2019.0", required)); // check TBB_VERSION
228 vector->push_back(string_pair("TBB: INTERFACE VERSION\t11008", required)); // check TBB_INTERFACE_VERSION
229 vector->push_back(string_pair("TBB: BUILD_DATE", required));
230 vector->push_back(string_pair("TBB: BUILD_HOST", required));
231 vector->push_back(string_pair("TBB: BUILD_OS", required));
232#if _WIN32||_WIN64
233#if !__MINGW32__
234 vector->push_back(string_pair("TBB: BUILD_CL", required));
235 vector->push_back(string_pair("TBB: BUILD_COMPILER", required));
236#else
237 vector->push_back(string_pair("TBB: BUILD_GCC", required));
238#endif
239#elif __APPLE__
240 vector->push_back(string_pair("TBB: BUILD_KERNEL", required));
241 vector->push_back(string_pair("TBB: BUILD_CLANG", required));
242 vector->push_back(string_pair("TBB: BUILD_XCODE", optional));
243 vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") )
244#elif __sun
245 vector->push_back(string_pair("TBB: BUILD_KERNEL", required));
246 vector->push_back(string_pair("TBB: BUILD_SUNCC", required));
247 vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") )
248#else // We use version_info_linux.sh for unsupported OSes
249#if !__ANDROID__
250 vector->push_back(string_pair("TBB: BUILD_KERNEL", required));
251#endif
252 vector->push_back(string_pair("TBB: BUILD_GCC", optional));
253 vector->push_back(string_pair("TBB: BUILD_CLANG", optional));
254 vector->push_back(string_pair("TBB: BUILD_TARGET_CXX", optional));
255 vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") )
256#if __ANDROID__
257 vector->push_back(string_pair("TBB: BUILD_NDK", optional));
258 vector->push_back(string_pair("TBB: BUILD_LD", optional));
259#else
260 vector->push_back(string_pair("TBB: BUILD_LIBC", required));
261 vector->push_back(string_pair("TBB: BUILD_LD", required));
262#endif // !__ANDROID__
263#endif // OS
264 vector->push_back(string_pair("TBB: BUILD_TARGET", required));
265 vector->push_back(string_pair("TBB: BUILD_COMMAND", required));
266 vector->push_back(string_pair("TBB: TBB_USE_DEBUG", required));
267 vector->push_back(string_pair("TBB: TBB_USE_ASSERT", required));
268#if __TBB_CPF_BUILD
269 vector->push_back(string_pair("TBB: TBB_PREVIEW_BINARY", required));
270#endif
271 vector->push_back(string_pair("TBB: DO_ITT_NOTIFY", required));
272 vector->push_back(string_pair("TBB: ITT", optional)); //#ifdef DO_ITT_NOTIFY
273 vector->push_back(string_pair("TBB: ALLOCATOR", required));
274#if _WIN32||_WIN64
275 vector->push_back(string_pair("TBB: Processor groups", required));
276 vector->push_back(string_pair("TBB: ----- Group", optional_multiple));
277#endif
278 vector->push_back(string_pair("TBB: RML", optional));
279 vector->push_back(string_pair("TBB: Intel(R) RML library built:", optional));
280 vector->push_back(string_pair("TBB: Intel(R) RML library version:", optional));
281 vector->push_back(string_pair("TBB: Tools support", required));
282 return;
283}
284#endif /* __TBB_WIN8UI_SUPPORT */
285