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 namespace { 32 33 // A few static global variables required due to the callback nature of JNI 34 // methods. 35 bool is_error_called; 36 const char* const null_return_expected_message_start = 37 "JNI method GetFieldID : Return is NULL from exceptionjni001.cpp : "; 38 const char* const null_file_expected_message_start = 39 "JNI method GetFieldID : Return is NULL from Unknown File : "; 40 41 // Used by the ErrorCheckerMessage and the tests to determine test success. 42 int expected_line_number; 43 bool error_message_ok; 44 const char* expected_message_start; 45 46 bool CheckMessage(JNIEnv* env, const char* message, const char* expected_message, 47 int expected_line) { 48 if (strstr(message, expected_message) != message) { 49 fprintf(stderr, "Message does not start as expected:\n\t%s\n\t%s\n", 50 message, expected_message); 51 return false; 52 } 53 54 int len = strlen(expected_message); 55 56 char* end_ptr = NULL; 57 int actual_line = strtol(message + len, &end_ptr, 0); 58 59 if (end_ptr == NULL || *end_ptr != '\0') { 60 fprintf(stderr, "end_ptr == NULL or *end_ptr != '\0' from %s\n", message); 61 return false; 62 } 63 64 if (actual_line != expected_line) { 65 fprintf(stderr, "Actual line does not match expected:\n"); 66 fprintf(stderr, "\tActual: %d\n\tExpected: %d\n\tfrom: %s (%s)\n", 67 actual_line, expected_line, message, message + len); 68 return false; 69 } 70 71 // Clear the exception if everything lines up. 72 env->ExceptionClear(); 73 return true; 74 } 75 76 void ErrorCheckerMessage(JNIEnv* env, const char* error_message) { 77 is_error_called = true; 78 error_message_ok = CheckMessage(env, error_message, expected_message_start, 79 expected_line_number); 80 } 81 82 bool checkSuccess(JNIEnv* env, jclass cls) { 83 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 84 is_error_called = false; 85 86 jni->GetFieldID(cls, "anInteger", "I", TRACE_JNI_CALL); 87 return !is_error_called; 88 } 89 90 bool checkFailureMessageReturnNull(JNIEnv* env, jclass cls) { 91 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 92 93 expected_message_start = null_return_expected_message_start; 94 expected_line_number = __LINE__ + 1; 95 jni->GetFieldID(cls, "whatever", "does not matter", TRACE_JNI_CALL); 96 97 return is_error_called && error_message_ok; 98 } 99 100 bool checkFailureMessageEmptyFile(JNIEnv* env, jclass cls) { 101 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 102 103 expected_message_start = null_file_expected_message_start; 104 expected_line_number = __LINE__ + 1; 105 jni->GetFieldID(cls, "whatever", "does not matter", __LINE__, NULL); 106 107 return is_error_called && error_message_ok; 108 } 109 110 bool checkFailureMessageNilLine(JNIEnv* env, jclass cls) { 111 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 112 113 expected_message_start = null_return_expected_message_start; 114 expected_line_number = 0; 115 jni->GetFieldID(cls, "whatever", "does not matter", 0, __FILE__); 116 117 return is_error_called && error_message_ok; 118 } 119 120 bool checkFailureMessageNegativeLine(JNIEnv* env, jclass cls) { 121 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 122 123 expected_message_start = null_return_expected_message_start; 124 expected_line_number = -1; 125 jni->GetFieldID(cls, "whatever", "does not matter", -1, __FILE__); 126 127 return is_error_called && error_message_ok; 128 } 129 130 bool checkFailureMessageMinLine(JNIEnv* env, jclass cls) { 131 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 132 133 expected_message_start = null_return_expected_message_start; 134 expected_line_number = INT32_MIN; 135 jni->GetFieldID(cls, "whatever", "does not matter", INT32_MIN, __FILE__); 136 137 return is_error_called && error_message_ok; 138 } 139 140 bool checkFailureMessageMaxLine(JNIEnv* env, jclass cls) { 141 ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); 142 143 expected_message_start = null_return_expected_message_start; 144 expected_line_number = INT32_MAX; 145 jni->GetFieldID(cls, "whatever", "does not matter", INT32_MAX, __FILE__); 146 147 return is_error_called && error_message_ok; 148 } 149 150 bool CheckExceptionJni(JNIEnv* env, jclass cls) { 151 typedef bool (*TestExceptionJniWrapper)(JNIEnv* env, jclass cls); 152 153 TestExceptionJniWrapper tests[] = { 154 checkSuccess, 155 checkFailureMessageReturnNull, 156 checkFailureMessageEmptyFile, 157 checkFailureMessageNilLine, 158 checkFailureMessageNegativeLine, 159 checkFailureMessageMinLine, 160 checkFailureMessageMaxLine, 161 }; 162 163 int max_tests = sizeof(tests) / sizeof(tests[0]); 164 for (int i = 0; i < max_tests; i++) { 165 fprintf(stderr, "Checking test %d\n", i); 166 is_error_called = false; 167 error_message_ok = false; 168 if (!tests[i](env, cls)) { 169 return false; 170 } 171 } 172 return true; 173 } 174 175 } 176 177 extern "C" { 178 179 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 180 return JNI_OK; 181 } 182 183 JNIEXPORT jboolean JNICALL 184 Java_nsk_share_ExceptionCheckingJniEnv_exceptionjni001_check(JNIEnv *env, jclass cls) { 185 return CheckExceptionJni(env, cls); 186 } 187 188 }