Skip to content

Commit a863d64

Browse files
Update test suite to 3.0 (#495)
1 parent 82d62cb commit a863d64

File tree

9 files changed

+306
-84
lines changed

9 files changed

+306
-84
lines changed

.github/workflows/integration.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ jobs:
105105
cache-to: type=gha,mode=max,scope=${{ github.workflow }}
106106

107107
- name: Run test tool
108-
uses: restatedev/sdk-test-suite@v2.4
108+
uses: restatedev/sdk-test-suite@v3.0
109109
with:
110110
restateContainerImage: ${{ inputs.restateCommit != '' && 'localhost/restatedev/restate-commit-download:latest' || (inputs.restateImage != '' && inputs.restateImage || 'ghcr.io/restatedev/restate:main') }}
111111
serviceContainerImage: "restatedev/typescript-test-services"
112112
exclusionsFile: "packages/restate-e2e-services/exclusions.yaml"
113113
testArtifactOutput: "sdk-typescript-integration-test-report"
114+
serviceContainerEnvFile: "packages/restate-e2e-services/.env"

packages/restate-e2e-services/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
RESTATE_LOGGING=TRACE
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,26 @@
1-
exclusions: {}
1+
exclusions:
2+
"alwaysSuspending":
3+
- "dev.restate.sdktesting.tests.Cancellation.cancelFromContext"
4+
- "dev.restate.sdktesting.tests.Combinators.awakeableOrTimeoutUsingAwaitAny"
5+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.callWithIdempotencyKey"
6+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.oneWayCallWithIdempotencyKey"
7+
"default":
8+
- "dev.restate.sdktesting.tests.Cancellation.cancelFromContext"
9+
- "dev.restate.sdktesting.tests.Combinators.awakeableOrTimeoutUsingAwaitAny"
10+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.callWithIdempotencyKey"
11+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.oneWayCallWithIdempotencyKey"
12+
"singleThreadSinglePartition":
13+
- "dev.restate.sdktesting.tests.Cancellation.cancelFromContext"
14+
- "dev.restate.sdktesting.tests.Combinators.awakeableOrTimeoutUsingAwaitAny"
15+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.callWithIdempotencyKey"
16+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.oneWayCallWithIdempotencyKey"
17+
"threeNodes":
18+
- "dev.restate.sdktesting.tests.Cancellation.cancelFromContext"
19+
- "dev.restate.sdktesting.tests.Combinators.awakeableOrTimeoutUsingAwaitAny"
20+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.callWithIdempotencyKey"
21+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.oneWayCallWithIdempotencyKey"
22+
"threeNodesAlwaysSuspending":
23+
- "dev.restate.sdktesting.tests.Cancellation.cancelFromContext"
24+
- "dev.restate.sdktesting.tests.Combinators.awakeableOrTimeoutUsingAwaitAny"
25+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.callWithIdempotencyKey"
26+
- "dev.restate.sdktesting.tests.ServiceToServiceCommunication.oneWayCallWithIdempotencyKey"

packages/restate-e2e-services/src/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import "./workflow.js";
2323
import "./proxy.js";
2424
import "./test_utils.js";
2525
import "./kill.js";
26+
import "./virtual_object_command_interpreter.js";
2627

2728
import { REGISTRY } from "./services.js";
2829

packages/restate-e2e-services/src/cancel_test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ const blockingService = restate.object({
4848
handlers: {
4949
async block(ctx: restate.ObjectContext, request: BlockingOperation) {
5050
const { id, promise } = ctx.awakeable();
51-
// DO NOT await the next CALL otherwise the test deadlocks.
52-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
53-
ctx.objectClient(AwakeableHolder, "cancel").hold(id);
51+
await ctx.objectClient(AwakeableHolder, ctx.key).hold(id);
5452
await promise;
5553

5654
switch (request) {

packages/restate-e2e-services/src/kill.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import * as restate from "@restatedev/restate-sdk";
1111
import { REGISTRY } from "./services.js";
1212
import type { AwakeableHolder } from "./awakeable_holder.js";
1313

14-
const kill = restate.service({
14+
const kill = restate.object({
1515
name: "KillTestRunner",
1616
handlers: {
1717
async startCallTree(ctx: restate.ObjectContext) {
18-
await ctx.objectClient(killSingleton, "").recursiveCall();
18+
await ctx.objectClient(killSingleton, ctx.key).recursiveCall();
1919
},
2020
},
2121
});
@@ -26,11 +26,11 @@ const killSingleton = restate.object({
2626
async recursiveCall(ctx: restate.ObjectContext) {
2727
const { id, promise } = ctx.awakeable();
2828
ctx
29-
.objectSendClient<AwakeableHolder>({ name: "AwakeableHolder" }, "kill")
29+
.objectSendClient<AwakeableHolder>({ name: "AwakeableHolder" }, ctx.key)
3030
.hold(id);
3131
await promise;
3232

33-
await ctx.objectClient(killSingleton, "").recursiveCall();
33+
await ctx.objectClient(killSingleton, ctx.key).recursiveCall();
3434
},
3535

3636
isUnlocked() {
@@ -39,5 +39,5 @@ const killSingleton = restate.object({
3939
},
4040
});
4141

42-
REGISTRY.addService(kill);
42+
REGISTRY.addObject(kill);
4343
REGISTRY.addObject(killSingleton);

packages/restate-e2e-services/src/proxy.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111

1212
import * as restate from "@restatedev/restate-sdk";
1313
import { REGISTRY } from "./services.js";
14+
import { TerminalError } from "@restatedev/restate-sdk";
1415

1516
type ProxyRequest = {
1617
serviceName: string;
1718
virtualObjectKey?: string;
1819
handlerName: string;
1920
message: Array<number>;
2021
delayMillis?: number;
22+
idempotencyKey?: string;
2123
};
2224

2325
type ManyCallRequest = {
@@ -30,6 +32,10 @@ function rawCall(
3032
ctx: restate.Context,
3133
request: ProxyRequest
3234
): Promise<Uint8Array> {
35+
// TODO add idempotency key support here
36+
if (request.idempotencyKey != undefined) {
37+
throw new TerminalError("idempotency key not supported yet");
38+
}
3339
return ctx.genericCall({
3440
service: request.serviceName,
3541
method: request.handlerName,
@@ -40,7 +46,11 @@ function rawCall(
4046
});
4147
}
4248

43-
function rawSend(ctx: restate.Context, request: ProxyRequest) {
49+
function rawSend(ctx: restate.Context, request: ProxyRequest): Promise<string> {
50+
// TODO add idempotency key support here
51+
if (request.idempotencyKey != undefined) {
52+
throw new TerminalError("idempotency key not supported yet");
53+
}
4454
ctx.genericSend({
4555
service: request.serviceName,
4656
method: request.handlerName,
@@ -49,6 +59,8 @@ function rawSend(ctx: restate.Context, request: ProxyRequest) {
4959
parameter: new Uint8Array(request.message),
5060
delay: request.delayMillis,
5161
});
62+
// TODO this should return the invocation id
63+
return Promise.resolve("unknown");
5264
}
5365

5466
const o = restate.service({
@@ -59,15 +71,15 @@ const o = restate.service({
5971
},
6072

6173
async oneWayCall(ctx: restate.Context, request: ProxyRequest) {
62-
rawSend(ctx, request);
74+
return rawSend(ctx, request);
6375
},
6476

6577
async manyCalls(ctx: restate.Context, request: ManyCallRequest[]) {
6678
const toAwait = [];
6779

6880
for (const r of request) {
6981
if (r.oneWayCall) {
70-
rawSend(ctx, r.proxyRequest);
82+
await rawSend(ctx, r.proxyRequest);
7183
continue;
7284
}
7385
const promise = rawCall(ctx, r.proxyRequest);

packages/restate-e2e-services/src/test_utils.ts

Lines changed: 8 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,7 @@
1010
import * as restate from "@restatedev/restate-sdk";
1111
import { REGISTRY } from "./services.js";
1212

13-
import type { AwakeableHolder } from "./awakeable_holder.js";
14-
import * as process from "node:process";
15-
import { ListObject } from "./list.js";
16-
17-
const AwakeableHolder: AwakeableHolder = { name: "AwakeableHolder" };
18-
const ListObject: ListObject = { name: "ListObject" };
19-
20-
type Command =
21-
| { type: "createAwakeableAndAwaitIt"; awakeableKey: string }
22-
| { type: "getEnvVariable"; envName: string };
23-
24-
interface InterpretRequest {
25-
listName: string;
26-
commands: Command[];
27-
}
13+
import { TerminalError } from "@restatedev/restate-sdk";
2814

2915
const o = restate.service({
3016
name: "TestUtilsService",
@@ -51,29 +37,6 @@ const o = restate.service({
5137
}
5238
),
5339

54-
async createAwakeableAndAwaitIt(
55-
ctx: restate.Context,
56-
req: { awakeableKey: string; awaitTimeout?: number }
57-
): Promise<{ type: "timeout" } | { type: "result"; value: string }> {
58-
const { id, promise } = ctx.awakeable<string>();
59-
60-
await ctx.objectClient(AwakeableHolder, req.awakeableKey).hold(id);
61-
62-
if (!req.awaitTimeout) {
63-
return { type: "result", value: await promise };
64-
}
65-
66-
try {
67-
const res = await promise.orTimeout(req.awaitTimeout);
68-
return { type: "result", value: res };
69-
} catch (e) {
70-
if (e instanceof restate.TimeoutError) {
71-
return { type: "timeout" };
72-
}
73-
throw e;
74-
}
75-
},
76-
7740
async sleepConcurrently(
7841
ctx: restate.Context,
7942
millisDuration: number[]
@@ -102,42 +65,16 @@ const o = restate.service({
10265
return invokedSideEffects;
10366
},
10467

105-
async getEnvVariable(ctx: restate.Context, env: string): Promise<string> {
106-
return ctx.run(() => process.env[env] ?? "");
107-
},
108-
109-
async interpretCommands(
68+
async cancelInvocation(
69+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
11070
ctx: restate.Context,
111-
req: InterpretRequest
71+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
72+
invocationId: string
11273
): Promise<void> {
113-
const listClient = ctx.objectSendClient(ListObject, req.listName);
114-
115-
async function createAwakeableAndAwaitIt(
116-
awakeableKey: string
117-
): Promise<string> {
118-
const { id, promise } = ctx.awakeable<string>();
119-
await ctx.objectClient(AwakeableHolder, awakeableKey).hold(id);
120-
return promise;
121-
}
122-
123-
async function getEnvVariable(envName: string): Promise<string> {
124-
return ctx.run(() => process.env[envName] ?? "");
125-
}
126-
127-
for (const command of req.commands) {
128-
switch (command.type) {
129-
case "createAwakeableAndAwaitIt":
130-
listClient.append(
131-
await createAwakeableAndAwaitIt(command.awakeableKey)
132-
);
133-
break;
134-
case "getEnvVariable":
135-
listClient.append(await getEnvVariable(command.envName));
136-
break;
137-
}
138-
}
74+
// TODO add cancel invocation here!
75+
return Promise.reject(new TerminalError("cancel is not supported yet"));
13976
},
14077
},
14178
});
14279

143-
REGISTRY.addObject(o);
80+
REGISTRY.addService(o);

0 commit comments

Comments
 (0)