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