some bugfixes regarding timeouts in test scripts, with simplified code

This commit is contained in:
Fredrik Osterlind 2012-03-23 15:14:24 +01:00
parent a9e36b0365
commit c78b5bad5c
3 changed files with 246 additions and 225 deletions

View File

@ -34,6 +34,7 @@ import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Dialog; import java.awt.Dialog;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Frame; import java.awt.Frame;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
@ -41,7 +42,6 @@ import java.awt.GraphicsEnvironment;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Window; import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter; import java.awt.event.ComponentAdapter;
@ -3051,7 +3051,12 @@ public class GUI extends Observable {
System.exit(1); System.exit(1);
} }
plugin.updateScript(scriptFile); plugin.updateScript(scriptFile);
plugin.setScriptActive(true); try {
plugin.setScriptActive(true);
} catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e);
System.exit(1);
}
sim.setDelayTime(0); sim.setDelayTime(0);
sim.startSimulation(); sim.startSimulation();
} else { } else {
@ -3704,7 +3709,7 @@ public class GUI extends Observable {
private static void showWarningsDialog(final Frame parent, final String[] warnings) { private static void showWarningsDialog(final Frame parent, final String[] warnings) {
new RunnableInEDT<Boolean>() { new RunnableInEDT<Boolean>() {
public Boolean work() { public Boolean work() {
final JDialog dialog = new JDialog((Frame)parent, "Compilation warnings", false); final JDialog dialog = new JDialog(parent, "Compilation warnings", false);
Box buttonBox = Box.createHorizontalBox(); Box buttonBox = Box.createHorizontalBox();
/* Warnings message list */ /* Warnings message list */

View File

@ -97,6 +97,11 @@ public class LogScriptEngine {
private boolean scriptActive = false; private boolean scriptActive = false;
private long timeout;
private long startTime;
private long startRealTime;
private long nextProgress;
private interface ScriptLog { private interface ScriptLog {
public void log(String log); public void log(String log);
public void testOK(); public void testOK();
@ -104,6 +109,10 @@ public class LogScriptEngine {
public void generateMessage(long delay, String msg); public void generateMessage(long delay, String msg);
} }
public LogScriptEngine(Simulation simulation) {
this.simulation = simulation;
}
/* Only called from the simulation loop */ /* Only called from the simulation loop */
private void stepScript() { private void stepScript() {
/* Release script - halt simulation */ /* Release script - halt simulation */
@ -130,10 +139,6 @@ public class LogScriptEngine {
} }
} }
public LogScriptEngine(Simulation simulation) {
this.simulation = simulation;
}
/* Only called from the simulation loop */ /* Only called from the simulation loop */
private void handleNewMoteOutput(Mote mote, int id, long time, String msg) { private void handleNewMoteOutput(Mote mote, int id, long time, String msg) {
try { try {
@ -195,16 +200,6 @@ public class LogScriptEngine {
} }
scriptActive = false; scriptActive = false;
if (semaphoreScript == null) {
/*logger.warn("semaphoreScript is not initialized");*/
}
if (semaphoreSim == null) {
/*logger.warn("semaphoreSim is not initialized");*/
}
if (scriptThread == null) {
/*logger.warn("scriptThread is not initialized");*/
}
timeoutEvent.remove(); timeoutEvent.remove();
timeoutProgressEvent.remove(); timeoutProgressEvent.remove();
@ -213,13 +208,17 @@ public class LogScriptEngine {
engine.put("SHUTDOWN", true); engine.put("SHUTDOWN", true);
try { try {
semaphoreScript.release(100); if (semaphoreScript != null) {
semaphoreScript.release(100);
}
} catch (Exception e) { } catch (Exception e) {
} finally { } finally {
semaphoreScript = null; semaphoreScript = null;
} }
try { try {
semaphoreSim.release(100); if (semaphoreSim != null) {
semaphoreSim.release(100);
}
} catch (Exception e) { } catch (Exception e) {
} finally { } finally {
semaphoreSim = null; semaphoreSim = null;
@ -235,7 +234,6 @@ public class LogScriptEngine {
} }
} }
scriptThread = null; scriptThread = null;
} }
public void activateScript(String scriptCode) throws ScriptException { public void activateScript(String scriptCode) throws ScriptException {
@ -245,43 +243,29 @@ public class LogScriptEngine {
scriptActive = true; scriptActive = true;
if (semaphoreScript != null) { if (semaphoreScript != null) {
logger.warn("semaphoreScript is already initialized"); logger.warn("Semaphores were not reset correctly");
semaphoreScript.release(100);
semaphoreScript = null;
} }
if (semaphoreSim != null) { if (semaphoreSim != null) {
logger.warn("semaphoreSim is already initialized"); logger.warn("Semaphores were not reset correctly");
} semaphoreSim.release(100);
if (scriptThread != null) { semaphoreSim = null;
logger.warn("scriptThread is already initialized");
} }
scriptThread = null;
/* Parse current script */ /* Parse current script */
ScriptParser parser = new ScriptParser(scriptCode); ScriptParser parser = new ScriptParser(scriptCode);
String jsCode = parser.getJSCode(); String jsCode = parser.getJSCode();
long timeoutTime = parser.getTimeoutTime(); timeout = parser.getTimeoutTime();
if (timeoutTime < 0) { if (timeout < 0) {
logger.info("No timeout defined, using default (us): " + DEFAULT_TIMEOUT); timeout = DEFAULT_TIMEOUT;
timeoutTime = DEFAULT_TIMEOUT; logger.info("Default script timeout in " + (timeout/Simulation.MILLISECOND) + " ms");
} else {
logger.info("Script timeout in " + (timeout/Simulation.MILLISECOND) + " ms");
} }
final long duration = timeoutTime;
simulation.invokeSimulationThread(new Runnable() {
public void run() {
final long startTime = simulation.getSimulationTime();
final long interval = (long) (0.01*5*duration);
simulation.scheduleEvent(timeoutProgressEvent = new TimeEvent(0) {
public void execute(long t) {
int percent = (int) (5*(t-startTime)/interval);
logger.info("Test script at " + percent + "%");
simulation.scheduleEvent(this, t+interval);
}
}, startTime+interval);
simulation.scheduleEvent(timeoutEvent, startTime + duration);
}
});
engine.eval(jsCode); engine.eval(jsCode);
/* Setup script control */ /* Setup script control */
@ -352,95 +336,7 @@ public class LogScriptEngine {
simulation.getEventCentral().addLogOutputListener(logOutputListener); simulation.getEventCentral().addLogOutputListener(logOutputListener);
/* Create script output logger */ /* Create script output logger */
engine.put("log", new ScriptLog() { engine.put("log", scriptLog);
public void log(String msg) {
if (scriptLogObserver != null) {
scriptLogObserver.update(null, msg);
}
}
public void append(String filename, String msg) {
try{
FileWriter fstream = new FileWriter(filename, true);
BufferedWriter out = new BufferedWriter(fstream);
out.write(msg);
out.close();
} catch (Exception e) {
logger.warn("Test append failed: " + filename + ": " + e.getMessage());
}
}
public void testOK() {
log("TEST OK\n");
if (GUI.isVisualized()) {
log("[if test was run without visualization, COOJA would now have been terminated]\n");
stopSimulation = true;
simulation.invokeSimulationThread(stopSimulationRunnable);
} else {
quitCooja = true;
simulation.invokeSimulationThread(quitRunnable);
}
timeoutEvent.remove();
timeoutProgressEvent.remove();
semaphoreSim.release(100);
throw new RuntimeException("test script killed");
}
public void writeFile(String filename, String msg) {
try{
FileWriter fstream = new FileWriter(filename, false);
BufferedWriter out = new BufferedWriter(fstream);
out.write(msg);
out.close();
} catch (Exception e) {
logger.warn("Write file failed: " + filename + ": " + e.getMessage());
}
}
public void testFailed() {
log("TEST FAILED\n");
if (GUI.isVisualized()) {
log("[if test was run without visualization, COOJA would now have been terminated]\n");
stopSimulation = true;
simulation.invokeSimulationThread(stopSimulationRunnable);
} else {
quitCooja = true;
simulation.invokeSimulationThread(quitRunnable);
}
semaphoreSim.release(100);
throw new RuntimeException("test script killed");
}
public void generateMessage(final long delay, final String msg) {
final Mote currentMote = (Mote) engine.get("mote");
final TimeEvent generateEvent = new TimeEvent(0) {
public void execute(long t) {
if (scriptThread == null ||
!scriptThread.isAlive()) {
logger.info("script thread not alive. try deactivating script.");
/*scriptThread.isInterrupted()*/
return;
}
/* Update script variables */
engine.put("mote", currentMote);
engine.put("id", currentMote.getID());
engine.put("time", currentMote.getSimulation().getSimulationTime());
engine.put("msg", msg);
stepScript();
}
};
simulation.invokeSimulationThread(new Runnable() {
public void run() {
simulation.scheduleEvent(
generateEvent,
simulation.getSimulationTime() + delay*Simulation.MILLISECOND);
}
});
}
});
Hashtable<Object, Object> hash = new Hashtable<Object, Object>(); Hashtable<Object, Object> hash = new Hashtable<Object, Object>();
engine.put("global", hash); engine.put("global", hash);
@ -449,27 +345,53 @@ public class LogScriptEngine {
scriptMote = new ScriptMote(); scriptMote = new ScriptMote();
engine.put("node", scriptMote); engine.put("node", scriptMote);
Runnable activate = new Runnable() {
public void run() {
startRealTime = System.currentTimeMillis();
startTime = simulation.getSimulationTime();
long endTime = startTime + timeout;
nextProgress = startTime + (endTime - startTime)/20;
timeoutProgressEvent.remove();
simulation.scheduleEvent(timeoutProgressEvent, nextProgress);
timeoutEvent.remove();
simulation.scheduleEvent(timeoutEvent, endTime);
}
};
if (simulation.isRunning()) {
simulation.invokeSimulationThread(activate);
} else {
activate.run();
}
} }
private TimeEvent timeoutEvent = new TimeEvent(0) { private TimeEvent timeoutEvent = new TimeEvent(0) {
public void execute(long t) { public void execute(long t) {
if (!scriptActive) { if (!scriptActive) {
return; return;
} }
logger.info("Timeout event @ " + t); logger.info("Timeout event @ " + t);
engine.put("TIMEOUT", true); engine.put("TIMEOUT", true);
stepScript(); stepScript();
} }
}; };
private TimeEvent timeoutProgressEvent = new TimeEvent(0) { private TimeEvent timeoutProgressEvent = new TimeEvent(0) {
public void execute(long t) { } public void execute(long t) {
}; nextProgress = t + timeout/20;
simulation.scheduleEvent(this, nextProgress);
double progress = 1.0*(t - startTime)/timeout;
long realDuration = System.currentTimeMillis()-startRealTime;
double estimatedLeft = 1.0*realDuration/progress - realDuration;
if (estimatedLeft == 0) estimatedLeft = 1;
logger.info(String.format("Test script at %2.2f%%, done in %2.1f sec", 100*progress, estimatedLeft/1000));
}
};
private Runnable stopSimulationRunnable = new Runnable() { private Runnable stopSimulationRunnable = new Runnable() {
public void run() { public void run() {
simulation.stopSimulation(); simulation.stopSimulation();
timeoutEvent.remove();
timeoutProgressEvent.remove();
} }
}; };
private Runnable quitRunnable = new Runnable() { private Runnable quitRunnable = new Runnable() {
@ -491,4 +413,83 @@ public class LogScriptEngine {
} }
}; };
private ScriptLog scriptLog = new ScriptLog() {
public void log(String msg) {
if (scriptLogObserver != null) {
scriptLogObserver.update(null, msg);
}
}
public void append(String filename, String msg) {
try{
FileWriter fstream = new FileWriter(filename, true);
BufferedWriter out = new BufferedWriter(fstream);
out.write(msg);
out.close();
} catch (Exception e) {
logger.warn("Test append failed: " + filename + ": " + e.getMessage());
}
}
public void writeFile(String filename, String msg) {
try{
FileWriter fstream = new FileWriter(filename, false);
BufferedWriter out = new BufferedWriter(fstream);
out.write(msg);
out.close();
} catch (Exception e) {
logger.warn("Write file failed: " + filename + ": " + e.getMessage());
}
}
public void testOK() {
log("TEST OK\n");
deactive();
}
public void testFailed() {
log("TEST FAILED\n");
deactive();
}
private void deactive() {
deactivateScript();
if (GUI.isVisualized()) {
log("[if test was run without visualization, COOJA would now have been terminated]\n");
stopSimulation = true;
simulation.invokeSimulationThread(stopSimulationRunnable);
} else {
quitCooja = true;
simulation.invokeSimulationThread(quitRunnable);
}
throw new RuntimeException("test script killed");
}
public void generateMessage(final long delay, final String msg) {
final Mote currentMote = (Mote) engine.get("mote");
final TimeEvent generateEvent = new TimeEvent(0) {
public void execute(long t) {
if (scriptThread == null ||
!scriptThread.isAlive()) {
logger.info("script thread not alive. try deactivating script.");
/*scriptThread.isInterrupted()*/
return;
}
/* Update script variables */
engine.put("mote", currentMote);
engine.put("id", currentMote.getID());
engine.put("time", currentMote.getSimulation().getSimulationTime());
engine.put("msg", msg);
stepScript();
}
};
simulation.invokeSimulationThread(new Runnable() {
public void run() {
simulation.scheduleEvent(
generateEvent,
simulation.getSimulationTime() + delay*Simulation.MILLISECOND);
}
});
}
};
} }

View File

@ -92,8 +92,7 @@ public class ScriptRunner extends VisPlugin {
static boolean headless; static boolean headless;
{ {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); headless = GraphicsEnvironment.isHeadless();
headless = ge.isHeadless();
if (!headless) { if (!headless) {
DefaultSyntaxKit.initKit(); DefaultSyntaxKit.initKit();
} }
@ -183,10 +182,14 @@ public class ScriptRunner extends VisPlugin {
toggleButton = new JButton("Activate"); toggleButton = new JButton("Activate");
toggleButton.addActionListener(new ActionListener() { toggleButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) { public void actionPerformed(ActionEvent ev) {
if (toggleButton.getText().equals("Activate")) { try {
setScriptActive(true); if (!isActive()) {
} else { setScriptActive(true);
setScriptActive(false); } else {
setScriptActive(false);
}
} catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e);
} }
} }
}); });
@ -276,7 +279,8 @@ public class ScriptRunner extends VisPlugin {
updateTitle(); updateTitle();
} }
public void setScriptActive(boolean active) { public void setScriptActive(boolean active)
throws Exception {
if (active) { if (active) {
/* setScriptActive(true) */ /* setScriptActive(true) */
@ -612,7 +616,10 @@ public class ScriptRunner extends VisPlugin {
} }
public void closePlugin() { public void closePlugin() {
setScriptActive(false); try {
setScriptActive(false);
} catch (Exception e) {
}
} }
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) { public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
@ -628,14 +635,22 @@ public class ScriptRunner extends VisPlugin {
} else if ("active".equals(name)) { } else if ("active".equals(name)) {
boolean active = Boolean.parseBoolean(element.getText()); boolean active = Boolean.parseBoolean(element.getText());
if (GUI.isVisualized()) { if (GUI.isVisualized()) {
setScriptActive(active); try {
setScriptActive(active);
} catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e);
}
} }
} }
} }
if (!GUI.isVisualized()) { if (!GUI.isVisualized()) {
/* Automatically activate script */ /* Automatically activate script */
setScriptActive(true); try {
setScriptActive(true);
} catch (Exception e) {
logger.fatal("Error: " + e.getMessage(), e);
}
simulation.setDelayTime(0); simulation.setDelayTime(0);
simulation.startSimulation(); simulation.startSimulation();
} }