Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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