blob: 83edc6c395e4cf211297f96b57578bbf68722f5b [file] [log] [blame]
// Copyright 2018 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 "lib/gtest/test_loop_fixture.h"
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <cstdlib>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/test/test_settings.h"
namespace gtest {
namespace {
using TestLoopFixtureTest = TestLoopFixture;
TEST_F(TestLoopFixtureTest, DefaultDispatcherIsSet) {
EXPECT_EQ(async_get_default_dispatcher(), dispatcher());
}
TEST_F(TestLoopFixtureTest, TimeIsAdvanced) {
EXPECT_EQ(Now(), zx::time(0));
RunLoopUntil(zx::time(0) + zx::sec(15));
EXPECT_EQ(Now(), zx::time(0) + zx::sec(15));
RunLoopFor(zx::sec(5));
EXPECT_EQ(Now(), zx::time(0) + zx::sec(20));
// RunLoopUntilIdle() should not advance the time.
RunLoopUntilIdle();
EXPECT_EQ(Now(), zx::time(0) + zx::sec(20));
}
TEST_F(TestLoopFixtureTest, WorkBeingDoneIsReported) {
EXPECT_FALSE(RunLoopUntilIdle());
EXPECT_FALSE(RunLoopUntil(zx::time(0) + zx::sec(5)));
EXPECT_FALSE(RunLoopFor(zx::sec(5)));
async::PostTask(dispatcher(), [] {});
EXPECT_TRUE(RunLoopUntilIdle());
async::PostTaskForTime(
dispatcher(), [] {}, zx::time(0) + zx::sec(15));
EXPECT_TRUE(RunLoopUntil(zx::time(0) + zx::sec(15)));
async::PostDelayedTask(
dispatcher(), [] {}, zx::sec(5));
EXPECT_TRUE(RunLoopFor(zx::sec(5)));
}
TEST_F(TestLoopFixtureTest, LoopCanQuitAndReset) {
async::PostDelayedTask(
dispatcher(), [] {}, zx::sec(1));
QuitLoop();
// Loop has quit, so time does not advance and no work is done.
EXPECT_FALSE(RunLoopFor(zx::sec(1)));
EXPECT_EQ(Now(), zx::time(0));
// Loop has reset, so time does advance and work is done.
EXPECT_TRUE(RunLoopFor(zx::sec(1)));
EXPECT_EQ(Now(), zx::time(0) + zx::sec(1));
// Quit task is posted, followed by another task. The quit task is
// dispatched and work is reported.
async::PostTask(dispatcher(), QuitLoopClosure());
async::PostTask(dispatcher(), [] {});
EXPECT_TRUE(RunLoopUntilIdle());
// Loop was quit, but it is now reset the remaining task will be dispatched
// on the next run.
EXPECT_TRUE(RunLoopUntilIdle());
}
TEST_F(TestLoopFixtureTest, LoopRunsRepeatedly) {
for (int i = 0; i <= 60; ++i) {
async::PostDelayedTask(
dispatcher(), [] {}, zx::sec(i));
}
// Run the loop repeatedly at ten second intervals until the delayed tasks
// are all dispatched.
RunLoopRepeatedlyFor(zx::sec(10));
EXPECT_GE(Now(), zx::time(0) + zx::min(1));
// There should be nothing further to dispatch.
EXPECT_FALSE(RunLoopUntilIdle());
}
// Test that --test_loop_seed correctly propagates the random seed to the test
// loop. This must be done before the test fixture is instanciated, hence the
// use of |SetUpTestSuite| to set the flag (and restore the environment variable
// to its original value once done).
class RandomSeedTest : public TestLoopFixture {
public:
static void SetUpTestSuite() {
random_seed_ = getenv("TEST_LOOP_RANDOM_SEED");
FXL_CHECK(fxl::SetTestSettings(
fxl::CommandLineFromInitializerList({"argv0", "--test_loop_seed=1234"})));
}
static void TearDownTestSuite() {
if (random_seed_) {
setenv("TEST_LOOP_RANDOM_SEED", random_seed_, /*overwrite=*/true);
random_seed_ = nullptr;
} else {
unsetenv("TEST_LOOP_RANDOM_SEED");
}
}
private:
static char *random_seed_;
};
char *RandomSeedTest::random_seed_;
TEST_F(RandomSeedTest, RandomSeedFromFlag) { EXPECT_EQ(test_loop().initial_state(), 1234u); }
} // namespace
} // namespace gtest