Skip to content

Commit adb19c5

Browse files
authored
tests: Adjust scenario tests according to latest maint naming changes (#3090)
* rename maint options according to the latest client options * adjust env variables cae repo uses RE_FAULT_INJECTOR_URL for fault injector DATABASE_NAME is needed to choose from the many databases in cae * fix connection cleanup test
1 parent 0438865 commit adb19c5

9 files changed

+419
-209
lines changed

packages/client/lib/tests/test-scenario/configuration.e2e.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "./test-scenario.util";
1212
import { createClient } from "../../..";
1313
import { FaultInjectorClient } from "./fault-injector-client";
14-
import { MovingEndpointType } from "../../../dist/lib/client/enterprise-maintenance-manager";
14+
import { MovingEndpointType } from "../../../lib/client/enterprise-maintenance-manager";
1515
import { RedisTcpSocketOptions } from "../../client/socket";
1616

1717
describe("Client Configuration and Handshake", () => {
@@ -59,7 +59,7 @@ describe("Client Configuration and Handshake", () => {
5959
it(`clientHandshakeWithEndpointType '${endpointType}'`, async () => {
6060
try {
6161
client = await createTestClient(clientConfig, {
62-
maintMovingEndpointType: endpointType,
62+
maintEndpointType: endpointType
6363
});
6464
client.on("error", () => {});
6565

@@ -154,7 +154,7 @@ describe("Client Configuration and Handshake", () => {
154154
describe("Feature Enablement", () => {
155155
it("connectionHandshakeIncludesEnablingNotifications", async () => {
156156
client = await createTestClient(clientConfig, {
157-
maintPushNotifications: "enabled",
157+
maintNotifications: "enabled"
158158
});
159159

160160
const { action_id } = await faultInjectorClient.migrateAndBindAction({
@@ -180,7 +180,7 @@ describe("Client Configuration and Handshake", () => {
180180
it("disabledDontReceiveNotifications", async () => {
181181
try {
182182
client = await createTestClient(clientConfig, {
183-
maintPushNotifications: "disabled",
183+
maintNotifications: "disabled",
184184
socket: {
185185
reconnectStrategy: false
186186
}

packages/client/lib/tests/test-scenario/connection-handoff.e2e.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,25 @@ describe("Connection Handoff", () => {
8686
{
8787
name: "external-ip",
8888
clientOptions: {
89-
maintMovingEndpointType: "external-ip",
89+
maintEndpointType: "external-ip",
9090
},
9191
},
9292
{
9393
name: "external-fqdn",
9494
clientOptions: {
95-
maintMovingEndpointType: "external-fqdn",
95+
maintEndpointType: "external-fqdn",
9696
},
9797
},
9898
{
9999
name: "auto",
100100
clientOptions: {
101-
maintMovingEndpointType: "auto",
101+
maintEndpointType: "auto",
102102
},
103103
},
104104
{
105105
name: "none",
106106
clientOptions: {
107-
maintMovingEndpointType: "none",
107+
maintEndpointType: "none",
108108
},
109109
},
110110
];
@@ -156,6 +156,7 @@ describe("Connection Handoff", () => {
156156

157157
describe("Connection Cleanup", () => {
158158
it("should shut down old connection", async () => {
159+
client = await createTestClient(clientConfig);
159160
const spyObject = spyOnTemporaryClientInstanceMethod(client, "destroy");
160161

161162
const { action_id: lowTimeoutBindAndMigrateActionId } =

packages/client/lib/tests/test-scenario/fault-injector-client.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ export class FaultInjectorClient {
5454
return this.#request<T>("POST", "/action", action);
5555
}
5656

57+
// public async printStatus() {
58+
// const action = {
59+
// type: 'execute_rladmin_command',
60+
// parameters: {
61+
// rladmin_command: "status",
62+
// bdb_id: "1"
63+
// }
64+
// }
65+
// const { action_id } = await this.#request<{action_id: string}>("POST", "/action", action);
66+
// const status = await this.waitForAction(action_id);
67+
// //@ts-ignore
68+
// console.log(status.output.output);
69+
// }
70+
5771
/**
5872
* Gets the status of a specific action.
5973
* @param actionId The ID of the action to check
@@ -87,7 +101,13 @@ export class FaultInjectorClient {
87101
while (Date.now() - startTime < maxWaitTime) {
88102
const action = await this.getActionStatus<ActionStatus>(actionId);
89103

90-
if (["finished", "failed", "success"].includes(action.status)) {
104+
if (action.status === "failed") {
105+
throw new Error(
106+
`Action id: ${actionId} failed! Error: ${action.error}`
107+
);
108+
}
109+
110+
if (["finished", "success"].includes(action.status)) {
91111
return action;
92112
}
93113

@@ -118,6 +138,7 @@ export class FaultInjectorClient {
118138
type: "migrate",
119139
params: {
120140
cluster_index: clusterIndexStr,
141+
bdb_id: bdbIdStr,
121142
},
122143
},
123144
{

packages/client/lib/tests/test-scenario/negative-tests.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe("Negative tests", () => {
77
() =>
88
createClient({
99
RESP: 2,
10-
maintPushNotifications: "enabled",
10+
maintNotifications: "enabled",
1111
}),
1212
"Error: Graceful Maintenance is only supported with RESP3",
1313
);
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import assert from "node:assert";
2+
import diagnostics_channel from "node:diagnostics_channel";
3+
import { FaultInjectorClient } from "./fault-injector-client";
4+
import {
5+
createTestClient,
6+
getDatabaseConfig,
7+
getDatabaseConfigFromEnv,
8+
getEnvConfig,
9+
RedisConnectionConfig,
10+
} from "./test-scenario.util";
11+
import { createClient } from "../../..";
12+
import { DiagnosticsEvent } from "../../client/enterprise-maintenance-manager";
13+
import { before } from "mocha";
14+
15+
describe("Push Notifications", () => {
16+
const createNotificationMessageHandler = (
17+
result: Record<DiagnosticsEvent["type"], number>,
18+
notifications: Array<DiagnosticsEvent["type"]>
19+
) => {
20+
return (message: unknown) => {
21+
if (notifications.includes((message as DiagnosticsEvent).type)) {
22+
const event = message as DiagnosticsEvent;
23+
result[event.type] = (result[event.type] ?? 0) + 1;
24+
}
25+
};
26+
};
27+
28+
let onMessageHandler: ReturnType<typeof createNotificationMessageHandler>;
29+
let clientConfig: RedisConnectionConfig;
30+
let client: ReturnType<typeof createClient<any, any, any, any>>;
31+
let faultInjectorClient: FaultInjectorClient;
32+
33+
before(() => {
34+
const envConfig = getEnvConfig();
35+
const redisConfig = getDatabaseConfigFromEnv(
36+
envConfig.redisEndpointsConfigPath
37+
);
38+
39+
faultInjectorClient = new FaultInjectorClient(envConfig.faultInjectorUrl);
40+
clientConfig = getDatabaseConfig(redisConfig);
41+
});
42+
43+
afterEach(() => {
44+
if (onMessageHandler!) {
45+
diagnostics_channel.unsubscribe("redis.maintenance", onMessageHandler);
46+
}
47+
48+
if (client && client.isOpen) {
49+
client.destroy();
50+
}
51+
});
52+
53+
describe("Push Notifications Enabled", () => {
54+
beforeEach(async () => {
55+
client = await createTestClient(clientConfig);
56+
57+
await client.flushAll();
58+
});
59+
60+
it("should receive FAILING_OVER and FAILED_OVER push notifications", async () => {
61+
const notifications: Array<DiagnosticsEvent["type"]> = [
62+
"FAILING_OVER",
63+
"FAILED_OVER",
64+
];
65+
66+
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
67+
68+
onMessageHandler = createNotificationMessageHandler(
69+
diagnosticsMap,
70+
notifications
71+
);
72+
73+
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
74+
75+
const { action_id: failoverActionId } =
76+
await faultInjectorClient.triggerAction({
77+
type: "failover",
78+
parameters: {
79+
bdb_id: clientConfig.bdbId.toString(),
80+
cluster_index: 0,
81+
},
82+
});
83+
84+
await faultInjectorClient.waitForAction(failoverActionId);
85+
86+
assert.strictEqual(
87+
diagnosticsMap.FAILING_OVER,
88+
1,
89+
"Should have received exactly one FAILING_OVER notification"
90+
);
91+
assert.strictEqual(
92+
diagnosticsMap.FAILED_OVER,
93+
1,
94+
"Should have received exactly one FAILED_OVER notification"
95+
);
96+
});
97+
});
98+
99+
describe("Push Notifications Disabled - Client", () => {
100+
beforeEach(async () => {
101+
client = await createTestClient(clientConfig, {
102+
maintNotifications: "disabled",
103+
});
104+
105+
client.on("error", (_err) => {
106+
// Expect the socket to be closed
107+
// Ignore errors
108+
});
109+
110+
await client.flushAll();
111+
});
112+
113+
it("should NOT receive FAILING_OVER and FAILED_OVER push notifications", async () => {
114+
const notifications: Array<DiagnosticsEvent["type"]> = [
115+
"FAILING_OVER",
116+
"FAILED_OVER",
117+
];
118+
119+
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
120+
121+
onMessageHandler = createNotificationMessageHandler(
122+
diagnosticsMap,
123+
notifications
124+
);
125+
126+
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
127+
128+
const { action_id: failoverActionId } =
129+
await faultInjectorClient.triggerAction({
130+
type: "failover",
131+
parameters: {
132+
bdb_id: clientConfig.bdbId.toString(),
133+
cluster_index: 0,
134+
},
135+
});
136+
137+
await faultInjectorClient.waitForAction(failoverActionId);
138+
139+
assert.strictEqual(
140+
diagnosticsMap.FAILING_OVER,
141+
undefined,
142+
"Should have received exactly one FAILING_OVER notification"
143+
);
144+
assert.strictEqual(
145+
diagnosticsMap.FAILED_OVER,
146+
undefined,
147+
"Should have received exactly one FAILED_OVER notification"
148+
);
149+
});
150+
});
151+
152+
describe("Push Notifications Disabled - Server", () => {
153+
beforeEach(async () => {
154+
client = await createTestClient(clientConfig);
155+
156+
client.on("error", (_err) => {
157+
// Expect the socket to be closed
158+
// Ignore errors
159+
});
160+
161+
await client.flushAll();
162+
});
163+
164+
before(async () => {
165+
const { action_id: disablePushNotificationsActionId } =
166+
await faultInjectorClient.triggerAction({
167+
type: "update_cluster_config",
168+
parameters: {
169+
config: { client_maint_notifications: false },
170+
},
171+
});
172+
173+
await faultInjectorClient.waitForAction(disablePushNotificationsActionId);
174+
});
175+
176+
after(async () => {
177+
const { action_id: enablePushNotificationsActionId } =
178+
await faultInjectorClient.triggerAction({
179+
type: "update_cluster_config",
180+
parameters: {
181+
config: { client_maint_notifications: true },
182+
},
183+
});
184+
185+
await faultInjectorClient.waitForAction(enablePushNotificationsActionId);
186+
});
187+
188+
it("should NOT receive FAILING_OVER and FAILED_OVER push notifications", async () => {
189+
const notifications: Array<DiagnosticsEvent["type"]> = [
190+
"FAILING_OVER",
191+
"FAILED_OVER",
192+
];
193+
194+
const diagnosticsMap: Record<DiagnosticsEvent["type"], number> = {};
195+
196+
onMessageHandler = createNotificationMessageHandler(
197+
diagnosticsMap,
198+
notifications
199+
);
200+
201+
diagnostics_channel.subscribe("redis.maintenance", onMessageHandler);
202+
203+
const { action_id: failoverActionId } =
204+
await faultInjectorClient.triggerAction({
205+
type: "failover",
206+
parameters: {
207+
bdb_id: clientConfig.bdbId.toString(),
208+
cluster_index: 0,
209+
},
210+
});
211+
212+
await faultInjectorClient.waitForAction(failoverActionId);
213+
214+
assert.strictEqual(
215+
diagnosticsMap.FAILING_OVER,
216+
undefined,
217+
"Should have received exactly one FAILING_OVER notification"
218+
);
219+
assert.strictEqual(
220+
diagnosticsMap.FAILED_OVER,
221+
undefined,
222+
"Should have received exactly one FAILED_OVER notification"
223+
);
224+
});
225+
});
226+
});

0 commit comments

Comments
 (0)