1
0
mirror of https://github.com/redis/node-redis.git synced 2025-12-09 21:21:11 +03:00
Files
node-redis/packages/client/lib/tests/test-scenario/configuration.e2e.ts
Pavel Pashov b97bbbe8c6 refactor(test): improve test scenario reliability and maintainability (#3077)
* refactor(test): improve test scenario reliability and maintainability

* tests: add resp3 check test (#1)

* test: refactor connection handoff tests with enhanced spy utility (#2)

* test: add comprehensive push notification disabled scenarios (#3)

* tests: add params config tests (#4)

* tests: add feature enablement tests (#5)

---------

Co-authored-by: Nikolay Karadzhov <nikolay.karadzhov@redis.com>
2025-09-18 12:45:55 +03:00

202 lines
6.4 KiB
TypeScript

import assert from "node:assert";
import diagnostics_channel from "node:diagnostics_channel";
import { DiagnosticsEvent } from "../../client/enterprise-maintenance-manager";
import {
RedisConnectionConfig,
createTestClient,
getDatabaseConfig,
getDatabaseConfigFromEnv,
getEnvConfig,
} from "./test-scenario.util";
import { createClient } from "../../..";
import { FaultInjectorClient } from "./fault-injector-client";
import { MovingEndpointType } from "../../../dist/lib/client/enterprise-maintenance-manager";
import { RedisTcpSocketOptions } from "../../client/socket";
describe("Client Configuration and Handshake", () => {
let clientConfig: RedisConnectionConfig;
let client: ReturnType<typeof createClient<any, any, any, any>>;
let faultInjectorClient: FaultInjectorClient;
let log: DiagnosticsEvent[] = [];
before(() => {
const envConfig = getEnvConfig();
const redisConfig = getDatabaseConfigFromEnv(
envConfig.redisEndpointsConfigPath,
);
faultInjectorClient = new FaultInjectorClient(envConfig.faultInjectorUrl);
clientConfig = getDatabaseConfig(redisConfig);
diagnostics_channel.subscribe("redis.maintenance", (event) => {
log.push(event as DiagnosticsEvent);
});
});
beforeEach(() => {
log.length = 0;
});
afterEach(async () => {
if (client && client.isOpen) {
await client.flushAll();
client.destroy();
}
});
describe("Parameter Configuration", () => {
const endpoints: MovingEndpointType[] = [
"auto",
// "internal-ip",
// "internal-fqdn",
"external-ip",
"external-fqdn",
"none",
];
for (const endpointType of endpoints) {
it(`clientHandshakeWithEndpointType '${endpointType}'`, async () => {
try {
client = await createTestClient(clientConfig, {
maintMovingEndpointType: endpointType,
});
client.on("error", () => {});
//need to copy those because they will be mutated later
const oldOptions = JSON.parse(JSON.stringify(client.options));
assert.ok(oldOptions);
const { action_id } = await faultInjectorClient.migrateAndBindAction({
bdbId: clientConfig.bdbId,
clusterIndex: 0,
});
await faultInjectorClient.waitForAction(action_id);
const movingEvent = log.find((event) => event.type === "MOVING");
assert(!!movingEvent, "Didnt receive moving PN");
let endpoint: string | undefined;
try {
//@ts-ignore
endpoint = movingEvent.data.push[3];
} catch (err) {
assert(
false,
`couldnt get endpoint from event ${JSON.stringify(movingEvent)}`,
);
}
assert(endpoint !== undefined, "no endpoint");
const newOptions = client.options;
assert.ok(newOptions);
if (oldOptions?.url) {
if (endpointType === "none") {
assert.equal(
newOptions!.url,
oldOptions.url,
"For movingEndpointTpe 'none', we expect old and new url to be the same",
);
} else {
assert.equal(
newOptions.url,
endpoint,
"Expected what came through the wire to be set in the new client",
);
assert.notEqual(
newOptions!.url,
oldOptions.url,
`For movingEndpointTpe ${endpointType}, we expect old and new url to be different`,
);
}
} else {
const oldSocket = oldOptions.socket as RedisTcpSocketOptions;
const newSocket = newOptions.socket as RedisTcpSocketOptions;
assert.ok(oldSocket);
assert.ok(newSocket);
if (endpointType === "none") {
assert.equal(
newSocket.host,
oldSocket.host,
"For movingEndpointTpe 'none', we expect old and new host to be the same",
);
} else {
assert.equal(
newSocket.host + ":" + newSocket.port,
endpoint,
"Expected what came through the wire to be set in the new client",
);
assert.notEqual(
newSocket.host,
oldSocket.host,
`For movingEndpointTpe ${endpointType}, we expect old and new host to be different`,
);
}
}
} catch (error: any) {
if (
endpointType === "internal-fqdn" ||
endpointType === "internal-ip"
) {
// errors are expected here, because we cannot connect to internal endpoints unless we are deployed in the same place as the server
} else {
assert(false, error);
}
}
});
}
});
describe("Feature Enablement", () => {
it("connectionHandshakeIncludesEnablingNotifications", async () => {
client = await createTestClient(clientConfig, {
maintPushNotifications: "enabled",
});
const { action_id } = await faultInjectorClient.migrateAndBindAction({
bdbId: clientConfig.bdbId,
clusterIndex: 0,
});
await faultInjectorClient.waitForAction(action_id);
let movingEvent = false;
let migratingEvent = false;
let migratedEvent = false;
for (const event of log) {
if (event.type === "MOVING") movingEvent = true;
if (event.type === "MIGRATING") migratingEvent = true;
if (event.type === "MIGRATED") migratedEvent = true;
}
assert.ok(movingEvent, "didnt receive MOVING PN");
assert.ok(migratingEvent, "didnt receive MIGRATING PN");
assert.ok(migratedEvent, "didnt receive MIGRATED PN");
});
it("disabledDontReceiveNotifications", async () => {
try {
client = await createTestClient(clientConfig, {
maintPushNotifications: "disabled",
socket: {
reconnectStrategy: false
}
});
client.on('error', console.log.bind(console))
const { action_id } = await faultInjectorClient.migrateAndBindAction({
bdbId: clientConfig.bdbId,
clusterIndex: 0,
});
await faultInjectorClient.waitForAction(action_id);
assert.equal(log.length, 0, "received a PN while feature is disabled");
} catch (error: any) { }
});
});
});