api-test.js
  1  'use strict';
  2  
  3  var ip = require('..');
  4  var assert = require('assert');
  5  var net = require('net');
  6  var os = require('os');
  7  
  8  describe('IP library for node.js', function() {
  9    describe('toBuffer()/toString() methods', function() {
 10      it('should convert to buffer IPv4 address', function() {
 11        var buf = ip.toBuffer('127.0.0.1');
 12        assert.equal(buf.toString('hex'), '7f000001');
 13        assert.equal(ip.toString(buf), '127.0.0.1');
 14      });
 15  
 16      it('should convert to buffer IPv4 address in-place', function() {
 17        var buf = new Buffer(128);
 18        var offset = 64;
 19        ip.toBuffer('127.0.0.1', buf, offset);
 20        assert.equal(buf.toString('hex', offset, offset + 4), '7f000001');
 21        assert.equal(ip.toString(buf, offset, 4), '127.0.0.1');
 22      });
 23  
 24      it('should convert to buffer IPv6 address', function() {
 25        var buf = ip.toBuffer('::1');
 26        assert(/(00){15,15}01/.test(buf.toString('hex')));
 27        assert.equal(ip.toString(buf), '::1');
 28        assert.equal(ip.toString(ip.toBuffer('1::')), '1::');
 29        assert.equal(ip.toString(ip.toBuffer('abcd::dcba')), 'abcd::dcba');
 30      });
 31  
 32      it('should convert to buffer IPv6 address in-place', function() {
 33        var buf = new Buffer(128);
 34        var offset = 64;
 35        ip.toBuffer('::1', buf, offset);
 36        assert(/(00){15,15}01/.test(buf.toString('hex', offset, offset + 16)));
 37        assert.equal(ip.toString(buf, offset, 16), '::1');
 38        assert.equal(ip.toString(ip.toBuffer('1::', buf, offset),
 39                                 offset, 16), '1::');
 40        assert.equal(ip.toString(ip.toBuffer('abcd::dcba', buf, offset),
 41                                 offset, 16), 'abcd::dcba');
 42      });
 43  
 44      it('should convert to buffer IPv6 mapped IPv4 address', function() {
 45        var buf = ip.toBuffer('::ffff:127.0.0.1');
 46        assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001');
 47        assert.equal(ip.toString(buf), '::ffff:7f00:1');
 48  
 49        buf = ip.toBuffer('ffff::127.0.0.1');
 50        assert.equal(buf.toString('hex'), 'ffff000000000000000000007f000001');
 51        assert.equal(ip.toString(buf), 'ffff::7f00:1');
 52  
 53        buf = ip.toBuffer('0:0:0:0:0:ffff:127.0.0.1');
 54        assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001');
 55        assert.equal(ip.toString(buf), '::ffff:7f00:1');
 56      });
 57    });
 58  
 59    describe('fromPrefixLen() method', function() {
 60      it('should create IPv4 mask', function() {
 61        assert.equal(ip.fromPrefixLen(24), '255.255.255.0');
 62      });
 63      it('should create IPv6 mask', function() {
 64        assert.equal(ip.fromPrefixLen(64), 'ffff:ffff:ffff:ffff::');
 65      });
 66      it('should create IPv6 mask explicitly', function() {
 67        assert.equal(ip.fromPrefixLen(24, 'IPV6'), 'ffff:ff00::');
 68      });
 69    });
 70  
 71    describe('not() method', function() {
 72      it('should reverse bits in address', function() {
 73        assert.equal(ip.not('255.255.255.0'), '0.0.0.255');
 74      });
 75    });
 76  
 77    describe('or() method', function() {
 78      it('should or bits in ipv4 addresses', function() {
 79        assert.equal(ip.or('0.0.0.255', '192.168.1.10'), '192.168.1.255');
 80      });
 81      it('should or bits in ipv6 addresses', function() {
 82        assert.equal(ip.or('::ff', '::abcd:dcba:abcd:dcba'),
 83                     '::abcd:dcba:abcd:dcff');
 84      });
 85      it('should or bits in mixed addresses', function() {
 86        assert.equal(ip.or('0.0.0.255', '::abcd:dcba:abcd:dcba'),
 87                     '::abcd:dcba:abcd:dcff');
 88      });
 89    });
 90  
 91    describe('mask() method', function() {
 92      it('should mask bits in address', function() {
 93        assert.equal(ip.mask('192.168.1.134', '255.255.255.0'), '192.168.1.0');
 94        assert.equal(ip.mask('192.168.1.134', '::ffff:ff00'), '::ffff:c0a8:100');
 95      });
 96  
 97      it('should not leak data', function() {
 98        for (var i = 0; i < 10; i++)
 99          assert.equal(ip.mask('::1', '0.0.0.0'), '::');
100      });
101    });
102  
103    describe('subnet() method', function() {
104      // Test cases calculated with http://www.subnet-calculator.com/
105      var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.192');
106  
107      it('should compute ipv4 network address', function() {
108        assert.equal(ipv4Subnet.networkAddress, '192.168.1.128');
109      });
110  
111      it('should compute ipv4 network\'s first address', function() {
112        assert.equal(ipv4Subnet.firstAddress, '192.168.1.129');
113      });
114  
115      it('should compute ipv4 network\'s last address', function() {
116        assert.equal(ipv4Subnet.lastAddress, '192.168.1.190');
117      });
118  
119      it('should compute ipv4 broadcast address', function() {
120        assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191');
121      });
122  
123      it('should compute ipv4 subnet number of addresses', function() {
124        assert.equal(ipv4Subnet.length, 64);
125      });
126  
127      it('should compute ipv4 subnet number of addressable hosts', function() {
128        assert.equal(ipv4Subnet.numHosts, 62);
129      });
130  
131      it('should compute ipv4 subnet mask', function() {
132        assert.equal(ipv4Subnet.subnetMask, '255.255.255.192');
133      });
134  
135      it('should compute ipv4 subnet mask\'s length', function() {
136        assert.equal(ipv4Subnet.subnetMaskLength, 26);
137      });
138  
139      it('should know whether a subnet contains an address', function() {
140        assert.equal(ipv4Subnet.contains('192.168.1.180'), true);
141      });
142  
143      it('should know whether a subnet does not contain an address', function() {
144        assert.equal(ipv4Subnet.contains('192.168.1.195'), false);
145      });
146    });
147  
148    describe('subnet() method with mask length 32', function() {
149      // Test cases calculated with http://www.subnet-calculator.com/
150      var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.255');
151      it('should compute ipv4 network\'s first address', function() {
152        assert.equal(ipv4Subnet.firstAddress, '192.168.1.134');
153      });
154  
155      it('should compute ipv4 network\'s last address', function() {
156        assert.equal(ipv4Subnet.lastAddress, '192.168.1.134');
157      });
158  
159      it('should compute ipv4 subnet number of addressable hosts', function() {
160        assert.equal(ipv4Subnet.numHosts, 1);
161      });
162    });
163  
164    describe('subnet() method with mask length 31', function() {
165      // Test cases calculated with http://www.subnet-calculator.com/
166      var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.254');
167      it('should compute ipv4 network\'s first address', function() {
168        assert.equal(ipv4Subnet.firstAddress, '192.168.1.134');
169      });
170  
171      it('should compute ipv4 network\'s last address', function() {
172        assert.equal(ipv4Subnet.lastAddress, '192.168.1.135');
173      });
174  
175      it('should compute ipv4 subnet number of addressable hosts', function() {
176        assert.equal(ipv4Subnet.numHosts, 2);
177      });
178    });
179  
180    describe('cidrSubnet() method', function() {
181      // Test cases calculated with http://www.subnet-calculator.com/
182      var ipv4Subnet = ip.cidrSubnet('192.168.1.134/26');
183  
184      it('should compute an ipv4 network address', function() {
185        assert.equal(ipv4Subnet.networkAddress, '192.168.1.128');
186      });
187  
188      it('should compute an ipv4 network\'s first address', function() {
189        assert.equal(ipv4Subnet.firstAddress, '192.168.1.129');
190      });
191  
192      it('should compute an ipv4 network\'s last address', function() {
193        assert.equal(ipv4Subnet.lastAddress, '192.168.1.190');
194      });
195  
196      it('should compute an ipv4 broadcast address', function() {
197        assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191');
198      });
199  
200      it('should compute an ipv4 subnet number of addresses', function() {
201        assert.equal(ipv4Subnet.length, 64);
202      });
203  
204      it('should compute an ipv4 subnet number of addressable hosts', function() {
205        assert.equal(ipv4Subnet.numHosts, 62);
206      });
207  
208      it('should compute an ipv4 subnet mask', function() {
209        assert.equal(ipv4Subnet.subnetMask, '255.255.255.192');
210      });
211  
212      it('should compute an ipv4 subnet mask\'s length', function() {
213        assert.equal(ipv4Subnet.subnetMaskLength, 26);
214      });
215  
216      it('should know whether a subnet contains an address', function() {
217        assert.equal(ipv4Subnet.contains('192.168.1.180'), true);
218      });
219  
220      it('should know whether a subnet contains an address', function() {
221        assert.equal(ipv4Subnet.contains('192.168.1.195'), false);
222      });
223  
224    });
225  
226    describe('cidr() method', function() {
227      it('should mask address in CIDR notation', function() {
228        assert.equal(ip.cidr('192.168.1.134/26'), '192.168.1.128');
229        assert.equal(ip.cidr('2607:f0d0:1002:51::4/56'), '2607:f0d0:1002::');
230      });
231    });
232  
233    describe('isEqual() method', function() {
234      it('should check if addresses are equal', function() {
235        assert(ip.isEqual('127.0.0.1', '::7f00:1'));
236        assert(!ip.isEqual('127.0.0.1', '::7f00:2'));
237        assert(ip.isEqual('127.0.0.1', '::ffff:7f00:1'));
238        assert(!ip.isEqual('127.0.0.1', '::ffaf:7f00:1'));
239        assert(ip.isEqual('::ffff:127.0.0.1', '::ffff:127.0.0.1'));
240        assert(ip.isEqual('::ffff:127.0.0.1', '127.0.0.1'));
241      });
242    });
243  
244  
245    describe('isPrivate() method', function() {
246      it('should check if an address is localhost', function() {
247        assert.equal(ip.isPrivate('127.0.0.1'), true);
248      });
249  
250      it('should check if an address is from a 192.168.x.x network', function() {
251        assert.equal(ip.isPrivate('192.168.0.123'), true);
252        assert.equal(ip.isPrivate('192.168.122.123'), true);
253        assert.equal(ip.isPrivate('192.162.1.2'), false);
254      });
255  
256      it('should check if an address is from a 172.16.x.x network', function() {
257        assert.equal(ip.isPrivate('172.16.0.5'), true);
258        assert.equal(ip.isPrivate('172.16.123.254'), true);
259        assert.equal(ip.isPrivate('171.16.0.5'), false);
260        assert.equal(ip.isPrivate('172.25.232.15'), true);
261        assert.equal(ip.isPrivate('172.15.0.5'), false);
262        assert.equal(ip.isPrivate('172.32.0.5'), false);
263      });
264  
265      it('should check if an address is from a 169.254.x.x network', function() {
266        assert.equal(ip.isPrivate('169.254.2.3'), true);
267        assert.equal(ip.isPrivate('169.254.221.9'), true);
268        assert.equal(ip.isPrivate('168.254.2.3'), false);
269      });
270  
271      it('should check if an address is from a 10.x.x.x network', function() {
272        assert.equal(ip.isPrivate('10.0.2.3'), true);
273        assert.equal(ip.isPrivate('10.1.23.45'), true);
274        assert.equal(ip.isPrivate('12.1.2.3'), false);
275      });
276  
277      it('should check if an address is from a private IPv6 network', function() {
278        assert.equal(ip.isPrivate('fd12:3456:789a:1::1'), true);
279        assert.equal(ip.isPrivate('fe80::f2de:f1ff:fe3f:307e'), true);
280        assert.equal(ip.isPrivate('::ffff:10.100.1.42'), true);
281        assert.equal(ip.isPrivate('::FFFF:172.16.200.1'), true);
282        assert.equal(ip.isPrivate('::ffff:192.168.0.1'), true);
283      });
284  
285      it('should check if an address is from the internet', function() {
286        assert.equal(ip.isPrivate('165.225.132.33'), false); // joyent.com
287      });
288  
289      it('should check if an address is a loopback IPv6 address', function() {
290        assert.equal(ip.isPrivate('::'), true);
291        assert.equal(ip.isPrivate('::1'), true);
292        assert.equal(ip.isPrivate('fe80::1'), true);
293      });
294    });
295  
296    describe('loopback() method', function() {
297      describe('undefined', function() {
298        it('should respond with 127.0.0.1', function() {
299          assert.equal(ip.loopback(), '127.0.0.1')
300        });
301      });
302  
303      describe('ipv4', function() {
304        it('should respond with 127.0.0.1', function() {
305          assert.equal(ip.loopback('ipv4'), '127.0.0.1')
306        });
307      });
308  
309      describe('ipv6', function() {
310        it('should respond with fe80::1', function() {
311          assert.equal(ip.loopback('ipv6'), 'fe80::1')
312        });
313      });
314    });
315  
316    describe('isLoopback() method', function() {
317      describe('127.0.0.1', function() {
318        it('should respond with true', function() {
319          assert.ok(ip.isLoopback('127.0.0.1'))
320        });
321      });
322  
323      describe('127.8.8.8', function () {
324        it('should respond with true', function () {
325          assert.ok(ip.isLoopback('127.8.8.8'))
326        });
327      });
328  
329      describe('8.8.8.8', function () {
330        it('should respond with false', function () {
331          assert.equal(ip.isLoopback('8.8.8.8'), false);
332        });
333      });
334  
335      describe('fe80::1', function() {
336        it('should respond with true', function() {
337          assert.ok(ip.isLoopback('fe80::1'))
338        });
339      });
340  
341      describe('::1', function() {
342        it('should respond with true', function() {
343          assert.ok(ip.isLoopback('::1'))
344        });
345      });
346  
347      describe('::', function() {
348        it('should respond with true', function() {
349          assert.ok(ip.isLoopback('::'))
350        });
351      });
352    });
353  
354    describe('address() method', function() {
355      describe('undefined', function() {
356        it('should respond with a private ip', function() {
357          assert.ok(ip.isPrivate(ip.address()));
358        });
359      });
360  
361      describe('private', function() {
362        [ undefined, 'ipv4', 'ipv6' ].forEach(function(family) {
363          describe(family, function() {
364            it('should respond with a private ip', function() {
365              assert.ok(ip.isPrivate(ip.address('private', family)));
366            });
367          });
368        });
369      });
370  
371      var interfaces = os.networkInterfaces();
372  
373      Object.keys(interfaces).forEach(function(nic) {
374        describe(nic, function() {
375          [ undefined, 'ipv4' ].forEach(function(family) {
376            describe(family, function() {
377              it('should respond with an ipv4 address', function() {
378                var addr = ip.address(nic, family);
379                assert.ok(!addr || net.isIPv4(addr));
380              });
381            });
382          });
383  
384          describe('ipv6', function() {
385            it('should respond with an ipv6 address', function() {
386              var addr = ip.address(nic, 'ipv6');
387              assert.ok(!addr || net.isIPv6(addr));
388            });
389          })
390        });
391      });
392    });
393  
394    describe('toLong() method', function() {
395      it('should respond with a int', function() {
396        assert.equal(ip.toLong('127.0.0.1'), 2130706433);
397        assert.equal(ip.toLong('255.255.255.255'), 4294967295);
398      });
399    });
400  
401    describe('fromLong() method', function() {
402      it('should repond with ipv4 address', function() {
403        assert.equal(ip.fromLong(2130706433), '127.0.0.1');
404        assert.equal(ip.fromLong(4294967295), '255.255.255.255');
405      });
406    })
407  });