Skip to content

Commit

Permalink
Test multiple reminder state types + improve timer tests. (dapr#855)
Browse files Browse the repository at this point in the history
Signed-off-by: Artur Souza <[email protected]>
Signed-off-by: Mahmut Canga <[email protected]>
  • Loading branch information
artursouza authored and macromania committed Jun 21, 2023
1 parent 8378bb0 commit 7ade730
Show file tree
Hide file tree
Showing 15 changed files with 395 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
GOPROXY: https://proxy.golang.org
JDK_VER: ${{ matrix.java }}
DAPR_CLI_VER: 1.10.0
DAPR_RUNTIME_VER: 1.10.0
DAPR_RUNTIME_VER: 1.10.6-rc.2
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v1.10.0/install/install.sh
DAPR_CLI_REF:
DAPR_REF:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
GOPROXY: https://proxy.golang.org
JDK_VER: ${{ matrix.java }}
DAPR_CLI_VER: 1.10.0
DAPR_RUNTIME_VER: 1.10.0
DAPR_RUNTIME_VER: 1.10.6-rc.2
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v1.10.0/install/install.sh
DAPR_CLI_REF:
DAPR_REF:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,85 @@
import io.dapr.it.AppRun;
import io.dapr.it.BaseIT;
import io.dapr.it.DaprRun;
import io.dapr.it.actors.app.ActorReminderDataParam;
import io.dapr.it.actors.app.MyActorService;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;

import static io.dapr.it.Retry.callWithRetry;
import static io.dapr.it.actors.MyActorTestUtils.countMethodCalls;
import static io.dapr.it.actors.MyActorTestUtils.fetchMethodCallLogs;
import static io.dapr.it.actors.MyActorTestUtils.validateMethodCalls;
import static io.dapr.it.actors.MyActorTestUtils.*;

@RunWith(Parameterized.class)
public class ActorReminderRecoveryIT extends BaseIT {

private static final Logger logger = LoggerFactory.getLogger(ActorReminderRecoveryIT.class);

private static final String METHOD_NAME = "receiveReminder";

/**
* Parameters for this test.
* Param #1: useGrpc.
*
* @return Collection of parameter tuples.
*/
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{
"MyActorTest",
new ActorReminderDataParam("36", "String"),
"36"
},
{
"MyActorTest",
new ActorReminderDataParam("\"my_text\"", "String"),
"\"my_text\""
},
{
"MyActorBinaryTest",
new ActorReminderDataParam(new byte[]{0, 1}, "Binary"),
"AAE="
},
{
"MyActorObjectTest",
new ActorReminderDataParam("{\"name\":\"abc\",\"age\":30}", "Object"),
"abc,30"
},
});
}

public String actorType;

public ActorReminderDataParam reminderDataParam;

public String expectedReminderStateText;

public String reminderName = UUID.randomUUID().toString();

private ActorProxy proxy;

private ImmutablePair<AppRun, DaprRun> runs;

private DaprRun clientRun;

public ActorReminderRecoveryIT(
String actorType,
ActorReminderDataParam reminderDataParam,
String expectedReminderStateText) {
this.actorType = actorType;
this.reminderDataParam = reminderDataParam;
this.expectedReminderStateText = expectedReminderStateText;
}

@Before
public void init() throws Exception {
runs = startSplitDaprAndApp(
Expand All @@ -66,11 +115,10 @@ public void init() throws Exception {
Thread.sleep(3000);

ActorId actorId = new ActorId(UUID.randomUUID().toString());
String actorType="MyActorTest";
logger.debug("Creating proxy builder");

ActorProxyBuilder<ActorProxy> proxyBuilder =
new ActorProxyBuilder(actorType, ActorProxy.class, newActorClient());
new ActorProxyBuilder(this.actorType, ActorProxy.class, newActorClient());
logger.debug("Creating actorId");
logger.debug("Building proxy");
proxy = proxyBuilder.build(actorId);
Expand All @@ -80,7 +128,7 @@ public void init() throws Exception {
public void tearDown() {
// call unregister
logger.debug("Calling actor method 'stopReminder' to unregister reminder");
proxy.invokeMethod("stopReminder", "myReminder").block();
proxy.invokeMethod("stopReminder", this.reminderName).block();
}

/**
Expand All @@ -90,7 +138,9 @@ public void tearDown() {
@Test
public void reminderRecoveryTest() throws Exception {
logger.debug("Invoking actor method 'startReminder' which will register a reminder");
proxy.invokeMethod("startReminder", "myReminder").block();
proxy.invokeMethod("setReminderData", this.reminderDataParam).block();

proxy.invokeMethod("startReminder", this.reminderName).block();

logger.debug("Pausing 7 seconds to allow reminder to fire");
Thread.sleep(7000);
Expand All @@ -100,6 +150,7 @@ public void reminderRecoveryTest() throws Exception {
logs.clear();
logs.addAll(fetchMethodCallLogs(proxy));
validateMethodCalls(logs, METHOD_NAME, 3);
validateMessageContent(logs, METHOD_NAME, this.expectedReminderStateText);
}, 5000);

// Restarts runtime only.
Expand All @@ -121,6 +172,7 @@ public void reminderRecoveryTest() throws Exception {
logger.info("Fetching logs for " + METHOD_NAME);
List<MethodEntryTracker> newLogs = fetchMethodCallLogs(proxy);
validateMethodCalls(newLogs, METHOD_NAME, 1);
validateMessageContent(newLogs, METHOD_NAME, this.expectedReminderStateText);

logger.info("Pausing 10 seconds to allow reminder to fire a few times");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static io.dapr.it.Retry.callWithRetry;
import static io.dapr.it.actors.MyActorTestUtils.fetchMethodCallLogs;
import static io.dapr.it.actors.MyActorTestUtils.validateMethodCalls;
import static io.dapr.it.actors.MyActorTestUtils.validateMessageContent;
import static org.junit.Assert.assertNotEquals;

public class ActorTimerRecoveryIT extends BaseIT {
Expand Down Expand Up @@ -76,6 +77,7 @@ public void timerRecoveryTest() throws Exception {
logs.clear();
logs.addAll(fetchMethodCallLogs(proxy));
validateMethodCalls(logs, METHOD_NAME, 3);
validateMessageContent(logs, METHOD_NAME, "ping!");
}, 5000);

// Restarts app only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@
public class MethodEntryTracker {
private boolean isEnter;
private String methodName;
private String message;
private Date date;

public MethodEntryTracker(boolean isEnter, String methodName, Date date) {
this(isEnter, methodName, null, date);
}

public MethodEntryTracker(boolean isEnter, String methodName, String message, Date date) {
this.isEnter = isEnter;
this.methodName = methodName;
this.message = message;
this.date = date;
}

Expand All @@ -34,12 +40,16 @@ public String getMethodName() {
return this.methodName;
}

public String getMessage() {
return this.message;
}

public Date getDate() {
return this.date;
}

@Override
public String toString() {
return this.date + " " + this.isEnter + " " + this.methodName;
return this.date + " " + this.isEnter + " " + (this.message != null? this.message + " ":"") + this.methodName;
}
}
41 changes: 33 additions & 8 deletions sdk-tests/src/test/java/io/dapr/it/actors/MyActorTestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.List;
import java.util.stream.Collectors;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;

/**
* Utility class for tests that use MyActor class.
Expand All @@ -39,12 +39,26 @@ static int countMethodCalls(List<MethodEntryTracker> logs, String methodName) {
// Counts number of times reminder is invoked.
// Events for each actor method call include "enter" and "exit" calls, so they are divided by 2.
List<MethodEntryTracker> calls =
logs.stream().filter(x -> x.getMethodName().equals(methodName)).collect(Collectors.toList());
logs.stream().filter(x -> x.getMethodName().equals(methodName)).collect(Collectors.toList());
System.out.printf(
"Size of %s count list is %d, which means it's been invoked half that many times.\n", methodName, calls.size());
"Size of %s count list is %d, which means it's been invoked half that many times.\n", methodName, calls.size());
return calls.size() / 2;
}

/**
* Checks if all entries for a method call contain the same message.
* @param logs logs with info about method entries and exits returned from the app
* @param methodName name of the method to be validated
* @param message expected message
*/
static void validateMessageContent(List<MethodEntryTracker> logs, String methodName, String message) {
List<MethodEntryTracker> calls =
logs.stream().filter(x -> x.getMethodName().equals(methodName)).collect(Collectors.toList());
for (MethodEntryTracker m : calls) {
assertEquals(message, m.getMessage());
}
}

/**
* Validate the number of call of a given method.
* @param logs logs with info about method entries and exits returned from the app
Expand All @@ -66,11 +80,22 @@ static List<MethodEntryTracker> fetchMethodCallLogs(ActorProxy proxy) {
ArrayList<MethodEntryTracker> trackers = new ArrayList<MethodEntryTracker>();
for(String t : logs) {
String[] toks = t.split("\\|");
MethodEntryTracker m = new MethodEntryTracker(
toks[0].equals("Enter") ? true : false,
toks[1],
new Date(toks[2]));
trackers.add(m);
if (toks.length == 3) {
MethodEntryTracker m = new MethodEntryTracker(
toks[0].equals("Enter") ? true : false,
toks[1],
new Date(toks[2]));
trackers.add(m);
} else if (toks.length == 4) {
MethodEntryTracker m = new MethodEntryTracker(
toks[0].equals("Enter") ? true : false,
toks[1],
toks[2],
new Date(toks[3]));
trackers.add(m);
} else {
fail("Invalid log entry");
}
}

return trackers;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2021 The Dapr Authors
* Licensed 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 io.dapr.it.actors.app;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.dapr.utils.TypeRef;

/**
* This class is for passing string or binary data to the Actor for registering reminder later on during test.
*/
public class ActorReminderDataParam {

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private String data;

private byte[] binaryData;

private String typeHint;

public ActorReminderDataParam() {
}

public ActorReminderDataParam(String data, String typeHint) {
this.data = data;
this.typeHint = typeHint;
}

public ActorReminderDataParam(byte[] data, String typeHint) {
this.binaryData = data;
this.typeHint = typeHint;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

public byte[] getBinaryData() {
return binaryData;
}

public void setBinaryData(byte[] binaryData) {
this.binaryData = binaryData;
}

public String getTypeHint() {
return typeHint;
}

public void setTypeHint(String typeHint) {
this.typeHint = typeHint;
}

public <T> T asObject(TypeRef<T> type) throws Exception {
if (this.data != null) {
return OBJECT_MAPPER.readValue(this.data, OBJECT_MAPPER.constructType(type.getType()));
} else if (this.binaryData != null) {
return OBJECT_MAPPER.readValue(this.binaryData, OBJECT_MAPPER.constructType(type.getType()));
}
return null;
}
}
4 changes: 3 additions & 1 deletion sdk-tests/src/test/java/io/dapr/it/actors/app/MyActor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ public interface MyActor {

List<String> retrieveActiveActors();

void startReminder(String name);
void setReminderData(ActorReminderDataParam param);

void startReminder(String name) throws Exception;

void stopReminder(String name);

Expand Down
Loading

0 comments on commit 7ade730

Please sign in to comment.