Mirror: Best-effort discovery of the machine's local network using just Node.js dgram sockets
1import os from 'node:os';
2import { vi, describe, it, expect } from 'vitest';
3import {
4 parseMacStr,
5 parseIpStr,
6 toIpStr,
7 interfaceAssignments,
8 matchAssignment,
9} from '../network';
10
11describe(parseMacStr, () => {
12 it('parses valid MAC addresses', () => {
13 expect(parseMacStr('11:22:33:44:55:66')).toEqual([17, 34, 51, 68, 85, 102]);
14 });
15});
16
17describe(parseIpStr, () => {
18 it('parses valid IP addresses', () => {
19 expect(parseIpStr('0.0.0.0').toString(16)).toBe('0');
20 expect(parseIpStr('1.1.1.1').toString(16)).toBe('1010101');
21 expect(parseIpStr('255.255.255.255').toString(16)).toBe('-1');
22 expect(parseIpStr('100.1.2.3').toString(16)).toBe('64010203');
23 });
24});
25
26describe(toIpStr, () => {
27 it.each([['0.0.0.0'], ['1.1.1.1'], ['255.255.255.255'], ['100.1.2.3']])(
28 'stringifies parsed IP (%s)',
29 addr => {
30 expect(toIpStr(parseIpStr(addr))).toBe(addr);
31 }
32 );
33});
34
35describe(interfaceAssignments, () => {
36 const networkInterfaces = vi
37 .spyOn(os, 'networkInterfaces')
38 .mockReturnValue([] as any);
39
40 it('returns sorted list of assignments', () => {
41 networkInterfaces.mockReturnValueOnce({
42 lo0: [
43 {
44 address: '127.0.0.1',
45 netmask: '255.0.0.0',
46 family: 'IPv4',
47 mac: '00:00:00:00:00:00',
48 internal: true,
49 cidr: '',
50 },
51 ],
52 en1: [
53 {
54 address: '10.0.0.10',
55 netmask: '255.255.255.0',
56 family: 'IPv4',
57 mac: '00:00:00:00:00:00',
58 internal: false,
59 cidr: '',
60 },
61 ],
62 tun2: [
63 {
64 address: '100.0.0.11',
65 netmask: '255.255.255.0',
66 family: 'IPv4',
67 mac: '00:00:00:00:00:00',
68 internal: true,
69 cidr: '',
70 },
71 ],
72 });
73 expect(interfaceAssignments()).toMatchInlineSnapshot(`
74 [
75 {
76 "address": "10.0.0.10",
77 "cidr": "",
78 "family": "IPv4",
79 "iname": "en1",
80 "internal": false,
81 "mac": "00:00:00:00:00:00",
82 "netmask": "255.255.255.0",
83 },
84 {
85 "address": "100.0.0.11",
86 "cidr": "",
87 "family": "IPv4",
88 "iname": "tun2",
89 "internal": true,
90 "mac": "00:00:00:00:00:00",
91 "netmask": "255.255.255.0",
92 },
93 {
94 "address": "127.0.0.1",
95 "cidr": "",
96 "family": "IPv4",
97 "iname": "lo0",
98 "internal": true,
99 "mac": "00:00:00:00:00:00",
100 "netmask": "255.0.0.0",
101 },
102 ]
103 `);
104 });
105});
106
107describe(matchAssignment, () => {
108 it('returns matching assignment by address', () => {
109 const assignment = {
110 iname: 'en0',
111 address: '100.0.0.11',
112 netmask: '255.255.255.0',
113 family: 'IPv4',
114 mac: '00:00:00:00:00:00',
115 internal: true,
116 cidr: '',
117 } as const;
118 expect(matchAssignment([assignment], '100.0.0.11')).toEqual({
119 ...assignment,
120 gateway: null,
121 });
122 });
123
124 it('returns matching assignment by gateway', () => {
125 const assignment = {
126 iname: 'en0',
127 address: '100.0.0.11',
128 netmask: '255.255.255.0',
129 family: 'IPv4',
130 mac: '00:00:00:00:00:00',
131 internal: true,
132 cidr: '',
133 } as const;
134 expect(matchAssignment([assignment], '100.0.0.1')).toEqual({
135 ...assignment,
136 gateway: '100.0.0.1',
137 });
138 });
139
140 it('returns null otherwise', () => {
141 const assignment = {
142 iname: 'en0',
143 address: '10.0.0.1',
144 netmask: '255.255.255.0',
145 family: 'IPv4',
146 mac: '00:00:00:00:00:00',
147 internal: true,
148 cidr: '',
149 } as const;
150 expect(matchAssignment([assignment], '100.0.0.1')).toBe(null);
151 });
152});