Adding ability to delay before executing a step in STC.

Change-Id: I9822ac35d37e6735068ebdf39b952db913a10e14
diff --git a/tools/test/scenarios/archetypes.xml b/tools/test/scenarios/archetypes.xml
index 9a136e3..307a206 100644
--- a/tools/test/scenarios/archetypes.xml
+++ b/tools/test/scenarios/archetypes.xml
@@ -73,7 +73,7 @@
               exec="mvn clean install"/>
         <step name="Install-REST-App" requires="^,~Verify-UI-Topo"
               exec="onos-app ${OCI} reinstall! target/test-app-1.2.3.oar"/>
-        <Xstep name="Verify-REST-App" requires="^" delay="2"
+        <step name="Verify-REST-App" requires="^" delay="2"
               exec="curl --fail -isS --user ${ONOS_WEB_USER}:${ONOS_WEB_PASS} http://${OCI}:8181/onos/test-app/sample"/>
 
         <step name="Uninstall-App" requires="^"
diff --git a/utils/stc/src/main/java/org/onlab/stc/Compiler.java b/utils/stc/src/main/java/org/onlab/stc/Compiler.java
index 919cbd5..64e0153 100644
--- a/utils/stc/src/main/java/org/onlab/stc/Compiler.java
+++ b/utils/stc/src/main/java/org/onlab/stc/Compiler.java
@@ -32,6 +32,7 @@
 
 import static com.google.common.base.Preconditions.*;
 import static com.google.common.base.Strings.isNullOrEmpty;
+import static java.lang.Integer.parseInt;
 import static org.onlab.graph.DepthFirstSearch.EdgeType.BACK_EDGE;
 import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
 import static org.onlab.stc.Scenario.loadScenario;
@@ -56,6 +57,7 @@
     private static final String COMMAND = "[@exec]";
     private static final String ENV = "[@env]";
     private static final String CWD = "[@cwd]";
+    private static final String DELAY = "[@delay]";
     private static final String REQUIRES = "[@requires]";
     private static final String IF = "[@if]";
     private static final String UNLESS = "[@unless]";
@@ -245,9 +247,10 @@
         String command = expand(cfg.getString(COMMAND, parentGroup != null ? parentGroup.command() : null), true);
         String env = expand(cfg.getString(ENV, parentGroup != null ? parentGroup.env() : null));
         String cwd = expand(cfg.getString(CWD, parentGroup != null ? parentGroup.cwd() : null));
+        int delay = parseInt(expand(cfg.getString(DELAY, parentGroup != null ? "" + parentGroup.delay() : "0")));
 
-        print("step name=%s command=%s env=%s cwd=%s", name, command, env, cwd);
-        Step step = new Step(name, command, env, cwd, parentGroup);
+        print("step name=%s command=%s env=%s cwd=%s delay=%d", name, command, env, cwd, delay);
+        Step step = new Step(name, command, env, cwd, parentGroup, delay);
         registerStep(step, cfg, namespace, parentGroup);
     }
 
@@ -264,9 +267,10 @@
         String command = expand(cfg.getString(COMMAND, parentGroup != null ? parentGroup.command() : null), true);
         String env = expand(cfg.getString(ENV, parentGroup != null ? parentGroup.env() : null));
         String cwd = expand(cfg.getString(CWD, parentGroup != null ? parentGroup.cwd() : null));
+        int delay = parseInt(expand(cfg.getString(DELAY, parentGroup != null ? "" + parentGroup.delay() : "0")));
 
-        print("group name=%s command=%s env=%s cwd=%s", name, command, env, cwd);
-        Group group = new Group(name, command, env, cwd, parentGroup);
+        print("group name=%s command=%s env=%s cwd=%s delay=%d", name, command, env, cwd, delay);
+        Group group = new Group(name, command, env, cwd, parentGroup, delay);
         if (registerStep(group, cfg, namespace, parentGroup)) {
             compile(cfg, namespace, group);
         }
diff --git a/utils/stc/src/main/java/org/onlab/stc/Group.java b/utils/stc/src/main/java/org/onlab/stc/Group.java
index 0281c36..e5f6efd 100644
--- a/utils/stc/src/main/java/org/onlab/stc/Group.java
+++ b/utils/stc/src/main/java/org/onlab/stc/Group.java
@@ -35,9 +35,10 @@
      * @param env     default path to file to be sourced into the environment
      * @param cwd     default path to current working directory for the step
      * @param group   optional group to which this step belongs
+     * @param delay   seconds to delay before executing
      */
-    public Group(String name, String command, String env, String cwd, Group group) {
-        super(name, command, env, cwd, group);
+    public Group(String name, String command, String env, String cwd, Group group, int delay) {
+        super(name, command, env, cwd, group, delay);
     }
 
     /**
diff --git a/utils/stc/src/main/java/org/onlab/stc/Step.java b/utils/stc/src/main/java/org/onlab/stc/Step.java
index e14addb..0c2c8ed 100644
--- a/utils/stc/src/main/java/org/onlab/stc/Step.java
+++ b/utils/stc/src/main/java/org/onlab/stc/Step.java
@@ -32,6 +32,7 @@
     protected final String env;
     protected final String cwd;
     protected final Group group;
+    protected final int delay;
 
     /**
      * Creates a new test step.
@@ -41,10 +42,12 @@
      * @param env     path to file to be sourced into the environment
      * @param cwd     path to current working directory for the step
      * @param group   optional group to which this step belongs
+     * @param delay   seconds to delay before executing
      */
-    public Step(String name, String command, String env, String cwd, Group group) {
+    public Step(String name, String command, String env, String cwd, Group group, int delay) {
         this.name = checkNotNull(name, "Name cannot be null");
         this.group = group;
+        this.delay = delay;
 
         // Set the command, environment and cwd
         // If one is not given use the value from the enclosing group
@@ -98,6 +101,14 @@
         return group;
     }
 
+    /**
+     * Returns the start delay in seconds.
+     *
+     * @return number of seconds
+     */
+    public int delay() {
+        return delay;
+    }
 
     @Override
     public int hashCode() {
@@ -124,6 +135,7 @@
                 .add("env", env)
                 .add("cwd", cwd)
                 .add("group", group)
+                .add("delay", delay)
                 .toString();
     }
 }
diff --git a/utils/stc/src/main/java/org/onlab/stc/StepProcessor.java b/utils/stc/src/main/java/org/onlab/stc/StepProcessor.java
index 4994369..f88c4bf1 100644
--- a/utils/stc/src/main/java/org/onlab/stc/StepProcessor.java
+++ b/utils/stc/src/main/java/org/onlab/stc/StepProcessor.java
@@ -38,6 +38,7 @@
     private static final String NEGATE_CODE = "!";
 
     private static final int FAIL = -1;
+    private static final int SECONDS = 1_000;
 
     static String launcher = "stc-launcher ";
 
@@ -67,6 +68,7 @@
     @Override
     public void run() {
         delegate.onStart(step, command);
+        delayIfNeeded();
         int code = execute();
         boolean ignoreCode = step.env() != null && step.env.equals(IGNORE_CODE);
         boolean negateCode = step.env() != null && step.env.equals(NEGATE_CODE);
@@ -76,6 +78,19 @@
     }
 
     /**
+     * Pauses if the step requires it.
+     */
+    private void delayIfNeeded() {
+        if (step.delay() > 0) {
+            try {
+                Thread.sleep(step.delay() * SECONDS);
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Interrupted", e);
+            }
+        }
+    }
+
+    /**
      * Executes the step process.
      *
      * @return exit code
diff --git a/utils/stc/src/test/java/org/onlab/stc/DependencyTest.java b/utils/stc/src/test/java/org/onlab/stc/DependencyTest.java
index 4438303..cb989d8 100644
--- a/utils/stc/src/test/java/org/onlab/stc/DependencyTest.java
+++ b/utils/stc/src/test/java/org/onlab/stc/DependencyTest.java
@@ -32,8 +32,8 @@
     @Before
     public void setUp() throws ConfigurationException {
         super.setUp();
-        step1 = new Step("step1", CMD, null, null, null);
-        step2 = new Step("step2", CMD, null, null, null);
+        step1 = new Step("step1", CMD, null, null, null, 0);
+        step2 = new Step("step2", CMD, null, null, null, 0);
     }
 
     @Test
diff --git a/utils/stc/src/test/java/org/onlab/stc/GroupTest.java b/utils/stc/src/test/java/org/onlab/stc/GroupTest.java
index 9b612c8..ad7eb42 100644
--- a/utils/stc/src/test/java/org/onlab/stc/GroupTest.java
+++ b/utils/stc/src/test/java/org/onlab/stc/GroupTest.java
@@ -28,23 +28,24 @@
 
     @Test
     public void basics() {
-        Group group = new Group(NAME, CMD, ENV, CWD, parent);
+        Group group = new Group(NAME, CMD, ENV, CWD, parent, 1);
         assertEquals("incorrect name", NAME, group.name());
         assertEquals("incorrect command", CMD, group.command());
         assertEquals("incorrect env", ENV, group.env());
         assertEquals("incorrect cwd", CWD, group.cwd());
         assertSame("incorrect group", parent, group.group());
+        assertEquals("incorrect delay", 1, group.delay());
 
-        Step step = new Step("step", null, null, null, group);
+        Step step = new Step("step", null, null, null, group, 0);
         group.addChild(step);
         assertSame("incorrect child", step, group.children().iterator().next());
     }
 
     @Test
     public void equality() {
-        Group g1 = new Group(NAME, CMD, null, null, parent);
-        Group g2 = new Group(NAME, CMD, ENV, CWD, null);
-        Group g3 = new Group("foo", null, null, null, parent);
+        Group g1 = new Group(NAME, CMD, null, null, parent, 0);
+        Group g2 = new Group(NAME, CMD, ENV, CWD, null, 0);
+        Group g3 = new Group("foo", null, null, null, parent, 0);
         new EqualsTester()
                 .addEqualityGroup(g1, g2)
                 .addEqualityGroup(g3)
diff --git a/utils/stc/src/test/java/org/onlab/stc/StepProcessorTest.java b/utils/stc/src/test/java/org/onlab/stc/StepProcessorTest.java
index 74d5024..6fd9ee1 100644
--- a/utils/stc/src/test/java/org/onlab/stc/StepProcessorTest.java
+++ b/utils/stc/src/test/java/org/onlab/stc/StepProcessorTest.java
@@ -50,7 +50,7 @@
 
     @Test
     public void basics() {
-        Step step = new Step("foo", "ls " + DIR.getAbsolutePath(), null, null, null);
+        Step step = new Step("foo", "ls " + DIR.getAbsolutePath(), null, null, null, 0);
         StepProcessor processor = new StepProcessor(step, DIR, delegate, step.command());
         processor.run();
         assertTrue("should be started", delegate.started);
diff --git a/utils/stc/src/test/java/org/onlab/stc/StepTest.java b/utils/stc/src/test/java/org/onlab/stc/StepTest.java
index 7108362..659876e 100644
--- a/utils/stc/src/test/java/org/onlab/stc/StepTest.java
+++ b/utils/stc/src/test/java/org/onlab/stc/StepTest.java
@@ -36,24 +36,25 @@
 
     @Before
     public void setUp() throws ConfigurationException {
-        parent = new Group("parent", null, null, null, null);
+        parent = new Group("parent", null, null, null, null, 0);
     }
 
     @Test
     public void basics() {
-        Step step = new Step(NAME, CMD, ENV, CWD, parent);
+        Step step = new Step(NAME, CMD, ENV, CWD, parent, 1);
         assertEquals("incorrect name", NAME, step.name());
         assertEquals("incorrect command", CMD, step.command());
         assertEquals("incorrect env", ENV, step.env());
         assertEquals("incorrect cwd", CWD, step.cwd());
         assertSame("incorrect group", parent, step.group());
+        assertEquals("incorrect delay", 1, step.delay());
     }
 
     @Test
     public void equality() {
-        Step s1 = new Step(NAME, CMD, null, null, parent);
-        Step s2 = new Step(NAME, CMD, ENV, CWD, null);
-        Step s3 = new Step("foo", null, null, null, parent);
+        Step s1 = new Step(NAME, CMD, null, null, parent, 0);
+        Step s2 = new Step(NAME, CMD, ENV, CWD, null, 0);
+        Step s3 = new Step("foo", null, null, null, parent, 0);
         new EqualsTester()
                 .addEqualityGroup(s1, s2)
                 .addEqualityGroup(s3)