// // Copyright (C) 2006 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.util.test; import java.util.ArrayList; import cmu.conditional.Conditional; import de.fosd.typechef.featureexpr.FeatureExpr; import de.fosd.typechef.featureexpr.FeatureExprFactory; import gov.nasa.jpf.annotation.MJI; import gov.nasa.jpf.vm.ClassInfo; import gov.nasa.jpf.vm.DirectCallStackFrame; import gov.nasa.jpf.vm.MJIEnv; import gov.nasa.jpf.vm.MethodInfo; import gov.nasa.jpf.vm.NativePeer; import gov.nasa.jpf.vm.StackFrame; import gov.nasa.jpf.vm.ThreadInfo; /** * native peer for our test class root */ public class JPF_gov_nasa_jpf_util_test_TestJPF extends NativePeer { ClassInfo testClass; MethodInfo testClassCtor; MethodInfo[] testMethods = null; int index = 0; int testObjRef = MJIEnv.NULL; boolean done; private static void pushDirectCallFrame(MJIEnv env, MethodInfo mi, int objRef, FeatureExpr ctx) { ThreadInfo ti = env.getThreadInfo(); DirectCallStackFrame frame = mi.createDirectCallStackFrame(ctx, ti, 0); frame.setReferenceArgument( ctx, 0, objRef, null); ti.pushFrame(frame); } private boolean initializeTestMethods(MJIEnv env, String[] selectedTests, FeatureExpr ctx) { if (selectedTests != null && selectedTests.length > 0) { testMethods = new MethodInfo[selectedTests.length]; int i = 0; for (String test : selectedTests) { MethodInfo mi = testClass.getMethod(test + "()V", false); if (mi != null && mi.isPublic() && !mi.isStatic()) { testMethods[i++] = mi; } else { env.throwException(ctx, "java.lang.RuntimeException", "no such test method: public void " + test + "()"); return false; } } } else { // collect all public void test..() methods ArrayList<MethodInfo> list = new ArrayList<MethodInfo>(); for (MethodInfo mi : testClass) { if (mi.getName().startsWith("test") && mi.isPublic() && !mi.isStatic() && mi.getSignature().equals("()V")) { list.add(mi); } } testMethods = list.toArray(new MethodInfo[list.size()]); } return true; } //--- our exported native methods public JPF_gov_nasa_jpf_util_test_TestJPF () { done = false; index = 0; testObjRef = MJIEnv.NULL; testMethods = null; testClass = null; testClassCtor = null; } @MJI public void $init____V (MJIEnv env, int objRef, FeatureExpr ctx){ // nothing } @MJI public void runTestsOfThisClass___3Ljava_lang_String_2__V (MJIEnv env, int clsObjRef, int selectedTestsRef, FeatureExpr ctx) { if (!done) { if (testMethods == null) { StackFrame frame = env.getCallerStackFrame(); // the runTestsOfThisClass() caller testClass = frame.getClassInfo(); testClassCtor = testClass.getMethod("<init>()V", true); String[] selectedTests = env.getStringArrayObject(ctx, selectedTestsRef); if (initializeTestMethods(env, selectedTests, ctx)) { env.repeatInvocation(); } } else { // this is re-executed if (testObjRef == MJIEnv.NULL) { // create a new test object testObjRef = env.newObject(ctx, testClass); if (testClassCtor != null) { pushDirectCallFrame(env, testClassCtor, testObjRef, ctx); env.repeatInvocation(); } } else { // enter the next test if (testMethods != null && (index < testMethods.length)) { MethodInfo miTest = testMethods[index++]; pushDirectCallFrame(env, miTest, testObjRef,ctx); if (index < testMethods.length) { testObjRef = MJIEnv.NULL; } else { done = true; } env.repeatInvocation(); } } } } } @MJI public int createAndRunJPF__Ljava_lang_StackTraceElement_2_3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int a1, int a2, FeatureExpr ctx){ // don't get recursive return MJIEnv.NULL; } @SuppressWarnings("deprecation") @MJI public int getProperty__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int clsObjRef, Conditional<Integer> keyRef, FeatureExpr ctx){ String key = env.getStringObject(ctx, keyRef.getValue()); String val = env.getConfig().getString(key); if (val != null){ return env.newString(FeatureExprFactory.True(), val); } else { return MJIEnv.NULL; } } /** * if any of our methods are executed, we know that we already run under JPF */ @MJI public boolean isJPFRun____Z (MJIEnv env, int clsObjRef, FeatureExpr ctx){ return true; } @MJI public boolean isJUnitRun____Z (MJIEnv env, int clsObjRef, FeatureExpr ctx){ return false; } @MJI public boolean isRunTestRun____Z (MJIEnv env, int clsObjRef, FeatureExpr ctx){ return false; } // we need to override these so that the actual test code gets executed // if we fail to intercept, the bytecode will actually start JPF @MJI public int noPropertyViolation___3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int jpfArgsRef, FeatureExpr ctx){ return MJIEnv.NULL; } @MJI public boolean verifyNoPropertyViolation___3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, Conditional<Integer> jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public boolean verifyAssertionErrorDetails__Ljava_lang_String_2_3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int detailsRef, int jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public boolean verifyAssertionError___3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public int unhandledException__Ljava_lang_String_2Ljava_lang_String_2_3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int xClassNameRef, int detailsRef, int jpfArgsRef, FeatureExpr ctx){ return MJIEnv.NULL; } @MJI public boolean verifyUnhandledException__Ljava_lang_String_2_3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, Conditional<Integer> xClassNameRef, Conditional<Integer> jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public boolean verifyUnhandledExceptionDetails__Ljava_lang_String_2Ljava_lang_String_2_3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int xClassNameRef, int detailsRef, int jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public int propertyViolation__Ljava_lang_Class_2_3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int propClsRef, int jpfArgsRef, FeatureExpr ctx){ return MJIEnv.NULL; } @MJI public boolean verifyPropertyViolation__Lgov_nasa_jpf_util_TypeRef_2_3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int propClsRef, int jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public int jpfException__Ljava_lang_Class_2_3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int xClsRef, int jpfArgsRef, FeatureExpr ctx){ return MJIEnv.NULL; } @MJI public boolean verifyJPFException__Lgov_nasa_jpf_util_TypeRef_2_3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int xClsRef, int jpfArgsRef, FeatureExpr ctx){ return true; } @MJI public int deadlock___3Ljava_lang_String_2__Lgov_nasa_jpf_JPF_2 (MJIEnv env, int clsObjRef, int jpfArgsRef, FeatureExpr ctx){ return MJIEnv.NULL; } @MJI public boolean verifyDeadlock___3Ljava_lang_String_2__Z (MJIEnv env, int clsObjRef, int jpfArgsRef, FeatureExpr ctx){ return true; } }