1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, Google and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include "jvmti.h" 29 #include "ExceptionCheckingJniEnv.hpp" 30 31 // A few static global variables required due to the callback nature of JNI 32 // methods. 33 static bool is_error_called; 34 static const char* const null_return_expected_message_start = 35 "JNI method GetFieldID : Return is NULL from exceptionjni001.cpp : "; 36 static const char* const null_file_expected_message_start = 37 "JNI method GetFieldID : Return is NULL from Unknown File : "; 38 39 // Used by the ErrorCheckerMessage and the tests to determine test success. 40 static int expected_line_number; 41 static bool error_message_ok; 42 static const char* expected_message_start; 43 44 static bool CheckMessage(JNIEnv* env, const char* message, const char* expected_message, 45 int expected_line) { 46 if (strstr(message, expected_message) != message) { 47 fprintf(stderr, "Message does not start as expected:\n\t%s\n\t%s\n", 48 message, expected_message); 49 return false; 50 } 51 52 int len = strlen(expected_message); 53 54 char* end_ptr = NULL; 55 int actual_line = strtol(message + len, &end_ptr, 0); 56 57 if (end_ptr == NULL || *end_ptr != '\0') { 58 fprintf(stderr, "end_ptr == NULL or *end_ptr != '\0' from %s\n", message); 59 return false; 60 } 61 62 if (actual_line != expected_line) { 63 fprintf(stderr, "Actual line does not match expected:\n"); 64 fprintf(stderr, "\tActual: %d\n\tExpected: %d\n\tfrom: %s (%s)\n", 65 actual_line, expected_line, message, message + len); 66 return false; 67 } 68 69 // Clear the exception if everything lines up. 70 env->ExceptionClear(); 71 return true; 72 } 73 74 static void ErrorCheckerMessage(JNIEnv* env, const char* error_message) { 75 is_error_called = true; 76 error_message_ok = CheckMessage(env, error_message, expected_message_start, 77 expected_line_number); 78 } 79 80 static bool checkSuccess(JNIEnv* env, jclass cls) { 81 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 82 is_error_called = false; 83 84 jni->GetFieldID(cls, "anInteger", "I", TRACE_JNI_CALL); 85 return !is_error_called; 86 } 87 88 static bool checkFailureMessageReturnNull(JNIEnv* env, jclass cls) { 89 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 90 91 expected_message_start = null_return_expected_message_start; 92 expected_line_number = __LINE__ + 1; 93 jni->GetFieldID(cls, "whatever", "does not matter", TRACE_JNI_CALL); 94 95 return is_error_called && error_message_ok; 96 } 97 98 static bool checkFailureMessageEmptyFile(JNIEnv* env, jclass cls) { 99 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 100 101 expected_message_start = null_file_expected_message_start; 102 expected_line_number = __LINE__ + 1; 103 jni->GetFieldID(cls, "whatever", "does not matter", __LINE__, NULL); 104 105 return is_error_called && error_message_ok; 106 } 107 108 static bool checkFailureMessageNilLine(JNIEnv* env, jclass cls) { 109 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 110 111 expected_message_start = null_return_expected_message_start; 112 expected_line_number = 0; 113 jni->GetFieldID(cls, "whatever", "does not matter", 0, __FILE__); 114 115 return is_error_called && error_message_ok; 116 } 117 118 static bool checkFailureMessageNegativeLine(JNIEnv* env, jclass cls) { 119 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 120 121 expected_message_start = null_return_expected_message_start; 122 expected_line_number = -1; 123 jni->GetFieldID(cls, "whatever", "does not matter", -1, __FILE__); 124 125 return is_error_called && error_message_ok; 126 } 127 128 static bool checkFailureMessageMinLine(JNIEnv* env, jclass cls) { 129 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 130 131 expected_message_start = null_return_expected_message_start; 132 expected_line_number = INT32_MIN; 133 jni->GetFieldID(cls, "whatever", "does not matter", INT32_MIN, __FILE__); 134 135 return is_error_called && error_message_ok; 136 } 137 138 static bool checkFailureMessageMaxLine(JNIEnv* env, jclass cls) { 139 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 140 141 expected_message_start = null_return_expected_message_start; 142 expected_line_number = INT32_MAX; 143 jni->GetFieldID(cls, "whatever", "does not matter", INT32_MAX, __FILE__); 144 145 return is_error_called && error_message_ok; 146 } 147 148 static bool CheckExceptionJni(JNIEnv* env, jclass cls) { 149 typedef bool (*TestExceptionJniWrapper)(JNIEnv* env, jclass cls); 150 151 TestExceptionJniWrapper tests[] = { 152 checkSuccess, 153 checkFailureMessageReturnNull, 154 checkFailureMessageEmptyFile, 155 checkFailureMessageNilLine, 156 checkFailureMessageNegativeLine, 157 checkFailureMessageMinLine, 158 checkFailureMessageMaxLine, 159 }; 160 161 int max_tests = sizeof(tests) / sizeof(tests[0]); 162 for (int i = 0; i < max_tests; i++) { 163 fprintf(stderr, "Checking test %d\n", i); 164 is_error_called = false; 165 error_message_ok = false; 166 if (!tests[i](env, cls)) { 167 return false; 168 } 169 } 170 return true; 171 } 172 173 extern "C" { 174 175 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 176 return JNI_OK; 177 } 178 179 JNIEXPORT jboolean JNICALL 180 Java_nsk_share_ExceptionCheckingJniEnv_exceptionjni001_check(JNIEnv *env, jclass cls) { 181 return CheckExceptionJni(env, cls); 182 } 183 184 }