blob: 65fd49574e54ceb4086661af5df127bace7574a3 [file] [log] [blame]
// Copyright 2020 The Chromium OS 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 "init/periodic_scheduler.h"
#include <memory>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using ::testing::_;
namespace {
void WaitForFile(const base::FilePath& path) {
int i = 0;
while (!base::PathExists(path)) {
sleep(1);
if (i++ > 5)
break;
}
}
} // namespace
class PeriodicSchedulerTest : public ::testing::Test {
public:
PeriodicSchedulerTest() {
CHECK(tmpdir_.CreateUniqueTempDir());
marker_file_ = tmpdir_.GetPath().Append("ok");
test_process_file_ = tmpdir_.GetPath().Append("spool/cron-lite/boo");
// Create a periodic scheduler for basic sanity testing.
std::vector<std::string> default_cmd({"touch", marker_file_.value()});
p = std::make_unique<PeriodicScheduler>(base::TimeDelta::FromSeconds(3),
base::TimeDelta::FromSeconds(10),
"boo", default_cmd);
p->set_spool_dir_for_test(tmpdir_.GetPath().Append("spool"));
p->set_check_freq_for_test(base::TimeDelta::FromSeconds(1));
}
~PeriodicSchedulerTest() = default;
void SetupDefaultDirectories() {
ASSERT_TRUE(base::CreateDirectory(tmpdir_.GetPath().Append("spool")));
ASSERT_TRUE(
base::CreateDirectory(tmpdir_.GetPath().Append("spool/cron-lite")));
}
void RunPeriodicScheduler() {
pid_t pid = fork();
PCHECK(pid != -1);
if (pid != 0) {
periodic_scheduler_pid_ = pid;
} else {
p->Run();
}
}
void StopPeriodicScheduler() {
EXPECT_EQ(kill(periodic_scheduler_pid_, SIGTERM), 0);
}
std::unique_ptr<PeriodicScheduler> p;
pid_t periodic_scheduler_pid_;
base::ScopedTempDir tmpdir_;
base::FilePath marker_file_;
base::FilePath test_process_file_;
};
TEST_F(PeriodicSchedulerTest, BasicSanity) {
// Create a fake symbolic link instead of the spool directory.
const base::FilePath symlink = tmpdir_.GetPath().Append("symlink");
ASSERT_TRUE(base::CreateSymbolicLink(tmpdir_.GetPath(), symlink));
// Run the periodic scheduler for enough time to make sure that the spool
// directory is recreated.
RunPeriodicScheduler();
WaitForFile(marker_file_);
StopPeriodicScheduler();
// Check sanity of permissions of spool.
EXPECT_TRUE(base::DirectoryExists(tmpdir_.GetPath().Append("spool")));
EXPECT_TRUE(base::DirectoryExists(
tmpdir_.GetPath().Append("spool").Append("cron-lite")));
// Check for the existence of the file that should have been created.
EXPECT_TRUE(base::PathExists(marker_file_));
}
TEST_F(PeriodicSchedulerTest, OldFileTest) {
SetupDefaultDirectories();
base::WriteFile(test_process_file_, nullptr, 0);
base::Time old_timestamp;
CHECK(base::Time::FromUTCString("1999-12-31 23:59", &old_timestamp));
base::TouchFile(test_process_file_, old_timestamp, old_timestamp);
RunPeriodicScheduler();
WaitForFile(marker_file_);
StopPeriodicScheduler();
// Check the existence of the new file.
EXPECT_TRUE(base::PathExists(marker_file_));
}
TEST_F(PeriodicSchedulerTest, EarlyKillTest) {
SetupDefaultDirectories();
base::WriteFile(test_process_file_, nullptr, 0);
auto now = base::Time::Now();
base::TouchFile(test_process_file_, now, now);
RunPeriodicScheduler();
sleep(2);
StopPeriodicScheduler();
// Check the existence of the new file.
EXPECT_FALSE(base::PathExists(marker_file_));
}