Thomas Vachuska

Removed STC as it has been moved to a separate repository.

Change-Id: I419079b4ce539e5c082dd3f9dcf2bf8a91e2e45a
Showing 43 changed files with 0 additions and 5458 deletions
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
37 <module>yangutils</module> 37 <module>yangutils</module>
38 <module>osgi</module> 38 <module>osgi</module>
39 <module>rest</module> 39 <module>rest</module>
40 - <module>stc</module>
41 <module>jdvue</module> 40 <module>jdvue</module>
42 <module>osgiwrap</module> 41 <module>osgiwrap</module>
43 </modules> 42 </modules>
......
1 -#!/bin/bash
2 -#-------------------------------------------------------------------------------
3 -# System Test Coordinator
4 -#-------------------------------------------------------------------------------
5 -
6 -STC_ROOT=${STC_ROOT:-$(dirname $0)/..}
7 -cd $STC_ROOT
8 -VER=1.6.0-SNAPSHOT
9 -
10 -PATH=$PWD/bin:$PATH
11 -
12 -java -jar target/onlab-stc-$VER.jar "$@"
1 -#!/bin/bash
2 -#-------------------------------------------------------------------------------
3 -# System Test Coordinator process launcher
4 -#-------------------------------------------------------------------------------
5 -
6 -env=$1 && shift
7 -cwd=$1 && shift
8 -
9 -if [ $env != "-" ]; then
10 - [ ! -f $env ] && echo "$env file not found" && exit 1
11 - source $env
12 -fi
13 -
14 -if [ $cwd != "-" ]; then
15 - [ ! -d $cwd ] && echo "$cwd directory not found" && exit 1
16 - cd $cwd
17 -fi
18 -
19 -"$@" 2>&1
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onlab-utils</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - </parent>
27 -
28 - <artifactId>onlab-stc</artifactId>
29 - <packaging>jar</packaging>
30 -
31 - <description>System Test Coordinator</description>
32 -
33 - <dependencies>
34 - <dependency>
35 - <groupId>org.onosproject</groupId>
36 - <artifactId>onlab-misc</artifactId>
37 - </dependency>
38 - <dependency>
39 - <groupId>org.onosproject</groupId>
40 - <artifactId>onlab-junit</artifactId>
41 - <scope>test</scope>
42 - </dependency>
43 -
44 - <dependency>
45 - <groupId>commons-configuration</groupId>
46 - <artifactId>commons-configuration</artifactId>
47 - </dependency>
48 -
49 - <dependency>
50 - <groupId>commons-collections</groupId>
51 - <artifactId>commons-collections</artifactId>
52 - </dependency>
53 -
54 - <dependency>
55 - <groupId>com.fasterxml.jackson.core</groupId>
56 - <artifactId>jackson-databind</artifactId>
57 - <version>2.7.3</version>
58 - <scope>compile</scope>
59 - </dependency>
60 - <dependency>
61 - <groupId>com.fasterxml.jackson.core</groupId>
62 - <artifactId>jackson-annotations</artifactId>
63 - <version>2.7.3</version>
64 - <scope>compile</scope>
65 - </dependency>
66 -
67 - <dependency>
68 - <groupId>org.eclipse.jetty</groupId>
69 - <artifactId>jetty-server</artifactId>
70 - <version>8.1.19.v20160209</version>
71 - </dependency>
72 - <dependency>
73 - <groupId>org.eclipse.jetty</groupId>
74 - <artifactId>jetty-servlet</artifactId>
75 - <version>8.1.19.v20160209</version>
76 - </dependency>
77 - <dependency>
78 - <groupId>org.eclipse.jetty</groupId>
79 - <artifactId>jetty-websocket</artifactId>
80 - <version>8.1.19.v20160209</version>
81 - </dependency>
82 - </dependencies>
83 -
84 - <build>
85 - <plugins>
86 - <plugin>
87 - <groupId>org.apache.maven.plugins</groupId>
88 - <artifactId>maven-shade-plugin</artifactId>
89 - <version>2.4.2</version>
90 - <configuration>
91 - <transformers>
92 - <transformer
93 - implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
94 - <mainClass>org.onlab.stc.Main
95 - </mainClass>
96 - </transformer>
97 - </transformers>
98 - <filters>
99 - <filter>
100 - <artifact>*:*</artifact>
101 - <excludes>
102 - <exclude>META-INF/*.SF</exclude>
103 - <exclude>META-INF/*.DSA</exclude>
104 - <exclude>META-INF/*.RSA</exclude>
105 - </excludes>
106 - </filter>
107 - </filters>
108 - </configuration>
109 - <executions>
110 - <execution>
111 - <phase>package</phase>
112 - <goals>
113 - <goal>shade</goal>
114 - </goals>
115 - </execution>
116 - </executions>
117 - </plugin>
118 - </plugins>
119 - </build>
120 -
121 -</project>
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="sample" description="Sample Test Scenario">
17 - <step name="alpha" exec="/bin/ls -l"/>
18 - <step name="beta" exec="/bin/ls -lF"/>
19 - <step name="gamma" exec="/bin/ls" requires="alpha,beta"/>
20 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.ImmutableList;
19 -import com.google.common.collect.ImmutableSet;
20 -import com.google.common.collect.Lists;
21 -import com.google.common.collect.Maps;
22 -import com.google.common.collect.Sets;
23 -import org.apache.commons.configuration.HierarchicalConfiguration;
24 -import org.onlab.graph.DepthFirstSearch;
25 -
26 -import java.io.File;
27 -import java.io.FileInputStream;
28 -import java.io.IOException;
29 -import java.util.List;
30 -import java.util.Map;
31 -import java.util.Set;
32 -
33 -import static com.google.common.base.Preconditions.*;
34 -import static com.google.common.base.Strings.isNullOrEmpty;
35 -import static java.lang.Integer.parseInt;
36 -import static org.onlab.graph.DepthFirstSearch.EdgeType.BACK_EDGE;
37 -import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
38 -import static org.onlab.stc.Scenario.loadScenario;
39 -
40 -/**
41 - * Entity responsible for loading a scenario and producing a redy-to-execute
42 - * process flow graph.
43 - */
44 -public class Compiler {
45 -
46 - private static final String DEFAULT_LOG_DIR = "${WORKSPACE}/tmp/stc/";
47 -
48 - private static final String IMPORT = "import";
49 - private static final String GROUP = "group";
50 - private static final String STEP = "step";
51 - private static final String PARALLEL = "parallel";
52 - private static final String SEQUENTIAL = "sequential";
53 - private static final String DEPENDENCY = "dependency";
54 -
55 - private static final String LOG_DIR = "[@logDir]";
56 - private static final String NAME = "[@name]";
57 - private static final String COMMAND = "[@exec]";
58 - private static final String ENV = "[@env]";
59 - private static final String CWD = "[@cwd]";
60 - private static final String DELAY = "[@delay]";
61 - private static final String REQUIRES = "[@requires]";
62 - private static final String IF = "[@if]";
63 - private static final String UNLESS = "[@unless]";
64 - private static final String VAR = "[@var]";
65 - private static final String STARTS = "[@starts]";
66 - private static final String ENDS = "[@ends]";
67 - private static final String FILE = "[@file]";
68 - private static final String NAMESPACE = "[@namespace]";
69 -
70 - static final String PROP_START = "${";
71 - static final String PROP_END = "}";
72 -
73 - private static final String HASH = "#";
74 - private static final String HASH_PREV = "#-1";
75 -
76 - private final Scenario scenario;
77 -
78 - private final Map<String, Step> steps = Maps.newHashMap();
79 - private final Map<String, Step> inactiveSteps = Maps.newHashMap();
80 - private final Map<String, String> requirements = Maps.newHashMap();
81 - private final Set<Dependency> dependencies = Sets.newHashSet();
82 - private final List<Integer> clonables = Lists.newArrayList();
83 -
84 - private ProcessFlow processFlow;
85 - private File logDir;
86 -
87 - private String previous = null;
88 - private String pfx = "";
89 - private boolean debugOn = System.getenv("debug") != null;
90 -
91 - /**
92 - * Creates a new compiler for the specified scenario.
93 - *
94 - * @param scenario scenario to be compiled
95 - */
96 - public Compiler(Scenario scenario) {
97 - this.scenario = scenario;
98 - }
99 -
100 - /**
101 - * Returns the scenario being compiled.
102 - *
103 - * @return test scenario
104 - */
105 - public Scenario scenario() {
106 - return scenario;
107 - }
108 -
109 - /**
110 - * Compiles the specified scenario to produce a final process flow graph.
111 - */
112 - public void compile() {
113 - compile(scenario.definition(), null, null);
114 - compileRequirements();
115 -
116 - // Produce the process flow
117 - processFlow = new ProcessFlow(ImmutableSet.copyOf(steps.values()),
118 - ImmutableSet.copyOf(dependencies));
119 -
120 - scanForCycles();
121 -
122 - // Extract the log directory if there was one specified
123 - String defaultPath = DEFAULT_LOG_DIR + scenario.name();
124 - String path = scenario.definition().getString(LOG_DIR, defaultPath);
125 - logDir = new File(expand(path));
126 - }
127 -
128 - /**
129 - * Returns the step with the specified name.
130 - *
131 - * @param name step or group name
132 - * @return test step or group
133 - */
134 - public Step getStep(String name) {
135 - return steps.get(name);
136 - }
137 -
138 - /**
139 - * Returns the process flow generated from this scenario definition.
140 - *
141 - * @return process flow as a graph
142 - */
143 - public ProcessFlow processFlow() {
144 - return processFlow;
145 - }
146 -
147 - /**
148 - * Returns the log directory where scenario logs should be kept.
149 - *
150 - * @return scenario logs directory
151 - */
152 - public File logDir() {
153 - return logDir;
154 - }
155 -
156 - /**
157 - * Recursively elaborates this definition to produce a final process flow graph.
158 - *
159 - * @param cfg hierarchical definition
160 - * @param namespace optional namespace
161 - * @param parentGroup optional parent group
162 - */
163 - private void compile(HierarchicalConfiguration cfg,
164 - String namespace, Group parentGroup) {
165 - String opfx = pfx;
166 - pfx = pfx + ">";
167 - print("pfx=%s namespace=%s", pfx, namespace);
168 -
169 - // Scan all imports
170 - cfg.configurationsAt(IMPORT)
171 - .forEach(c -> processImport(c, namespace, parentGroup));
172 -
173 - // Scan all steps
174 - cfg.configurationsAt(STEP)
175 - .forEach(c -> processStep(c, namespace, parentGroup));
176 -
177 - // Scan all groups
178 - cfg.configurationsAt(GROUP)
179 - .forEach(c -> processGroup(c, namespace, parentGroup));
180 -
181 - // Scan all parallel groups
182 - cfg.configurationsAt(PARALLEL)
183 - .forEach(c -> processParallelGroup(c, namespace, parentGroup));
184 -
185 - // Scan all sequential groups
186 - cfg.configurationsAt(SEQUENTIAL)
187 - .forEach(c -> processSequentialGroup(c, namespace, parentGroup));
188 -
189 - // Scan all dependencies
190 - cfg.configurationsAt(DEPENDENCY)
191 - .forEach(c -> processDependency(c, namespace));
192 -
193 - pfx = opfx;
194 - }
195 -
196 - /**
197 - * Compiles requirements for all steps and groups accrued during the
198 - * overall compilation process.
199 - */
200 - private void compileRequirements() {
201 - requirements.forEach((name, requires) ->
202 - compileRequirements(getStep(name), requires));
203 - }
204 -
205 - private void compileRequirements(Step src, String requires) {
206 - split(requires).forEach(n -> {
207 - boolean isSoft = n.startsWith("~");
208 - String name = n.replaceFirst("^~", "");
209 - Step dst = getStep(name);
210 - if (dst != null) {
211 - dependencies.add(new Dependency(src, dst, isSoft));
212 - }
213 - });
214 - }
215 -
216 - /**
217 - * Processes an import directive.
218 - *
219 - * @param cfg hierarchical definition
220 - * @param namespace optional namespace
221 - * @param parentGroup optional parent group
222 - */
223 - private void processImport(HierarchicalConfiguration cfg,
224 - String namespace, Group parentGroup) {
225 - String file = checkNotNull(expand(cfg.getString(FILE)),
226 - "Import directive must specify 'file'");
227 - String newNamespace = expand(prefix(cfg.getString(NAMESPACE), namespace));
228 - print("import file=%s namespace=%s", file, newNamespace);
229 - try {
230 - Scenario importScenario = loadScenario(new FileInputStream(file));
231 - compile(importScenario.definition(), newNamespace, parentGroup);
232 - } catch (IOException e) {
233 - throw new IllegalArgumentException("Unable to import scenario", e);
234 - }
235 - }
236 -
237 - /**
238 - * Processes a step directive.
239 - *
240 - * @param cfg hierarchical definition
241 - * @param namespace optional namespace
242 - * @param parentGroup optional parent group
243 - */
244 - private void processStep(HierarchicalConfiguration cfg,
245 - String namespace, Group parentGroup) {
246 - String name = expand(prefix(cfg.getString(NAME), namespace));
247 - String command = expand(cfg.getString(COMMAND, parentGroup != null ? parentGroup.command() : null), true);
248 - String env = expand(cfg.getString(ENV, parentGroup != null ? parentGroup.env() : null));
249 - String cwd = expand(cfg.getString(CWD, parentGroup != null ? parentGroup.cwd() : null));
250 - int delay = parseInt(expand(cfg.getString(DELAY, parentGroup != null ? "" + parentGroup.delay() : "0")));
251 -
252 - print("step name=%s command=%s env=%s cwd=%s delay=%d", name, command, env, cwd, delay);
253 - Step step = new Step(name, command, env, cwd, parentGroup, delay);
254 - registerStep(step, cfg, namespace, parentGroup);
255 - }
256 -
257 - /**
258 - * Processes a group directive.
259 - *
260 - * @param cfg hierarchical definition
261 - * @param namespace optional namespace
262 - * @param parentGroup optional parent group
263 - */
264 - private void processGroup(HierarchicalConfiguration cfg,
265 - String namespace, Group parentGroup) {
266 - String name = expand(prefix(cfg.getString(NAME), namespace));
267 - String command = expand(cfg.getString(COMMAND, parentGroup != null ? parentGroup.command() : null), true);
268 - String env = expand(cfg.getString(ENV, parentGroup != null ? parentGroup.env() : null));
269 - String cwd = expand(cfg.getString(CWD, parentGroup != null ? parentGroup.cwd() : null));
270 - int delay = parseInt(expand(cfg.getString(DELAY, parentGroup != null ? "" + parentGroup.delay() : "0")));
271 -
272 - print("group name=%s command=%s env=%s cwd=%s delay=%d", name, command, env, cwd, delay);
273 - Group group = new Group(name, command, env, cwd, parentGroup, delay);
274 - if (registerStep(group, cfg, namespace, parentGroup)) {
275 - compile(cfg, namespace, group);
276 - }
277 - }
278 -
279 - /**
280 - * Registers the specified step or group.
281 - *
282 - * @param step step or group
283 - * @param cfg hierarchical definition
284 - * @param namespace optional namespace
285 - * @param parentGroup optional parent group
286 - * @return true of the step or group was registered as active
287 - */
288 - private boolean registerStep(Step step, HierarchicalConfiguration cfg,
289 - String namespace, Group parentGroup) {
290 - checkState(!steps.containsKey(step.name()), "Step %s already exists", step.name());
291 - String ifClause = expand(cfg.getString(IF));
292 - String unlessClause = expand(cfg.getString(UNLESS));
293 -
294 - if ((ifClause != null && ifClause.length() == 0) ||
295 - (unlessClause != null && unlessClause.length() > 0) ||
296 - (parentGroup != null && inactiveSteps.containsValue(parentGroup))) {
297 - inactiveSteps.put(step.name(), step);
298 - return false;
299 - }
300 -
301 - if (parentGroup != null) {
302 - parentGroup.addChild(step);
303 - }
304 -
305 - steps.put(step.name(), step);
306 - processRequirements(step, expand(cfg.getString(REQUIRES)), namespace);
307 - previous = step.name();
308 - return true;
309 - }
310 -
311 - /**
312 - * Processes a parallel clone group directive.
313 - *
314 - * @param cfg hierarchical definition
315 - * @param namespace optional namespace
316 - * @param parentGroup optional parent group
317 - */
318 - private void processParallelGroup(HierarchicalConfiguration cfg,
319 - String namespace, Group parentGroup) {
320 - String var = cfg.getString(VAR);
321 - print("parallel var=%s", var);
322 -
323 - int i = 1;
324 - while (condition(var, i).length() > 0) {
325 - clonables.add(0, i);
326 - compile(cfg, namespace, parentGroup);
327 - clonables.remove(0);
328 - i++;
329 - }
330 - }
331 -
332 - /**
333 - * Processes a sequential clone group directive.
334 - *
335 - * @param cfg hierarchical definition
336 - * @param namespace optional namespace
337 - * @param parentGroup optional parent group
338 - */
339 - private void processSequentialGroup(HierarchicalConfiguration cfg,
340 - String namespace, Group parentGroup) {
341 - String var = cfg.getString(VAR);
342 - String starts = cfg.getString(STARTS);
343 - String ends = cfg.getString(ENDS);
344 - print("sequential var=%s", var);
345 -
346 - int i = 1;
347 - while (condition(var, i).length() > 0) {
348 - clonables.add(0, i);
349 - compile(cfg, namespace, parentGroup);
350 - if (i > 1) {
351 - processSequentialRequirements(starts, ends, namespace);
352 - }
353 - clonables.remove(0);
354 - i++;
355 - }
356 - }
357 -
358 - /**
359 - * Hooks starts of this sequence tier to the previous tier.
360 - *
361 - * @param starts comma-separated list of start steps
362 - * @param ends comma-separated list of end steps
363 - * @param namespace optional namespace
364 - */
365 - private void processSequentialRequirements(String starts, String ends,
366 - String namespace) {
367 - for (String s : split(starts)) {
368 - String start = expand(prefix(s, namespace));
369 - String reqs = requirements.get(s);
370 - for (String n : split(ends)) {
371 - boolean isSoft = n.startsWith("~");
372 - String name = n.replaceFirst("^~", "");
373 - name = (isSoft ? "~" : "") + expand(prefix(name, namespace));
374 - reqs = reqs == null ? name : (reqs + "," + name);
375 - }
376 - requirements.put(start, reqs);
377 - }
378 - }
379 -
380 - /**
381 - * Returns the elaborated repetition construct conditional.
382 - *
383 - * @param var repetition var property
384 - * @param i index to elaborate
385 - * @return elaborated string
386 - */
387 - private String condition(String var, Integer i) {
388 - return expand(var.replaceFirst("#", i.toString())).trim();
389 - }
390 -
391 - /**
392 - * Processes a dependency directive.
393 - *
394 - * @param cfg hierarchical definition
395 - * @param namespace optional namespace
396 - */
397 - private void processDependency(HierarchicalConfiguration cfg, String namespace) {
398 - String name = expand(prefix(cfg.getString(NAME), namespace));
399 - String requires = expand(cfg.getString(REQUIRES));
400 -
401 - print("dependency name=%s requires=%s", name, requires);
402 - Step step = getStep(name, namespace);
403 - if (!inactiveSteps.containsValue(step)) {
404 - processRequirements(step, requires, namespace);
405 - }
406 - }
407 -
408 - /**
409 - * Processes the specified requiremenst string and adds dependency for
410 - * each requirement of the given step.
411 - *
412 - * @param src source step
413 - * @param requires comma-separated list of required steps
414 - * @param namespace optional namespace
415 - */
416 - private void processRequirements(Step src, String requires, String namespace) {
417 - String reqs = requirements.get(src.name());
418 - for (String n : split(requires)) {
419 - boolean isSoft = n.startsWith("~");
420 - String name = n.replaceFirst("^~", "");
421 - name = previous != null && name.equals("^") ? previous : name;
422 - name = (isSoft ? "~" : "") + expand(prefix(name, namespace));
423 - reqs = reqs == null ? name : (reqs + "," + name);
424 - }
425 - requirements.put(src.name(), reqs);
426 - }
427 -
428 - /**
429 - * Retrieves the step or group with the specified name.
430 - *
431 - * @param name step or group name
432 - * @param namespace optional namespace
433 - * @return step or group; null if none found in active or inactive steps
434 - */
435 - private Step getStep(String name, String namespace) {
436 - String dName = prefix(name, namespace);
437 - Step step = steps.get(dName);
438 - step = step != null ? step : inactiveSteps.get(dName);
439 - checkArgument(step != null, "Unknown step %s", dName);
440 - return step;
441 - }
442 -
443 - /**
444 - * Prefixes the specified name with the given namespace.
445 - *
446 - * @param name name of a step or a group
447 - * @param namespace optional namespace
448 - * @return composite name
449 - */
450 - private String prefix(String name, String namespace) {
451 - return isNullOrEmpty(namespace) ? name : namespace + "." + name;
452 - }
453 -
454 - /**
455 - * Expands any environment variables in the specified string. These are
456 - * specified as ${property} tokens.
457 - *
458 - * @param string string to be processed
459 - * @param keepTokens true if the original unresolved tokens should be kept
460 - * @return original string with expanded substitutions
461 - */
462 - private String expand(String string, boolean... keepTokens) {
463 - if (string == null) {
464 - return null;
465 - }
466 -
467 - String pString = string;
468 - StringBuilder sb = new StringBuilder();
469 - int start, end, last = 0;
470 - while ((start = pString.indexOf(PROP_START, last)) >= 0) {
471 - end = pString.indexOf(PROP_END, start + PROP_START.length());
472 - checkArgument(end > start, "Malformed property in %s", pString);
473 - sb.append(pString.substring(last, start));
474 - String prop = pString.substring(start + PROP_START.length(), end);
475 - String value;
476 - if (prop.equals(HASH)) {
477 - value = Integer.toString(clonables.get(0));
478 - } else if (prop.equals(HASH_PREV)) {
479 - value = Integer.toString(clonables.get(0) - 1);
480 - } else if (prop.endsWith(HASH)) {
481 - pString = pString.replaceFirst("#}", clonables.get(0) + "}");
482 - last = start;
483 - continue;
484 - } else {
485 - // Try system property first, then fall back to env. variable.
486 - value = System.getProperty(prop);
487 - if (value == null) {
488 - value = System.getenv(prop);
489 - }
490 - }
491 - if (value == null && keepTokens.length == 1 && keepTokens[0]) {
492 - sb.append("${").append(prop).append("}");
493 - } else {
494 - sb.append(value != null ? value : "");
495 - }
496 - last = end + 1;
497 - }
498 - sb.append(pString.substring(last));
499 - return sb.toString().replace('\n', ' ').replace('\r', ' ');
500 - }
501 -
502 - /**
503 - * Splits the comma-separated string into a list of strings.
504 - *
505 - * @param string string to split
506 - * @return list of strings
507 - */
508 - private List<String> split(String string) {
509 - ImmutableList.Builder<String> builder = ImmutableList.builder();
510 - String[] fields = string != null ? string.split(",") : new String[0];
511 - for (String field : fields) {
512 - builder.add(field.trim());
513 - }
514 - return builder.build();
515 - }
516 -
517 - /**
518 - * Scans the process flow graph for cyclic dependencies.
519 - */
520 - private void scanForCycles() {
521 - DepthFirstSearch<Step, Dependency> dfs = new DepthFirstSearch<>();
522 - // Use a brute-force method of searching paths from all vertices.
523 - processFlow().getVertexes().forEach(s -> {
524 - DepthFirstSearch<Step, Dependency>.SpanningTreeResult r =
525 - dfs.search(processFlow, s, null, null, ALL_PATHS);
526 - r.edges().forEach((e, et) -> checkArgument(et != BACK_EDGE,
527 - "Process flow has a cycle involving dependency from %s to %s",
528 - e.src().name, e.dst().name));
529 - });
530 - }
531 -
532 -
533 - /**
534 - * Prints formatted output.
535 - *
536 - * @param format printf format string
537 - * @param args arguments to be printed
538 - */
539 - private void print(String format, Object... args) {
540 - if (debugOn) {
541 - System.err.println(pfx + String.format(format, args));
542 - }
543 - }
544 -
545 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.ImmutableList;
19 -import com.google.common.collect.Maps;
20 -import com.google.common.collect.Sets;
21 -
22 -import java.io.File;
23 -import java.util.List;
24 -import java.util.Map;
25 -import java.util.Set;
26 -import java.util.concurrent.CountDownLatch;
27 -import java.util.concurrent.ExecutorService;
28 -import java.util.concurrent.TimeUnit;
29 -import java.util.regex.Matcher;
30 -import java.util.regex.Pattern;
31 -
32 -import static com.google.common.base.Preconditions.checkArgument;
33 -import static com.google.common.base.Preconditions.checkNotNull;
34 -import static java.util.concurrent.Executors.newFixedThreadPool;
35 -import static org.onlab.stc.Compiler.PROP_END;
36 -import static org.onlab.stc.Compiler.PROP_START;
37 -import static org.onlab.stc.Coordinator.Directive.*;
38 -import static org.onlab.stc.Coordinator.Status.*;
39 -
40 -/**
41 - * Coordinates execution of a scenario process flow.
42 - */
43 -public class Coordinator {
44 -
45 - private static final int MAX_THREADS = 64;
46 -
47 - private final ExecutorService executor = newFixedThreadPool(MAX_THREADS);
48 -
49 - private final ProcessFlow processFlow;
50 -
51 - private final StepProcessListener delegate;
52 - private final CountDownLatch latch;
53 - private final ScenarioStore store;
54 -
55 - private static final Pattern PROP_ERE = Pattern.compile("^@stc ([a-zA-Z0-9_.]+)=(.*$)");
56 - private final Map<String, String> properties = Maps.newConcurrentMap();
57 -
58 - private final Set<StepProcessListener> listeners = Sets.newConcurrentHashSet();
59 - private File logDir;
60 -
61 - /**
62 - * Represents action to be taken on a test step.
63 - */
64 - public enum Directive {
65 - NOOP, RUN, SKIP
66 - }
67 -
68 - /**
69 - * Represents processor state.
70 - */
71 - public enum Status {
72 - WAITING, IN_PROGRESS, SUCCEEDED, FAILED, SKIPPED
73 - }
74 -
75 - /**
76 - * Creates a process flow coordinator.
77 - *
78 - * @param scenario test scenario to coordinate
79 - * @param processFlow process flow to coordinate
80 - * @param logDir scenario log directory
81 - */
82 - public Coordinator(Scenario scenario, ProcessFlow processFlow, File logDir) {
83 - this.processFlow = processFlow;
84 - this.logDir = logDir;
85 - this.store = new ScenarioStore(processFlow, logDir, scenario.name());
86 - this.delegate = new Delegate();
87 - this.latch = new CountDownLatch(1);
88 - }
89 -
90 - /**
91 - * Resets any previously accrued status and events.
92 - */
93 - public void reset() {
94 - store.reset();
95 - }
96 -
97 - /**
98 - * Resets all previously accrued status and events for steps that lie
99 - * in the range between the steps or groups whose names match the specified
100 - * patterns.
101 - *
102 - * @param runFromPatterns list of starting step patterns
103 - * @param runToPatterns list of ending step patterns
104 - */
105 - public void reset(List<String> runFromPatterns, List<String> runToPatterns) {
106 - List<Step> fromSteps = matchSteps(runFromPatterns);
107 - List<Step> toSteps = matchSteps(runToPatterns);
108 -
109 - // FIXME: implement this
110 - }
111 -
112 - /**
113 - * Returns number of milliseconds it took to execute.
114 - *
115 - * @return number of millis elapsed during the run
116 - */
117 - public long duration() {
118 - return store.endTime() - store.startTime();
119 - }
120 -
121 - /**
122 - * Returns a list of steps that match the specified list of patterns.
123 - *
124 - * @param runToPatterns list of patterns
125 - * @return list of steps with matching names
126 - */
127 - private List<Step> matchSteps(List<String> runToPatterns) {
128 - ImmutableList.Builder<Step> builder = ImmutableList.builder();
129 - store.getSteps().forEach(step -> {
130 - runToPatterns.forEach(p -> {
131 - if (step.name().matches(p)) {
132 - builder.add(step);
133 - }
134 - });
135 - });
136 - return builder.build();
137 - }
138 -
139 - /**
140 - * Starts execution of the process flow graph.
141 - */
142 - public void start() {
143 - executeRoots(null);
144 - }
145 -
146 - /**
147 - * Waits for completion of the entire process flow.
148 - *
149 - * @return exit code to use
150 - * @throws InterruptedException if interrupted while waiting for completion
151 - */
152 - public int waitFor() throws InterruptedException {
153 - while (!store.isComplete()) {
154 - latch.await(1, TimeUnit.SECONDS);
155 - }
156 - return store.hasFailures() ? 1 : 0;
157 - }
158 -
159 - /**
160 - * Returns set of all test steps.
161 - *
162 - * @return set of steps
163 - */
164 - public Set<Step> getSteps() {
165 - return store.getSteps();
166 - }
167 -
168 - /**
169 - * Returns a chronological list of step or group records.
170 - *
171 - * @return list of events
172 - */
173 - List<StepEvent> getRecords() {
174 - return store.getEvents();
175 - }
176 -
177 - /**
178 - * Returns the status record of the specified test step.
179 - *
180 - * @param step test step or group
181 - * @return step status record
182 - */
183 - public Status getStatus(Step step) {
184 - return store.getStatus(step);
185 - }
186 -
187 - /**
188 - * Adds the specified listener.
189 - *
190 - * @param listener step process listener
191 - */
192 - public void addListener(StepProcessListener listener) {
193 - listeners.add(checkNotNull(listener, "Listener cannot be null"));
194 - }
195 -
196 - /**
197 - * Removes the specified listener.
198 - *
199 - * @param listener step process listener
200 - */
201 - public void removeListener(StepProcessListener listener) {
202 - listeners.remove(checkNotNull(listener, "Listener cannot be null"));
203 - }
204 -
205 - /**
206 - * Executes the set of roots in the scope of the specified group or globally
207 - * if no group is given.
208 - *
209 - * @param group optional group
210 - */
211 - private void executeRoots(Group group) {
212 - // FIXME: add ability to skip past completed steps
213 - Set<Step> steps =
214 - group != null ? group.children() : processFlow.getVertexes();
215 - steps.forEach(step -> {
216 - if (processFlow.getEdgesFrom(step).isEmpty() && step.group() == group) {
217 - execute(step);
218 - }
219 - });
220 - }
221 -
222 - /**
223 - * Executes the specified step.
224 - *
225 - * @param step step to execute
226 - */
227 - private synchronized void execute(Step step) {
228 - Directive directive = nextAction(step);
229 - if (directive == RUN) {
230 - store.markStarted(step);
231 - if (step instanceof Group) {
232 - Group group = (Group) step;
233 - delegate.onStart(group, null);
234 - executeRoots(group);
235 - } else {
236 - executor.execute(new StepProcessor(step, logDir, delegate,
237 - substitute(step.command())));
238 - }
239 - } else if (directive == SKIP) {
240 - skipStep(step);
241 - }
242 - }
243 -
244 - /**
245 - * Recursively skips the specified step or group and any steps/groups within.
246 - *
247 - * @param step step or group
248 - */
249 - private void skipStep(Step step) {
250 - if (step instanceof Group) {
251 - Group group = (Group) step;
252 - store.markComplete(step, SKIPPED);
253 - group.children().forEach(this::skipStep);
254 - }
255 - delegate.onCompletion(step, SKIPPED);
256 -
257 - }
258 -
259 - /**
260 - * Determines the state of the specified step.
261 - *
262 - * @param step test step
263 - * @return state of the step process
264 - */
265 - private Directive nextAction(Step step) {
266 - Status status = store.getStatus(step);
267 - if (status != WAITING) {
268 - return NOOP;
269 - }
270 -
271 - for (Dependency dependency : processFlow.getEdgesFrom(step)) {
272 - Status depStatus = store.getStatus(dependency.dst());
273 - if (depStatus == WAITING || depStatus == IN_PROGRESS) {
274 - return NOOP;
275 - } else if (((depStatus == FAILED || depStatus == SKIPPED) && !dependency.isSoft()) ||
276 - (step.group() != null && store.getStatus(step.group()) == SKIPPED)) {
277 - return SKIP;
278 - }
279 - }
280 - return RUN;
281 - }
282 -
283 - /**
284 - * Executes the successors to the specified step.
285 - *
286 - * @param step step whose successors are to be executed
287 - */
288 - private void executeSucessors(Step step) {
289 - processFlow.getEdgesTo(step).forEach(dependency -> execute(dependency.src()));
290 - completeParentIfNeeded(step.group());
291 - }
292 -
293 - /**
294 - * Checks whether the specified parent group, if any, should be marked
295 - * as complete.
296 - *
297 - * @param group parent group that should be checked
298 - */
299 - private synchronized void completeParentIfNeeded(Group group) {
300 - if (group != null && getStatus(group) == IN_PROGRESS) {
301 - boolean done = true;
302 - boolean failed = false;
303 - for (Step child : group.children()) {
304 - Status status = store.getStatus(child);
305 - done = done && (status == SUCCEEDED || status == FAILED || status == SKIPPED);
306 - failed = failed || status == FAILED;
307 - }
308 - if (done) {
309 - delegate.onCompletion(group, failed ? FAILED : SUCCEEDED);
310 - }
311 - }
312 - }
313 -
314 - /**
315 - * Expands the var references with values from the properties map.
316 - *
317 - * @param string string to perform substitutions on
318 - */
319 - private String substitute(String string) {
320 - StringBuilder sb = new StringBuilder();
321 - int start, end, last = 0;
322 - while ((start = string.indexOf(PROP_START, last)) >= 0) {
323 - end = string.indexOf(PROP_END, start + PROP_START.length());
324 - checkArgument(end > start, "Malformed property in %s", string);
325 - sb.append(string.substring(last, start));
326 - String prop = string.substring(start + PROP_START.length(), end);
327 - String value = properties.get(prop);
328 - sb.append(value != null ? value : "");
329 - last = end + 1;
330 - }
331 - sb.append(string.substring(last));
332 - return sb.toString().replace('\n', ' ').replace('\r', ' ');
333 - }
334 -
335 - /**
336 - * Scrapes the line of output for any variables to be captured and posted
337 - * in the properties for later use.
338 - *
339 - * @param line line of output to scrape for property exports
340 - */
341 - private void scrapeForVariables(String line) {
342 - Matcher matcher = PROP_ERE.matcher(line);
343 - if (matcher.matches()) {
344 - String prop = matcher.group(1);
345 - String value = matcher.group(2);
346 - properties.put(prop, value);
347 - }
348 - }
349 -
350 -
351 - /**
352 - * Prints formatted output.
353 - *
354 - * @param format printf format string
355 - * @param args arguments to be printed
356 - */
357 - public static void print(String format, Object... args) {
358 - System.out.println(String.format(format, args));
359 - }
360 -
361 - /**
362 - * Internal delegate to monitor the process execution.
363 - */
364 - private class Delegate implements StepProcessListener {
365 - @Override
366 - public void onStart(Step step, String command) {
367 - listeners.forEach(listener -> listener.onStart(step, command));
368 - }
369 -
370 - @Override
371 - public void onCompletion(Step step, Status status) {
372 - store.markComplete(step, status);
373 - listeners.forEach(listener -> listener.onCompletion(step, status));
374 - executeSucessors(step);
375 - if (store.isComplete()) {
376 - latch.countDown();
377 - }
378 - }
379 -
380 - @Override
381 - public void onOutput(Step step, String line) {
382 - scrapeForVariables(line);
383 - listeners.forEach(listener -> listener.onOutput(step, line));
384 - }
385 - }
386 -
387 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onlab.graph.AbstractEdge;
20 -
21 -import java.util.Objects;
22 -
23 -/**
24 - * Representation of a dependency from one step on completion of another.
25 - */
26 -public class Dependency extends AbstractEdge<Step> {
27 -
28 - private boolean isSoft;
29 -
30 - /**
31 - * Creates a new edge between the specified source and destination vertexes.
32 - *
33 - * @param src source vertex
34 - * @param dst destination vertex
35 - * @param isSoft indicates whether this is a hard or soft dependency
36 - */
37 - public Dependency(Step src, Step dst, boolean isSoft) {
38 - super(src, dst);
39 - this.isSoft = isSoft;
40 - }
41 -
42 - /**
43 - * Indicates whether this is a soft or hard dependency, i.e. one that
44 - * requires successful completion of the dependency or just any completion.
45 - *
46 - * @return true if dependency is a soft one
47 - */
48 - public boolean isSoft() {
49 - return isSoft;
50 - }
51 -
52 - @Override
53 - public int hashCode() {
54 - return 31 * super.hashCode() + Objects.hash(isSoft);
55 - }
56 -
57 - @Override
58 - public boolean equals(Object obj) {
59 - if (this == obj) {
60 - return true;
61 - }
62 - if (obj instanceof Dependency) {
63 - final Dependency other = (Dependency) obj;
64 - return super.equals(other) && Objects.equals(this.isSoft, other.isSoft);
65 - }
66 - return false;
67 - }
68 -
69 - @Override
70 - public String toString() {
71 - return MoreObjects.toStringHelper(this)
72 - .add("name", src().name())
73 - .add("requires", dst().name())
74 - .add("isSoft", isSoft)
75 - .toString();
76 - }
77 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.ImmutableSet;
19 -import com.google.common.collect.Sets;
20 -
21 -import java.util.Set;
22 -
23 -/**
24 - * Represenation of a related group of steps.
25 - */
26 -public class Group extends Step {
27 -
28 - private final Set<Step> children = Sets.newHashSet();
29 -
30 - /**
31 - * Creates a new test step.
32 - *
33 - * @param name group name
34 - * @param command default command
35 - * @param env default path to file to be sourced into the environment
36 - * @param cwd default path to current working directory for the step
37 - * @param group optional group to which this step belongs
38 - * @param delay seconds to delay before executing
39 - */
40 - public Group(String name, String command, String env, String cwd, Group group, int delay) {
41 - super(name, command, env, cwd, group, delay);
42 - }
43 -
44 - /**
45 - * Returns the set of child steps and groups contained within this group.
46 - *
47 - * @return set of children
48 - */
49 - public Set<Step> children() {
50 - return ImmutableSet.copyOf(children);
51 - }
52 -
53 - /**
54 - * Adds the specified step or group as a child of this group.
55 - *
56 - * @param child child step or group to add
57 - */
58 - public void addChild(Step child) {
59 - children.add(child);
60 - }
61 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.ImmutableList;
19 -import com.google.common.io.Files;
20 -import org.eclipse.jetty.server.Server;
21 -import org.eclipse.jetty.servlet.ServletHandler;
22 -import org.eclipse.jetty.util.log.Logger;
23 -import org.onlab.stc.Coordinator.Status;
24 -
25 -import java.io.File;
26 -import java.io.FileInputStream;
27 -import java.io.FileNotFoundException;
28 -import java.io.IOException;
29 -import java.text.SimpleDateFormat;
30 -import java.util.Date;
31 -import java.util.List;
32 -import java.util.Objects;
33 -import java.util.Set;
34 -
35 -import static java.lang.System.currentTimeMillis;
36 -import static org.onlab.stc.Coordinator.Status.*;
37 -import static org.onlab.stc.Coordinator.print;
38 -
39 -/**
40 - * Main program for executing system test coordinator.
41 - */
42 -public final class Main {
43 -
44 - private static final String NONE = "\u001B[0m";
45 - private static final String GRAY = "\u001B[30;1m";
46 - private static final String RED = "\u001B[31;1m";
47 - private static final String GREEN = "\u001B[32;1m";
48 - private static final String BLUE = "\u001B[36m";
49 -
50 - private static final String SUCCESS_SUMMARY =
51 - "%s %sPassed! %d steps succeeded%s";
52 - private static final String MIXED_SUMMARY =
53 - "%s%d steps succeeded; %s%d steps failed; %s%d steps skipped%s";
54 - private static final String FAILURE_SUMMARY = "%s %sFailed! " + MIXED_SUMMARY;
55 - private static final String ABORTED_SUMMARY = "%s %sAborted! " + MIXED_SUMMARY;
56 -
57 - private boolean isReported = false;
58 -
59 - private enum Command {
60 - LIST, RUN, RUN_RANGE, HELP
61 - }
62 -
63 - private final String scenarioFile;
64 -
65 - private Command command = Command.HELP;
66 - private String runFromPatterns = "";
67 - private String runToPatterns = "";
68 -
69 - private Coordinator coordinator;
70 - private Compiler compiler;
71 - private Monitor monitor;
72 - private Listener delegate = new Listener();
73 -
74 - private static boolean useColor = Objects.equals("true", System.getenv("stcColor"));
75 - private static boolean dumpLogs = Objects.equals("true", System.getenv("stcDumpLogs"));
76 -
77 - // usage: stc [<scenario-file>] [run]
78 - // usage: stc [<scenario-file>] run [from <from-patterns>] [to <to-patterns>]]
79 - // usage: stc [<scenario-file>] list
80 -
81 - // Public construction forbidden
82 - private Main(String[] args) {
83 - this.scenarioFile = args[0];
84 -
85 - if (args.length <= 1 || args.length == 2 && args[1].equals("run")) {
86 - command = Command.RUN;
87 - } else if (args.length == 2 && args[1].equals("list")) {
88 - command = Command.LIST;
89 - } else if (args.length >= 4 && args[1].equals("run")) {
90 - int i = 2;
91 - if (args[i].equals("from")) {
92 - command = Command.RUN_RANGE;
93 - runFromPatterns = args[i + 1];
94 - i += 2;
95 - }
96 -
97 - if (args.length >= i + 2 && args[i].equals("to")) {
98 - command = Command.RUN_RANGE;
99 - runToPatterns = args[i + 1];
100 - }
101 - }
102 - }
103 -
104 - /**
105 - * Main entry point for coordinating test scenario execution.
106 - *
107 - * @param args command-line arguments
108 - */
109 - public static void main(String[] args) {
110 - Main main = new Main(args);
111 - main.run();
112 - }
113 -
114 - // Runs the scenario processing
115 - private void run() {
116 - try {
117 - // Load scenario
118 - Scenario scenario = Scenario.loadScenario(new FileInputStream(scenarioFile));
119 -
120 - // Elaborate scenario
121 - compiler = new Compiler(scenario);
122 - compiler.compile();
123 -
124 - // Setup the process flow coordinator
125 - coordinator = new Coordinator(scenario, compiler.processFlow(),
126 - compiler.logDir());
127 - coordinator.addListener(delegate);
128 -
129 - // Prepare the GUI monitor
130 - monitor = new Monitor(coordinator, compiler);
131 - startMonitorServer(monitor);
132 -
133 - // Execute process flow
134 - processCommand();
135 -
136 - } catch (FileNotFoundException e) {
137 - print("Unable to find scenario file %s", scenarioFile);
138 - }
139 - }
140 -
141 - // Initiates a web-server for the monitor GUI.
142 - private static void startMonitorServer(Monitor monitor) {
143 - org.eclipse.jetty.util.log.Log.setLog(new NullLogger());
144 - Server server = new Server(9999);
145 - ServletHandler handler = new ServletHandler();
146 - server.setHandler(handler);
147 - MonitorWebSocketServlet.setMonitor(monitor);
148 - handler.addServletWithMapping(MonitorWebSocketServlet.class, "/*");
149 - try {
150 - server.start();
151 - } catch (Exception e) {
152 - print("GUI already active; running without...");
153 - }
154 - }
155 -
156 - // Processes the appropriate command
157 - private void processCommand() {
158 - switch (command) {
159 - case RUN:
160 - processRun();
161 - break;
162 - case LIST:
163 - processList();
164 - break;
165 - case RUN_RANGE:
166 - processRunRange();
167 - break;
168 - default:
169 - print("Unsupported command %s", command);
170 - }
171 - }
172 -
173 - // Processes the scenario 'run' command.
174 - private void processRun() {
175 - coordinator.reset();
176 - runCoordinator();
177 - }
178 -
179 - // Processes the scenario 'run' command for range of steps.
180 - private void processRunRange() {
181 - coordinator.reset(list(runFromPatterns), list(runToPatterns));
182 - runCoordinator();
183 - }
184 -
185 - // Processes the scenario 'list' command.
186 - private void processList() {
187 - coordinator.getRecords()
188 - .forEach(event -> logStatus(event.time(), event.name(), event.status(), event.command()));
189 - printSummary(0, false);
190 - System.exit(0);
191 - }
192 -
193 - // Runs the coordinator and waits for it to finish.
194 - private void runCoordinator() {
195 - try {
196 - Runtime.getRuntime().addShutdownHook(new ShutdownHook());
197 - coordinator.start();
198 - int exitCode = coordinator.waitFor();
199 - pause(100); // allow stdout to flush
200 - printSummary(exitCode, false);
201 - System.exit(exitCode);
202 - } catch (InterruptedException e) {
203 - print("Unable to execute scenario %s", scenarioFile);
204 - }
205 - }
206 -
207 - private synchronized void printSummary(int exitCode, boolean isAborted) {
208 - if (!isReported) {
209 - isReported = true;
210 - Set<Step> steps = coordinator.getSteps();
211 - String duration = formatDuration((int) (coordinator.duration() / 1_000));
212 - int count = steps.size();
213 - if (exitCode == 0) {
214 - print(SUCCESS_SUMMARY, duration, color(SUCCEEDED), count, color(null));
215 - } else {
216 - long success = steps.stream().filter(s -> coordinator.getStatus(s) == SUCCEEDED).count();
217 - long failed = steps.stream().filter(s -> coordinator.getStatus(s) == FAILED).count();
218 - long skipped = steps.stream().filter(s -> coordinator.getStatus(s) == SKIPPED).count();
219 - print(isAborted ? ABORTED_SUMMARY : FAILURE_SUMMARY, duration,
220 - color(FAILED), color(SUCCEEDED), success,
221 - color(FAILED), failed, color(SKIPPED), skipped, color(null));
222 - }
223 - }
224 - }
225 -
226 - /**
227 - * Internal delegate to monitor the process execution.
228 - */
229 - private class Listener implements StepProcessListener {
230 - @Override
231 - public void onStart(Step step, String command) {
232 - logStatus(currentTimeMillis(), step.name(), IN_PROGRESS, command);
233 - }
234 -
235 - @Override
236 - public void onCompletion(Step step, Status status) {
237 - logStatus(currentTimeMillis(), step.name(), status, null);
238 - if (dumpLogs && !(step instanceof Group) && status == FAILED) {
239 - dumpLogs(step);
240 - }
241 - }
242 -
243 - @Override
244 - public void onOutput(Step step, String line) {
245 - }
246 - }
247 -
248 - // Logs the step status.
249 - private static void logStatus(long time, String name, Status status, String cmd) {
250 - if (cmd != null) {
251 - print("%s %s%s %s%s -- %s", time(time), color(status), name, action(status), color(null), cmd);
252 - } else {
253 - print("%s %s%s %s%s", time(time), color(status), name, action(status), color(null));
254 - }
255 - }
256 -
257 - // Dumps the step logs to standard output.
258 - private void dumpLogs(Step step) {
259 - File logFile = new File(compiler.logDir(), step.name() + ".log");
260 - try {
261 - print(">>>>>");
262 - Files.copy(logFile, System.out);
263 - print("<<<<<");
264 - } catch (IOException e) {
265 - print("Unable to dump log file %s", logFile.getName());
266 - }
267 - }
268 -
269 - // Produces a description of event using the specified step status.
270 - private static String action(Status status) {
271 - return status == IN_PROGRESS ? "started" :
272 - (status == SUCCEEDED ? "completed" :
273 - (status == FAILED ? "failed" :
274 - (status == SKIPPED ? "skipped" : "waiting")));
275 - }
276 -
277 - // Produces an ANSI escape code for color using the specified step status.
278 - private static String color(Status status) {
279 - if (!useColor) {
280 - return "";
281 - }
282 - return status == null ? NONE :
283 - (status == IN_PROGRESS ? BLUE :
284 - (status == SUCCEEDED ? GREEN :
285 - (status == FAILED ? RED : GRAY)));
286 - }
287 -
288 - // Produces a list from the specified comma-separated string.
289 - private static List<String> list(String patterns) {
290 - return ImmutableList.copyOf(patterns.split(","));
291 - }
292 -
293 - // Produces a formatted time stamp.
294 - private static String time(long time) {
295 - return new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date(time));
296 - }
297 -
298 - // Pauses for the specified number of millis.
299 - private static void pause(int ms) {
300 - try {
301 - Thread.sleep(ms);
302 - } catch (InterruptedException e) {
303 - print("Interrupted!");
304 - }
305 - }
306 -
307 - // Formats time duration
308 - private static String formatDuration(int totalSeconds) {
309 - int seconds = totalSeconds % 60;
310 - int totalMinutes = totalSeconds / 60;
311 - int minutes = totalMinutes % 60;
312 - int hours = totalMinutes / 60;
313 - return hours > 0 ?
314 - String.format("%d:%02d:%02d", hours, minutes, seconds) :
315 - String.format("%d:%02d", minutes, seconds);
316 - }
317 -
318 - // Shutdown hook to report status even when aborted.
319 - private class ShutdownHook extends Thread {
320 - @Override
321 - public void run() {
322 - printSummary(1, true);
323 - }
324 - }
325 -
326 - // Logger to quiet Jetty down
327 - private static class NullLogger implements Logger {
328 - @Override
329 - public String getName() {
330 - return "quiet";
331 - }
332 -
333 - @Override
334 - public void warn(String msg, Object... args) {
335 - }
336 -
337 - @Override
338 - public void warn(Throwable thrown) {
339 - }
340 -
341 - @Override
342 - public void warn(String msg, Throwable thrown) {
343 - }
344 -
345 - @Override
346 - public void info(String msg, Object... args) {
347 - }
348 -
349 - @Override
350 - public void info(Throwable thrown) {
351 - }
352 -
353 - @Override
354 - public void info(String msg, Throwable thrown) {
355 - }
356 -
357 - @Override
358 - public boolean isDebugEnabled() {
359 - return false;
360 - }
361 -
362 - @Override
363 - public void setDebugEnabled(boolean enabled) {
364 - }
365 -
366 - @Override
367 - public void debug(String msg, Object... args) {
368 - }
369 -
370 - @Override
371 - public void debug(Throwable thrown) {
372 - }
373 -
374 - @Override
375 - public void debug(String msg, Throwable thrown) {
376 - }
377 -
378 - @Override
379 - public Logger getLogger(String name) {
380 - return this;
381 - }
382 -
383 - @Override
384 - public void ignore(Throwable ignored) {
385 - }
386 - }
387 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.fasterxml.jackson.databind.ObjectMapper;
19 -import com.fasterxml.jackson.databind.node.ArrayNode;
20 -import com.fasterxml.jackson.databind.node.ObjectNode;
21 -import com.google.common.collect.Maps;
22 -import org.onlab.stc.MonitorLayout.Box;
23 -
24 -import java.io.FileWriter;
25 -import java.io.IOException;
26 -import java.io.PrintWriter;
27 -import java.util.Map;
28 -
29 -import static org.onlab.stc.Coordinator.Status.IN_PROGRESS;
30 -
31 -/**
32 - * Scenario test monitor.
33 - */
34 -public class Monitor implements StepProcessListener {
35 -
36 - private final ObjectMapper mapper = new ObjectMapper();
37 -
38 - private final Coordinator coordinator;
39 - private final Compiler compiler;
40 - private final MonitorLayout layout;
41 -
42 - private MonitorDelegate delegate;
43 -
44 - private Map<Step, Box> boxes = Maps.newHashMap();
45 -
46 - /**
47 - * Creates a new shared process flow monitor.
48 - *
49 - * @param coordinator process flow coordinator
50 - * @param compiler scenario compiler
51 - */
52 - Monitor(Coordinator coordinator, Compiler compiler) {
53 - this.coordinator = coordinator;
54 - this.compiler = compiler;
55 - this.layout = new MonitorLayout(compiler);
56 - coordinator.addListener(this);
57 - }
58 -
59 - /**
60 - * Sets the process monitor delegate.
61 - *
62 - * @param delegate process monitor delegate
63 - */
64 - void setDelegate(MonitorDelegate delegate) {
65 - this.delegate = delegate;
66 - }
67 -
68 - /**
69 - * Notifies the process monitor delegate with the specified event.
70 - *
71 - * @param event JSON event data
72 - */
73 - public void notify(ObjectNode event) {
74 - if (delegate != null) {
75 - delegate.notify(event);
76 - }
77 - }
78 -
79 - /**
80 - * Returns the scenario process flow as JSON data.
81 - *
82 - * @return scenario process flow data
83 - */
84 - ObjectNode scenarioData() {
85 - ObjectNode root = mapper.createObjectNode();
86 - ArrayNode steps = mapper.createArrayNode();
87 - ArrayNode requirements = mapper.createArrayNode();
88 -
89 - ProcessFlow pf = compiler.processFlow();
90 - pf.getVertexes().forEach(step -> add(step, steps));
91 - pf.getEdges().forEach(requirement -> add(requirement, requirements));
92 -
93 - root.set("steps", steps);
94 - root.set("requirements", requirements);
95 -
96 - try (FileWriter fw = new FileWriter("/tmp/data.json");
97 - PrintWriter pw = new PrintWriter(fw)) {
98 - pw.println(root.toString());
99 - } catch (IOException e) {
100 - e.printStackTrace();
101 - }
102 - return root;
103 - }
104 -
105 -
106 - private void add(Step step, ArrayNode steps) {
107 - Box box = layout.get(step);
108 - ObjectNode sn = mapper.createObjectNode()
109 - .put("name", step.name())
110 - .put("isGroup", step instanceof Group)
111 - .put("status", status(coordinator.getStatus(step)))
112 - .put("tier", box.tier())
113 - .put("depth", box.depth());
114 - if (step.group() != null) {
115 - sn.put("group", step.group().name());
116 - }
117 - steps.add(sn);
118 - }
119 -
120 - private String status(Coordinator.Status status) {
121 - return status.toString().toLowerCase();
122 - }
123 -
124 - private void add(Dependency requirement, ArrayNode requirements) {
125 - ObjectNode rn = mapper.createObjectNode();
126 - rn.put("src", requirement.src().name())
127 - .put("dst", requirement.dst().name())
128 - .put("isSoft", requirement.isSoft());
129 - requirements.add(rn);
130 - }
131 -
132 - @Override
133 - public void onStart(Step step, String command) {
134 - notify(event(step, status(IN_PROGRESS)));
135 - }
136 -
137 - @Override
138 - public void onCompletion(Step step, Coordinator.Status status) {
139 - notify(event(step, status(status)));
140 - }
141 -
142 - @Override
143 - public void onOutput(Step step, String line) {
144 -
145 - }
146 -
147 - private ObjectNode event(Step step, String status) {
148 - ObjectNode event = mapper.createObjectNode()
149 - .put("name", step.name())
150 - .put("status", status);
151 - return event;
152 - }
153 -
154 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.fasterxml.jackson.databind.node.ObjectNode;
19 -
20 -/**
21 - * Delegate to which monitor can send notifications.
22 - */
23 -public interface MonitorDelegate {
24 -
25 - /**
26 - * Issues JSON event to be sent to any connected monitor clients.
27 - *
28 - * @param event JSON event data
29 - */
30 - void notify(ObjectNode event);
31 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.Lists;
19 -import com.google.common.collect.Maps;
20 -
21 -import java.util.List;
22 -import java.util.Map;
23 -import java.util.Set;
24 -import java.util.stream.Collectors;
25 -import java.util.stream.IntStream;
26 -
27 -/**
28 - * Computes scenario process flow layout for the Monitor GUI.
29 - */
30 -public class MonitorLayout {
31 -
32 - public static final int WIDTH = 210;
33 - public static final int HEIGHT = 30;
34 - public static final int W_GAP = 40;
35 - public static final int H_GAP = 50;
36 - public static final int SLOT_WIDTH = WIDTH + H_GAP;
37 -
38 - private final Compiler compiler;
39 - private final ProcessFlow flow;
40 -
41 - private Map<Step, Box> boxes = Maps.newHashMap();
42 -
43 - /**
44 - * Creates a new shared process flow monitor.
45 - *
46 - * @param compiler scenario compiler
47 - */
48 - MonitorLayout(Compiler compiler) {
49 - this.compiler = compiler;
50 - this.flow = compiler.processFlow();
51 -
52 - // Extract the flow and create initial bounding boxes.
53 - boxes.put(null, new Box(null, 0));
54 - flow.getVertexes().forEach(this::createBox);
55 -
56 - computeLayout(null, 0, 1);
57 - }
58 -
59 - // Computes the graph layout giving preference to group associations.
60 - private void computeLayout(Group group, int absoluteTier, int tier) {
61 - Box box = boxes.get(group);
62 -
63 - // Find all children of the group, or items with no group if at top.
64 - Set<Step> children = group != null ? group.children() :
65 - flow.getVertexes().stream().filter(s -> s.group() == null)
66 - .collect(Collectors.toSet());
67 -
68 - children.forEach(s -> visit(s, absoluteTier, 1, group));
69 -
70 - // Figure out what the group root vertexes are.
71 - Set<Step> roots = findRoots(group);
72 -
73 - // Compute the boxes for each of the roots.
74 - roots.forEach(s -> updateBox(s, absoluteTier + 1, 1, group));
75 -
76 - // Update the tier and depth of the group bounding box.
77 - computeTiersAndDepth(group, box, absoluteTier, tier, children);
78 -
79 - // Compute the minimum breadth of this group's bounding box.
80 - computeBreadth(group, box, children);
81 -
82 - // Compute child placements
83 - computeChildPlacements(group, box, children);
84 - }
85 -
86 - // Updates the box for the specified step, given the tier number, which
87 - // is relative to the parent.
88 - private Box updateBox(Step step, int absoluteTier, int tier, Group group) {
89 - Box box = boxes.get(step);
90 - if (step instanceof Group) {
91 - computeLayout((Group) step, absoluteTier, tier);
92 - } else {
93 - box.setTierAndDepth(absoluteTier, tier, 1, group);
94 - }
95 -
96 - // Follow the steps downstream of this one.
97 - follow(step, absoluteTier + box.depth(), box.tier() + box.depth());
98 - return box;
99 - }
100 -
101 - // Backwards follows edges leading towards the specified step to visit
102 - // the source vertex and compute layout of those vertices that had
103 - // sufficient number of visits to compute their tier.
104 - private void follow(Step step, int absoluteTier, int tier) {
105 - Group from = step.group();
106 - flow.getEdgesTo(step).stream()
107 - .filter(d -> visit(d.src(), absoluteTier, tier, from))
108 - .forEach(d -> updateBox(d.src(), absoluteTier, tier, from));
109 - }
110 -
111 - // Visits each step, records maximum tier and returns true if this
112 - // was the last expected visit.
113 - private boolean visit(Step step, int absoluteTier, int tier, Group from) {
114 - Box box = boxes.get(step);
115 - return box.visitAndLatchMaxTier(absoluteTier, tier, from);
116 - }
117 -
118 - // Computes the absolute and relative tiers and the depth of the group
119 - // bounding box.
120 - private void computeTiersAndDepth(Group group, Box box,
121 - int absoluteTier, int tier, Set<Step> children) {
122 - int depth = children.stream().mapToInt(this::bottomMostTier).max().getAsInt();
123 - box.setTierAndDepth(absoluteTier, tier, depth, group);
124 - }
125 -
126 - // Returns the bottom-most tier this step occupies relative to its parent.
127 - private int bottomMostTier(Step step) {
128 - Box box = boxes.get(step);
129 - return box.tier() + box.depth();
130 - }
131 -
132 - // Computes breadth of the specified group.
133 - private void computeBreadth(Group group, Box box, Set<Step> children) {
134 - if (box.breadth() == 0) {
135 - // Scan through all tiers and determine the maximum breadth of each.
136 - IntStream.range(1, box.depth)
137 - .forEach(t -> computeTierBreadth(t, box, children));
138 - box.latchBreadth(children.stream()
139 - .mapToInt(s -> boxes.get(s).breadth())
140 - .max().getAsInt());
141 - }
142 - }
143 -
144 - // Computes tier width.
145 - private void computeTierBreadth(int t, Box box, Set<Step> children) {
146 - box.latchBreadth(children.stream().map(boxes::get)
147 - .filter(b -> isSpanningTier(b, t))
148 - .mapToInt(Box::breadth).sum());
149 - }
150 -
151 - // Computes the actual child box placements relative to the parent using
152 - // the previously established tier, depth and breadth attributes.
153 - private void computeChildPlacements(Group group, Box box,
154 - Set<Step> children) {
155 - // Order the root-nodes in alphanumeric order first.
156 - List<Box> tierBoxes = Lists.newArrayList(boxesOnTier(1, children));
157 - tierBoxes.sort((a, b) -> a.step().name().compareTo(b.step().name()));
158 -
159 - // Place the boxes centered on the parent box; left to right.
160 - int tierBreadth = tierBoxes.stream().mapToInt(Box::breadth).sum();
161 - int slot = 1;
162 - for (Box b : tierBoxes) {
163 - b.updateCenter(1, slot(slot, tierBreadth));
164 - slot += b.breadth();
165 - }
166 - }
167 -
168 - // Returns the horizontal offset off the parent center.
169 - private int slot(int slot, int tierBreadth) {
170 - boolean even = tierBreadth % 2 == 0;
171 - int multiplier = -tierBreadth / 2 + slot - 1;
172 - return even ? multiplier * SLOT_WIDTH + SLOT_WIDTH / 2 : multiplier * SLOT_WIDTH;
173 - }
174 -
175 - // Returns a list of all child step boxes that start on the specified tier.
176 - private List<Box> boxesOnTier(int tier, Set<Step> children) {
177 - return boxes.values().stream()
178 - .filter(b -> b.tier() == tier && children.contains(b.step()))
179 - .collect(Collectors.toList());
180 - }
181 -
182 - // Determines whether the specified box spans, or occupies a tier.
183 - private boolean isSpanningTier(Box b, int tier) {
184 - return (b.depth() == 1 && b.tier() == tier) ||
185 - (b.tier() <= tier && tier < b.tier() + b.depth());
186 - }
187 -
188 -
189 - // Determines roots of the specified group or of the entire graph.
190 - private Set<Step> findRoots(Group group) {
191 - Set<Step> steps = group != null ? group.children() : flow.getVertexes();
192 - return steps.stream().filter(s -> isRoot(s, group)).collect(Collectors.toSet());
193 - }
194 -
195 - private boolean isRoot(Step step, Group group) {
196 - if (step.group() != group) {
197 - return false;
198 - }
199 -
200 - Set<Dependency> requirements = flow.getEdgesFrom(step);
201 - return requirements.stream().filter(r -> r.dst().group() == group)
202 - .collect(Collectors.toSet()).isEmpty();
203 - }
204 -
205 - /**
206 - * Returns the bounding box for the specified step. If null is given, it
207 - * returns the overall bounding box.
208 - *
209 - * @param step step or group; null for the overall bounding box
210 - * @return bounding box
211 - */
212 - public Box get(Step step) {
213 - return boxes.get(step);
214 - }
215 -
216 - /**
217 - * Returns the bounding box for the specified step name. If null is given,
218 - * it returns the overall bounding box.
219 - *
220 - * @param name name of step or group; null for the overall bounding box
221 - * @return bounding box
222 - */
223 - public Box get(String name) {
224 - return get(name == null ? null : compiler.getStep(name));
225 - }
226 -
227 - // Creates a bounding box for the specified step or group.
228 - private void createBox(Step step) {
229 - boxes.put(step, new Box(step, flow.getEdgesFrom(step).size()));
230 - }
231 -
232 - /**
233 - * Bounding box data for a step or group.
234 - */
235 - final class Box {
236 -
237 - private Step step;
238 - private int remainingRequirements;
239 -
240 - private int absoluteTier = 0;
241 - private int tier;
242 - private int depth = 1;
243 - private int breadth;
244 - private int center, top;
245 -
246 - private Box(Step step, int remainingRequirements) {
247 - this.step = step;
248 - this.remainingRequirements = remainingRequirements + 1;
249 - breadth = step == null || step instanceof Group ? 0 : 1;
250 - }
251 -
252 - private void latchTiers(int absoluteTier, int tier, Group from) {
253 - this.absoluteTier = Math.max(this.absoluteTier, absoluteTier);
254 - if (step == null || step.group() == from) {
255 - this.tier = Math.max(this.tier, tier);
256 - }
257 - }
258 -
259 - public void latchBreadth(int breadth) {
260 - this.breadth = Math.max(this.breadth, breadth);
261 - }
262 -
263 - void setTierAndDepth(int absoluteTier, int tier, int depth, Group from) {
264 - latchTiers(absoluteTier, tier, from);
265 - this.depth = depth;
266 - }
267 -
268 - boolean visitAndLatchMaxTier(int absoluteTier, int tier, Group from) {
269 - latchTiers(absoluteTier, tier, from);
270 - --remainingRequirements;
271 - return remainingRequirements == 0;
272 - }
273 -
274 - Step step() {
275 - return step;
276 - }
277 -
278 - public int absoluteTier() {
279 - return absoluteTier;
280 - }
281 -
282 - int tier() {
283 - return tier;
284 - }
285 -
286 - int depth() {
287 - return depth;
288 - }
289 -
290 - int breadth() {
291 - return breadth;
292 - }
293 -
294 - int top() {
295 - return top;
296 - }
297 -
298 - int center() {
299 - return center;
300 - }
301 -
302 - public void updateCenter(int top, int center) {
303 - this.top = top;
304 - this.center = center;
305 - }
306 - }
307 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.fasterxml.jackson.databind.ObjectMapper;
19 -import com.fasterxml.jackson.databind.node.ObjectNode;
20 -import org.eclipse.jetty.websocket.WebSocket;
21 -
22 -import java.io.IOException;
23 -
24 -import static org.onlab.stc.Coordinator.print;
25 -
26 -/**
27 - * Web socket capable of interacting with the STC monitor GUI.
28 - */
29 -public class MonitorWebSocket implements WebSocket.OnTextMessage, WebSocket.OnControl {
30 -
31 - private static final long MAX_AGE_MS = 30_000;
32 -
33 - private static final byte PING = 0x9;
34 - private static final byte PONG = 0xA;
35 - private static final byte[] PING_DATA = new byte[]{(byte) 0xde, (byte) 0xad};
36 -
37 - private final Monitor monitor;
38 -
39 - private Connection connection;
40 - private FrameConnection control;
41 -
42 - private final ObjectMapper mapper = new ObjectMapper();
43 -
44 - private long lastActive = System.currentTimeMillis();
45 -
46 - /**
47 - * Creates a new monitor client GUI web-socket.
48 - *
49 - * @param monitor shared process flow monitor
50 - */
51 - MonitorWebSocket(Monitor monitor) {
52 - this.monitor = monitor;
53 - }
54 -
55 - /**
56 - * Issues a close on the connection.
57 - */
58 - synchronized void close() {
59 - destroyHandlers();
60 - if (connection.isOpen()) {
61 - connection.close();
62 - }
63 - }
64 -
65 - /**
66 - * Indicates if this connection is idle.
67 - *
68 - * @return true if idle or closed
69 - */
70 - synchronized boolean isIdle() {
71 - long quietFor = System.currentTimeMillis() - lastActive;
72 - boolean idle = quietFor > MAX_AGE_MS;
73 - if (idle || (connection != null && !connection.isOpen())) {
74 - return true;
75 - } else if (connection != null) {
76 - try {
77 - control.sendControl(PING, PING_DATA, 0, PING_DATA.length);
78 - } catch (IOException e) {
79 - print("Unable to send ping message due to: %s", e);
80 - }
81 - }
82 - return false;
83 - }
84 -
85 - @Override
86 - public void onOpen(Connection connection) {
87 - this.connection = connection;
88 - this.control = (FrameConnection) connection;
89 - try {
90 - createHandlers();
91 - sendMessage(message("flow", monitor.scenarioData()));
92 -
93 - } catch (Exception e) {
94 - print("Unable to open monitor connection: %s", e);
95 - this.connection.close();
96 - this.connection = null;
97 - this.control = null;
98 - }
99 - }
100 -
101 - @Override
102 - public synchronized void onClose(int closeCode, String message) {
103 - destroyHandlers();
104 - }
105 -
106 - @Override
107 - public boolean onControl(byte controlCode, byte[] data, int offset, int length) {
108 - lastActive = System.currentTimeMillis();
109 - return true;
110 - }
111 -
112 - @Override
113 - public void onMessage(String data) {
114 - lastActive = System.currentTimeMillis();
115 - try {
116 - ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
117 - // TODO:
118 - print("Got message: %s", message);
119 - } catch (Exception e) {
120 - print("Unable to parse GUI message %s due to %s", data, e);
121 - }
122 - }
123 -
124 - public synchronized void sendMessage(ObjectNode message) {
125 - try {
126 - if (connection.isOpen()) {
127 - connection.sendMessage(message.toString());
128 - }
129 - } catch (IOException e) {
130 - print("Unable to send message %s to GUI due to %s", message, e);
131 - }
132 - }
133 -
134 - public ObjectNode message(String type, ObjectNode payload) {
135 - ObjectNode message = mapper.createObjectNode().put("event", type);
136 - message.set("payload", payload);
137 - return message;
138 - }
139 -
140 - // Creates new message handlers.
141 - private synchronized void createHandlers() {
142 - }
143 -
144 - // Destroys message handlers.
145 - private synchronized void destroyHandlers() {
146 - }
147 -
148 -}
149 -
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.fasterxml.jackson.databind.node.ObjectNode;
19 -import com.google.common.io.ByteStreams;
20 -import com.google.common.net.MediaType;
21 -import org.eclipse.jetty.websocket.WebSocket;
22 -import org.eclipse.jetty.websocket.WebSocketServlet;
23 -
24 -import javax.servlet.ServletException;
25 -import javax.servlet.http.HttpServletRequest;
26 -import javax.servlet.http.HttpServletResponse;
27 -import java.io.IOException;
28 -import java.io.InputStream;
29 -import java.util.HashSet;
30 -import java.util.Iterator;
31 -import java.util.Set;
32 -import java.util.Timer;
33 -import java.util.TimerTask;
34 -
35 -/**
36 - * Web socket servlet capable of creating web sockets for the STC monitor.
37 - */
38 -public class MonitorWebSocketServlet extends WebSocketServlet
39 - implements MonitorDelegate {
40 -
41 - private static final long PING_DELAY_MS = 5000;
42 - private static final String DOT = ".";
43 -
44 - private static Monitor monitor;
45 - private static MonitorWebSocketServlet instance;
46 -
47 - private final Set<MonitorWebSocket> sockets = new HashSet<>();
48 - private final Timer timer = new Timer();
49 - private final TimerTask pruner = new Pruner();
50 -
51 - /**
52 - * Binds the shared process flow monitor.
53 - *
54 - * @param m process monitor reference
55 - */
56 - public static void setMonitor(Monitor m) {
57 - monitor = m;
58 - }
59 -
60 - /**
61 - * Closes all currently open monitor web-sockets.
62 - */
63 - public static void closeAll() {
64 - if (instance != null) {
65 - instance.sockets.forEach(MonitorWebSocket::close);
66 - instance.sockets.clear();
67 - }
68 - }
69 -
70 - @Override
71 - public void init() throws ServletException {
72 - super.init();
73 - instance = this;
74 - monitor.setDelegate(this);
75 - timer.schedule(pruner, PING_DELAY_MS, PING_DELAY_MS);
76 - }
77 -
78 - @Override
79 - protected void doGet(HttpServletRequest req, HttpServletResponse resp)
80 - throws ServletException, IOException {
81 - String uri = req.getRequestURI();
82 - uri = uri.length() <= 1 ? "/index.html" : uri;
83 - InputStream resource = getClass().getResourceAsStream(uri);
84 - if (resource == null) {
85 - resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
86 - } else {
87 - byte[] entity = ByteStreams.toByteArray(resource);
88 - resp.setStatus(HttpServletResponse.SC_OK);
89 - resp.setContentType(contentType(uri).toString());
90 - resp.setContentLength(entity.length);
91 - resp.getOutputStream().write(entity);
92 - }
93 - }
94 -
95 - private MediaType contentType(String uri) {
96 - int sep = uri.lastIndexOf(DOT);
97 - String ext = sep > 0 ? uri.substring(sep + 1) : null;
98 - return ext == null ? MediaType.APPLICATION_BINARY :
99 - ext.equals("html") ? MediaType.HTML_UTF_8 :
100 - ext.equals("js") ? MediaType.JAVASCRIPT_UTF_8 :
101 - ext.equals("css") ? MediaType.CSS_UTF_8 :
102 - MediaType.APPLICATION_BINARY;
103 - }
104 -
105 - @Override
106 - public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
107 - MonitorWebSocket socket = new MonitorWebSocket(monitor);
108 - synchronized (sockets) {
109 - sockets.add(socket);
110 - }
111 - return socket;
112 - }
113 -
114 - @Override
115 - public void notify(ObjectNode event) {
116 - if (instance != null) {
117 - instance.sockets.forEach(ws -> ws.sendMessage(event));
118 - }
119 - }
120 -
121 - // Task for pruning web-sockets that are idle.
122 - private class Pruner extends TimerTask {
123 - @Override
124 - public void run() {
125 - synchronized (sockets) {
126 - Iterator<MonitorWebSocket> it = sockets.iterator();
127 - while (it.hasNext()) {
128 - MonitorWebSocket socket = it.next();
129 - if (socket.isIdle()) {
130 - it.remove();
131 - socket.close();
132 - }
133 - }
134 - }
135 - }
136 - }
137 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.onlab.graph.MutableAdjacencyListsGraph;
19 -
20 -import java.util.Set;
21 -
22 -/**
23 - * Graph representation of a test process flow.
24 - */
25 -public class ProcessFlow extends MutableAdjacencyListsGraph<Step, Dependency> {
26 -
27 - /**
28 - * Creates a graph comprising of the specified vertexes and edges.
29 - *
30 - * @param vertexes set of graph vertexes
31 - * @param edges set of graph edges
32 - */
33 - public ProcessFlow(Set<Step> vertexes, Set<Dependency> edges) {
34 - super(vertexes, edges);
35 - }
36 -
37 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.apache.commons.configuration.ConfigurationException;
19 -import org.apache.commons.configuration.HierarchicalConfiguration;
20 -import org.apache.commons.configuration.XMLConfiguration;
21 -
22 -import java.io.InputStream;
23 -
24 -import static com.google.common.base.Preconditions.checkNotNull;
25 -import static com.google.common.base.Preconditions.checkState;
26 -
27 -/**
28 - * Representation of a re-usable test scenario.
29 - */
30 -public final class Scenario {
31 -
32 - private static final String SCENARIO = "scenario";
33 - private static final String NAME = "[@name]";
34 - private static final String DESCRIPTION = "[@description]";
35 -
36 - private final String name;
37 - private final String description;
38 - private final HierarchicalConfiguration definition;
39 -
40 - // Creates a new scenario from the specified definition.
41 - private Scenario(String name, String description, HierarchicalConfiguration definition) {
42 - this.name = checkNotNull(name, "Name cannot be null");
43 - this.description = checkNotNull(description, "Description cannot be null");
44 - this.definition = checkNotNull(definition, "Definition cannot be null");
45 - }
46 -
47 - /**
48 - * Loads a new scenario from the specified hierarchical configuration.
49 - *
50 - * @param definition scenario definition
51 - * @return loaded scenario
52 - */
53 - public static Scenario loadScenario(HierarchicalConfiguration definition) {
54 - String name = definition.getString(NAME);
55 - String description = definition.getString(DESCRIPTION, "");
56 - checkState(name != null, "Scenario name must be specified");
57 - return new Scenario(name, description, definition);
58 - }
59 -
60 - /**
61 - * Loads a new scenario from the specified input stream.
62 - *
63 - * @param stream scenario definition stream
64 - * @return loaded scenario
65 - */
66 - public static Scenario loadScenario(InputStream stream) {
67 - XMLConfiguration cfg = new XMLConfiguration();
68 - cfg.setAttributeSplittingDisabled(true);
69 - cfg.setDelimiterParsingDisabled(true);
70 - cfg.setRootElementName(SCENARIO);
71 - try {
72 - cfg.load(stream);
73 - return loadScenario(cfg);
74 - } catch (ConfigurationException e) {
75 - throw new IllegalArgumentException("Unable to load scenario from the stream", e);
76 - }
77 - }
78 -
79 - /**
80 - * Returns the scenario name.
81 - *
82 - * @return scenario name
83 - */
84 - public String name() {
85 - return name;
86 - }
87 -
88 - /**
89 - * Returns the scenario description.
90 - *
91 - * @return scenario description
92 - */
93 - public String description() {
94 - return description;
95 - }
96 -
97 - /**
98 - * Returns the scenario definition.
99 - *
100 - * @return scenario definition
101 - */
102 - public HierarchicalConfiguration definition() {
103 - return definition;
104 - }
105 -
106 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.collect.ImmutableList;
19 -import com.google.common.collect.Lists;
20 -import com.google.common.collect.Maps;
21 -import org.apache.commons.configuration.ConfigurationException;
22 -import org.apache.commons.configuration.PropertiesConfiguration;
23 -import org.onlab.stc.Coordinator.Status;
24 -
25 -import java.io.File;
26 -import java.util.List;
27 -import java.util.Map;
28 -import java.util.Set;
29 -
30 -import static com.google.common.base.Preconditions.checkNotNull;
31 -import static org.onlab.stc.Coordinator.Status.*;
32 -import static org.onlab.stc.Coordinator.print;
33 -
34 -/**
35 - * Maintains state of scenario execution.
36 - */
37 -class ScenarioStore {
38 -
39 - private final ProcessFlow processFlow;
40 - private final File storeFile;
41 - private final File logDir;
42 -
43 - private final List<StepEvent> events = Lists.newArrayList();
44 - private final Map<String, Status> statusMap = Maps.newConcurrentMap();
45 -
46 - private long startTime = Long.MAX_VALUE;
47 - private long endTime = Long.MIN_VALUE;
48 -
49 - /**
50 - * Creates a new scenario store for the specified process flow.
51 - *
52 - * @param processFlow scenario process flow
53 - * @param logDir scenario log directory
54 - * @param name scenario name
55 - */
56 - ScenarioStore(ProcessFlow processFlow, File logDir, String name) {
57 - this.processFlow = processFlow;
58 - this.logDir = logDir;
59 - this.storeFile = new File(logDir, name + ".stc");
60 - load();
61 - }
62 -
63 - /**
64 - * Resets status of all steps to waiting and clears all events.
65 - */
66 - void reset() {
67 - events.clear();
68 - statusMap.clear();
69 - processFlow.getVertexes().forEach(step -> statusMap.put(step.name(), WAITING));
70 - try {
71 - removeLogs();
72 - PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
73 - cfg.clear();
74 - cfg.save();
75 - startTime = Long.MAX_VALUE;
76 - endTime = Long.MIN_VALUE;
77 - } catch (ConfigurationException e) {
78 - print("Unable to store file %s", storeFile);
79 - }
80 -
81 - }
82 -
83 - /**
84 - * Returns set of all test steps.
85 - *
86 - * @return set of steps
87 - */
88 - Set<Step> getSteps() {
89 - return processFlow.getVertexes();
90 - }
91 -
92 - /**
93 - * Returns a chronological list of step or group records.
94 - *
95 - * @return list of events
96 - */
97 - synchronized List<StepEvent> getEvents() {
98 - return ImmutableList.copyOf(events);
99 - }
100 -
101 - /**
102 - * Returns the status record of the specified test step.
103 - *
104 - * @param step test step or group
105 - * @return step status record
106 - */
107 - Status getStatus(Step step) {
108 - return checkNotNull(statusMap.get(step.name()), "Step %s not found", step.name());
109 - }
110 -
111 - /**
112 - * Marks the specified test step as being in progress.
113 - *
114 - * @param step test step or group
115 - */
116 - synchronized void markStarted(Step step) {
117 - add(new StepEvent(step.name(), IN_PROGRESS, step.command()));
118 - save();
119 - }
120 -
121 - /**
122 - * Marks the specified test step as being complete.
123 - *
124 - * @param step test step or group
125 - * @param status new step status
126 - */
127 - synchronized void markComplete(Step step, Status status) {
128 - add(new StepEvent(step.name(), status, null));
129 - save();
130 - }
131 -
132 - /**
133 - * Returns true if all steps in the store have been marked as completed
134 - * regardless of the completion status.
135 - *
136 - * @return true if all steps completed one way or another
137 - */
138 - synchronized boolean isComplete() {
139 - return !statusMap.values().stream().anyMatch(s -> s == WAITING || s == IN_PROGRESS);
140 - }
141 -
142 - /**
143 - * Indicates whether there are any failures.
144 - *
145 - * @return true if there are failed steps
146 - */
147 - boolean hasFailures() {
148 - for (Status status : statusMap.values()) {
149 - if (status == FAILED) {
150 - return true;
151 - }
152 - }
153 - return false;
154 - }
155 -
156 - /**
157 - * Registers a new step record.
158 - *
159 - * @param event step event
160 - */
161 - private synchronized void add(StepEvent event) {
162 - events.add(event);
163 - statusMap.put(event.name(), event.status());
164 - startTime = Math.min(startTime, event.time());
165 - endTime = Math.max(endTime, event.time());
166 - }
167 -
168 - /**
169 - * Loads the states from disk.
170 - */
171 - private void load() {
172 - try {
173 - PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
174 - cfg.getKeys().forEachRemaining(prop -> add(StepEvent.fromString(cfg.getString(prop))));
175 - cfg.save();
176 - } catch (ConfigurationException e) {
177 - print("Unable to load file %s", storeFile);
178 - }
179 - }
180 -
181 - /**
182 - * Saves the states to disk.
183 - */
184 - private void save() {
185 - try {
186 - PropertiesConfiguration cfg = new PropertiesConfiguration(storeFile);
187 - events.forEach(event -> cfg.setProperty("T" + event.time(), event.toString()));
188 - cfg.save();
189 - } catch (ConfigurationException e) {
190 - print("Unable to store file %s", storeFile);
191 - }
192 - }
193 -
194 - /**
195 - * Removes all scenario log files.
196 - */
197 - private void removeLogs() {
198 - File[] logFiles = logDir.listFiles();
199 - if (logFiles != null && logFiles.length > 0) {
200 - for (File file : logFiles) {
201 - if (!file.delete()) {
202 - print("Unable to delete log file %s", file);
203 - }
204 - }
205 - }
206 - }
207 -
208 - /**
209 - * Returns the scenario run start time.
210 - *
211 - * @return start time in mills since start of epoch
212 - */
213 - public long startTime() {
214 - return startTime;
215 - }
216 -
217 - /**
218 - * Returns the scenario run end time or current time if the scenario
219 - * is still running.
220 - *
221 - * @return end time (or current time) in mills since start of epoch
222 - */
223 - public long endTime() {
224 - return endTime > 0 ? endTime : System.currentTimeMillis();
225 - }
226 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onlab.graph.Vertex;
20 -
21 -import java.util.Objects;
22 -
23 -import static com.google.common.base.Preconditions.checkNotNull;
24 -
25 -/**
26 - * Representation of a test step.
27 - */
28 -public class Step implements Vertex {
29 -
30 - protected final String name;
31 - protected final String command;
32 - protected final String env;
33 - protected final String cwd;
34 - protected final Group group;
35 - protected final int delay;
36 -
37 - /**
38 - * Creates a new test step.
39 - *
40 - * @param name step name
41 - * @param command step command to execute
42 - * @param env path to file to be sourced into the environment
43 - * @param cwd path to current working directory for the step
44 - * @param group optional group to which this step belongs
45 - * @param delay seconds to delay before executing
46 - */
47 - public Step(String name, String command, String env, String cwd, Group group, int delay) {
48 - this.name = checkNotNull(name, "Name cannot be null");
49 - this.group = group;
50 - this.delay = delay;
51 -
52 - // Set the command, environment and cwd
53 - // If one is not given use the value from the enclosing group
54 - this.command = command != null ? command : group != null && group.command != null ? group.command : null;
55 - this.env = env != null ? env : group != null && group.env != null ? group.env : null;
56 - this.cwd = cwd != null ? cwd : group != null && group.cwd != null ? group.cwd : null;
57 - }
58 -
59 - /**
60 - * Returns the step name.
61 - *
62 - * @return step name
63 - */
64 - public String name() {
65 - return name;
66 - }
67 -
68 - /**
69 - * Returns the step command string.
70 - *
71 - * @return command string
72 - */
73 - public String command() {
74 - return command;
75 - }
76 -
77 - /**
78 - * Returns the step environment script path.
79 - *
80 - * @return env script path
81 - */
82 - public String env() {
83 - return env;
84 - }
85 -
86 - /**
87 - * Returns the step current working directory path.
88 - *
89 - * @return current working dir path
90 - */
91 - public String cwd() {
92 - return cwd;
93 - }
94 -
95 - /**
96 - * Returns the enclosing group; null if none.
97 - *
98 - * @return enclosing group or null
99 - */
100 - public Group group() {
101 - return group;
102 - }
103 -
104 - /**
105 - * Returns the start delay in seconds.
106 - *
107 - * @return number of seconds
108 - */
109 - public int delay() {
110 - return delay;
111 - }
112 -
113 - @Override
114 - public int hashCode() {
115 - return name.hashCode();
116 - }
117 -
118 - @Override
119 - public boolean equals(Object obj) {
120 - if (this == obj) {
121 - return true;
122 - }
123 - if (obj instanceof Step) {
124 - final Step other = (Step) obj;
125 - return Objects.equals(this.name, other.name);
126 - }
127 - return false;
128 - }
129 -
130 - @Override
131 - public String toString() {
132 - return MoreObjects.toStringHelper(this)
133 - .add("name", name)
134 - .add("command", command)
135 - .add("env", env)
136 - .add("cwd", cwd)
137 - .add("group", group)
138 - .add("delay", delay)
139 - .toString();
140 - }
141 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.onlab.stc.Coordinator.Status;
19 -
20 -import static java.lang.Long.parseLong;
21 -import static org.onlab.stc.Coordinator.Status.valueOf;
22 -
23 -/**
24 - * Represents an event of execution of a scenario step or group.
25 - */
26 -public class StepEvent {
27 -
28 - private static final String SEP = "~";
29 -
30 - private final String name;
31 - private final long time;
32 - private final Status status;
33 - private final String command;
34 -
35 - /**
36 - * Creates a new step record.
37 - *
38 - * @param name test step or group name
39 - * @param time time in millis since start of epoch
40 - * @param status step completion status
41 - * @param command step command
42 - */
43 - public StepEvent(String name, long time, Status status, String command) {
44 - this.name = name;
45 - this.time = time;
46 - this.status = status;
47 - this.command = command;
48 - }
49 -
50 - /**
51 - * Creates a new step record for non-running status.
52 - *
53 - * @param name test step or group name
54 - * @param status status
55 - * @param command step command
56 - */
57 - public StepEvent(String name, Status status, String command) {
58 - this(name, System.currentTimeMillis(), status, command);
59 - }
60 -
61 - /**
62 - * Returns the test step or test group name.
63 - *
64 - * @return step or group name
65 - */
66 - public String name() {
67 - return name;
68 - }
69 -
70 - /**
71 - * Returns the step event time.
72 - *
73 - * @return time in millis since start of epoch
74 - */
75 - public long time() {
76 - return time;
77 - }
78 -
79 - /**
80 - * Returns the step completion status.
81 - *
82 - * @return completion status
83 - */
84 - public Status status() {
85 - return status;
86 - }
87 -
88 - /**
89 - * Returns the step command.
90 - *
91 - * @return step command
92 - */
93 - public String command() {
94 - return command;
95 - }
96 -
97 -
98 - @Override
99 - public String toString() {
100 - return name + SEP + time + SEP + status + SEP + command;
101 - }
102 -
103 - /**
104 - * Returns a record parsed from the specified string.
105 - *
106 - * @param string string encoding
107 - * @return step record
108 - */
109 - public static StepEvent fromString(String string) {
110 - String[] fields = string.split("~");
111 - return fields.length == 4 ?
112 - new StepEvent(fields[0], parseLong(fields[1]), valueOf(fields[2]),
113 - fields[3].equals("null") ? null : fields[3]) :
114 - new StepEvent(fields[0], 0, Status.WAITING, null);
115 - }
116 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -/**
19 - * Entity capable of receiving notifications of process step execution events.
20 - */
21 -public interface StepProcessListener {
22 -
23 - /**
24 - * Indicates that process step has started.
25 - *
26 - * @param step subject step
27 - * @param command actual command executed; includes run-time substitutions
28 - */
29 - default void onStart(Step step, String command) {
30 - }
31 -
32 - /**
33 - * Indicates that process step has completed.
34 - *
35 - * @param step subject step
36 - * @param status step completion status
37 - */
38 - default void onCompletion(Step step, Coordinator.Status status) {
39 - }
40 -
41 - /**
42 - * Notifies when a new line of output becomes available.
43 - *
44 - * @param step subject step
45 - * @param line line of output
46 - */
47 - default void onOutput(Step step, String line) {
48 - }
49 -
50 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.onlab.stc.Coordinator.Status;
19 -
20 -import java.io.BufferedReader;
21 -import java.io.File;
22 -import java.io.IOException;
23 -import java.io.InputStream;
24 -import java.io.InputStreamReader;
25 -import java.io.PrintWriter;
26 -
27 -import static java.lang.String.format;
28 -import static org.onlab.stc.Coordinator.Status.FAILED;
29 -import static org.onlab.stc.Coordinator.Status.SUCCEEDED;
30 -import static org.onlab.stc.Coordinator.print;
31 -
32 -/**
33 - * Manages execution of the specified step or a group.
34 - */
35 -class StepProcessor implements Runnable {
36 -
37 - private static final String IGNORE_CODE = "~";
38 - private static final String NEGATE_CODE = "!";
39 -
40 - private static final int FAIL = -1;
41 - private static final int SECONDS = 1_000;
42 -
43 - static String launcher = "stc-launcher ";
44 -
45 - private final Step step;
46 - private final File logDir;
47 - private String command;
48 -
49 - private Process process;
50 - private StepProcessListener delegate;
51 -
52 - /**
53 - * Creates a process monitor.
54 - *
55 - * @param step step or group to be executed
56 - * @param logDir directory where step process log should be stored
57 - * @param delegate process lifecycle listener
58 - * @param command actual command to execute
59 - */
60 - StepProcessor(Step step, File logDir, StepProcessListener delegate,
61 - String command) {
62 - this.step = step;
63 - this.logDir = logDir;
64 - this.delegate = delegate;
65 - this.command = command;
66 - }
67 -
68 - @Override
69 - public void run() {
70 - delegate.onStart(step, command);
71 - delayIfNeeded();
72 - int code = execute();
73 - boolean ignoreCode = step.env() != null && step.env.equals(IGNORE_CODE);
74 - boolean negateCode = step.env() != null && step.env.equals(NEGATE_CODE);
75 - Status status = ignoreCode || code == 0 && !negateCode || code != 0 && negateCode ?
76 - SUCCEEDED : FAILED;
77 - delegate.onCompletion(step, status);
78 - }
79 -
80 - /**
81 - * Pauses if the step requires it.
82 - */
83 - private void delayIfNeeded() {
84 - if (step.delay() > 0) {
85 - try {
86 - Thread.sleep(step.delay() * SECONDS);
87 - } catch (InterruptedException e) {
88 - throw new RuntimeException("Interrupted", e);
89 - }
90 - }
91 - }
92 -
93 - /**
94 - * Executes the step process.
95 - *
96 - * @return exit code
97 - */
98 - private int execute() {
99 - try (PrintWriter pw = new PrintWriter(logFile())) {
100 - process = Runtime.getRuntime().exec(command());
101 - processOutput(pw);
102 -
103 - // Wait for the process to complete and get its exit code.
104 - if (process.isAlive()) {
105 - process.waitFor();
106 - }
107 - return process.exitValue();
108 -
109 - } catch (IOException e) {
110 - print("Unable to run step %s using command %s", step.name(), step.command());
111 - } catch (InterruptedException e) {
112 - print("Step %s interrupted", step.name());
113 - }
114 - return FAIL;
115 - }
116 -
117 - /**
118 - * Returns ready-to-run command for the step.
119 - *
120 - * @return command to execute
121 - */
122 - private String command() {
123 - return format("%s %s %s %s", launcher,
124 - step.env() != null ? step.env() : "-",
125 - step.cwd() != null ? step.cwd() : "-",
126 - command);
127 - }
128 -
129 - /**
130 - * Captures output of the step process.
131 - *
132 - * @param pw print writer to send output to
133 - * @throws IOException if unable to read output or write logs
134 - */
135 - private void processOutput(PrintWriter pw) throws IOException {
136 - InputStream out = process.getInputStream();
137 - BufferedReader br = new BufferedReader(new InputStreamReader(out));
138 -
139 - // Slurp its combined stderr/stdout
140 - String line;
141 - while ((line = br.readLine()) != null) {
142 - pw.println(line);
143 - delegate.onOutput(step, line);
144 - }
145 - }
146 -
147 - /**
148 - * Returns the log file for the step output.
149 - *
150 - * @return log file
151 - */
152 - private File logFile() {
153 - return new File(logDir, step.name() + ".log");
154 - }
155 -
156 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * System Test Coordinator tool for modular scenario-based testing.
19 - */
20 -package org.onlab.stc;
...\ No newline at end of file ...\ No newline at end of file
1 -{
2 - "requirements": [
3 - {
4 - "dst": "Reactive-Forwarding.Ping-2",
5 - "isSoft": false,
6 - "src": "Reactive-Forwarding.Link-2-Down"
7 - },
8 - {
9 - "dst": "Final-Check-Logs-2",
10 - "isSoft": true,
11 - "src": "Fetch-Logs-2"
12 - },
13 - {
14 - "dst": "Host-Intent.Ping-4",
15 - "isSoft": false,
16 - "src": "Host-Intent.Link-2-Up"
17 - },
18 - {
19 - "dst": "Install-1",
20 - "isSoft": false,
21 - "src": "Wait-for-Start-1"
22 - },
23 - {
24 - "dst": "Host-Intent.Link-1-Down",
25 - "isSoft": false,
26 - "src": "Host-Intent.Ping-2"
27 - },
28 - {
29 - "dst": "Host-Intent.Link-2-Up",
30 - "isSoft": false,
31 - "src": "Host-Intent.Ping-5"
32 - },
33 - {
34 - "dst": "Host-Intent.Ping-2",
35 - "isSoft": false,
36 - "src": "Host-Intent.Link-2-Down"
37 - },
38 - {
39 - "dst": "Reinstall-App-With-CLI",
40 - "isSoft": false,
41 - "src": "Verify-CLI"
42 - },
43 - {
44 - "dst": "Create-App-UI-Overlay",
45 - "isSoft": false,
46 - "src": "Build-App-With-UI"
47 - },
48 - {
49 - "dst": "Secure-SSH",
50 - "isSoft": true,
51 - "src": "Wait-for-Start-1"
52 - },
53 - {
54 - "dst": "Pause-For-Masters",
55 - "isSoft": true,
56 - "src": "Check-Flows"
57 - },
58 - {
59 - "dst": "Secure-SSH",
60 - "isSoft": true,
61 - "src": "Wait-for-Start-3"
62 - },
63 - {
64 - "dst": "Uninstall-3",
65 - "isSoft": false,
66 - "src": "Kill-3"
67 - },
68 - {
69 - "dst": "Balance-Masters",
70 - "isSoft": false,
71 - "src": "Pause-For-Masters"
72 - },
73 - {
74 - "dst": "Reactive-Forwarding.Net-Pingall",
75 - "isSoft": true,
76 - "src": "Reactive-Forwarding.Net-Link-Down-Up"
77 - },
78 - {
79 - "dst": "Wait-for-Start-3",
80 - "isSoft": true,
81 - "src": "Check-Logs-3"
82 - },
83 - {
84 - "dst": "Wait-for-Start-2",
85 - "isSoft": true,
86 - "src": "Check-Components-2"
87 - },
88 - {
89 - "dst": "Uninstall-Reactive-Forwarding",
90 - "isSoft": false,
91 - "src": "Find-Host-1"
92 - },
93 - {
94 - "dst": "Wipe-Out-Data-Before",
95 - "isSoft": true,
96 - "src": "Initial-Summary-Check"
97 - },
98 - {
99 - "dst": "Reactive-Forwarding.Ping-3",
100 - "isSoft": false,
101 - "src": "Reactive-Forwarding.Link-1-Up"
102 - },
103 - {
104 - "dst": "Archetypes",
105 - "isSoft": true,
106 - "src": "Wrapup"
107 - },
108 - {
109 - "dst": "Reactive-Forwarding.Ping-4",
110 - "isSoft": false,
111 - "src": "Reactive-Forwarding.Link-2-Up"
112 - },
113 - {
114 - "dst": "Host-Intent-Connectivity",
115 - "isSoft": true,
116 - "src": "Net-Teardown"
117 - },
118 - {
119 - "dst": "Host-Intent.Ping-3",
120 - "isSoft": false,
121 - "src": "Host-Intent.Link-1-Up"
122 - },
123 - {
124 - "dst": "Host-Intent.Ping-1",
125 - "isSoft": false,
126 - "src": "Host-Intent.Link-1-Down"
127 - },
128 - {
129 - "dst": "Install-App",
130 - "isSoft": false,
131 - "src": "Create-App-CLI-Overlay"
132 - },
133 - {
134 - "dst": "Final-Check-Logs-3",
135 - "isSoft": true,
136 - "src": "Fetch-Logs-3"
137 - },
138 - {
139 - "dst": "Install-App",
140 - "isSoft": false,
141 - "src": "Verify-App"
142 - },
143 - {
144 - "dst": "Host-Intent.Link-2-Down",
145 - "isSoft": false,
146 - "src": "Host-Intent.Ping-3"
147 - },
148 - {
149 - "dst": "Prerequisites",
150 - "isSoft": false,
151 - "src": "Setup"
152 - },
153 - {
154 - "dst": "Verify-App",
155 - "isSoft": true,
156 - "src": "Reinstall-App-With-CLI"
157 - },
158 - {
159 - "dst": "Net-Smoke",
160 - "isSoft": true,
161 - "src": "Archetypes"
162 - },
163 - {
164 - "dst": "Setup",
165 - "isSoft": true,
166 - "src": "Wrapup"
167 - },
168 - {
169 - "dst": "Start-Mininet",
170 - "isSoft": false,
171 - "src": "Wait-For-Mininet"
172 - },
173 - {
174 - "dst": "Verify-UI",
175 - "isSoft": false,
176 - "src": "Uninstall-App"
177 - },
178 - {
179 - "dst": "Kill-3",
180 - "isSoft": false,
181 - "src": "Install-3"
182 - },
183 - {
184 - "dst": "Wait-for-Start-1",
185 - "isSoft": true,
186 - "src": "Check-Components-1"
187 - },
188 - {
189 - "dst": "Wait-for-Start-1",
190 - "isSoft": true,
191 - "src": "Check-Nodes-1"
192 - },
193 - {
194 - "dst": "Push-Topos",
195 - "isSoft": false,
196 - "src": "Start-Mininet"
197 - },
198 - {
199 - "dst": "Reactive-Forwarding.Check-Summary-For-Hosts",
200 - "isSoft": true,
201 - "src": "Reactive-Forwarding.Config-Topo"
202 - },
203 - {
204 - "dst": "Reactive-Forwarding.Install-Apps",
205 - "isSoft": false,
206 - "src": "Reactive-Forwarding.Check-Apps"
207 - },
208 - {
209 - "dst": "Push-Bits",
210 - "isSoft": false,
211 - "src": "Install-2"
212 - },
213 - {
214 - "dst": "Install-1",
215 - "isSoft": false,
216 - "src": "Secure-SSH"
217 - },
218 - {
219 - "dst": "Create-Intent",
220 - "isSoft": false,
221 - "src": "Host-Intent.Net-Link-Down-Up"
222 - },
223 - {
224 - "dst": "Verify-CLI",
225 - "isSoft": true,
226 - "src": "Reinstall-App-With-UI"
227 - },
228 - {
229 - "dst": "Wait-for-Start-3",
230 - "isSoft": true,
231 - "src": "Check-Apps-3"
232 - },
233 - {
234 - "dst": "Net-Smoke",
235 - "isSoft": true,
236 - "src": "Wrapup"
237 - },
238 - {
239 - "dst": "Initial-Summary-Check",
240 - "isSoft": false,
241 - "src": "Start-Mininet"
242 - },
243 - {
244 - "dst": "Install-3",
245 - "isSoft": false,
246 - "src": "Wait-for-Start-3"
247 - },
248 - {
249 - "dst": "Reactive-Forwarding.Link-1-Up",
250 - "isSoft": false,
251 - "src": "Reactive-Forwarding.Ping-4"
252 - },
253 - {
254 - "dst": "Check-Summary",
255 - "isSoft": true,
256 - "src": "Balance-Masters"
257 - },
258 - {
259 - "dst": "Reactive-Forwarding.Net-Link-Down-Up",
260 - "isSoft": true,
261 - "src": "Host-Intent-Connectivity"
262 - },
263 - {
264 - "dst": "Secure-SSH",
265 - "isSoft": true,
266 - "src": "Wait-for-Start-2"
267 - },
268 - {
269 - "dst": "Build-App-With-CLI",
270 - "isSoft": false,
271 - "src": "Reinstall-App-With-CLI"
272 - },
273 - {
274 - "dst": "Uninstall-1",
275 - "isSoft": false,
276 - "src": "Kill-1"
277 - },
278 - {
279 - "dst": "Find-Host-1",
280 - "isSoft": false,
281 - "src": "Find-Host-2"
282 - },
283 - {
284 - "dst": "Create-App-CLI-Overlay",
285 - "isSoft": false,
286 - "src": "Build-App-With-CLI"
287 - },
288 - {
289 - "dst": "Net-Setup",
290 - "isSoft": false,
291 - "src": "Reactive-Forwarding.Net-Link-Down-Up"
292 - },
293 - {
294 - "dst": "Kill-2",
295 - "isSoft": false,
296 - "src": "Install-2"
297 - },
298 - {
299 - "dst": "Wait-for-Start-1",
300 - "isSoft": true,
301 - "src": "Check-Logs-1"
302 - },
303 - {
304 - "dst": "Wait-for-Start-2",
305 - "isSoft": true,
306 - "src": "Check-Nodes-2"
307 - },
308 - {
309 - "dst": "Reactive-Forwarding.Ping-All-And-Verify",
310 - "isSoft": true,
311 - "src": "Reactive-Forwarding.Check-Summary-For-Hosts"
312 - },
313 - {
314 - "dst": "Clean-Up",
315 - "isSoft": false,
316 - "src": "Create-App"
317 - },
318 - {
319 - "dst": "Host-Intent.Link-1-Up",
320 - "isSoft": false,
321 - "src": "Host-Intent.Ping-4"
322 - },
323 - {
324 - "dst": "Build-App-With-UI",
325 - "isSoft": false,
326 - "src": "Reinstall-App-With-UI"
327 - },
328 - {
329 - "dst": "Install-2",
330 - "isSoft": false,
331 - "src": "Secure-SSH"
332 - },
333 - {
334 - "dst": "Wait-For-Mininet",
335 - "isSoft": false,
336 - "src": "Check-Summary"
337 - },
338 - {
339 - "dst": "Host-Intent.Net-Link-Down-Up",
340 - "isSoft": false,
341 - "src": "Remove-Intent"
342 - },
343 - {
344 - "dst": "Net-Setup",
345 - "isSoft": false,
346 - "src": "Host-Intent-Connectivity"
347 - },
348 - {
349 - "dst": "Net-Setup",
350 - "isSoft": false,
351 - "src": "Reactive-Forwarding.Net-Pingall"
352 - },
353 - {
354 - "dst": "Reactive-Forwarding.Link-2-Down",
355 - "isSoft": false,
356 - "src": "Reactive-Forwarding.Ping-3"
357 - },
358 - {
359 - "dst": "Find-Host-2",
360 - "isSoft": false,
361 - "src": "Create-Intent"
362 - },
363 - {
364 - "dst": "Wait-for-Start-2",
365 - "isSoft": true,
366 - "src": "Check-Apps-2"
367 - },
368 - {
369 - "dst": "Final-Check-Logs-1",
370 - "isSoft": true,
371 - "src": "Fetch-Logs-1"
372 - },
373 - {
374 - "dst": "Install-2",
375 - "isSoft": false,
376 - "src": "Wait-for-Start-2"
377 - },
378 - {
379 - "dst": "Reactive-Forwarding.Ping-1",
380 - "isSoft": false,
381 - "src": "Reactive-Forwarding.Link-1-Down"
382 - },
383 - {
384 - "dst": "Create-App",
385 - "isSoft": false,
386 - "src": "Build-App"
387 - },
388 - {
389 - "dst": "Check-Summary",
390 - "isSoft": true,
391 - "src": "Check-Flows"
392 - },
393 - {
394 - "dst": "Build-App",
395 - "isSoft": false,
396 - "src": "Install-App"
397 - },
398 - {
399 - "dst": "Reinstall-App-With-UI",
400 - "isSoft": false,
401 - "src": "Verify-UI"
402 - },
403 - {
404 - "dst": "Uninstall-2",
405 - "isSoft": false,
406 - "src": "Kill-2"
407 - },
408 - {
409 - "dst": "Setup",
410 - "isSoft": false,
411 - "src": "Archetypes"
412 - },
413 - {
414 - "dst": "Setup",
415 - "isSoft": false,
416 - "src": "Net-Smoke"
417 - },
418 - {
419 - "dst": "Kill-1",
420 - "isSoft": false,
421 - "src": "Install-1"
422 - },
423 - {
424 - "dst": "Reactive-Forwarding.Link-1-Down",
425 - "isSoft": false,
426 - "src": "Reactive-Forwarding.Ping-2"
427 - },
428 - {
429 - "dst": "Wait-for-Start-2",
430 - "isSoft": true,
431 - "src": "Check-Logs-2"
432 - },
433 - {
434 - "dst": "Wait-for-Start-3",
435 - "isSoft": true,
436 - "src": "Check-Components-3"
437 - },
438 - {
439 - "dst": "Wait-for-Start-3",
440 - "isSoft": true,
441 - "src": "Check-Nodes-3"
442 - },
443 - {
444 - "dst": "Stop-Mininet-If-Needed",
445 - "isSoft": false,
446 - "src": "Start-Mininet"
447 - },
448 - {
449 - "dst": "Reactive-Forwarding.Link-2-Up",
450 - "isSoft": false,
451 - "src": "Reactive-Forwarding.Ping-5"
452 - },
453 - {
454 - "dst": "Reactive-Forwarding.Check-Apps",
455 - "isSoft": false,
456 - "src": "Reactive-Forwarding.Ping-All-And-Verify"
457 - },
458 - {
459 - "dst": "Install-3",
460 - "isSoft": false,
461 - "src": "Secure-SSH"
462 - },
463 - {
464 - "dst": "Push-Bits",
465 - "isSoft": false,
466 - "src": "Install-3"
467 - },
468 - {
469 - "dst": "Reinstall-App-With-CLI",
470 - "isSoft": false,
471 - "src": "Create-App-UI-Overlay"
472 - },
473 - {
474 - "dst": "Push-Bits",
475 - "isSoft": false,
476 - "src": "Install-1"
477 - },
478 - {
479 - "dst": "Wait-for-Start-1",
480 - "isSoft": true,
481 - "src": "Check-Apps-1"
482 - }
483 - ],
484 - "steps": [
485 - {
486 - "group": "Net-Setup",
487 - "isGroup": false,
488 - "name": "Check-Summary",
489 - "status": "waiting"
490 - },
491 - {
492 - "group": "Net-Setup",
493 - "isGroup": false,
494 - "name": "Check-Flows",
495 - "status": "waiting"
496 - },
497 - {
498 - "group": "Wrapup",
499 - "isGroup": false,
500 - "name": "Final-Check-Logs-1",
501 - "status": "waiting"
502 - },
503 - {
504 - "group": "Wrapup",
505 - "isGroup": false,
506 - "name": "Final-Check-Logs-2",
507 - "status": "waiting"
508 - },
509 - {
510 - "group": "Archetypes",
511 - "isGroup": false,
512 - "name": "Clean-Up",
513 - "status": "waiting"
514 - },
515 - {
516 - "group": "Archetypes",
517 - "isGroup": false,
518 - "name": "Build-App-With-UI",
519 - "status": "waiting"
520 - },
521 - {
522 - "group": "Archetypes",
523 - "isGroup": false,
524 - "name": "Uninstall-App",
525 - "status": "waiting"
526 - },
527 - {
528 - "group": "Wrapup",
529 - "isGroup": false,
530 - "name": "Final-Check-Logs-3",
531 - "status": "waiting"
532 - },
533 - {
534 - "group": "Host-Intent.Net-Link-Down-Up",
535 - "isGroup": false,
536 - "name": "Host-Intent.Link-2-Down",
537 - "status": "waiting"
538 - },
539 - {
540 - "group": "Wrapup",
541 - "isGroup": false,
542 - "name": "Fetch-Logs-3",
543 - "status": "waiting"
544 - },
545 - {
546 - "group": "Wrapup",
547 - "isGroup": false,
548 - "name": "Fetch-Logs-2",
549 - "status": "waiting"
550 - },
551 - {
552 - "group": "Setup",
553 - "isGroup": false,
554 - "name": "Check-Components-3",
555 - "status": "waiting"
556 - },
557 - {
558 - "group": "Wrapup",
559 - "isGroup": false,
560 - "name": "Fetch-Logs-1",
561 - "status": "waiting"
562 - },
563 - {
564 - "group": "Net-Setup",
565 - "isGroup": false,
566 - "name": "Push-Topos",
567 - "status": "waiting"
568 - },
569 - {
570 - "group": "Reactive-Forwarding.Net-Pingall",
571 - "isGroup": false,
572 - "name": "Reactive-Forwarding.Check-Apps",
573 - "status": "waiting"
574 - },
575 - {
576 - "group": "Setup",
577 - "isGroup": false,
578 - "name": "Wait-for-Start-3",
579 - "status": "waiting"
580 - },
581 - {
582 - "group": "Setup",
583 - "isGroup": false,
584 - "name": "Wait-for-Start-2",
585 - "status": "waiting"
586 - },
587 - {
588 - "group": "Setup",
589 - "isGroup": false,
590 - "name": "Wait-for-Start-1",
591 - "status": "waiting"
592 - },
593 - {
594 - "group": "Net-Smoke",
595 - "isGroup": true,
596 - "name": "Host-Intent-Connectivity",
597 - "status": "waiting"
598 - },
599 - {
600 - "group": "Host-Intent-Connectivity",
601 - "isGroup": false,
602 - "name": "Create-Intent",
603 - "status": "waiting"
604 - },
605 - {
606 - "isGroup": true,
607 - "name": "Prerequisites",
608 - "status": "in_progress"
609 - },
610 - {
611 - "group": "Setup",
612 - "isGroup": false,
613 - "name": "Push-Bits",
614 - "status": "waiting"
615 - },
616 - {
617 - "group": "Setup",
618 - "isGroup": false,
619 - "name": "Check-Logs-2",
620 - "status": "waiting"
621 - },
622 - {
623 - "group": "Setup",
624 - "isGroup": false,
625 - "name": "Check-Logs-3",
626 - "status": "waiting"
627 - },
628 - {
629 - "group": "Setup",
630 - "isGroup": false,
631 - "name": "Kill-1",
632 - "status": "waiting"
633 - },
634 - {
635 - "group": "Setup",
636 - "isGroup": false,
637 - "name": "Kill-3",
638 - "status": "waiting"
639 - },
640 - {
641 - "group": "Setup",
642 - "isGroup": false,
643 - "name": "Kill-2",
644 - "status": "waiting"
645 - },
646 - {
647 - "group": "Host-Intent-Connectivity",
648 - "isGroup": true,
649 - "name": "Host-Intent.Net-Link-Down-Up",
650 - "status": "waiting"
651 - },
652 - {
653 - "group": "Host-Intent.Net-Link-Down-Up",
654 - "isGroup": false,
655 - "name": "Host-Intent.Ping-1",
656 - "status": "waiting"
657 - },
658 - {
659 - "group": "Archetypes",
660 - "isGroup": false,
661 - "name": "Verify-UI",
662 - "status": "waiting"
663 - },
664 - {
665 - "group": "Host-Intent.Net-Link-Down-Up",
666 - "isGroup": false,
667 - "name": "Host-Intent.Ping-2",
668 - "status": "waiting"
669 - },
670 - {
671 - "group": "Host-Intent.Net-Link-Down-Up",
672 - "isGroup": false,
673 - "name": "Host-Intent.Ping-3",
674 - "status": "waiting"
675 - },
676 - {
677 - "group": "Setup",
678 - "isGroup": false,
679 - "name": "Uninstall-1",
680 - "status": "waiting"
681 - },
682 - {
683 - "group": "Setup",
684 - "isGroup": false,
685 - "name": "Check-Logs-1",
686 - "status": "waiting"
687 - },
688 - {
689 - "group": "Host-Intent.Net-Link-Down-Up",
690 - "isGroup": false,
691 - "name": "Host-Intent.Ping-4",
692 - "status": "waiting"
693 - },
694 - {
695 - "group": "Setup",
696 - "isGroup": false,
697 - "name": "Uninstall-3",
698 - "status": "waiting"
699 - },
700 - {
701 - "group": "Host-Intent.Net-Link-Down-Up",
702 - "isGroup": false,
703 - "name": "Host-Intent.Ping-5",
704 - "status": "waiting"
705 - },
706 - {
707 - "group": "Setup",
708 - "isGroup": false,
709 - "name": "Uninstall-2",
710 - "status": "waiting"
711 - },
712 - {
713 - "group": "Reactive-Forwarding.Net-Pingall",
714 - "isGroup": false,
715 - "name": "Reactive-Forwarding.Install-Apps",
716 - "status": "waiting"
717 - },
718 - {
719 - "group": "Net-Smoke",
720 - "isGroup": true,
721 - "name": "Reactive-Forwarding.Net-Link-Down-Up",
722 - "status": "waiting"
723 - },
724 - {
725 - "group": "Prerequisites",
726 - "isGroup": false,
727 - "name": "Check-ONOS-Bits",
728 - "status": "in_progress"
729 - },
730 - {
731 - "isGroup": true,
732 - "name": "Wrapup",
733 - "status": "waiting"
734 - },
735 - {
736 - "group": "Setup",
737 - "isGroup": false,
738 - "name": "Install-2",
739 - "status": "waiting"
740 - },
741 - {
742 - "group": "Host-Intent-Connectivity",
743 - "isGroup": false,
744 - "name": "Find-Host-1",
745 - "status": "waiting"
746 - },
747 - {
748 - "group": "Setup",
749 - "isGroup": false,
750 - "name": "Install-1",
751 - "status": "waiting"
752 - },
753 - {
754 - "group": "Net-Setup",
755 - "isGroup": false,
756 - "name": "Wipe-Out-Data-Before",
757 - "status": "waiting"
758 - },
759 - {
760 - "group": "Net-Setup",
761 - "isGroup": false,
762 - "name": "Pause-For-Masters",
763 - "status": "waiting"
764 - },
765 - {
766 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
767 - "isGroup": false,
768 - "name": "Reactive-Forwarding.Link-2-Up",
769 - "status": "waiting"
770 - },
771 - {
772 - "group": "Net-Smoke",
773 - "isGroup": true,
774 - "name": "Reactive-Forwarding.Net-Pingall",
775 - "status": "waiting"
776 - },
777 - {
778 - "group": "Setup",
779 - "isGroup": false,
780 - "name": "Check-Components-2",
781 - "status": "waiting"
782 - },
783 - {
784 - "group": "Setup",
785 - "isGroup": false,
786 - "name": "Check-Components-1",
787 - "status": "waiting"
788 - },
789 - {
790 - "group": "Archetypes",
791 - "isGroup": false,
792 - "name": "Reinstall-App-With-UI",
793 - "status": "waiting"
794 - },
795 - {
796 - "group": "Archetypes",
797 - "isGroup": false,
798 - "name": "Reinstall-App-With-CLI",
799 - "status": "waiting"
800 - },
801 - {
802 - "group": "Archetypes",
803 - "isGroup": false,
804 - "name": "Build-App-With-CLI",
805 - "status": "waiting"
806 - },
807 - {
808 - "group": "Host-Intent-Connectivity",
809 - "isGroup": false,
810 - "name": "Uninstall-Reactive-Forwarding",
811 - "status": "waiting"
812 - },
813 - {
814 - "group": "Host-Intent.Net-Link-Down-Up",
815 - "isGroup": false,
816 - "name": "Host-Intent.Link-2-Up",
817 - "status": "waiting"
818 - },
819 - {
820 - "group": "Net-Teardown",
821 - "isGroup": false,
822 - "name": "Stop-Mininet",
823 - "status": "waiting"
824 - },
825 - {
826 - "group": "Reactive-Forwarding.Net-Pingall",
827 - "isGroup": false,
828 - "name": "Reactive-Forwarding.Config-Topo",
829 - "status": "waiting"
830 - },
831 - {
832 - "group": "Archetypes",
833 - "isGroup": false,
834 - "name": "Create-App-CLI-Overlay",
835 - "status": "waiting"
836 - },
837 - {
838 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
839 - "isGroup": false,
840 - "name": "Reactive-Forwarding.Link-1-Down",
841 - "status": "waiting"
842 - },
843 - {
844 - "isGroup": true,
845 - "name": "Net-Smoke",
846 - "status": "waiting"
847 - },
848 - {
849 - "group": "Prerequisites",
850 - "isGroup": false,
851 - "name": "Check-Passwordless-Login-2",
852 - "status": "in_progress"
853 - },
854 - {
855 - "group": "Prerequisites",
856 - "isGroup": false,
857 - "name": "Check-Passwordless-Login-1",
858 - "status": "in_progress"
859 - },
860 - {
861 - "group": "Prerequisites",
862 - "isGroup": false,
863 - "name": "Check-Passwordless-Login-3",
864 - "status": "in_progress"
865 - },
866 - {
867 - "group": "Setup",
868 - "isGroup": false,
869 - "name": "Secure-SSH",
870 - "status": "waiting"
871 - },
872 - {
873 - "group": "Net-Smoke",
874 - "isGroup": true,
875 - "name": "Net-Setup",
876 - "status": "waiting"
877 - },
878 - {
879 - "group": "Setup",
880 - "isGroup": false,
881 - "name": "Check-Nodes-1",
882 - "status": "waiting"
883 - },
884 - {
885 - "group": "Setup",
886 - "isGroup": false,
887 - "name": "Install-3",
888 - "status": "waiting"
889 - },
890 - {
891 - "group": "Host-Intent-Connectivity",
892 - "isGroup": false,
893 - "name": "Find-Host-2",
894 - "status": "waiting"
895 - },
896 - {
897 - "group": "Net-Setup",
898 - "isGroup": false,
899 - "name": "Initial-Summary-Check",
900 - "status": "waiting"
901 - },
902 - {
903 - "group": "Archetypes",
904 - "isGroup": false,
905 - "name": "Create-App",
906 - "status": "waiting"
907 - },
908 - {
909 - "group": "Setup",
910 - "isGroup": false,
911 - "name": "Check-Nodes-3",
912 - "status": "waiting"
913 - },
914 - {
915 - "group": "Setup",
916 - "isGroup": false,
917 - "name": "Check-Nodes-2",
918 - "status": "waiting"
919 - },
920 - {
921 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
922 - "isGroup": false,
923 - "name": "Reactive-Forwarding.Link-2-Down",
924 - "status": "waiting"
925 - },
926 - {
927 - "isGroup": true,
928 - "name": "Setup",
929 - "status": "waiting"
930 - },
931 - {
932 - "group": "Archetypes",
933 - "isGroup": false,
934 - "name": "Verify-App",
935 - "status": "waiting"
936 - },
937 - {
938 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
939 - "isGroup": false,
940 - "name": "Reactive-Forwarding.Ping-1",
941 - "status": "waiting"
942 - },
943 - {
944 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
945 - "isGroup": false,
946 - "name": "Reactive-Forwarding.Ping-2",
947 - "status": "waiting"
948 - },
949 - {
950 - "group": "Net-Setup",
951 - "isGroup": false,
952 - "name": "Start-Mininet",
953 - "status": "waiting"
954 - },
955 - {
956 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
957 - "isGroup": false,
958 - "name": "Reactive-Forwarding.Ping-3",
959 - "status": "waiting"
960 - },
961 - {
962 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
963 - "isGroup": false,
964 - "name": "Reactive-Forwarding.Ping-4",
965 - "status": "waiting"
966 - },
967 - {
968 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
969 - "isGroup": false,
970 - "name": "Reactive-Forwarding.Ping-5",
971 - "status": "waiting"
972 - },
973 - {
974 - "group": "Archetypes",
975 - "isGroup": false,
976 - "name": "Verify-CLI",
977 - "status": "waiting"
978 - },
979 - {
980 - "group": "Reactive-Forwarding.Net-Pingall",
981 - "isGroup": false,
982 - "name": "Reactive-Forwarding.Check-Summary-For-Hosts",
983 - "status": "waiting"
984 - },
985 - {
986 - "group": "Net-Smoke",
987 - "isGroup": true,
988 - "name": "Net-Teardown",
989 - "status": "waiting"
990 - },
991 - {
992 - "group": "Host-Intent.Net-Link-Down-Up",
993 - "isGroup": false,
994 - "name": "Host-Intent.Link-1-Up",
995 - "status": "waiting"
996 - },
997 - {
998 - "group": "Host-Intent-Connectivity",
999 - "isGroup": false,
1000 - "name": "Remove-Intent",
1001 - "status": "waiting"
1002 - },
1003 - {
1004 - "group": "Archetypes",
1005 - "isGroup": false,
1006 - "name": "Install-App",
1007 - "status": "waiting"
1008 - },
1009 - {
1010 - "group": "Archetypes",
1011 - "isGroup": false,
1012 - "name": "Create-App-UI-Overlay",
1013 - "status": "waiting"
1014 - },
1015 - {
1016 - "group": "Reactive-Forwarding.Net-Link-Down-Up",
1017 - "isGroup": false,
1018 - "name": "Reactive-Forwarding.Link-1-Up",
1019 - "status": "waiting"
1020 - },
1021 - {
1022 - "group": "Net-Setup",
1023 - "isGroup": false,
1024 - "name": "Wait-For-Mininet",
1025 - "status": "waiting"
1026 - },
1027 - {
1028 - "group": "Setup",
1029 - "isGroup": false,
1030 - "name": "Check-Apps-3",
1031 - "status": "waiting"
1032 - },
1033 - {
1034 - "group": "Setup",
1035 - "isGroup": false,
1036 - "name": "Check-Apps-2",
1037 - "status": "waiting"
1038 - },
1039 - {
1040 - "group": "Setup",
1041 - "isGroup": false,
1042 - "name": "Check-Apps-1",
1043 - "status": "waiting"
1044 - },
1045 - {
1046 - "group": "Net-Setup",
1047 - "isGroup": false,
1048 - "name": "Stop-Mininet-If-Needed",
1049 - "status": "waiting"
1050 - },
1051 - {
1052 - "group": "Prerequisites",
1053 - "isGroup": false,
1054 - "name": "Check-Environment",
1055 - "status": "in_progress"
1056 - },
1057 - {
1058 - "isGroup": true,
1059 - "name": "Archetypes",
1060 - "status": "waiting"
1061 - },
1062 - {
1063 - "group": "Host-Intent.Net-Link-Down-Up",
1064 - "isGroup": false,
1065 - "name": "Host-Intent.Link-1-Down",
1066 - "status": "waiting"
1067 - },
1068 - {
1069 - "group": "Net-Setup",
1070 - "isGroup": false,
1071 - "name": "Balance-Masters",
1072 - "status": "waiting"
1073 - },
1074 - {
1075 - "group": "Reactive-Forwarding.Net-Pingall",
1076 - "isGroup": false,
1077 - "name": "Reactive-Forwarding.Ping-All-And-Verify",
1078 - "status": "waiting"
1079 - },
1080 - {
1081 - "group": "Archetypes",
1082 - "isGroup": false,
1083 - "name": "Build-App",
1084 - "status": "waiting"
1085 - }
1086 - ]
1087 -}
1 -<!DOCTYPE html>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<html>
18 -<head lang="en">
19 - <meta charset="utf-8">
20 - <title>Scenario Test Coordinator</title>
21 -
22 - <link rel="stylesheet" href="stc.css">
23 -
24 - <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
25 - <script src="stc.js"></script>
26 -</head>
27 -<body>
28 -</body>
29 -</html>
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -.body {
18 - font-family: Helvetica, Arial, sans-serif;
19 -}
20 -
21 -.node {
22 - stroke: #fff;
23 - stroke-width: 1.5px;
24 -}
25 -
26 -.link {
27 - stroke: #999;
28 - stroke-opacity: .6;
29 -}
30 -
31 -text {
32 - font-family: 'DejaVu Sans', Arial, Helvetica, sans-serif;
33 - stroke: #000;
34 - stroke-width: 0.2;
35 - font-weight: normal;
36 - font-size: 0.6em;
37 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -(function () {
17 -
18 - var ws, flow,
19 - nodes = [],
20 - links = [],
21 - nodeIndexes = {};
22 -
23 - var width = 2400,
24 - height = 2400;
25 -
26 - var color = d3.scale.category20();
27 -
28 - var force = d3.layout.force()
29 - .charge(-820)
30 - .linkDistance(50)
31 - .size([width, height]);
32 -
33 - // Process flow graph layout
34 - function createNode(n) {
35 - nodeIndexes[n.name] = nodes.push(n) - 1;
36 - }
37 -
38 - function createLink(e) {
39 - e.source = nodeIndexes[e.src];
40 - e.target = nodeIndexes[e.dst];
41 - links.push(e);
42 - }
43 -
44 - // Returns the newly computed bounding box of the rectangle
45 - function adjustRectToFitText(n) {
46 - var text = n.select('text'),
47 - box = text.node().getBBox();
48 -
49 - text.attr('text-anchor', 'left')
50 - .attr('y', 2)
51 - .attr('x', 4);
52 -
53 - // add padding
54 - box.x -= 4;
55 - box.width += 8;
56 - box.y -= 2;
57 - box.height += 4;
58 -
59 - n.select("rect").attr(box);
60 - }
61 -
62 - function processFlow() {
63 - var svg = d3.select("body").append("svg")
64 - .attr("width", width)
65 - .attr("height", height);
66 -
67 - flow.steps.forEach(createNode);
68 - flow.requirements.forEach(createLink);
69 -
70 - force
71 - .nodes(nodes)
72 - .links(links)
73 - .start();
74 -
75 - var link = svg.selectAll(".link")
76 - .data(links)
77 - .enter().append("line")
78 - .attr("class", "link")
79 - .style("stroke-width", function(d) { return d.isSoft ? 1 : 2; });
80 -
81 - var node = svg.selectAll(".node")
82 - .data(nodes)
83 - .enter().append("g")
84 - .attr("class", "node")
85 - .call(force.drag);
86 -
87 - node.append("rect")
88 - .attr({ rx: 5, ry:5, width:180, height:18 })
89 - .style("fill", function(d) { return color(d.group); });
90 -
91 - node.append("text").text( function(d) { return d.name; })
92 - .attr({ dy:"1.1em", width:100, height:16, x:4, y:2 });
93 -
94 - node.append("title")
95 - .text(function(d) { return d.name; });
96 -
97 - force.on("tick", function() {
98 - link.attr("x1", function(d) { return d.source.x; })
99 - .attr("y1", function(d) { return d.source.y; })
100 - .attr("x2", function(d) { return d.target.x; })
101 - .attr("y2", function(d) { return d.target.y; });
102 -
103 - node.attr("transform", function(d) { return "translate(" + (d.x - 180/2) + "," + (d.y - 18/2) + ")"; });
104 - });
105 - }
106 -
107 -
108 - // Web socket callbacks
109 -
110 - function handleOpen() {
111 - console.log('WebSocket open');
112 - }
113 -
114 - // Handles the specified (incoming) message using handler bindings.
115 - function handleMessage(msg) {
116 - console.log('rx: ', msg);
117 - evt = JSON.parse(msg.data);
118 - if (evt.event === 'progress') {
119 -
120 - } else if (evt.event === 'log') {
121 -
122 - } else if (evt.event === 'flow') {
123 - flow = evt.payload;
124 - processFlow();
125 - }
126 - }
127 -
128 - function handleClose() {
129 - console.log('WebSocket closed');
130 - }
131 -
132 - if (false) {
133 - d3.json("data.json", function (error, data) {
134 - flow = data;
135 - processFlow();
136 - });
137 - return;
138 - }
139 -
140 - // Open the web-socket
141 - ws = new WebSocket(document.location.href.replace('http:', 'ws:'));
142 - if (ws) {
143 - ws.onopen = handleOpen;
144 - ws.onmessage = handleMessage;
145 - ws.onclose = handleClose;
146 - }
147 -
148 -})();
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.junit.AfterClass;
19 -import org.junit.BeforeClass;
20 -import org.junit.Test;
21 -import org.onlab.util.Tools;
22 -
23 -import com.google.common.io.Files;
24 -
25 -import java.io.File;
26 -import java.io.FileInputStream;
27 -import java.io.FileNotFoundException;
28 -import java.io.IOException;
29 -
30 -import static com.google.common.io.ByteStreams.toByteArray;
31 -import static com.google.common.io.Files.write;
32 -import static org.junit.Assert.assertEquals;
33 -import static org.junit.Assert.assertSame;
34 -import static org.onlab.stc.Scenario.loadScenario;
35 -
36 -/**
37 - * Test of the test scenario compiler.
38 - */
39 -public class CompilerTest {
40 -
41 -
42 - private static File testDir;
43 -
44 - @BeforeClass
45 - public static void setUpClass() throws IOException {
46 - testDir = Files.createTempDir();
47 - stageTestResource("scenario.xml");
48 - stageTestResource("simple-scenario.xml");
49 - stageTestResource("one-scenario.xml");
50 - stageTestResource("two-scenario.xml");
51 -
52 - System.setProperty("prop.foo", "Foobar");
53 - System.setProperty("prop.bar", "Barfoo");
54 - System.setProperty("TOC1", "1.2.3.1");
55 - System.setProperty("TOC2", "1.2.3.2");
56 - System.setProperty("TOC3", "1.2.3.3");
57 - System.setProperty("test.dir", testDir.getAbsolutePath());
58 - }
59 -
60 - @AfterClass
61 - public static void tearDownClass() throws IOException {
62 - Tools.removeDirectory(testDir.getPath());
63 - }
64 -
65 - static FileInputStream getStream(String name) throws FileNotFoundException {
66 - return new FileInputStream(new File(testDir, name));
67 - }
68 -
69 - static void stageTestResource(String name) throws IOException {
70 - byte[] bytes = toByteArray(CompilerTest.class.getResourceAsStream(name));
71 - write(bytes, new File(testDir, name));
72 - }
73 -
74 - @Test
75 - public void basics() throws Exception {
76 - Scenario scenario = loadScenario(getStream("scenario.xml"));
77 - Compiler compiler = new Compiler(scenario);
78 - compiler.compile();
79 - ProcessFlow flow = compiler.processFlow();
80 -
81 - assertSame("incorrect scenario", scenario, compiler.scenario());
82 - assertEquals("incorrect step count", 33, flow.getVertexes().size());
83 - assertEquals("incorrect dependency count", 26, flow.getEdges().size());
84 - assertEquals("incorrect logDir",
85 - new File(testDir.getAbsolutePath(), "foo"), compiler.logDir());
86 -
87 - Step step = compiler.getStep("there");
88 - assertEquals("incorrect edge count", 2, flow.getEdgesFrom(step).size());
89 - assertEquals("incorrect edge count", 0, flow.getEdgesTo(step).size());
90 -
91 - Step group = compiler.getStep("three");
92 - assertEquals("incorrect edge count", 2, flow.getEdgesFrom(group).size());
93 - assertEquals("incorrect edge count", 0, flow.getEdgesTo(group).size());
94 - }
95 -
96 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.junit.AfterClass;
19 -import org.junit.BeforeClass;
20 -import org.junit.Test;
21 -import org.onlab.util.Tools;
22 -
23 -import java.io.IOException;
24 -
25 -import static org.onlab.stc.CompilerTest.getStream;
26 -import static org.onlab.stc.Coordinator.print;
27 -import static org.onlab.stc.Scenario.loadScenario;
28 -
29 -/**
30 - * Test of the test coordinator.
31 - */
32 -public class CoordinatorTest {
33 -
34 - private Coordinator coordinator;
35 - private StepProcessListener listener = new Listener();
36 -
37 - @BeforeClass
38 - public static void setUpClass() throws IOException {
39 - CompilerTest.setUpClass();
40 -
41 - StepProcessor.launcher = "true ";
42 - }
43 -
44 - @AfterClass
45 - public static void tearDownClass() throws IOException {
46 - CompilerTest.tearDownClass();
47 - }
48 -
49 - @Test
50 - public void simple() throws IOException, InterruptedException {
51 - executeTest("simple-scenario.xml");
52 - }
53 -
54 - @Test
55 - public void complex() throws IOException, InterruptedException {
56 - executeTest("scenario.xml");
57 - }
58 -
59 - private void executeTest(String name) throws IOException, InterruptedException {
60 - Scenario scenario = loadScenario(getStream(name));
61 - Compiler compiler = new Compiler(scenario);
62 - compiler.compile();
63 - Tools.removeDirectory(compiler.logDir());
64 - coordinator = new Coordinator(scenario, compiler.processFlow(), compiler.logDir());
65 - coordinator.addListener(listener);
66 - coordinator.reset();
67 - coordinator.start();
68 - coordinator.waitFor();
69 - coordinator.removeListener(listener);
70 - }
71 -
72 - private class Listener implements StepProcessListener {
73 - @Override
74 - public void onStart(Step step, String command) {
75 - print("> %s: started; %s", step.name(), command);
76 - }
77 -
78 - @Override
79 - public void onCompletion(Step step, Coordinator.Status status) {
80 - print("< %s: %s", step.name(), status == Coordinator.Status.SUCCEEDED ? "completed" : "failed");
81 - }
82 -
83 - @Override
84 - public void onOutput(Step step, String line) {
85 - print(" %s: %s", step.name(), line);
86 - }
87 - }
88 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.testing.EqualsTester;
19 -import org.apache.commons.configuration.ConfigurationException;
20 -import org.junit.Before;
21 -import org.junit.Test;
22 -
23 -import static org.junit.Assert.*;
24 -
25 -/**
26 - * Test of the test step dependency.
27 - */
28 -public class DependencyTest extends StepTest {
29 -
30 - protected Step step1, step2;
31 -
32 - @Override
33 - @Before
34 - public void setUp() throws ConfigurationException {
35 - super.setUp();
36 - step1 = new Step("step1", CMD, null, null, null, 0);
37 - step2 = new Step("step2", CMD, null, null, null, 0);
38 - }
39 -
40 - @Test
41 - public void hard() {
42 - Dependency hard = new Dependency(step1, step2, false);
43 - assertSame("incorrect src", step1, hard.src());
44 - assertSame("incorrect dst", step2, hard.dst());
45 - assertFalse("incorrect isSoft", hard.isSoft());
46 - }
47 -
48 - @Test
49 - public void soft() {
50 - Dependency soft = new Dependency(step2, step1, true);
51 - assertSame("incorrect src", step2, soft.src());
52 - assertSame("incorrect dst", step1, soft.dst());
53 - assertTrue("incorrect isSoft", soft.isSoft());
54 - }
55 -
56 - @Override
57 - @Test
58 - public void equality() {
59 - Dependency d1 = new Dependency(step1, step2, false);
60 - Dependency d2 = new Dependency(step1, step2, false);
61 - Dependency d3 = new Dependency(step1, step2, true);
62 - Dependency d4 = new Dependency(step2, step1, true);
63 - new EqualsTester()
64 - .addEqualityGroup(d1, d2)
65 - .addEqualityGroup(d3)
66 - .addEqualityGroup(d4)
67 - .testEquals();
68 - }
69 -
70 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.testing.EqualsTester;
19 -import org.junit.Test;
20 -
21 -import static org.junit.Assert.assertEquals;
22 -import static org.junit.Assert.assertSame;
23 -
24 -/**
25 - * Test of the test scenario entity.
26 - */
27 -public class GroupTest extends StepTest {
28 -
29 - @Test
30 - public void basics() {
31 - Group group = new Group(NAME, CMD, ENV, CWD, parent, 1);
32 - assertEquals("incorrect name", NAME, group.name());
33 - assertEquals("incorrect command", CMD, group.command());
34 - assertEquals("incorrect env", ENV, group.env());
35 - assertEquals("incorrect cwd", CWD, group.cwd());
36 - assertSame("incorrect group", parent, group.group());
37 - assertEquals("incorrect delay", 1, group.delay());
38 -
39 - Step step = new Step("step", null, null, null, group, 0);
40 - group.addChild(step);
41 - assertSame("incorrect child", step, group.children().iterator().next());
42 - }
43 -
44 - @Test
45 - public void equality() {
46 - Group g1 = new Group(NAME, CMD, null, null, parent, 0);
47 - Group g2 = new Group(NAME, CMD, ENV, CWD, null, 0);
48 - Group g3 = new Group("foo", null, null, null, parent, 0);
49 - new EqualsTester()
50 - .addEqualityGroup(g1, g2)
51 - .addEqualityGroup(g3)
52 - .testEquals();
53 - }
54 -
55 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.junit.AfterClass;
19 -import org.junit.BeforeClass;
20 -import org.junit.Test;
21 -import org.onlab.stc.MonitorLayout.Box;
22 -
23 -import java.io.IOException;
24 -
25 -import static org.junit.Assert.assertEquals;
26 -import static org.onlab.stc.CompilerTest.getStream;
27 -import static org.onlab.stc.CompilerTest.stageTestResource;
28 -import static org.onlab.stc.MonitorLayout.SLOT_WIDTH;
29 -import static org.onlab.stc.Scenario.loadScenario;
30 -
31 -/**
32 - * Tests of the monitor layout functionality.
33 - */
34 -public class MonitorLayoutTest {
35 -
36 - private MonitorLayout layout;
37 -
38 - @BeforeClass
39 - public static void setUpClass() throws IOException {
40 - CompilerTest.setUpClass();
41 - }
42 -
43 - @AfterClass
44 - public static void tearDownClass() throws IOException {
45 - CompilerTest.tearDownClass();
46 - }
47 -
48 - private Compiler getCompiler(String name) throws IOException {
49 - stageTestResource(name);
50 - Scenario scenario = loadScenario(getStream(name));
51 - Compiler compiler = new Compiler(scenario);
52 - compiler.compile();
53 - return compiler;
54 - }
55 -
56 - @Test
57 - public void basic() throws IOException {
58 - layout = new MonitorLayout(getCompiler("layout-basic.xml"));
59 - validate(layout, null, 0, 1, 5, 2);
60 - validate(layout, "a", 1, 1, 1, 1, 1, -SLOT_WIDTH / 2);
61 - validate(layout, "b", 2, 2, 1, 1, 0, 0);
62 - validate(layout, "f", 3, 3, 1);
63 -
64 - validate(layout, "g", 1, 1, 4, 1, 1, SLOT_WIDTH / 2);
65 - validate(layout, "c", 2, 1, 1);
66 - validate(layout, "d", 3, 2, 1);
67 - validate(layout, "e", 4, 3, 1);
68 - }
69 -
70 - @Test
71 - public void basicNest() throws IOException {
72 - layout = new MonitorLayout(getCompiler("layout-basic-nest.xml"));
73 - validate(layout, null, 0, 1, 6, 2);
74 - validate(layout, "a", 1, 1, 1, 1, 1, -SLOT_WIDTH / 2);
75 - validate(layout, "b", 2, 2, 1);
76 - validate(layout, "f", 3, 3, 1);
77 -
78 - validate(layout, "g", 1, 1, 5, 1);
79 - validate(layout, "c", 2, 1, 1);
80 -
81 - validate(layout, "gg", 3, 2, 3, 1);
82 - validate(layout, "d", 4, 1, 1);
83 - validate(layout, "e", 5, 2, 1);
84 - }
85 -
86 - @Test
87 - public void staggeredDependencies() throws IOException {
88 - layout = new MonitorLayout(getCompiler("layout-staggered-dependencies.xml"));
89 - validate(layout, null, 0, 1, 7, 4);
90 - validate(layout, "a", 1, 1, 1, 1, 1, -SLOT_WIDTH - SLOT_WIDTH / 2);
91 - validate(layout, "aa", 1, 1, 1, 1, 1, -SLOT_WIDTH / 2);
92 - validate(layout, "b", 2, 2, 1);
93 - validate(layout, "f", 3, 3, 1);
94 -
95 - validate(layout, "g", 1, 1, 5, 2, 1, +SLOT_WIDTH / 2);
96 - validate(layout, "c", 2, 1, 1);
97 -
98 - validate(layout, "gg", 3, 2, 3, 2);
99 - validate(layout, "d", 4, 1, 1);
100 - validate(layout, "dd", 4, 1, 1);
101 - validate(layout, "e", 5, 2, 1);
102 -
103 - validate(layout, "i", 6, 6, 1);
104 - }
105 -
106 - @Test
107 - public void deepNext() throws IOException {
108 - layout = new MonitorLayout(getCompiler("layout-deep-nest.xml"));
109 - validate(layout, null, 0, 1, 7, 6);
110 - validate(layout, "a", 1, 1, 1);
111 - validate(layout, "aa", 1, 1, 1);
112 - validate(layout, "b", 2, 2, 1);
113 - validate(layout, "f", 3, 3, 1);
114 -
115 - validate(layout, "g", 1, 1, 5, 2);
116 - validate(layout, "c", 2, 1, 1);
117 -
118 - validate(layout, "gg", 3, 2, 3, 2);
119 - validate(layout, "d", 4, 1, 1);
120 - validate(layout, "dd", 4, 1, 1);
121 - validate(layout, "e", 5, 2, 1);
122 -
123 - validate(layout, "i", 6, 6, 1);
124 -
125 - validate(layout, "g1", 1, 1, 6, 2);
126 - validate(layout, "g2", 2, 1, 5, 2);
127 - validate(layout, "g3", 3, 1, 4, 2);
128 - validate(layout, "u", 4, 1, 1);
129 - validate(layout, "v", 4, 1, 1);
130 - validate(layout, "w", 5, 2, 1);
131 - validate(layout, "z", 6, 3, 1);
132 - }
133 -
134 -
135 - private void validate(MonitorLayout layout, String name,
136 - int absoluteTier, int tier, int depth, int breadth) {
137 - Box b = layout.get(name);
138 - assertEquals("incorrect absolute tier", absoluteTier, b.absoluteTier());
139 - assertEquals("incorrect tier", tier, b.tier());
140 - assertEquals("incorrect depth", depth, b.depth());
141 - assertEquals("incorrect breadth", breadth, b.breadth());
142 - }
143 -
144 - private void validate(MonitorLayout layout, String name,
145 - int absoluteTier, int tier, int depth, int breadth,
146 - int top, int center) {
147 - validate(layout, name, absoluteTier, tier, depth, breadth);
148 - Box b = layout.get(name);
149 - assertEquals("incorrect top", top, b.top());
150 - assertEquals("incorrect center", center, b.center());
151 - }
152 -
153 - private void validate(MonitorLayout layout, String name,
154 - int absoluteTier, int tier, int depth) {
155 - validate(layout, name, absoluteTier, tier, depth, 1);
156 - }
157 -
158 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.apache.commons.configuration.ConfigurationException;
19 -import org.junit.Test;
20 -
21 -import static org.junit.Assert.assertEquals;
22 -import static org.onlab.stc.Scenario.loadScenario;
23 -
24 -/**
25 - * Test of the test scenario entity.
26 - */
27 -public class ScenarioTest {
28 -
29 - @Test
30 - public void basics() throws ConfigurationException {
31 - Scenario scenario = loadScenario(getClass().getResourceAsStream("scenario.xml"));
32 - assertEquals("incorrect name", "foo", scenario.name());
33 - assertEquals("incorrect description", "Test Scenario", scenario.description());
34 - assertEquals("incorrect logDir", "Test Scenario", scenario.description());
35 - assertEquals("incorrect definition", "Test Scenario",
36 - scenario.definition().getString("[@description]"));
37 - }
38 -
39 - @Test(expected = IllegalArgumentException.class)
40 - public void badStream() throws ConfigurationException {
41 - loadScenario(getClass().getResourceAsStream("no.xml"));
42 - }
43 -
44 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import org.junit.BeforeClass;
19 -import org.junit.ClassRule;
20 -import org.junit.Test;
21 -import org.junit.rules.TemporaryFolder;
22 -import java.io.File;
23 -import static com.google.common.base.Preconditions.checkState;
24 -import static org.junit.Assert.assertEquals;
25 -import static org.junit.Assert.assertTrue;
26 -import static org.onlab.stc.Coordinator.Status.SUCCEEDED;
27 -
28 -/**
29 - * Test of the step processor.
30 - */
31 -public class StepProcessorTest {
32 -
33 - @ClassRule
34 - public static TemporaryFolder testFolder = new TemporaryFolder();
35 -
36 - private static File dir;
37 - private final Listener delegate = new Listener();
38 -
39 - @BeforeClass
40 - public static void setUpClass() {
41 - dir = testFolder.getRoot();
42 - StepProcessor.launcher = "echo";
43 - checkState(dir.exists() || dir.mkdirs(), "Unable to create directory");
44 - }
45 -
46 - @Test
47 - public void basics() {
48 - Step step = new Step("foo", "ls " + dir.getAbsolutePath(), null, null, null, 0);
49 - StepProcessor processor = new StepProcessor(step, dir, delegate, step.command());
50 - processor.run();
51 - assertTrue("should be started", delegate.started);
52 - assertTrue("should be stopped", delegate.stopped);
53 - assertEquals("incorrect status", SUCCEEDED, delegate.status);
54 - assertTrue("should have output", delegate.output);
55 - }
56 -
57 - private class Listener implements StepProcessListener {
58 -
59 - private Coordinator.Status status;
60 - private boolean started, stopped, output;
61 -
62 - @Override
63 - public void onStart(Step step, String command) {
64 - started = true;
65 - }
66 -
67 - @Override
68 - public void onCompletion(Step step, Coordinator.Status status) {
69 - stopped = true;
70 - this.status = status;
71 - }
72 -
73 - @Override
74 - public void onOutput(Step step, String line) {
75 - output = true;
76 - }
77 - }
78 -
79 -}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.stc;
17 -
18 -import com.google.common.testing.EqualsTester;
19 -import org.apache.commons.configuration.ConfigurationException;
20 -import org.junit.Before;
21 -import org.junit.Test;
22 -
23 -import static org.junit.Assert.assertEquals;
24 -import static org.junit.Assert.assertSame;
25 -
26 -/**
27 - * Test of the test step entity.
28 - */
29 -public class StepTest {
30 -
31 - protected static final String NAME = "step";
32 - protected static final String CMD = "command";
33 - protected static final String ENV = "environment";
34 - protected static final String CWD = "directory";
35 - protected Group parent;
36 -
37 - @Before
38 - public void setUp() throws ConfigurationException {
39 - parent = new Group("parent", null, null, null, null, 0);
40 - }
41 -
42 - @Test
43 - public void basics() {
44 - Step step = new Step(NAME, CMD, ENV, CWD, parent, 1);
45 - assertEquals("incorrect name", NAME, step.name());
46 - assertEquals("incorrect command", CMD, step.command());
47 - assertEquals("incorrect env", ENV, step.env());
48 - assertEquals("incorrect cwd", CWD, step.cwd());
49 - assertSame("incorrect group", parent, step.group());
50 - assertEquals("incorrect delay", 1, step.delay());
51 - }
52 -
53 - @Test
54 - public void equality() {
55 - Step s1 = new Step(NAME, CMD, null, null, parent, 0);
56 - Step s2 = new Step(NAME, CMD, ENV, CWD, null, 0);
57 - Step s3 = new Step("foo", null, null, null, parent, 0);
58 - new EqualsTester()
59 - .addEqualityGroup(s1, s2)
60 - .addEqualityGroup(s3)
61 - .testEquals();
62 - }
63 -}
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="basic-nest">
17 - <step name="a"/>
18 - <step name="b" requires="a"/>
19 - <step name="f" requires="b"/>
20 - <group name="g">
21 - <step name="c"/>
22 - <group name="gg" requires="c">
23 - <step name="d"/>
24 - <step name="e" requires="d"/>
25 - </group>
26 - </group>
27 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="basic">
17 - <step name="a"/>
18 - <step name="b" requires="a"/>
19 - <step name="f" requires="b"/>
20 - <group name="g">
21 - <step name="c"/>
22 - <step name="d" requires="c"/>
23 - <step name="e" requires="d"/>
24 - </group>
25 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="basic-nest">
17 - <step name="a"/>
18 - <step name="aa"/>
19 - <step name="b" requires="a"/>
20 - <step name="f" requires="b,aa"/>
21 - <group name="g">
22 - <step name="c"/>
23 - <group name="gg" requires="c">
24 - <step name="d"/>
25 - <step name="dd" requires="c"/>
26 - <step name="e" requires="d"/>
27 - </group>
28 - </group>
29 - <step name="i" requires="f,g"/>
30 -
31 - <group name="g1">
32 - <group name="g2">
33 - <group name="g3">
34 - <step name="u"/>
35 - <step name="v"/>
36 - <step name="w" requires="u,v"/>
37 - <step name="z" requires="u,w"/>
38 - </group>
39 - </group>
40 - </group>
41 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="basic-nest">
17 - <step name="a"/>
18 - <step name="aa"/>
19 - <step name="b" requires="a"/>
20 - <step name="f" requires="b,aa"/>
21 - <group name="g">
22 - <step name="c"/>
23 - <group name="gg" requires="c">
24 - <step name="d"/>
25 - <step name="dd" requires="c"/>
26 - <step name="e" requires="d"/>
27 - </group>
28 - </group>
29 - <step name="i" requires="f,g"/>
30 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -
17 -<scenario name="one" description="" logDir="${test.dir}/junit-stc/one">
18 - <step name="yolo" exec="some-command args"/>
19 - <step name="hello" exec="some-command other args" requires="yolo"/>
20 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="foo" description="Test Scenario" logDir="${test.dir}/foo">
17 - <import file="${test.dir}/one-scenario.xml" namespace="foo"/>
18 -
19 - <import file="${test.dir}/two-scenario.xml"/>
20 -
21 - <dependency name="dude" requires="~yolo"/>
22 -
23 - <step name="yo" exec="some-command ${HOME} and ${prop.foo} args" if="${prop.foo}"/>
24 - <step name="hi" exec="some-command ${prop.bar} or ${HOME} other args"/>
25 - <step name="there" exec="another-command" requires="yo,hi"/>
26 -
27 - <step name="maybe" exec="another-command" requires="~hi" unless="${prop.foo}"/>
28 -
29 - <group name="alpha" exec="same-command args" requires="yo">
30 - <step name="one" exec="asdads"/>
31 - <step name="two" exec="asdads"/>
32 - <group name="three" exec="asdads" requires="one,two">
33 - <step name="three.a"/>
34 - <step name="three.b" requires="three.a"/>
35 - <step name="three.c" requires="three.b"/>
36 - </group>
37 - </group>
38 -
39 - <dependency name="maybe" requires="yo"/>
40 -
41 - <parallel var="${TOC#}" requires="alpha">
42 - <step name="ping-${#}" exec="asdads ${TOC#}"/>
43 - <step name="pong-${#}" exec="asdads"/>
44 - <step name="ding-${#}" exec="asdads" requires="ping-${#},pong-${#}"/>
45 - <dependency name="maybe" requires="ding-${#}"/>
46 - </parallel>
47 -
48 - <sequential var="${TOC#}" requires="alpha" starts="fifi-${#},gigi-${#}" ends="gaga-${#-1}">
49 - <step name="fifi-${#}" exec="asdads ${TOC#}"/>
50 - <step name="gigi-${#}" exec="asdads"/>
51 - <step name="gaga-${#}" exec="asdads" requires="fifi-${#},gigi-${#}"/>
52 - <dependency name="maybe" requires="gaga-${#}"/>
53 - </sequential>
54 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<scenario name="foo" description="Simple Test Scenario" logDir="${test.dir}/junit-stc/foo">
17 - <group name="alpha" exec="same-command args">
18 - <step name="one" exec="asdads"/>
19 - <step name="two" exec="asdads"/>
20 - <group name="three" exec="asdads" requires="one,two">
21 - <step name="three.a"/>
22 - <step name="three.b" requires="three.a"/>
23 - <step name="three.c" requires="three.b"/>
24 - </group>
25 - </group>
26 -</scenario>
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -
17 -<scenario name="two" description="" logDir="${test.dir}/junit-stc/two">
18 - <step name="dude" exec="some-command args"/>
19 - <step name="waz" exec="some-command other args"/>
20 - <step name="up" exec="another-command" requires="dude,waz"/>
21 -</scenario>
...\ No newline at end of file ...\ No newline at end of file