summaryrefslogtreecommitdiff
path: root/spec/channel_spec.lua
blob: d8dbb13652705159ca156de6e90d950415720e1b (plain)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
describe("channel module", function()
	it("should load",function()
		require("channel")
	end)
	describe("SimpleChannel",function()
		local channel = require("channel")
		it("should exist",function()
			assert(channel.SimpleChannel)
			assert(channel.SimpleChannel())
		end)
		it("should send messages",function()
			local sc = channel.SimpleChannel()
			assert(not sc:poll())
			sc:send("Hello")
			assert(sc:poll())
			assert(sc:recv() == "Hello")
		end)
		it("should send any string",function()
			local sc = channel.SimpleChannel()
			local rng = tostring(math.random())
			sc:send(rng)
			assert(sc:recv() == rng)
		end)
	end)
	describe("FaultyChannel",function()
		local channel = require("channel")
		it("should exist",function()
			assert(channel.FaultyChannel)
			assert(channel.FaultyChannel())
		end)
		it("can has a .time that allows it to time travel",function()
			channel.FaultyChannel.time = 0
			local fc = channel.FaultyChannel({
				loss_std = 0,
				avg_latency = 5
			})
			fc:send("a")
			assert(#fc.to_deliver == 1)
			assert(#fc.buffer == 0)
			channel.FaultyChannel.time = 10
			fc:pump()
			assert(#fc.to_deliver == 0)
			assert(#fc.buffer == 1)
			assert(fc:recv() == "a")
		end)
		it("has a normal() function that does normal distribution", function()
			local normal = channel.FaultyChannel.normal
			for i = 1, 20 do
				math.randomseed(i)
				local res = normal(nil,1,0.1)
				assert(res > 0.5 and res < 1.5)
			end
		end)
		it("can pump() with no side effects if time has not changed", function()
			channel.FaultyChannel.time = 0
			local fc = channel.FaultyChannel({
				loss = 0,
				avg_latency = 5
			})
			fc:send("a")
			assert(#fc.to_deliver == 1)
			assert(#fc.buffer == 0)
			fc:pump()
			assert(#fc.to_deliver == 1)
			assert(#fc.buffer == 0)
			channel.FaultyChannel.time = 4
			fc:pump()
			fc:send("b")
			assert(#fc.to_deliver == 2)
			assert(#fc.buffer == 0)
			channel.FaultyChannel.time = 6
			fc:pump()
			assert(#fc.to_deliver == 1)
			assert(#fc.buffer == 1)
		end)
		it("can be configured to not drop messages", function()
			channel.FaultyChannel.time = 0
			local fc = channel.FaultyChannel({
				avg_latency = 5,
				loss = 0
			})
			local i = 100
			for _ = 1,i do
				fc:send("a")
			end
			channel.FaultyChannel.time = 10
			local j = 0
			while fc:poll() do
				j = j + 1
				fc:recv()
			end
			assert(j == i)
		end)
		it("should drop messages sometimes",function()
			local fc = channel.FaultyChannel()
			local i = 100
			for _ = 1, i do
				fc:send("a")
			end
			-- Time forward
			--channel.FaultyChannel.time = math.huge
			local j = 0
			while fc:poll() do
				j = j + 1
				fc:recv()
			end
			assert(j < i)
		end)
		it("should keep a queue of messages", function()
			channel.FaultyChannel.time = 0
			local fc = channel.FaultyChannel({
				loss = 0,
				avg_latency=0,
				latency_std=0,
			})
			local i = 100
			for j = 1, i do
				fc:send(tostring(j))
			end
			channel.FaultyChannel.time = 1
			fc:pump()
			assert(#fc.to_deliver == 0)
			assert(#fc.buffer == i)
			for j = 1, i do
				assert(tonumber(fc:recv()) == j)
			end
			assert(not fc:poll())
		end)
		it("should deliver messages with different latencies", function()
			channel.FaultyChannel.time = 0
			local fc = channel.FaultyChannel({
				loss = 0,
				avg_latency = 20,
				latency_std = 5,
			})
			local i = 100
			for j = 1, i do
				fc:send(tostring(j))
			end
			local received = 0
			local increment = 0.5
			local last_received = nil
			local found_out_of_order = false
			while received < i do
				while fc:poll() do
					local recv = tonumber(fc:recv())
					if last_received and last_received < recv then
						found_out_of_order = true
					end
					last_received = recv
					received = received + 1
				end
				channel.FaultyChannel.time = channel.FaultyChannel.time + increment
			end
			assert(found_out_of_order)
		end)
	end)
end)