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> | ... | ... |
utils/stc/bin/stc
deleted
100755 → 0
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 "$@" |
utils/stc/bin/stc-launcher
deleted
100755 → 0
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 |
utils/stc/pom.xml
deleted
100644 → 0
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> |
utils/stc/sample/scenario.xml
deleted
100644 → 0
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 |
utils/stc/src/main/resources/stc.css
deleted
100644 → 0
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 |
utils/stc/src/main/resources/stc.js
deleted
100644 → 0
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 |
-
Please register or login to post a comment