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

Add unit test with testcontainers #9

Merged
merged 5 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<mysql-connector.version>8.4.0</mysql-connector.version>
<okhttp.version>4.12.0</okhttp.version>
<protobuf.version>4.27.2</protobuf.version>
<testcontainers.version>1.19.8</testcontainers.version>
<testcontainers.version>1.20.0</testcontainers.version>
</properties>

<dependencies>
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/io/eigr/spawn/api/Spawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,10 @@ private Map<String, ActorOuterClass.Actor> getActors(List<Entity> entities) {

Map<String, String> tags = new HashMap<>();
ActorOuterClass.Metadata metadata = ActorOuterClass.Metadata.newBuilder()
.setChannelGroup(actorEntity.getChannel()).putAllTags(tags)
.addChannelGroup(ActorOuterClass.Channel.newBuilder()
.setTopic(actorEntity.getChannel())
.build())
.putAllTags(tags)
.build();

return ActorOuterClass.Actor.newBuilder()
Expand Down
10 changes: 9 additions & 1 deletion src/main/proto/eigr/functions/protocol/actors/actor.proto
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,19 @@ message ActorState {
message Metadata {
// A channel group represents a way to send actions to various actors
// that belong to a certain semantic group.
string channel_group = 1;
repeated Channel channel_group = 1;

map<string, string> tags = 2;
}

// Represents a Pub-Sub binding, where a actor can be subscribed to a channel
// and map a specific action to a specific topic if necessary
// if the action is not informed, the default action will be "receive".
message Channel {
string topic = 1;
string action = 2;
}

// The type that defines the runtime characteristics of the Actor.
// Regardless of the type of actor it is important that
// all actors are registered during the proxy and host initialization phase.
Expand Down
74 changes: 74 additions & 0 deletions src/test/java/io/eigr/spawn/AbstractContainerBaseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.eigr.spawn;

import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.PortBinding;
import io.eigr.spawn.api.Spawn;
import io.eigr.spawn.api.TransportOpts;
import io.eigr.spawn.api.exceptions.SpawnException;
import io.eigr.spawn.api.extensions.DependencyInjector;
import io.eigr.spawn.api.extensions.SimpleDependencyInjector;
import io.eigr.spawn.test.actors.ActorWithConstructor;
import io.eigr.spawn.test.actors.JoeActor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

abstract class AbstractContainerBaseTest {

private static final Logger log = LoggerFactory.getLogger(AbstractContainerBaseTest.class);
private static final GenericContainer<?> SPAWN_CONTAINER;
private static final String spawnProxyImage = "eigr/spawn-proxy:1.4.1-rc.1";
private static final String userFunctionPort = "8091";
private static final String spawnProxyPort = "9004";
protected static final Spawn spawnSystem;
protected static final String spawnSystemName = "spawn-system-test";

static {
Testcontainers.exposeHostPorts(8091);

SPAWN_CONTAINER = new GenericContainer<>(DockerImageName.parse(spawnProxyImage))
.withCreateContainerCmdModifier(e -> e.withHostConfig(HostConfig.newHostConfig()
.withPortBindings(PortBinding.parse("9004:9004"))))
.withEnv("TZ", "America/Fortaleza")
sleipnir marked this conversation as resolved.
Show resolved Hide resolved
.withEnv("SPAWN_PROXY_LOGGER_LEVEL", "DEBUG")
.withEnv("SPAWN_STATESTORE_KEY", "3Jnb0hZiHIzHTOih7t2cTEPEpY98Tu1wvQkPfq/XwqE=")
.withEnv("PROXY_ACTOR_SYSTEM_NAME", spawnSystemName)
.withEnv("PROXY_DATABASE_TYPE", "native")
.withEnv("PROXY_DATABASE_DATA_DIR", "mnesia_data")
.withEnv("NODE_COOKIE", "cookie-9ce3712b0c3ee21b582c30f942c0d4da-HLuZyQzy+nt0p0r/PVVFTp2tqfLom5igrdmwkYSuO+Q=")
.withEnv("POD_NAMESPACE", spawnSystemName)
.withEnv("POD_IP", spawnSystemName)
.withEnv("PROXY_HTTP_PORT", spawnProxyPort)
.withEnv("USER_FUNCTION_PORT", userFunctionPort)
.withEnv("USER_FUNCTION_HOST", "host.docker.internal") // Docker
.withExtraHost("host.docker.internal", "host-gateway") // Docker
// .withEnv("USER_FUNCTION_HOST", "host.containers.internal") // Podman
// .withExtraHost("host.containers.internal", "host-gateway") // Podman
.withExposedPorts(9004);
SPAWN_CONTAINER.start();

DependencyInjector injector = SimpleDependencyInjector.createInjector();
injector.bind(String.class, "Hello with Constructor");

spawnSystem = new Spawn.SpawnSystem()
.create(spawnSystemName)
.withActor(JoeActor.class)
.withActor(ActorWithConstructor.class, injector, arg -> new ActorWithConstructor((DependencyInjector) arg))
.withTerminationGracePeriodSeconds(5)
.withTransportOptions(TransportOpts.builder()
.port(8091)
.proxyPort(9004)
.build())
.build();

try {
spawnSystem.start();
} catch (SpawnException e) {
throw new RuntimeException(e);
}
log.info(String.format("%s started", spawnSystemName));
}
}

37 changes: 37 additions & 0 deletions src/test/java/io/eigr/spawn/ContainerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.eigr.spawn;

import io.eigr.spawn.api.ActorIdentity;
import io.eigr.spawn.api.ActorRef;
import io.eigr.spawn.api.exceptions.SpawnException;
import io.eigr.spawn.java.test.domain.Actor;
import org.junit.Test;

import java.util.Optional;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

public final class ContainerTest extends AbstractContainerBaseTest {

@Test
public void testApp() throws SpawnException {
ActorRef joeActor = spawnSystem.createActorRef(
ActorIdentity.of(spawnSystemName, "test_joe"));

Actor.Request msg = Actor.Request.newBuilder()
.setLanguage("erlang")
.build();

Optional<Actor.Reply> maybeReply =
joeActor.invoke("setLanguage", msg, Actor.Reply.class);

if (maybeReply.isPresent()) {
Actor.Reply reply = maybeReply.get();
assertNotNull(reply);
assertEquals("Hello From Java", reply.getResponse());
} else {
throw new RuntimeException("Error");
}

}
}