From 1723e0590fc7d71a98b30b93501502bf76cca2de Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Fri, 26 Jan 2024 11:51:34 +0100 Subject: [PATCH] Split in separate files --- .../test/restate_test_environment.ts | 129 ++++++++++++++++++ typescript/end-to-end-testing/test/test.ts | 120 ++-------------- 2 files changed, 140 insertions(+), 109 deletions(-) create mode 100644 typescript/end-to-end-testing/test/restate_test_environment.ts diff --git a/typescript/end-to-end-testing/test/restate_test_environment.ts b/typescript/end-to-end-testing/test/restate_test_environment.ts new file mode 100644 index 00000000..65060ea4 --- /dev/null +++ b/typescript/end-to-end-testing/test/restate_test_environment.ts @@ -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 { + // 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 { + 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 { + let startedRestateHttpServer = await prepareRestateServer(mountServicesFn); + let startedRestateContainer = await prepareRestateTestContainer( + (startedRestateHttpServer.address() as net.AddressInfo).port + ); + return new RestateTestEnvironment( + startedRestateHttpServer, + startedRestateContainer + ); + } +} diff --git a/typescript/end-to-end-testing/test/test.ts b/typescript/end-to-end-testing/test/test.ts index 7418172f..cf9ce340 100644 --- a/typescript/end-to-end-testing/test/test.ts +++ b/typescript/end-to-end-testing/test/test.ts @@ -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 { - // 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 { - 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 () => {