Skip to content

Commit

Permalink
fix: jedis wrapper call NPE (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
mr3 authored Jan 12, 2024
1 parent 8374c98 commit e1965fa
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.sun.tools.attach.VirtualMachine;

import java.io.IOException;
import java.util.Arrays;

/**
* agent attacher
Expand Down Expand Up @@ -52,7 +53,8 @@ public static void main(String[] args) {
virtualMachine.detach();
} catch (Throwable e) {
// expected behavior, it will be returned as error stream to the caller, if any
e.printStackTrace();
System.err.printf("agent attach failed, pid: %s, args: %s, error: %s%n",
pid, Arrays.toString(args), e.getMessage());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.arex.inst.extension.matcher;

import static org.junit.jupiter.api.Assertions.*;

import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.jupiter.api.Test;

/**
* @since 2024/1/12
*/
class SafeExtendsClassMatcherTest {

@Test
void extendsClass() {
ElementMatcher.Junction<TypeDescription> matcher = SafeExtendsClassMatcher.extendsClass(
ElementMatchers.is(SafeExtendsClassMatcher.class));

assertTrue(matcher.matches(TypeDescription.ForLoadedType.of(SafeExtendsClassMatcher.class)));
}

@Test
void testExtendsClass() {
ElementMatcher.Junction<TypeDescription> matcher = SafeExtendsClassMatcher.extendsClass(
ElementMatchers.is(ElementMatcher.Junction.AbstractBase.class), true);

assertTrue(matcher.matches(TypeDescription.ForLoadedType.of(SafeExtendsClassMatcher.class)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.arex.inst.runtime.context;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

/**
* @since 2024/1/12
*/
class RepeatedCollectManagerTest {
@BeforeAll
static void setUp() {
Mockito.mockStatic(ContextManager.class);
}
@AfterAll
static void tearDown() {
Mockito.clearAllCaches();
}

@Test
void test() {
assertTrue(RepeatedCollectManager.validate());
assertTrue(RepeatedCollectManager.exitAndValidate());

Mockito.when(ContextManager.needRecord()).thenReturn(true);
RepeatedCollectManager.enter();
RepeatedCollectManager.enter();
assertFalse(RepeatedCollectManager.exitAndValidate());
assertTrue(RepeatedCollectManager.exitAndValidate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.arex.foundation.util;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mockStatic;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

/**
* @since 2024/1/12
*/
class NetUtilsTest {

@BeforeEach
void setUp() {
}

@AfterEach
void tearDown() {
}

@Test
void getIpAddress() {
try (MockedStatic<NetUtils> netUtils = mockStatic(NetUtils.class)) {
netUtils.when(NetUtils::getIpAddress).thenReturn("127.0.0.1");
assertEquals("127.0.0.1", NetUtils.getIpAddress());
}
}

@Test
void checkTcpPortAvailable() {
assertEquals(-1, NetUtils.checkTcpPortAvailable(1));

assertEquals(8080, NetUtils.checkTcpPortAvailable(8080));
}

@Test
void isTcpPortAvailable() {
assertFalse(NetUtils.isTcpPortAvailable(1));

assertTrue(NetUtils.isTcpPortAvailable(8080));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.arex.inst.jedis.v2;

import io.arex.agent.bootstrap.model.MockResult;
import io.arex.agent.bootstrap.util.ArrayUtils;
import io.arex.inst.runtime.context.ContextManager;
import io.arex.inst.runtime.serializer.Serializer;
import io.arex.inst.redis.common.RedisExtractor;
Expand Down Expand Up @@ -527,8 +528,8 @@ public String ping(String message) {
* mset/msetnx
*/
private <U> U call(String command, String[] keysValues, Callable<U> callable, U defaultValue) {
if (keysValues == null || keysValues.length == 0) {
return null;
if (ArrayUtils.isEmpty(keysValues)) {
return defaultValue;
}

if (keysValues.length == 2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.arex.inst.runtime.context.ContextManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
Expand Down Expand Up @@ -52,6 +53,33 @@ static void tearDown() {
Mockito.clearAllCaches();
}

@Test
void callWithEmptyKeysValuesReturnsDefault() {
long result = target.msetnx( new String[]{});
assertEquals(0, result);
}

@Test
void callWithTwoKeysValuesReturnsCallableResult() {
Mockito.when(ContextManager.needRecord()).thenReturn(false);
Mockito.when(client.getIntegerReply()).thenReturn(1L);
try (MockedConstruction<RedisExtractor> mocked = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
})) {
long result = target.msetnx("key", "value");
assertEquals(1L, result);

result = target.msetnx("key1", "value1", "key2", "value2", "key3", "value3");
assertEquals(1L, result);

result = target.exists("key1", "key2", "key3");
assertEquals(1L, result);
} catch (Exception e) {
assertThrows(NullPointerException.class, () -> {
throw e;
});
}
}

@ParameterizedTest
@MethodSource("callCase")
void call(Runnable mocker, Predicate<String> predicate) {
Expand Down Expand Up @@ -89,4 +117,4 @@ static Stream<Arguments> callCase() {
arguments(mocker3, predicate2)
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.arex.inst.jedis.v4;

import io.arex.agent.bootstrap.util.ArrayUtils;
import io.arex.inst.runtime.context.ContextManager;
import io.arex.inst.runtime.serializer.Serializer;
import io.arex.agent.bootstrap.model.MockResult;
Expand Down Expand Up @@ -572,8 +573,8 @@ public String ping(String message) {
* mset/msetnx
*/
private <U> U call(String command, String[] keysValues, Callable<U> callable, U defaultValue) {
if (keysValues == null || keysValues.length == 0) {
return null;
if (ArrayUtils.isEmpty(keysValues)) {
return defaultValue;
}

if (keysValues.length == 2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import io.arex.inst.runtime.context.ContextManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
Expand All @@ -18,8 +18,8 @@
import java.util.function.Predicate;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -48,6 +48,33 @@ static void tearDown() {
Mockito.clearAllCaches();
}

@Test
void callWithEmptyKeysValuesReturnsDefault() {
long result = target.msetnx( new String[]{});
assertEquals(0, result);
}

@Test
void callWithTwoKeysValuesReturnsCallableResult() {
Mockito.when(ContextManager.needRecord()).thenReturn(false);
Mockito.when(connection.executeCommand(any(CommandObject.class))).thenReturn(1L);
try (MockedConstruction<RedisExtractor> mocked = Mockito.mockConstruction(RedisExtractor.class, (mock, context) -> {
})) {
long result = target.msetnx("key", "value");
assertEquals(1L, result);

result = target.msetnx("key1", "value1", "key2", "value2", "key3", "value3");
assertEquals(1L, result);

result = target.exists("key1", "key2", "key3");
assertEquals(1L, result);
} catch (Exception e) {
assertThrows(NullPointerException.class, () -> {
throw e;
});
}
}

@ParameterizedTest
@MethodSource("callCase")
void call(Runnable mocker, Predicate<String> predicate) {
Expand Down Expand Up @@ -85,4 +112,4 @@ static Stream<Arguments> callCase() {
arguments(mocker3, predicate2)
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.arex.inst.redis.common;

import static org.junit.jupiter.api.Assertions.*;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;

/**
* @since 2024/1/12
*/
class RedisKeyUtilTest {

@Test
void generateWithIterableKeys() {
String result = RedisKeyUtil.generate(Arrays.asList("key1", "key2", "key3"));
assertEquals("key1;key2;key3", result);
}

@Test
void generateWithMapKeys() {
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
String result = RedisKeyUtil.generate(map);
assertTrue(result.contains("key1"));
assertTrue(result.contains("key2"));
}

@Test
void generateWithVarargsKeys() {
String result = RedisKeyUtil.generate("key1", "key2", "key3");
assertEquals("key1;key2;key3", result);
}

@Test
void generateWithEmptyVarargsKeys() {
String result = RedisKeyUtil.generate();
assertEquals("", result);
}

@Test
void generateWithSingleVarargsKey() {
String result = RedisKeyUtil.generate("key1");
assertEquals("key1", result);
}

@Test
void generateWithByteValue() {
String result = RedisKeyUtil.generate(new byte[]{'k', 'e', 'y'});
assertEquals("key", result);
}

@Test
void generateWithCharValue() {
String result = RedisKeyUtil.generate(new char[]{'k', 'e', 'y'});
assertEquals("key", result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.arex.inst.time;

import static org.junit.jupiter.api.Assertions.*;

import io.arex.agent.bootstrap.TraceContextManager;
import io.arex.agent.bootstrap.cache.TimeCache;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

/**
* @since 2024/1/12
*/
class TimeMachineInterceptorTest {
@BeforeAll
static void setUp() {
Mockito.mockStatic(TraceContextManager.class);
}

@AfterAll
static void tearDown() {
Mockito.clearAllCaches();
}

@Test
void onEnter() {
// traceId is not null
Mockito.when(TraceContextManager.get()).thenReturn("test");
assertEquals(0, TimeCache.get());
TimeCache.put(1L);
assertNotEquals(0, TimeMachineInterceptor.onEnter());
}

@Test
void onExit() {
long result = 456L;
TimeMachineInterceptor.onExit(123L, result);
assertEquals(456L, result);
}
}
Loading

0 comments on commit e1965fa

Please sign in to comment.