Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright © 2014 Intel Corporation |
| 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 (including the next |
| 12 | * paragraph) shall be included in all copies or substantial portions of the |
| 13 | * Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 | * IN THE SOFTWARE. |
| 22 | */ |
| 23 | |
| 24 | /* A collection of unit tests for blob.c */ |
| 25 | |
Aaron Watry | 60c3a0a | 2016-11-22 11:18:11 -0600 | [diff] [blame] | 26 | #include <inttypes.h> |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> |
| 29 | #include <stdbool.h> |
| 30 | #include <string.h> |
Dylan Baker | 5eb0f33 | 2018-05-22 15:32:22 -0700 | [diff] [blame] | 31 | #ifdef _MSC_VER |
| 32 | #include <BaseTsd.h> |
| 33 | typedef SSIZE_T ssize_t; |
| 34 | #endif |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 35 | |
| 36 | #include "util/ralloc.h" |
| 37 | #include "blob.h" |
| 38 | |
| 39 | #define bytes_test_str "bytes_test" |
| 40 | #define reserve_test_str "reserve_test" |
| 41 | |
| 42 | /* This placeholder must be the same length as the next overwrite_test_str */ |
| 43 | #define placeholder_str "XXXXXXXXXXXXXX" |
| 44 | #define overwrite_test_str "overwrite_test" |
| 45 | #define uint32_test 0x12345678 |
| 46 | #define uint32_placeholder 0xDEADBEEF |
| 47 | #define uint32_overwrite 0xA1B2C3D4 |
| 48 | #define uint64_test 0x1234567890ABCDEF |
| 49 | #define string_test_str "string_test" |
| 50 | |
| 51 | bool error = false; |
| 52 | |
| 53 | static void |
| 54 | expect_equal(uint64_t expected, uint64_t actual, const char *test) |
| 55 | { |
| 56 | if (actual != expected) { |
Aaron Watry | 60c3a0a | 2016-11-22 11:18:11 -0600 | [diff] [blame] | 57 | fprintf(stderr, |
| 58 | "Error: Test '%s' failed: " |
| 59 | "Expected=%" PRIu64 ", " |
| 60 | "Actual=%" PRIu64 "\n", |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 61 | test, expected, actual); |
| 62 | error = true; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | static void |
| 67 | expect_unequal(uint64_t expected, uint64_t actual, const char *test) |
| 68 | { |
| 69 | if (actual == expected) { |
Aaron Watry | 60c3a0a | 2016-11-22 11:18:11 -0600 | [diff] [blame] | 70 | fprintf(stderr, |
| 71 | "Error: Test '%s' failed: Result=%" PRIu64 ", " |
| 72 | "but expected something different.\n", |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 73 | test, actual); |
| 74 | error = true; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | static void |
| 79 | expect_equal_str(const char *expected, const char *actual, const char *test) |
| 80 | { |
| 81 | if (strcmp(expected, actual)) { |
| 82 | fprintf (stderr, "Error: Test '%s' failed:\n\t" |
| 83 | "Expected=\"%s\", Actual=\"%s\"\n", |
| 84 | test, expected, actual); |
| 85 | error = true; |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | static void |
Jason Ekstrand | 4d56ff0 | 2017-10-11 12:09:02 -0700 | [diff] [blame] | 90 | expect_equal_bytes(uint8_t *expected, const uint8_t *actual, |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 91 | size_t num_bytes, const char *test) |
| 92 | { |
| 93 | size_t i; |
| 94 | |
| 95 | if (memcmp(expected, actual, num_bytes)) { |
| 96 | fprintf (stderr, "Error: Test '%s' failed:\n\t", test); |
| 97 | |
| 98 | fprintf (stderr, "Expected=["); |
| 99 | for (i = 0; i < num_bytes; i++) { |
| 100 | if (i != 0) |
| 101 | fprintf(stderr, ", "); |
| 102 | fprintf(stderr, "0x%02x", expected[i]); |
| 103 | } |
| 104 | fprintf (stderr, "]"); |
| 105 | |
| 106 | fprintf (stderr, "Actual=["); |
| 107 | for (i = 0; i < num_bytes; i++) { |
| 108 | if (i != 0) |
| 109 | fprintf(stderr, ", "); |
| 110 | fprintf(stderr, "0x%02x", actual[i]); |
| 111 | } |
| 112 | fprintf (stderr, "]\n"); |
| 113 | |
| 114 | error = true; |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /* Test at least one call of each blob_write_foo and blob_read_foo function, |
| 119 | * verifying that we read out everything we wrote, that every bytes is |
| 120 | * consumed, and that the overrun bit is not set. |
| 121 | */ |
| 122 | static void |
| 123 | test_write_and_read_functions (void) |
| 124 | { |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 125 | struct blob blob; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 126 | struct blob_reader reader; |
Connor Abbott | 6935440 | 2017-09-15 00:29:46 -0400 | [diff] [blame] | 127 | ssize_t reserved; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 128 | size_t str_offset, uint_offset; |
| 129 | uint8_t reserve_buf[sizeof(reserve_test_str)]; |
| 130 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 131 | blob_init(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 132 | |
| 133 | /*** Test blob by writing one of every possible kind of value. */ |
| 134 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 135 | blob_write_bytes(&blob, bytes_test_str, sizeof(bytes_test_str)); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 136 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 137 | reserved = blob_reserve_bytes(&blob, sizeof(reserve_test_str)); |
Connor Abbott | 6935440 | 2017-09-15 00:29:46 -0400 | [diff] [blame] | 138 | blob_overwrite_bytes(&blob, reserved, reserve_test_str, sizeof(reserve_test_str)); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 139 | |
| 140 | /* Write a placeholder, (to be replaced later via overwrite_bytes) */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 141 | str_offset = blob.size; |
| 142 | blob_write_bytes(&blob, placeholder_str, sizeof(placeholder_str)); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 143 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 144 | blob_write_uint32(&blob, uint32_test); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 145 | |
| 146 | /* Write a placeholder, (to be replaced later via overwrite_uint32) */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 147 | uint_offset = blob.size; |
| 148 | blob_write_uint32(&blob, uint32_placeholder); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 149 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 150 | blob_write_uint64(&blob, uint64_test); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 151 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 152 | blob_write_intptr(&blob, (intptr_t) &blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 153 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 154 | blob_write_string(&blob, string_test_str); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 155 | |
| 156 | /* Finally, overwrite our placeholders. */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 157 | blob_overwrite_bytes(&blob, str_offset, overwrite_test_str, |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 158 | sizeof(overwrite_test_str)); |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 159 | blob_overwrite_uint32(&blob, uint_offset, uint32_overwrite); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 160 | |
| 161 | /*** Now read each value and verify. */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 162 | blob_reader_init(&reader, blob.data, blob.size); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 163 | |
| 164 | expect_equal_str(bytes_test_str, |
| 165 | blob_read_bytes(&reader, sizeof(bytes_test_str)), |
| 166 | "blob_write/read_bytes"); |
| 167 | |
| 168 | blob_copy_bytes(&reader, reserve_buf, sizeof(reserve_buf)); |
| 169 | expect_equal_str(reserve_test_str, (char *) reserve_buf, |
| 170 | "blob_reserve_bytes/blob_copy_bytes"); |
| 171 | |
| 172 | expect_equal_str(overwrite_test_str, |
| 173 | blob_read_bytes(&reader, sizeof(overwrite_test_str)), |
| 174 | "blob_overwrite_bytes"); |
| 175 | |
| 176 | expect_equal(uint32_test, blob_read_uint32(&reader), |
| 177 | "blob_write/read_uint32"); |
| 178 | expect_equal(uint32_overwrite, blob_read_uint32(&reader), |
| 179 | "blob_overwrite_uint32"); |
| 180 | expect_equal(uint64_test, blob_read_uint64(&reader), |
| 181 | "blob_write/read_uint64"); |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 182 | expect_equal((intptr_t) &blob, blob_read_intptr(&reader), |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 183 | "blob_write/read_intptr"); |
| 184 | expect_equal_str(string_test_str, blob_read_string(&reader), |
| 185 | "blob_write/read_string"); |
| 186 | |
| 187 | expect_equal(reader.end - reader.data, reader.current - reader.data, |
| 188 | "read_consumes_all_bytes"); |
| 189 | expect_equal(false, reader.overrun, "read_does_not_overrun"); |
| 190 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 191 | blob_finish(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | /* Test that data values are written and read with proper alignment. */ |
| 195 | static void |
| 196 | test_alignment(void) |
| 197 | { |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 198 | struct blob blob; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 199 | struct blob_reader reader; |
| 200 | uint8_t bytes[] = "ABCDEFGHIJKLMNOP"; |
| 201 | size_t delta, last, num_bytes; |
| 202 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 203 | blob_init(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 204 | |
| 205 | /* First, write an intptr value to the blob and capture that size. This is |
| 206 | * the expected offset between any pair of intptr values (if written with |
| 207 | * alignment). |
| 208 | */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 209 | blob_write_intptr(&blob, (intptr_t) &blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 210 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 211 | delta = blob.size; |
| 212 | last = blob.size; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 213 | |
| 214 | /* Then loop doing the following: |
| 215 | * |
| 216 | * 1. Write an unaligned number of bytes |
| 217 | * 2. Verify that write results in an unaligned size |
| 218 | * 3. Write an intptr_t value |
| 219 | * 2. Verify that that write results in an aligned size |
| 220 | */ |
| 221 | for (num_bytes = 1; num_bytes < sizeof(intptr_t); num_bytes++) { |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 222 | blob_write_bytes(&blob, bytes, num_bytes); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 223 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 224 | expect_unequal(delta, blob.size - last, "unaligned write of bytes"); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 225 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 226 | blob_write_intptr(&blob, (intptr_t) &blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 227 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 228 | expect_equal(2 * delta, blob.size - last, "aligned write of intptr"); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 229 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 230 | last = blob.size; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | /* Finally, test that reading also does proper alignment. Since we know |
| 234 | * that values were written with all the right alignment, all we have to do |
| 235 | * here is verify that correct values are read. |
| 236 | */ |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 237 | blob_reader_init(&reader, blob.data, blob.size); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 238 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 239 | expect_equal((intptr_t) &blob, blob_read_intptr(&reader), |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 240 | "read of initial, aligned intptr_t"); |
| 241 | |
| 242 | for (num_bytes = 1; num_bytes < sizeof(intptr_t); num_bytes++) { |
| 243 | expect_equal_bytes(bytes, blob_read_bytes(&reader, num_bytes), |
| 244 | num_bytes, "unaligned read of bytes"); |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 245 | expect_equal((intptr_t) &blob, blob_read_intptr(&reader), |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 246 | "aligned read of intptr_t"); |
| 247 | } |
| 248 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 249 | blob_finish(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 250 | } |
| 251 | |
| 252 | /* Test that we detect overrun. */ |
| 253 | static void |
| 254 | test_overrun(void) |
| 255 | { |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 256 | struct blob blob; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 257 | struct blob_reader reader; |
| 258 | uint32_t value = 0xdeadbeef; |
| 259 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 260 | blob_init(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 261 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 262 | blob_write_uint32(&blob, value); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 263 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 264 | blob_reader_init(&reader, blob.data, blob.size); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 265 | |
| 266 | expect_equal(value, blob_read_uint32(&reader), "read before overrun"); |
| 267 | expect_equal(false, reader.overrun, "overrun flag not set"); |
| 268 | expect_equal(0, blob_read_uint32(&reader), "read at overrun"); |
| 269 | expect_equal(true, reader.overrun, "overrun flag set"); |
| 270 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 271 | blob_finish(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | /* Test that we can read and write some large objects, (exercising the code in |
| 275 | * the blob_write functions to realloc blob->data. |
| 276 | */ |
| 277 | static void |
| 278 | test_big_objects(void) |
| 279 | { |
| 280 | void *ctx = ralloc_context(NULL); |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 281 | struct blob blob; |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 282 | struct blob_reader reader; |
| 283 | int size = 1000; |
| 284 | int count = 1000; |
| 285 | size_t i; |
| 286 | char *buf; |
| 287 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 288 | blob_init(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 289 | |
| 290 | /* Initialize our buffer. */ |
| 291 | buf = ralloc_size(ctx, size); |
| 292 | for (i = 0; i < size; i++) { |
| 293 | buf[i] = i % 256; |
| 294 | } |
| 295 | |
| 296 | /* Write it many times. */ |
| 297 | for (i = 0; i < count; i++) { |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 298 | blob_write_bytes(&blob, buf, size); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 299 | } |
| 300 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 301 | blob_reader_init(&reader, blob.data, blob.size); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 302 | |
| 303 | /* Read and verify it many times. */ |
| 304 | for (i = 0; i < count; i++) { |
| 305 | expect_equal_bytes((uint8_t *) buf, blob_read_bytes(&reader, size), size, |
| 306 | "read of large objects"); |
| 307 | } |
| 308 | |
| 309 | expect_equal(reader.end - reader.data, reader.current - reader.data, |
| 310 | "number of bytes read reading large objects"); |
| 311 | |
| 312 | expect_equal(false, reader.overrun, |
| 313 | "overrun flag not set reading large objects"); |
| 314 | |
Jason Ekstrand | 49bb9f7 | 2017-10-11 09:44:33 -0700 | [diff] [blame] | 315 | blob_finish(&blob); |
Carl Worth | 977ddec | 2014-12-15 15:58:34 -0800 | [diff] [blame] | 316 | ralloc_free(ctx); |
| 317 | } |
| 318 | |
| 319 | int |
| 320 | main (void) |
| 321 | { |
| 322 | test_write_and_read_functions (); |
| 323 | test_alignment (); |
| 324 | test_overrun (); |
| 325 | test_big_objects (); |
| 326 | |
| 327 | return error ? 1 : 0; |
| 328 | } |