diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java index 10785505..1a097408 100644 --- a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/Parameter.java @@ -1,8 +1,14 @@ package org.bench4q.agent.scenario; +import java.util.List; + +import org.bench4q.agent.scenario.dfa.DFA; +import org.bench4q.agent.scenario.dfa.ParamPart; + public class Parameter { private String key; private String value; + private ParamPart[] paramParts; public String getKey() { return key; @@ -20,4 +26,17 @@ public class Parameter { this.value = value; } + public ParamPart[] getParamParts() { + return paramParts; + } + + private void setParamParts(ParamPart[] paramParts) { + this.paramParts = paramParts; + } + + public void compileToGenerateParts() { + List paramParts = DFA.resolveMaltipleParamPart(this + .getValue()); + this.setParamParts(paramParts.toArray(new ParamPart[paramParts.size()])); + } } diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/VUser.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/VUser.java index b5b97877..d085bf06 100644 --- a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/VUser.java +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/VUser.java @@ -153,11 +153,16 @@ public class VUser implements Runnable { private Map prepareBehaviorParameters(Behavior behavior) { Map behaviorParameters = new HashMap(); for (Parameter parameter : behavior.getParameters()) { + compile(parameter.getValue()); behaviorParameters.put(parameter.getKey(), parameter.getValue()); } return behaviorParameters; } + private void compile(String value) { + // TODO: Add the state pattern to this and parse the value + } + private void preparePlugins(Scenario scenario, Map plugins) { for (UsePlugin usePlugin : scenario.getUsePlugins()) { String pluginId = usePlugin.getId(); diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java index 80142d7a..81211001 100644 --- a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/behavior/Behavior.java @@ -59,6 +59,12 @@ public abstract class Behavior { return ""; } + public void compile() { + for (Parameter parameter : this.getParameters()) { + parameter.compileToGenerateParts(); + } + } + public void distillParams(SessionObject session) { for (Parameter parameter : this.getParameters()) { String s = parameter.getValue(); diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/DFA.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/DFA.java new file mode 100644 index 00000000..7c705e71 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/DFA.java @@ -0,0 +1,114 @@ +package org.bench4q.agent.scenario.dfa; + +import java.util.LinkedList; +import java.util.List; + +import org.bench4q.agent.scenario.dfa.ParamPart.ParamPartType; +import org.bench4q.agent.utils.ParameterParser; + +public class DFA { + + public static List resolveMaltipleParamPart( + String paramOriginValue) { + List result; + StringBuilder buf1; + StringBuilder buf2; + int state; + ParamPart part; + char c; + + result = new LinkedList(); + buf1 = new StringBuilder(); + buf2 = new StringBuilder(); + state = 0; + loop: for (int i = 0, len = paramOriginValue.length(); i < len; i++) { + c = paramOriginValue.charAt(i); + switch (state) { + case 0: /* Literal string */ + switch (c) { + case '$': + if (buf1.length() > 0) { + part = new ParamPart(); + part.setType(ParamPartType.STRING); + part.setContentForStringType(buf1.toString()); + result.add(part); + buf1.setLength(0); + } + state = 2; + continue; + default: + buf1.append(c); + continue; + } + // no more state == 1 (irrelevantly used for "escape sequence") + case 2: /* Context call */ + switch (c) { + case '#': + part = new ParamPart(); + part.setType(ParamPartType.SESSION_ID); + result.add(part); + state = 0; + continue; + case '{': + state = 3; + continue; + case '$': /* $$ is the escape sequence for $ */ + buf1.append(c); + state = 0; + continue; + default: /* Syntax error */ + break loop; + } + case 3: /* plugInId */ + switch (c) { + case ':': + state = 4; + continue; + case '{': + break loop; + case '}': /* no ':' means system property */ + part = new ParamPart(); + part.setType(ParamPartType.PROPERTY); + part.setPluginIdForContextCallType(null); + part.setVariableForContextCallAndProperty(ParameterParser + .unescape(buf1.toString())); + result.add(part); + buf1.setLength(0); + state = 0; + continue; + default: + buf1.append(c); + continue; + } + case 4: /* Variable */ + switch (c) { + case '}': + part = new ParamPart(); + part.setType(ParamPartType.CONTEXT_CALL); + part.setPluginIdForContextCallType(ParameterParser + .unescape(buf1.toString())); + part.setVariableForContextCallAndProperty(ParameterParser + .unescape(buf2.toString())); + result.add(part); + buf1.setLength(0); + buf2.setLength(0); + state = 0; + continue; + case '{': /* Syntax error */ + break loop; + default: + buf2.append(c); + continue; + } + } + } + if (state == 0 && buf1.length() > 0) { + part = new ParamPart(); + part.setType(ParamPartType.STRING); + part.setContentForStringType(buf1.toString()); + result.add(part); + } + return result; + } + +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/ParamPart.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/ParamPart.java new file mode 100644 index 00000000..c6cf19e5 --- /dev/null +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/scenario/dfa/ParamPart.java @@ -0,0 +1,65 @@ +package org.bench4q.agent.scenario.dfa; + +public class ParamPart { + public static enum ParamPartType { + STRING, SESSION_ID, CONTEXT_CALL, PROPERTY + } + + private ParamPartType type; + private String contentForStringType; + private String pluginIdForContextCallType; + private String variableForContextCallAndProperty; + + public ParamPartType getType() { + return type; + } + + public void setType(ParamPartType type) { + this.type = type; + } + + public String getContentForStringType() { + return contentForStringType; + } + + public void setContentForStringType(String contentForStringType) { + this.contentForStringType = contentForStringType; + } + + public String getPluginIdForContextCallType() { + return pluginIdForContextCallType; + } + + public void setPluginIdForContextCallType(String pluginIdForContextCallType) { + this.pluginIdForContextCallType = pluginIdForContextCallType; + } + + public String getVariableForContextCallAndProperty() { + return variableForContextCallAndProperty; + } + + public void setVariableForContextCallAndProperty( + String variableForContextCallAndProperty) { + this.variableForContextCallAndProperty = variableForContextCallAndProperty; + } + + @Override + public String toString() { + switch (type) { + case STRING: + return this.contentForStringType; + case SESSION_ID: + return "$#"; + case CONTEXT_CALL: + return "${" + this.pluginIdForContextCallType + ":" + + this.variableForContextCallAndProperty + "}"; + case PROPERTY: + return "${" + this.variableForContextCallAndProperty + "}"; + default: + return "Plug-in parameter part " + this.contentForStringType + "/" + + this.pluginIdForContextCallType + "/" + + this.variableForContextCallAndProperty + + " has an unspecified type " + type.toString(); + } + } +} diff --git a/Bench4Q-Agent/src/main/java/org/bench4q/agent/utils/ParameterParser.java b/Bench4Q-Agent/src/main/java/org/bench4q/agent/utils/ParameterParser.java index ba876655..d45c991b 100644 --- a/Bench4Q-Agent/src/main/java/org/bench4q/agent/utils/ParameterParser.java +++ b/Bench4Q-Agent/src/main/java/org/bench4q/agent/utils/ParameterParser.java @@ -101,7 +101,7 @@ public abstract class ParameterParser { * the string where some characters are escaped by '\' character * @return the unescaped string */ - static String unescape(String value) { + public static String unescape(String value) { StringBuilder result = new StringBuilder(); char c; boolean escape = false; // escape sequence diff --git a/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_DFA.java b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_DFA.java new file mode 100644 index 00000000..8a3e5477 --- /dev/null +++ b/Bench4Q-Agent/src/test/java/org/bench4q/agent/test/scenario/Test_DFA.java @@ -0,0 +1,94 @@ +package org.bench4q.agent.test.scenario; + +import static org.junit.Assert.*; + +import java.util.List; + +import org.bench4q.agent.scenario.dfa.DFA; +import org.bench4q.agent.scenario.dfa.ParamPart; +import org.bench4q.agent.scenario.dfa.ParamPart.ParamPartType; +import org.junit.Test; + +public class Test_DFA { + private static final String TEST_CASE = "${csvProvider0:userName}"; + private static final String TEST_CASE2 = "${csvProvider0:userName}$#"; + private static final String TEST_CASE3 = "${csvProvider0:userName}$#okOrNot"; + private static final String TEST_CASE4 = "${csvProvider0:userName}$#okOrNot${file.separator}"; + + @Test + public void test_resolveMaltipleParamPart_WithOnePluginIdVariable() { + List result = DFA.resolveMaltipleParamPart(TEST_CASE); + assertEquals(1, result.size()); + assertEquals("csvProvider0", result.get(0) + .getPluginIdForContextCallType()); + assertEquals("userName", result.get(0) + .getVariableForContextCallAndProperty()); + assertNull(result.get(0).getContentForStringType()); + } + + @Test + public void test_resolveMaltipleParamPart_WithOnePluginIdVariable_AND_OneSessionID() { + List result = DFA.resolveMaltipleParamPart(TEST_CASE2); + assertEquals(2, result.size()); + assertEquals("csvProvider0", result.get(0) + .getPluginIdForContextCallType()); + assertEquals(ParamPartType.CONTEXT_CALL, result.get(0).getType()); + assertEquals("userName", result.get(0) + .getVariableForContextCallAndProperty()); + assertNull(result.get(0).getContentForStringType()); + assertEquals(ParamPartType.SESSION_ID, result.get(1).getType()); + assertNull(result.get(1).getContentForStringType()); + assertNull(result.get(1).getPluginIdForContextCallType()); + assertNull(result.get(1).getVariableForContextCallAndProperty()); + } + + @Test + public void test_resolveMaltipleParamPart_WithOnePluginIdVariable_AND_OneSessionID_And_PlainString() { + List result = DFA.resolveMaltipleParamPart(TEST_CASE3); + assertEquals(3, result.size()); + assertEquals("csvProvider0", result.get(0) + .getPluginIdForContextCallType()); + assertEquals(ParamPartType.CONTEXT_CALL, result.get(0).getType()); + assertEquals("userName", result.get(0) + .getVariableForContextCallAndProperty()); + assertNull(result.get(0).getContentForStringType()); + + assertEquals(ParamPartType.SESSION_ID, result.get(1).getType()); + assertNull(result.get(1).getContentForStringType()); + assertNull(result.get(1).getPluginIdForContextCallType()); + assertNull(result.get(1).getVariableForContextCallAndProperty()); + + assertEquals(ParamPartType.STRING, result.get(2).getType()); + assertNull(result.get(2).getPluginIdForContextCallType()); + assertNull(result.get(2).getVariableForContextCallAndProperty()); + assertEquals("okOrNot", result.get(2).getContentForStringType()); + } + + @Test + public void test_resolveMaltipleParamPart_WithOnePluginIdVariable_AND_OneSessionID_And_PlainString_AND_Property() { + List result = DFA.resolveMaltipleParamPart(TEST_CASE4); + assertEquals(4, result.size()); + assertEquals("csvProvider0", result.get(0) + .getPluginIdForContextCallType()); + assertEquals(ParamPartType.CONTEXT_CALL, result.get(0).getType()); + assertEquals("userName", result.get(0) + .getVariableForContextCallAndProperty()); + assertNull(result.get(0).getContentForStringType()); + + assertEquals(ParamPartType.SESSION_ID, result.get(1).getType()); + assertNull(result.get(1).getContentForStringType()); + assertNull(result.get(1).getPluginIdForContextCallType()); + assertNull(result.get(1).getVariableForContextCallAndProperty()); + + assertEquals(ParamPartType.STRING, result.get(2).getType()); + assertNull(result.get(2).getPluginIdForContextCallType()); + assertNull(result.get(2).getVariableForContextCallAndProperty()); + assertEquals("okOrNot", result.get(2).getContentForStringType()); + + assertEquals(ParamPartType.PROPERTY, result.get(3).getType()); + assertNull(result.get(3).getPluginIdForContextCallType()); + assertNull(result.get(3).getContentForStringType()); + assertEquals("file.separator", result.get(3) + .getVariableForContextCallAndProperty()); + } +} diff --git a/relative Docs/取参数状态机.vsdx b/relative Docs/取参数状态机.vsdx index 265a8ee6..0604fcf9 100644 Binary files a/relative Docs/取参数状态机.vsdx and b/relative Docs/取参数状态机.vsdx differ