| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <algorithm> | |
| 6 #include <ostream> | |
| 7 #include <string> | |
| 8 | |
| 9 #include "mojo/public/bindings/tests/sample_service.mojom.h" | |
| 10 #include "mojo/public/cpp/bindings/allocation_scope.h" | |
| 11 #include "mojo/public/cpp/environment/environment.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 namespace mojo { | |
| 15 | |
| 16 template <> | |
| 17 class TypeConverter<sample::Bar, int32_t> { | |
| 18 public: | |
| 19 static int32_t ConvertTo(const sample::Bar& bar) { | |
| 20 return static_cast<int32_t>(bar.alpha()) << 16 | | |
| 21 static_cast<int32_t>(bar.beta()) << 8 | | |
| 22 static_cast<int32_t>(bar.gamma()); | |
| 23 } | |
| 24 }; | |
| 25 | |
| 26 } // namespace mojo | |
| 27 | |
| 28 namespace sample { | |
| 29 namespace { | |
| 30 | |
| 31 // Set this variable to true to print the message in hex. | |
| 32 bool g_dump_message_as_hex = false; | |
| 33 | |
| 34 // Set this variable to true to print the message in human readable form. | |
| 35 bool g_dump_message_as_text = false; | |
| 36 | |
| 37 // Make a sample |Foo|. | |
| 38 Foo MakeFoo() { | |
| 39 mojo::String name("foopy"); | |
| 40 | |
| 41 Bar::Builder bar; | |
| 42 bar.set_alpha(20); | |
| 43 bar.set_beta(40); | |
| 44 bar.set_gamma(60); | |
| 45 bar.set_type(Bar::TYPE_VERTICAL); | |
| 46 | |
| 47 mojo::Array<Bar>::Builder extra_bars(3); | |
| 48 for (size_t i = 0; i < extra_bars.size(); ++i) { | |
| 49 Bar::Type type = i % 2 == 0 ? Bar::TYPE_VERTICAL : Bar::TYPE_HORIZONTAL; | |
| 50 Bar::Builder bar; | |
| 51 uint8_t base = static_cast<uint8_t>(i * 100); | |
| 52 bar.set_alpha(base); | |
| 53 bar.set_beta(base + 20); | |
| 54 bar.set_gamma(base + 40); | |
| 55 bar.set_type(type); | |
| 56 extra_bars[i] = bar.Finish(); | |
| 57 } | |
| 58 | |
| 59 mojo::Array<uint8_t>::Builder data(10); | |
| 60 for (size_t i = 0; i < data.size(); ++i) | |
| 61 data[i] = static_cast<uint8_t>(data.size() - i); | |
| 62 | |
| 63 mojo::Array<mojo::DataPipeConsumerHandle>::Builder input_streams(2); | |
| 64 mojo::Array<mojo::DataPipeProducerHandle>::Builder output_streams(2); | |
| 65 for (size_t i = 0; i < input_streams.size(); ++i) { | |
| 66 MojoCreateDataPipeOptions options; | |
| 67 options.struct_size = sizeof(MojoCreateDataPipeOptions); | |
| 68 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
| 69 options.element_num_bytes = 1; | |
| 70 options.capacity_num_bytes = 1024; | |
| 71 mojo::ScopedDataPipeProducerHandle producer; | |
| 72 mojo::ScopedDataPipeConsumerHandle consumer; | |
| 73 mojo::CreateDataPipe(&options, &producer, &consumer); | |
| 74 input_streams[i] = consumer.Pass(); | |
| 75 output_streams[i] = producer.Pass(); | |
| 76 } | |
| 77 | |
| 78 mojo::ScopedMessagePipeHandle pipe0, pipe1; | |
| 79 mojo::CreateMessagePipe(&pipe0, &pipe1); | |
| 80 | |
| 81 Foo::Builder foo; | |
| 82 foo.set_name(name); | |
| 83 foo.set_x(1); | |
| 84 foo.set_y(2); | |
| 85 foo.set_a(false); | |
| 86 foo.set_b(true); | |
| 87 foo.set_c(false); | |
| 88 foo.set_bar(bar.Finish()); | |
| 89 foo.set_extra_bars(extra_bars.Finish()); | |
| 90 foo.set_data(data.Finish()); | |
| 91 foo.set_source(pipe1.Pass()); | |
| 92 foo.set_input_streams(input_streams.Finish()); | |
| 93 foo.set_output_streams(output_streams.Finish()); | |
| 94 | |
| 95 return foo.Finish(); | |
| 96 } | |
| 97 | |
| 98 // Check that the given |Foo| is identical to the one made by |MakeFoo()|. | |
| 99 void CheckFoo(const Foo& foo) { | |
| 100 const std::string kName("foopy"); | |
| 101 ASSERT_FALSE(foo.name().is_null()); | |
| 102 EXPECT_EQ(kName.size(), foo.name().size()); | |
| 103 for (size_t i = 0; i < std::min(kName.size(), foo.name().size()); i++) { | |
| 104 // Test both |operator[]| and |at|. | |
| 105 EXPECT_EQ(kName[i], foo.name().at(i)) << i; | |
| 106 EXPECT_EQ(kName[i], foo.name()[i]) << i; | |
| 107 } | |
| 108 EXPECT_EQ(kName, foo.name().To<std::string>()); | |
| 109 | |
| 110 EXPECT_EQ(1, foo.x()); | |
| 111 EXPECT_EQ(2, foo.y()); | |
| 112 EXPECT_FALSE(foo.a()); | |
| 113 EXPECT_TRUE(foo.b()); | |
| 114 EXPECT_FALSE(foo.c()); | |
| 115 | |
| 116 EXPECT_EQ(20, foo.bar().alpha()); | |
| 117 EXPECT_EQ(40, foo.bar().beta()); | |
| 118 EXPECT_EQ(60, foo.bar().gamma()); | |
| 119 EXPECT_EQ(Bar::TYPE_VERTICAL, foo.bar().type()); | |
| 120 | |
| 121 EXPECT_EQ(3u, foo.extra_bars().size()); | |
| 122 for (size_t i = 0; i < foo.extra_bars().size(); i++) { | |
| 123 uint8_t base = static_cast<uint8_t>(i * 100); | |
| 124 Bar::Type type = i % 2 == 0 ? Bar::TYPE_VERTICAL : Bar::TYPE_HORIZONTAL; | |
| 125 EXPECT_EQ(base, foo.extra_bars()[i].alpha()) << i; | |
| 126 EXPECT_EQ(base + 20, foo.extra_bars()[i].beta()) << i; | |
| 127 EXPECT_EQ(base + 40, foo.extra_bars()[i].gamma()) << i; | |
| 128 EXPECT_EQ(type, foo.extra_bars()[i].type()) << i; | |
| 129 } | |
| 130 | |
| 131 EXPECT_EQ(10u, foo.data().size()); | |
| 132 for (size_t i = 0; i < foo.data().size(); ++i) { | |
| 133 EXPECT_EQ(static_cast<uint8_t>(foo.data().size() - i), foo.data()[i]) << i; | |
| 134 } | |
| 135 | |
| 136 EXPECT_FALSE(foo.input_streams().is_null()); | |
| 137 EXPECT_EQ(2u, foo.input_streams().size()); | |
| 138 | |
| 139 EXPECT_FALSE(foo.output_streams().is_null()); | |
| 140 EXPECT_EQ(2u, foo.output_streams().size()); | |
| 141 } | |
| 142 | |
| 143 void PrintSpacer(int depth) { | |
| 144 for (int i = 0; i < depth; ++i) | |
| 145 std::cout << " "; | |
| 146 } | |
| 147 | |
| 148 void Print(int depth, const char* name, bool value) { | |
| 149 PrintSpacer(depth); | |
| 150 std::cout << name << ": " << (value ? "true" : "false") << std::endl; | |
| 151 } | |
| 152 | |
| 153 void Print(int depth, const char* name, int32_t value) { | |
| 154 PrintSpacer(depth); | |
| 155 std::cout << name << ": " << value << std::endl; | |
| 156 } | |
| 157 | |
| 158 void Print(int depth, const char* name, uint8_t value) { | |
| 159 PrintSpacer(depth); | |
| 160 std::cout << name << ": " << uint32_t(value) << std::endl; | |
| 161 } | |
| 162 | |
| 163 void Print(int depth, const char* name, mojo::Handle value) { | |
| 164 PrintSpacer(depth); | |
| 165 std::cout << name << ": 0x" << std::hex << value.value() << std::endl; | |
| 166 } | |
| 167 | |
| 168 void Print(int depth, const char* name, const mojo::String& str) { | |
| 169 std::string s = str.To<std::string>(); | |
| 170 PrintSpacer(depth); | |
| 171 std::cout << name << ": \"" << str.To<std::string>() << "\"" << std::endl; | |
| 172 } | |
| 173 | |
| 174 void Print(int depth, const char* name, const Bar& bar) { | |
| 175 PrintSpacer(depth); | |
| 176 std::cout << name << ":" << std::endl; | |
| 177 if (!bar.is_null()) { | |
| 178 ++depth; | |
| 179 Print(depth, "alpha", bar.alpha()); | |
| 180 Print(depth, "beta", bar.beta()); | |
| 181 Print(depth, "gamma", bar.gamma()); | |
| 182 Print(depth, "packed", bar.To<int32_t>()); | |
| 183 --depth; | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 template <typename T> | |
| 188 void Print(int depth, const char* name, | |
| 189 const mojo::Passable<T>& passable) { | |
| 190 Print(depth, name, passable.get()); | |
| 191 } | |
| 192 | |
| 193 template <typename T> | |
| 194 void Print(int depth, const char* name, const mojo::Array<T>& array) { | |
| 195 PrintSpacer(depth); | |
| 196 std::cout << name << ":" << std::endl; | |
| 197 if (!array.is_null()) { | |
| 198 ++depth; | |
| 199 for (size_t i = 0; i < array.size(); ++i) { | |
| 200 std::stringstream buf; | |
| 201 buf << i; | |
| 202 Print(depth, buf.str().data(), array.at(i)); | |
| 203 } | |
| 204 --depth; | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 void Print(int depth, const char* name, const Foo& foo) { | |
| 209 PrintSpacer(depth); | |
| 210 std::cout << name << ":" << std::endl; | |
| 211 if (!foo.is_null()) { | |
| 212 ++depth; | |
| 213 Print(depth, "name", foo.name()); | |
| 214 Print(depth, "x", foo.x()); | |
| 215 Print(depth, "y", foo.y()); | |
| 216 Print(depth, "a", foo.a()); | |
| 217 Print(depth, "b", foo.b()); | |
| 218 Print(depth, "c", foo.c()); | |
| 219 Print(depth, "bar", foo.bar()); | |
| 220 Print(depth, "extra_bars", foo.extra_bars()); | |
| 221 Print(depth, "data", foo.data()); | |
| 222 Print(depth, "source", foo.source().get()); | |
| 223 Print(depth, "input_streams", foo.input_streams()); | |
| 224 Print(depth, "output_streams", foo.output_streams()); | |
| 225 --depth; | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 void DumpHex(const uint8_t* bytes, uint32_t num_bytes) { | |
| 230 for (uint32_t i = 0; i < num_bytes; ++i) { | |
| 231 std::cout << std::setw(2) << std::setfill('0') << std::hex << | |
| 232 uint32_t(bytes[i]); | |
| 233 | |
| 234 if (i % 16 == 15) { | |
| 235 std::cout << std::endl; | |
| 236 continue; | |
| 237 } | |
| 238 | |
| 239 if (i % 2 == 1) | |
| 240 std::cout << " "; | |
| 241 if (i % 8 == 7) | |
| 242 std::cout << " "; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 class ServiceImpl : public Service { | |
| 247 public: | |
| 248 virtual void Frobinate(const Foo& foo, BazOptions baz, ScopedPortHandle port) | |
| 249 MOJO_OVERRIDE { | |
| 250 // Users code goes here to handle the incoming Frobinate message. | |
| 251 | |
| 252 // We mainly check that we're given the expected arguments. | |
| 253 CheckFoo(foo); | |
| 254 EXPECT_EQ(BAZ_EXTRA, baz); | |
| 255 | |
| 256 if (g_dump_message_as_text) { | |
| 257 // Also dump the Foo structure and all of its members. | |
| 258 std::cout << "Frobinate:" << std::endl; | |
| 259 int depth = 1; | |
| 260 Print(depth, "foo", foo); | |
| 261 Print(depth, "baz", baz); | |
| 262 Print(depth, "port", port.get()); | |
| 263 } | |
| 264 } | |
| 265 }; | |
| 266 | |
| 267 class SimpleMessageReceiver : public mojo::MessageReceiver { | |
| 268 public: | |
| 269 virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE { | |
| 270 // Imagine some IPC happened here. | |
| 271 | |
| 272 if (g_dump_message_as_hex) { | |
| 273 DumpHex(reinterpret_cast<const uint8_t*>(message->data()), | |
| 274 message->data_num_bytes()); | |
| 275 } | |
| 276 | |
| 277 // In the receiving process, an implementation of ServiceStub is known to | |
| 278 // the system. It receives the incoming message. | |
| 279 ServiceImpl impl; | |
| 280 | |
| 281 ServiceStub stub(&impl); | |
| 282 return stub.Accept(message); | |
| 283 } | |
| 284 | |
| 285 virtual bool AcceptWithResponder(mojo::Message* message, | |
| 286 mojo::MessageReceiver* responder) | |
| 287 MOJO_OVERRIDE { | |
| 288 return false; | |
| 289 } | |
| 290 }; | |
| 291 | |
| 292 TEST(BindingsSampleTest, Basic) { | |
| 293 mojo::Environment env; | |
| 294 SimpleMessageReceiver receiver; | |
| 295 | |
| 296 // User has a proxy to a Service somehow. | |
| 297 Service* service = new ServiceProxy(&receiver); | |
| 298 | |
| 299 // User constructs a message to send. | |
| 300 | |
| 301 // Notice that it doesn't matter in what order the structs / arrays are | |
| 302 // allocated. Here, the various members of Foo are allocated before Foo is | |
| 303 // allocated. | |
| 304 | |
| 305 mojo::AllocationScope scope; | |
| 306 | |
| 307 Foo foo = MakeFoo(); | |
| 308 CheckFoo(foo); | |
| 309 | |
| 310 mojo::InterfacePipe<Port, mojo::AnyInterface> pipe; | |
| 311 service->Frobinate(foo, Service::BAZ_EXTRA, pipe.handle_to_self.Pass()); | |
| 312 } | |
| 313 | |
| 314 TEST(BindingsSampleTest, DefaultValues) { | |
| 315 mojo::Environment env; | |
| 316 SimpleMessageReceiver receiver; | |
| 317 mojo::AllocationScope scope; | |
| 318 | |
| 319 Bar bar = Bar::Builder().Finish(); | |
| 320 EXPECT_EQ(255, bar.alpha()); | |
| 321 | |
| 322 Foo foo = Foo::Builder().Finish(); | |
| 323 ASSERT_FALSE(foo.name().is_null()); | |
| 324 EXPECT_EQ("Fooby", foo.name().To<std::string>()); | |
| 325 EXPECT_TRUE(foo.a()); | |
| 326 EXPECT_EQ(3u, foo.data().size()); | |
| 327 EXPECT_EQ(1, foo.data()[0]); | |
| 328 EXPECT_EQ(2, foo.data()[1]); | |
| 329 EXPECT_EQ(3, foo.data()[2]); | |
| 330 | |
| 331 DefaultsTestInner inner = DefaultsTestInner::Builder().Finish(); | |
| 332 EXPECT_EQ(1u, inner.names().size()); | |
| 333 EXPECT_EQ("Jim", inner.names()[0].To<std::string>()); | |
| 334 EXPECT_EQ(6*12, inner.height()); | |
| 335 | |
| 336 DefaultsTest full = DefaultsTest::Builder().Finish(); | |
| 337 EXPECT_EQ(1u, full.people().size()); | |
| 338 EXPECT_EQ(32, full.people()[0].age()); | |
| 339 EXPECT_EQ(2u, full.people()[0].names().size()); | |
| 340 EXPECT_EQ("Bob", full.people()[0].names()[0].To<std::string>()); | |
| 341 EXPECT_EQ("Bobby", full.people()[0].names()[1].To<std::string>()); | |
| 342 EXPECT_EQ(6*12, full.people()[0].height()); | |
| 343 | |
| 344 EXPECT_EQ(7, full.point().x()); | |
| 345 EXPECT_EQ(15, full.point().y()); | |
| 346 | |
| 347 EXPECT_EQ(1u, full.shape_masks().size()); | |
| 348 EXPECT_EQ(1 << imported::SHAPE_RECTANGLE, full.shape_masks()[0]); | |
| 349 | |
| 350 EXPECT_EQ(imported::SHAPE_CIRCLE, full.thing().shape()); | |
| 351 EXPECT_EQ(imported::COLOR_BLACK, full.thing().color()); | |
| 352 } | |
| 353 | |
| 354 } // namespace | |
| 355 } // namespace sample | |
| OLD | NEW |