Added check for cyclic dependencies.
Changes intent test scenarios to use the key and added dependencies to make them more robust; h2h still fails intermittently due to a bug.
Increased parallelism of the smoke test scenario.
Change-Id: Ib7fed38d17d1b25c5dd854ef1cd4dc777002c5fc
diff --git a/tools/test/bin/onos-check-apps b/tools/test/bin/onos-check-apps
index 9bdf393..dfd6b4e 100755
--- a/tools/test/bin/onos-check-apps
+++ b/tools/test/bin/onos-check-apps
@@ -9,16 +9,26 @@
aux=/tmp/stc-$$.log
trap "rm -f $aux $aux.1 $aux.2 2>/dev/null" EXIT
-onos ${1:-$OCI} "onos:apps -s -a" | grep -v /bin/client > $aux
-cat $aux
+for attempt in {1..3}; do
+ onos ${1:-$OCI} "onos:apps -s -a" | grep -v /bin/client > $aux
+ cat $aux
-# Normalize the installed apps
-cut -c7- $aux | grep -v '/bin/client' | cut -d\ -f1 | sort > $aux.1
+ # Normalize the installed apps
+ cut -c7- $aux | grep -v '/bin/client' | cut -d\ -f1 | sort > $aux.1
-# Normalize the expected apps
-apps=${2:-$ONOS_APPS}
-apps=${apps:-drivers,openflow}
-(for app in ${apps//,/ }; do echo org.onosproject.$app; done) | sort > $aux.2
+ # Normalize the expected apps
+ apps=${2:-$ONOS_APPS}
+ apps=${apps:-drivers,openflow}
+ (for app in ${apps//,/ }; do echo org.onosproject.$app; done) | sort > $aux.2
-# Check for differences
-diff $aux.1 $aux.2
+ # Check for differences
+ case ${3:-equals} in
+ equals) diff $aux.1 $aux.2;;
+ includes) [ $(egrep -c -f $aux.2 $aux.1) -eq $(wc -l $aux.2 | sed "s|$aux.2||g") ];;
+ excludes) ! egrep -f $aux.2 $aux.1;;
+ esac
+
+ [ $? -eq 0 ] && exit 0 || sleep 1
+done
+
+exit 1;
diff --git a/tools/test/bin/onos-check-intent b/tools/test/bin/onos-check-intent
index 55410ad..e332dc5 100755
--- a/tools/test/bin/onos-check-intent
+++ b/tools/test/bin/onos-check-intent
@@ -13,9 +13,9 @@
echo onos-check-intent: $*
set -x
-for i in 1 2 3; do
- onos $target "onos:intents" > $aux
- ( cat $aux | grep "id=$2" | grep "state=$3" ) && cat $aux && exit 0
+for i in {1..10}; do
+ onos $target "onos:intents" | tee $aux
+ ( cat $aux | grep "key=$2" | grep "state=$3" ) && cat $aux && exit 0
sleep 1
done
diff --git a/tools/test/bin/onos-create-intent b/tools/test/bin/onos-create-intent
index 6482103..d1c0b93 100755
--- a/tools/test/bin/onos-create-intent
+++ b/tools/test/bin/onos-create-intent
@@ -18,15 +18,5 @@
set -x
-onos $target "onos:add-${type}-intent" "${arg1}" "${arg2}" >> $aux
-result=$?
-cat $aux
-
-if [ $result -eq 0 ]; then
- id=$(cat $aux | sed -e "1d" | sed -e "s/^[a-zA-Z]*{//" | sed -e "s/,.*$//" | sed -e "s/^...//")
- echo @stc ${name}Id=${id}
-fi
-
-
-exit $result
+onos $target "onos:add-${type}-intent" --key $name "${arg1}" "${arg2}"
diff --git a/tools/test/scenarios/net-host-intent.xml b/tools/test/scenarios/net-host-intent.xml
index 88b79bf..fbf8c4a 100644
--- a/tools/test/scenarios/net-host-intent.xml
+++ b/tools/test/scenarios/net-host-intent.xml
@@ -16,36 +16,44 @@
<scenario name="net-host-intent" description="Network host intent connectivity test">
<!-- TODO: parametrize this via recipes -->
<group name="Host-Intent-Connectivity">
- <step name="Uninstall-Reactive-Forwarding"
+ <step name="Host-Intent.Uninstall-Reactive-Forwarding"
exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="Host-Intent.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
- <step name="Find-Host-1" requires="^"
- exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect ."/>
- <step name="Find-Host-2" requires="^"
- exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect ."/>
+ <step name="Host-Intent.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect ."/>
+ <step name="Host-Intent.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect ."/>
- <step name="Create-Intent" requires="^"
- exec="onos-create-intent ${OC1} hostToHost host 00:00:00:00:00:01/-1 00:00:00:00:00:04/-1"/>
- <step name="Validate-Intent-Installed" exec="onos-check-intent ${OC1} ${hostToHostId} INSTALLED"
- requires="Create-Intent" />
+ <step name="Host-Intent.Create-Intent" requires="^"
+ exec="onos-create-intent ${OC1} h2h host 00:00:00:00:00:01/-1 00:00:00:00:00:04/-1"/>
+ <step name="Host-Intent.Validate-Intent-Installed" requires="Host-Intent.Create-Intent"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
<import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Host-Intent"/>
- <dependency name="Host-Intent.Net-Link-Down-Up" requires="Validate-Intent-Installed"/>
+ <dependency name="Host-Intent.Net-Link-Down-Up"
+ requires="Host-Intent.Validate-Intent-Installed"/>
- <step name="Validate-Intent-Installed-Still" exec="onos-check-intent ${OC1} ${hostToHostId} INSTALLED"
- requires="Host-Intent.Link-1-Down" />
+ <step name="Host-Intent.Validate-Intent-Installed-Still" requires="Host-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
- <step name="Validate-Intent-Failed" exec="onos-check-intent ${OC1} ${hostToHostId} FAILED"
- requires="Host-Intent.Link-2-Down" />
+ <dependency name="Host-Intent.Link-2-Down"
+ requires="~Host-Intent.Validate-Intent-Installed-Still" />
- <step name="Validate-Intent-Installed-Again" exec="onos-check-intent ${OC1} ${hostToHostId} INSTALLED"
- requires="Host-Intent.Link-1-Up" />
- <dependency name="Host-Intent.Ping-4" requires="Validate-Intent-Installed-Again" />
+ <step name="Host-Intent.Validate-Intent-Failed" requires="Host-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} h2h FAILED"/>
- <step name="Remove-Intent" requires="~Host-Intent.Net-Link-Down-Up"
- exec="onos ${OC1} remove-intent -p"/>
-
+ <dependency name="Host-Intent.Link-1-Up"
+ requires="~Host-Intent.Validate-Intent-Failed" />
+ <step name="Host-Intent.Validate-Intent-Installed-Again" requires="Host-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} h2h INSTALLED"/>
+ <dependency name="Host-Intent.Ping-4"
+ requires="~Host-Intent.Validate-Intent-Installed-Again" />
+
+ <step name="Host-Intent.Remove-Intent" requires="~Host-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli h2h"/>
</group>
</scenario>
diff --git a/tools/test/scenarios/net-link-down-up.xml b/tools/test/scenarios/net-link-down-up.xml
index 70a8fee..8bcbfa7 100644
--- a/tools/test/scenarios/net-link-down-up.xml
+++ b/tools/test/scenarios/net-link-down-up.xml
@@ -18,21 +18,21 @@
<group name="Net-Link-Down-Up">
<step name="Ping-1"
exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
- <step name="Link-1-Down" requires="Ping-1"
+ <step name="Link-1-Down" requires="~Ping-1"
exec="onos-mininet sendAndExpect link s4 s7 down --expect ."/>
- <step name="Ping-2" requires="Link-1-Down"
+ <step name="Ping-2" requires="~Link-1-Down"
exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
- <step name="Link-2-Down" requires="Ping-2"
+ <step name="Link-2-Down" requires="~Ping-2"
exec="onos-mininet sendAndExpect link s4 s5 down --expect ."/>
- <step name="Ping-3" requires="Link-2-Down"
- exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect 100% packet loss"/>
- <step name="Link-1-Up" requires="Ping-3"
+ <step name="Ping-3" requires="~Link-2-Down"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect 100% packet loss"/>
+ <step name="Link-1-Up" requires="~Ping-3"
exec="onos-mininet sendAndExpect link s4 s7 up --expect ."/>
- <step name="Ping-4" requires="Link-1-Up"
+ <step name="Ping-4" requires="~Link-1-Up"
exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
- <step name="Link-2-Up" requires="Ping-4"
+ <step name="Link-2-Up" requires="~Ping-4"
exec="onos-mininet sendAndExpect link s4 s5 up --expect ."/>
- <step name="Ping-5" requires="Link-2-Up"
+ <step name="Ping-5" requires="~Link-2-Up"
exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/>
</group>
</scenario>
\ No newline at end of file
diff --git a/tools/test/scenarios/net-pingall.xml b/tools/test/scenarios/net-pingall.xml
index df1ae1f..8968e0d 100644
--- a/tools/test/scenarios/net-pingall.xml
+++ b/tools/test/scenarios/net-pingall.xml
@@ -18,11 +18,14 @@
<group name="Net-Pingall">
<step name="Install-Apps"
exec="onos ${OC1} app activate org.onosproject.openflow org.onosproject.proxyarp org.onosproject.fwd"/>
+ <step name="Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} drivers,openflow,proxyarp,fwd includes"/>
- <step name="Check-Apps" requires="Install-Apps"
- exec="onos-check-apps ${OC1} drivers,openflow,proxyarp,fwd"/>
+ <!-- TODO: take this out when initial pingall sweep is 100% -->
+ <step name="Initial-Ping-All" requires="Check-Apps"
+ exec="onos-mininet sendAndExpect py net.pingAll(1) --expect 600 received"/>
- <step name="Ping-All-And-Verify" requires="Check-Apps"
+ <step name="Ping-All-And-Verify" requires="Check-Apps,Initial-Ping-All"
exec="onos-mininet sendAndExpect py net.pingAll(1) --expect 600/600 received"/>
<step name="Check-Summary-For-Hosts" requires="~Ping-All-And-Verify"
diff --git a/tools/test/scenarios/net-point-intent.xml b/tools/test/scenarios/net-point-intent.xml
index 125f491..acb8212 100644
--- a/tools/test/scenarios/net-point-intent.xml
+++ b/tools/test/scenarios/net-point-intent.xml
@@ -13,44 +13,65 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<scenario name="net-point-intent" description="Network point to point intent connectivity test">
+<scenario name="net-point-intent"
+ description="Network point to point intent connectivity test">
<!-- TODO: parametrize this via recipes -->
- <group name="Point-To-Point-Intent-Connectivity">
- <step name="P2P-Uninstall-Reactive-Forwarding"
+ <group name="P2P-Intent-Connectivity">
+ <step name="P2P-Intent.Uninstall-Reactive-Forwarding"
exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/>
+ <step name="P2P-Intent.Check-Apps" requires="^"
+ exec="onos-check-apps ${OC1} fwd,ifwd excludes"/>
- <step name="P2P-Find-Host-1" requires="^"
- exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect ."/>
- <step name="P2PFind-Host-2" requires="^"
- exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect ."/>
+ <step name="P2P-Intent.Find-Host-1" requires="^"
+ exec="onos-mininet sendAndExpect h1 ping -c1 -w1 h4 --expect ."/>
+ <step name="P2P-Intent.Find-Host-2" requires="^"
+ exec="onos-mininet sendAndExpect h4 ping -c1 -w1 h1 --expect ."/>
- <step name="P2P-Create-Intent-1-To-4" requires="^"
- exec="onos-create-intent ${OC1} oneToFour point of:0000000000000001/1 of:0000000000000004/1"/>
- <step name="P2P-Create-Intent-4-To-1" requires="^"
- exec="onos-create-intent ${OC1} fourToOne point of:0000000000000004/1 of:0000000000000001/1"/>
+ <step name="P2P-Intent.Create-Intent-XY" requires="^"
+ exec="onos-create-intent ${OC1} xy point of:0000000000000001/1 of:0000000000000004/1"/>
+ <step name="P2P-Intent.Create-Intent-YX" requires="^"
+ exec="onos-create-intent ${OC1} yx point of:0000000000000004/1 of:0000000000000001/1"/>
- <step name="P2P-Validate-Point-Intents-Installed1" exec="onos-check-intent ${OC1} ${fourToOneId} INSTALLED"
- requires="^" />
- <step name="P2P-Validate-Point-Intents-Installed2" exec="onos-check-intent ${OC1} ${oneToFourId} INSTALLED"
- requires="^" />
+ <step name="P2P-Intent.Validate-Intent-XY-Installed" requires="^"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed" requires="^"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
- <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Point-To-Point-Intent"/>
- <dependency name="Point-To-Point-Intent.Net-Link-Down-Up" requires="P2P-Validate-Point-Intents-Installed2"/>
- <step name="P2P-Validate-Intent-Installed-Still" exec="onos-check-intent ${OC1} ${fourToOneId} INSTALLED"
- requires="Point-To-Point-Intent.Link-1-Down" />
+ <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="P2P-Intent"/>
+ <dependency name="P2P-Intent.Net-Link-Down-Up"
+ requires="P2P-Intent.Validate-Intent-XY-Installed,
+ P2P-Intent.Validate-Intent-YX-Installed"/>
- <step name="P2P-Validate-Intent-Failed" exec="onos-check-intent ${OC1} ${fourToOneId} FAILED"
- requires="Point-To-Point-Intent.Link-2-Down" />
- <step name="P2P-Validate-Intent-Failed2" exec="onos-check-intent ${OC1} ${oneToFourId} FAILED"
- requires="Point-To-Point-Intent.Link-2-Down" />
+ <step name="P2P-Intent.Validate-Intent-XY-Installed-Still" requires="P2P-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed-Still" requires="P2P-Intent.Link-1-Down"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
- <step name="P2P-Validate-Intent-Installed-Again" exec="onos-check-intent ${OC1} ${fourToOneId} INSTALLED"
- requires="Point-To-Point-Intent.Link-1-Up" />
- <dependency name="Point-To-Point-Intent.Ping-4" requires="P2P-Validate-Intent-Installed-Again" />
+ <dependency name="P2P-Intent.Link-2-Down"
+ requires="~P2P-Intent.Validate-Intent-XY-Installed-Still,
+ ~P2P-Intent.Validate-Intent-YX-Installed-Still"/>
- <step name="P2P-Remove-Intent-4-to-1" requires="~Point-To-Point-Intent.Net-Link-Down-Up"
- exec="onos ${OC1} remove-intent -p org.onosproject.cli ${fourToOneId}"/>
- <step name="P2P-Remove-Intent-1-to-4" requires="^"
- exec="onos ${OC1} remove-intent -p org.onosproject.cli ${oneToFourId}"/>
+ <step name="P2P-Intent.Validate-Intent-XY-Failed" requires="P2P-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} xy FAILED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Failed" requires="P2P-Intent.Link-2-Down"
+ exec="onos-check-intent ${OC1} yx FAILED"/>
+
+ <dependency name="P2P-Intent.Link-1-Up"
+ requires="~P2P-Intent.Validate-Intent-XY-Failed,
+ ~P2P-Intent.Validate-Intent-YX-Failed" />
+
+ <step name="P2P-Intent.Validate-Intent-XY-Installed-Again" requires="P2P-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} xy INSTALLED"/>
+ <step name="P2P-Intent.Validate-Intent-YX-Installed-Again" requires="P2P-Intent.Link-1-Up"
+ exec="onos-check-intent ${OC1} yx INSTALLED"/>
+
+ <dependency name="P2P-Intent.Ping-4"
+ requires="~P2P-Intent.Validate-Intent-XY-Installed-Again,
+ ~P2P-Intent.Validate-Intent-YX-Installed-Again"/>
+
+ <step name="P2P-Intent.Remove-Intent-XY" requires="~P2P-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli xy"/>
+ <step name="P2P-Intent.Remove-Intent-YX" requires="~P2P-Intent.Net-Link-Down-Up"
+ exec="onos ${OC1} remove-intent -p org.onosproject.cli yx"/>
</group>
</scenario>
diff --git a/tools/test/scenarios/net-setup.xml b/tools/test/scenarios/net-setup.xml
index 5b71dfe..e179ec5 100644
--- a/tools/test/scenarios/net-setup.xml
+++ b/tools/test/scenarios/net-setup.xml
@@ -29,7 +29,7 @@
exec="onos-mininet start topos/topo att-onos.py ${ONOS_INSTANCES}"/>
<step name="Wait-For-Mininet" requires="Start-Mininet"
- exec="onos-mininet wait 20"/>
+ exec="onos-mininet wait 10"/>
<step name="Check-Summary" requires="Wait-For-Mininet"
exec="onos-check-summary ${OC1} [0-9]* 25 140 0"/>
diff --git a/tools/test/scenarios/net-smoke.xml b/tools/test/scenarios/net-smoke.xml
index 15974c1..025dd26 100644
--- a/tools/test/scenarios/net-smoke.xml
+++ b/tools/test/scenarios/net-smoke.xml
@@ -27,9 +27,9 @@
<dependency name="Host-Intent-Connectivity" requires="Net-Setup,~Reactive-Forwarding.Net-Link-Down-Up"/>
<import file="${ONOS_SCENARIOS}/net-point-intent.xml"/>
- <dependency name="Point-To-Point-Intent-Connectivity" requires="Net-Setup,~Reactive-Forwarding.Net-Link-Down-Up,Host-Intent-Connectivity"/>
+ <dependency name="P2P-Intent-Connectivity" requires="Net-Setup,~Reactive-Forwarding.Net-Link-Down-Up,Host-Intent-Connectivity"/>
<import file="${ONOS_SCENARIOS}/net-teardown.xml"/>
- <dependency name="Net-Teardown" requires="~Host-Intent-Connectivity,~Point-To-Point-Intent-Connectivity"/>
+ <dependency name="Net-Teardown" requires="~Host-Intent-Connectivity,~P2P-Intent-Connectivity"/>
</group>
</scenario>
diff --git a/tools/test/scenarios/smoke.xml b/tools/test/scenarios/smoke.xml
index 88608d5..ce8140a 100644
--- a/tools/test/scenarios/smoke.xml
+++ b/tools/test/scenarios/smoke.xml
@@ -23,7 +23,7 @@
<dependency name="Net-Smoke" requires="Setup"/>
<import file="${ONOS_SCENARIOS}/archetypes.xml"/>
- <dependency name="Archetypes" requires="~Net-Smoke,Setup"/>
+ <dependency name="Archetypes" requires="Setup"/>
<import file="${ONOS_SCENARIOS}/wrapup.xml"/>
<dependency name="Wrapup" requires="~Archetypes,~Setup,~Net-Smoke"/>
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 162e8df..c2a0c81 100644
--- a/utils/stc/src/main/java/org/onlab/stc/Compiler.java
+++ b/utils/stc/src/main/java/org/onlab/stc/Compiler.java
@@ -21,6 +21,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onlab.graph.DepthFirstSearch;
import java.io.File;
import java.io.FileInputStream;
@@ -29,10 +30,10 @@
import java.util.Map;
import java.util.Set;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Preconditions.*;
import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onlab.graph.DepthFirstSearch.EdgeType.BACK_EDGE;
+import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
import static org.onlab.stc.Scenario.loadScenario;
/**
@@ -109,6 +110,8 @@
processFlow = new ProcessFlow(ImmutableSet.copyOf(steps.values()),
ImmutableSet.copyOf(dependencies));
+ scanForCycles();
+
// Extract the log directory if there was one specified
String defaultPath = DEFAULT_LOG_DIR + scenario.name();
String path = scenario.definition().getString(LOG_DIR, defaultPath);
@@ -449,6 +452,22 @@
}
/**
+ * Scans the process flow graph for cyclic dependencies.
+ */
+ private void scanForCycles() {
+ DepthFirstSearch<Step, Dependency> dfs = new DepthFirstSearch<>();
+ // Use a brute-force method of searching paths from all vertices.
+ processFlow().getVertexes().forEach(s -> {
+ DepthFirstSearch<Step, Dependency>.SpanningTreeResult r =
+ dfs.search(processFlow, s, null, null, ALL_PATHS);
+ r.edges().forEach((e, et) -> checkArgument(et != BACK_EDGE,
+ "Process flow has a cycle involving dependency from %s to %s",
+ e.src().name, e.dst().name));
+ });
+ }
+
+
+ /**
* Prints formatted output.
*
* @param format printf format string