diff --git a/.github/workflows/maven-core-publish.yml b/.github/workflows/maven-core-publish.yml
index ab04855..b936216 100644
--- a/.github/workflows/maven-core-publish.yml
+++ b/.github/workflows/maven-core-publish.yml
@@ -16,10 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set up JDK 11
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: '21'
distribution: 'temurin'
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
diff --git a/.github/workflows/maven-extension-publish.yml b/.github/workflows/maven-extension-publish.yml
index 72af674..f18d0bc 100644
--- a/.github/workflows/maven-extension-publish.yml
+++ b/.github/workflows/maven-extension-publish.yml
@@ -16,10 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set up JDK 11
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: '21'
distribution: 'temurin'
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
diff --git a/.github/workflows/maven-parent-publish.yml b/.github/workflows/maven-parent-publish.yml
index ceee795..1929fea 100644
--- a/.github/workflows/maven-parent-publish.yml
+++ b/.github/workflows/maven-parent-publish.yml
@@ -16,10 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set up JDK 11
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
- java-version: '11'
+ java-version: '21'
distribution: 'temurin'
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
diff --git a/.github/workflows/ut.yml b/.github/workflows/ut.yml
index 902e2bd..b1e01d7 100644
--- a/.github/workflows/ut.yml
+++ b/.github/workflows/ut.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- java-version: [ 8, 11 ]
+ java-version: [21]
steps:
- uses: actions/checkout@v3
- name: "Test for JDK ${{ matrix.java-version }}"
diff --git a/arex-compare-core/pom.xml b/arex-compare-core/pom.xml
index f0c843e..96d5519 100644
--- a/arex-compare-core/pom.xml
+++ b/arex-compare-core/pom.xml
@@ -5,7 +5,7 @@
arex-compare-parent
com.arextest
- 0.2.17
+ 0.2.18
4.0.0
@@ -36,6 +36,10 @@
org.slf4j
slf4j-api
+
+ org.javadelight
+ delight-nashorn-sandbox
+
org.junit.jupiter
junit-jupiter-engine
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/compare/GenericCompare.java b/arex-compare-core/src/main/java/com/arextest/diff/compare/GenericCompare.java
index e6acaa2..0332130 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/compare/GenericCompare.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/compare/GenericCompare.java
@@ -4,6 +4,7 @@
import com.arextest.diff.handler.log.register.LogRegister;
import com.arextest.diff.model.compare.CompareContext;
import com.arextest.diff.model.enumeration.ParentNodeType;
+import com.arextest.diff.model.exception.FindErrorException;
import com.arextest.diff.model.log.NodeEntity;
import com.arextest.diff.utils.IgnoreUtil;
import com.arextest.diff.utils.ListUti;
@@ -12,9 +13,12 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.List;
import java.util.Objects;
+import java.util.logging.Logger;
public class GenericCompare {
+ private static final Logger LOGGER = Logger.getLogger(GenericCompare.class.getName());
+
public static void jsonCompare(Object obj1, Object obj2, CompareContext compareContext)
throws Exception {
@@ -42,6 +46,18 @@ public static void jsonCompare(Object obj1, Object obj2, CompareContext compareC
return;
}
+ // custom compare
+ try {
+ if (ScriptCompare.isScriptComparisonRequired(fuzzyPath, compareContext)) {
+ ScriptCompare.scriptCompare(obj1, obj2, fuzzyPath, compareContext);
+ return;
+ }
+ } catch (FindErrorException e) {
+ throw e;
+ } catch (Exception e) {
+ LOGGER.warning("Script compare error: " + e.getMessage());
+ }
+
// field missing
if (obj1 == null && obj2 == null) {
return;
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/compare/ScriptCompare.java b/arex-compare-core/src/main/java/com/arextest/diff/compare/ScriptCompare.java
new file mode 100644
index 0000000..1b4de76
--- /dev/null
+++ b/arex-compare-core/src/main/java/com/arextest/diff/compare/ScriptCompare.java
@@ -0,0 +1,72 @@
+package com.arextest.diff.compare;
+
+import com.arextest.diff.handler.log.LogMarker;
+import com.arextest.diff.handler.log.register.LogRegister;
+import com.arextest.diff.model.compare.CompareContext;
+import com.arextest.diff.model.enumeration.ParentNodeType;
+import com.arextest.diff.model.exception.FindErrorException;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
+import com.arextest.diff.model.script.ScriptMethodContext;
+import com.arextest.diff.model.script.ScriptSandbox;
+import com.arextest.diff.utils.JacksonHelperUtil;
+import java.util.List;
+import javax.script.ScriptException;
+
+public class ScriptCompare {
+
+ public static boolean isScriptComparisonRequired(List fuzzyPath,
+ CompareContext compareContext) {
+ return compareContext.scriptCompareConfigMap != null
+ && compareContext.scriptCompareConfigMap.containsKey(fuzzyPath);
+ }
+
+ // custom compare
+ public static void scriptCompare(Object obj1, Object obj2, List fuzzyPath,
+ CompareContext compareContext)
+ throws ScriptException, NoSuchMethodException, FindErrorException {
+
+ ScriptMethodContext context = new ScriptMethodContext();
+ context.setBasePath(compareContext.currentNodeLeft);
+ context.setTestPath(compareContext.currentNodeRight);
+
+ Object baseValue = JacksonHelperUtil.objectMapper.convertValue(obj1, Object.class);
+ Object testValue = JacksonHelperUtil.objectMapper.convertValue(obj2, Object.class);
+ ScriptSandbox scriptSandbox = compareContext.scriptSandbox;
+ ScriptMethod scriptMethod = compareContext.scriptCompareConfigMap.get(fuzzyPath);
+ int result = scriptSandbox.invoke(context, baseValue, testValue, scriptMethod);
+ if (result == ScriptCompareType.Matched) {
+ return;
+ }
+ LogRegister.register(obj1, obj2,
+ ScriptCompareType.convert(result, compareContext.parentNodeType), compareContext);
+ }
+
+ public interface ScriptCompareType {
+
+ int Matched = 1;
+ int Unmatched = 2;
+ // the node of basic msg is missing
+ int LEFT_MISSING = 3;
+ // the node of test msg is missing
+ int RIGHT_MISSING = 4;
+
+ static LogMarker convert(int type, int parentType) {
+ switch (type) {
+ case Unmatched:
+ return LogMarker.VALUE_DIFF;
+ case LEFT_MISSING:
+ return parentType == ParentNodeType.OBJECT ? LogMarker.LEFT_OBJECT_MISSING
+ : LogMarker.LEFT_ARRAY_MISSING;
+ case RIGHT_MISSING:
+ return parentType == ParentNodeType.OBJECT ? LogMarker.RIGHT_OBJECT_MISSING
+ : LogMarker.RIGHT_ARRAY_MISSING;
+ default:
+ return LogMarker.UNKNOWN;
+ }
+
+ }
+
+ }
+
+
+}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/factory/TaskThreadFactory.java b/arex-compare-core/src/main/java/com/arextest/diff/factory/TaskThreadFactory.java
index 6e3c986..30646c7 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/factory/TaskThreadFactory.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/factory/TaskThreadFactory.java
@@ -10,15 +10,35 @@ public class TaskThreadFactory {
private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors();
private static final int MAX_POOL_SIZE = CORE_SIZE + 1;
private static final int QUENE_SIZE = 500;
- public static ExecutorService jsonObjectThreadPool = new ThreadPoolExecutor(CORE_SIZE,
+
+ public static ExecutorService jsonObjectThreadPool = new ThreadPoolExecutor(
+ CORE_SIZE,
MAX_POOL_SIZE,
- 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(QUENE_SIZE),
+ 1,
+ TimeUnit.MINUTES,
+ new LinkedBlockingQueue<>(QUENE_SIZE),
new NamedThreadFactory("JsonObject"),
- new CallerRunsPolicyWithReport("JsonObject"));
- public static ExecutorService structureHandlerThreadPool = new ThreadPoolExecutor(CORE_SIZE,
+ new CallerRunsPolicyWithReport("JsonObject")
+ );
+
+ public static ExecutorService structureHandlerThreadPool = new ThreadPoolExecutor(
+ CORE_SIZE,
MAX_POOL_SIZE,
- 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(QUENE_SIZE),
+ 1,
+ TimeUnit.MINUTES,
+ new LinkedBlockingQueue<>(QUENE_SIZE),
new NamedThreadFactory("structureHandler"),
- new CallerRunsPolicyWithReport("structureHandler"));
+ new CallerRunsPolicyWithReport("structureHandler")
+ );
+
+ public static ExecutorService jsEvalThreadPool = new ThreadPoolExecutor(
+ CORE_SIZE,
+ MAX_POOL_SIZE,
+ 1,
+ TimeUnit.MINUTES,
+ new LinkedBlockingQueue<>(QUENE_SIZE),
+ new NamedThreadFactory("jsEval"),
+ new CallerRunsPolicyWithReport("jsEval")
+ );
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/handler/CompareHandler.java b/arex-compare-core/src/main/java/com/arextest/diff/handler/CompareHandler.java
index 7eeb7ab..05a4fa5 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/handler/CompareHandler.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/handler/CompareHandler.java
@@ -37,6 +37,9 @@ public List doHandler(RulesConfig rulesConfig, KeyComputeResponse key
compareContext.logProcess = logProcess;
compareContext.quickCompare = rulesConfig.isQuickCompare();
+ compareContext.scriptSandbox = rulesConfig.getScriptSandbox();
+ compareContext.scriptCompareConfigMap = rulesConfig.getScriptCompareConfigMap();
+
if (msgStructureFuture != null) {
MutablePair msgStructureMutablePair = msgStructureFuture.join();
compareContext.baseMsgStructure = msgStructureMutablePair.getLeft();
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/handler/log/LogMarker.java b/arex-compare-core/src/main/java/com/arextest/diff/handler/log/LogMarker.java
index 516590c..eb78e25 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/handler/log/LogMarker.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/handler/log/LogMarker.java
@@ -1,47 +1,70 @@
package com.arextest.diff.handler.log;
public enum LogMarker {
- ZERO,
- // This marker indicates that there is a null value at the recursive entry
- NULL_CHECK,
- // This marker indicates that there is different type
- TYPE_DIFF,
+ UNKNOWN(0),
+
+ // This mark indicates that there is unmatched value at the comparison of value
+ VALUE_DIFF(1),
// This marker indicates that there is right missing at the comparison of object
- RIGHT_OBJECT_MISSING,
+ RIGHT_OBJECT_MISSING(2),
// This marker indicates that there is left missing at the comparison of object
- LEFT_OBJECT_MISSING,
+ LEFT_OBJECT_MISSING(3),
- // This marker indicates that there is different count at the comparison of array
- DIFF_ARRAY_COUNT,
+ // This mark indicates that there is left missing at the comparision of array
+ LEFT_ARRAY_MISSING(4),
// This marker indicates that there is right missing at the comparison of array
- RIGHT_ARRAY_MISSING,
+ RIGHT_ARRAY_MISSING(5),
- // This marker indicates that there is not unique key at the left search of listkey
- REPEAT_LEFT_KEY,
+ // This marker indicates that there is a null value at the recursive entry
+ NULL_CHECK(6),
- // This mark indicates that there is right missing at the comparison of listKey mode
- RIGHT_ARRAY_MISSING_KEY,
+ // This marker indicates that there is different type
+ TYPE_DIFF(7),
- // This mark indicates that there is left missing at the comparision of array
- LEFT_ARRAY_MISSING,
+ // This marker indicates that there is different count at the comparison of array
+ DIFF_ARRAY_COUNT(8),
+
+ // This marker indicates that there is not unique key at the left search of listkey
+ REPEAT_LEFT_KEY(9),
// This marker indicates that there is not unique key at the right search of listkey
- REPEAT_RIGHT_KEY,
+ REPEAT_RIGHT_KEY(10),
+
+ // This mark indicates that there is right missing at the comparison of listKey mode
+ RIGHT_ARRAY_MISSING_KEY(11),
// This mark indicates that there is left missing at the comparison of listKey mode
- LEFT_ARRAY_MISSING_KEY,
+ LEFT_ARRAY_MISSING_KEY(12),
// This mark indicates that there is left reference not fund at the comparison of value
- LEFT_REF_NOT_FOUND,
+ LEFT_REF_NOT_FOUND(13),
// This mark indicates that there is right reference not found at the comparison of value
- RIGHT_REF_NOT_FOUND,
+ RIGHT_REF_NOT_FOUND(14);
+
+ private Integer code;
+
+ LogMarker(int code) {
+ this.code = code;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public static LogMarker from(int code) {
+ for (LogMarker type : LogMarker.values()) {
+ if (type.getCode() == code) {
+ return type;
+ }
+ }
+ return UNKNOWN;
+ }
+
- // This mark indicates that there is unmatched value at the comparison of value
- VALUE_DIFF,
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/handler/log/register/LogRegister.java b/arex-compare-core/src/main/java/com/arextest/diff/handler/log/register/LogRegister.java
index ff887eb..2b845a2 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/handler/log/register/LogRegister.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/handler/log/register/LogRegister.java
@@ -32,6 +32,10 @@ public static void register(Object obj1, Object obj2, LogMarker logMarker,
}
LogEntity log = null;
switch (logMarker) {
+ case UNKNOWN:
+ log = produceLog(obj1, obj2, UnmatchedType.UNMATCHED, ErrorType.NA,
+ compareContext.currentListKeysLeft, compareContext);
+ break;
case NULL_CHECK:
log = nullCheck(obj1, obj2, logMarker, compareContext);
break;
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/CompareOptions.java b/arex-compare-core/src/main/java/com/arextest/diff/model/CompareOptions.java
index e04e015..87cc283 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/model/CompareOptions.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/CompareOptions.java
@@ -1,6 +1,7 @@
package com.arextest.diff.model;
import com.arextest.diff.model.enumeration.CategoryType;
+import com.arextest.diff.model.script.ScriptCompareConfig;
import com.arextest.diff.utils.ListUti;
import com.arextest.diff.utils.StringUtil;
import java.util.ArrayList;
@@ -23,7 +24,6 @@ public class CompareOptions {
* The decompressService which is loaded from this pluginJarUrl is the level of each compare.
*/
private String pluginJarUrl;
-
/**
* the collection of the node path chosen to compare
*/
@@ -60,6 +60,9 @@ public class CompareOptions {
*/
private Map, List>> listSortConfig;
+
+ private List scriptCompareConfigList;
+
/**
* change the message and configuration to lowercase, for the inconsistency between the actual
* message and the contract case
@@ -255,6 +258,28 @@ public CompareOptions putListSortConfig(Map, List>> li
return this;
}
+ public CompareOptions putScriptCompareConfig(ScriptCompareConfig scriptCompareConfig) {
+ if (scriptCompareConfig == null || ListUti.isEmpty(scriptCompareConfig.getNodePath())) {
+ return this;
+ }
+ if (this.scriptCompareConfigList == null) {
+ this.scriptCompareConfigList = new ArrayList<>();
+ }
+ this.scriptCompareConfigList.add(scriptCompareConfig);
+ return this;
+ }
+
+ public CompareOptions putScriptCompareConfig(Collection scriptCompareConfigList) {
+ if (scriptCompareConfigList == null || scriptCompareConfigList.isEmpty()) {
+ return this;
+ }
+ if (this.scriptCompareConfigList == null) {
+ this.scriptCompareConfigList = new ArrayList<>();
+ }
+ this.scriptCompareConfigList.addAll(scriptCompareConfigList);
+ return this;
+ }
+
public CompareOptions putNameToLower(Boolean nameToLower) {
this.nameToLower = nameToLower;
return this;
@@ -332,6 +357,10 @@ public Map, List>> getListSortConfig() {
return listSortConfig;
}
+ public List getScriptCompareConfigList() {
+ return scriptCompareConfigList;
+ }
+
public Boolean getNameToLower() {
return nameToLower;
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/GlobalOptions.java b/arex-compare-core/src/main/java/com/arextest/diff/model/GlobalOptions.java
index 8209885..31faa90 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/model/GlobalOptions.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/GlobalOptions.java
@@ -1,11 +1,16 @@
package com.arextest.diff.model;
import com.arextest.diff.handler.decompress.TransformServiceBuilder;
+import com.arextest.diff.model.script.ScriptContentInfo;
+import com.arextest.diff.model.script.ScriptSandbox;
import com.arextest.diff.utils.StringUtil;
+import java.util.Collection;
import java.util.Set;
public class GlobalOptions {
+ private ScriptSandbox scriptSandbox = new ScriptSandbox();
+
/**
* The url address of the plug-in jar which is specified by the interface http or absolute path.
* The decompressService which is loaded from this pluginJarUrl is the level of SYSTEM.
@@ -177,4 +182,39 @@ public Boolean getOnlyCompareExistListElements() {
return onlyCompareExistListElements;
}
+ // region scriptSandbox
+ public GlobalOptions putCompareScript(ScriptContentInfo scriptContentInfo) {
+ scriptSandbox.putCompareScript(scriptContentInfo);
+ return this;
+ }
+
+ public GlobalOptions putCompareScript(Collection scriptContentInfo) {
+ if (scriptContentInfo == null || scriptContentInfo.isEmpty()) {
+ return this;
+ }
+ for (ScriptContentInfo script : scriptContentInfo) {
+ scriptSandbox.putCompareScript(script);
+ }
+ return this;
+ }
+
+ public GlobalOptions putScriptMaxCPUTime(long maxCPUTime) {
+ scriptSandbox.getSandbox().setMaxCPUTime(maxCPUTime);
+ return this;
+ }
+
+ public GlobalOptions putScriptMaxMemory(long maxMemory) {
+ scriptSandbox.getSandbox().setMaxMemory(maxMemory);
+ return this;
+ }
+
+ public GlobalOptions putScriptMaxPreparedStatements(int maxPreparedStatements) {
+ scriptSandbox.getSandbox().setMaxPreparedStatements(maxPreparedStatements);
+ return this;
+ }
+
+ public ScriptSandbox getScriptSandbox() {
+ return scriptSandbox;
+ }
+ // endregion
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/RulesConfig.java b/arex-compare-core/src/main/java/com/arextest/diff/model/RulesConfig.java
index fe47bf0..30ccf6a 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/model/RulesConfig.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/RulesConfig.java
@@ -5,6 +5,8 @@
import com.arextest.diff.model.key.ListSortEntity;
import com.arextest.diff.model.key.ReferenceEntity;
import com.arextest.diff.model.pathparse.ExpressionNodeEntity;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
+import com.arextest.diff.model.script.ScriptSandbox;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -14,6 +16,8 @@
public class RulesConfig {
+ private ScriptSandbox scriptSandbox;
+
/**
* @see CategoryType
*/
@@ -41,6 +45,8 @@ public class RulesConfig {
private List listSortEntities = Collections.emptyList();
+ private Map, ScriptMethod> scriptCompareConfigMap;
+
private boolean nameToLower;
private boolean nullEqualsEmpty;
@@ -69,6 +75,14 @@ public class RulesConfig {
public RulesConfig() {
}
+ public ScriptSandbox getScriptSandbox() {
+ return scriptSandbox;
+ }
+
+ public void setScriptSandbox(ScriptSandbox scriptSandbox) {
+ this.scriptSandbox = scriptSandbox;
+ }
+
public String getCategoryType() {
return categoryType;
}
@@ -159,6 +173,15 @@ public void setListSortEntities(List listSortEntities) {
this.listSortEntities = listSortEntities;
}
+ public Map, ScriptMethod> getScriptCompareConfigMap() {
+ return scriptCompareConfigMap;
+ }
+
+ public void setScriptCompareConfigMap(
+ Map, ScriptMethod> scriptCompareConfigMap) {
+ this.scriptCompareConfigMap = scriptCompareConfigMap;
+ }
+
public boolean isNameToLower() {
return nameToLower;
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/compare/CompareContext.java b/arex-compare-core/src/main/java/com/arextest/diff/model/compare/CompareContext.java
index 1d26f30..1dc7dbe 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/model/compare/CompareContext.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/compare/CompareContext.java
@@ -6,6 +6,8 @@
import com.arextest.diff.model.log.NodeEntity;
import com.arextest.diff.model.parse.MsgStructure;
import com.arextest.diff.model.pathparse.ExpressionNodeEntity;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
+import com.arextest.diff.model.script.ScriptSandbox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -61,6 +63,10 @@ public class CompareContext {
public MsgStructure baseMsgStructure;
public MsgStructure testMsgStructure;
+ public ScriptSandbox scriptSandbox;
+
+ public Map, ScriptMethod> scriptCompareConfigMap;
+
public byte ignoreReferenceNotFound = 0;
// 0:object 1:array
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/log/UnmatchedPairEntity.java b/arex-compare-core/src/main/java/com/arextest/diff/model/log/UnmatchedPairEntity.java
index 8234706..a4784a6 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/model/log/UnmatchedPairEntity.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/log/UnmatchedPairEntity.java
@@ -61,6 +61,9 @@ public void setRightUnmatchedPath(List rightUnmatchedPath) {
}
public UnmatchedPairEntity buildListKeys(List listKeys) {
+ if (listKeys == null) {
+ return this;
+ }
this.listKeys = new ArrayList<>(listKeys);
return this;
}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptCompareConfig.java b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptCompareConfig.java
new file mode 100644
index 0000000..fe87595
--- /dev/null
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptCompareConfig.java
@@ -0,0 +1,65 @@
+package com.arextest.diff.model.script;
+
+import java.util.List;
+
+public class ScriptCompareConfig {
+
+ List nodePath;
+ ScriptMethod scriptMethod;
+
+ public ScriptCompareConfig() {
+ }
+
+ public ScriptCompareConfig(List nodePath, ScriptMethod scriptMethod) {
+ this.nodePath = nodePath;
+ this.scriptMethod = scriptMethod;
+ }
+
+ public List getNodePath() {
+ return nodePath;
+ }
+
+ public void setNodePath(List nodePath) {
+ this.nodePath = nodePath;
+ }
+
+ public ScriptMethod getScriptMethod() {
+ return scriptMethod;
+ }
+
+ public void setScriptMethod(
+ ScriptMethod scriptMethod) {
+ this.scriptMethod = scriptMethod;
+ }
+
+ public static class ScriptMethod {
+
+ private String methodName;
+ private String methodArgs;
+
+ public ScriptMethod() {
+ }
+
+ public ScriptMethod(String methodName, String methodArgs) {
+ this.methodName = methodName;
+ this.methodArgs = methodArgs;
+ }
+
+ public String getMethodName() {
+ return methodName;
+ }
+
+ public void setMethodName(String methodName) {
+ this.methodName = methodName;
+ }
+
+ public String getMethodArgs() {
+ return methodArgs;
+ }
+
+ public void setMethodArgs(String methodArgs) {
+ this.methodArgs = methodArgs;
+ }
+ }
+
+}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptContentInfo.java b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptContentInfo.java
new file mode 100644
index 0000000..9458584
--- /dev/null
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptContentInfo.java
@@ -0,0 +1,44 @@
+package com.arextest.diff.model.script;
+
+public class ScriptContentInfo {
+
+ private String aliasName;
+
+ private String functionName;
+
+ private String scriptContent;
+
+
+ public ScriptContentInfo() {
+ }
+
+ public ScriptContentInfo(String aliasName, String functionName, String scriptContent) {
+ this.aliasName = aliasName;
+ this.functionName = functionName;
+ this.scriptContent = scriptContent;
+ }
+
+ public String getAliasName() {
+ return aliasName;
+ }
+
+ public void setAliasName(String aliasName) {
+ this.aliasName = aliasName;
+ }
+
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ public void setFunctionName(String functionName) {
+ this.functionName = functionName;
+ }
+
+ public String getScriptContent() {
+ return scriptContent;
+ }
+
+ public void setScriptContent(String scriptContent) {
+ this.scriptContent = scriptContent;
+ }
+}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptMethodContext.java b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptMethodContext.java
new file mode 100644
index 0000000..7401e9b
--- /dev/null
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptMethodContext.java
@@ -0,0 +1,26 @@
+package com.arextest.diff.model.script;
+
+import com.arextest.diff.model.log.NodeEntity;
+import java.util.List;
+
+public class ScriptMethodContext {
+
+ private List basePath;
+ private List testPath;
+
+ public List getBasePath() {
+ return basePath;
+ }
+
+ public void setBasePath(List basePath) {
+ this.basePath = basePath;
+ }
+
+ public List getTestPath() {
+ return testPath;
+ }
+
+ public void setTestPath(List testPath) {
+ this.testPath = testPath;
+ }
+}
\ No newline at end of file
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptSandbox.java b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptSandbox.java
new file mode 100644
index 0000000..2015f1d
--- /dev/null
+++ b/arex-compare-core/src/main/java/com/arextest/diff/model/script/ScriptSandbox.java
@@ -0,0 +1,68 @@
+package com.arextest.diff.model.script;
+
+import com.arextest.diff.factory.TaskThreadFactory;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
+import delight.nashornsandbox.NashornSandbox;
+import delight.nashornsandbox.NashornSandboxes;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.script.Invocable;
+import javax.script.ScriptException;
+
+public class ScriptSandbox {
+
+ private NashornSandbox sandbox = createSandbox();
+
+ public ScriptSandbox() {
+ }
+
+ private Map compareScripts = new HashMap<>();
+
+ private Set loadedScripts = new HashSet<>();
+
+ public NashornSandbox getSandbox() {
+ return sandbox;
+ }
+
+ public void putCompareScript(ScriptContentInfo scriptContentInfo) {
+ if (scriptContentInfo.getAliasName() != null && !scriptContentInfo.getAliasName().isEmpty()) {
+ compareScripts.put(scriptContentInfo.getAliasName(), scriptContentInfo);
+ }
+ if (scriptContentInfo.getFunctionName() != null && !scriptContentInfo.getFunctionName()
+ .isEmpty()) {
+ compareScripts.put(scriptContentInfo.getFunctionName(), scriptContentInfo);
+ }
+ }
+
+ public int invoke(ScriptMethodContext context, Object obj1, Object obj2,
+ ScriptMethod scriptMethod)
+ throws ScriptException, NoSuchMethodException {
+
+ String methodName = scriptMethod.getMethodName();
+ String methodArgs = scriptMethod.getMethodArgs();
+ if (!loadedScripts.contains(methodName)) {
+ ScriptContentInfo contentInfo = compareScripts.get(methodName);
+ if (contentInfo == null || contentInfo.getScriptContent() == null
+ || contentInfo.getScriptContent().isEmpty()) {
+ throw new IllegalArgumentException("Script content is empty for method: " + methodName);
+ }
+ sandbox.eval(contentInfo.getScriptContent());
+ loadedScripts.add(methodName);
+ }
+ String functionName = compareScripts.get(methodName).getFunctionName();
+ Invocable invocable = sandbox.getSandboxedInvocable();
+ return (Integer) invocable.invokeFunction(functionName, context, obj1, obj2, methodArgs);
+ }
+
+ private NashornSandbox createSandbox() {
+ NashornSandbox nashornSandbox = NashornSandboxes.create();
+ nashornSandbox.setMaxCPUTime(2 * 60 * 1000);
+ nashornSandbox.setMaxMemory(512 * 1024 * 1024 * 8L);
+ nashornSandbox.setMaxPreparedStatements(50);
+ nashornSandbox.setExecutor(TaskThreadFactory.jsEvalThreadPool);
+ return nashornSandbox;
+ }
+
+}
diff --git a/arex-compare-core/src/main/java/com/arextest/diff/utils/OptionsToRulesConvert.java b/arex-compare-core/src/main/java/com/arextest/diff/utils/OptionsToRulesConvert.java
index 1406c90..b3af32a 100644
--- a/arex-compare-core/src/main/java/com/arextest/diff/utils/OptionsToRulesConvert.java
+++ b/arex-compare-core/src/main/java/com/arextest/diff/utils/OptionsToRulesConvert.java
@@ -9,6 +9,8 @@
import com.arextest.diff.model.TransformConfig.TransformMethod;
import com.arextest.diff.model.key.ListSortEntity;
import com.arextest.diff.model.key.ReferenceEntity;
+import com.arextest.diff.model.script.ScriptCompareConfig;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -22,6 +24,7 @@ public static RulesConfig optionsToConfig(String baseMsg, String testMsg,
RulesConfig rulesConfig = new RulesConfig();
rulesConfig.setBaseMsg(baseMsg);
rulesConfig.setTestMsg(testMsg);
+ rulesConfig.setScriptSandbox(globalOptions.getScriptSandbox());
systemToRules(rulesConfig);
globalOptionsToRules(globalOptions, rulesConfig);
@@ -43,6 +46,8 @@ private static void configToLower(RulesConfig rulesConfig) {
FieldToLowerUtil.mapKeyToLower(rulesConfig.getTransformConfigMap()));
FieldToLowerUtil.referenceToLower(rulesConfig.getReferenceEntities());
FieldToLowerUtil.keyConfigToLower(rulesConfig.getListSortEntities());
+ rulesConfig.setScriptCompareConfigMap(
+ FieldToLowerUtil.mapKeyToLower(rulesConfig.getScriptCompareConfigMap()));
}
@@ -102,6 +107,8 @@ private static void optionsToRules(CompareOptions compareOptions, RulesConfig ru
rulesConfig.setReferenceEntities(referenceConfigConvert(compareOptions.getReferenceConfig()));
rulesConfig.setListSortEntities(listSortConfigConvert(compareOptions.getListSortConfig(),
rulesConfig.getReferenceEntities()));
+ rulesConfig.setScriptCompareConfigMap(
+ scriptCompareConfigConvert(compareOptions.getScriptCompareConfigList()));
if (compareOptions.getSelectIgnoreCompare() != null) {
rulesConfig.setSelectIgnoreCompare(compareOptions.getSelectIgnoreCompare());
}
@@ -222,4 +229,17 @@ private static List listSortConfigConvert(
}
+ private static Map, ScriptMethod> scriptCompareConfigConvert(
+ List scriptCompareConfigList) {
+ if (scriptCompareConfigList == null || scriptCompareConfigList.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ Map, ScriptMethod> result = new HashMap<>(scriptCompareConfigList.size());
+ for (ScriptCompareConfig scriptCompareConfig : scriptCompareConfigList) {
+ result.put(scriptCompareConfig.getNodePath(), scriptCompareConfig.getScriptMethod());
+ }
+ return result;
+ }
+
}
diff --git a/arex-compare-core/src/test/java/com/arextest/diff/sdk/CompareSDKTest.java b/arex-compare-core/src/test/java/com/arextest/diff/sdk/CompareSDKTest.java
index 03793e1..5e4524d 100644
--- a/arex-compare-core/src/test/java/com/arextest/diff/sdk/CompareSDKTest.java
+++ b/arex-compare-core/src/test/java/com/arextest/diff/sdk/CompareSDKTest.java
@@ -6,6 +6,9 @@
import com.arextest.diff.model.TransformConfig;
import com.arextest.diff.model.TransformConfig.TransformMethod;
import com.arextest.diff.model.enumeration.CategoryType;
+import com.arextest.diff.model.script.ScriptCompareConfig;
+import com.arextest.diff.model.script.ScriptCompareConfig.ScriptMethod;
+import com.arextest.diff.model.script.ScriptContentInfo;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -916,4 +919,126 @@ public void testMultiCompare() {
Assertions.assertEquals(0, compare.getCode());
}
+ @Test
+ public void testScriptCompare() {
+ CompareSDK compareSDK = new CompareSDK();
+
+ compareSDK.getGlobalOptions().putCompareScript(
+ Arrays.asList(
+ new ScriptContentInfo(
+ "test",
+ "tolerance",
+ "function tolerance(context, baseValue, testValue, arg) {\n"
+ + " if(Math.abs(baseValue - testValue) <= 3) {\n"
+ + " return 1;\n"
+ + " }else{\n"
+ + " return 2;\n"
+ + " }\n"
+ + "}"
+ )
+ )
+ );
+
+ CompareOptions compareOptions = new CompareOptions();
+ compareOptions.putScriptCompareConfig(
+ new ScriptCompareConfig(Arrays.asList("score"), new ScriptMethod("test", ""))
+ );
+
+ String baseMsg = "{\n"
+ + " \"score\": 18"
+ + "}";
+ String testMsg = "{\n"
+ + " \"score\": 20\n"
+ + "}";
+ CompareResult compare = compareSDK.compare(baseMsg, testMsg, compareOptions);
+ Assertions.assertEquals(0, compare.getLogs().size());
+ }
+
+ @Test
+ public void testScriptCompare2() {
+ CompareSDK compareSDK = new CompareSDK();
+
+ compareSDK.getGlobalOptions().putCompareScript(
+ Arrays.asList(
+ new ScriptContentInfo(
+ "",
+ "equals",
+ "function equals(context, baseValue, testValue, arg) {\n"
+ + " if(baseValue === null && testValue !== null) {\n"
+ + " return 3;\n"
+ + " }\n"
+ + " if(baseValue !== null && testValue === null) {\n"
+ + " return 4;\n"
+ + " }\n"
+ + " if(baseValue !== testValue) {\n"
+ + " return 2;\n"
+ + " }\n"
+ + " return 1;\n"
+ + "}"
+ )
+ )
+ );
+
+ CompareOptions compareOptions = new CompareOptions();
+ compareOptions.putScriptCompareConfig(
+ new ScriptCompareConfig(Arrays.asList("scores", "maths"), new ScriptMethod("equals", ""))
+ );
+
+ String baseMsg = "{\n"
+ + " \"name\": \"xiaoming\",\n"
+ + " \"scores\": [\n"
+ + " {\n"
+ + " \"maths\": 90\n"
+ + " },\n"
+ + " {\n"
+ + " \"maths\": 70\n"
+ + " }\n"
+ + " ],\n"
+ + " \"alias\": null,\n"
+ + " \"age\": 18\n"
+ + "}";
+ String testMsg = "{\n"
+ + " \"name\": \"xiaoming\",\n"
+ + " \"scores\": [\n"
+ + " {\n"
+ + " \"maths\": 18\n"
+ + " }\n"
+ + " ],\n"
+ + " \"alias\": null,\n"
+ + " \"age\": 18\n"
+ + "}";
+ CompareResult compare = compareSDK.compare(baseMsg, testMsg, compareOptions);
+ Assertions.assertEquals(2, compare.getLogs().size());
+ }
+
+
+ @Test
+ public void testScriptCompare3() {
+ CompareSDK compareSDK = new CompareSDK();
+
+ compareSDK.getGlobalOptions().putCompareScript(
+ Arrays.asList(
+ new ScriptContentInfo(
+ "test",
+ "func_67356dbc7ac2aa763be9f8af",
+ "function func_67356dbc7ac2aa763be9f8af(context, baseValue, testValue, arg) {return 2;}"
+ )
+ )
+ );
+
+ CompareOptions compareOptions = new CompareOptions();
+ compareOptions.putScriptCompareConfig(
+ new ScriptCompareConfig(Arrays.asList("score"), new ScriptMethod("test", ""))
+ );
+
+ String baseMsg = "{\n"
+ + " \"score\": 18"
+ + "}";
+ String testMsg = "{\n"
+ + " \"score\": 20\n"
+ + "}";
+ CompareResult compare = compareSDK.quickCompare(baseMsg, testMsg, compareOptions);
+ Assertions.assertEquals(1, compare.getCode());
+ }
+
}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 07ae0cf..6db61ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,15 +7,15 @@
com.arextest
arex-compare-parent
pom
- 0.2.17
+ 0.2.18
arex-compare-extension
arex-compare-core
- 8
- 8
+ 21
+ 21
UTF-8
@@ -90,6 +90,11 @@
slf4j-api
1.7.21
+
+ org.javadelight
+ delight-nashorn-sandbox
+ 0.5.0
+
org.junit.jupiter
junit-jupiter-engine
@@ -123,8 +128,8 @@
maven-compiler-plugin
3.6.0
-
- 1.8
+
+ 21
@@ -227,8 +232,8 @@
maven-compiler-plugin
3.6.0
-
- 1.8
+
+ 21