Skip to content

Commit e1965fa

Browse files
authored
fix: jedis wrapper call NPE (#375)
1 parent 8374c98 commit e1965fa

File tree

11 files changed

+287
-11
lines changed

11 files changed

+287
-11
lines changed

arex-attacher/src/main/java/io/arex/attacher/AgentAttacher.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.sun.tools.attach.VirtualMachine;
55

66
import java.io.IOException;
7+
import java.util.Arrays;
78

89
/**
910
* agent attacher
@@ -52,7 +53,8 @@ public static void main(String[] args) {
5253
virtualMachine.detach();
5354
} catch (Throwable e) {
5455
// expected behavior, it will be returned as error stream to the caller, if any
55-
e.printStackTrace();
56+
System.err.printf("agent attach failed, pid: %s, args: %s, error: %s%n",
57+
pid, Arrays.toString(args), e.getMessage());
5658
}
5759
}
58-
}
60+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.arex.inst.extension.matcher;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import net.bytebuddy.description.type.TypeDescription;
6+
import net.bytebuddy.matcher.ElementMatcher;
7+
import net.bytebuddy.matcher.ElementMatchers;
8+
import org.junit.jupiter.api.Test;
9+
10+
/**
11+
* @since 2024/1/12
12+
*/
13+
class SafeExtendsClassMatcherTest {
14+
15+
@Test
16+
void extendsClass() {
17+
ElementMatcher.Junction<TypeDescription> matcher = SafeExtendsClassMatcher.extendsClass(
18+
ElementMatchers.is(SafeExtendsClassMatcher.class));
19+
20+
assertTrue(matcher.matches(TypeDescription.ForLoadedType.of(SafeExtendsClassMatcher.class)));
21+
}
22+
23+
@Test
24+
void testExtendsClass() {
25+
ElementMatcher.Junction<TypeDescription> matcher = SafeExtendsClassMatcher.extendsClass(
26+
ElementMatchers.is(ElementMatcher.Junction.AbstractBase.class), true);
27+
28+
assertTrue(matcher.matches(TypeDescription.ForLoadedType.of(SafeExtendsClassMatcher.class)));
29+
}
30+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.arex.inst.runtime.context;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import org.junit.jupiter.api.AfterAll;
6+
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.Test;
8+
import org.mockito.Mockito;
9+
10+
/**
11+
* @since 2024/1/12
12+
*/
13+
class RepeatedCollectManagerTest {
14+
@BeforeAll
15+
static void setUp() {
16+
Mockito.mockStatic(ContextManager.class);
17+
}
18+
@AfterAll
19+
static void tearDown() {
20+
Mockito.clearAllCaches();
21+
}
22+
23+
@Test
24+
void test() {
25+
assertTrue(RepeatedCollectManager.validate());
26+
assertTrue(RepeatedCollectManager.exitAndValidate());
27+
28+
Mockito.when(ContextManager.needRecord()).thenReturn(true);
29+
RepeatedCollectManager.enter();
30+
RepeatedCollectManager.enter();
31+
assertFalse(RepeatedCollectManager.exitAndValidate());
32+
assertTrue(RepeatedCollectManager.exitAndValidate());
33+
}
34+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.arex.foundation.util;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import static org.mockito.Mockito.mockStatic;
5+
6+
import org.junit.jupiter.api.AfterEach;
7+
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.Test;
9+
import org.mockito.MockedStatic;
10+
11+
/**
12+
* @since 2024/1/12
13+
*/
14+
class NetUtilsTest {
15+
16+
@BeforeEach
17+
void setUp() {
18+
}
19+
20+
@AfterEach
21+
void tearDown() {
22+
}
23+
24+
@Test
25+
void getIpAddress() {
26+
try (MockedStatic<NetUtils> netUtils = mockStatic(NetUtils.class)) {
27+
netUtils.when(NetUtils::getIpAddress).thenReturn("127.0.0.1");
28+
assertEquals("127.0.0.1", NetUtils.getIpAddress());
29+
}
30+
}
31+
32+
@Test
33+
void checkTcpPortAvailable() {
34+
assertEquals(-1, NetUtils.checkTcpPortAvailable(1));
35+
36+
assertEquals(8080, NetUtils.checkTcpPortAvailable(8080));
37+
}
38+
39+
@Test
40+
void isTcpPortAvailable() {
41+
assertFalse(NetUtils.isTcpPortAvailable(1));
42+
43+
assertTrue(NetUtils.isTcpPortAvailable(8080));
44+
}
45+
}

arex-instrumentation/redis/arex-jedis-v2/src/main/java/io/arex/inst/jedis/v2/JedisWrapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.arex.inst.jedis.v2;
22

33
import io.arex.agent.bootstrap.model.MockResult;
4+
import io.arex.agent.bootstrap.util.ArrayUtils;
45
import io.arex.inst.runtime.context.ContextManager;
56
import io.arex.inst.runtime.serializer.Serializer;
67
import io.arex.inst.redis.common.RedisExtractor;
@@ -527,8 +528,8 @@ public String ping(String message) {
527528
* mset/msetnx
528529
*/
529530
private <U> U call(String command, String[] keysValues, Callable<U> callable, U defaultValue) {
530-
if (keysValues == null || keysValues.length == 0) {
531-
return null;
531+
if (ArrayUtils.isEmpty(keysValues)) {
532+
return defaultValue;
532533
}
533534

534535
if (keysValues.length == 2) {

arex-instrumentation/redis/arex-jedis-v2/src/test/java/io/arex/inst/jedis/v2/JedisWrapperTest.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.arex.inst.runtime.context.ContextManager;
66
import org.junit.jupiter.api.AfterAll;
77
import org.junit.jupiter.api.BeforeAll;
8+
import org.junit.jupiter.api.Test;
89
import org.junit.jupiter.api.extension.ExtendWith;
910
import org.junit.jupiter.params.ParameterizedTest;
1011
import org.junit.jupiter.params.provider.Arguments;
@@ -52,6 +53,33 @@ static void tearDown() {
5253
Mockito.clearAllCaches();
5354
}
5455

56+
@Test
57+
void callWithEmptyKeysValuesReturnsDefault() {
58+
long result = target.msetnx( new String[]{});
59+
assertEquals(0, result);
60+
}
61+
62+
@Test
63+
void callWithTwoKeysValuesReturnsCallableResult() {
64+
Mockito.when(ContextManager.needRecord()).thenReturn(false);
65+
Mockito.when(client.getIntegerReply()).thenReturn(1L);
66+
try (MockedConstruction<RedisExtractor> mocked = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
67+
})) {
68+
long result = target.msetnx("key", "value");
69+
assertEquals(1L, result);
70+
71+
result = target.msetnx("key1", "value1", "key2", "value2", "key3", "value3");
72+
assertEquals(1L, result);
73+
74+
result = target.exists("key1", "key2", "key3");
75+
assertEquals(1L, result);
76+
} catch (Exception e) {
77+
assertThrows(NullPointerException.class, () -> {
78+
throw e;
79+
});
80+
}
81+
}
82+
5583
@ParameterizedTest
5684
@MethodSource("callCase")
5785
void call(Runnable mocker, Predicate<String> predicate) {
@@ -89,4 +117,4 @@ static Stream<Arguments> callCase() {
89117
arguments(mocker3, predicate2)
90118
);
91119
}
92-
}
120+
}

arex-instrumentation/redis/arex-jedis-v4/src/main/java/io/arex/inst/jedis/v4/JedisWrapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.arex.inst.jedis.v4;
22

3+
import io.arex.agent.bootstrap.util.ArrayUtils;
34
import io.arex.inst.runtime.context.ContextManager;
45
import io.arex.inst.runtime.serializer.Serializer;
56
import io.arex.agent.bootstrap.model.MockResult;
@@ -572,8 +573,8 @@ public String ping(String message) {
572573
* mset/msetnx
573574
*/
574575
private <U> U call(String command, String[] keysValues, Callable<U> callable, U defaultValue) {
575-
if (keysValues == null || keysValues.length == 0) {
576-
return null;
576+
if (ArrayUtils.isEmpty(keysValues)) {
577+
return defaultValue;
577578
}
578579

579580
if (keysValues.length == 2) {

arex-instrumentation/redis/arex-jedis-v4/src/test/java/io/arex/inst/jedis/v4/JedisWrapperTest.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import io.arex.inst.runtime.context.ContextManager;
66
import org.junit.jupiter.api.AfterAll;
77
import org.junit.jupiter.api.BeforeAll;
8+
import org.junit.jupiter.api.Test;
89
import org.junit.jupiter.api.extension.ExtendWith;
9-
import org.junit.jupiter.api.function.Executable;
1010
import org.junit.jupiter.params.ParameterizedTest;
1111
import org.junit.jupiter.params.provider.Arguments;
1212
import org.junit.jupiter.params.provider.MethodSource;
@@ -18,8 +18,8 @@
1818
import java.util.function.Predicate;
1919
import java.util.stream.Stream;
2020

21+
import static org.junit.jupiter.api.Assertions.assertEquals;
2122
import static org.junit.jupiter.api.Assertions.assertThrows;
22-
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
2323
import static org.junit.jupiter.api.Assertions.assertTrue;
2424
import static org.junit.jupiter.params.provider.Arguments.arguments;
2525
import static org.mockito.ArgumentMatchers.any;
@@ -48,6 +48,33 @@ static void tearDown() {
4848
Mockito.clearAllCaches();
4949
}
5050

51+
@Test
52+
void callWithEmptyKeysValuesReturnsDefault() {
53+
long result = target.msetnx( new String[]{});
54+
assertEquals(0, result);
55+
}
56+
57+
@Test
58+
void callWithTwoKeysValuesReturnsCallableResult() {
59+
Mockito.when(ContextManager.needRecord()).thenReturn(false);
60+
Mockito.when(connection.executeCommand(any(CommandObject.class))).thenReturn(1L);
61+
try (MockedConstruction<RedisExtractor> mocked = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
62+
})) {
63+
long result = target.msetnx("key", "value");
64+
assertEquals(1L, result);
65+
66+
result = target.msetnx("key1", "value1", "key2", "value2", "key3", "value3");
67+
assertEquals(1L, result);
68+
69+
result = target.exists("key1", "key2", "key3");
70+
assertEquals(1L, result);
71+
} catch (Exception e) {
72+
assertThrows(NullPointerException.class, () -> {
73+
throw e;
74+
});
75+
}
76+
}
77+
5178
@ParameterizedTest
5279
@MethodSource("callCase")
5380
void call(Runnable mocker, Predicate<String> predicate) {
@@ -85,4 +112,4 @@ static Stream<Arguments> callCase() {
85112
arguments(mocker3, predicate2)
86113
);
87114
}
88-
}
115+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.arex.inst.redis.common;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import java.util.Arrays;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import org.junit.jupiter.api.Test;
9+
10+
/**
11+
* @since 2024/1/12
12+
*/
13+
class RedisKeyUtilTest {
14+
15+
@Test
16+
void generateWithIterableKeys() {
17+
String result = RedisKeyUtil.generate(Arrays.asList("key1", "key2", "key3"));
18+
assertEquals("key1;key2;key3", result);
19+
}
20+
21+
@Test
22+
void generateWithMapKeys() {
23+
Map<String, String> map = new HashMap<>();
24+
map.put("key1", "value1");
25+
map.put("key2", "value2");
26+
String result = RedisKeyUtil.generate(map);
27+
assertTrue(result.contains("key1"));
28+
assertTrue(result.contains("key2"));
29+
}
30+
31+
@Test
32+
void generateWithVarargsKeys() {
33+
String result = RedisKeyUtil.generate("key1", "key2", "key3");
34+
assertEquals("key1;key2;key3", result);
35+
}
36+
37+
@Test
38+
void generateWithEmptyVarargsKeys() {
39+
String result = RedisKeyUtil.generate();
40+
assertEquals("", result);
41+
}
42+
43+
@Test
44+
void generateWithSingleVarargsKey() {
45+
String result = RedisKeyUtil.generate("key1");
46+
assertEquals("key1", result);
47+
}
48+
49+
@Test
50+
void generateWithByteValue() {
51+
String result = RedisKeyUtil.generate(new byte[]{'k', 'e', 'y'});
52+
assertEquals("key", result);
53+
}
54+
55+
@Test
56+
void generateWithCharValue() {
57+
String result = RedisKeyUtil.generate(new char[]{'k', 'e', 'y'});
58+
assertEquals("key", result);
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.arex.inst.time;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import io.arex.agent.bootstrap.TraceContextManager;
6+
import io.arex.agent.bootstrap.cache.TimeCache;
7+
import org.junit.jupiter.api.AfterAll;
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.api.Test;
10+
import org.mockito.Mockito;
11+
12+
/**
13+
* @since 2024/1/12
14+
*/
15+
class TimeMachineInterceptorTest {
16+
@BeforeAll
17+
static void setUp() {
18+
Mockito.mockStatic(TraceContextManager.class);
19+
}
20+
21+
@AfterAll
22+
static void tearDown() {
23+
Mockito.clearAllCaches();
24+
}
25+
26+
@Test
27+
void onEnter() {
28+
// traceId is not null
29+
Mockito.when(TraceContextManager.get()).thenReturn("test");
30+
assertEquals(0, TimeCache.get());
31+
TimeCache.put(1L);
32+
assertNotEquals(0, TimeMachineInterceptor.onEnter());
33+
}
34+
35+
@Test
36+
void onExit() {
37+
long result = 456L;
38+
TimeMachineInterceptor.onExit(123L, result);
39+
assertEquals(456L, result);
40+
}
41+
}

0 commit comments

Comments
 (0)