Skip to content

Commit 265ca94

Browse files
authored
Add unit tests (#2)
* Add unit tests * Fix wrong job name * Fix run_tests.sh file permissions
1 parent 5a8d845 commit 265ca94

File tree

6 files changed

+414
-1
lines changed

6 files changed

+414
-1
lines changed

.github/workflows/ci.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ jobs:
1616
steps:
1717
- uses: actions/checkout@v2
1818
- name: Proof
19-
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "gnatprove -P /app/cobs.gpr -j0 --level=1"
19+
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "gnatprove -P /app/cobs.gpr -j0 --level=1"
20+
unit_test:
21+
name: unit_test
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v2
25+
- name: Unit tests
26+
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "cd /app/tests && ./run_tests.sh"

tests/run_tests.sh

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
3+
gprbuild -p -P unit_tests.gpr -j0
4+
obj/main

tests/src/cobs_tests.adb

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
-------------------------------------------------------------------------------
2+
-- Copyright (c) 2020 Daniel King
3+
--
4+
-- Permission is hereby granted, free of charge, to any person obtaining a
5+
-- copy of this software and associated documentation files (the "Software"),
6+
-- to deal in the Software without restriction, including without limitation
7+
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
-- and/or sell copies of the Software, and to permit persons to whom the
9+
-- Software is furnished to do so, subject to the following conditions:
10+
--
11+
-- The above copyright notice and this permission notice shall be included in
12+
-- all copies or substantial portions of the Software.
13+
--
14+
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20+
-- DEALINGS IN THE SOFTWARE.
21+
-------------------------------------------------------------------------------
22+
with AUnit.Assertions; use AUnit.Assertions;
23+
with AUnit.Test_Caller;
24+
with AUnit.Test_Suites; use AUnit.Test_Suites;
25+
26+
with System.Storage_Elements; use System.Storage_Elements;
27+
28+
with COBS;
29+
30+
package body COBS_Tests
31+
is
32+
33+
package Test_Caller is new AUnit.Test_Caller (Test);
34+
35+
-----------------------
36+
-- Test_Encode_Empty --
37+
-----------------------
38+
39+
-- Test the output of Encode when presented with an empty input.
40+
-- The output should only consist of the overhead byte and frame delimiter.
41+
42+
procedure Test_Encode_Empty (T : in out Test)
43+
is
44+
Input : constant Storage_Array (1 .. 0) := (others => 0);
45+
Output : Storage_Array (1 .. 2);
46+
Length : Storage_Count;
47+
48+
Expected_Output : constant Storage_Array (1 .. 2) :=
49+
(1 => 1, -- Overhead byte
50+
2 => 0); -- Frame delimiter
51+
52+
begin
53+
COBS.Encode (Input, Output, Length);
54+
55+
Assert (Length = 2, "Incorrect Length");
56+
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
57+
end Test_Encode_Empty;
58+
59+
----------------------------
60+
-- Test_Encode_All_Zeroes --
61+
----------------------------
62+
63+
-- Test the output of Encode when presented with an input that consists
64+
-- of all zeroes.
65+
--
66+
-- The output should not contain any additional overhead bytes.
67+
68+
procedure Test_Encode_All_Zeroes (T : in out Test)
69+
is
70+
Input : constant Storage_Array (1 .. 1000) := (others => 0);
71+
Output : Storage_Array (1 .. 2000);
72+
Length : Storage_Count;
73+
74+
Expected_Output : constant Storage_Array (1 .. 1002) :=
75+
(1 => 1, -- Overhead byte
76+
1002 => 0, -- Frame delimiter
77+
others => 1); -- Data bytes (encoded)
78+
79+
begin
80+
COBS.Encode (Input, Output, Length);
81+
82+
Assert (Length = 1002, "Incorrect Length");
83+
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
84+
end Test_Encode_All_Zeroes;
85+
86+
---------------------------
87+
-- Test_Encode_No_Zeroes --
88+
---------------------------
89+
90+
-- Test the output of Encode when presented with an input consisting of
91+
-- no zero bytes.
92+
--
93+
-- The output should contain additional overhead bytes, in groups of 254 bytes.
94+
95+
procedure Test_Encode_No_Zeroes (T : in out Test)
96+
is
97+
Input : constant Storage_Array (1 .. 1000) := (others => 1);
98+
Output : Storage_Array (1 .. 2000);
99+
Length : Storage_Count;
100+
101+
Expected_Output : constant Storage_Array (1 .. 1005) :=
102+
(1 => 255, -- 1st overhead byte
103+
256 => 255, -- 2nd overhead byte
104+
511 => 255, -- 3rd overhead byte
105+
766 => 239, -- 4th overhead byte
106+
1005 => 0, -- Frame delimiter
107+
others => 1); -- Data byte
108+
109+
begin
110+
COBS.Encode (Input, Output, Length);
111+
112+
Assert (Length = 1005, "Incorrect Length");
113+
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
114+
end Test_Encode_No_Zeroes;
115+
116+
-----------------------------
117+
-- Test_Decode_Empty_Frame --
118+
-----------------------------
119+
120+
-- Test the decoder when presented with an empty frame.
121+
--
122+
-- The output should be of length 0.
123+
124+
procedure Test_Decode_Empty_Frame (T : in out Test)
125+
is
126+
Input : constant Storage_Array (1 .. 1) := (others => 0);
127+
Output : Storage_Array (1 .. 1);
128+
Length : Storage_Count;
129+
130+
begin
131+
COBS.Decode (Input, Output, Length);
132+
133+
Assert (Length = 0, "Incorrect length");
134+
end Test_Decode_Empty_Frame;
135+
136+
------------------------------------
137+
-- Test_Decode_No_Frame_Delimiter --
138+
------------------------------------
139+
140+
-- Test the decoder behaviour when the frame delimiter is missing from
141+
-- the input buffer.
142+
--
143+
-- The decoder should continue until the end of the input buffer is reached.
144+
145+
procedure Test_Decode_No_Frame_Delimiter (T : in out Test)
146+
is
147+
Input : constant Storage_Array (1 .. 7) := (6, 1, 2, 3, 4, 5, 5);
148+
Expected_Output : constant Storage_Array (1 .. 6) := ( 1, 2, 3, 4, 5, 0);
149+
Output : Storage_Array (1 .. 10);
150+
Length : Storage_Count;
151+
begin
152+
COBS.Decode (Input, Output, Length);
153+
Assert (Output (1 .. Length) = Expected_Output, "Failed output");
154+
end Test_Decode_No_Frame_Delimiter;
155+
156+
------------------------------
157+
-- Test_Decode_Test_Vectors --
158+
------------------------------
159+
160+
-- Test the decoder with some test vectors.
161+
162+
procedure Test_Decode_Test_Vectors (T : in out Test)
163+
is
164+
-- Short case with no replaced bytes.
165+
Input_1 : constant Storage_Array (1 .. 7) := (6, 1, 2, 3, 4, 5, 0);
166+
Output_1 : constant Storage_Array (1 .. 5) := ( 1, 2, 3, 4, 5 );
167+
168+
-- Short case with one replaced byte.
169+
Input_2 : constant Storage_Array (1 .. 7) := (3, 1, 2, 3, 4, 5, 0);
170+
Output_2 : constant Storage_Array (1 .. 5) := ( 1, 2, 0, 4, 5 );
171+
172+
-- Case where data size is 253 (no extra overhead byte)
173+
Input_3 : constant Storage_Array (1 .. 255) := (1 => 254, -- Overhead byte
174+
255 => 0, -- Frame delimiter
175+
others => 123);
176+
Output_3 : constant Storage_Array (1 .. 253) := (others => 123);
177+
178+
-- Case where data size is 254 (no extra overhead byte)
179+
Input_4 : constant Storage_Array (1 .. 256) := (1 => 255, -- Overhead byte
180+
256 => 0, -- Frame delimiter
181+
others => 123);
182+
Output_4 : constant Storage_Array (1 .. 254) := (others => 123);
183+
184+
-- Case where data size is 255 (1 extra overhead byte)
185+
Input_5 : constant Storage_Array (1 .. 258) := (1 => 255, -- Overhead byte
186+
256 => 2, -- Overhead byte
187+
258 => 0, -- Frame delimiter
188+
others => 123);
189+
Output_5 : constant Storage_Array (1 .. 255) := (others => 123);
190+
191+
192+
Output : Storage_Array (1 .. 1000);
193+
Length : Storage_Count;
194+
begin
195+
196+
COBS.Decode (Input_1, Output, Length);
197+
Assert (Output (1 .. Length) = Output_1, "Failed test vector 1");
198+
199+
COBS.Decode (Input_2, Output, Length);
200+
Assert (Output (1 .. Length) = Output_2, "Failed test vector 2");
201+
202+
COBS.Decode (Input_3, Output, Length);
203+
Assert (Output (1 .. Length) = Output_3, "Failed test vector 3");
204+
205+
COBS.Decode (Input_4, Output, Length);
206+
Assert (Output (1 .. Length) = Output_4, "Failed test vector 4");
207+
208+
COBS.Decode (Input_5, Output, Length);
209+
Assert (Output (1 .. Length) = Output_5, "Failed test vector 5");
210+
211+
end Test_Decode_Test_Vectors;
212+
213+
---------------------------------
214+
-- Test_Encode_Decode_Loopback --
215+
---------------------------------
216+
217+
-- Test that encodes then decodes data of varying length.
218+
--
219+
-- The decoded data should match the original data that was encoded.
220+
221+
procedure Test_Encode_Decode_Loopback (T : in out Test)
222+
is
223+
Input : Storage_Array (1 .. 1000);
224+
Encoded : Storage_Array (1 .. 2000);
225+
Decoded : Storage_Array (1 .. 2000);
226+
Length : Storage_Count;
227+
228+
begin
229+
-- Generate a sequence containing no zeroes
230+
231+
for I in Input'Range loop
232+
Input (I) := Storage_Element (I mod Storage_Element'Modulus);
233+
234+
if Input (I) = 0 then
235+
Input (I) := Input (I) + 1;
236+
end if;
237+
end loop;
238+
239+
-- Put some zeroes in the data with varying distances between them.
240+
241+
Input (5) := 0;
242+
Input (300) := 0;
243+
Input (400) := 0;
244+
Input (401) := 0;
245+
Input (402) := 0;
246+
Input (700) := 0;
247+
Input (999) := 0;
248+
249+
-- Test varying lengths of input data.
250+
251+
for I in 1 .. Input'Length loop
252+
COBS.Encode (Input, Encoded, Length);
253+
COBS.Decode (Encoded (1 .. Length), Decoded, Length);
254+
255+
Assert (Length = Input'Length,
256+
"Invalid length on iteration:" & Integer'Image (I));
257+
258+
Assert (Decoded (1 .. Length) = Input,
259+
"Decoded data does not match original input on iteration:" & Integer'Image (I));
260+
end loop;
261+
end Test_Encode_Decode_Loopback;
262+
263+
-----------
264+
-- Suite --
265+
-----------
266+
267+
function Suite return AUnit.Test_Suites.Access_Test_Suite
268+
is
269+
Ret : constant Access_Test_Suite := new Test_Suite;
270+
begin
271+
Ret.Add_Test (Test_Caller.Create ("Encode an empty array",
272+
Test_Encode_Empty'Access));
273+
Ret.Add_Test (Test_Caller.Create ("Encode an array of all zeroes",
274+
Test_Encode_All_Zeroes'Access));
275+
Ret.Add_Test (Test_Caller.Create ("Encode an array of no zeroes",
276+
Test_Encode_No_Zeroes'Access));
277+
Ret.Add_Test (Test_Caller.Create ("Decode an empty frame",
278+
Test_Decode_Empty_Frame'Access));
279+
Ret.Add_Test (Test_Caller.Create ("Decode a frame with a missing frame delimiter",
280+
Test_Decode_No_Frame_Delimiter'Access));
281+
Ret.Add_Test (Test_Caller.Create ("Decode test vectors",
282+
Test_Decode_Test_Vectors'Access));
283+
Ret.Add_Test (Test_Caller.Create ("Encode/decode loopback",
284+
Test_Encode_Decode_Loopback'Access));
285+
286+
return Ret;
287+
end Suite;
288+
289+
end COBS_Tests;

tests/src/cobs_tests.ads

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-------------------------------------------------------------------------------
2+
-- Copyright (c) 2020 Daniel King
3+
--
4+
-- Permission is hereby granted, free of charge, to any person obtaining a
5+
-- copy of this software and associated documentation files (the "Software"),
6+
-- to deal in the Software without restriction, including without limitation
7+
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
-- and/or sell copies of the Software, and to permit persons to whom the
9+
-- Software is furnished to do so, subject to the following conditions:
10+
--
11+
-- The above copyright notice and this permission notice shall be included in
12+
-- all copies or substantial portions of the Software.
13+
--
14+
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20+
-- DEALINGS IN THE SOFTWARE.
21+
-------------------------------------------------------------------------------
22+
with AUnit.Test_Fixtures;
23+
with AUnit.Test_Suites;
24+
25+
package COBS_Tests
26+
is
27+
28+
type Test is new AUnit.Test_Fixtures.Test_Fixture with null record;
29+
30+
--------------------
31+
-- Encode tests --
32+
--------------------
33+
34+
procedure Test_Encode_Empty (T : in out Test);
35+
procedure Test_Encode_All_Zeroes (T : in out Test);
36+
procedure Test_Encode_No_Zeroes (T : in out Test);
37+
38+
--------------------
39+
-- Decode tests --
40+
--------------------
41+
42+
procedure Test_Decode_Empty_Frame (T : in out Test);
43+
procedure Test_Decode_No_Frame_Delimiter (T : in out Test);
44+
procedure Test_Decode_Test_Vectors (T : in out Test);
45+
46+
---------------------------
47+
-- Encode/decode tests --
48+
---------------------------
49+
50+
procedure Test_Encode_Decode_Loopback (T : in out Test);
51+
52+
----------------
53+
-- Test suite --
54+
----------------
55+
56+
function Suite return AUnit.Test_Suites.Access_Test_Suite;
57+
58+
end COBS_Tests;

0 commit comments

Comments
 (0)