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