inbound-tag.test.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { describe, it, expect } from 'vitest';
  2. import { composeInboundTag, isAutoInboundTag, type InboundTagInput } from '@/lib/xray/inbound-tag';
  3. // Parity with web/service/port_conflict.go TestInboundTransports: the L4 suffix
  4. // the tag encodes must match the Go service so the form preview agrees with the
  5. // tag the backend re-derives on save.
  6. describe('composeInboundTag transport suffix parity', () => {
  7. const base = (over: Partial<InboundTagInput>): InboundTagInput => ({
  8. port: 443,
  9. nodeId: null,
  10. protocol: 'vless',
  11. ...over,
  12. });
  13. const cases: Array<[string, InboundTagInput, string]> = [
  14. ['vless tcp', base({ streamSettings: { network: 'tcp' } }), 'in-443-tcp'],
  15. ['vless ws (still tcp)', base({ streamSettings: { network: 'ws' } }), 'in-443-tcp'],
  16. ['vless kcp is udp', base({ streamSettings: { network: 'kcp' } }), 'in-443-udp'],
  17. ['vless quic is udp', base({ streamSettings: { network: 'quic' } }), 'in-443-udp'],
  18. ['vless empty stream defaults tcp', base({}), 'in-443-tcp'],
  19. ['vmess tcp', base({ protocol: 'vmess', streamSettings: { network: 'tcp' } }), 'in-443-tcp'],
  20. ['trojan grpc is tcp', base({ protocol: 'trojan', streamSettings: { network: 'grpc' } }), 'in-443-tcp'],
  21. ['hysteria forced udp', base({ protocol: 'hysteria', streamSettings: { network: 'tcp' } }), 'in-443-udp'],
  22. ['wireguard forced udp', base({ protocol: 'wireguard' }), 'in-443-udp'],
  23. ['shadowsocks tcp,udp', base({ protocol: 'shadowsocks', settings: { network: 'tcp,udp' } }), 'in-443-tcpudp'],
  24. ['shadowsocks udp only', base({ protocol: 'shadowsocks', settings: { network: 'udp' } }), 'in-443-udp'],
  25. ['shadowsocks tcp only', base({ protocol: 'shadowsocks', settings: { network: 'tcp' } }), 'in-443-tcp'],
  26. ['mixed udp on', base({ protocol: 'mixed', streamSettings: { network: 'tcp' }, settings: { udp: true } }), 'in-443-tcpudp'],
  27. ['mixed udp off', base({ protocol: 'mixed', streamSettings: { network: 'tcp' }, settings: { udp: false } }), 'in-443-tcp'],
  28. ['tunnel allowedNetwork udp', base({ protocol: 'tunnel', settings: { allowedNetwork: 'udp' } }), 'in-443-udp'],
  29. ];
  30. it.each(cases)('%s', (_name, input, want) => {
  31. expect(composeInboundTag(input)).toBe(want);
  32. });
  33. it('ignores the listen address and adds the node prefix', () => {
  34. expect(composeInboundTag(base({ port: 8443, streamSettings: { network: 'tcp' } })))
  35. .toBe('in-8443-tcp');
  36. expect(composeInboundTag(base({ nodeId: 1, port: 443, streamSettings: { network: 'tcp' } })))
  37. .toBe('n1-in-443-tcp');
  38. });
  39. });
  40. // Parity with TestIsAutoGeneratedTag.
  41. describe('isAutoInboundTag', () => {
  42. const input: InboundTagInput = {
  43. port: 443, nodeId: null, protocol: 'vless', streamSettings: { network: 'tcp' },
  44. };
  45. it('recognises canonical, dedup-suffixed and empty as auto', () => {
  46. expect(isAutoInboundTag('in-443-tcp', input)).toBe(true);
  47. expect(isAutoInboundTag('in-443-tcp-2', input)).toBe(true);
  48. expect(isAutoInboundTag('', input)).toBe(true);
  49. });
  50. it('treats custom / stale / malformed-suffix tags as not auto', () => {
  51. expect(isAutoInboundTag('my-custom', input)).toBe(false);
  52. expect(isAutoInboundTag('in-8443-tcp', input)).toBe(false);
  53. expect(isAutoInboundTag('in-443-tcp-x', input)).toBe(false);
  54. expect(isAutoInboundTag('in-443-tcp-', input)).toBe(false);
  55. });
  56. });