| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "fidl/test/frobinator/cpp/fidl.h" |
| |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <zircon/syscalls.h> |
| |
| #include <memory> |
| #include <string> |
| |
| #include <gtest/gtest.h> |
| |
| #include "lib/fidl/cpp/binding.h" |
| #include "src/developer/shell/josh/lib/js_testing_utils.h" |
| #include "src/developer/shell/josh/lib/runtime.h" |
| #include "src/developer/shell/josh/lib/zx.h" |
| #include "src/lib/fidl_codec/library_loader_test_data.h" |
| #include "testing/fidl/async_loop_for_test.h" |
| #include "testing/fidl/frobinator_impl.h" |
| |
| namespace shell { |
| |
| // TODO(jeremymanson): Dedup this with the version in async_loop_for_test.h |
| |
| class AsyncLoopForTestImpl { |
| public: |
| AsyncLoopForTestImpl() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {} |
| ~AsyncLoopForTestImpl() = default; |
| |
| async::Loop* loop() { return &loop_; } |
| |
| private: |
| async::Loop loop_; |
| }; |
| |
| class AsyncLoopForTest { |
| public: |
| // The AsyncLoopForTest constructor should also call |
| // async_set_default_dispatcher() with the chosen dispatcher implementation. |
| AsyncLoopForTest(); |
| ~AsyncLoopForTest(); |
| |
| // This call matches the behavior of async_loop_run_until_idle(). |
| zx_status_t RunUntilIdle(); |
| |
| // This call matches the behavior of async_loop_run(). |
| zx_status_t Run(); |
| |
| // Returns the underlying async_dispatcher_t. |
| async_dispatcher_t* dispatcher(); |
| |
| private: |
| std::unique_ptr<AsyncLoopForTestImpl> impl_; |
| }; |
| |
| AsyncLoopForTest::AsyncLoopForTest() : impl_(std::make_unique<AsyncLoopForTestImpl>()) {} |
| |
| AsyncLoopForTest::~AsyncLoopForTest() = default; |
| |
| zx_status_t AsyncLoopForTest::RunUntilIdle() { return impl_->loop()->RunUntilIdle(); } |
| |
| zx_status_t AsyncLoopForTest::Run() { return impl_->loop()->Run(); } |
| |
| async_dispatcher_t* AsyncLoopForTest::dispatcher() { return impl_->loop()->dispatcher(); } |
| |
| class FidlTest : public JsTest { |
| protected: |
| void SetUp() override { JsTest::SetUp(); } |
| }; |
| |
| // Sanity check test to make sure Hello World works. |
| TEST_F(FidlTest, SimpleFrobinator) { |
| InitBuiltins("", ""); |
| |
| // Load up some FIDL to call. |
| fidl_codec_test::FidlcodecExamples examples; |
| const std::string fidl_to_find = "frobinator.fidl.json"; |
| std::string frob_fidl; |
| for (const auto& element : examples.map()) { |
| if (0 == element.first.compare(element.first.length() - fidl_to_find.length(), |
| fidl_to_find.length(), fidl_to_find)) { |
| frob_fidl = element.second; |
| } |
| } |
| std::string load = "fidl.loadLibraryIr(`" + frob_fidl + "`);\n"; |
| |
| // Set up a channel to call over. |
| zx_handle_t out0, out1; |
| zx_status_t status = zx_channel_create(0, &out0, &out1); |
| ASSERT_EQ(ZX_OK, status) << "Unable to create zx_channel"; |
| JSContext* ctx = ctx_->Get(); |
| JSValue js_handle = zx::HandleCreate(ctx, out0, ZX_OBJ_TYPE_CHANNEL); |
| JS_DefinePropertyValueStr(ctx, JS_GetGlobalObject(ctx), "outHandle", js_handle, |
| JS_PROP_CONFIGURABLE); |
| |
| // Set up the server side of the channel. |
| AsyncLoopForTest loop; |
| fidl::test::FrobinatorImpl impl; |
| fidl::Binding<fidl::test::frobinator::Frobinator> binding(&impl, ::zx::channel(out1)); |
| |
| binding.set_error_handler( |
| [](zx_status_t status) { FAIL() << "Frob call failed with status " << status; }); |
| // Send a message from a JS client. |
| std::string test_string = load + R"( |
| if (globalThis.outHandle == undefined) { |
| throw "outHandle undefined"; |
| } |
| |
| fidl.loadLibrary("fidl.test.frobinator"); |
| client = new fidl.ProtocolClient( |
| new zx.Channel(globalThis.outHandle), fidling.fidl_test_frobinator.Frobinator); |
| client.Frob("one"); |
| )"; |
| ASSERT_TRUE(Eval(test_string)); |
| EXPECT_EQ(0u, impl.frobs.size()); |
| |
| loop.RunUntilIdle(); |
| |
| // This means that the message was received. |
| EXPECT_EQ(1u, impl.frobs.size()); |
| } |
| |
| // TODO(jeremymanson): Write a test that relies on a service. This requires us to componentize |
| // these tests. |
| |
| } // namespace shell |