blob: 9e87520eaa88cf4716628cfca15ac5d8cbad8789 [file] [log] [blame]
// Copyright 2024 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "status_table.h"
#include "async_loop.h"
#include "test.h"
#include "util.h"
/// A StatusTable sub-class that just appends method calls to a log string.
struct TestStatusTable : public StatusTable {
TestStatusTable(const StatusTable::Config& config, AsyncLoop& async_loop)
: StatusTable(config, async_loop) {}
std::string GetCommandDescription(CommandPointer command) const override {
return StringFormat("command_%zu", reinterpret_cast<size_t>(command));
}
void PrintOnCurrentLine(const std::string& line) override {
StringAppendFormat(log_, "PrintOnCurrentLine(%s)\n", line.c_str());
}
void PrintOnNextLine(const std::string& line) override {
StringAppendFormat(log_, "PrintOnNextLine(%s)\n", line.c_str());
}
void ClearNextLine() override { log_ += "ClearNextLine()\n"; }
void MoveUp(size_t line_count) override {
StringAppendFormat(log_, "MoveUp(%zd)\n", line_count);
}
void Flush() override { log_ += "Flush()\n"; }
static StatusTable::CommandPointer MakeCommand(size_t n) {
return reinterpret_cast<StatusTable::CommandPointer>(n);
}
// Return log (and clear it as well in the instance)
std::string log() { return std::move(log_); }
mutable std::string log_;
};
TEST(StatusTable, NoCommands) {
StatusTable::Config table_config = { 0, 100 };
AsyncLoop& loop = AsyncLoop::Get();
AsyncLoop::ScopedTestClock clock(loop);
TestStatusTable table(table_config, loop);
ASSERT_EQ(table.log(), "");
table.SetStatus("some_status");
table.BuildStarted();
auto cmd1 = table.MakeCommand(1);
auto cmd2 = table.MakeCommand(2);
auto cmd3 = table.MakeCommand(3);
table.CommandStarted(cmd1);
table.CommandStarted(cmd2);
table.CommandStarted(cmd3);
table.UpdateTable();
ASSERT_EQ(table.log(), "");
clock.AdvanceTimeMillis(100);
table.CommandEnded(cmd2);
clock.AdvanceTimeMillis(400);
table.CommandEnded(cmd3);
table.UpdateTable();
ASSERT_EQ(table.log(), "");
table.BuildEnded();
ASSERT_EQ(table.log(), "");
}
TEST(StatusTable, TwoCommandsNoPeriodicUpdates) {
StatusTable::Config table_config = { 2, -1 };
AsyncLoop& loop = AsyncLoop::Get();
AsyncLoop::ScopedTestClock clock(loop);
TestStatusTable table(table_config, loop);
ASSERT_EQ(table.log(), "");
table.SetStatus("some_status");
table.BuildStarted();
auto cmd1 = table.MakeCommand(1);
auto cmd2 = table.MakeCommand(2);
auto cmd3 = table.MakeCommand(3);
table.CommandStarted(cmd1);
clock.AdvanceTimeMillis(250);
table.CommandStarted(cmd2);
clock.AdvanceTimeMillis(320);
table.CommandStarted(cmd3);
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.5s | command_1)\n"
"PrintOnNextLine( 0.3s | command_2)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
clock.AdvanceTimeMillis(100);
table.CommandEnded(cmd1);
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.4s | command_2)\n"
"PrintOnNextLine( 0.1s | command_3)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
clock.AdvanceTimeMillis(400);
table.CommandEnded(cmd2);
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.5s | command_3)\n"
"ClearNextLine()\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.CommandEnded(cmd3);
table.UpdateTable();
ASSERT_EQ(table.log(),
"ClearNextLine()\n"
"MoveUp(1)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.BuildEnded();
table.UpdateTable();
ASSERT_EQ(table.log_, "Flush()\n");
}
TEST(StatusTable, TwoCommandsWithPeriodicUpdates) {
StatusTable::Config table_config = { 2, 100 };
AsyncLoop& loop = AsyncLoop::Get();
AsyncLoop::ScopedTestClock clock(loop);
TestStatusTable table(table_config, loop);
ASSERT_EQ(table.log(), "");
table.SetStatus("some_status");
table.BuildStarted();
auto cmd1 = table.MakeCommand(1);
auto cmd2 = table.MakeCommand(2);
auto cmd3 = table.MakeCommand(3);
table.CommandStarted(cmd1);
clock.AdvanceTimeMillis(250); // time == 250
table.CommandStarted(cmd2);
clock.AdvanceTimeMillis(320); // time == 570
table.CommandStarted(cmd3);
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.5s | command_1)\n"
"PrintOnNextLine( 0.3s | command_2)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
// Check that if not enough time passes by, no update is performed.
clock.AdvanceTimeMillis(50); // time == 620
table.UpdateTable();
ASSERT_EQ(table.log(), "");
clock.AdvanceTimeMillis(50); // time == 670
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.6s | command_1)\n"
"PrintOnNextLine( 0.4s | command_2)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.log_.clear();
clock.AdvanceTimeMillis(100); // time == 770
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.7s | command_1)\n"
"PrintOnNextLine( 0.5s | command_2)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.CommandEnded(cmd1);
clock.AdvanceTimeMillis(100); // time == 870
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.6s | command_2)\n"
"PrintOnNextLine( 0.3s | command_3)\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
clock.AdvanceTimeMillis(400); // time == 1270
table.CommandEnded(cmd2);
table.UpdateTable();
ASSERT_EQ(table.log(),
"PrintOnNextLine( 0.7s | command_3)\n"
"ClearNextLine()\n"
"MoveUp(2)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.CommandEnded(cmd3);
clock.AdvanceTimeMillis(100); // time == 1370
table.UpdateTable();
ASSERT_EQ(table.log(),
"ClearNextLine()\n"
"MoveUp(1)\n"
"PrintOnCurrentLine(some_status)\n"
"Flush()\n");
table.BuildEnded();
table.UpdateTable();
ASSERT_EQ(table.log_, "Flush()\n");
}