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