Skip to content

Commit

Permalink
Add unit tests (#2)
Browse files Browse the repository at this point in the history
* Add unit tests

* Fix wrong job name

* Fix run_tests.sh file permissions
  • Loading branch information
damaki authored Aug 30, 2020
1 parent 5a8d845 commit 265ca94
Show file tree
Hide file tree
Showing 6 changed files with 414 additions and 1 deletion.
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Proof
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "gnatprove -P /app/cobs.gpr -j0 --level=1"
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "gnatprove -P /app/cobs.gpr -j0 --level=1"
unit_test:
name: unit_test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Unit tests
run: docker run -v $PWD:/app componolit/ci:gnat-community-2020 /bin/sh -c "cd /app/tests && ./run_tests.sh"
4 changes: 4 additions & 0 deletions tests/run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

gprbuild -p -P unit_tests.gpr -j0
obj/main
289 changes: 289 additions & 0 deletions tests/src/cobs_tests.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
-------------------------------------------------------------------------------
-- Copyright (c) 2020 Daniel King
--
-- Permission is hereby granted, free of charge, to any person obtaining a
-- copy of this software and associated documentation files (the "Software"),
-- to deal in the Software without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
with AUnit.Assertions; use AUnit.Assertions;
with AUnit.Test_Caller;
with AUnit.Test_Suites; use AUnit.Test_Suites;

with System.Storage_Elements; use System.Storage_Elements;

with COBS;

package body COBS_Tests
is

package Test_Caller is new AUnit.Test_Caller (Test);

-----------------------
-- Test_Encode_Empty --
-----------------------

-- Test the output of Encode when presented with an empty input.
-- The output should only consist of the overhead byte and frame delimiter.

procedure Test_Encode_Empty (T : in out Test)
is
Input : constant Storage_Array (1 .. 0) := (others => 0);
Output : Storage_Array (1 .. 2);
Length : Storage_Count;

Expected_Output : constant Storage_Array (1 .. 2) :=
(1 => 1, -- Overhead byte
2 => 0); -- Frame delimiter

begin
COBS.Encode (Input, Output, Length);

Assert (Length = 2, "Incorrect Length");
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
end Test_Encode_Empty;

----------------------------
-- Test_Encode_All_Zeroes --
----------------------------

-- Test the output of Encode when presented with an input that consists
-- of all zeroes.
--
-- The output should not contain any additional overhead bytes.

procedure Test_Encode_All_Zeroes (T : in out Test)
is
Input : constant Storage_Array (1 .. 1000) := (others => 0);
Output : Storage_Array (1 .. 2000);
Length : Storage_Count;

Expected_Output : constant Storage_Array (1 .. 1002) :=
(1 => 1, -- Overhead byte
1002 => 0, -- Frame delimiter
others => 1); -- Data bytes (encoded)

begin
COBS.Encode (Input, Output, Length);

Assert (Length = 1002, "Incorrect Length");
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
end Test_Encode_All_Zeroes;

---------------------------
-- Test_Encode_No_Zeroes --
---------------------------

-- Test the output of Encode when presented with an input consisting of
-- no zero bytes.
--
-- The output should contain additional overhead bytes, in groups of 254 bytes.

procedure Test_Encode_No_Zeroes (T : in out Test)
is
Input : constant Storage_Array (1 .. 1000) := (others => 1);
Output : Storage_Array (1 .. 2000);
Length : Storage_Count;

Expected_Output : constant Storage_Array (1 .. 1005) :=
(1 => 255, -- 1st overhead byte
256 => 255, -- 2nd overhead byte
511 => 255, -- 3rd overhead byte
766 => 239, -- 4th overhead byte
1005 => 0, -- Frame delimiter
others => 1); -- Data byte

begin
COBS.Encode (Input, Output, Length);

Assert (Length = 1005, "Incorrect Length");
Assert (Output (1 .. Length) = Expected_Output, "Incorrect output");
end Test_Encode_No_Zeroes;

-----------------------------
-- Test_Decode_Empty_Frame --
-----------------------------

-- Test the decoder when presented with an empty frame.
--
-- The output should be of length 0.

procedure Test_Decode_Empty_Frame (T : in out Test)
is
Input : constant Storage_Array (1 .. 1) := (others => 0);
Output : Storage_Array (1 .. 1);
Length : Storage_Count;

begin
COBS.Decode (Input, Output, Length);

Assert (Length = 0, "Incorrect length");
end Test_Decode_Empty_Frame;

------------------------------------
-- Test_Decode_No_Frame_Delimiter --
------------------------------------

-- Test the decoder behaviour when the frame delimiter is missing from
-- the input buffer.
--
-- The decoder should continue until the end of the input buffer is reached.

procedure Test_Decode_No_Frame_Delimiter (T : in out Test)
is
Input : constant Storage_Array (1 .. 7) := (6, 1, 2, 3, 4, 5, 5);
Expected_Output : constant Storage_Array (1 .. 6) := ( 1, 2, 3, 4, 5, 0);
Output : Storage_Array (1 .. 10);
Length : Storage_Count;
begin
COBS.Decode (Input, Output, Length);
Assert (Output (1 .. Length) = Expected_Output, "Failed output");
end Test_Decode_No_Frame_Delimiter;

------------------------------
-- Test_Decode_Test_Vectors --
------------------------------

-- Test the decoder with some test vectors.

procedure Test_Decode_Test_Vectors (T : in out Test)
is
-- Short case with no replaced bytes.
Input_1 : constant Storage_Array (1 .. 7) := (6, 1, 2, 3, 4, 5, 0);
Output_1 : constant Storage_Array (1 .. 5) := ( 1, 2, 3, 4, 5 );

-- Short case with one replaced byte.
Input_2 : constant Storage_Array (1 .. 7) := (3, 1, 2, 3, 4, 5, 0);
Output_2 : constant Storage_Array (1 .. 5) := ( 1, 2, 0, 4, 5 );

-- Case where data size is 253 (no extra overhead byte)
Input_3 : constant Storage_Array (1 .. 255) := (1 => 254, -- Overhead byte
255 => 0, -- Frame delimiter
others => 123);
Output_3 : constant Storage_Array (1 .. 253) := (others => 123);

-- Case where data size is 254 (no extra overhead byte)
Input_4 : constant Storage_Array (1 .. 256) := (1 => 255, -- Overhead byte
256 => 0, -- Frame delimiter
others => 123);
Output_4 : constant Storage_Array (1 .. 254) := (others => 123);

-- Case where data size is 255 (1 extra overhead byte)
Input_5 : constant Storage_Array (1 .. 258) := (1 => 255, -- Overhead byte
256 => 2, -- Overhead byte
258 => 0, -- Frame delimiter
others => 123);
Output_5 : constant Storage_Array (1 .. 255) := (others => 123);


Output : Storage_Array (1 .. 1000);
Length : Storage_Count;
begin

COBS.Decode (Input_1, Output, Length);
Assert (Output (1 .. Length) = Output_1, "Failed test vector 1");

COBS.Decode (Input_2, Output, Length);
Assert (Output (1 .. Length) = Output_2, "Failed test vector 2");

COBS.Decode (Input_3, Output, Length);
Assert (Output (1 .. Length) = Output_3, "Failed test vector 3");

COBS.Decode (Input_4, Output, Length);
Assert (Output (1 .. Length) = Output_4, "Failed test vector 4");

COBS.Decode (Input_5, Output, Length);
Assert (Output (1 .. Length) = Output_5, "Failed test vector 5");

end Test_Decode_Test_Vectors;

---------------------------------
-- Test_Encode_Decode_Loopback --
---------------------------------

-- Test that encodes then decodes data of varying length.
--
-- The decoded data should match the original data that was encoded.

procedure Test_Encode_Decode_Loopback (T : in out Test)
is
Input : Storage_Array (1 .. 1000);
Encoded : Storage_Array (1 .. 2000);
Decoded : Storage_Array (1 .. 2000);
Length : Storage_Count;

begin
-- Generate a sequence containing no zeroes

for I in Input'Range loop
Input (I) := Storage_Element (I mod Storage_Element'Modulus);

if Input (I) = 0 then
Input (I) := Input (I) + 1;
end if;
end loop;

-- Put some zeroes in the data with varying distances between them.

Input (5) := 0;
Input (300) := 0;
Input (400) := 0;
Input (401) := 0;
Input (402) := 0;
Input (700) := 0;
Input (999) := 0;

-- Test varying lengths of input data.

for I in 1 .. Input'Length loop
COBS.Encode (Input, Encoded, Length);
COBS.Decode (Encoded (1 .. Length), Decoded, Length);

Assert (Length = Input'Length,
"Invalid length on iteration:" & Integer'Image (I));

Assert (Decoded (1 .. Length) = Input,
"Decoded data does not match original input on iteration:" & Integer'Image (I));
end loop;
end Test_Encode_Decode_Loopback;

-----------
-- Suite --
-----------

function Suite return AUnit.Test_Suites.Access_Test_Suite
is
Ret : constant Access_Test_Suite := new Test_Suite;
begin
Ret.Add_Test (Test_Caller.Create ("Encode an empty array",
Test_Encode_Empty'Access));
Ret.Add_Test (Test_Caller.Create ("Encode an array of all zeroes",
Test_Encode_All_Zeroes'Access));
Ret.Add_Test (Test_Caller.Create ("Encode an array of no zeroes",
Test_Encode_No_Zeroes'Access));
Ret.Add_Test (Test_Caller.Create ("Decode an empty frame",
Test_Decode_Empty_Frame'Access));
Ret.Add_Test (Test_Caller.Create ("Decode a frame with a missing frame delimiter",
Test_Decode_No_Frame_Delimiter'Access));
Ret.Add_Test (Test_Caller.Create ("Decode test vectors",
Test_Decode_Test_Vectors'Access));
Ret.Add_Test (Test_Caller.Create ("Encode/decode loopback",
Test_Encode_Decode_Loopback'Access));

return Ret;
end Suite;

end COBS_Tests;
58 changes: 58 additions & 0 deletions tests/src/cobs_tests.ads
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-------------------------------------------------------------------------------
-- Copyright (c) 2020 Daniel King
--
-- Permission is hereby granted, free of charge, to any person obtaining a
-- copy of this software and associated documentation files (the "Software"),
-- to deal in the Software without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
with AUnit.Test_Fixtures;
with AUnit.Test_Suites;

package COBS_Tests
is

type Test is new AUnit.Test_Fixtures.Test_Fixture with null record;

--------------------
-- Encode tests --
--------------------

procedure Test_Encode_Empty (T : in out Test);
procedure Test_Encode_All_Zeroes (T : in out Test);
procedure Test_Encode_No_Zeroes (T : in out Test);

--------------------
-- Decode tests --
--------------------

procedure Test_Decode_Empty_Frame (T : in out Test);
procedure Test_Decode_No_Frame_Delimiter (T : in out Test);
procedure Test_Decode_Test_Vectors (T : in out Test);

---------------------------
-- Encode/decode tests --
---------------------------

procedure Test_Encode_Decode_Loopback (T : in out Test);

----------------
-- Test suite --
----------------

function Suite return AUnit.Test_Suites.Access_Test_Suite;

end COBS_Tests;
Loading

0 comments on commit 265ca94

Please sign in to comment.