|
| 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; |
0 commit comments