blob: 0ff8a11aaf2bec9840e059b67a1fdbe7bbf0936b [file] [log] [blame]
#include <sdbusplus/bus.hpp>
#include <gtest/gtest.h>
#include "host_epoch.hpp"
#include "utils.hpp"
#include "config.h"
#include "types.hpp"
namespace phosphor
{
namespace time
{
using namespace std::chrono;
using namespace std::chrono_literals;
class TestHostEpoch : public testing::Test
{
public:
sdbusplus::bus::bus bus;
HostEpoch hostEpoch;
static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist";
static constexpr auto FILE_OFFSET = "saved_host_offset";
static constexpr auto delta = 2s;
TestHostEpoch()
: bus(sdbusplus::bus::new_default()),
hostEpoch(bus, OBJPATH_HOST)
{
// Make sure the file does not exist
std::remove(FILE_NOT_EXIST);
}
~TestHostEpoch()
{
// Cleanup test file
std::remove(FILE_OFFSET);
}
// Proxies for HostEpoch's private members and functions
Mode getTimeMode()
{
return hostEpoch.timeMode;
}
Owner getTimeOwner()
{
return hostEpoch.timeOwner;
}
microseconds getOffset()
{
return hostEpoch.offset;
}
void setTimeOwner(Owner owner)
{
hostEpoch.timeOwner = owner;
}
};
TEST_F(TestHostEpoch, empty)
{
EXPECT_EQ(Mode::NTP, getTimeMode());
EXPECT_EQ(Owner::BMC, getTimeOwner());
}
TEST_F(TestHostEpoch, readDataFileNotExist)
{
// When file does not exist, the default offset shall be 0
microseconds offset(0);
auto value = utils::readData<decltype(offset)::rep>(FILE_NOT_EXIST);
EXPECT_EQ(0, value);
}
TEST_F(TestHostEpoch, writeAndReadData)
{
// Write offset to file
microseconds offsetToWrite(1234567);
utils::writeData<decltype(offsetToWrite)::rep>(
FILE_OFFSET, offsetToWrite.count());
// Read it back
microseconds offsetToRead;
offsetToRead = microseconds(
utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
EXPECT_EQ(offsetToWrite, offsetToRead);
}
TEST_F(TestHostEpoch, setElapsedNotAllowed)
{
// By default offset shall be 0
EXPECT_EQ(0, getOffset().count());
// Set time in BMC mode is not allowed,
// so verify offset is still 0 after set time
microseconds diff = 1min;
hostEpoch.elapsed(hostEpoch.elapsed() + diff.count());
EXPECT_EQ(0, getOffset().count());
}
TEST_F(TestHostEpoch, setElapsedInFutureAndGet)
{
// Set to HOST owner so that we can set elapsed
setTimeOwner(Owner::HOST);
// Get current time, and set future +1min time
auto t1 = hostEpoch.elapsed();
EXPECT_NE(0, t1);
microseconds diff = 1min;
auto t2 = t1 + diff.count();
hostEpoch.elapsed(t2);
// Verify that the offset shall be positive,
// and less or equal to diff, and shall be not too less.
auto offset = getOffset();
EXPECT_GT(offset, microseconds(0));
EXPECT_LE(offset, diff);
diff -= delta;
EXPECT_GE(offset, diff);
// Now get time shall be around future +1min time
auto epochNow = duration_cast<microseconds>(
system_clock::now().time_since_epoch()).count();
auto elapsedGot = hostEpoch.elapsed();
EXPECT_LT(epochNow, elapsedGot);
auto epochDiff = elapsedGot - epochNow;
diff = 1min;
EXPECT_GT(epochDiff, (diff - delta).count());
EXPECT_LT(epochDiff, (diff + delta).count());
}
TEST_F(TestHostEpoch, setElapsedInPastAndGet)
{
// Set to HOST owner so that we can set elapsed
setTimeOwner(Owner::HOST);
// Get current time, and set past -1min time
auto t1 = hostEpoch.elapsed();
EXPECT_NE(0, t1);
microseconds diff = 1min;
auto t2 = t1 - diff.count();
hostEpoch.elapsed(t2);
// Verify that the offset shall be negative, and the absolute value
// shall be equal or greater than diff, and shall not be too greater
auto offset = getOffset();
EXPECT_LT(offset, microseconds(0));
offset = -offset;
EXPECT_GE(offset, diff);
diff += 10s;
EXPECT_LE(offset, diff);
// Now get time shall be around past -1min time
auto epochNow = duration_cast<microseconds>(
system_clock::now().time_since_epoch()).count();
auto elapsedGot = hostEpoch.elapsed();
EXPECT_LT(elapsedGot, epochNow);
auto epochDiff = epochNow - elapsedGot;
diff = 1min;
EXPECT_GT(epochDiff, (diff - delta).count());
EXPECT_LT(epochDiff, (diff + delta).count());
}
}
}