| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/public/cpp/bindings/allocation_scope.h" | |
| 6 #include "mojo/public/cpp/bindings/array.h" | 5 #include "mojo/public/cpp/bindings/array.h" |
| 6 #include "mojo/public/cpp/bindings/lib/array_serialization.h" |
| 7 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" | 7 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" |
| 8 #include "mojo/public/cpp/bindings/lib/scratch_buffer.h" | |
| 9 #include "mojo/public/cpp/environment/environment.h" | 8 #include "mojo/public/cpp/environment/environment.h" |
| 10 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" | 9 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 11 |
| 13 namespace mojo { | 12 namespace mojo { |
| 14 namespace test { | 13 namespace test { |
| 15 namespace { | 14 namespace { |
| 16 | 15 |
| 17 // Tests that basic Array operations work. | 16 // Tests that basic Array operations work. |
| 18 TEST(ArrayTest, Basic) { | 17 TEST(ArrayTest, Basic) { |
| 19 Environment env; | 18 Array<char> array(8); |
| 20 | 19 for (size_t i = 0; i < array.size(); ++i) { |
| 21 // 8 bytes for the array, with 8 bytes left over for elements. | |
| 22 internal::FixedBuffer buf(8 + 8*sizeof(char)); | |
| 23 EXPECT_EQ(16u, buf.size()); | |
| 24 | |
| 25 Array<char>::Builder builder(8); | |
| 26 EXPECT_EQ(8u, builder.size()); | |
| 27 for (size_t i = 0; i < builder.size(); ++i) { | |
| 28 char val = static_cast<char>(i*2); | 20 char val = static_cast<char>(i*2); |
| 29 builder[i] = val; | 21 array[i] = val; |
| 30 EXPECT_EQ(val, builder.at(i)); | 22 EXPECT_EQ(val, array.at(i)); |
| 31 } | |
| 32 Array<char> array = builder.Finish(); | |
| 33 for (size_t i = 0; i < array.size(); ++i) { | |
| 34 char val = static_cast<char>(i) * 2; | |
| 35 EXPECT_EQ(val, array[i]); | |
| 36 } | 23 } |
| 37 } | 24 } |
| 38 | 25 |
| 39 // Tests that basic Array<bool> operations work, and that it's packed into 1 | 26 // Tests that basic Array<bool> operations work. |
| 40 // bit per element. | |
| 41 TEST(ArrayTest, Bool) { | 27 TEST(ArrayTest, Bool) { |
| 42 Environment env; | 28 Array<bool> array(64); |
| 43 | |
| 44 // 8 bytes for the array header, with 8 bytes left over for elements. | |
| 45 internal::FixedBuffer buf(8 + 3); | |
| 46 EXPECT_EQ(16u, buf.size()); | |
| 47 | |
| 48 // An array of 64 bools can fit into 8 bytes. | |
| 49 Array<bool>::Builder builder(64); | |
| 50 EXPECT_EQ(64u, builder.size()); | |
| 51 for (size_t i = 0; i < builder.size(); ++i) { | |
| 52 bool val = i % 3 == 0; | |
| 53 builder[i] = val; | |
| 54 EXPECT_EQ(val, builder.at(i)); | |
| 55 } | |
| 56 Array<bool> array = builder.Finish(); | |
| 57 for (size_t i = 0; i < array.size(); ++i) { | 29 for (size_t i = 0; i < array.size(); ++i) { |
| 58 bool val = i % 3 == 0; | 30 bool val = i % 3 == 0; |
| 59 EXPECT_EQ(val, array[i]); | 31 array[i] = val; |
| 32 EXPECT_EQ(val, array.at(i)); |
| 60 } | 33 } |
| 61 } | 34 } |
| 62 | 35 |
| 63 // Tests that Array<Handle> supports transferring handles. | 36 // Tests that Array<ScopedMessagePipeHandle> supports transferring handles. |
| 64 TEST(ArrayTest, Handle) { | 37 TEST(ArrayTest, Handle) { |
| 65 Environment env; | |
| 66 | |
| 67 AllocationScope scope; | |
| 68 | |
| 69 ScopedMessagePipeHandle pipe0, pipe1; | 38 ScopedMessagePipeHandle pipe0, pipe1; |
| 70 CreateMessagePipe(&pipe0, &pipe1); | 39 CreateMessagePipe(&pipe0, &pipe1); |
| 71 | 40 |
| 72 Array<MessagePipeHandle>::Builder handles_builder(2); | 41 Array<ScopedMessagePipeHandle> handles(2); |
| 73 handles_builder[0] = pipe0.Pass(); | 42 handles[0] = pipe0.Pass(); |
| 74 handles_builder[1].reset(pipe1.release()); | 43 handles[1].reset(pipe1.release()); |
| 75 | 44 |
| 76 EXPECT_FALSE(pipe0.is_valid()); | 45 EXPECT_FALSE(pipe0.is_valid()); |
| 77 EXPECT_FALSE(pipe1.is_valid()); | 46 EXPECT_FALSE(pipe1.is_valid()); |
| 78 | 47 |
| 79 Array<MessagePipeHandle> handles = handles_builder.Finish(); | 48 Array<ScopedMessagePipeHandle> handles2 = handles.Pass(); |
| 80 EXPECT_TRUE(handles[0].is_valid()); | 49 EXPECT_TRUE(handles2[0].is_valid()); |
| 81 EXPECT_TRUE(handles[1].is_valid()); | 50 EXPECT_TRUE(handles2[1].is_valid()); |
| 82 | 51 |
| 83 pipe0 = handles[0].Pass(); | 52 pipe0 = handles2[0].Pass(); |
| 84 EXPECT_TRUE(pipe0.is_valid()); | 53 EXPECT_TRUE(pipe0.is_valid()); |
| 85 EXPECT_FALSE(handles[0].is_valid()); | 54 EXPECT_FALSE(handles2[0].is_valid()); |
| 86 } | 55 } |
| 87 | 56 |
| 88 // Tests that Array<Handle> supports closing handles. | 57 // Tests that Array<ScopedMessagePipeHandle> supports closing handles. |
| 89 TEST(ArrayTest, HandlesAreClosed) { | 58 TEST(ArrayTest, HandlesAreClosed) { |
| 90 Environment env; | 59 ScopedMessagePipeHandle pipe0, pipe1; |
| 91 | 60 CreateMessagePipe(&pipe0, &pipe1); |
| 92 ScopedMessagePipeHandle msg_pipe0, msg_pipe1; | |
| 93 CreateMessagePipe(&msg_pipe0, &msg_pipe1); | |
| 94 | |
| 95 ScopedHandle pipe0 = ScopedHandle::From(msg_pipe0.Pass()); | |
| 96 ScopedHandle pipe1 = ScopedHandle::From(msg_pipe1.Pass()); | |
| 97 | 61 |
| 98 MojoHandle pipe0_value = pipe0.get().value(); | 62 MojoHandle pipe0_value = pipe0.get().value(); |
| 99 MojoHandle pipe1_value = pipe1.get().value(); | 63 MojoHandle pipe1_value = pipe1.get().value(); |
| 100 | 64 |
| 101 { | 65 { |
| 102 AllocationScope scope; | 66 Array<ScopedMessagePipeHandle> handles(2); |
| 103 | 67 handles[0] = pipe0.Pass(); |
| 104 Array<Handle>::Builder handles_builder(2); | 68 handles[1].reset(pipe1.release()); |
| 105 handles_builder[0] = pipe0.Pass(); | |
| 106 handles_builder[1].reset(pipe1.release()); | |
| 107 | |
| 108 MOJO_ALLOW_UNUSED Array<Handle> handles = | |
| 109 handles_builder.Finish(); | |
| 110 } | 69 } |
| 111 | 70 |
| 112 // We expect the pipes to have been closed. | 71 // We expect the pipes to have been closed. |
| 113 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); | 72 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); |
| 114 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); | 73 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); |
| 115 } | 74 } |
| 116 | 75 |
| 117 // Tests that Array<MessagePipeHandle> supports closing handles. | 76 TEST(ArrayTest, Serialization_ArrayOfPOD) { |
| 118 TEST(ArrayTest, MessagePipeHandlesAreClosed) { | 77 Array<int32_t> array(4); |
| 119 Environment env; | 78 for (size_t i = 0; i < array.size(); ++i) |
| 79 array[i] = static_cast<int32_t>(i); |
| 120 | 80 |
| 121 ScopedMessagePipeHandle pipe0, pipe1; | 81 size_t size = GetSerializedSize_(array); |
| 122 CreateMessagePipe(&pipe0, &pipe1); | 82 EXPECT_EQ(8U + 4*4U, size); |
| 123 | 83 |
| 124 MojoHandle pipe0_value = pipe0.get().value(); | 84 internal::FixedBuffer buf(size); |
| 125 MojoHandle pipe1_value = pipe1.get().value(); | 85 internal::Array_Data<int32_t>* data; |
| 86 Serialize_(array.Pass(), &buf, &data); |
| 126 | 87 |
| 127 { | 88 Array<int32_t> array2; |
| 128 AllocationScope scope; | 89 Deserialize_(data, &array2); |
| 129 | 90 |
| 130 Array<MessagePipeHandle>::Builder handles_builder(2); | 91 EXPECT_EQ(4U, array2.size()); |
| 131 handles_builder[0] = pipe0.Pass(); | 92 for (size_t i = 0; i < array2.size(); ++i) |
| 132 handles_builder[1].reset(pipe1.release()); | 93 EXPECT_EQ(static_cast<int32_t>(i), array2[i]); |
| 94 } |
| 133 | 95 |
| 134 MOJO_ALLOW_UNUSED Array<MessagePipeHandle> handles = | 96 TEST(ArrayTest, Serialization_ArrayOfArrayOfPOD) { |
| 135 handles_builder.Finish(); | 97 Array<Array<int32_t> > array(2); |
| 98 for (size_t j = 0; j < array.size(); ++j) { |
| 99 Array<int32_t> inner(4); |
| 100 for (size_t i = 0; i < inner.size(); ++i) |
| 101 inner[i] = static_cast<int32_t>(i + (j * 10)); |
| 102 array[j] = inner.Pass(); |
| 136 } | 103 } |
| 137 | 104 |
| 138 // We expect the pipes to have been closed. | 105 size_t size = GetSerializedSize_(array); |
| 139 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); | 106 EXPECT_EQ(8U + 2*8U + 2*(8U + 4*4U), size); |
| 140 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); | 107 |
| 108 internal::FixedBuffer buf(size); |
| 109 internal::Array_Data<internal::Array_Data<int32_t>*>* data; |
| 110 Serialize_(array.Pass(), &buf, &data); |
| 111 |
| 112 Array<Array<int32_t> > array2; |
| 113 Deserialize_(data, &array2); |
| 114 |
| 115 EXPECT_EQ(2U, array2.size()); |
| 116 for (size_t j = 0; j < array2.size(); ++j) { |
| 117 const Array<int32_t>& inner = array2[j]; |
| 118 EXPECT_EQ(4U, inner.size()); |
| 119 for (size_t i = 0; i < inner.size(); ++i) |
| 120 EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]); |
| 121 } |
| 122 } |
| 123 |
| 124 TEST(ArrayTest, Serialization_ArrayOfBool) { |
| 125 Array<bool> array(10); |
| 126 for (size_t i = 0; i < array.size(); ++i) |
| 127 array[i] = i % 2 ? true : false; |
| 128 |
| 129 size_t size = GetSerializedSize_(array); |
| 130 EXPECT_EQ(8U + 8U, size); |
| 131 |
| 132 internal::FixedBuffer buf(size); |
| 133 internal::Array_Data<bool>* data; |
| 134 Serialize_(array.Pass(), &buf, &data); |
| 135 |
| 136 Array<bool> array2; |
| 137 Deserialize_(data, &array2); |
| 138 |
| 139 EXPECT_EQ(10U, array2.size()); |
| 140 for (size_t i = 0; i < array2.size(); ++i) |
| 141 EXPECT_EQ(i % 2 ? true : false, array2[i]); |
| 142 } |
| 143 |
| 144 TEST(ArrayTest, Serialization_ArrayOfString) { |
| 145 Array<String> array(10); |
| 146 for (size_t i = 0; i < array.size(); ++i) { |
| 147 char c = 'A' + 1; |
| 148 array[i] = String(&c, 1); |
| 149 } |
| 150 |
| 151 size_t size = GetSerializedSize_(array); |
| 152 EXPECT_EQ(8U + // array header |
| 153 10*8U + // array payload (10 pointers) |
| 154 10*(8U + // string header |
| 155 8U), // string length of 1 padded to 8 |
| 156 size); |
| 157 |
| 158 internal::FixedBuffer buf(size); |
| 159 internal::Array_Data<internal::String_Data*>* data; |
| 160 Serialize_(array.Pass(), &buf, &data); |
| 161 |
| 162 Array<String> array2; |
| 163 Deserialize_(data, &array2); |
| 164 |
| 165 EXPECT_EQ(10U, array2.size()); |
| 166 for (size_t i = 0; i < array2.size(); ++i) { |
| 167 char c = 'A' + 1; |
| 168 EXPECT_EQ(String(&c, 1), array2[i]); |
| 169 } |
| 141 } | 170 } |
| 142 | 171 |
| 143 } // namespace | 172 } // namespace |
| 144 } // namespace test | 173 } // namespace test |
| 145 } // namespace mojo | 174 } // namespace mojo |
| OLD | NEW |