| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // TODO(vardhan): Needs a lot more testing. | |
| 6 | |
| 7 #include <mojo/bindings/array.h> | |
| 8 | |
| 9 #include <mojo/bindings/struct.h> | |
| 10 #include <stddef.h> | |
| 11 | |
| 12 #include "gtest/gtest.h" | |
| 13 #include "mojo/public/c/tests/bindings/testing_util.h" | |
| 14 #include "mojo/public/cpp/system/macros.h" | |
| 15 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom-c.h" | |
| 16 #include "mojo/public/interfaces/bindings/tests/test_unions.mojom-c.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // Tests MojomArray_New(). | |
| 21 TEST(ArrayTest, New) { | |
| 22 char bytes_buffer[1000]; | |
| 23 struct MojomBuffer buf = {bytes_buffer, sizeof(bytes_buffer), 0}; | |
| 24 | |
| 25 struct MojomArrayHeader* arr = NULL; | |
| 26 arr = MojomArray_New(&buf, 3, sizeof(uint32_t)); | |
| 27 EXPECT_EQ(buf.buf, (char*)arr); | |
| 28 | |
| 29 // Test that things are rounded up if data is not already multiple-of-8. | |
| 30 EXPECT_EQ(8u // array header | |
| 31 + 3 * sizeof(uint32_t) // space for 3 uint32_ts. | |
| 32 + 4u, // padding to round up to 8 bytes. | |
| 33 buf.num_bytes_used); | |
| 34 | |
| 35 EXPECT_EQ(buf.num_bytes_used, arr->num_bytes); | |
| 36 EXPECT_EQ(3ul, arr->num_elements); | |
| 37 | |
| 38 // Test failure when we try to allocate too much. | |
| 39 EXPECT_EQ(NULL, MojomArray_New(&buf, UINT32_MAX, sizeof(uint32_t))); | |
| 40 EXPECT_EQ(NULL, MojomArray_New(&buf, 1000, sizeof(uint32_t))); | |
| 41 | |
| 42 // Test the simple case (no rounding necessary). | |
| 43 buf.num_bytes_used = 0; | |
| 44 arr = MojomArray_New(&buf, 4, sizeof(uint32_t)); | |
| 45 EXPECT_EQ(8u // array header | |
| 46 + 4 * sizeof(uint32_t), // space for 4 uint32_ts | |
| 47 buf.num_bytes_used); | |
| 48 EXPECT_EQ(buf.num_bytes_used, arr->num_bytes); | |
| 49 EXPECT_EQ(4ul, arr->num_elements); | |
| 50 } | |
| 51 | |
| 52 // Tests serialized size of an array of unions. | |
| 53 TEST(ArraySerializationTest, ArrayOfUnions) { | |
| 54 char bytes_buffer[1000] = {0}; | |
| 55 MojomBuffer buf = {bytes_buffer, sizeof(bytes_buffer), 0}; | |
| 56 | |
| 57 struct mojo_test_SmallStruct* small_struct = | |
| 58 static_cast<struct mojo_test_SmallStruct*>( | |
| 59 MojomBuffer_Allocate(&buf, sizeof(struct mojo_test_SmallStruct))); | |
| 60 *small_struct = mojo_test_SmallStruct{ | |
| 61 // header | |
| 62 { | |
| 63 sizeof(mojo_test_SmallStruct), | |
| 64 0, // version | |
| 65 }, | |
| 66 {NULL}, // dummy_struct | |
| 67 {0, mojo_test_PodUnion_Tag__UNKNOWN__, {}}, // pod_union | |
| 68 {NULL}, // pod_union_array | |
| 69 {NULL}, // nullable_pod_union_array | |
| 70 {NULL}, // s_array | |
| 71 {NULL}, // pod_union_map | |
| 72 {NULL}, // nullable_pod_union_map | |
| 73 }; | |
| 74 | |
| 75 EXPECT_EQ(8u + 6 * 8u // 6 references types | |
| 76 + 1 * 16u, // 1 union type | |
| 77 mojo_test_SmallStruct_ComputeSerializedSize(small_struct)); | |
| 78 | |
| 79 small_struct->nullable_pod_union_array.ptr = | |
| 80 MojomArray_New(&buf, 2, sizeof(struct mojo_test_PodUnion)); | |
| 81 | |
| 82 // 0th element is NULL. | |
| 83 MOJOM_ARRAY_INDEX(small_struct->nullable_pod_union_array.ptr, | |
| 84 struct mojo_test_PodUnion, 0) | |
| 85 ->size = 0; | |
| 86 // 1st element is not NULL. | |
| 87 struct mojo_test_PodUnion* e1 = MOJOM_ARRAY_INDEX( | |
| 88 small_struct->nullable_pod_union_array.ptr, struct mojo_test_PodUnion, 0); | |
| 89 e1->size = sizeof(struct mojo_test_PodUnion); | |
| 90 e1->tag = mojo_test_PodUnion_Tag_f_int8; | |
| 91 e1->data.f_f_int8 = 13; | |
| 92 | |
| 93 EXPECT_EQ(8u + 6 * 8u // 6 references types | |
| 94 + 1 * 16u // 1 union type | |
| 95 + (8u + 16u * 2), // array of 2 unions | |
| 96 mojo_test_SmallStruct_ComputeSerializedSize(small_struct)); | |
| 97 | |
| 98 // Save the underlying buffer before encoding, so we can decode+compare | |
| 99 // later. | |
| 100 char bytes_buffer_copy[sizeof(bytes_buffer)]; | |
| 101 memcpy(bytes_buffer_copy, bytes_buffer, sizeof(bytes_buffer)); | |
| 102 | |
| 103 mojo_test_SmallStruct_EncodePointersAndHandles(small_struct, | |
| 104 buf.num_bytes_used, NULL); | |
| 105 | |
| 106 // The null pointers should now be 0-offsets: | |
| 107 EXPECT_EQ(0u, small_struct->dummy_struct.offset); | |
| 108 EXPECT_EQ(0u, small_struct->pod_union_array.offset); | |
| 109 EXPECT_EQ(0u, small_struct->s_array.offset); | |
| 110 EXPECT_EQ(0u, small_struct->pod_union_map.offset); | |
| 111 EXPECT_EQ(0u, small_struct->nullable_pod_union_map.offset); | |
| 112 | |
| 113 // Test the pod_union_array offset: | |
| 114 EXPECT_EQ( | |
| 115 sizeof(struct mojo_test_SmallStruct) - | |
| 116 offsetof(struct mojo_test_SmallStruct, nullable_pod_union_array), | |
| 117 small_struct->nullable_pod_union_array.offset); | |
| 118 | |
| 119 mojo_test_SmallStruct_DecodePointersAndHandles(small_struct, | |
| 120 buf.num_bytes_used, NULL, 0); | |
| 121 EXPECT_EQ(0, memcmp(buf.buf, bytes_buffer_copy, buf.num_bytes_used)); | |
| 122 | |
| 123 { | |
| 124 char bytes_buffer2[sizeof(bytes_buffer)] = {0}; | |
| 125 struct MojomBuffer buf2 = {bytes_buffer2, sizeof(bytes_buffer2), 0}; | |
| 126 CopyAndCompare(&buf2, small_struct, buf.num_bytes_used, | |
| 127 mojo_test_SmallStruct_DeepCopy, | |
| 128 mojo_test_SmallStruct_EncodePointersAndHandles, | |
| 129 mojo_test_SmallStruct_DecodePointersAndHandles); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 // Tests serialized size of an array of arrays. | |
| 134 TEST(ArraySerializationTest, ArrayOfArrays) { | |
| 135 char bytes_buffer[1000] = {0}; | |
| 136 MojomBuffer buf = {bytes_buffer, sizeof(bytes_buffer), 0}; | |
| 137 | |
| 138 struct mojo_test_ArrayOfArrays* arr = | |
| 139 static_cast<struct mojo_test_ArrayOfArrays*>( | |
| 140 MojomBuffer_Allocate(&buf, sizeof(struct mojo_test_ArrayOfArrays))); | |
| 141 *arr = mojo_test_ArrayOfArrays{ | |
| 142 // header | |
| 143 { | |
| 144 sizeof(struct mojo_test_ArrayOfArrays), 0, | |
| 145 }, | |
| 146 {NULL}, | |
| 147 {NULL}, | |
| 148 }; | |
| 149 | |
| 150 auto* a_array = MojomArray_New(&buf, 2, sizeof(union MojomArrayHeaderPtr)); | |
| 151 arr->a.ptr = a_array; | |
| 152 MOJOM_ARRAY_INDEX(arr->a.ptr, union MojomArrayHeaderPtr, 0)->ptr = NULL; | |
| 153 MOJOM_ARRAY_INDEX(arr->a.ptr, union MojomArrayHeaderPtr, 1)->ptr = NULL; | |
| 154 | |
| 155 EXPECT_EQ(24u + (8u + 2 * 8u) // a (with 2 null arrays) | |
| 156 + 0u, // b (null altogether) | |
| 157 mojo_test_ArrayOfArrays_ComputeSerializedSize(arr)); | |
| 158 | |
| 159 // fill in |a| with array<int32> of size 2. | |
| 160 struct MojomArrayHeader* array_int32 = | |
| 161 MojomArray_New(&buf, 2, sizeof(int32_t)); | |
| 162 MOJOM_ARRAY_INDEX(arr->a.ptr, union MojomArrayHeaderPtr, 0) | |
| 163 ->ptr = array_int32; | |
| 164 *MOJOM_ARRAY_INDEX(array_int32, int32_t, 0) = 13; | |
| 165 *MOJOM_ARRAY_INDEX(array_int32, int32_t, 1) = 13; | |
| 166 | |
| 167 EXPECT_EQ(24u + (8u + 2 * 8u) // a (with 2 arrays, 1 of them NULL) | |
| 168 + 0u // b (null altogether) | |
| 169 + (8u + 8u), // first array<int> in a | |
| 170 mojo_test_ArrayOfArrays_ComputeSerializedSize(arr)); | |
| 171 | |
| 172 // Save the underlying buffer before encoding, so we can decode+compare | |
| 173 // later. | |
| 174 char bytes_buffer_copy[sizeof(bytes_buffer)]; | |
| 175 memcpy(bytes_buffer_copy, bytes_buffer, sizeof(bytes_buffer)); | |
| 176 | |
| 177 mojo_test_ArrayOfArrays_EncodePointersAndHandles(arr, buf.num_bytes_used, | |
| 178 NULL); | |
| 179 | |
| 180 EXPECT_EQ(sizeof(struct mojo_test_ArrayOfArrays) - | |
| 181 offsetof(struct mojo_test_ArrayOfArrays, a), | |
| 182 arr->a.offset); | |
| 183 | |
| 184 // Array of int32 should occur at the end of the array of 2 arrays -- so the | |
| 185 // offset is 2 pointer-sizes (1st one pointers to the array of int32, second | |
| 186 // one is NULL). | |
| 187 EXPECT_EQ(2 * sizeof(union MojomArrayHeaderPtr), | |
| 188 MOJOM_ARRAY_INDEX(a_array, union MojomArrayHeaderPtr, 0)->offset); | |
| 189 EXPECT_EQ(0u, | |
| 190 MOJOM_ARRAY_INDEX(a_array, union MojomArrayHeaderPtr, 1)->offset); | |
| 191 | |
| 192 mojo_test_ArrayOfArrays_DecodePointersAndHandles(arr, buf.num_bytes_used, | |
| 193 NULL, 0); | |
| 194 EXPECT_EQ(0, memcmp(buf.buf, bytes_buffer_copy, buf.num_bytes_used)); | |
| 195 | |
| 196 { | |
| 197 char bytes_buffer2[sizeof(bytes_buffer)] = {0}; | |
| 198 struct MojomBuffer buf2 = {bytes_buffer2, sizeof(bytes_buffer2), 0}; | |
| 199 CopyAndCompare(&buf2, arr, buf.num_bytes_used, | |
| 200 mojo_test_ArrayOfArrays_DeepCopy, | |
| 201 mojo_test_ArrayOfArrays_EncodePointersAndHandles, | |
| 202 mojo_test_ArrayOfArrays_DecodePointersAndHandles); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 // Tests serialization of an array of handles. | |
| 207 TEST(ArraySerializationTest, ArrayOfHandles) { | |
| 208 char buffer_bytes[1000] = {0}; | |
| 209 MojomBuffer buf = {buffer_bytes, sizeof(buffer_bytes), 0}; | |
| 210 | |
| 211 struct mojo_test_StructWithNullableHandles* handle_struct = | |
| 212 static_cast<struct mojo_test_StructWithNullableHandles*>( | |
| 213 MojomBuffer_Allocate( | |
| 214 &buf, sizeof(struct mojo_test_StructWithNullableHandles))); | |
| 215 *handle_struct = mojo_test_StructWithNullableHandles{ | |
| 216 // header | |
| 217 {sizeof(struct mojo_test_StructWithNullableHandles), 0}, | |
| 218 // These fields will be initialized below. | |
| 219 MOJO_HANDLE_INVALID, | |
| 220 {0}, | |
| 221 {NULL}, | |
| 222 }; | |
| 223 | |
| 224 handle_struct->h = 10; | |
| 225 auto* array_h = MojomArray_New(&buf, 3, sizeof(MojoHandle)); | |
| 226 handle_struct->array_h.ptr = array_h; | |
| 227 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 0) = 20; | |
| 228 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 1) = | |
| 229 MOJO_HANDLE_INVALID; | |
| 230 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 2) = 30; | |
| 231 | |
| 232 EXPECT_EQ( | |
| 233 8u + 4u + 4u + 8u + 4u + (8u + 3 * 4u), | |
| 234 mojo_test_StructWithNullableHandles_ComputeSerializedSize(handle_struct)); | |
| 235 | |
| 236 // Save the underlying buffer before encoding, so we can decode+compare | |
| 237 // later. | |
| 238 char buffer_bytes_copy[sizeof(buffer_bytes)]; | |
| 239 memcpy(buffer_bytes_copy, buffer_bytes, sizeof(buffer_bytes)); | |
| 240 | |
| 241 MojoHandle handles[5] = {}; | |
| 242 struct MojomHandleBuffer handle_buf = {handles, MOJO_ARRAYSIZE(handles), 0u}; | |
| 243 mojo_test_StructWithNullableHandles_EncodePointersAndHandles( | |
| 244 handle_struct, buf.num_bytes_used, &handle_buf); | |
| 245 EXPECT_EQ(3u, handle_buf.num_handles_used); | |
| 246 EXPECT_EQ(static_cast<MojoHandle>(10u), handles[0]); | |
| 247 EXPECT_EQ(static_cast<MojoHandle>(20u), handles[1]); | |
| 248 EXPECT_EQ(static_cast<MojoHandle>(30u), handles[2]); | |
| 249 | |
| 250 EXPECT_EQ(0u, handle_struct->h); | |
| 251 EXPECT_EQ(1u, *MOJOM_ARRAY_INDEX(array_h, MojoHandle, 0)); | |
| 252 EXPECT_EQ(static_cast<MojoHandle>(-1), | |
| 253 *MOJOM_ARRAY_INDEX(array_h, MojoHandle, 1)); | |
| 254 EXPECT_EQ(2u, *MOJOM_ARRAY_INDEX(array_h, MojoHandle, 2)); | |
| 255 | |
| 256 EXPECT_EQ(sizeof(struct mojo_test_StructWithNullableHandles) - | |
| 257 offsetof(struct mojo_test_StructWithNullableHandles, array_h), | |
| 258 handle_struct->array_h.offset); | |
| 259 | |
| 260 mojo_test_StructWithNullableHandles_DecodePointersAndHandles( | |
| 261 handle_struct, buf.num_bytes_used, handles, MOJO_ARRAYSIZE(handles)); | |
| 262 EXPECT_EQ(0, memcmp(buf.buf, buffer_bytes_copy, buf.num_bytes_used)); | |
| 263 | |
| 264 // Check that the handles in the handles array are invalidated: | |
| 265 EXPECT_EQ(MOJO_HANDLE_INVALID, handles[0]); | |
| 266 EXPECT_EQ(MOJO_HANDLE_INVALID, handles[1]); | |
| 267 EXPECT_EQ(MOJO_HANDLE_INVALID, handles[2]); | |
| 268 | |
| 269 { | |
| 270 char buffer_bytes2[sizeof(buffer_bytes)] = {0}; | |
| 271 struct MojomBuffer buf2 = {buffer_bytes2, sizeof(buffer_bytes2), 0}; | |
| 272 auto* copied_struct = | |
| 273 mojo_test_StructWithNullableHandles_DeepCopy(&buf2, handle_struct); | |
| 274 | |
| 275 // The copy should still have the handles. | |
| 276 EXPECT_EQ(static_cast<MojoHandle>(10u), handle_struct->h); | |
| 277 EXPECT_EQ(static_cast<MojoHandle>(20u), | |
| 278 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 0)); | |
| 279 EXPECT_EQ(MOJO_HANDLE_INVALID, | |
| 280 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 1)); | |
| 281 EXPECT_EQ(static_cast<MojoHandle>(30u), | |
| 282 *MOJOM_ARRAY_INDEX(handle_struct->array_h.ptr, MojoHandle, 2)); | |
| 283 // The new struct should have the handles now: | |
| 284 EXPECT_EQ(static_cast<MojoHandle>(10u), copied_struct->h); | |
| 285 EXPECT_EQ(static_cast<MojoHandle>(20u), | |
| 286 *MOJOM_ARRAY_INDEX(copied_struct->array_h.ptr, MojoHandle, 0)); | |
| 287 EXPECT_EQ(MOJO_HANDLE_INVALID, | |
| 288 *MOJOM_ARRAY_INDEX(copied_struct->array_h.ptr, MojoHandle, 1)); | |
| 289 EXPECT_EQ(static_cast<MojoHandle>(30u), | |
| 290 *MOJOM_ARRAY_INDEX(copied_struct->array_h.ptr, MojoHandle, 2)); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 } // namespace | |
| OLD | NEW |