/** * Copyright (c) 2022 EdgerOS Team. * All rights reserved. * * Detailed license information can be found in the LICENSE file. * * Author : xueqiang * Date : 2024-08-05 16:14:40 * LastEditors : xueqiang * LastEditTime : 2024-08-15 15:55:34 */ import { NoopPolicy } from '../../deps/cockatiel' import assert from 'assert' import { type IKeyValue, DBClient, type ClientOptions, type Namespace } from '../index' import { proxy } from '../../deps/proxy' export function getOptions(defaults?: any): ClientOptions { return { etcd: { hosts: getHost(), faultHandling: { global: new NoopPolicy(), host: () => new NoopPolicy(), }, }, } } export function getHost(): string { if (proxy.isActive) { return proxy.address() } return '10.12.0.204:2379' } export const expectReject = async function (promise: Promise, err: any) { await promise .then(() => { throw new Error('expected to reject') }) .catch((actualErr: unknown) => { assert.ok(actualErr instanceof err) }) } export async function createTestClient(): Promise { const client = new DBClient(getOptions()) await client.init() return client } /** * Creates an etcd client with the default options and seeds some keys. */ export async function createTestClientAndKeys() { const client = await createTestClient() await createTestKeys(client) return client } /** * Creates test keys in the given namespace. */ export async function createTestKeys(client: DBClient | Namespace) { await Promise.all([ client.put('foo1').value('bar1'), client.put('foo2').value('bar2'), client.put('foo3').value('{"value":"bar3"}'), client.put('baz').value('bar5'), ]) } /** * Destroys the etcd client and wipes all keys. */ export async function tearDownTestClient(client?: DBClient) { if (client) { await client.delete().all() client.close() } } const originalSetTimeout = setTimeout export const unmockedDelay = async (duration: number) => await new Promise((resolve, reject) => originalSetTimeout(resolve, duration)) export function containSubset(previous: string[] | Buffer[] | IKeyValue[], subset: any): boolean { if (!Array.isArray(subset)) { subset = [subset] } if (!Array.isArray(previous)) { previous = [previous] } let result = false for (const item of subset) { if (Buffer.isBuffer(item)) { if (previous.length > 0) { for (const preItem of previous) { // eslint-disable-next-line @typescript-eslint/no-base-to-string -- i if (preItem.toString() === item.toString()) { result = true break } else { result = false } } } } else if (typeof item === 'object') { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-loop-func -- l Object.entries(item).forEach(([key, value]) => { if (previous.length > 0) { for (const preItem of previous) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- i // @ts-ignore if (deepEqual(preItem[key], value)) { result = true } else { result = false } } } }) } if (!result) { return result } } return result } export function deepEqual(x: any, y: any): boolean { if (x === y) { return true } else if (Buffer.isBuffer(x) && Buffer.isBuffer(y)) { return x.toString() === y.toString() } else if ((typeof x === 'object') && (typeof y === 'object')) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- i if (Object.keys(x).length !== Object.keys(y).length) { return false } for (const prop in x) { if (Object.hasOwnProperty.call(prop)) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- i if (!deepEqual(x[prop], y[prop])) { return false } } else { return false } } return true } else { return false } }