aboutsummaryrefslogtreecommitdiffstats
path: root/test/inet.lua
blob: 705715aac6c49d68178913dd4ac923912642d7ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
local inet = require 'inet'
local test = require 'test'

local function parse(addr)
	local ret, err = inet(addr)
	assert(ret, (err or '')..' '..addr)
	return ret, err
end

local function dontparse(...)
	test.fail(parse, ...)
end

return test.new(function()
	local ip
	-- parsing
	parse('1:2:3:4:5:6:7:8')
	parse('::1/33')
	parse('1::/33')
	parse('1:2:3:4:5:6:7::/33')
	parse('::2:3:4:5:6:7:8/33')
	parse('2a03:5440:1010::80/64')
	dontparse('::1::/33')
	dontparse('::1/33a')
	dontparse('::1/150')
	dontparse('1:2:3:4::2:3:4:5:6:7:8/33')
	assert(tostring(parse('1:0:0:1::/64') * 1) == '1:0:0:2::/64')
	assert(tostring(parse('1::/64') * 5 / 32 * 3) == '1:3:0:5::/32')
	assert(tostring(parse('5::64') / 32 * -3) == '4:fffd::64/32')
	assert(tostring(parse('2::/32') ^ 1) == '2::/33')
	assert(tostring(parse('2::/32') ^ -1) == '2::/31')
	assert(tostring(parse('2::/128') * 5) == '2::5')
	assert(tostring(parse('2::/49') - 1)
		== '1:ffff:ffff:ffff:ffff:ffff:ffff:ffff/49')
	assert(tostring(parse('2::/49') - 1 + 2) == '2::1/49')
	assert(tostring(parse('1:ffff:ffff:fe00::/56') * 2) == '2::/56')
	assert(tostring(parse('1:ffff:ffff:fe00::/56') * 2 * -2)
		== '1:ffff:ffff:fe00::/56')
	ip = inet('10.0.0.0/33')
	assert(ip == nil)

	ip = inet('10.0.0.0/24')
	assert(type(ip) == 'table')
	assert(#ip == 24, 'incorrect netmask')
	assert(ip:family() == 4, 'incorrect family')
	assert(tostring(ip) == '10.0.0.0/24', 'not human readable')

	assert(inet('10.0.0.0/32') == inet('10.0.0.0'))
	assert(inet('10.0.0.0/31') ~= inet('10.0.0.0'))

	assert(tostring(ip+1) == '10.0.0.1/24', 'ip adding is broken')
	assert(tostring(ip+9-1) == '10.0.0.8/24', 'ip subtract is broken')
	assert(tostring(ip*1) == '10.0.1.0/24', 'ip multiplification is broken')
	assert(tostring(ip/8) == '10.0.0.0/8', 'ip division is broken')
	assert(tostring(ip^1) == '10.0.0.0/25', 'ip power is broken')

	-- test inet4.__lt
	assert(inet('10.0.0.0/24') > inet('10.0.0.0/30'), 'inet less than is broken')
	assert(not (inet('10.0.0.0/30') > inet('10.0.0.0/30')), 'inet less than is broken')
	assert(inet('10.0.0.0/30') >= inet('10.0.0.0/30'), 'inet less than is broken')
	assert(inet('10.0.0.0/30') <= inet('10.0.0.0/30'), 'inet less than is broken')
	assert(inet('10.0.0.0/30') < inet('10.0.0.0/24'), 'inet less than is broken')
	assert(not (inet('10.0.0.0/24') < inet('10.0.0.0/30')), 'inet less than is broken')
	assert(not (inet('10.0.0.0/30') < inet('10.0.0.0/30')), 'inet less than is broken')
	assert(not (inet('20.0.0.0/30') < inet('10.0.0.0/24')), 'inet less than is broken')

	-- test inet4.__le
	assert(inet('10.0.1.2/24') <= inet('10.0.0.0/16'))
	assert(not (inet('10.0.1.0/24') <= inet('10.0.0.0/24')))

	assert(inet('127.0.0.1/8'):netmask() == inet('255.0.0.0'))


	-- test inet*.__eq
	assert(inet('10.0.0.0/30') == inet('10.0.0.0/30'), 'inet4 eq is broken')
	assert(inet('10.0.1.0/30') ~= inet('10.0.0.0/30'), 'inet4 eq is broken')
	assert(inet('10.0.0.0/31') ~= inet('10.0.0.0/30'), 'inet4 eq is broken')
	assert(inet('::1') == inet('::1'), 'inet6 eq is broken')
	assert(inet('::1') ~= inet('::2'), 'inet6 eq is broken')
	assert(inet('::1/64') ~= inet('::1/56'), 'inet6 eq is broken')

	-- test inet*.ipstring
	assert((ip+1):ipstring() == '10.0.0.1', 'ip4 string is broken')
	assert(inet('::1/64'):ipstring() == '::1', 'ip6 string is broken')

	-- test inet*.network
	assert(inet('10.0.0.1/30'):network() == inet('10.0.0.0/30'), 'inet4.network() is broken')
	assert(inet('1::2/64'):network() == inet('1::/64'), 'inet6.network() is broken')
	ip = inet('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/62')
	assert((ip/22):network() == inet('ffff:fc00::/22'), 'inet6.network() is broken')
	assert((ip/27):network() == inet('ffff:ffe0::/27'), 'inet6.network() is broken')

	--- test inet4:flip
	assert(inet('10.0.0.1/24'):flip() == inet('10.0.1.1/24'), 'inet4.flip() is broken')
	assert(inet('10.0.0.0/24'):flip() == inet('10.0.1.0/24'), 'inet4.flip() is broken')
	assert(inet('10.0.0.0/24'):flip():flip() == inet('10.0.0.0/24'), 'inet4.flip() is broken')
	assert(inet('10.20.30.0/24'):flip() == inet('10.20.31.0/24'))
	assert(inet('10.20.30.5/24'):flip() == inet('10.20.31.5/24'))
	assert(inet('10.20.30.5/32'):flip() == inet('10.20.30.4/32'))
	assert(inet('0.0.0.0/0'):flip() == nil)
	local ips = {
		inet('::'),
		inet('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'),
	}
	assert(inet('::/0'):flip() == nil)
	assert(inet('::1/32'):flip() == inet('0:1::1/32'))
	assert(inet('::1/48'):flip() == inet('0:0:1::1/48'))
	for i=1,#ips do
		ip = ips[i]
		for j=1,128 do
			local foo = ip / j
			local bar = foo:flip()
			assert(foo ~= bar)
			assert(foo == bar:flip())
		end
	end

	-- test inspectablity of metatable
	assert(#(getmetatable(inet('::/0'))) ~= nil)

	-- TODO inet6.__le
	-- TODO inet6.__eq

	assert(not inet.is4(false))
	assert(not inet.is4('foo'))
	assert(not inet.is4(42))
	assert(inet.is4(inet('0.0.0.0')))
	assert(not inet.is4(inet('::')))

	assert(not inet.is6(false))
	assert(not inet.is6('foo'))
	assert(not inet.is6(42))
	assert(not inet.is6(inet('0.0.0.0')))
	assert(inet.is6(inet('::')))

	assert(not inet.is(false))
	assert(not inet.is('foo'))
	assert(not inet.is(42))
	assert(inet.is(inet('0.0.0.0')))
	assert(inet.is(inet('::')))
end)