Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: merge record dynamicClass #341

Merged
merged 7 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public static void initialize(Instrumentation inst, File agentFile, String agent
File[] extensionFiles = getExtensionJarFiles(agentFile);
classLoader = createAgentClassLoader(agentFile, extensionFiles);
InstrumentationHolder.setAgentClassLoader(classLoader);
InstrumentationHolder.setInstrumentation(inst);
AgentInstaller installer = createAgentInstaller(inst, agentFile, agentArgs);
addJarToLoaderSearch(agentFile, extensionFiles);
installer.install();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@
import java.lang.ref.WeakReference;
import java.util.concurrent.*;

class WeakCache<K, V> extends ReferenceQueue<K> implements Cache<K, V> {
public class WeakCache<K, V> extends ReferenceQueue<K> implements Cache<K, V> {
final ConcurrentMap<WeakReferenceKey<K>, V> target;

final CleanUpTask<V> cleanUpTask;

public WeakCache() {
this(new ConcurrentHashMap<>());
this(new ConcurrentHashMap<>(), null);
}

public WeakCache(CleanUpTask<V> cleanUpTask) {
this(new ConcurrentHashMap<>(), cleanUpTask);

Check warning on line 18 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java#L18

Added line #L18 was not covered by tests
}

public WeakCache(ConcurrentMap<WeakReferenceKey<K>, V> target) {
public WeakCache(ConcurrentMap<WeakReferenceKey<K>, V> target, CleanUpTask<V> cleanUpTask) {
this.target = target;
this.cleanUpTask = cleanUpTask;
}

public V get(K key) {
Expand All @@ -38,20 +45,31 @@
target.clear();
}

public boolean containsKey(K key) {
check();
return target.containsKey(new WeakReferenceKey<>(key));

Check warning on line 50 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java#L49-L50

Added lines #L49 - L50 were not covered by tests
}

void check() {
Reference<?> reference;
while ((reference = poll()) != null) {
target.remove(reference);
final V value = target.remove(reference);
if (cleanUpTask != null && value != null) {
cleanUpTask.cleanUp(value);

Check warning on line 58 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java#L58

Added line #L58 was not covered by tests
}
}
}

static final class WeakReferenceKey<K> extends WeakReference<K> {
private final int hashCode;

WeakReferenceKey(K key) {
this(key, null);
}

Check warning on line 68 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/internal/WeakCache.java#L67-L68

Added lines #L67 - L68 were not covered by tests

WeakReferenceKey(K key, ReferenceQueue<? super K> queue) {
super(key, queue);

hashCode = System.identityHashCode(key);
hashCode = (key == null) ? 0 : System.identityHashCode(key);
}

@Override
Expand All @@ -68,5 +86,12 @@
return other != null && other.equals(this);
}
}

public interface CleanUpTask<T> {
/**
* @param object object to cleanup
*/
void cleanUp(T object);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
private long creationTime;
private Mocker.Target targetRequest;
private Mocker.Target targetResponse;
private boolean needMerge;
private String operationName;

public ArexMocker() {
Expand Down Expand Up @@ -116,4 +117,12 @@
public void setOperationName(String operationName) {
this.operationName = operationName;
}

public boolean isNeedMerge() {
return needMerge;

Check warning on line 122 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/ArexMocker.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/ArexMocker.java#L122

Added line #L122 was not covered by tests
}

public void setNeedMerge(boolean needMerge) {
this.needMerge = needMerge;
}

Check warning on line 127 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/ArexMocker.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/ArexMocker.java#L126-L127

Added lines #L126 - L127 were not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

public static MockCategoryType create(String name, boolean entryPoint, boolean skipComparison) {
return CATEGORY_TYPE_MAP.computeIfAbsent(name,
key -> new MockCategoryType(name, entryPoint, skipComparison));
key -> new MockCategoryType(name, entryPoint, skipComparison));

Check warning on line 41 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/MockCategoryType.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/MockCategoryType.java#L41

Added line #L41 was not covered by tests
}

public static Collection<MockCategoryType> values() {
Expand Down Expand Up @@ -78,6 +78,9 @@
this.skipComparison = skipComparison;
}

public static MockCategoryType of(String name) {
return CATEGORY_TYPE_MAP.get(name);

Check warning on line 82 in arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/MockCategoryType.java

View check run for this annotation

Codecov / codecov/patch

arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/model/MockCategoryType.java#L82

Added line #L82 was not covered by tests
}

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,8 @@ default String recordLogTitle() {
default String replayLogTitle() {
return "replay." + getCategoryType().getName();
}

public boolean isNeedMerge();

public void setNeedMerge(boolean needMerge);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package io.arex.agent.bootstrap.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;

public class CollectionUtil {
private static final List<?> EMPTY_LIST = newArrayList();
Expand Down Expand Up @@ -41,4 +38,42 @@ public static <E> List<E> newArrayList(E... elements) {
Collections.addAll(list, elements);
return list;
}

/**
* split to multiple list by split count
*/
public static <V> List<List<V>> split(List<V> originalList, int splitCount) {
if (isEmpty(originalList)) {
return emptyList();
}
int originalSize = originalList.size();
List<List<V>> splitList = new ArrayList<>();
if (originalSize < splitCount || splitCount == 0) {
splitList.add(originalList);
return splitList;
}
for (int i = 0; i < splitCount; i++) {
List<V> list = new ArrayList<>();
splitList.add(list);
}
int index = 0;
for (V value : originalList) {
splitList.get(index).add(value);
index = (index + 1) % splitCount;
}
return splitList;
}

public static <V> List<V> filterNull(List<V> originalList) {
if (isEmpty(originalList)) {
return emptyList();
}
List<V> filterList = new ArrayList<>(originalList.size());
for (V element : originalList) {
if (element != null) {
filterList.add(element);
}
}
return filterList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,26 @@ static int capacity(int expectedSize) {
// any large value
return Integer.MAX_VALUE;
}

public static <K> boolean getBoolean(final Map<? super K, ?> map, final K key) {
return getBoolean(map, key, false);
}

public static <K> boolean getBoolean(final Map<? super K, ?> map, final K key, boolean defaultValue) {
if (isEmpty(map) || map.get(key) == null) {
return defaultValue;
}
final Object answer = map.get(key);
if (answer instanceof Boolean) {
return (Boolean) answer;
}
if (answer instanceof String) {
return Boolean.parseBoolean((String) answer);
}
if (answer instanceof Number) {
final Number num = (Number) answer;
return num.intValue() != 0;
}
return defaultValue;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package io.arex.agent.bootstrap.util;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.params.provider.Arguments.arguments;

import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class CollectionUtilTest {

Expand Down Expand Up @@ -33,4 +39,33 @@ void newArrayList() {
actualResult = CollectionUtil.newArrayList("test");
assertInstanceOf(ArrayList.class, actualResult);
}

@ParameterizedTest
@MethodSource("splitCase")
void split(List<String> originalList, int splitCount, Predicate<List<List<String>>> predicate) {
assertTrue(predicate.test(CollectionUtil.split(originalList, splitCount)));
}

static Stream<Arguments> splitCase() {
Supplier<List<String>> lessSplitCountList = () -> CollectionUtil.newArrayList("mock");
Supplier<List<String>> normalSplitCountList = () -> CollectionUtil.newArrayList("mock1", "mock2");

Predicate<List<List<String>>> empty = CollectionUtil::isEmpty;
Predicate<List<List<String>>> notEmpty = CollectionUtil::isNotEmpty;

return Stream.of(
arguments(null, 1, empty),
arguments(lessSplitCountList.get(), 2, notEmpty),
arguments(normalSplitCountList.get(), 2, notEmpty)
);
}

@Test
void filterNull() {
List<String> actualResult = CollectionUtil.filterNull(null);
assertEquals(0, actualResult.size());

actualResult = CollectionUtil.filterNull(CollectionUtil.newArrayList("mock"));
assertEquals(1, actualResult.size());
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package io.arex.agent.bootstrap.util;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.params.provider.Arguments.arguments;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class MapUtilsTest {

Expand Down Expand Up @@ -41,4 +46,29 @@ public static int capacity(Map<String, String> map) {
return 0;
}
}

@ParameterizedTest
@MethodSource("getBooleanCase")
void getBoolean(Map<String, Object> map, String key, Predicate<Boolean> asserts) {
asserts.test(MapUtils.getBoolean(map, key));
}

static Stream<Arguments> getBooleanCase() {
Map<String, Object> map = new HashMap<>();
map.put("booleanKey", true);
map.put("stringKey", "true");
map.put("numberKey", 1);
map.put("key", String.class);

Predicate<Boolean> asserts1 = bool -> bool;
Predicate<Boolean> asserts2 = bool -> !bool;

return Stream.of(
arguments(null, null, asserts1),
arguments(map, "booleanKey", asserts2),
arguments(map, "stringKey", asserts2),
arguments(map, "numberKey", asserts2),
arguments(map, "key", asserts1)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import io.arex.agent.bootstrap.util.ConcurrentHashSet;
import io.arex.agent.bootstrap.util.StringUtil;
import io.arex.inst.runtime.model.ArexConstants;
import io.arex.inst.runtime.model.MergeDTO;
import io.arex.inst.runtime.util.MergeRecordReplayUtil;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class ArexContext {
Expand All @@ -18,11 +18,13 @@
private final long createTime;
private final AtomicInteger sequence;
private Set<Integer> methodSignatureHashList;
private Map<String, Object> cachedReplayResultMap;
private Map<Integer, List<MergeDTO>> cachedReplayResultMap;
private Map<String, Set<String>> excludeMockTemplate;

private Map<String, Object> attachments = null;

private LinkedBlockingQueue<MergeDTO> mergeRecordQueue;

private boolean isRedirectRequest;
private boolean isInvalidCase;

Expand Down Expand Up @@ -72,7 +74,7 @@
return methodSignatureHashList;
}

public Map<String, Object> getCachedReplayResultMap() {
public Map<Integer, List<MergeDTO>> getCachedReplayResultMap() {
if (cachedReplayResultMap == null) {
cachedReplayResultMap = new ConcurrentHashMap<>();
}
Expand Down Expand Up @@ -138,6 +140,13 @@
return isRedirectRequest;
}

public LinkedBlockingQueue<MergeDTO> getMergeRecordQueue() {
if (mergeRecordQueue == null) {
mergeRecordQueue = new LinkedBlockingQueue<>(2048);
}
return mergeRecordQueue;
}

public void clear() {
if (methodSignatureHashList != null) {
methodSignatureHashList.clear();
Expand All @@ -151,5 +160,10 @@
if (attachments != null) {
attachments.clear();
}
if (mergeRecordQueue != null) {
// async thread merge record (main entry has ended)
MergeRecordReplayUtil.recordRemain(this);
mergeRecordQueue.clear();

Check warning on line 166 in arex-instrumentation-api/src/main/java/io/arex/inst/runtime/context/ArexContext.java

View check run for this annotation

Codecov / codecov/patch

arex-instrumentation-api/src/main/java/io/arex/inst/runtime/context/ArexContext.java#L165-L166

Added lines #L165 - L166 were not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@

private static void publish(ArexContext context, boolean isCreate) {
if (CollectionUtil.isNotEmpty(LISTENERS)) {
LISTENERS.stream().forEach(listener -> {
LISTENERS.forEach(listener -> {

Check warning on line 87 in arex-instrumentation-api/src/main/java/io/arex/inst/runtime/context/ContextManager.java

View check run for this annotation

Codecov / codecov/patch

arex-instrumentation-api/src/main/java/io/arex/inst/runtime/context/ContextManager.java#L87

Added line #L87 was not covered by tests
if (isCreate) {
listener.onCreate(context);
} else {
Expand Down
Loading