#include #include #include #include using namespace torch::monitor; TEST(MonitorTest, CounterDouble) { FixedCountStat a{ "a", {Aggregation::MEAN, Aggregation::COUNT}, 2, }; a.add(5.0); ASSERT_EQ(a.count(), 1); a.add(6.0); ASSERT_EQ(a.count(), 0); auto stats = a.get(); std::unordered_map want = { {Aggregation::MEAN, 5.5}, {Aggregation::COUNT, 2.0}, }; ASSERT_EQ(stats, want); } TEST(MonitorTest, CounterInt64Sum) { FixedCountStat a{ "a", {Aggregation::SUM}, 2, }; a.add(5); a.add(6); auto stats = a.get(); std::unordered_map want = { {Aggregation::SUM, 11}, }; ASSERT_EQ(stats, want); } TEST(MonitorTest, CounterInt64Value) { FixedCountStat a{ "a", {Aggregation::VALUE}, 2, }; a.add(5); a.add(6); auto stats = a.get(); std::unordered_map want = { {Aggregation::VALUE, 6}, }; ASSERT_EQ(stats, want); } TEST(MonitorTest, CounterInt64Mean) { FixedCountStat a{ "a", {Aggregation::MEAN}, 2, }; { // zero samples case auto stats = a.get(); std::unordered_map want = { {Aggregation::MEAN, 0}, }; ASSERT_EQ(stats, want); } a.add(0); a.add(10); { auto stats = a.get(); std::unordered_map want = { {Aggregation::MEAN, 5}, }; ASSERT_EQ(stats, want); } } TEST(MonitorTest, CounterInt64Count) { FixedCountStat a{ "a", {Aggregation::COUNT}, 2, }; ASSERT_EQ(a.count(), 0); a.add(0); ASSERT_EQ(a.count(), 1); a.add(10); ASSERT_EQ(a.count(), 0); auto stats = a.get(); std::unordered_map want = { {Aggregation::COUNT, 2}, }; ASSERT_EQ(stats, want); } TEST(MonitorTest, CounterInt64MinMax) { FixedCountStat a{ "a", {Aggregation::MIN, Aggregation::MAX}, 6, }; { auto stats = a.get(); std::unordered_map want = { {Aggregation::MAX, 0}, {Aggregation::MIN, 0}, }; ASSERT_EQ(stats, want); } a.add(0); a.add(5); a.add(-5); a.add(-6); a.add(9); a.add(2); { auto stats = a.get(); std::unordered_map want = { {Aggregation::MAX, 9}, {Aggregation::MIN, -6}, }; ASSERT_EQ(stats, want); } } TEST(MonitorTest, CounterInt64WindowSize) { FixedCountStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, /*windowSize=*/3, }; a.add(1); a.add(2); ASSERT_EQ(a.count(), 2); a.add(3); ASSERT_EQ(a.count(), 0); a.add(4); ASSERT_EQ(a.count(), 1); auto stats = a.get(); std::unordered_map want = { {Aggregation::COUNT, 3}, {Aggregation::SUM, 6}, }; ASSERT_EQ(stats, want); } template struct TestIntervalStat : public IntervalStat { uint64_t mockWindowId{0}; TestIntervalStat( std::string name, std::initializer_list aggregations, std::chrono::milliseconds windowSize) : IntervalStat(name, aggregations, windowSize) {} uint64_t currentWindowId() const override { return mockWindowId; } }; struct AggregatingEventHandler : public EventHandler { std::vector events; void handle(const Event& e) override { events.emplace_back(e); } }; template struct HandlerGuard { std::shared_ptr handler; HandlerGuard() : handler(std::make_shared()) { registerEventHandler(handler); } ~HandlerGuard() { unregisterEventHandler(handler); } }; TEST(MonitorTest, IntervalStat) { HandlerGuard guard; IntervalStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, std::chrono::milliseconds(1), }; ASSERT_EQ(guard.handler->events.size(), 0); a.add(1); ASSERT_LE(a.count(), 1); std::this_thread::sleep_for(std::chrono::milliseconds(2)); a.add(2); ASSERT_LE(a.count(), 1); ASSERT_GE(guard.handler->events.size(), 1); ASSERT_LE(guard.handler->events.size(), 2); } TEST(MonitorTest, IntervalStatEvent) { HandlerGuard guard; TestIntervalStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, std::chrono::milliseconds(1), }; ASSERT_EQ(guard.handler->events.size(), 0); a.add(1); ASSERT_EQ(a.count(), 1); a.add(2); ASSERT_EQ(a.count(), 2); ASSERT_EQ(guard.handler->events.size(), 0); a.mockWindowId = 100; a.add(3); ASSERT_LE(a.count(), 1); ASSERT_EQ(guard.handler->events.size(), 1); Event e = guard.handler->events.at(0); ASSERT_EQ(e.name, "torch.monitor.Stat"); ASSERT_NE(e.timestamp, std::chrono::system_clock::time_point{}); std::unordered_map data{ {"a.sum", 3L}, {"a.count", 2L}, }; ASSERT_EQ(e.data, data); } TEST(MonitorTest, IntervalStatEventDestruction) { HandlerGuard guard; { TestIntervalStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, std::chrono::hours(10), }; a.add(1); ASSERT_EQ(a.count(), 1); ASSERT_EQ(guard.handler->events.size(), 0); } ASSERT_EQ(guard.handler->events.size(), 1); Event e = guard.handler->events.at(0); ASSERT_EQ(e.name, "torch.monitor.Stat"); ASSERT_NE(e.timestamp, std::chrono::system_clock::time_point{}); std::unordered_map data{ {"a.sum", 1L}, {"a.count", 1L}, }; ASSERT_EQ(e.data, data); } TEST(MonitorTest, FixedCountStatEvent) { HandlerGuard guard; FixedCountStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, 3, }; ASSERT_EQ(guard.handler->events.size(), 0); a.add(1); ASSERT_EQ(a.count(), 1); a.add(2); ASSERT_EQ(a.count(), 2); ASSERT_EQ(guard.handler->events.size(), 0); a.add(1); ASSERT_EQ(a.count(), 0); ASSERT_EQ(guard.handler->events.size(), 1); Event e = guard.handler->events.at(0); ASSERT_EQ(e.name, "torch.monitor.Stat"); ASSERT_NE(e.timestamp, std::chrono::system_clock::time_point{}); std::unordered_map data{ {"a.sum", 4L}, {"a.count", 3L}, }; ASSERT_EQ(e.data, data); } TEST(MonitorTest, FixedCountStatEventDestruction) { HandlerGuard guard; { FixedCountStat a{ "a", {Aggregation::COUNT, Aggregation::SUM}, 3, }; ASSERT_EQ(guard.handler->events.size(), 0); a.add(1); ASSERT_EQ(a.count(), 1); ASSERT_EQ(guard.handler->events.size(), 0); } ASSERT_EQ(guard.handler->events.size(), 1); Event e = guard.handler->events.at(0); ASSERT_EQ(e.name, "torch.monitor.Stat"); ASSERT_NE(e.timestamp, std::chrono::system_clock::time_point{}); std::unordered_map data{ {"a.sum", 1L}, {"a.count", 1L}, }; ASSERT_EQ(e.data, data); }