blob: 33a235999f7900c4c5e97e0cd370565dbbffa395 [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 "src/connectivity/weave/weavestack/app.h"
#include <lib/async/cpp/time.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/syslog/cpp/macros.h>
// clang-format off
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/PlatformManager.h>
#include "generic_platform_manager_impl_fuchsia.ipp"
#include "configuration_manager_delegate_impl.h"
#include "connectivity_manager_delegate_impl.h"
#include "thread_stack_manager_delegate_impl.h"
// clang-format on
#include <gtest/gtest.h>
namespace weavestack {
namespace {
using nl::Weave::DeviceLayer::ConfigurationManagerDelegateImpl;
using nl::Weave::DeviceLayer::ConfigurationMgrImpl;
using nl::Weave::DeviceLayer::ConnectivityManagerDelegateImpl;
using nl::Weave::DeviceLayer::ConnectivityMgrImpl;
using nl::Weave::DeviceLayer::PlatformMgr;
using nl::Weave::DeviceLayer::PlatformMgrImpl;
using nl::Weave::DeviceLayer::ThreadStackManagerDelegateImpl;
using nl::Weave::DeviceLayer::ThreadStackMgrImpl;
void SetDefaultDelegates() {
ConfigurationMgrImpl().SetDelegate(std::make_unique<ConfigurationManagerDelegateImpl>());
ConnectivityMgrImpl().SetDelegate(std::make_unique<ConnectivityManagerDelegateImpl>());
ThreadStackMgrImpl().SetDelegate(std::make_unique<ThreadStackManagerDelegateImpl>());
}
void ClearDelegates() {
ConfigurationMgrImpl().SetDelegate(nullptr);
ConnectivityMgrImpl().SetDelegate(nullptr);
ThreadStackMgrImpl().SetDelegate(nullptr);
}
} // namespace
class AppTest : public ::gtest::RealLoopFixture {
public:
void SetUp() {
RealLoopFixture::SetUp();
SetDefaultDelegates();
PlatformMgrImpl().SetDispatcher(dispatcher());
PlatformMgr().InitWeaveStack();
}
void TearDown() {
PlatformMgrImpl().ShutdownWeaveStack();
ClearDelegates();
RealLoopFixture::TearDown();
}
void PrepareSelect() {
struct timeval t;
memset(&t, 0, sizeof(t));
ClearFds();
PlatformMgrImpl().GetSystemLayer().PrepareSelect(fds.num_fds, &fds.read_fds, &fds.write_fds,
&fds.except_fds, t);
}
int GetSelectResult() {
struct timeval t;
memset(&t, 0, sizeof(t));
int ret = select(fds.num_fds, &fds.read_fds, &fds.write_fds, &fds.except_fds, &t);
return ret;
}
void ClearFds() {
FD_ZERO(&fds.read_fds);
FD_ZERO(&fds.write_fds);
FD_ZERO(&fds.except_fds);
fds.num_fds = 0;
}
static void EmptyWorkFunc(intptr_t arg) {}
protected:
struct {
fd_set read_fds;
fd_set write_fds;
fd_set except_fds;
int num_fds;
} fds;
};
TEST(App, CanRunApp) {
auto app = App();
SetDefaultDelegates();
EXPECT_EQ(ZX_OK, app.Init());
EXPECT_EQ(ZX_ERR_TIMED_OUT,
app.Run(async::Now(app.loop()->dispatcher()) + zx::duration(ZX_SEC(1)), false));
app.Quit();
ClearDelegates();
}
TEST(App, CallInitAgain) {
auto app = App();
SetDefaultDelegates();
EXPECT_EQ(ZX_OK, app.Init());
EXPECT_EQ(ZX_ERR_BAD_STATE, app.Init());
app.Quit();
ClearDelegates();
}
TEST_F(AppTest, WakeSelectTest) {
// Get and clear existing fds;
PrepareSelect();
int ret = GetSelectResult();
PlatformMgrImpl().GetSystemLayer().HandleSelectResult(ret, &fds.read_fds, &fds.write_fds,
&fds.except_fds);
PrepareSelect();
// select will timeout when no fds are set and returns 0.
EXPECT_EQ(0, GetSelectResult());
PrepareSelect();
PlatformMgr().ScheduleWork(EmptyWorkFunc, (intptr_t)0);
// GetSelectResult should return 1 as only the WakeSelect fd should be set.
EXPECT_EQ(1, GetSelectResult());
}
} // namespace weavestack