| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- import { describe, expect, it } from 'vitest';
- import { buildClonePayload, pickClonePort } from '@/lib/xray/inbound-clone';
- import { DBInbound } from '@/models/dbinbound';
- function sourceInbound() {
- return new DBInbound({
- id: 7,
- port: 443,
- listen: '0.0.0.0',
- protocol: 'vless',
- remark: 'edge',
- enable: true,
- settings: JSON.stringify({
- clients: [{ id: 'uuid-1', email: 'a@test', flow: 'xtls-rprx-vision' }],
- decryption: 'none',
- }),
- streamSettings: { network: 'tcp', security: 'reality', realitySettings: { dest: 'www.lovelive-anime.jp:443' } },
- sniffing: { enabled: true },
- nodeId: 2,
- shareAddrStrategy: 'node',
- shareAddr: '',
- });
- }
- describe('buildClonePayload', () => {
- it('omits nodeId for a local-panel target so the row stays panel-local', () => {
- const payload = buildClonePayload(sourceInbound(), 23456, null);
- expect(payload).not.toHaveProperty('nodeId');
- });
- it('carries nodeId for a node target', () => {
- const payload = buildClonePayload(sourceInbound(), 23456, 5);
- expect(payload.nodeId).toBe(5);
- });
- it('stages the clone disabled with cleared clients, fresh port, and no tag', () => {
- const payload = buildClonePayload(sourceInbound(), 23456, 3);
- expect(payload.enable).toBe(false);
- expect(payload.port).toBe(23456);
- expect(payload.listen).toBe('');
- expect(payload).not.toHaveProperty('tag');
- expect(payload.remark).toBe('edge (clone)');
- const settings = JSON.parse(payload.settings);
- // Clients are dropped (emails are unique panel-wide, UUIDs must not
- // repeat across nodes) while the rest of the settings survive verbatim.
- expect(settings.clients).toEqual([]);
- expect(settings.decryption).toBe('none');
- });
- it('stringifies object-shaped streamSettings and sniffing from hydrated rows', () => {
- const payload = buildClonePayload(sourceInbound(), 23456, null);
- expect(JSON.parse(payload.streamSettings)).toEqual({
- network: 'tcp',
- security: 'reality',
- realitySettings: { dest: 'www.lovelive-anime.jp:443' },
- });
- expect(JSON.parse(payload.sniffing)).toEqual({ enabled: true });
- });
- it('survives malformed settings JSON with an empty client list fallback', () => {
- const broken = sourceInbound();
- broken.settings = '{not json';
- const payload = buildClonePayload(broken, 23456, null);
- const settings = JSON.parse(payload.settings);
- expect(settings.clients ?? []).toEqual([]);
- });
- });
- describe('pickClonePort', () => {
- it('never returns a port already bound on the target', () => {
- const used = new Set<number>();
- for (let p = 10000; p <= 60000; p++) if (p !== 23456) used.add(p);
- expect(pickClonePort(used)).toBe(23456);
- });
- it('stops probing when the range looks exhausted instead of spinning', () => {
- const used = new Set<number>();
- for (let p = 10000; p <= 60000; p++) used.add(p);
- const port = pickClonePort(used);
- expect(port).toBeGreaterThanOrEqual(10000);
- expect(port).toBeLessThanOrEqual(60000);
- });
- });
|