You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Adapt legacy sentinel tests to use the new test utils (#2976)
* modified legacy sentinel tests * Adapt legacy sentinel tests to use the new test utils * modify tmpdir creation * reduced sentinel config timeouts, removed unneeded comment --------- Co-authored-by: H. Temelski <hristo.temelski@redis.com>
This commit is contained in:
@@ -62,7 +62,7 @@ export interface RedisServerDocker {
|
||||
dockerId: string;
|
||||
}
|
||||
|
||||
async function spawnRedisServerDocker(
|
||||
export async function spawnRedisServerDocker(
|
||||
options: RedisServerDockerOptions, serverArguments: Array<string>): Promise<RedisServerDocker> {
|
||||
let port;
|
||||
if (options.mode == "sentinel") {
|
||||
@@ -374,35 +374,16 @@ export async function spawnRedisSentinel(
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix));
|
||||
|
||||
for (let i = 0; i < sentinelCount; i++) {
|
||||
sentinelPromises.push((async () => {
|
||||
const port = (await portIterator.next()).value;
|
||||
|
||||
let sentinelConfig = `port ${port}
|
||||
sentinel monitor mymaster 127.0.0.1 ${master.port} 2
|
||||
sentinel down-after-milliseconds mymaster 5000
|
||||
sentinel failover-timeout mymaster 6000
|
||||
`;
|
||||
if (password !== undefined) {
|
||||
sentinelConfig += `requirepass ${password}\n`;
|
||||
sentinelConfig += `sentinel auth-pass mymaster ${password}\n`;
|
||||
}
|
||||
|
||||
const dir = fs.mkdtempSync(path.join(tmpDir, i.toString()));
|
||||
fs.writeFile(`${dir}/redis.conf`, sentinelConfig, err => {
|
||||
if (err) {
|
||||
console.error("failed to create temporary config file", err);
|
||||
}
|
||||
});
|
||||
|
||||
return await spawnRedisServerDocker(
|
||||
{
|
||||
image: dockerConfigs.image,
|
||||
version: dockerConfigs.version,
|
||||
mode: "sentinel",
|
||||
mounts: [`${dir}/redis.conf:/redis/config/node-sentinel-1/redis.conf`],
|
||||
port: port,
|
||||
}, serverArguments);
|
||||
})());
|
||||
sentinelPromises.push(
|
||||
spawnSentinelNode(
|
||||
dockerConfigs,
|
||||
serverArguments,
|
||||
master.port,
|
||||
"mymaster",
|
||||
path.join(tmpDir, i.toString()),
|
||||
password,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
const sentinelNodes = await Promise.all(sentinelPromises);
|
||||
@@ -424,3 +405,43 @@ after(() => {
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
export async function spawnSentinelNode(
|
||||
dockerConfigs: RedisServerDockerOptions,
|
||||
serverArguments: Array<string>,
|
||||
masterPort: number,
|
||||
sentinelName: string,
|
||||
tmpDir: string,
|
||||
password?: string,
|
||||
) {
|
||||
const port = (await portIterator.next()).value;
|
||||
|
||||
let sentinelConfig = `port ${port}
|
||||
sentinel monitor ${sentinelName} 127.0.0.1 ${masterPort} 2
|
||||
sentinel down-after-milliseconds ${sentinelName} 500
|
||||
sentinel failover-timeout ${sentinelName} 1000
|
||||
`;
|
||||
if (password !== undefined) {
|
||||
sentinelConfig += `requirepass ${password}\n`;
|
||||
sentinelConfig += `sentinel auth-pass ${sentinelName} ${password}\n`;
|
||||
}
|
||||
|
||||
const dir = fs.mkdtempSync(tmpDir);
|
||||
fs.writeFile(`${dir}/redis.conf`, sentinelConfig, err => {
|
||||
if (err) {
|
||||
console.error("failed to create temporary config file", err);
|
||||
}
|
||||
});
|
||||
|
||||
return await spawnRedisServerDocker(
|
||||
{
|
||||
image: dockerConfigs.image,
|
||||
version: dockerConfigs.version,
|
||||
mode: "sentinel",
|
||||
mounts: [`${dir}/redis.conf:/redis/config/node-sentinel-1/redis.conf`],
|
||||
port: port,
|
||||
},
|
||||
serverArguments,
|
||||
);
|
||||
}
|
@@ -19,10 +19,13 @@ import {
|
||||
RedisClusterType
|
||||
} from '@redis/client/index';
|
||||
import { RedisNode } from '@redis/client/lib/sentinel/types'
|
||||
import { spawnRedisServer, spawnRedisCluster, spawnRedisSentinel, RedisServerDockerOptions } from './dockers';
|
||||
import { spawnRedisServer, spawnRedisCluster, spawnRedisSentinel, RedisServerDockerOptions, RedisServerDocker, spawnSentinelNode, spawnRedisServerDocker } from './dockers';
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
|
||||
interface TestUtilsConfig {
|
||||
/**
|
||||
@@ -395,19 +398,19 @@ export default class TestUtils {
|
||||
S extends RedisScripts = {},
|
||||
RESP extends RespVersions = 2,
|
||||
TYPE_MAPPING extends TypeMapping = {}
|
||||
>(
|
||||
range: ([minVersion: Array<number>, maxVersion: Array<number>] | [minVersion: Array<number>, 'LATEST']),
|
||||
title: string,
|
||||
fn: (sentinel: RedisSentinelType<M, F, S, RESP, TYPE_MAPPING>) => unknown,
|
||||
options: SentinelTestOptions<M, F, S, RESP, TYPE_MAPPING>
|
||||
): void {
|
||||
>(
|
||||
range: ([minVersion: Array<number>, maxVersion: Array<number>] | [minVersion: Array<number>, 'LATEST']),
|
||||
title: string,
|
||||
fn: (sentinel: RedisSentinelType<M, F, S, RESP, TYPE_MAPPING>) => unknown,
|
||||
options: SentinelTestOptions<M, F, S, RESP, TYPE_MAPPING>
|
||||
): void {
|
||||
|
||||
if (this.isVersionInRange(range[0], range[1] === 'LATEST' ? [Infinity, Infinity, Infinity] : range[1])) {
|
||||
return this.testWithClientSentinel(`${title} [${range[0].join('.')}] - [${(range[1] === 'LATEST') ? range[1] : range[1].join(".")}] `, fn, options)
|
||||
} else {
|
||||
console.warn(`Skipping test ${title} because server version ${this.#VERSION_NUMBERS.join('.')} is not within range ${range[0].join(".")} - ${range[1] !== 'LATEST' ? range[1].join(".") : 'LATEST'}`)
|
||||
if (this.isVersionInRange(range[0], range[1] === 'LATEST' ? [Infinity, Infinity, Infinity] : range[1])) {
|
||||
return this.testWithClientSentinel(`${title} [${range[0].join('.')}] - [${(range[1] === 'LATEST') ? range[1] : range[1].join(".")}] `, fn, options)
|
||||
} else {
|
||||
console.warn(`Skipping test ${title} because server version ${this.#VERSION_NUMBERS.join('.')} is not within range ${range[0].join(".")} - ${range[1] !== 'LATEST' ? range[1].join(".") : 'LATEST'}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testWithClientPool<
|
||||
M extends RedisModules = {},
|
||||
@@ -541,4 +544,46 @@ export default class TestUtils {
|
||||
this.testWithClient(`client.${title}`, fn, options.client);
|
||||
this.testWithCluster(`cluster.${title}`, fn, options.cluster);
|
||||
}
|
||||
|
||||
|
||||
spawnRedisServer<
|
||||
M extends RedisModules = {},
|
||||
F extends RedisFunctions = {},
|
||||
S extends RedisScripts = {},
|
||||
RESP extends RespVersions = 2,
|
||||
TYPE_MAPPING extends TypeMapping = {}
|
||||
// POLICIES extends CommandPolicies = {}
|
||||
>(
|
||||
options: ClientPoolTestOptions<M, F, S, RESP, TYPE_MAPPING>
|
||||
): Promise<RedisServerDocker> {
|
||||
return spawnRedisServerDocker(this.#DOCKER_IMAGE, options.serverArguments)
|
||||
}
|
||||
|
||||
async spawnRedisSentinels<
|
||||
M extends RedisModules = {},
|
||||
F extends RedisFunctions = {},
|
||||
S extends RedisScripts = {},
|
||||
RESP extends RespVersions = 2,
|
||||
TYPE_MAPPING extends TypeMapping = {}
|
||||
// POLICIES extends CommandPolicies = {}
|
||||
>(
|
||||
options: ClientPoolTestOptions<M, F, S, RESP, TYPE_MAPPING>,
|
||||
masterPort: number,
|
||||
sentinelName: string,
|
||||
count: number
|
||||
): Promise<Array<RedisServerDocker>> {
|
||||
const sentinels: Array<RedisServerDocker> = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const appPrefix = 'sentinel-config-dir';
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), appPrefix));
|
||||
|
||||
sentinels.push(await spawnSentinelNode(this.#DOCKER_IMAGE, options.serverArguments, masterPort, sentinelName, tmpDir))
|
||||
|
||||
if (tmpDir) {
|
||||
fs.rmSync(tmpDir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
return sentinels
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user