Merge "Merge branch 'stable-3.3'"
diff --git a/.zuul.yaml b/.zuul.yaml
index 118ec6a..27c8491 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -7,6 +7,15 @@
bazelisk_test_targets: "plugins/task/lint_test plugins/task/..."
- project:
+ description: |
+ Build the plugin in check, and also build and publish it after
+ every merged commit.
check:
jobs:
- plugins-task-build
+ post:
+ jobs:
+ - plugins-task-build
+ - gerrit-plugin-publish:
+ dependencies:
+ - plugins-task-build
diff --git a/BUILD b/BUILD
index ea5fe6f..0b04753 100644
--- a/BUILD
+++ b/BUILD
@@ -28,7 +28,7 @@
size = "medium",
srcs = ["test/docker/run.sh"],
args = ["--task-plugin-jar", "$(location :task)"],
- data = [plugin_name] + glob(["test/**"]),
+ data = [plugin_name] + glob(["test/**"]) + glob(["src/main/resources/Documentation/*"]),
local = True,
)
diff --git a/src/main/java/com/google/gerrit/common/Container.java b/src/main/java/com/google/gerrit/common/Container.java
index eb0a0f6..6e11534 100644
--- a/src/main/java/com/google/gerrit/common/Container.java
+++ b/src/main/java/com/google/gerrit/common/Container.java
@@ -55,4 +55,21 @@
}
return Objects.hash(values);
}
+
+ @Override
+ public String toString() {
+ List<String> fieldStrings = new ArrayList<>();
+ try {
+ for (Field field : getClass().getDeclaredFields()) {
+ field.setAccessible(true);
+ fieldStrings.add(field.getName() + ": " + Objects.toString(field.get(this)));
+ }
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ }
+ String fields = String.join(", ", fieldStrings);
+ if (!"".equals(fields)) {
+ fields = "{" + fields + "}";
+ }
+ return getClass().toString() + fields;
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
index f01d74d..3a8d903 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
@@ -59,7 +59,7 @@
public boolean onlyInvalid = false;
@Option(name = "--evaluation-time", usage = "Include elapsed evaluation time on each task")
- boolean evaluationTime = false;
+ public boolean evaluationTime = false;
@Option(
name = "--preview",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
index 93923e1..7896417 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
@@ -59,7 +59,7 @@
if ("true".equalsIgnoreCase(query)) {
return true;
}
- return cqb.parse(query).asMatchable().match(c);
+ return getPredicate(query).asMatchable().match(c);
}
protected Predicate<ChangeData> getPredicate(String query) throws QueryParseException {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
index b8bf285..028762c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
@@ -32,30 +32,42 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/** Use to expand properties like ${_name} for a Task Definition. */
+/** Use to expand properties like ${_name} in the text of various definitions. */
public class Properties {
- public Properties(ChangeData changeData, Task definition, Map<String, String> parentProperties)
- throws StorageException {
- Map<String, String> expanded = new HashMap<>(parentProperties);
- expanded.putAll(getInternalProperties(definition, changeData));
- Map<String, String> unexpanded = definition.properties;
- unexpanded.putAll(definition.exported);
- new RecursiveExpander(expanded).expand(unexpanded);
+ /** Use to expand properties specifically for Tasks. */
+ public static class Task extends Expander {
+ public static final Task EMPTY_PARENT = new Task();
- definition.properties = expanded;
- for (String property : definition.exported.keySet()) {
- definition.exported.put(property, expanded.get(property));
+ public Task() {
+ super(Collections.emptyMap());
}
- new Expander(expanded).expandFieldValues(definition, Collections.emptySet());
+ public Task(ChangeData changeData, TaskConfig.Task definition, Task parentProperties)
+ throws StorageException {
+ super(parentProperties.forDescendants());
+ valueByName.putAll(getInternalProperties(definition, changeData));
+ new RecursiveExpander(valueByName).expand(definition.getAllProperties());
+
+ definition.setExpandedProperties(valueByName);
+
+ expandFieldValues(definition, Collections.emptySet());
+ }
+
+ protected Map<String, String> forDescendants() {
+ return new HashMap<>(valueByName);
+ }
}
- public Properties(NamesFactory namesFactory, Map<String, String> properties) {
- new Expander(properties).expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+ /** Use to expand properties specifically for NamesFactories. */
+ public static class NamesFactory extends Expander {
+ public NamesFactory(TaskConfig.NamesFactory namesFactory, Task properties) {
+ super(properties.valueByName);
+ expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+ }
}
- protected static Map<String, String> getInternalProperties(Task definition, ChangeData changeData)
- throws StorageException {
+ protected static Map<String, String> getInternalProperties(
+ TaskConfig.Task definition, ChangeData changeData) throws StorageException {
Map<String, String> properties = new HashMap<>();
properties.put("_name", definition.name);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 77adee2..5e987ca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.task;
+import com.google.common.primitives.Primitives;
import com.google.gerrit.common.Container;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.server.git.meta.AbstractVersionedMetaData;
@@ -43,7 +44,7 @@
}
}
- private class Section extends Container {
+ protected class Section extends Container {
public TaskConfig config;
public Section() {
@@ -57,7 +58,6 @@
public String fail;
public String failHint;
public String inProgress;
- public String name;
public String pass;
public String preloadTask;
public Map<String, String> properties;
@@ -78,7 +78,6 @@
fail = getString(s, KEY_FAIL, null);
failHint = getString(s, KEY_FAIL_HINT, null);
inProgress = getString(s, KEY_IN_PROGRESS, null);
- name = s.subSection;
pass = getString(s, KEY_PASS, null);
preloadTask = getString(s, KEY_PRELOAD_TASK, null);
properties = getProperties(s, KEY_PROPERTIES_PREFIX);
@@ -90,15 +89,41 @@
}
protected TaskBase(TaskBase base) {
- for (Field field : TaskBase.class.getDeclaredFields()) {
+ copyDeclaredFields(TaskBase.class, base);
+ }
+
+ protected <T> void copyDeclaredFields(Class<T> cls, T from) {
+ for (Field field : cls.getDeclaredFields()) {
try {
field.setAccessible(true);
- field.set(this, field.get(base));
+ Class<?> fieldCls = field.getType();
+ Object val = field.get(from);
+ if (field.getType().isPrimitive()
+ || Primitives.isWrapperType(fieldCls)
+ || (val instanceof String)
+ || val == null) {
+ field.set(this, val);
+ } else if (val instanceof List) {
+ List<?> list = List.class.cast(val);
+ field.set(this, new ArrayList<>(list));
+ } else if (val instanceof Map) {
+ Map<?, ?> map = Map.class.cast(val);
+ field.set(this, new HashMap<>(map));
+ } else if (field.getName().equals("this$0")) { // Don't copy internal final field
+ } else {
+ throw new RuntimeException(
+ "Don't know how to deep copy " + fieldValueToString(field, val));
+ }
} catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException(
+ "Cannot access field to copy it " + fieldValueToString(field, "unknown"));
}
}
}
+
+ protected String fieldValueToString(Field field, Object val) {
+ return "field:" + field.getName() + " value:" + val + " type:" + field.getType();
+ }
}
public class Task extends TaskBase {
@@ -106,12 +131,26 @@
public Task(SubSection s, boolean isVisible, boolean isTrusted) {
super(s, isVisible, isTrusted);
- name = getString(s, KEY_NAME, s.subSection);
+ name = s.subSection;
}
protected Task(TaskBase base) {
super(base);
}
+
+ protected Map<String, String> getAllProperties() {
+ Map<String, String> all = new HashMap<>(properties);
+ all.putAll(exported);
+ return all;
+ }
+
+ protected void setExpandedProperties(Map<String, String> expanded) {
+ properties.clear();
+ properties.putAll(expanded);
+ for (String property : exported.keySet()) {
+ exported.put(property, properties.get(property));
+ }
+ }
}
public class TasksFactory extends TaskBase {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index 461d14e..9c4b476 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -40,12 +40,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
+import java.util.function.BiFunction;
import org.eclipse.jgit.errors.ConfigInvalidException;
/**
@@ -94,11 +93,19 @@
return root.getRootNodes();
}
+ public Node createNodeOrNull(NodeList parent, Task definition) {
+ try {
+ return new Node(parent, definition);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
protected class NodeList {
+ protected NodeList parent = null;
protected LinkedList<String> path = new LinkedList<>();
protected List<Node> nodes;
protected Set<String> names = new HashSet<>();
- protected Map<String, String> properties;
protected void addSubDefinitions(List<Task> defs) {
for (Task def : defs) {
@@ -107,28 +114,29 @@
}
protected void addSubDefinition(Task def) {
+ addSubDefinition(def, (d, c) -> createNodeOrNull(d, c));
+ }
+
+ protected void addSubDefinition(Task def, BiFunction<NodeList, Task, Node> nodeConstructor) {
Node node = null;
if (def != null && !path.contains(def.name) && names.add(def.name)) {
// path check above detects looping definitions
// names check above detects duplicate subtasks
- try {
- node = new Node(def, path, properties);
- } catch (Exception e) {
- } // bad definition, handled with null
+ node = nodeConstructor.apply(this, def);
}
nodes.add(node);
}
public ChangeData getChangeData() {
- return TaskTree.this.changeData;
+ return parent == null ? TaskTree.this.changeData : parent.getChangeData();
+ }
+
+ protected Properties.Task getProperties() {
+ return Properties.Task.EMPTY_PARENT;
}
}
protected class Root extends NodeList {
- protected Root() {
- properties = new HashMap<String, String>();
- }
-
public List<Node> getRootNodes() throws ConfigInvalidException, IOException {
if (nodes == null) {
nodes = new ArrayList<>();
@@ -144,15 +152,15 @@
public class Node extends NodeList {
public final Task task;
+ protected final Properties.Task properties;
- public Node(Task definition, List<String> path, Map<String, String> parentProperties)
- throws ConfigInvalidException, StorageException {
+ public Node(NodeList parent, Task definition) throws ConfigInvalidException, StorageException {
+ this.parent = parent;
this.task = definition;
- this.path.addAll(path);
+ this.path.addAll(parent.path);
this.path.add(definition.name);
Preloader.preload(definition);
- new Properties(getChangeData(), definition, parentProperties);
- properties = definition.properties;
+ properties = new Properties.Task(getChangeData(), definition, parent.getProperties());
}
public List<Node> getSubNodes() {
@@ -209,13 +217,12 @@
}
protected void addSubTasksFactoryDefinitions() throws StorageException {
- List<Task> taskList = new ArrayList<>();
for (String taskFactoryName : task.subTasksFactories) {
TasksFactory tasksFactory = task.config.getTasksFactory(taskFactoryName);
if (tasksFactory != null) {
NamesFactory namesFactory = task.config.getNamesFactory(tasksFactory.namesFactory);
if (namesFactory != null && namesFactory.type != null) {
- new Properties(namesFactory, task.properties);
+ new Properties.NamesFactory(namesFactory, getProperties());
switch (NamesFactoryType.getNamesFactoryType(namesFactory.type)) {
case STATIC:
addStaticTypeTasksDefinitions(tasksFactory, namesFactory);
@@ -247,7 +254,9 @@
.query(changeQueryBuilderProvider.get().parse(namesFactory.changes))
.entities();
for (ChangeData changeData : changeDataList) {
- addSubDefinition(task.config.createTask(tasksFactory, changeData.getId().toString()));
+ addSubDefinition(
+ task.config.createTask(tasksFactory, changeData.getId().toString()),
+ new ChangeNodeFactory(changeData)::createChangeNodeOrNull);
}
return;
}
@@ -270,6 +279,11 @@
.getTasks();
}
+ @Override
+ protected Properties.Task getProperties() {
+ return properties;
+ }
+
protected String resolveTaskFileName(String file) throws ConfigInvalidException {
if (file == null) {
throw new ConfigInvalidException("External file not defined");
@@ -295,4 +309,30 @@
return BranchNameKey.create(allUsers.get(), RefNames.refsUsers(acct));
}
}
+
+ public class ChangeNodeFactory {
+ public class ChangeNode extends Node {
+ public ChangeNode(NodeList parent, Task definition) throws ConfigInvalidException {
+ super(parent, definition);
+ }
+
+ public ChangeData getChangeData() {
+ return ChangeNodeFactory.this.changeData;
+ }
+ }
+
+ protected ChangeData changeData;
+
+ public ChangeNodeFactory(ChangeData changeData) {
+ this.changeData = changeData;
+ }
+
+ public ChangeNode createChangeNodeOrNull(NodeList parent, Task definition) {
+ try {
+ return new ChangeNode(parent, definition);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
}
diff --git a/src/main/resources/Documentation/task.md b/src/main/resources/Documentation/task.md
index 8c1309e..fa5e834 100644
--- a/src/main/resources/Documentation/task.md
+++ b/src/main/resources/Documentation/task.md
@@ -430,13 +430,18 @@
set-<property-name> = <property-value>
```
-Subtasks inherit all custom properties from their parents. A task is invalid
-if it attempts to override an already set property.
+Subtasks inherit all custom properties from their parents, however
+subtasks may override inherrited properties and give them new values.
Example:
```
[task "foo-project"]
set-project-name = foo
+ subtask = sub-project
+ subtask = common-to-many-projects
+
+ [task "sub-project"]
+ set-project-name = sub-foo # Overrides value from 'foo-project'
subtask = common-to-many-projects
[task "common-to-many-projects"]
@@ -530,5 +535,8 @@
Examples
--------
-See [task_states](task_states.html) for a comprehensive list of examples
+See [task_states](test/task_states.html) for a comprehensive list of examples
of task configs and their states.
+
+See what the results will look when [previewing](test/preview.html) a change
+to those states.
diff --git a/src/main/resources/Documentation/task_states.md b/src/main/resources/Documentation/task_states.md
deleted file mode 100644
index 8b0c705..0000000
--- a/src/main/resources/Documentation/task_states.md
+++ /dev/null
@@ -1,1189 +0,0 @@
-@PLUGIN@ States
-===============
-
-Below are sample config files which illustrate many examples of how task
-states are affected by their own criteria and their subtasks' states.
-
-`task.config` file in project `All-Project` on ref `refs/meta/config`.
-
-```
-[root "Root N/A"]
- applicable = is:closed # Assumes test query is "is:open"
-
-[root "Root APPLICABLE"]
- applicable = is:open # Assumes test query is "is:open"
- pass = True
- subtask = Subtask APPLICABLE
-
-[root "Root PASS"]
- pass = True
-
-[root "Root FAIL"]
- fail = True
-
-[root "Root straight PASS"]
- applicable = is:open
- pass = is:open
-
-[root "Root straight FAIL"]
- applicable = is:open
- fail = is:open
- pass = is:open
-
-[root "Root PASS-fail"]
- applicable = is:open
- fail = NOT is:open
-
-[root "Root pass-FAIL"]
- applicable = is:open
- fail = is:open
-
-[root "Root PASS-waiting-fail"]
- applicable = is:open
- fail = NOT is:open
- subtask = Subtask PASS
-
-[root "Root pass-WAITING-fail"]
- applicable = is:open
- fail = NOT is:open
- subtask = Subtask FAIL
-
-[root "Root pass-waiting-FAIL"]
- applicable = is:open
- fail = is:open
- subtask = Subtask PASS
-
-[root "Root grouping PASS (subtask PASS)"]
- subtask = Subtask PASS
-
-[root "Root grouping WAITING (subtask READY)"]
- subtask = Subtask READY
-
-[root "Root grouping WAITING (subtask FAIL)"]
- subtask = Subtask FAIL
-
-[root "Root grouping NA (subtask NA)"]
- applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
- subtask = Subtask NA
-
-[root "Root READY (subtask PASS)"]
- applicable = is:open
- pass = NOT is:open
- subtask = Subtask PASS
- ready-hint = You must now run the ready task
-
-[root "Root WAITING (subtask READY)"]
- applicable = is:open
- pass = is:open
- subtask = Subtask READY
-
-[root "Root WAITING (subtask FAIL)"]
- applicable = is:open
- pass = is:open
- subtask = Subtask FAIL
-
-[root "Root IN PROGRESS"]
- applicable = is:open
- in-progress = is:open
- pass = NOT is:open
-
-[root "Root NOT IN PROGRESS"]
- applicable = is:open
- in-progress = NOT is:open
- pass = NOT is:open
-
-[root "Root Optional subtasks"]
- subtask = OPTIONAL MISSING |
- subtask = Subtask Optional |
-
-[root "Subtasks File"]
- subtasks-file = common.config
-
-[root "Subtasks File (Missing)"]
- subtasks-file = common.config
- subtasks-file = missing
-
-[root "Subtasks External"]
- subtasks-external = user special
-
-[root "Subtasks External (Missing)"]
- subtasks-external = user special
- subtasks-external = missing
-
-[root "Subtasks External (User Missing)"]
- subtasks-external = user special
- subtasks-external = user missing
-
-[root "Subtasks External (File Missing)"]
- subtasks-external = user special
- subtasks-external = file missing
-
-[root "Root tasks-factory"]
- subtasks-factory = tasks-factory static
- subtasks-factory = tasks-factory change
-
-[root "Root tasks-factory static (empty name)"]
- subtasks-factory = tasks-factory static (empty name)
-# Grouping task since it has no pass criteria, not output since it has no subtasks
-
-[root "Root tasks-factory static (empty name PASS)"]
- pass = True
- subtasks-factory = tasks-factory static (empty name)
-
-[root "Root Properties"]
- set-root-property = root-value
- export-root = ${_name}
- fail = True
- fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
- subtask = Subtask Properties
-
-[root "Root Preload"]
- preload-task = Subtask FAIL
- subtask = Subtask Preload
-
-[root "Root INVALID Preload"]
- preload-task = missing
-
-[root "INVALIDS"]
- subtasks-file = invalids.config
-
-[root "Root NA Pass"]
- applicable = NOT is:open # Assumes test query is "is:open"
- pass = True
-
-[root "Root NA Fail"]
- applicable = NOT is:open # Assumes test query is "is:open"
- fail = True
-
-[root "NA INVALIDS"]
- applicable = NOT is:open # Assumes test query is "is:open"
- subtasks-file = invalids.config
-
-[tasks-factory "tasks-factory static"]
- names-factory = names-factory static list
- fail = True
-
-[tasks-factory "tasks-factory static (empty name)"]
- names-factory = names-factory static (empty name list)
- fail = True
-
-[tasks-factory "tasks-factory change"]
- names-factory = names-factory change list
- fail = True
-
-[task "Subtask APPLICABLE"]
- applicable = is:open
- pass = True
-
-[task "Subtask FAIL"]
- applicable = is:open
- fail = is:open
- pass = is:open
-
-[task "Subtask READY"]
- applicable = is:open
- pass = NOT is:open
- subtask = Subtask PASS
-
-[task "Subtask PASS"]
- applicable = is:open
- pass = is:open
-
-[task "Subtask Optional"]
- subtask = Subtask PASS |
- subtask = OPTIONAL MISSING | Subtask FAIL
- subtask = OPTIONAL MISSING | OPTIONAL MISSING |
- subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
-
-[task "Subtask NA"]
- applicable = NOT is:open # Assumes test query is "is:open"
-
-[task "Subtask Properties"]
- export-subtask = ${_name}
- subtask = Subtask Properties Hints
- subtask = Chained ${_name}
- subtask = Subtask Properties Reset
- subtasks-factory = TaskFactory Properties Hints
-
-[task "Subtask Properties Hints"]
- set-first-property = first-value
- set-second-property = ${first-property} second-extra ${third-property}
- set-third-property = third-value
- fail = True
- fail-hint = Name(${_name}) root-property(${root-property}) first-property(${first-property}) second-property(${second-property}) root(${root})
-
-[task "Chained Subtask Properties"]
- pass = True
-
-[task "Subtask Properties Reset"]
- pass = True
- set-first-property = reset-first-value
- fail-hint = first-property(${first-property})
-
-[tasks-factory "TaskFactory Properties Hints"]
- names-factory = NamesFactory Properties
- fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
- fail = True
-
-[names-factory "NamesFactory Properties"]
- type = change
- changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
-
-[task "Subtask Preload"]
- preload-task = Subtask READY
- subtask = Subtask Preload Preload
- subtask = Subtask Preload Hints PASS
- subtask = Subtask Preload Hints FAIL
- subtask = Subtask Preload Override Pass
- subtask = Subtask Preload Override Fail
- subtask = Subtask Preload Extend Subtasks
- subtask = Subtask Preload Optional
- subtask = Subtask Preload Properties
-
-[task "Subtask Preload Preload"]
- preload-task = Subtask Preload with Preload
-
-[task "Subtask Preload with Preload"]
- preload-task = Subtask PASS
-
-[task "Subtask Preload Hints PASS"]
- preload-task = Subtask Hints
- pass = False
-
-[task "Subtask Preload Hints FAIL"]
- preload-task = Subtask Hints
- fail = True
-
-[task "Subtask Preload Override Pass"]
- preload-task = Subtask PASS
- pass = False
-
-[task "Subtask Preload Override Fail"]
- preload-task = Subtask FAIL
- fail = False
-
-[task "Subtask Preload Extend Subtasks"]
- preload-task = Subtask READY
- subtask = Subtask APPLICABLE
-
-[task "Subtask Preload Optional"]
- preload-task = Missing | Subtask PASS
-
-[task "Subtask Preload Properties"]
- preload-task = Subtask Properties Hints
- set-fourth-property = fourth-value
- fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
-
-[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
- ready-hint = Task is ready
- fail-hint = Task failed
-
-[external "user special"]
- user = testuser
- file = special.config
-
-[external "user missing"]
- user = missing
- file = special.config
-
-[external "file missing"]
- user = testuser
- file = missing
-
-[names-factory "names-factory static list"]
- name = my a task
- name = my b task
- name = my c task
- name = my d task Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
- type = static
-
-[names-factory "names-factory static (empty name list)"]
- type = static
-
-[names-factory "names-factory change list"]
- changes = change:_change1_number OR change:_change2_number
- type = change
-
-```
-
-`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "file task/common.config PASS"]
- applicable = is:open
- pass = is:open
-
-[task "file task/common.config FAIL"]
- applicable = is:open
- fail = is:open
-```
-
-`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "No PASS criteria"]
- fail-hint = Invalid without Pass criteria and without subtasks
-
-[task "WAITING (subtask INVALID)"]
- pass = is:open
- subtask = Subtask INVALID
-
-[task "WAITING (subtask duplicate)"]
- subtask = Subtask INVALID
- subtask = Subtask INVALID
-
-[task "WAITING (subtask missing)"]
- pass = is:open
- subtask = MISSING # security bug: subtask name appears in output
-
-[task "Grouping WAITING (subtask INVALID)"]
- subtask = Subtask INVALID
-
-[task "Grouping WAITING (subtask missing)"]
- subtask = MISSING # security bug: subtask name appears in output
-
-[task "Subtask INVALID"]
- fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
-
-[task "Subtask Optional"]
- subtask = MISSING | MISSING
-
-[task "NA Bad PASS query"]
- applicable = NOT is:open # Assumes test query is "is:open"
- fail = True
- pass = has:bad
-
-[task "NA Bad FAIL query"]
- applicable = NOT is:open # Assumes test query is "is:open"
- pass = True
- fail = has:bad
-
-[task "NA Bad INPROGRESS query"]
- applicable = NOT is:open # Assumes test query is "is:open"
- fail = True
- in-progress = has:bad
-
-[task "Looping"]
- subtask = Looping
-
-[task "Looping Properties"]
- set-A = ${B}
- set-B = ${A}
- fail = True
-
-[task "task (tasks-factory missing)"]
- subtasks-factory = missing
-
-[task "task (names-factory type missing)"]
- subtasks-factory = tasks-factory (names-factory type missing)
-
-[task "task (names-factory type INVALID)"]
- subtasks-factory = tasks-factory (names-factory type INVALID)
-
-[task "task (names-factory duplicate)"]
- subtasks-factory = tasks-factory (names-factory duplicate)
-
-[task "task (names-factory changes type missing)"]
- subtasks-factory = tasks-factory change (names-factory type missing)
-
-[task "task (names-factory changes missing)"]
- subtasks-factory = tasks-factory change (names-factory changes missing)
-
-[task "task (names-factory changes invalid)"]
- subtasks-factory = tasks-factory change (names-factory changes invalid)
-
-[task "task (tasks-factory changes loop)"]
- subtasks-factory = tasks-factory change loop
-
-[tasks-factory "tasks-factory (names-factory type missing)"]
- names-factory = names-factory (type missing)
- fail = True
-
-[tasks-factory "tasks-factory (names-factory type INVALID)"]
- names-factory = name-factory (type INVALID)
-
-[tasks-factory "tasks-factory (names-factory duplicate)"]
- names-factory = names-factory duplicate
- fail = True
-
-[tasks-factory "tasks-factory change (names-factory type missing)"]
- names-factory = names-factory change list (type missing)
- fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes missing)"]
- names-factory = names-factory change list (changes missing)
- fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes invalid)"]
- names-factory = names-factory change list (changes invalid)
- fail = True
-
-[tasks-factory "tasks-factory change loop"]
- names-factory = names-factory change constant
- subtask = task (tasks-factory changes loop)
- fail = true
-
-[names-factory "names-factory (type missing)"]
- name = no type test
-
-[names-factory "names-factory change list (type missing)"]
- changes = change:_change1_number OR change:_change2_number
-
-[names-factory "names-factory (type INVALID)"]
- name = invalid type test
- type = invalid
-
-[names-factory "names-factory duplicate"]
- name = duplicate
- name = duplicate
- type = static
-
-[names-factory "names-factory change list (changes missing)"]
- type = change
-
-[names-factory "names-factory change list (changes invalid)"]
- change = change:invalidChange
- type = change
-
-[names-factory "names-factory change constant"]
- changes = change:_change1_number OR change:_change2_number
- type = change
-
-```
-
-`task/special.config` file in project `All-Users` on ref `refs/users/self`.
-
-```
-[task "userfile task/special.config PASS"]
- applicable = is:open
- pass = is:open
-
-[task "userfile task/special.config FAIL"]
- applicable = is:open
- fail = is:open
-```
-
-The expected output for the above task config looks like:
-
-```
- $ ssh -x -p 29418 review-example gerrit query is:open \
- --task--applicable --format json|head -1 |json_pp
-{
- ...,
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "hasPass" : true,
- "name" : "Root APPLICABLE",
- "status" : "PASS",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask APPLICABLE",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Root FAIL",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Root straight PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Root straight FAIL",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Root PASS-fail",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Root pass-FAIL",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Root PASS-waiting-fail",
- "status" : "PASS",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root pass-WAITING-fail",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root pass-waiting-FAIL",
- "status" : "FAIL",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Root grouping PASS (subtask PASS)",
- "status" : "PASS",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Root grouping WAITING (subtask READY)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Root grouping WAITING (subtask FAIL)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : true,
- "hint" : "You must now run the ready task",
- "name" : "Root READY (subtask PASS)",
- "status" : "READY",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root WAITING (subtask READY)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root WAITING (subtask FAIL)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : true,
- "inProgress" : true,
- "name" : "Root IN PROGRESS",
- "status" : "READY"
- },
- {
- "hasPass" : true,
- "inProgress" : false,
- "name" : "Root NOT IN PROGRESS",
- "status" : "READY"
- },
- {
- "hasPass" : false,
- "name" : "Root Optional subtasks",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks File",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "file task/common.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "file task/common.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks File (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "file task/common.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "file task/common.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks External",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks External (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks External (User Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks External (File Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Root tasks-factory",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "my a task",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "my b task",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "my c task",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root tasks-factory static (empty name PASS)",
- "status" : "PASS"
- },
- {
- "exported" : {
- "root" : "Root Properties"
- },
- "hasPass" : true,
- "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "Root Properties",
- "status" : "FAIL",
- "subTasks" : [
- {
- "exported" : {
- "subtask" : "Subtask Properties"
- },
- "hasPass" : false,
- "name" : "Subtask Properties",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
- "name" : "Subtask Properties Hints",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Chained Subtask Properties",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Subtask Properties Reset",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "_change3_number",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "_change1_number",
- "status" : "FAIL"
- }
- ]
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Root Preload",
- "status" : "FAIL",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask Preload",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Subtask Preload Preload",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "hint" : "Task is ready",
- "name" : "Subtask Preload Hints PASS",
- "status" : "READY"
- },
- {
- "hasPass" : true,
- "hint" : "Task failed",
- "name" : "Subtask Preload Hints FAIL",
- "status" : "FAIL"
- },
- {
- "hasPass" : true,
- "name" : "Subtask Preload Override Pass",
- "status" : "READY"
- },
- {
- "hasPass" : true,
- "name" : "Subtask Preload Override Fail",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Subtask Preload Extend Subtasks",
- "status" : "READY",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "name" : "Subtask APPLICABLE",
- "status" : "PASS"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "Subtask Preload Optional",
- "status" : "PASS"
- },
- {
- "hasPass" : true,
- "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
- "name" : "Subtask Preload Properties",
- "status" : "FAIL"
- }
- ]
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "duplicate",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
- ...
-```
diff --git a/src/main/resources/Documentation/test/preview.md b/src/main/resources/Documentation/test/preview.md
new file mode 100644
index 0000000..e53b7d8
--- /dev/null
+++ b/src/main/resources/Documentation/test/preview.md
@@ -0,0 +1,603 @@
+[root "INVALIDS Preview"]
+ subtasks-file = invalids.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "INVALIDS Preview",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "No PASS criteria",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "WAITING (subtask duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad PASS query",
+ "status" : "FAIL" # Only Test Suite: !invalid
+ "status" : "INVALID" # Only Test Suite: invalid
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad FAIL query",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad INPROGRESS query",
+ "status" : "FAIL" # Only Test Suite: !invalid
+ "status" : "INVALID" # Only Test Suite: invalid
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Looping",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "duplicate",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes invalid)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory changes loop)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change2_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root PASS Preview"]
+ pass = True
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root PASS Preview",
+ "status" : "PASS"
+}
+
+[root "Root READY (subtask PASS) Preview"]
+ applicable = is:open
+ pass = NOT is:open
+ subtask = Subtask PASS Preview
+ ready-hint = You must now run the ready task
+
+[task "Subtask PASS Preview"]
+ applicable = is:open
+ pass = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "You must now run the ready task",
+ "name" : "Root READY (subtask PASS) Preview",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS Preview",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Subtasks External Preview"]
+ subtasks-external = user special Preview
+
+[external "user special Preview"]
+ user = testuser
+ file = special.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks External Preview",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root NA Pass Preview"]
+ applicable = NOT is:open
+ pass = True
+
+{
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "Root NA Pass Preview",
+ "status" : "PASS"
+}
+
+[root "NA INVALIDS Preview"]
+ applicable = NOT is:open
+ subtasks-file = invalids.config
+
+{
+ "applicable" : false,
+ "hasPass" : false,
+ "name" : "NA INVALIDS Preview",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "No PASS criteria",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "WAITING (subtask duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad PASS query",
+ "status" : "FAIL" # Only Test Suite: !invalid
+ "status" : "INVALID" # Only Test Suite: invalid
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad FAIL query",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad INPROGRESS query",
+ "status" : "FAIL" # Only Test Suite: !invalid
+ "status" : "INVALID" # Only Test Suite: invalid
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Looping",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "duplicate",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes invalid)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory changes loop)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change2_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/main/resources/Documentation/test/task_states.md b/src/main/resources/Documentation/test/task_states.md
new file mode 100644
index 0000000..ea09541
--- /dev/null
+++ b/src/main/resources/Documentation/test/task_states.md
@@ -0,0 +1,2093 @@
+@PLUGIN@ States
+===============
+
+Below are sample config files which illustrate many examples of how task
+states are affected by their own criteria and their subtasks' states.
+To better help visualize the output that each `root` example leads to,
+the json output for the root definition (and any definitions that it
+refers to) will be placed inline right after the root. Naturally, this
+json is not a part of the config, however it is part of the expected
+output for task config when running the following:
+
+```
+ $ ssh -x -p 29418 review-example gerrit query is:open \
+ --task--all --format json|head -1 |json_pp
+```
+
+The config below is expected to be in the `task.config` file in project
+`All-Projects` on ref `refs/meta/config`.
+
+```
+[root "Root N/A"]
+ applicable = is:closed # Assumes test query is "is:open"
+
+{
+ "applicable" : false,
+ "hasPass" : false,
+ "name" : "Root N/A",
+ "status" : "INVALID"
+}
+
+[root "Root APPLICABLE"]
+ applicable = is:open # Assumes test query is "is:open"
+ pass = True
+ subtask = Subtask APPLICABLE
+
+[task "Subtask APPLICABLE"]
+ applicable = is:open
+ pass = True
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root APPLICABLE",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask APPLICABLE",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root PASS"]
+ pass = True
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root PASS",
+ "status" : "PASS"
+}
+
+[root "Root FAIL"]
+ fail = True
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root FAIL",
+ "status" : "FAIL"
+}
+
+[root "Root straight PASS"]
+ applicable = is:open
+ pass = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root straight PASS",
+ "status" : "PASS"
+}
+
+[root "Root straight FAIL"]
+ applicable = is:open
+ fail = is:open
+ pass = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root straight FAIL",
+ "status" : "FAIL"
+}
+
+[root "Root PASS-fail"]
+ applicable = is:open
+ fail = NOT is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root PASS-fail",
+ "status" : "PASS"
+}
+
+[root "Root pass-FAIL"]
+ applicable = is:open
+ fail = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root pass-FAIL",
+ "status" : "FAIL"
+}
+
+[root "Root PASS-waiting-fail"]
+ applicable = is:open
+ fail = NOT is:open
+ subtask = Subtask PASS
+
+[task "Subtask PASS"]
+ applicable = is:open
+ pass = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root PASS-waiting-fail",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root pass-WAITING-fail"]
+ applicable = is:open
+ fail = NOT is:open
+ subtask = Subtask FAIL
+
+[task "Subtask FAIL"]
+ applicable = is:open
+ fail = is:open
+ pass = is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root pass-WAITING-fail",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root pass-waiting-FAIL"]
+ applicable = is:open
+ fail = is:open
+ subtask = Subtask PASS
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root pass-waiting-FAIL",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root grouping PASS (subtask PASS)"]
+ subtask = Subtask PASS
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root grouping PASS (subtask PASS)",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root grouping WAITING (subtask READY)"]
+ subtask = Subtask READY
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root grouping WAITING (subtask READY)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask READY",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root grouping WAITING (subtask FAIL)"]
+ subtask = Subtask FAIL
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root grouping WAITING (subtask FAIL)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root grouping NA (subtask NA)"]
+ applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
+ subtask = Subtask NA
+
+[task "Subtask NA"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root grouping NA (subtask NA)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : false,
+ "hasPass" : false,
+ "name" : "Subtask NA",
+ "status" : "INVALID"
+ }
+ ]
+}
+
+[root "Root READY (subtask PASS)"]
+ applicable = is:open
+ pass = NOT is:open
+ subtask = Subtask PASS
+ ready-hint = You must now run the ready task
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "You must now run the ready task",
+ "name" : "Root READY (subtask PASS)",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root WAITING (subtask READY)"]
+ applicable = is:open
+ pass = is:open
+ subtask = Subtask READY
+
+[task "Subtask READY"]
+ applicable = is:open
+ pass = NOT is:open
+ subtask = Subtask PASS
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root WAITING (subtask READY)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask READY",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root WAITING (subtask FAIL)"]
+ applicable = is:open
+ pass = is:open
+ subtask = Subtask FAIL
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root WAITING (subtask FAIL)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root IN PROGRESS"]
+ applicable = is:open
+ in-progress = is:open
+ pass = NOT is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "inProgress" : true,
+ "name" : "Root IN PROGRESS",
+ "status" : "READY"
+}
+
+[root "Root NOT IN PROGRESS"]
+ applicable = is:open
+ in-progress = NOT is:open
+ pass = NOT is:open
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "inProgress" : false,
+ "name" : "Root NOT IN PROGRESS",
+ "status" : "READY"
+}
+
+[root "Root OPTIONAL MISSING"]
+ subtask = OPTIONAL MISSING |
+ pass = True
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root OPTIONAL MISSING",
+ "status" : "PASS"
+}
+
+[root "Root Optional subtask EXISTS"]
+ subtask = Subtask Optional EXISTS |
+
+[task "Subtask Optional EXISTS"]
+ subtask = Subtask PASS |
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Optional subtask EXISTS",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional EXISTS",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Optional subtask MISSING then EXISTS"]
+ subtask = Subtask Optional MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then EXISTS"]
+ subtask = OPTIONAL MISSING | Subtask FAIL
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Optional subtask MISSING then EXISTS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional MISSING then EXISTS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Optional subtask MISSING then MISSING"]
+ subtask = Subtask Optional MISSING then MISSING |
+
+[task "Subtask Optional MISSING then MISSING"]
+ subtask = OPTIONAL MISSING | OPTIONAL MISSING |
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Optional subtask MISSING then MISSING",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional MISSING then MISSING"
+ }
+ ]
+}
+
+[root "Root Optional subtask MISSING then MISSING then EXISTS"]
+ subtask = Subtask Optional MISSING then MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then MISSING then EXISTS"]
+ subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Optional subtask MISSING then MISSING then EXISTS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional MISSING then MISSING then EXISTS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask READY",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+[root "Subtasks File"]
+ subtasks-file = common.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks File",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "file task/common.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "file task/common.config FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Subtasks File (Missing)"]
+ subtasks-file = common.config
+ subtasks-file = missing
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks File (Missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "file task/common.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "file task/common.config FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Subtasks External"]
+ subtasks-external = user special
+
+[external "user special"]
+ user = testuser
+ file = special.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks External",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Subtasks External (Missing)"]
+ subtasks-external = user special
+ subtasks-external = missing
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks External (Missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config FAIL",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+}
+
+[root "Subtasks External (User Missing)"]
+ subtasks-external = user special
+ subtasks-external = user missing
+
+[external "user missing"]
+ user = missing
+ file = special.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks External (User Missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config FAIL",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+}
+
+[root "Subtasks External (File Missing)"]
+ subtasks-external = user special
+ subtasks-external = file missing
+
+[external "file missing"]
+ user = testuser
+ file = missing
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtasks External (File Missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "userfile task/special.config FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root tasks-factory STATIC"]
+ subtasks-factory = tasks-factory static
+
+[tasks-factory "tasks-factory static"]
+ names-factory = names-factory static list
+ fail = True
+
+[names-factory "names-factory static list"]
+ type = static
+ name = my a task
+ name = my b task
+ name = my c task
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root tasks-factory STATIC",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "my a task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "my b task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "my c task",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root tasks-factory CHANGE"]
+ subtasks-factory = tasks-factory change
+
+[tasks-factory "tasks-factory change"]
+ names-factory = names-factory change list
+ fail = True
+
+[names-factory "names-factory change list"]
+ changes = change:_change1_number OR change:_change2_number
+ type = change
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root tasks-factory CHANGE",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change2_number",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root tasks-factory static (empty name)"]
+ subtasks-factory = tasks-factory static (empty name)
+ # Grouping task since it has no pass criteria, not output since it has no subtasks
+
+[tasks-factory "tasks-factory static (empty name)"]
+ names-factory = names-factory static (empty name list)
+ fail = True
+
+[names-factory "names-factory static (empty name list)"]
+ type = static
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root tasks-factory static (empty name)"
+}
+
+[root "Root tasks-factory static (empty name PASS)"]
+ pass = True
+ subtasks-factory = tasks-factory static (empty name)
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root tasks-factory static (empty name PASS)",
+ "status" : "PASS"
+}
+
+[root "Root Properties"]
+ set-root-property = root-value
+ subtask = Subtask Properties
+
+[task "Subtask Properties"]
+ subtask = Subtask Properties Hints
+
+[task "Subtask Properties Hints"]
+ set-first-property = first-value
+ set-second-property = ${first-property} second-extra ${third-property}
+ set-third-property = third-value
+ fail = True
+ fail-hint = root-property(${root-property}) first-property(${first-property}) second-property(${second-property})
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Properties",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value)",
+ "name" : "Subtask Properties Hints",
+ "status" : "FAIL"
+ }
+ ]
+ }
+ ]
+}
+
+
+[root "Root Properties Reset By Subtask"]
+ set-root-to-reset-by-subtask = reset-my-root-value
+ subtask = Subtask Properties Reset
+
+[task "Subtask Properties Reset"]
+ fail = True
+ set-root-to-reset-by-subtask = reset-by-subtask-root-value
+ fail-hint = root-to-reset-by-subtask:(${root-to-reset-by-subtask})
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties Reset By Subtask",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "root-to-reset-by-subtask:(reset-by-subtask-root-value)",
+ "name" : "Subtask Properties Reset",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Properties Exports"]
+ export-root-exported = ${_name}
+ subtask = Subtask Properties Exports
+ fail = True
+ fail-hint = root-exported(${root-exported})
+
+[task "Subtask Properties Exports"]
+ export-subtask-exported = ${_name}
+ fail = True
+ fail-hint = root-exported(${root-exported}) subtask-exported(${subtask-exported})
+
+{
+ "applicable" : true,
+ "exported" : {
+ "root-exported" : "Root Properties Exports"
+ },
+ "hasPass" : true,
+ "hint" : "root-exported(Root Properties Exports)",
+ "name" : "Root Properties Exports",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "exported" : {
+ "subtask-exported" : "Subtask Properties Exports"
+ },
+ "hasPass" : true,
+ "hint" : "root-exported(Root Properties Exports) subtask-exported(Subtask Properties Exports)",
+ "name" : "Subtask Properties Exports",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Internal Properties"]
+ export-root = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+ set-root-internals = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+ fail = True
+ fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+ subtask = Subtask Internal Properties
+
+[task "Subtask Internal Properties"]
+ fail = True
+ fail-hint = root-internals(${root-internals}) Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+
+{
+ "applicable" : true,
+ "exported" : {
+ "root" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)"
+ },
+ "hasPass" : true,
+ "hint" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+ "name" : "Root Internal Properties",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "root-internals(Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)) Name(Subtask Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+ "name" : "Subtask Internal Properties",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Subtask Via Property"]
+ set-subtask = Subtask
+ subtask = ${subtask} Via Property
+
+[task "Subtask Via Property"]
+ subtask = Second ${_name}
+
+[task "Second Subtask Via Property"]
+ fail = True
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Subtask Via Property",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Via Property",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Second Subtask Via Property",
+ "status" : "FAIL"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Properties tasks-factory STATIC"]
+ subtasks-factory = tasks-factory STATIC Properties
+
+[tasks-factory "tasks-factory STATIC Properties"]
+ set-welcome-message = Welcome to the jungle
+ names-factory = names-factory static list
+ fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+ fail = True
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties tasks-factory STATIC",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Welcome to the jungle Name(my a task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+ "name" : "my a task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Welcome to the jungle Name(my b task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+ "name" : "my b task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Welcome to the jungle Name(my c task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+ "name" : "my c task",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Properties tasks-factory CHANGE"]
+ subtasks-factory = tasks-factory CHANGE Properties
+
+[tasks-factory "tasks-factory CHANGE Properties"]
+ set-welcome-message = Welcome to the pleasuredome
+ names-factory = names-factory a change
+ fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+ fail = True
+
+[names-factory "names-factory a change"]
+ type = change
+ changes = change:_change1_number OR change:_change2_number
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties tasks-factory CHANGE",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Welcome to the pleasuredome Name(_change1_number) Change Number(_change1_number) Change Id(_change1_id) Change Project(_change1_project) Change Branch(_change1_branch) Change Status(_change1_status) Change Topic(_change1_topic)",
+ "name" : "_change1_number",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Welcome to the pleasuredome Name(_change2_number) Change Number(_change2_number) Change Id(_change2_id) Change Project(_change2_project) Change Branch(_change2_branch) Change Status(_change2_status) Change Topic(_change2_topic)",
+ "name" : "_change2_number",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Properties names-factory STATIC"]
+ subtasks-factory = tasks-factory Properties names-factory STATIC
+
+[tasks-factory "tasks-factory Properties names-factory STATIC"]
+ names-factory = Properties names-factory STATIC
+ fail = True
+
+[names-factory "Properties names-factory STATIC"]
+ type = static
+ name = Change Number(${_change_number})
+ name = Change Id(${_change_id})
+ name = Change Project(${_change_project})
+ name = Change Branch(${_change_branch})
+ name = Change Status(${_change_status})
+ name = Change Topic(${_change_topic})
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties names-factory STATIC",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Number(_change_number)",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Id(_change_id)",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Project(_change_project)",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Branch(_change_branch)",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Status(_change_status)",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Change Topic(_change_topic)",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Properties names-factory CHANGE"]
+ subtasks-factory = tasks-factory Properties names-factory CHANGE
+
+[tasks-factory "tasks-factory Properties names-factory CHANGE"]
+ names-factory = Properties names-factory CHANGE
+ fail = True
+
+[names-factory "Properties names-factory CHANGE"]
+ type = change
+ changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties names-factory CHANGE",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change_number",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Properties Expansion"]
+ applicable = status:open
+ subtask = Subtask Property Expansion fail-hint
+
+[task "Subtask Property Expansion fail-hint"]
+ subtasks-factory = tasks-factory Property Expansion fail-hint
+
+[tasks-factory "tasks-factory Property Expansion fail-hint"]
+ set-first-property = first-property ${_name}
+ fail-hint = ${first-property}
+ fail = true
+ names-factory = names-factory static list
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Properties Expansion",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Property Expansion fail-hint",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "first-property my a task",
+ "name" : "my a task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "first-property my b task",
+ "name" : "my b task",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "first-property my c task",
+ "name" : "my c task",
+ "status" : "FAIL"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Preload"]
+ preload-task = Subtask FAIL
+ subtask = Subtask Preload
+
+[task "Subtask Preload"]
+ preload-task = Subtask READY
+
+{
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Root Preload",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Preload",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Preload Preload"]
+ subtask = Subtask Preload Preload
+
+[task "Subtask Preload Preload"]
+ preload-task = Subtask Preload with Preload
+
+[task "Subtask Preload with Preload"]
+ preload-task = Subtask PASS
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Preload Preload",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Preload Preload",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root Preload Hints PASS"]
+ subtask = Subtask Preload Hints PASS
+
+[task "Subtask Preload Hints PASS"]
+ preload-task = Subtask Hints
+ pass = False
+
+[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
+ ready-hint = Task is ready
+ fail-hint = Task failed
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Preload Hints PASS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Task is ready",
+ "name" : "Subtask Preload Hints PASS",
+ "status" : "READY"
+ }
+ ]
+}
+
+[root "Root Preload Hints FAIL"]
+ subtask = Subtask Preload Hints FAIL
+
+[task "Subtask Preload Hints FAIL"]
+ preload-task = Subtask Hints
+ fail = True
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Preload Hints FAIL",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "Task failed",
+ "name" : "Subtask Preload Hints FAIL",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root Override Preload Pass"]
+ subtask = Subtask Override Preload Pass
+
+[task "Subtask Override Preload Pass"]
+ preload-task = Subtask PASS
+ pass = False
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Override Preload Pass",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Override Preload Pass",
+ "status" : "READY"
+ }
+ ]
+}
+
+[root "Root Override Preload Fail"]
+ subtask = Subtask Override Preload Fail
+
+[task "Subtask Override Preload Fail"]
+ preload-task = Subtask FAIL
+ fail = False
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Override Preload Fail",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Override Preload Fail",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root Append Preloaded Subtasks"]
+ subtask = Subtask Append Preloaded Subtasks
+
+[task "Subtask Append Preloaded Subtasks"]
+ preload-task = Subtask READY
+ subtask = Subtask APPLICABLE
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Append Preloaded Subtasks",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Append Preloaded Subtasks",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask APPLICABLE",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root Preload Optional"]
+ subtask = Subtask Preload Optional
+[task "Subtask Preload Optional"]
+ preload-task = Missing | Subtask PASS
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Preload Optional",
+ "status" : "PASS",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask Preload Optional",
+ "status" : "PASS"
+ }
+ ]
+}
+
+[root "Root Preload Properties"]
+ subtask = Subtask Preload Properties
+
+[task "Subtask Preload Properties"]
+ preload-task = Subtask Properties Hints
+ set-fourth-property = fourth-value
+ fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Root Preload Properties",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
+ "name" : "Subtask Preload Properties",
+ "status" : "FAIL"
+ }
+ ]
+}
+
+[root "Root INVALID Preload"]
+ preload-task = missing
+
+{
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+}
+
+[root "INVALIDS"]
+ subtasks-file = invalids.config
+
+{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "INVALIDS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "No PASS criteria",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "WAITING (subtask duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad PASS query",
+ "status" : "FAIL" # Only Test Suite: all
+ "status" : "INVALID" # Only Test Suite: !all
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad FAIL query",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad INPROGRESS query",
+ "status" : "FAIL" # Only Test Suite: all
+ "status" : "INVALID" # Only Test Suite: !all
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Looping",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "duplicate",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes invalid)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory changes loop)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change2_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+[root "Root NA Pass"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ pass = True
+
+{
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "Root NA Pass",
+ "status" : "PASS"
+}
+
+[root "Root NA Fail"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ fail = True
+
+{
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "Root NA Fail",
+ "status" : "FAIL"
+}
+
+[root "NA INVALIDS"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ subtasks-file = invalids.config
+
+{
+ "applicable" : false,
+ "hasPass" : false,
+ "name" : "NA INVALIDS",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "No PASS criteria",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "WAITING (subtask duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Grouping WAITING (subtask missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask INVALID",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad PASS query",
+ "status" : "FAIL" # Only Test Suite: all
+ "status" : "INVALID" # Only Test Suite: !all
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad FAIL query",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : false,
+ "hasPass" : true,
+ "name" : "NA Bad INPROGRESS query",
+ "status" : "FAIL" # Only Test Suite: all
+ "status" : "INVALID" # Only Test Suite: !all
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Looping",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory type INVALID)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory duplicate)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "duplicate",
+ "status" : "FAIL"
+ },
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes type missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes missing)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (names-factory changes invalid)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "task (tasks-factory changes loop)",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change1_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "_change2_number",
+ "status" : "FAIL",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+```
+
+`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "file task/common.config PASS"]
+ applicable = is:open
+ pass = is:open
+
+[task "file task/common.config FAIL"]
+ applicable = is:open
+ fail = is:open
+```
+
+`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "No PASS criteria"]
+ fail-hint = Invalid without Pass criteria and without subtasks
+
+[task "WAITING (subtask INVALID)"]
+ pass = is:open
+ subtask = Subtask INVALID
+
+[task "WAITING (subtask duplicate)"]
+ subtask = Subtask INVALID
+ subtask = Subtask INVALID
+
+[task "WAITING (subtask missing)"]
+ pass = is:open
+ subtask = MISSING # security bug: subtask name appears in output
+
+[task "Grouping WAITING (subtask INVALID)"]
+ subtask = Subtask INVALID
+
+[task "Grouping WAITING (subtask missing)"]
+ subtask = MISSING # security bug: subtask name appears in output
+
+[task "Subtask INVALID"]
+ fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
+
+[task "Subtask Optional"]
+ subtask = MISSING | MISSING
+
+[task "NA Bad PASS query"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ fail = True
+ pass = has:bad
+
+[task "NA Bad FAIL query"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ pass = True
+ fail = has:bad
+
+[task "NA Bad INPROGRESS query"]
+ applicable = NOT is:open # Assumes test query is "is:open"
+ fail = True
+ in-progress = has:bad
+
+[task "Looping"]
+ subtask = Looping
+
+[task "Looping Properties"]
+ set-A = ${B}
+ set-B = ${A}
+ fail = True
+
+[task "task (tasks-factory missing)"]
+ subtasks-factory = missing
+
+[task "task (names-factory type missing)"]
+ subtasks-factory = tasks-factory (names-factory type missing)
+
+[task "task (names-factory type INVALID)"]
+ subtasks-factory = tasks-factory (names-factory type INVALID)
+
+[task "task (names-factory duplicate)"]
+ subtasks-factory = tasks-factory (names-factory duplicate)
+
+[task "task (names-factory changes type missing)"]
+ subtasks-factory = tasks-factory change (names-factory type missing)
+
+[task "task (names-factory changes missing)"]
+ subtasks-factory = tasks-factory change (names-factory changes missing)
+
+[task "task (names-factory changes invalid)"]
+ subtasks-factory = tasks-factory change (names-factory changes invalid)
+
+[task "task (tasks-factory changes loop)"]
+ subtasks-factory = tasks-factory change loop
+
+[tasks-factory "tasks-factory (names-factory type missing)"]
+ names-factory = names-factory (type missing)
+ fail = True
+
+[tasks-factory "tasks-factory (names-factory type INVALID)"]
+ names-factory = name-factory (type INVALID)
+
+[tasks-factory "tasks-factory (names-factory duplicate)"]
+ names-factory = names-factory duplicate
+ fail = True
+
+[tasks-factory "tasks-factory change (names-factory type missing)"]
+ names-factory = names-factory change list (type missing)
+ fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes missing)"]
+ names-factory = names-factory change list (changes missing)
+ fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes invalid)"]
+ names-factory = names-factory change list (changes invalid)
+ fail = True
+
+[tasks-factory "tasks-factory change loop"]
+ names-factory = names-factory change constant
+ subtask = task (tasks-factory changes loop)
+ fail = True
+
+[names-factory "names-factory (type missing)"]
+ name = no type test
+
+[names-factory "names-factory change list (type missing)"]
+ changes = change:_change1_number OR change:_change2_number
+
+[names-factory "names-factory (type INVALID)"]
+ name = invalid type test
+ type = invalid
+
+[names-factory "names-factory duplicate"]
+ name = duplicate
+ name = duplicate
+ type = static
+
+[names-factory "names-factory change list (changes missing)"]
+ type = change
+
+[names-factory "names-factory change list (changes invalid)"]
+ change = change:invalidChange
+ type = change
+
+[names-factory "names-factory change constant"]
+ changes = change:_change1_number OR change:_change2_number
+ type = change
+
+```
+
+`task/special.config` file in project `All-Users` on ref `refs/users/self`.
+
+```
+[task "userfile task/special.config PASS"]
+ applicable = is:open
+ pass = is:open
+
+[task "userfile task/special.config FAIL"]
+ applicable = is:open
+ fail = is:open
+```
diff --git a/test/all b/test/all
deleted file mode 100644
index 4832bba..0000000
--- a/test/all
+++ /dev/null
@@ -1,1134 +0,0 @@
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "Root N/A",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root APPLICABLE",
- "status" : "PASS",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask APPLICABLE",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root FAIL",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root straight PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root straight FAIL",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root PASS-fail",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root pass-FAIL",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root PASS-waiting-fail",
- "status" : "PASS",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root pass-WAITING-fail",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root pass-waiting-FAIL",
- "status" : "FAIL",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root grouping PASS (subtask PASS)",
- "status" : "PASS",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root grouping WAITING (subtask READY)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root grouping WAITING (subtask FAIL)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root grouping NA (subtask NA)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "Subtask NA",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "You must now run the ready task",
- "name" : "Root READY (subtask PASS)",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root WAITING (subtask READY)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root WAITING (subtask FAIL)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "inProgress" : true,
- "name" : "Root IN PROGRESS",
- "status" : "READY"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "inProgress" : false,
- "name" : "Root NOT IN PROGRESS",
- "status" : "READY"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root Optional subtasks",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask FAIL",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask READY",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks File",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "file task/common.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "file task/common.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks File (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "file task/common.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "file task/common.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External (User Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External (File Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root tasks-factory",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "my a task",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "my b task",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "my c task",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root tasks-factory static (empty name)"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root tasks-factory static (empty name PASS)",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "exported" : {
- "root" : "Root Properties"
- },
- "hasPass" : true,
- "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "Root Properties",
- "status" : "FAIL",
- "subTasks" : [
- {
- "applicable" : true,
- "exported" : {
- "subtask" : "Subtask Properties"
- },
- "hasPass" : false,
- "name" : "Subtask Properties",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
- "name" : "Subtask Properties Hints",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Chained Subtask Properties",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Properties Reset",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "_change3_number",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
- "name" : "_change1_number",
- "status" : "FAIL"
- }
- ]
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root Preload",
- "status" : "FAIL",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload Preload",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "Task is ready",
- "name" : "Subtask Preload Hints PASS",
- "status" : "READY"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "Task failed",
- "name" : "Subtask Preload Hints FAIL",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload Override Pass",
- "status" : "READY"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload Override Fail",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload Extend Subtasks",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask APPLICABLE",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask Preload Optional",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
- "name" : "Subtask Preload Properties",
- "status" : "FAIL"
- }
- ]
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "FAIL"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "duplicate",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "Root NA Pass",
- "status" : "PASS"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "Root NA Fail",
- "status" : "FAIL"
- },
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "NA INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "FAIL"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "duplicate",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
diff --git a/test/check_task_statuses.sh b/test/check_task_statuses.sh
index beff75a..5b7e161 100755
--- a/test/check_task_statuses.sh
+++ b/test/check_task_statuses.sh
@@ -1,4 +1,18 @@
-#!/bin/bash
+#!/usr/bin/env bash
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
# Usage:
# All-Projects.git - must have 'Push' rights on refs/meta/config
@@ -15,6 +29,120 @@
fi
}
+# output must match expected to pass
+result_out() { # test expected actual
+ local name=$1 expected=$2 actual=$3
+
+ [ "$expected" = "$actual" ]
+ result "$name" "$(diff <(echo "$expected") <(echo "$actual"))"
+}
+
+result_root() { # group root expected_file actual_file
+ local name="$1 - $(echo "$2" | sed -es'/Root //')"
+ result_out "$name" "$(get_root "$2" < "$3")" "$(get_root "$2" < "$4")"
+}
+
+# -------- Git Config
+
+config() { git config -f "$CONFIG" "$@" ; } # [args]...
+config_section_keys() { # section > keys ...
+ # handlers.handler-filter filter.sh -> handler-filter
+ config -l --name-only |\
+ grep "^$1\." | \
+ sed -es"/^$1\.//;s/\..*$//" |\
+ awk '$0 != prev ; {prev = $0}'
+}
+
+# -------- Pre JSON --------
+#
+# pre_json is a "templated json" used in the test docs to express test results. It looks
+# like json but has some extra comments to express when a certain output should be used.
+# These comments look like: "# Only Test Suite: <suite>"
+#
+
+remove_suite() { # suite < pre_json > json
+ grep -v "# Only Test Suite: $1" | \
+ sed -e's/# Only Test Suite:.*$//; s/ *$//'
+}
+
+remove_not_suite() { remove_suite !"$1" ; } # suite < pre_json > json
+
+# -------- Test Doc Format --------
+#
+# Test Doc Format has intermixed git config task definitions with json roots. This
+# makes it easy to define tests close to their outputs. Be aware that all of the
+# config will get consolidated into a single file, so non root config will be shared
+# amongst all the roots.
+#
+
+# Sample Test Doc for 2 roots:
+#
+# [root "Root PASS"]
+# pass = True
+#
+# {
+# "applicable" : true,
+# "hasPass" : true,
+# "name" : "Root PASS",
+# "status" : "PASS"
+# }
+#
+# [root "Root FAIL"]
+# fail = True
+#
+# {
+# <other root>
+# }
+
+# Strip the json from Test Doc formatted text. For the sample above, the output would be:
+#
+# [root "Root PASS"]
+# pass = True
+#
+# [root "Root FAIL"]
+# fail = True
+# ...
+#
+testdoc_2_cfg() { awk '/^\{/,/^$/ { next } ; 1' ; } # testdoc_format > task_config
+
+# Strip the git config from Test Doc formatted text. For the sample above, the output would be:
+#
+# { "plugins" : [
+# { "name" : "task",
+# "roots" : [
+# {
+# "applicable" : true,
+# "hasPass" : true,
+# "name" : "Root PASS",
+# "status" : "PASS"
+# },
+# {
+# <other root>
+# },
+# ...
+# }
+testdoc_2_pjson() { # < testdoc_format > pjson_task_roots
+ awk 'BEGIN { print "{ \"plugins\" : [ { \"name\" : \"task\", \"roots\" : [" }; \
+ /^\{/ { open=1 }; \
+ open && end { print "}," ; end=0 }; \
+ /^\}/ { open=0 ; end=1 }; \
+ open; \
+ END { print "}]}]}" }'
+}
+
+# ---- JSON PARSING ----
+
+json_pp() { # < json > json
+ python -c "import sys, json; \
+ print json.dumps(json.loads(sys.stdin.read()), indent=3, \
+ separators=(',', ' : '), sort_keys=True)"
+}
+
+json_val_by() { # json index|'key' > value
+ echo "$1" | python -c "import json,sys;print json.load(sys.stdin)[$2]"
+}
+json_val_by_key() { json_val_by "$1" "'$2'" ; } # json key > value
+
# --------
gssh() { ssh -x -p "$PORT" "$SERVER" gerrit "$@" ; } # cmd [args]...
@@ -24,27 +152,55 @@
commit_message() { printf "$1 \n\nChange-Id: $2" ; } # message change-id > commit_msg
+err() { echo "ERROR: $1" >&2 ; exit 1 ; }
+
# Run a test setup command quietly, exit on failure
-q_setup() { # cmd [args...]
- local out ; out=$("$@" 2>&1) || { echo "$out" ; exit ; }
+q_setup() { local out ; out=$("$@" 2>&1) || err "$out" ; } # cmd [args...]
+
+ensure() { "$@" || err "$1 results are not valid" ; } # cmd [args]... < data > data
+
+set_change() { # change_json
+ { CHANGE=("$(json_val_by_key "$1" number)" \
+ "$(json_val_by_key "$1" id)" \
+ "$(json_val_by_key "$1" project)" \
+ "refs/heads/$(json_val_by_key "$1" branch)" \
+ "$(json_val_by_key "$1" status)" \
+ "$(json_val_by_key "$1" topic)") ; } 2> /dev/null
}
-replace_change_properties() { # file change_token change_number change_id project branch status topic
+# change_token change_number change_id project branch status topic < templated_txt > change_txt
+replace_change_properties() {
+ sed -e "s|_change$1_number|$2|g" \
+ -e "s|_change$1_id|$3|g" \
+ -e "s|_change$1_project|$4|g" \
+ -e "s|_change$1_branch|$5|g" \
+ -e "s|_change$1_status|$6|g" \
+ -e "s|_change$1_topic|$7|g"
+}
- sed -i -e "s/_change$2_number/$3/g" \
- -e "s/_change$2_id/$4/g" \
- -e "s/_change$2_project/$5/g" \
- -e "s/_change$2_branch/$6/g" \
- -e "s/_change$2_status/$7/g" \
- -e "s/_change$2_topic/$8/g" "$1"
+replace_default_changes() {
+ replace_change_properties "1" "${CHANGE1[@]}" | replace_change_properties "2" "${CHANGE2[@]}"
}
replace_user() { # < text_with_testuser > text_with_$USER
sed -e"s/testuser/$USER/"
}
+strip_non_applicable() { ensure "$MYDIR"/strip_non_applicable.py ; } # < json > json
+strip_non_invalid() { ensure "$MYDIR"/strip_non_invalid.py ; } # < json > json
+
+get_root() { # root < task_plugin_ouptut > root_json
+ python -c "if True: # NOP to start indent
+ import sys, json
+
+ roots=json.loads(sys.stdin.read())['plugins'][0]['roots']
+ for root in roots:
+ if 'name' in root.keys() and root['name']=='$1':
+ print json.dumps(root, indent=3, separators=(',', ' : '), sort_keys=True)"
+}
+
example() { # example_num
- awk '/```/{Q++;E=(Q+1)/2};E=='"$1" < "$DOC_STATES" | grep -v '```' | replace_user
+ echo "$DOC_STATES" | awk '/```/{Q++;E=(Q+1)/2};E=='"$1" | grep -v '```' | replace_user
}
get_change_num() { # < gerrit_push_response > changenum
@@ -95,31 +251,42 @@
)
}
-query() { # query
- gssh query "$@" \
- --format json | head -1 | python -c "import sys, json; \
- print json.dumps(json.loads(sys.stdin.read()), indent=3, \
- separators=(',', ' : '), sort_keys=True)"
+query_plugins() { # query
+ gssh query "$@" --format json | head -1 | python -c "import sys, json; \
+ plugins={}; plugins['plugins']=json.loads(sys.stdin.read())['plugins']; \
+ print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)"
}
-query_plugins() { query "$@" | awk '$0==" \"plugins\" : [",$0==" ],"' ; }
-
test_tasks() { # name expected_file task_args...
local name=$1 expected=$2 ; shift 2
- local output=$STATUSES.$name
+ local output=$STATUSES.$name out root
query_plugins "$@" > "$output"
- out=$(diff "$expected" "$output")
- result "$name" "$out"
+ echo "$ROOTS" | while read root ; do
+ result_root "$name" "$root" "$expected" "$output"
+ done
+ out=$(diff "$expected" "$output" | head -15)
+ [ -z "$out" ]
+ result "$name - Full Test Suite" "$out"
+}
+
+test_generated() { # name task_args...
+ local name=$1 ; shift
+ test_tasks "$name" "$EXPECTED.$name" "$@"
}
test_file() { # name task_args...
local name=$1 ; shift
- test_tasks "$name" "$MYDIR/$name" "$@"
+ local expected=$MYDIR/$name output=$STATUSES.$name
+
+ query "$@" | awk '$0==" \"plugins\" : [",$0==" ],"' > "$output"
+ out=$(diff "$expected" "$output")
+ result "$name" "$out"
}
-MYDIR=$(dirname "$0")
-DOCS=$MYDIR/.././src/main/resources/Documentation
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+MYDIR=$(dirname -- "$(readlink -f -- "$0")")
+DOCS=$MYDIR/.././src/main/resources/Documentation/test
OUT=$MYDIR/../target/tests
ALL=$OUT/All-Projects
@@ -128,7 +295,7 @@
USERS=$OUT/All-Users
USER_TASKS=$USERS/task
-DOC_STATES=$DOCS/task_states.md
+DOC_PREVIEW=$DOCS/preview.md
EXPECTED=$OUT/expected
STATUSES=$OUT/statuses
@@ -151,54 +318,72 @@
REF_ALL=refs/meta/config
REF_USERS=refs/users/self
-RESULT=0
+CONFIG=$ROOT_CFG
-mkdir -p "$OUT"
+mkdir -p "$OUT" "$ALL_TASKS" "$USER_TASKS"
+
q_setup setup_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
q_setup setup_repo "$USERS" "$REMOTE_USERS" "$REF_USERS" --initial-commit
q_setup setup_repo "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH"
-mkdir -p "$ALL_TASKS" "$USER_TASKS"
+changes=$(gssh query "status:open limit:2" --format json)
+set_change "$(echo "$changes" | awk 'NR==1')" ; CHANGE1=("${CHANGE[@]}")
+set_change "$(echo "$changes" | awk 'NR==2')" ; CHANGE2=("${CHANGE[@]}")
+DOC_STATES=$(replace_default_changes < "$DOCS/task_states.md")
-CHANGES=($(gssh query "status:open limit:2" | grep 'number:' | awk '{print $2}'))
-replace_change_properties "$DOC_STATES" "1" "${CHANGES[0]}"
-replace_change_properties "$DOC_STATES" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/all" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/all" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview.invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview.invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid-applicable" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid-applicable" "2" "${CHANGES[1]}"
+example 2 | replace_user | testdoc_2_cfg > "$ROOT_CFG"
+example 3 > "$COMMON_CFG"
+example 4 > "$INVALIDS_CFG"
+example 5 > "$USER_SPECIAL_CFG"
-example 1 |sed -e"s/current-user/$USER/" > "$ROOT_CFG"
-example 2 > "$COMMON_CFG"
-example 3 > "$INVALIDS_CFG"
-example 4 > "$USER_SPECIAL_CFG"
+ROOTS=$(config_section_keys "root") || err "Invalid ROOTS"
q_setup update_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
q_setup update_repo "$USERS" "$REMOTE_USERS" "$REF_USERS"
-example 5 |tail -n +5| awk 'NR>1{print P};{P=$0}' > "$EXPECTED"
-
change3_id=$(gen_change_id)
change3_number=$(create_repo_change "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH" "$change3_id")
-replace_change_properties "$EXPECTED" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
-replace_change_properties "$MYDIR/all" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
-query="change:$change3_number status:open"
-test_tasks statuses "$EXPECTED" --task--applicable "$query"
-test_file all --task--all "$query"
+all_pjson=$(example 2 | testdoc_2_pjson | \
+ replace_change_properties \
+ "" \
+ "$change3_number" \
+ "$change3_id" \
+ "$PROJECT" \
+ "refs\/heads\/$BRANCH" \
+ "NEW" \
+ "")
-replace_user < "$MYDIR"/root.change > "$ROOT_CFG"
+no_all_json=$(echo "$all_pjson" | remove_suite all)
+
+echo "$no_all_json" | strip_non_applicable | \
+ grep -v "\"applicable\" :" > "$EXPECTED".applicable
+
+echo "$all_pjson" | remove_not_suite all | ensure json_pp > "$EXPECTED".all
+
+echo "$no_all_json" | strip_non_invalid > "$EXPECTED".invalid
+
+strip_non_invalid < "$EXPECTED".applicable > "$EXPECTED".invalid-applicable
+
+
+preview_pjson=$(testdoc_2_pjson < "$DOC_PREVIEW" | replace_default_changes)
+echo "$preview_pjson" | remove_suite invalid | ensure json_pp > "$EXPECTED".preview
+echo "$preview_pjson" | remove_not_suite invalid | strip_non_invalid > "$EXPECTED".preview-invalid
+
+testdoc_2_cfg < "$DOC_PREVIEW" | replace_user > "$ROOT_CFG"
cnum=$(create_repo_change "$ALL" "$REMOTE_ALL" "$REF_ALL")
-test_file preview --task--preview "$cnum,1" --task--all "$query"
-test_file preview.invalid --task--preview "$cnum,1" --task--invalid "$query"
+PREVIEW_ROOTS=$(config_section_keys "root")
-test_file invalid --task--invalid "$query"
-test_file invalid-applicable --task--applicable --task--invalid "$query"
+RESULT=0
+query="change:$change3_number status:open"
+test_generated applicable --task--applicable "$query"
+test_generated all --task--all "$query"
+
+test_generated invalid --task--invalid "$query"
+test_generated invalid-applicable --task--applicable --task--invalid "$query"
+
+ROOTS=$PREVIEW_ROOTS
+test_generated preview --task--preview "$cnum,1" --task--all "$query"
+test_generated preview-invalid --task--preview "$cnum,1" --task--invalid "$query"
exit $RESULT
diff --git a/test/docker/run.sh b/test/docker/run.sh
index 9c1f5d9..a57780b 100755
--- a/test/docker/run.sh
+++ b/test/docker/run.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-readlink --canonicalize / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
MYDIR=$(dirname -- "$(readlink -f -- "$0")")
ARTIFACTS=$MYDIR/gerrit/artifacts
@@ -85,8 +85,7 @@
usage "$MISSING, did you forget --task-plugin-jar?"
fi
[ -n "$GERRIT_WAR" ] && cp -f "$GERRIT_WAR" "$ARTIFACTS/gerrit.war"
-progress "Building docker images" build_images
-run_task_plugin_tests ; RESULT=$?
-cleanup
-
-exit "$RESULT"
+( trap cleanup EXIT SIGTERM
+ progress "Building docker images" build_images
+ run_task_plugin_tests
+)
diff --git a/test/docker/run_tests/wait-for-it.sh b/test/docker/run_tests/wait-for-it.sh
index d7b6e3c..17436f2 100755
--- a/test/docker/run_tests/wait-for-it.sh
+++ b/test/docker/run_tests/wait-for-it.sh
@@ -2,7 +2,7 @@
# https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh
# Use this script to test if a given TCP host/port are available
-cmdname=$(basename $0)
+cmdname=$(basename -- "$0")
echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
diff --git a/test/invalid b/test/invalid
deleted file mode 100644
index 5b5bc32..0000000
--- a/test/invalid
+++ /dev/null
@@ -1,559 +0,0 @@
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "Root N/A",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Root grouping NA (subtask NA)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "Subtask NA",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External (User Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "NA INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
diff --git a/test/invalid-applicable b/test/invalid-applicable
deleted file mode 100644
index 369ac47..0000000
--- a/test/invalid-applicable
+++ /dev/null
@@ -1,244 +0,0 @@
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "hasPass" : false,
- "name" : "Subtasks External (Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtasks External (User Missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "INVALIDS",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
diff --git a/test/preview b/test/preview
deleted file mode 100644
index 235eaca..0000000
--- a/test/preview
+++ /dev/null
@@ -1,570 +0,0 @@
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "INVALIDS Preview",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "FAIL"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "duplicate",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Root PASS Preview",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "hint" : "You must now run the ready task",
- "name" : "Root READY (subtask PASS) Preview",
- "status" : "READY",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "Subtask PASS Preview",
- "status" : "PASS"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtasks External Preview",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config PASS",
- "status" : "PASS"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "userfile task/special.config FAIL",
- "status" : "FAIL"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "Root NA Pass Preview",
- "status" : "PASS"
- },
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "NA INVALIDS Preview",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "FAIL"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "FAIL"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "duplicate",
- "status" : "FAIL"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
diff --git a/test/preview.invalid b/test/preview.invalid
deleted file mode 100644
index 3f0c844..0000000
--- a/test/preview.invalid
+++ /dev/null
@@ -1,511 +0,0 @@
- "plugins" : [
- {
- "name" : "task",
- "roots" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "INVALIDS Preview",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : false,
- "name" : "NA INVALIDS Preview",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "No PASS criteria",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "WAITING (subtask duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Grouping WAITING (subtask missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask INVALID",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Subtask Optional",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad PASS query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad FAIL query",
- "status" : "INVALID"
- },
- {
- "applicable" : false,
- "hasPass" : true,
- "name" : "NA Bad INPROGRESS query",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "Looping",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory type INVALID)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory duplicate)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes type missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes missing)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (names-factory changes invalid)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : false,
- "name" : "task (tasks-factory changes loop)",
- "status" : "WAITING",
- "subTasks" : [
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change1_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- },
- {
- "applicable" : true,
- "hasPass" : true,
- "name" : "_change2_number",
- "status" : "FAIL",
- "subTasks" : [
- {
- "name" : "UNKNOWN",
- "status" : "INVALID"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ],
diff --git a/test/root.change b/test/root.change
deleted file mode 100644
index 99dea09..0000000
--- a/test/root.change
+++ /dev/null
@@ -1,30 +0,0 @@
-[root "INVALIDS Preview"]
- subtasks-file = invalids.config
-
-[root "Root PASS Preview"]
- pass = True
-
-[root "Root READY (subtask PASS) Preview"]
- applicable = is:open
- pass = NOT is:open
- subtask = Subtask PASS Preview
- ready-hint = You must now run the ready task
-
-[root "Subtasks External Preview"]
- subtasks-external = user special Preview
-
-[root "Root NA Pass Preview"]
- applicable = NOT is:open
- pass = True
-
-[root "NA INVALIDS Preview"]
- applicable = NOT is:open
- subtasks-file = invalids.config
-
-[task "Subtask PASS Preview"]
- applicable = is:open
- pass = is:open
-
-[external "user special Preview"]
- user = testuser
- file = special.config
diff --git a/test/strip_non_applicable.py b/test/strip_non_applicable.py
new file mode 100755
index 0000000..1ff097a
--- /dev/null
+++ b/test/strip_non_applicable.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import json
+
+APPLICABLE='applicable'
+HASPASS='hasPass'
+STATUS='status'
+SUBTASKS='subTasks'
+
+def del_non_applicable(tasks):
+ i=0
+ while i < len(tasks):
+ nexti = i + 1
+
+ task=tasks[i]
+ if APPLICABLE in task.keys() and task[APPLICABLE] == False:
+ del tasks[i]
+ nexti = i
+ else:
+ subtasks=[]
+ if SUBTASKS in task.keys():
+ subtasks=task[SUBTASKS]
+ del_non_applicable(subtasks)
+ if SUBTASKS in task.keys() and len(subtasks) == 0:
+ del task[SUBTASKS]
+ if not SUBTASKS in task.keys():
+ if HASPASS in task.keys() and task[HASPASS] == False:
+ status=''
+ if STATUS in task.keys():
+ status = task[STATUS]
+ if status != 'INVALID':
+ del tasks[i]
+ nexti = i
+
+ i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+del_non_applicable(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)
diff --git a/test/strip_non_invalid.py b/test/strip_non_invalid.py
new file mode 100755
index 0000000..dafae15
--- /dev/null
+++ b/test/strip_non_invalid.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import json
+
+STATUS='status'
+SUBTASKS='subTasks'
+
+def keep_invalid(tasks):
+ i=0
+ while i < len(tasks):
+ nexti = i + 1
+
+ task=tasks[i]
+ if SUBTASKS in task.keys():
+ subtasks=task[SUBTASKS]
+ keep_invalid(subtasks)
+ if len(subtasks) == 0:
+ del task[SUBTASKS]
+
+ status=''
+ if STATUS in task.keys():
+ status = task[STATUS]
+ if status != 'INVALID' and not SUBTASKS in task.keys():
+ del tasks[i]
+ nexti = i
+
+ i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+keep_invalid(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)