com.emc.mongoose.scenario.json.step.ForStep Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongoose-scenario-json Show documentation
Show all versions of mongoose-scenario-json Show documentation
Mongoose is a high-load storage performance testing tool
package com.emc.mongoose.scenario.json.step;
import com.emc.mongoose.api.common.exception.OmgShootMyFootException;
import com.emc.mongoose.scenario.ScenarioParseException;
import com.emc.mongoose.ui.config.Config;
import com.emc.mongoose.ui.log.Loggers;
import static com.emc.mongoose.api.common.supply.PatternDefinedSupplier.FORMAT_BRACKETS;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
Created by andrey on 04.06.16.
*/
public final class ForStep
extends SequentialStep {
public static final String KEY_NODE_IN = "in";
public static final char REPLACE_MARKER_CHAR = '$';
public static final Pattern SEQ_SPEC_PATTERN = Pattern.compile(
"(-?[\\d.]+)(-(-?[\\d.]+)(,([\\d.]+))?)?"
);
private final String replaceMarkerName;
private final List valueSeq;
private final boolean infinite;
public ForStep(final Config appConfig, final Map subTree)
throws ScenarioParseException {
super(appConfig, subTree);
final Object value = subTree.get(KEY_NODE_VALUE);
if(value != null) {
infinite = false;
if(value instanceof Short || value instanceof Integer) {
final int n = (int) value;
replaceMarkerName = null;
valueSeq = new ArrayList(n);
for(int i = 0; i < n; i ++) {
valueSeq.add(i);
}
} else if(value instanceof String) {
final Object seqSpec = subTree.get(KEY_NODE_IN);
if(seqSpec == null) {
// sequence is a number surrounded with quotes?
try {
final int n = Integer.parseInt((String) value);
replaceMarkerName = null;
valueSeq = new ArrayList(n);
for(int i = 0; i < n; i ++) {
valueSeq.add(i);
}
} catch(final NumberFormatException e) {
throw new ScenarioParseException(
"Expected an integer value for the \"value\", but got: \"" + value +
"\""
);
}
} else {
this.replaceMarkerName = (String) value;
if(seqSpec instanceof List) {
// sequence is the json array
this.valueSeq = (List) seqSpec;
} else if(seqSpec instanceof String) {
// sequence is a replacement placeholder
final Matcher m = SEQ_SPEC_PATTERN.matcher((String) seqSpec);
if(!m.matches()) {
throw new ScenarioParseException(
"String \"in\" value \"" + seqSpec +
"\" should match the pattern: \"" + SEQ_SPEC_PATTERN.pattern() +
"\""
);
}
m.reset();
if(m.find()) {
valueSeq = new ArrayList();
double start;
double end = Double.NaN;
double step = Double.NaN;
String t = m.group(1);
if(t != null) {
start = Double.parseDouble(t);
} else {
throw new ScenarioParseException("No start value in the \"in\"");
}
t = m.group(3);
if(t != null) {
end = Double.parseDouble(t);
}
t = m.group(5);
if(t != null) {
step = Double.parseDouble(t);
}
if(Double.isNaN(step)) {
step = 1;
}
if(Double.isNaN(end)) {
end = start;
start = 0;
}
if(start == end) {
if(start == (long) start) {
valueSeq.add((long) start);
} else {
valueSeq.add(start);
}
} else {
if(step <= 0) {
throw new ScenarioParseException("Step value should be > 0");
}
if(start < end) {
Loggers.MSG.info(
"Parsed loop range: {} = {}, {} <= {}, {} += {}",
replaceMarkerName, start, replaceMarkerName, end,
replaceMarkerName, step
);
for(double i = start; i <= end; i += step) {
if(i == (long) i) {
valueSeq.add((long) i);
} else {
valueSeq.add(i);
}
}
} else {
Loggers.MSG.info(
"Parsed loop range: {} = {}, {} => {}, {} -= {}",
replaceMarkerName, start, replaceMarkerName, end,
replaceMarkerName, step
);
for(double i = start; i >= end; i -= step) {
if(i == (long) i) {
valueSeq.add((long) i);
} else {
valueSeq.add(i);
}
}
}
}
} else {
throw new ScenarioParseException(
"String \"in\" value \"" + seqSpec +
"\" should match the pattern: \"" +
SEQ_SPEC_PATTERN.pattern() + "\""
);
}
} else {
throw new ScenarioParseException(
"Unexpected \"in\" value: \"" + seqSpec + "\""
);
}
}
} else {
throw new ScenarioParseException("Unexpected value: \"" + value + "\"");
}
} else {
infinite = true;
valueSeq = null;
replaceMarkerName = null;
}
// calls "appendNewJob", invoking it manually again after "valueSeq" is initialized already
loadSubTree(subTree);
}
@Override
protected void loadSubTree(final Map subTree)
throws ScenarioParseException {
if(infinite) {
super.loadSubTree(subTree);
return;
}
if(valueSeq == null) {
// skip the early invocation from the base class constructor while "valueSeq" is not
// initialized yet
return;
} else if(replaceMarkerName == null) {
for(final Object o : valueSeq) {
super.loadSubTree(subTree);
}
return;
}
final Object nodeConfig = subTree.get(KEY_NODE_CONFIG);
/*if(nodeConfig != null) {
if(nodeConfig instanceof Map) {
localConfig.apply((Map) nodeConfig);
} else {
throw new ScenarioParseException(
"Invalid config node type: \"" + nodeConfig.getClass() + "\""
);
}
}*/
final Object stepsTreeList = subTree.getOrDefault(
KEY_NODE_STEPS, subTree.get(KEY_NODE_JOBS)
);
final String replacePattern = Character.toString(REPLACE_MARKER_CHAR) + FORMAT_BRACKETS[0] +
replaceMarkerName + FORMAT_BRACKETS[1];
Map nextNodeConfig;
try {
if(stepsTreeList != null) {
if(stepsTreeList instanceof List) {
Config childJobConfig;
Map newJobTree;
for(final Object nextValue : valueSeq) {
childJobConfig = localConfig.replace(replacePattern, nextValue);
if(nodeConfig != null) {
nextNodeConfig = Config.replace(
(Map) nodeConfig, replacePattern, nextValue
);
childJobConfig.apply(nextNodeConfig, null);
}
append(
new BasicTaskStep(
() -> Loggers.MSG.info(
"Use next value for \"{}\": {}", replaceMarkerName, nextValue
)
)
);
for(final Object job : (List) stepsTreeList) {
if(job != null) {
if(job instanceof Map) {
newJobTree = findAndSubstitute(
(Map) job, replacePattern, nextValue
);
appendNewJob(newJobTree, childJobConfig);
} else {
throw new ScenarioParseException(
"Invalid job node type: \"" + job.getClass() + "\""
);
}
} else {
throw new ScenarioParseException("job node is null");
}
}
}
} else {
throw new ScenarioParseException(
"Invalid jobs node type: \"" + stepsTreeList.getClass() + "\""
);
}
}
} catch(final OmgShootMyFootException | IOException e) {
throw new ScenarioParseException("Failed to replace the configuration values", e);
}
}
private static Map findAndSubstitute(
final Map srcTree, final String replacePattern, final Object newValue
) {
if(newValue == null) {
return findAndSubstituteWithNull(srcTree, replacePattern);
} else if(newValue instanceof List) {
return findAndSubstituteWithList(srcTree, replacePattern, (List) newValue);
} else {
return findAndSubstituteWith(srcTree, replacePattern, newValue);
}
}
private static Map findAndSubstituteWithNull(
final Map srcTree, final String replacePattern
) {
final Map dstTree = new LinkedHashMap<>();
Object treeNode;
for(final String key : srcTree.keySet()) {
treeNode = srcTree.get(key);
if(treeNode instanceof Map) {
dstTree.put(
key, findAndSubstituteWithNull((Map) treeNode, replacePattern)
);
} else if(treeNode instanceof String) {
if(treeNode.equals(replacePattern)) {
dstTree.put(key, null);
} else {
dstTree.put(key, treeNode);
}
} else if(treeNode instanceof List) {
final List srcListNode = (List) treeNode;
final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy