blob: a33ccb8e64b91c35437069732d420f95aacff609 [file] [log] [blame]
// Copyright 2020 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 "src/connectivity/weave/weavestack/fidl/bootstrap_impl.h"
#include <fuchsia/weave/cpp/fidl_test_base.h>
#include <lib/sys/cpp/testing/component_context_provider.h>
#include <lib/syslog/cpp/macros.h>
#include <unordered_map>
#include <gtest/gtest.h>
#include <src/lib/files/file.h>
#include <src/lib/fsl/vmo/strings.h>
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
namespace weavestack {
namespace {
using fuchsia::weave::Bootstrap_ImportWeaveConfig_Result;
} // namespace
class TestableBootstrapImpl : public BootstrapImpl {
public:
TestableBootstrapImpl(sys::ComponentContext* context) : BootstrapImpl(context) {}
void SetShouldServe(bool value) { should_serve_ = value; }
void SetConfigPath(std::string config_path) { config_path_ = std::move(config_path); }
private:
std::string GetConfigPath() override { return config_path_; }
bool ShouldServe() override { return should_serve_; }
std::string config_path_;
bool should_serve_;
};
class BootstrapImplTest : public gtest::TestLoopFixture {
public:
void SetUp() override {
TestLoopFixture::SetUp();
// Set up BootstrapImpl.
ResetImpl(/*should_serve*/ true);
// Connect to the interface under test.
bootstrap_.set_error_handler([this](zx_status_t error) { last_error_ = error; });
ReconnectBootstrapPtr();
ASSERT_TRUE(bootstrap_.is_bound());
}
protected:
fuchsia::weave::BootstrapPtr& bootstrap() { return bootstrap_; }
TestableBootstrapImpl& bootstrap_impl() { return *bootstrap_impl_; }
void ResetImpl(bool should_serve) {
// If the server is already bound, the error handler will be invoked when we destroy the impl.
if (bootstrap_.is_bound()) {
bootstrap_impl_ = nullptr;
RunLoopUntilIdle();
last_error_ = ZX_OK;
}
bootstrap_impl_ = std::make_unique<TestableBootstrapImpl>(provider_.context());
bootstrap_impl_->SetShouldServe(should_serve);
bootstrap_impl_->Init();
}
void ReconnectBootstrapPtr() {
last_error_ = ZX_OK;
provider_.ConnectToPublicService(bootstrap_.NewRequest());
RunLoopUntilIdle();
}
zx_status_t last_error() const { return last_error_; }
private:
sys::testing::ComponentContextProvider provider_;
fuchsia::weave::BootstrapPtr bootstrap_;
std::unique_ptr<TestableBootstrapImpl> bootstrap_impl_;
zx_status_t last_error_;
};
// Test Cases ------------------------------------------------------------------
TEST_F(BootstrapImplTest, NoServe) {
ResetImpl(/*should_serve*/ false);
EXPECT_FALSE(bootstrap().is_bound());
EXPECT_EQ(ZX_OK, last_error());
ReconnectBootstrapPtr();
EXPECT_FALSE(bootstrap().is_bound());
EXPECT_EQ(ZX_ERR_NOT_FOUND, last_error());
}
TEST_F(BootstrapImplTest, ImportConfigHappy) {
constexpr char kConfigPath[] = "/data/config-happy.json";
bootstrap_impl().SetConfigPath(kConfigPath);
constexpr char kContents[] = "{\"key\": \"value\"}";
Bootstrap_ImportWeaveConfig_Result result;
fuchsia::mem::Buffer buffer;
ASSERT_TRUE(fsl::VmoFromString(kContents, &buffer));
EXPECT_TRUE(bootstrap().is_bound());
bool called = false;
bootstrap()->ImportWeaveConfig(std::move(buffer), [&](Bootstrap_ImportWeaveConfig_Result r) {
called = true;
result = std::move(r);
});
RunLoopUntilIdle();
// Confirm results.
EXPECT_TRUE(called);
EXPECT_TRUE(result.is_response());
std::string contents;
files::ReadFileToString(kConfigPath, &contents);
EXPECT_EQ(kContents, contents);
// Ensure binding is closed and FIDL is no longer serving.
EXPECT_FALSE(bootstrap().is_bound());
EXPECT_EQ(ZX_OK, last_error());
ReconnectBootstrapPtr();
EXPECT_FALSE(bootstrap().is_bound());
EXPECT_EQ(ZX_ERR_NOT_FOUND, last_error());
}
TEST_F(BootstrapImplTest, ImportConfigFail) {
constexpr char kConfigPath[] = "/data/config-fail.json";
bootstrap_impl().SetConfigPath(kConfigPath);
constexpr char kContents[] = "{\"key\": \"value\"}";
Bootstrap_ImportWeaveConfig_Result result;
fuchsia::mem::Buffer buffer;
ASSERT_TRUE(fsl::VmoFromString(kContents, &buffer));
// Restrict rights to cause read failure.
zx::vmo temp;
buffer.vmo.duplicate(ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER, &temp);
buffer.vmo = std::move(temp);
EXPECT_TRUE(bootstrap().is_bound());
bool called = false;
bootstrap()->ImportWeaveConfig(std::move(buffer), [&](Bootstrap_ImportWeaveConfig_Result r) {
called = true;
result = std::move(r);
});
RunLoopUntilIdle();
// Confirm results.
EXPECT_TRUE(called);
EXPECT_TRUE(result.is_err());
EXPECT_EQ(ZX_ERR_IO, result.err());
// Ensure binding is still intact and FIDL is still serving.
EXPECT_TRUE(bootstrap().is_bound());
ReconnectBootstrapPtr();
EXPECT_TRUE(bootstrap().is_bound());
}
} // namespace weavestack