This is an automated email from the ASF dual-hosted git repository.
likeguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 792ef9797 [type:feature] added expression and replaced some grammar of
${} with expression (#4180)
792ef9797 is described below
commit 792ef97972c00d122a2e13ef17511eae24d11f7b
Author: 愿凌飞 <[email protected]>
AuthorDate: Mon Nov 28 15:42:37 2022 +0800
[type:feature] added expression and replaced some grammar of ${} with
expression (#4180)
* Added mock ${} support SpEL
* implement first idea
* revert old generator
* removed redundancy
* handled exceptions uniformly and added test
* fixed code style
Co-authored-by: xiaoyu <[email protected]>
Co-authored-by: likeguo <[email protected]>
---
.../test/http/combination/MockPluginTest.java | 2 +-
.../plugin/mock/generator/BoolGenerator.java | 12 +-
.../mock/generator/CurrentTimeGenerator.java | 23 +--
.../plugin/mock/generator/EmailGenerator.java | 21 +--
.../plugin/mock/generator/EnStringGenerator.java | 21 ++-
.../plugin/mock/generator/ExpressionGenerator.java | 109 ++++++++++++
.../plugin/mock/generator/GeneratorFactory.java | 42 +++--
.../plugin/mock/generator/PhoneGenerator.java | 19 +--
.../mock/generator/RandomDoubleGenerator.java | 25 ++-
.../plugin/mock/generator/RandomIntGenerator.java | 20 +--
.../plugin/mock/generator/RangeDataGenerator.java | 23 ++-
.../plugin/mock/generator/ZhStringGenerator.java | 23 ++-
.../apache/shenyu/plugin/mock/util/MockUtil.java | 184 +++++++++++++++++++++
...g.apache.shenyu.plugin.mock.generator.Generator | 1 +
.../plugin/mock/generator/ArrayGeneratorTest.java | 8 +-
.../mock/generator/ExpressionGeneratorTest.java | 137 +++++++++++++++
.../mock/generator/GeneratorFactoryTest.java} | 44 +++--
17 files changed, 556 insertions(+), 158 deletions(-)
diff --git
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/MockPluginTest.java
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/MockPluginTest.java
index 79df74178..d39fac765 100644
---
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/MockPluginTest.java
+++
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/MockPluginTest.java
@@ -100,7 +100,7 @@ public class MockPluginTest extends AbstractPluginDataInit {
MockHandle placeholderMockHandler = new MockHandle();
placeholderMockHandler.setHttpStatusCode(200);
- placeholderMockHandler.setResponseContent("{\"number\":${int|10-20}}");
+
placeholderMockHandler.setResponseContent("{\"number\":${expression|#int(10,20)}");
ruleLocalDataList.add(buildRuleLocalData(TEST_PLACEHOLDER_MOCK,
placeholderMockHandler));
return ruleLocalDataList;
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
index 1233bccdb..5149e9f05 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
@@ -17,7 +17,7 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
/**
@@ -25,22 +25,22 @@ import org.apache.shenyu.spi.Join;
*/
@Join
public class BoolGenerator implements Generator<Boolean> {
-
+
@Override
public String getName() {
return "bool";
}
-
+
@Override
public Boolean generate() {
- return RandomUtil.randomInt(0, 1) == 1;
+ return MockUtil.bool();
}
-
+
@Override
public int getParamSize() {
return 0;
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^bool$");
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/CurrentTimeGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/CurrentTimeGenerator.java
index 372c6d71b..bba44f180 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/CurrentTimeGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/CurrentTimeGenerator.java
@@ -17,13 +17,9 @@
package org.apache.shenyu.plugin.mock.generator;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.time.DateTimeException;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
import java.util.List;
/**
@@ -31,11 +27,7 @@ import java.util.List;
*/
@Join
public class CurrentTimeGenerator implements Generator<String> {
-
- private static final String DEFAULT_FORMAT = "YYYY-MM-dd HH:mm:ss";
-
- private static final Logger LOG =
LoggerFactory.getLogger(CurrentTimeGenerator.class);
-
+
private String format;
@Override
@@ -45,14 +37,7 @@ public class CurrentTimeGenerator implements
Generator<String> {
@Override
public String generate() {
- LocalDateTime now = LocalDateTime.now();
- try {
- return DateTimeFormatter.ofPattern(format).format(now);
- } catch (DateTimeException e) {
- LOG.warn("format fail,use default format :{}", DEFAULT_FORMAT);
- return DateTimeFormatter.ofPattern(DEFAULT_FORMAT).format(now);
- }
-
+ return MockUtil.current(format);
}
@Override
@@ -64,8 +49,6 @@ public class CurrentTimeGenerator implements
Generator<String> {
public void initParam(final List<String> params, final String rule) {
if (params.size() >= 1) {
format = params.get(0);
- } else {
- format = DEFAULT_FORMAT;
}
}
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EmailGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EmailGenerator.java
index 9e064ebf2..4e3ea7513 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EmailGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EmailGenerator.java
@@ -17,42 +17,35 @@
package org.apache.shenyu.plugin.mock.generator;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
-import static org.apache.shenyu.plugin.mock.util.RandomUtil.randomInt;
-import static
org.apache.shenyu.plugin.mock.util.RandomUtil.randomLowerLetterString;
-
/**
* Random email address generator.
*/
@Join
public class EmailGenerator implements Generator<String> {
-
- private static final String[] DOMAIN_SUFFIX = {"com", "org", "cn",
"com.cn", "top", "edu", "io"};
-
+
@Override
public String getName() {
return "email";
}
-
+
@Override
public String generate() {
- return String.format("%s@%s.%s",
- randomLowerLetterString(randomInt(5, 10)),
- randomLowerLetterString(randomInt(3, 8)),
- DOMAIN_SUFFIX[randomInt(0, DOMAIN_SUFFIX.length - 1)]);
+ return MockUtil.email();
}
-
+
@Override
public int getParamSize() {
return 0;
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^email$");
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EnStringGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EnStringGenerator.java
index d52e3a0d0..1dc7bcdab 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EnStringGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/EnStringGenerator.java
@@ -17,8 +17,7 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
import java.util.List;
@@ -28,38 +27,38 @@ import java.util.List;
*/
@Join
public class EnStringGenerator implements Generator<String> {
-
+
private int min;
-
+
private int max;
-
+
@Override
public String getName() {
return "zh";
}
-
+
@Override
public String generate() {
- return RandomStringUtils.random(RandomUtil.randomInt(min, max), 5,
129, true, false);
+ return MockUtil.en(min, max);
}
-
+
@Override
public int getParamSize() {
return 1;
}
-
+
@Override
public void initParam(final List<String> params, final String rule) {
String[] range = params.get(0).split("-");
min = Integer.parseInt(range[0]);
max = Integer.parseInt(range[1]);
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^en\\|\\d+-\\d+$");
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ExpressionGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ExpressionGenerator.java
new file mode 100644
index 000000000..8cdcc5364
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ExpressionGenerator.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.shenyu.plugin.mock.generator;
+
+import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
+import org.apache.shenyu.spi.Join;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import java.util.List;
+
+@Join
+public class ExpressionGenerator implements Generator<String> {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ExpressionGenerator.class);
+
+ private static final ExpressionParser PARSER = new SpelExpressionParser();
+
+ private static final EvaluationContext CONTEXT = initContext();
+
+ private String expression;
+
+ @Override
+ public String getName() {
+ return "expression";
+ }
+
+ @Override
+ public String generate() {
+ Object val = PARSER.parseExpression(expression).getValue(CONTEXT);
+ if (val instanceof MockUtil.FormatDouble) {
+ return val.toString();
+ }
+ return JsonUtils.toJson(val);
+ }
+
+ @Override
+ public int getParamSize() {
+ return 1;
+ }
+
+ @Override
+ public void initParam(final List<String> params, final String rule) {
+ expression = params.get(0);
+ }
+
+ @Override
+ public boolean match(final String rule) {
+ return rule.matches("^expression\\|.+");
+ }
+
+ private static EvaluationContext initContext() {
+
+ StandardEvaluationContext context = new StandardEvaluationContext();
+
+ try {
+ registerMockFunction(context, "double", "randomDouble",
double.class, double.class, String[].class);
+
+ registerMockFunction(context, "bool", "bool");
+
+ registerMockFunction(context, "int", "randomInt", int.class,
int.class);
+
+ registerMockFunction(context, "email", "email");
+
+ registerMockFunction(context, "phone", "phone");
+
+ registerMockFunction(context, "zh", "zh", int.class, int.class);
+
+ registerMockFunction(context, "en", "en", int.class, int.class);
+
+ registerMockFunction(context, "oneOf", "oneOf", Object[].class);
+
+ registerMockFunction(context, "current", "current",
String[].class);
+
+ } catch (NoSuchMethodException e) {
+ // It will never happen
+ LOG.error(e.getMessage(), e);
+ }
+ return context;
+ }
+
+ private static void registerMockFunction(final StandardEvaluationContext
context,
+ final String name,
+ final String methodName,
+ final Class<?>... parameterTypes)
throws NoSuchMethodException {
+ context.registerFunction(name,
+ MockUtil.class.getDeclaredMethod(methodName, parameterTypes));
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactory.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactory.java
index ce02e458b..45154d9b2 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactory.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactory.java
@@ -29,24 +29,24 @@ import java.util.regex.Pattern;
* GeneratorFactory.
*/
public final class GeneratorFactory {
-
+
private static final Logger LOG =
LoggerFactory.getLogger(GeneratorFactory.class);
-
+
/**
* If expression parsing fails, the ${} placeholder
* will be replaced with the following.
*/
private static final String ERROR_PARSE = "\"[#ERROR EXPRESSION#]\"";
-
+
/**
* Regular expression to extract rule content.
*/
private static final Pattern RULE_CONTENT_PATTERN = Pattern
.compile("^\\$\\{(.+?)}$", Pattern.MULTILINE);
-
+
private GeneratorFactory() {
}
-
+
/**
* New instance mock data generator.
*
@@ -62,25 +62,31 @@ public final class GeneratorFactory {
}
return null;
}
-
+
private static String generate(final String rule) {
final Matcher matcher = RULE_CONTENT_PATTERN.matcher(rule);
- if (matcher.find()) {
- String ruleContent = matcher.group(1);
- String ruleName = ruleContent.split("\\|")[0];
- Generator<?> generator = newInstance(ruleName, rule);
- if (generator == null || !generator.match(ruleContent)) {
- return rule;
- }
- String[] prefixAndSuffix = generator.getPrefixAndSuffix();
+ if (!matcher.find()) {
+ return rule;
+ }
+
+ String ruleContent = matcher.group(1);
+ String ruleName = ruleContent.split("\\|")[0];
+ Generator<?> generator = newInstance(ruleName, rule);
+ if (generator == null || !generator.match(ruleContent)) {
+ return rule;
+ }
+
+ String[] prefixAndSuffix = generator.getPrefixAndSuffix();
+ try {
generator.parseRule(ruleContent);
Object generateData = generator.generate();
return String.join("", prefixAndSuffix[0],
generateData.toString(), prefixAndSuffix[1]);
- } else {
+ } catch (Exception e) {
+ LOG.error(e.getMessage(), e);
return rule;
}
}
-
+
/**
* replace placeholder in content.
*
@@ -96,13 +102,13 @@ public final class GeneratorFactory {
generateData = ERROR_PARSE;
}
String toString = String.valueOf(generateData);
- placeHolder = placeHolder.replaceAll("([$|{}\\]\\[])", "\\\\$1");
+ placeHolder = placeHolder.replaceAll("([$|{}()\\]\\[])", "\\\\$1");
afterDeal = afterDeal.replaceFirst(placeHolder, toString);
placeHolder = getPlaceholder(afterDeal);
}
return afterDeal;
}
-
+
private static String getPlaceholder(final String rule) {
int start = rule.indexOf("${");
if (start < 0) {
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/PhoneGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/PhoneGenerator.java
index 3008254ec..4edcd1f30 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/PhoneGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/PhoneGenerator.java
@@ -17,7 +17,7 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
/**
@@ -25,32 +25,27 @@ import org.apache.shenyu.spi.Join;
*/
@Join
public class PhoneGenerator implements Generator<String> {
-
+
@Override
public String getName() {
return "phone";
}
-
+
@Override
public String generate() {
- StringBuilder builder = new StringBuilder("1");
- builder.append(RandomUtil.randomInt(3, 9));
- for (int i = 0; i < 9; i++) {
- builder.append(RandomUtil.randomInt(0, 9));
- }
- return builder.toString();
+ return MockUtil.phone();
}
-
+
@Override
public int getParamSize() {
return 0;
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^phone$");
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomDoubleGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomDoubleGenerator.java
index 859f07574..82e4fe6b5 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomDoubleGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomDoubleGenerator.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.plugin.mock.generator;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
import java.util.List;
@@ -27,32 +28,28 @@ import java.util.Objects;
*/
@Join
public class RandomDoubleGenerator implements Generator<String> {
-
+
private Double min;
-
+
private Double max;
-
+
private String format;
-
+
@Override
public String getName() {
return "double";
}
-
+
@Override
public String generate() {
- Double result = (Math.random() * (max - min)) + min;
- if (format != null) {
- return String.format(format, result);
- }
- return String.valueOf(result);
+ return MockUtil.randomDouble(min, max, format).toString();
}
-
+
@Override
public int getParamSize() {
return 1;
}
-
+
@Override
public void initParam(final List<String> params, final String rule) {
String[] range = params.get(0).split("-");
@@ -62,12 +59,12 @@ public class RandomDoubleGenerator implements
Generator<String> {
format = Objects.equals(params.get(1), "") ? null : params.get(1);
}
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^double\\|\\d+(?:\\.\\d+)?-\\d+(?:\\.\\d+)?.*");
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomIntGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomIntGenerator.java
index 3defb223e..d48502c42 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomIntGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RandomIntGenerator.java
@@ -17,7 +17,7 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
import java.util.List;
@@ -27,36 +27,36 @@ import java.util.List;
*/
@Join
public class RandomIntGenerator implements Generator<Integer> {
-
+
private int min;
-
+
private int max;
-
+
@Override
public String getName() {
return "int";
}
-
+
@Override
public Integer generate() {
- return RandomUtil.randomInt(min, max);
+ return MockUtil.randomInt(min, max);
}
-
+
@Override
public int getParamSize() {
return 1;
}
-
+
@Override
public void initParam(final List<String> params, final String rule) {
String[] range = params.get(0).split("-");
min = Integer.parseInt(range[0]);
max = Integer.parseInt(range[1]);
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^int\\|\\d+-\\d+$");
}
-
+
}
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RangeDataGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RangeDataGenerator.java
index 3e957c9b9..60cbbbb09 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RangeDataGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/RangeDataGenerator.java
@@ -17,44 +17,43 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
import java.util.Arrays;
import java.util.List;
-import java.util.stream.Collectors;
/**
* Specify the in-list data generator.
*/
@Join
public class RangeDataGenerator implements Generator<String> {
-
- private List<String> data;
-
+
+ private String[] data;
+
@Override
public String getName() {
return "list";
}
-
+
@Override
public String generate() {
- return data.get(RandomUtil.randomInt(0, data.size() - 1));
+ return MockUtil.oneOf(data).toString();
}
-
+
@Override
public int getParamSize() {
return 0;
}
-
+
@Override
public void initParam(final List<String> params, final String rule) {
String rangeData = params.get(0).replaceAll("\\[(.+)]", "$1");
data = Arrays.stream(rangeData.split("(?<!\\\\),"))
.map(data -> data.replace("\\,", ","))
- .collect(Collectors.toList());
+ .toArray(String[]::new);
}
-
+
@Override
public boolean match(final String rule) {
boolean matches = rule.matches("^list\\|\\[.+]$");
@@ -64,7 +63,7 @@ public class RangeDataGenerator implements Generator<String> {
}
return false;
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ZhStringGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ZhStringGenerator.java
index 996484740..9f6e00668 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ZhStringGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/ZhStringGenerator.java
@@ -17,51 +17,48 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.shenyu.plugin.mock.util.MockUtil;
import org.apache.shenyu.spi.Join;
import java.util.List;
-import java.util.Random;
/**
* Random length Chinese string generator.
*/
@Join
public class ZhStringGenerator implements Generator<String> {
-
+
private int min;
-
+
private int max;
-
+
@Override
public String getName() {
return "zh";
}
-
+
@Override
public String generate() {
- Random random = new Random();
- int len = random.nextInt(max - min - 1) + min;
- return RandomStringUtils.random(len, 0x4e00, 0x9fa5, false, false);
+ return MockUtil.zh(min, max);
}
-
+
@Override
public int getParamSize() {
return 1;
}
-
+
@Override
public void initParam(final List<String> params, final String rule) {
String[] range = params.get(0).split("-");
min = Integer.parseInt(range[0]);
max = Integer.parseInt(range[1]);
}
-
+
@Override
public boolean match(final String rule) {
return rule.matches("^zh\\|\\d+-\\d+$");
}
-
+
@Override
public String[] getPrefixAndSuffix() {
return new String[]{"\"", "\""};
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/util/MockUtil.java
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/util/MockUtil.java
new file mode 100644
index 000000000..083be1e92
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/util/MockUtil.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.shenyu.plugin.mock.util;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.shenyu.plugin.mock.generator.CurrentTimeGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.DateTimeException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+import java.util.Random;
+
+import static
org.apache.shenyu.plugin.mock.util.RandomUtil.randomLowerLetterString;
+
+public class MockUtil {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(CurrentTimeGenerator.class);
+
+ private static final String DEFAULT_FORMAT = "YYYY-MM-dd HH:mm:ss";
+
+ private static final String[] DOMAIN_SUFFIX = {"com", "org", "cn",
"com.cn", "top", "edu", "io"};
+
+ /**
+ * Randomly generate Boolean.
+ *
+ * @return Boolean
+ */
+ public static Boolean bool() {
+ return RandomUtil.randomInt(0, 1) == 1;
+ }
+
+ /**
+ * Randomly generate int in the specified range.
+ *
+ * @param min min
+ * @param max max
+ * @return int
+ */
+ public static int randomInt(final int min, final int max) {
+ return RandomUtil.randomInt(min, max);
+ }
+
+ /**
+ * Randomly generate Double in the specified range.
+ *
+ * @param min min
+ * @param max max
+ * @param format format
+ * @return formatDouble
+ */
+ public static FormatDouble randomDouble(final double min, final double
max, final String... format) {
+
+ Double result = (Math.random() * (max - min)) + min;
+ if (format != null && format.length != 0) {
+ return new FormatDouble(result, format[0]);
+ }
+ return new FormatDouble(result);
+ }
+
+ /**
+ * Randomly generate email.
+ *
+ * @return email
+ */
+ public static String email() {
+ return String.format("%s@%s.%s",
+ randomLowerLetterString(randomInt(5, 10)),
+ randomLowerLetterString(randomInt(3, 8)),
+ DOMAIN_SUFFIX[randomInt(0, DOMAIN_SUFFIX.length - 1)]);
+ }
+
+ /**
+ * Randomly generate phone.
+ *
+ * @return phone
+ */
+ public static String phone() {
+ StringBuilder builder = new StringBuilder("1");
+ builder.append(RandomUtil.randomInt(3, 9));
+ for (int i = 0; i < 9; i++) {
+ builder.append(RandomUtil.randomInt(0, 9));
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Randomly generate Chinese string.
+ *
+ * @param min min
+ * @param max max
+ * @return chinese string
+ */
+ public static String zh(final int min, final int max) {
+ Random random = new Random();
+ int len = random.nextInt(max - min - 1) + min;
+ return RandomStringUtils.random(len, 0x4e00, 0x9fa5, false, false);
+ }
+
+ /**
+ * Randomly generate English string.
+ *
+ * @param min min
+ * @param max max
+ * @return english string
+ */
+ public static String en(final int min, final int max) {
+ return RandomStringUtils.random(RandomUtil.randomInt(min, max), 5,
129, true, false);
+ }
+
+ /**
+ * Randomly generate item of data.
+ *
+ * @param data data
+ * @return item
+ */
+ public static Object oneOf(final Object... data) {
+ return data[RandomUtil.randomInt(0, data.length - 1)];
+ }
+
+ /**
+ * Generate current time.
+ *
+ * @param formats formats
+ * @return time
+ */
+ public static String current(final String... formats) {
+ String format = DEFAULT_FORMAT;
+ if (Objects.nonNull(formats) && formats.length != 0 &&
Objects.nonNull(formats[0])) {
+ format = formats[0];
+ }
+ LocalDateTime now = LocalDateTime.now();
+ try {
+ return DateTimeFormatter.ofPattern(format).format(now);
+ } catch (DateTimeException e) {
+ LOG.warn("format fail,use default format :{}", DEFAULT_FORMAT);
+ return DateTimeFormatter.ofPattern(DEFAULT_FORMAT).format(now);
+ }
+
+ }
+
+ public static class FormatDouble {
+
+ private final Double val;
+
+ private final String format;
+
+ public FormatDouble(final Double val, final String format) {
+ this.val = val;
+ this.format = format;
+ }
+
+ public FormatDouble(final Double val) {
+ this.val = val;
+ this.format = null;
+ }
+
+ @Override
+ public String toString() {
+ if (Objects.isNull(format)) {
+ return val.toString();
+ }
+ return String.format(format, val);
+ }
+ }
+
+}
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.mock.generator.Generator
b/shenyu-plugin/shenyu-plugin-mock/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.mock.generator.Generator
index fb1b6fd52..0e3f8b9ec 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.mock.generator.Generator
+++
b/shenyu-plugin/shenyu-plugin-mock/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.mock.generator.Generator
@@ -24,4 +24,5 @@ int=org.apache.shenyu.plugin.mock.generator.RandomIntGenerator
list=org.apache.shenyu.plugin.mock.generator.RangeDataGenerator
zh=org.apache.shenyu.plugin.mock.generator.ZhStringGenerator
array=org.apache.shenyu.plugin.mock.generator.ArrayGenerator
+expression=org.apache.shenyu.plugin.mock.generator.ExpressionGenerator
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ArrayGeneratorTest.java
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ArrayGeneratorTest.java
index 852cf4a01..451510ccb 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ArrayGeneratorTest.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ArrayGeneratorTest.java
@@ -19,9 +19,9 @@ package org.apache.shenyu.plugin.mock.generator;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* The test case for {@link ArrayGenerator}.
@@ -42,6 +42,10 @@ public final class ArrayGeneratorTest {
arrayGenerator.parseRule("array|{\"ints\":${array|10|3}}|3");
String generate = arrayGenerator.generate();
assertEquals("{\"ints\":[10,10,10]},{\"ints\":[10,10,10]},{\"ints\":[10,10,10]}",
generate);
+
+ arrayGenerator.parseRule("array|{\"int\":${expression|#oneOf(10)}}|3");
+ generate = arrayGenerator.generate();
+ assertEquals("{\"int\":10},{\"int\":10},{\"int\":10}", generate);
}
@Test
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ExpressionGeneratorTest.java
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ExpressionGeneratorTest.java
new file mode 100644
index 000000000..1a0df96c8
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/ExpressionGeneratorTest.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.shenyu.plugin.mock.generator;
+
+import org.apache.shenyu.common.utils.JsonUtils;
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDate;
+import java.util.Arrays;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.in;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.hamcrest.Matchers.matchesRegex;
+import static org.hamcrest.Matchers.oneOf;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class ExpressionGeneratorTest {
+
+ private final ExpressionGenerator generator = new ExpressionGenerator();
+
+ @Test
+ public void testGenerate() {
+
+ generator.parseRule("expression|T(java.time.LocalDate).now()");
+ assertThat(generator.generate(),
is(JsonUtils.toJson(LocalDate.now().toString())));
+
+ generator.parseRule("expression|1==1");
+ assertThat(generator.generate(), is("true"));
+ }
+
+ @Test
+ public void testBoolGenerate() {
+ generator.parseRule("expression|#bool()");
+ String generate = generator.generate();
+ assertThat(generate, in(Arrays.asList("true", "false")));
+
+ }
+
+ @Test
+ public void testCurrentTimeGenerate() {
+ generator.parseRule("expression|#current()");
+ assertTrue(generator.generate().matches("^\"\\d{4}(-\\d{2}){2}
\\d{2}(:\\d{2}){2}\"$"));
+ generator.parseRule("expression|#current('YYYY-MM-dd')");
+ assertTrue(generator.generate().matches("^\"\\d{4}(-\\d{2}){2}\"$"));
+ }
+
+ @Test
+ public void testEmailTimeGenerate() {
+ generator.parseRule("expression|#email()");
+ assertNotNull(generator.generate());
+ }
+
+ @Test
+ public void testEnStringGenerate() {
+ int max = 10;
+ int min = 5;
+ generator.parseRule(String.format("expression|#en(%d,%d)", min, max));
+ String enString = generator.generate();
+ assertThat(enString, matchesRegex("\"[a-zA-Z]{" + min + "," + max +
"}\""));
+ }
+
+ @Test
+ public void testPhoneGenerate() {
+ generator.parseRule("expression|#phone()");
+ String phone = generator.generate();
+ assertTrue(phone.matches("^\"1[3-9]\\d{9}\"$"));
+ }
+
+ @Test
+ public void testRandomDoubleGenerate() {
+ double min = 10.5;
+ double max = 12.0;
+ generator.parseRule(String.format("expression|#double(%f,%f)", min,
max));
+ String doubleValue = generator.generate();
+ assertThat(Double.valueOf(doubleValue),
allOf(greaterThanOrEqualTo(min), lessThanOrEqualTo(max)));
+
+ generator.parseRule("expression|#double(10.5,12.0,'¥%.2f')");
+ doubleValue = generator.generate();
+ assertThat(Double.valueOf(doubleValue.substring(1)),
allOf(greaterThanOrEqualTo(min), lessThanOrEqualTo(max)));
+ assertThat(doubleValue, matchesRegex("^¥\\d+.\\d{2}$"));
+ }
+
+ @Test
+ public void testRandomIntGenerate() {
+ int min = 10;
+ int max = 15;
+ generator.parseRule(String.format("expression|#int(%d,%d)", min, max));
+ String val = generator.generate();
+ assertThat(Integer.valueOf(val), allOf(greaterThanOrEqualTo(min),
lessThanOrEqualTo(max)));
+ }
+
+ @Test
+ public void testRandomDataGenerate() {
+
+ generator.parseRule("expression|#oneOf('shenyu','number',1)");
+ String val = generator.generate();
+ assertThat(val, oneOf("\"shenyu\"", "\"number\"", "1"));
+ }
+
+ @Test
+ public void testZhDataGenerate() {
+
+ int minLength = 10;
+ int maxLength = 20;
+ generator.parseRule(String.format("expression|#zh(%d,%d)", minLength,
maxLength));
+ String val = generator.generate();
+ assertThat(val.length(), allOf(greaterThanOrEqualTo(minLength),
lessThanOrEqualTo(maxLength)));
+ }
+
+ @Test
+ public void testMatch() {
+ assertTrue(generator.match("expression|23"));
+ assertFalse(generator.match("expression"));
+ assertFalse(generator.match("expression|"));
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactoryTest.java
similarity index 51%
copy from
shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
copy to
shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactoryTest.java
index 1233bccdb..e0ccd3854 100644
---
a/shenyu-plugin/shenyu-plugin-mock/src/main/java/org/apache/shenyu/plugin/mock/generator/BoolGenerator.java
+++
b/shenyu-plugin/shenyu-plugin-mock/src/test/java/org/apache/shenyu/plugin/mock/generator/GeneratorFactoryTest.java
@@ -17,32 +17,26 @@
package org.apache.shenyu.plugin.mock.generator;
-import org.apache.shenyu.plugin.mock.util.RandomUtil;
-import org.apache.shenyu.spi.Join;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
-/**
- * Boolean Generator.
- */
-@Join
-public class BoolGenerator implements Generator<Boolean> {
-
- @Override
- public String getName() {
- return "bool";
- }
-
- @Override
- public Boolean generate() {
- return RandomUtil.randomInt(0, 1) == 1;
- }
-
- @Override
- public int getParamSize() {
- return 0;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.matchesRegex;
+
+public class GeneratorFactoryTest {
+
+ @Test
+ public void testDealRule() {
+ String dealedContent = GeneratorFactory.dealRule("${phone}");
+ assertThat(dealedContent, matchesRegex("^\"1[3-9]\\d{9}\"$"));
}
-
- @Override
- public boolean match(final String rule) {
- return rule.matches("^bool$");
+
+ @ParameterizedTest
+ @ValueSource(strings = {"${expression|(sdxc}", "${wrong_rule|123}"})
+ public void testDealRuleWithWrongContent(final String content) {
+ String dealedContent = GeneratorFactory.dealRule(content);
+ assertThat(dealedContent, is("\"[#ERROR EXPRESSION#]\""));
}
}