12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #ifdef __APPLE__
29 # include <dlfcn.h>
30 #endif
31
32 #include "prims/jni.h"
33 #include "unittest.hpp"
34
35 extern "C" {
36
37 static bool is_prefix(const char* prefix, const char* str) {
38 return strncmp(str, prefix, strlen(prefix)) == 0;
39 }
40
41 static bool is_suffix(const char* suffix, const char* str) {
42 size_t suffix_len = strlen(suffix);
43 size_t str_len = strlen(str);
44 if (str_len < suffix_len) {
45 return false;
46 }
47 return strncmp(str + (str_len - suffix_len), suffix, suffix_len) == 0;
48 }
49
50
51 static int init_jvm(int argc, char **argv, bool disable_error_handling) {
52 // don't care about the program name
53 argc--;
54 argv++;
55
103 _is_initialized = true;
104 }
105 }
106 };
107
108 static char* get_java_home_arg(int argc, char** argv) {
109 for (int i = 0; i < argc; i++) {
110 if (strncmp(argv[i], "-jdk", strlen(argv[i])) == 0) {
111 return argv[i+1];
112 }
113 if (is_prefix("--jdk=", argv[i])) {
114 return argv[i] + strlen("--jdk=");
115 }
116 if (is_prefix("-jdk:", argv[i])) {
117 return argv[i] + strlen("-jdk:");
118 }
119 }
120 return NULL;
121 }
122
123 static int num_args_to_skip(char* arg) {
124 if (strcmp(arg, "-jdk") == 0) {
125 return 2; // skip the argument after -jdk as well
126 }
127 if (is_prefix("--jdk=", arg)) {
128 return 1;
129 }
130 if (is_prefix("-jdk:", arg)) {
131 return 1;
132 }
133 return 0;
134 }
135
136 static char** remove_test_runner_arguments(int* argcp, char **argv) {
137 int argc = *argcp;
138 char** new_argv = (char**) malloc(sizeof(char*) * argc);
139 int new_argc = 0;
140
141 int i = 0;
142 while (i < argc) {
143 int args_to_skip = num_args_to_skip(argv[i]);
144 if (args_to_skip == 0) {
145 new_argv[new_argc] = argv[i];
146 i++;
147 new_argc++;
148 } else {
149 i += num_args_to_skip(argv[i]);
150 }
151 }
152
153 *argcp = new_argc;
154 return new_argv;
155 }
156
157 JNIEXPORT void JNICALL runUnitTests(int argc, char** argv) {
158 ::testing::InitGoogleTest(&argc, argv);
159 ::testing::GTEST_FLAG(death_test_style) = "threadsafe";
160
161 bool is_vmassert_test = false;
162 bool is_othervm_test = false;
163 // death tests facility is used for both regular death tests, other vm and vmassert tests
164 if (::testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) {
165 // when we execute death test, filter value equals to test name
166 const char* test_name = ::testing::GTEST_FLAG(filter).c_str();
167 const char* const othervm_suffix = "_other_vm_test"; // TEST_OTHER_VM
168 const char* const vmassert_suffix = "_vm_assert_test"; // TEST_VM_ASSERT(_MSG)
169 if (is_suffix(othervm_suffix, test_name)) {
170 is_othervm_test = true;
171 } else if (is_suffix(vmassert_suffix, test_name)) {
172 is_vmassert_test = true;
173 }
174 }
175
176 char* java_home = get_java_home_arg(argc, argv);
177 if (java_home == NULL) {
200 argv = remove_test_runner_arguments(&argc, argv);
201
202 if (is_vmassert_test || is_othervm_test) {
203 // both vmassert and other vm tests require inited jvm
204 // but only vmassert tests disable hs_err and core file generation
205 if (init_jvm(argc, argv, is_vmassert_test) != 0) {
206 abort();
207 }
208 } else {
209 ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();
210 listeners.Append(new JVMInitializerListener(argc, argv));
211 }
212
213 int result = RUN_ALL_TESTS();
214 if (result != 0) {
215 fprintf(stderr, "ERROR: RUN_ALL_TESTS() failed. Error %d\n", result);
216 exit(2);
217 }
218 }
219
220 } // extern "C"
|
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #ifdef __APPLE__
29 # include <dlfcn.h>
30 #endif
31
32 #ifdef _WIN32
33 #include <windows.h>
34 #else
35 #include <pthread.h>
36 #endif
37
38 #include "prims/jni.h"
39 #include "unittest.hpp"
40
41 // Default value for -new-thread option: true on AIX because we run into
42 // problems when attempting to initialize the JVM on the primordial thread.
43 #ifdef _AIX
44 const static bool DEFAULT_SPAWN_IN_NEW_THREAD = true;
45 #else
46 const static bool DEFAULT_SPAWN_IN_NEW_THREAD = false;
47 #endif
48
49 static bool is_prefix(const char* prefix, const char* str) {
50 return strncmp(str, prefix, strlen(prefix)) == 0;
51 }
52
53 static bool is_suffix(const char* suffix, const char* str) {
54 size_t suffix_len = strlen(suffix);
55 size_t str_len = strlen(str);
56 if (str_len < suffix_len) {
57 return false;
58 }
59 return strncmp(str + (str_len - suffix_len), suffix, suffix_len) == 0;
60 }
61
62
63 static int init_jvm(int argc, char **argv, bool disable_error_handling) {
64 // don't care about the program name
65 argc--;
66 argv++;
67
115 _is_initialized = true;
116 }
117 }
118 };
119
120 static char* get_java_home_arg(int argc, char** argv) {
121 for (int i = 0; i < argc; i++) {
122 if (strncmp(argv[i], "-jdk", strlen(argv[i])) == 0) {
123 return argv[i+1];
124 }
125 if (is_prefix("--jdk=", argv[i])) {
126 return argv[i] + strlen("--jdk=");
127 }
128 if (is_prefix("-jdk:", argv[i])) {
129 return argv[i] + strlen("-jdk:");
130 }
131 }
132 return NULL;
133 }
134
135 static bool get_spawn_new_main_thread_arg(int argc, char** argv) {
136 // -new-thread[=(true|false)]
137 for (int i = 0; i < argc; i++) {
138 if (is_prefix("-new-thread", argv[i])) {
139 const char* v = argv[i] + strlen("-new-thread");
140 if (strlen(v) == 0) {
141 return true;
142 } else {
143 if (strcmp(v, "=true") == 0) {
144 return true;
145 } else if (strcmp(v, "=false") == 0) {
146 return false;
147 } else {
148 fprintf(stderr, "Invalid value for -new-thread (%s)", v);
149 }
150 }
151 }
152 }
153 return DEFAULT_SPAWN_IN_NEW_THREAD;
154 }
155
156 static int num_args_to_skip(char* arg) {
157 if (strcmp(arg, "-jdk") == 0) {
158 return 2; // skip the argument after -jdk as well
159 }
160 if (is_prefix("--jdk=", arg)) {
161 return 1;
162 }
163 if (is_prefix("-jdk:", arg)) {
164 return 1;
165 }
166 if (is_prefix("-new-thread", arg)) {
167 return 1;
168 }
169 return 0;
170 }
171
172 static char** remove_test_runner_arguments(int* argcp, char **argv) {
173 int argc = *argcp;
174 char** new_argv = (char**) malloc(sizeof(char*) * argc);
175 int new_argc = 0;
176
177 int i = 0;
178 while (i < argc) {
179 int args_to_skip = num_args_to_skip(argv[i]);
180 if (args_to_skip == 0) {
181 new_argv[new_argc] = argv[i];
182 i++;
183 new_argc++;
184 } else {
185 i += num_args_to_skip(argv[i]);
186 }
187 }
188
189 *argcp = new_argc;
190 return new_argv;
191 }
192
193 static void runUnitTestsInner(int argc, char** argv) {
194 ::testing::InitGoogleTest(&argc, argv);
195 ::testing::GTEST_FLAG(death_test_style) = "threadsafe";
196
197 bool is_vmassert_test = false;
198 bool is_othervm_test = false;
199 // death tests facility is used for both regular death tests, other vm and vmassert tests
200 if (::testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) {
201 // when we execute death test, filter value equals to test name
202 const char* test_name = ::testing::GTEST_FLAG(filter).c_str();
203 const char* const othervm_suffix = "_other_vm_test"; // TEST_OTHER_VM
204 const char* const vmassert_suffix = "_vm_assert_test"; // TEST_VM_ASSERT(_MSG)
205 if (is_suffix(othervm_suffix, test_name)) {
206 is_othervm_test = true;
207 } else if (is_suffix(vmassert_suffix, test_name)) {
208 is_vmassert_test = true;
209 }
210 }
211
212 char* java_home = get_java_home_arg(argc, argv);
213 if (java_home == NULL) {
236 argv = remove_test_runner_arguments(&argc, argv);
237
238 if (is_vmassert_test || is_othervm_test) {
239 // both vmassert and other vm tests require inited jvm
240 // but only vmassert tests disable hs_err and core file generation
241 if (init_jvm(argc, argv, is_vmassert_test) != 0) {
242 abort();
243 }
244 } else {
245 ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();
246 listeners.Append(new JVMInitializerListener(argc, argv));
247 }
248
249 int result = RUN_ALL_TESTS();
250 if (result != 0) {
251 fprintf(stderr, "ERROR: RUN_ALL_TESTS() failed. Error %d\n", result);
252 exit(2);
253 }
254 }
255
256 // Thread support for -new-thread option
257
258 struct args_t {
259 int argc; char** argv;
260 };
261
262 #define STACK_SIZE 0x200000
263
264 #ifdef _WIN32
265
266 static DWORD thread_wrapper(void* p) {
267 const args_t* const p_args = (const args_t*) p;
268 runUnitTestsInner(p_args->argc, p_args->argv);
269 return 0;
270 }
271
272 static void run_in_new_thread(const args_t* args) {
273 HANDLE hdl;
274 hdl = CreateThread(NULL, STACK_SIZE, thread_wrapper, (void*)args, 0, NULL);
275 if (hdl == NULL) {
276 fprintf(stderr, "Failed to create main thread\n");
277 exit(2);
278 }
279 WaitForSingleObject(hdl, INFINITE);
280 }
281
282 #else
283
284 static void* thread_wrapper(void* p) {
285 const args_t* const p_args = (const args_t*) p;
286 runUnitTestsInner(p_args->argc, p_args->argv);
287 return 0;
288 }
289
290 static void run_in_new_thread(const args_t* args) {
291 pthread_t tid;
292 pthread_attr_t attr;
293
294 pthread_attr_init(&attr);
295 pthread_attr_setstacksize(&attr, STACK_SIZE);
296
297 if (pthread_create(&tid, &attr, thread_wrapper, (void*)args) != 0) {
298 fprintf(stderr, "Failed to create main thread\n");
299 exit(2);
300 }
301
302 if (pthread_join(tid, NULL) != 0) {
303 fprintf(stderr, "Failed to join main thread\n");
304 exit(2);
305 }
306 }
307
308 #endif
309
310 extern "C"
311 JNIEXPORT void JNICALL runUnitTests(int argc, char** argv) {
312 const bool spawn_new_main_thread = get_spawn_new_main_thread_arg(argc, argv);
313 if (spawn_new_main_thread) {
314 args_t args;
315 args.argc = argc;
316 args.argv = argv;
317 run_in_new_thread(&args);
318 } else {
319 runUnitTestsInner(argc, argv);
320 }
321 }
322
|