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 26#include <inttypes.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <stdbool.h> 30#include <string.h> 31#ifdef _MSC_VER 32#include <BaseTsd.h> 33typedef SSIZE_T ssize_t; 34#endif 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 51bool error = false; 52 53static void 54expect_equal(uint64_t expected, uint64_t actual, const char *test) 55{ 56 if (actual != expected) { 57 fprintf(stderr, 58 "Error: Test '%s' failed: " 59 "Expected=%" PRIu64 ", " 60 "Actual=%" PRIu64 "\n", 61 test, expected, actual); 62 error = true; 63 } 64} 65 66static void 67expect_unequal(uint64_t expected, uint64_t actual, const char *test) 68{ 69 if (actual == expected) { 70 fprintf(stderr, 71 "Error: Test '%s' failed: Result=%" PRIu64 ", " 72 "but expected something different.\n", 73 test, actual); 74 error = true; 75 } 76} 77 78static void 79expect_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 89static void 90expect_equal_bytes(uint8_t *expected, const uint8_t *actual, 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 */ 122static void 123test_write_and_read_functions (void) 124{ 125 struct blob blob; 126 struct blob_reader reader; 127 ssize_t reserved; 128 size_t str_offset, uint_offset; 129 uint8_t reserve_buf[sizeof(reserve_test_str)]; 130 131 blob_init(&blob); 132 133 /*** Test blob by writing one of every possible kind of value. */ 134 135 blob_write_bytes(&blob, bytes_test_str, sizeof(bytes_test_str)); 136 137 reserved = blob_reserve_bytes(&blob, sizeof(reserve_test_str)); 138 blob_overwrite_bytes(&blob, reserved, reserve_test_str, sizeof(reserve_test_str)); 139 140 /* Write a placeholder, (to be replaced later via overwrite_bytes) */ 141 str_offset = blob.size; 142 blob_write_bytes(&blob, placeholder_str, sizeof(placeholder_str)); 143 144 blob_write_uint32(&blob, uint32_test); 145 146 /* Write a placeholder, (to be replaced later via overwrite_uint32) */ 147 uint_offset = blob.size; 148 blob_write_uint32(&blob, uint32_placeholder); 149 150 blob_write_uint64(&blob, uint64_test); 151 152 blob_write_intptr(&blob, (intptr_t) &blob); 153 154 blob_write_string(&blob, string_test_str); 155 156 /* Finally, overwrite our placeholders. */ 157 blob_overwrite_bytes(&blob, str_offset, overwrite_test_str, 158 sizeof(overwrite_test_str)); 159 blob_overwrite_uint32(&blob, uint_offset, uint32_overwrite); 160 161 /*** Now read each value and verify. */ 162 blob_reader_init(&reader, blob.data, blob.size); 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"); 182 expect_equal((intptr_t) &blob, blob_read_intptr(&reader), 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 191 blob_finish(&blob); 192} 193 194/* Test that data values are written and read with proper alignment. */ 195static void 196test_alignment(void) 197{ 198 struct blob blob; 199 struct blob_reader reader; 200 uint8_t bytes[] = "ABCDEFGHIJKLMNOP"; 201 size_t delta, last, num_bytes; 202 203 blob_init(&blob); 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 */ 209 blob_write_intptr(&blob, (intptr_t) &blob); 210 211 delta = blob.size; 212 last = blob.size; 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++) { 222 blob_write_bytes(&blob, bytes, num_bytes); 223 224 expect_unequal(delta, blob.size - last, "unaligned write of bytes"); 225 226 blob_write_intptr(&blob, (intptr_t) &blob); 227 228 expect_equal(2 * delta, blob.size - last, "aligned write of intptr"); 229 230 last = blob.size; 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 */ 237 blob_reader_init(&reader, blob.data, blob.size); 238 239 expect_equal((intptr_t) &blob, blob_read_intptr(&reader), 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"); 245 expect_equal((intptr_t) &blob, blob_read_intptr(&reader), 246 "aligned read of intptr_t"); 247 } 248 249 blob_finish(&blob); 250} 251 252/* Test that we detect overrun. */ 253static void 254test_overrun(void) 255{ 256 struct blob blob; 257 struct blob_reader reader; 258 uint32_t value = 0xdeadbeef; 259 260 blob_init(&blob); 261 262 blob_write_uint32(&blob, value); 263 264 blob_reader_init(&reader, blob.data, blob.size); 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 271 blob_finish(&blob); 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 */ 277static void 278test_big_objects(void) 279{ 280 void *ctx = ralloc_context(NULL); 281 struct blob blob; 282 struct blob_reader reader; 283 int size = 1000; 284 int count = 1000; 285 size_t i; 286 char *buf; 287 288 blob_init(&blob); 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++) { 298 blob_write_bytes(&blob, buf, size); 299 } 300 301 blob_reader_init(&reader, blob.data, blob.size); 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 315 blob_finish(&blob); 316 ralloc_free(ctx); 317} 318 319int 320main (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} 329