• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <inttypes.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdbool.h>
28 #include <string.h>
29 #ifdef _MSC_VER
30 #include <BaseTsd.h>
31 typedef SSIZE_T ssize_t;
32 #endif
33 
34 #include "util/ralloc.h"
35 #include "blob.h"
36 
37 #include <gtest/gtest.h>
38 #include "mesa-gtest-extras.h"
39 
40 #define bytes_test_str     "bytes_test"
41 #define reserve_test_str   "reserve_test"
42 
43 // This placeholder must be the same length as the next overwrite_test_str.
44 #define placeholder_str    "XXXXXXXXXXXXXX"
45 #define overwrite_test_str "overwrite_test"
46 #define uint32_test        0x12345678
47 #define uint32_placeholder 0xDEADBEEF
48 #define uint32_overwrite   0xA1B2C3D4
49 #define uint64_test        0x1234567890ABCDEF
50 #define string_test_str    "string_test"
51 
52 
53 // Test at least one call of each blob_write_foo and blob_read_foo function,
54 // verifying that we read out everything we wrote, that every bytes is
55 // consumed, and that the overrun bit is not set.
TEST(BlobTest,WriteAndReadFunctions)56 TEST(BlobTest, WriteAndReadFunctions)
57 {
58    struct blob blob;
59    struct blob_reader reader;
60    ssize_t reserved;
61    size_t str_offset, uint_offset;
62    uint8_t reserve_buf[sizeof(reserve_test_str)];
63 
64    blob_init(&blob);
65 
66    // Test blob by writing one of every possible kind of value.
67 
68    blob_write_bytes(&blob, bytes_test_str, sizeof(bytes_test_str));
69 
70    reserved = blob_reserve_bytes(&blob, sizeof(reserve_test_str));
71    blob_overwrite_bytes(&blob, reserved, reserve_test_str, sizeof(reserve_test_str));
72 
73    // Write a placeholder, (to be replaced later via overwrite_bytes).
74    str_offset = blob.size;
75    blob_write_bytes(&blob, placeholder_str, sizeof(placeholder_str));
76 
77    blob_write_uint32(&blob, uint32_test);
78 
79    // Write a placeholder, (to be replaced later via overwrite_uint32).
80    uint_offset = blob.size;
81    blob_write_uint32(&blob, uint32_placeholder);
82 
83    blob_write_uint64(&blob, uint64_test);
84 
85    blob_write_intptr(&blob, (intptr_t) &blob);
86 
87    blob_write_string(&blob, string_test_str);
88 
89    // Finally, overwrite our placeholders.
90    blob_overwrite_bytes(&blob, str_offset, overwrite_test_str,
91                         sizeof(overwrite_test_str));
92    blob_overwrite_uint32(&blob, uint_offset, uint32_overwrite);
93 
94    // Now read each value and verify.
95 
96    blob_reader_init(&reader, blob.data, blob.size);
97 
98    EXPECT_STREQ(bytes_test_str,
99                 (const char *)blob_read_bytes(&reader, sizeof(bytes_test_str))) <<
100                 "blob_write/read_bytes";
101 
102    blob_copy_bytes(&reader, reserve_buf, sizeof(reserve_buf));
103 
104    EXPECT_STREQ(reserve_test_str, (char *) reserve_buf)
105       << "blob_reserve_bytes/blob_copy_bytes";
106 
107    EXPECT_STREQ(overwrite_test_str,
108                 (const char *) blob_read_bytes(&reader, sizeof(overwrite_test_str)))
109       << "blob_overwrite_bytes";
110 
111    EXPECT_EQ(uint32_test, blob_read_uint32(&reader)) << "blob_write/read_uint32";
112    EXPECT_EQ(uint32_overwrite, blob_read_uint32(&reader)) << "blob_overwrite_uint32";
113    EXPECT_EQ(uint64_test, blob_read_uint64(&reader)) << "blob_write/read_uint64";
114    EXPECT_EQ((intptr_t) &blob, blob_read_intptr(&reader)) << "blob_write/read_intptr";
115 
116    EXPECT_STREQ(string_test_str, blob_read_string(&reader)) << "blob_write/read_string";
117 
118    EXPECT_EQ(reader.end - reader.data, reader.current - reader.data) << "read_consumes_all_bytes";
119    EXPECT_FALSE(reader.overrun) << "read_does_not_overrun";
120 
121    blob_finish(&blob);
122 }
123 
124 // Test that data values are written and read with proper alignment.
TEST(BlobTest,Alignment)125 TEST(BlobTest, Alignment)
126 {
127    struct blob blob;
128    struct blob_reader reader;
129    uint8_t bytes[] = "ABCDEFGHIJKLMNOP";
130    size_t delta, last, num_bytes;
131 
132    blob_init(&blob);
133 
134    // First, write an intptr value to the blob and capture that size. This is
135    // the expected offset between any pair of intptr values (if written with
136    // alignment).
137    blob_write_intptr(&blob, (intptr_t) &blob);
138 
139    delta = blob.size;
140    last = blob.size;
141 
142    // Then loop doing the following:
143    //
144    //   1. Write an unaligned number of bytes
145    //   2. Verify that write results in an unaligned size
146    //   3. Write an intptr_t value
147    //   2. Verify that that write results in an aligned size
148    //
149    for (num_bytes = 1; num_bytes < sizeof(intptr_t); num_bytes++) {
150       blob_write_bytes(&blob, bytes, num_bytes);
151 
152       EXPECT_NE(delta, blob.size - last) << "unaligned write of bytes";
153 
154       blob_write_intptr(&blob, (intptr_t) &blob);
155 
156       EXPECT_EQ(2 * delta, blob.size - last) << "aligned write of intptr";
157 
158       last = blob.size;
159    }
160 
161    // Finally, test that reading also does proper alignment. Since we know
162    // that values were written with all the right alignment, all we have to do
163    // here is verify that correct values are read.
164    blob_reader_init(&reader, blob.data, blob.size);
165 
166    EXPECT_EQ((intptr_t) &blob, blob_read_intptr(&reader))
167       << "read of initial, aligned intptr_t";
168 
169    for (num_bytes = 1; num_bytes < sizeof(intptr_t); num_bytes++) {
170       EXPECT_U8_ARRAY_EQUAL(bytes, (const uint8_t *) blob_read_bytes(&reader, num_bytes),
171                             num_bytes) << "unaligned read of bytes";
172       EXPECT_EQ((intptr_t) &blob, blob_read_intptr(&reader)) << "aligned read of intptr_t";
173    }
174 
175    blob_finish(&blob);
176 }
177 
178 // Test that we detect overrun.
TEST(BlobTest,DetectOverrun)179 TEST(BlobTest, DetectOverrun)
180 {
181    struct blob blob;
182    struct blob_reader reader;
183    uint32_t value = 0xdeadbeef;
184 
185    blob_init(&blob);
186 
187    blob_write_uint32(&blob, value);
188 
189    blob_reader_init(&reader, blob.data, blob.size);
190 
191    EXPECT_EQ(value, blob_read_uint32(&reader)) << "read before overrun";
192    EXPECT_FALSE(reader.overrun);
193    EXPECT_EQ(0, blob_read_uint32(&reader)) << "read at overrun";
194    EXPECT_TRUE(reader.overrun);
195 
196    blob_finish(&blob);
197 }
198 
199 // Test that we can read and write some large objects, (exercising the code in
200 // the blob_write functions to realloc blob->data.
TEST(BlobTest,BigObjects)201 TEST(BlobTest, BigObjects)
202 {
203    void *ctx = ralloc_context(NULL);
204    struct blob blob;
205    struct blob_reader reader;
206    int size = 1000;
207    int count = 1000;
208    char *buf;
209 
210    blob_init(&blob);
211 
212    // Initialize our buffer.
213    buf = (char *) ralloc_size(ctx, size);
214    for (int i = 0; i < size; i++) {
215       buf[i] = i % 256;
216    }
217 
218    // Write it many times.
219    for (int i = 0; i < count; i++) {
220       blob_write_bytes(&blob, buf, size);
221    }
222 
223    blob_reader_init(&reader, blob.data, blob.size);
224 
225    // Read and verify it many times.
226    for (int i = 0; i < count; i++) {
227       EXPECT_U8_ARRAY_EQUAL((uint8_t *) buf,
228                             (const uint8_t *) blob_read_bytes(&reader, size), size)
229          << "read of large objects, iteration " << i;
230    }
231 
232    EXPECT_EQ(reader.end - reader.data, reader.current - reader.data)
233       << "number of bytes read reading large objects";
234 
235    EXPECT_FALSE(reader.overrun) << "overrun flag not set reading large objects";
236 
237    blob_finish(&blob);
238    ralloc_free(ctx);
239 }
240