@projectlibertylabs/p2p-peer-test
Version:
CLI tool to test libp2p connections and discover peer protocols
240 lines (208 loc) • 7.4 kB
JavaScript
import { describe, it, expect } from 'vitest';
import {
parseMultiaddrs,
safeParseInt,
measureDuration,
pipe,
compose,
isNullOrUndefined,
isEmpty,
createPromiseWithTimeout
} from './utils.js';
describe('parseMultiaddrs', () => {
it('should parse single multiaddr', () => {
const input = '/ip4/127.0.0.1/tcp/4001';
const result = parseMultiaddrs(input);
expect(result).toEqual(['/ip4/127.0.0.1/tcp/4001']);
});
it('should parse multiple multiaddrs separated by newlines', () => {
const input = `/ip4/127.0.0.1/tcp/4001
/ip4/127.0.0.1/tcp/4002
/ip4/127.0.0.1/tcp/4003`;
const result = parseMultiaddrs(input);
expect(result).toEqual([
'/ip4/127.0.0.1/tcp/4001',
'/ip4/127.0.0.1/tcp/4002',
'/ip4/127.0.0.1/tcp/4003'
]);
});
it('should parse multiaddrs with mixed whitespace', () => {
const input = '/ip4/127.0.0.1/tcp/4001 /ip4/127.0.0.1/tcp/4002\n\n/ip4/127.0.0.1/tcp/4003';
const result = parseMultiaddrs(input);
expect(result).toEqual([
'/ip4/127.0.0.1/tcp/4001',
'/ip4/127.0.0.1/tcp/4002',
'/ip4/127.0.0.1/tcp/4003'
]);
});
it('should filter out non-multiaddr lines', () => {
const input = `/ip4/127.0.0.1/tcp/4001
# This is a comment
/ip4/127.0.0.1/tcp/4002
invalid line
/ip4/127.0.0.1/tcp/4003`;
const result = parseMultiaddrs(input);
expect(result).toEqual([
'/ip4/127.0.0.1/tcp/4001',
'/ip4/127.0.0.1/tcp/4002',
'/ip4/127.0.0.1/tcp/4003'
]);
});
it('should remove duplicates', () => {
const input = `/ip4/127.0.0.1/tcp/4001
/ip4/127.0.0.1/tcp/4002
/ip4/127.0.0.1/tcp/4001
/ip4/127.0.0.1/tcp/4003`;
const result = parseMultiaddrs(input);
expect(result).toEqual([
'/ip4/127.0.0.1/tcp/4001',
'/ip4/127.0.0.1/tcp/4002',
'/ip4/127.0.0.1/tcp/4003'
]);
});
it('should handle empty input', () => {
expect(parseMultiaddrs('')).toEqual([]);
expect(parseMultiaddrs(' ')).toEqual([]);
expect(parseMultiaddrs(null)).toEqual([]);
expect(parseMultiaddrs(undefined)).toEqual([]);
});
it('should trim whitespace from addresses', () => {
const input = ' /ip4/127.0.0.1/tcp/4001 \n /ip4/127.0.0.1/tcp/4002 ';
const result = parseMultiaddrs(input);
expect(result).toEqual(['/ip4/127.0.0.1/tcp/4001', '/ip4/127.0.0.1/tcp/4002']);
});
it('should handle real-world paste example', () => {
const input = `/dns4/3.collator.frequency.xyz/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB
/ip4/10.40.10.23/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB
/ip4/3.129.100.199/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB`;
const result = parseMultiaddrs(input);
expect(result).toHaveLength(3);
expect(result[0]).toBe(
'/dns4/3.collator.frequency.xyz/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB'
);
expect(result[1]).toBe(
'/ip4/10.40.10.23/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB'
);
expect(result[2]).toBe(
'/ip4/3.129.100.199/tcp/30333/p2p/12D3KooWLsZTXsv1eY6U9YhowipQ73R5D1zQTaWECUCkxLawWpoB'
);
});
});
describe('safeParseInt', () => {
it('should parse valid integer string', () => {
expect(safeParseInt('123', 0)).toBe(123);
expect(safeParseInt('0', 10)).toBe(0);
expect(safeParseInt('-5', 0)).toBe(-5);
});
it('should return default value for invalid input', () => {
expect(safeParseInt('abc', 42)).toBe(null);
expect(safeParseInt('', 10)).toBe(10);
expect(safeParseInt(null, 5)).toBe(5);
});
it('should use validator function when provided', () => {
const positiveValidator = (n) => n > 0;
expect(safeParseInt('10', 0, positiveValidator)).toBe(10);
expect(safeParseInt('-5', 0, positiveValidator)).toBe(null);
expect(safeParseInt('0', 1, positiveValidator)).toBe(null);
});
it('should handle numeric input', () => {
expect(safeParseInt(123, 0)).toBe(123);
expect(safeParseInt(0, 10)).toBe(10); // 0 is falsy, so uses default
});
});
describe('measureDuration', () => {
it('should return positive duration', () => {
const start = performance.now() - 100; // 100ms ago
const duration = measureDuration(start);
expect(duration).toBeGreaterThan(90);
expect(duration).toBeLessThan(200); // Allow some variance
expect(Number.isInteger(duration)).toBe(true);
});
it('should return 0 or positive for current time', () => {
const start = performance.now();
const duration = measureDuration(start);
expect(duration).toBeGreaterThanOrEqual(0);
expect(Number.isInteger(duration)).toBe(true);
});
});
describe('pipe', () => {
it('should apply functions left to right', () => {
const add5 = (x) => x + 5;
const multiply2 = (x) => x * 2;
const subtract1 = (x) => x - 1;
const piped = pipe(add5, multiply2, subtract1);
expect(piped(10)).toBe(29); // ((10 + 5) * 2) - 1 = 29
});
it('should work with single function', () => {
const double = (x) => x * 2;
const piped = pipe(double);
expect(piped(5)).toBe(10);
});
it('should work with no functions', () => {
const piped = pipe();
expect(piped(42)).toBe(42);
});
});
describe('compose', () => {
it('should apply functions right to left', () => {
const add5 = (x) => x + 5;
const multiply2 = (x) => x * 2;
const subtract1 = (x) => x - 1;
const composed = compose(subtract1, multiply2, add5);
expect(composed(10)).toBe(29); // ((10 + 5) * 2) - 1 = 29
});
it('should work with single function', () => {
const double = (x) => x * 2;
const composed = compose(double);
expect(composed(5)).toBe(10);
});
});
describe('isNullOrUndefined', () => {
it('should return true for null and undefined', () => {
expect(isNullOrUndefined(null)).toBe(true);
expect(isNullOrUndefined(undefined)).toBe(true);
});
it('should return false for other values', () => {
expect(isNullOrUndefined(0)).toBe(false);
expect(isNullOrUndefined('')).toBe(false);
expect(isNullOrUndefined(false)).toBe(false);
expect(isNullOrUndefined([])).toBe(false);
expect(isNullOrUndefined({})).toBe(false);
});
});
describe('isEmpty', () => {
it('should return true for empty values', () => {
expect(isEmpty(null)).toBe(true);
expect(isEmpty(undefined)).toBe(true);
expect(isEmpty('')).toBe(true);
expect(isEmpty(' ')).toBe(true);
expect(isEmpty([])).toBe(true);
});
it('should return false for non-empty values', () => {
expect(isEmpty('hello')).toBe(false);
expect(isEmpty('0')).toBe(false);
expect(isEmpty([1])).toBe(false);
expect(isEmpty(0)).toBe(false);
expect(isEmpty(false)).toBe(false);
expect(isEmpty({})).toBe(false);
});
});
describe('createPromiseWithTimeout', () => {
it('should resolve when promise resolves before timeout', async () => {
const fastPromise = Promise.resolve('success');
const result = await createPromiseWithTimeout(fastPromise, 1000, 'timeout');
expect(result).toBe('success');
});
it('should reject with timeout error when promise takes too long', async () => {
const slowPromise = new Promise((resolve) => setTimeout(() => resolve('late'), 100));
await expect(
createPromiseWithTimeout(slowPromise, 10, 'Custom timeout message')
).rejects.toThrow('Custom timeout message');
});
it('should reject with original error when promise rejects', async () => {
const failingPromise = Promise.reject(new Error('Original error'));
await expect(createPromiseWithTimeout(failingPromise, 1000, 'timeout')).rejects.toThrow(
'Original error'
);
});
});