Skip to content

Commit

Permalink
Split in separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
slinkydeveloper committed Jan 26, 2024
1 parent d0094f8 commit 1723e05
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 109 deletions.
129 changes: 129 additions & 0 deletions typescript/end-to-end-testing/test/restate_test_environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import * as restate from "@restatedev/restate-sdk";

import {
GenericContainer,
StartedTestContainer,
TestContainers,
Wait,
} from "testcontainers";
import * as http2 from "http2";
import * as net from "net";

// Prepare the restate server
async function prepareRestateServer(
mountServicesFn: (server: restate.RestateServer) => void
): Promise<http2.Http2Server> {
// Prepare RestateServer
const restateServer = restate.createServer();
mountServicesFn(restateServer);

// Start HTTP2 server on random port
const restateHttpServer = http2.createServer(restateServer);
await new Promise((resolve, reject) => {
restateHttpServer
.listen(0)
.once("listening", resolve)
.once("error", reject);
});
const restateServerPort = (restateHttpServer.address() as net.AddressInfo)
.port;
console.info(`Started listening on port ${restateServerPort}`);

return restateHttpServer;
}

// Prepare the restate testcontainer
async function prepareRestateTestContainer(
restateServerPort: number
): Promise<StartedTestContainer> {
const restateContainer = new GenericContainer(
"docker.io/restatedev/restate:latest"
)
// Expose ports
.withExposedPorts(8080, 9070)
// Wait start on health checks
.withWaitStrategy(
Wait.forAll([
Wait.forHttp("/grpc.health.v1.Health/Check", 8080),
Wait.forHttp("/health", 9070),
])
);

// This MUST be executed before starting the restate container
// Expose host port to access the restate server
await TestContainers.exposeHostPorts(restateServerPort);

// Start restate container
const startedRestateContainer = await restateContainer.start();

// From now on, if something fails, stop the container to cleanup the environment
try {
console.info("Going to register services");

// Register this service endpoint
const res = await fetch(
`http://${startedRestateContainer.getHost()}:${startedRestateContainer.getMappedPort(
9070
)}/deployments`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// See https://node.testcontainers.org/features/networking/#expose-host-ports-to-container
uri: `http://host.testcontainers.internal:${restateServerPort}`,
}),
}
);
if (!res.ok) {
const badResponse = await res.text();
throw new Error(
`Error ${res.status} during registration: ${badResponse}`
);
}

console.info("Registered");
return startedRestateContainer;
} catch (e) {
await startedRestateContainer.stop();
throw e;
}
}

export class RestateTestEnvironment {
constructor(
readonly startedRestateHttpServer: http2.Http2Server,
readonly startedRestateContainer: StartedTestContainer
) {}

public baseUrl(): string {
return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(
8080
)}`;
}

public adminAPIBaseUrl(): string {
return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(
9070
)}`;
}

public async stop() {
await this.startedRestateContainer.stop();
this.startedRestateHttpServer.close();
}

public static async start(
mountServicesFn: (server: restate.RestateServer) => void
): Promise<RestateTestEnvironment> {
let startedRestateHttpServer = await prepareRestateServer(mountServicesFn);
let startedRestateContainer = await prepareRestateTestContainer(
(startedRestateHttpServer.address() as net.AddressInfo).port
);
return new RestateTestEnvironment(
startedRestateHttpServer,
startedRestateContainer
);
}
}
120 changes: 11 additions & 109 deletions typescript/end-to-end-testing/test/test.ts
Original file line number Diff line number Diff line change
@@ -1,134 +1,36 @@
import * as restate from "@restatedev/restate-sdk";

import {
GenericContainer,
StartedTestContainer,
TestContainers,
Wait,
} from "testcontainers";
import { createPromiseClient, Transport } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-node";
import { ExampleService } from "./generated/example_connect";
import * as http2 from "http2";
import * as net from "net";

import { protoMetadata } from "../src/generated/proto/example";
import { MyExampleService } from "../src/example_service";

// Prepare the restate server
async function prepareRestateServer(
mountServicesFn: (server: restate.RestateServer) => void
): Promise<http2.Http2Server> {
// Prepare RestateServer
const restateServer = restate.createServer();
mountServicesFn(restateServer);

// Start HTTP2 server on random port
const restateHttpServer = http2.createServer(restateServer);
await new Promise((resolve, reject) => {
restateHttpServer
.listen(0)
.once("listening", resolve)
.once("error", reject);
});
const restateServerPort = (restateHttpServer.address() as net.AddressInfo)
.port;
console.info(`Started listening on port ${restateServerPort}`);

return restateHttpServer;
}

// Prepare the restate testcontainer
async function prepareRestateTestContainer(
restateServerPort: number
): Promise<StartedTestContainer> {
const restateContainer = new GenericContainer(
"docker.io/restatedev/restate:latest"
)
// Expose ports
.withExposedPorts(8080, 9070)
// Wait start on health checks
.withWaitStrategy(
Wait.forAll([
Wait.forHttp("/grpc.health.v1.Health/Check", 8080),
Wait.forHttp("/health", 9070),
])
);

// This MUST be executed before starting the restate container
// Expose host port to access the restate server
await TestContainers.exposeHostPorts(restateServerPort);

// Start restate container
const startedRestateContainer = await restateContainer.start();

// From now on, if something fails, stop the container to cleanup the environment
try {
console.info("Going to register services");

// Register this service endpoint
const res = await fetch(
`http://${startedRestateContainer.getHost()}:${startedRestateContainer.getMappedPort(
9070
)}/deployments`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// See https://node.testcontainers.org/features/networking/#expose-host-ports-to-container
uri: `http://host.testcontainers.internal:${restateServerPort}`,
}),
}
);
if (!res.ok) {
const badResponse = await res.text();
throw new Error(
`Error ${res.status} during registration: ${badResponse}`
);
}

console.info("Registered");
return startedRestateContainer;
} catch (e) {
await startedRestateContainer.stop();
throw e;
}
}
import { RestateTestEnvironment } from "./restate_test_environment";

describe("ExampleService", () => {
let startedRestateHttpServer: http2.Http2Server;
let startedRestateContainer: StartedTestContainer;
let restateTestEnvironment: RestateTestEnvironment;
let clientTransport: Transport;

// Deploy Restate and the Service endpoint once for all the tests in this suite
beforeAll(async () => {
startedRestateHttpServer = await prepareRestateServer((restateServer) =>
restateServer.bindService({
service: "ExampleService",
instance: new MyExampleService(),
descriptor: protoMetadata,
})
);

startedRestateContainer = await prepareRestateTestContainer(
(startedRestateHttpServer.address() as net.AddressInfo).port
restateTestEnvironment = await RestateTestEnvironment.start(
(restateServer) =>
restateServer.bindService({
service: "ExampleService",
instance: new MyExampleService(),
descriptor: protoMetadata,
})
);

// Prepare the Connect client transport
clientTransport = createConnectTransport({
baseUrl: `http://${startedRestateContainer.getHost()}:${startedRestateContainer.getMappedPort(
8080
)}`,
baseUrl: restateTestEnvironment.baseUrl(),
httpVersion: "1.1",
});
}, 10_000);

// Stop Restate and the Service endpoint
afterAll(async () => {
await startedRestateContainer.stop();
startedRestateHttpServer.close();
await restateTestEnvironment.stop();
});

it("works", async () => {
Expand Down

0 comments on commit 1723e05

Please sign in to comment.