blob: 0fed255bf8d395b2f676bfe359820afb0e4dbc07 [file] [log] [blame]
// 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