From 571b0f34f282d37b07118fec9b54ad5fc2271106 Mon Sep 17 00:00:00 2001 From: sahankj2000 Date: Tue, 30 Apr 2024 12:15:13 +0530 Subject: [PATCH] Adding Changes --- .../cli/NBCLIScenarioPreprocessorTest.java | 37 +++++++++++- .../scenarios/NBCLIScenarioPreprocessor.java | 58 ++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/nb-engine/nb-engine-cli/src/test/java/io/nosqlbench/engine/cli/NBCLIScenarioPreprocessorTest.java b/nb-engine/nb-engine-cli/src/test/java/io/nosqlbench/engine/cli/NBCLIScenarioPreprocessorTest.java index bb9b02156..563733d94 100644 --- a/nb-engine/nb-engine-cli/src/test/java/io/nosqlbench/engine/cli/NBCLIScenarioPreprocessorTest.java +++ b/nb-engine/nb-engine-cli/src/test/java/io/nosqlbench/engine/cli/NBCLIScenarioPreprocessorTest.java @@ -130,7 +130,7 @@ public class NBCLIScenarioPreprocessorTest { "driver", "stdout", "labels", "workload:scenario_test,scenario:schema_only", "step", "schema", - "tags", "block:\"schema.*\"", + "tags", "block:schema.*", "workload", "scenario_test" )); NBCLIOptions opts1 = new NBCLIOptions(new String[]{"scenario_test", "schema_only", "doundef=20"}, NBCLIOptions.Mode.ParseAllOptions); @@ -185,7 +185,7 @@ public class NBCLIScenarioPreprocessorTest { "driver", "stdout", "labels", "workload:scenario_test,scenario:schema_only", "step", "schema", - "tags", "block:\"schema.*\"", + "tags", "block:schema.*", "workload", "scenario_test" )); NBCLIOptions opts1 = new NBCLIOptions(new String[]{"example_scenarios", "namedsteps.one", "testparam1=testvalue2"}, NBCLIOptions.Mode.ParseAllOptions); @@ -201,4 +201,37 @@ public class NBCLIScenarioPreprocessorTest { .isThrownBy(() -> new NBCLIOptions(new String[]{"scenario_test", "duplicate_param"}, NBCLIOptions.Mode.ParseAllOptions)) .withMessageContaining("Duplicate occurrence of parameter \"threads\""); } + + @Test + public void testCommandSplitter() { + String normalCmd = "run driver=stdout tags==block:main-read cycles==10 threads=auto param=test1"; + assertThat(NBCLIScenarioPreprocessor.splitCommand(normalCmd)) + .isEqualTo(List.of("run", "driver=stdout", "tags==block:main-read", "cycles==10", "threads=auto", "param=test1")); + + // param='test1' or pram="test1" -> param=test1 + String quotedParamCmd = "run driver=stdout tags==block:\"main.*\" cycles==10 threads=auto param='test1'"; + assertThat(NBCLIScenarioPreprocessor.splitCommand(quotedParamCmd)) + .isEqualTo(List.of("run", "driver=stdout", "tags==block:main.*", "cycles==10", "threads=auto", "param=test1")); + + // param="test 1" or params='test 1' -> param=test 1 + String paramWithSpaceCmd = "run driver=stdout tags==block:\"main.*\" cycles==10 threads=auto param='test 1'"; + assertThat(NBCLIScenarioPreprocessor.splitCommand(paramWithSpaceCmd)) + .isEqualTo(List.of("run", "driver=stdout", "tags==block:main.*", "cycles==10", "threads=auto", "param=test 1")); + + // param=\"test1\" -> param="test1", param=\'test1\' -> param='test1' + String escapingQuotesParamCmd = "run driver=stdout tags==block:'main.*' cycles==10 threads=auto param=\\\"test1\\\""; + assertThat(NBCLIScenarioPreprocessor.splitCommand(escapingQuotesParamCmd)) + .isEqualTo(List.of("run", "driver=stdout", "tags==block:main.*", "cycles==10", "threads=auto", "param=\"test1\"")); + + // param=test1\\test2 -> param=test1\test2 + String escapingSlashParamCmd = "run driver=stdout tags==block:'main.*' cycles==10 threads=auto param=test1\\\\test2"; + assertThat(NBCLIScenarioPreprocessor.splitCommand(escapingSlashParamCmd)) + .isEqualTo(List.of("run", "driver=stdout", "tags==block:main.*", "cycles==10", "threads=auto", "param=test1\\test2")); + + // param="test1 -> unclosed quote " + String unclosedQuoteCmd = "run driver=stdout tags==block:'main.*' cycles==10 threads=auto param=\"test1"; + assertThatExceptionOfType(BasicError.class) + .isThrownBy(() -> NBCLIScenarioPreprocessor.splitCommand(unclosedQuoteCmd)) + .withMessageContaining("Unclosed double quote found in scenario cmd"); + } } diff --git a/nb-engine/nb-engine-core/src/main/java/io/nosqlbench/engine/api/scenarios/NBCLIScenarioPreprocessor.java b/nb-engine/nb-engine-core/src/main/java/io/nosqlbench/engine/api/scenarios/NBCLIScenarioPreprocessor.java index 25a34a28c..4e47e0d9d 100644 --- a/nb-engine/nb-engine-core/src/main/java/io/nosqlbench/engine/api/scenarios/NBCLIScenarioPreprocessor.java +++ b/nb-engine/nb-engine-core/src/main/java/io/nosqlbench/engine/api/scenarios/NBCLIScenarioPreprocessor.java @@ -252,10 +252,66 @@ public class NBCLIScenarioPreprocessor { private static final Pattern WordAndMaybeAssignment = Pattern.compile("(?\\w[-_\\d\\w.]+)((?=+)(?.+))?"); + public static List splitCommand(String cmd) { + List cmdSplit = new ArrayList<>(); + Stack stack = new Stack<>(); + StringBuilder builder = new StringBuilder(); + for (char c : cmd.toCharArray()) { + switch (c) { + case ' ': + if (!stack.isEmpty() && (stack.peek() == '\'' || stack.peek() == '\"')) { + builder.append(c); + } else if (!builder.isEmpty()) { + cmdSplit.add(builder.toString()); + builder.delete(0, builder.length()); + } + break; + case '\"': + case '\'': + if (!stack.isEmpty()) { + if (stack.peek() == c) { + stack.pop(); + } else if (stack.peek() == '\\') { + stack.pop(); + builder.append(c); + } else { + stack.push(c); + } + } else { + stack.push(c); + } + break; + case '\\': + if (!stack.isEmpty() && stack.peek() == c) { + stack.pop(); + builder.append(c); + } else { + stack.push(c); + } + break; + default: + builder.append(c); + } + } + if (!stack.isEmpty()) { + if (stack.peek() == '\'') { + throw new BasicError("Unclosed single quote found in scenario cmd '" + cmd + "'"); + } else if (stack.peek() == '\"') { + throw new BasicError("Unclosed double quote found in scenario cmd '" + cmd + "'"); + } else { + throw new BasicError("Unused escape character \"\\\" found in scenario cmd '" + cmd + "'"); + } + } + if (!builder.isEmpty()) { + cmdSplit.add(builder.toString()); + } + return cmdSplit; + } + private static LinkedHashMap parseStep(String cmd, String stepName, String scenarioName) { LinkedHashMap parsedStep = new LinkedHashMap<>(); - String[] namedStepPieces = cmd.split(" +"); + List namedStepPieces = splitCommand(cmd); for (String commandFragment : namedStepPieces) { Matcher matcher = WordAndMaybeAssignment.matcher(commandFragment);