//
// Copyright (C) 2010 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.test.mc.basic;
import java.util.ArrayList;
import org.junit.Test;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.ListenerAdapter;
import gov.nasa.jpf.search.Search;
import gov.nasa.jpf.util.test.TestJPF;
import gov.nasa.jpf.vm.ElementInfo;
import gov.nasa.jpf.vm.MethodInfo;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.VM;
/**
* test of the VMListener method notifications
*/
public class MethodListenerTest extends TestJPF {
// avoid loading JPF classes when running under JPF (specify classnames explicitly)
static String CLSNAME = "gov.nasa.jpf.test.mc.basic.MethodListenerTest";
static String LISTENER = "+listener=gov.nasa.jpf.test.mc.basic.MethodListenerTest$Listener";
public static class Listener extends ListenerAdapter {
String startMthName;
boolean traceActive = false;
int level;
public Listener (Config config){
startMthName = config.getString("_start");
}
String levelPrefix (int lvl){
String prefix = "";
for (int i=0; i<lvl; i++){
prefix += " ";
}
return prefix;
}
@Override
public void searchStarted(Search search) {
trace.clear();
}
@Override
public void methodEntered (VM vm, ThreadInfo ti, MethodInfo mi){
assertSame(mi, ThreadInfo.getCurrentThread().getTopFrameMethodInfo());
if (CLSNAME.equals(mi.getClassName())){
String mthName = mi.getName();
if (mthName.equals(startMthName)) {
traceActive = true;
level=0;
}
if (traceActive){
String prefix = levelPrefix(level);
trace.add(prefix + "> " + mthName);
System.out.println(prefix + "> " + mthName);
level++;
}
}
}
@Override
public void methodExited (VM vm, ThreadInfo ti, MethodInfo mi){
if (traceActive){
assertSame(mi, ThreadInfo.getCurrentThread().getTopFrameMethodInfo());
if (CLSNAME.equals(mi.getClassName())){
level--;
String prefix = levelPrefix(level);
trace.add(prefix + "< " + mi.getName());
System.out.println(prefix + "< " + mi.getName());
if (level == 0){
traceActive = false;
}
}
}
}
@Override
public void exceptionThrown (VM vm, ThreadInfo ti, ElementInfo ei){
if (traceActive){
String xCls = ei.getClassInfo().getName();
trace.add("X " + xCls);
System.out.println("X " + xCls);
}
}
}
static ArrayList<String> trace = new ArrayList<String>();
static boolean traceEquals(String... expected){
if (expected.length != trace.size()){
System.err.println("wrong trace size, found: " + trace.size() + ", expected: " + expected.length);
return false;
}
int i = 0;
for (String s : trace){
if (!s.equals(expected[i])){
System.err.println("wrong trace entry, found: " + s + ", expected: " + expected[i]);
return false;
}
i++;
}
return true;
}
//--- internal test stuff
void foo(){
bar();
}
int bar(){
return 24;
}
void baz (){
blowUp();
}
void blowUp() {
throw new RuntimeException("I blow up");
}
void time() {
System.currentTimeMillis();
}
//--- test methods
@Test public void testBasicInvocation() {
if (verifyNoPropertyViolation(LISTENER, "+_start=testBasicInvocation")){
foo();
} else {
assertTrue(traceEquals(
"> testBasicInvocation",
" > foo",
" > bar",
" < bar",
" < foo",
"< testBasicInvocation"));
}
}
@Test public void testException() {
if (verifyNoPropertyViolation(LISTENER, "+_start=testException")){
try {
baz();
} catch (RuntimeException x){
}
} else {
assertTrue(traceEquals(
"> testException",
" > baz",
" > blowUp",
"X java.lang.RuntimeException",
" < blowUp",
" < baz",
"< testException"));
}
}
}