Skip to content

[TEST] Add metrics system test coverage #405

Description

@kcenon

Summary

Add comprehensive test coverage for the metric_reporter class and network metrics infrastructure.

Current State

  • network_metrics.h defines standard metric names
  • metric_reporter class provides static methods for reporting
  • No test coverage exists for metrics

Current interface:

class metric_reporter {
public:
    static void report_connection_accepted();
    static void report_connection_failed(const std::string& reason);
    static void report_bytes_sent(size_t bytes);
    static void report_bytes_received(size_t bytes);
    static void report_latency(double ms);
    static void report_error(const std::string& error_type);
    static void report_timeout();
    static void report_active_connections(size_t count);
    static void report_session_duration(double ms);
};

Test Plan

Unit Tests (test_network_metrics.cpp)

1. Metric Names Constants

TEST(MetricNamesTest, ConnectionMetrics) {
    EXPECT_STREQ(metric_names::CONNECTIONS_ACTIVE, 
                 "network.connections.active");
    EXPECT_STREQ(metric_names::CONNECTIONS_TOTAL, 
                 "network.connections.total");
    EXPECT_STREQ(metric_names::CONNECTIONS_FAILED, 
                 "network.connections.failed");
}

TEST(MetricNamesTest, TransferMetrics) {
    EXPECT_STREQ(metric_names::BYTES_SENT, "network.bytes.sent");
    EXPECT_STREQ(metric_names::BYTES_RECEIVED, "network.bytes.received");
}

TEST(MetricNamesTest, PerformanceMetrics) {
    EXPECT_STREQ(metric_names::LATENCY_MS, "network.latency.ms");
    EXPECT_STREQ(metric_names::THROUGHPUT_MBPS, "network.throughput.mbps");
}

2. Reporter Integration Tests (with mock monitoring)

class MockMonitor : public monitoring_interface {
public:
    std::vector<std::pair<std::string, double>> reported_gauges;
    std::vector<std::pair<std::string, int64_t>> reported_counters;
    
    void gauge(const std::string& name, double value) override {
        reported_gauges.emplace_back(name, value);
    }
    
    void counter(const std::string& name, int64_t delta) override {
        reported_counters.emplace_back(name, delta);
    }
};

TEST_F(MetricReporterTest, ReportsConnectionAccepted) {
    metric_reporter::report_connection_accepted();
    
    ASSERT_EQ(mock_monitor_->reported_counters.size(), 1);
    EXPECT_EQ(mock_monitor_->reported_counters[0].first,
              metric_names::CONNECTIONS_TOTAL);
    EXPECT_EQ(mock_monitor_->reported_counters[0].second, 1);
}

TEST_F(MetricReporterTest, ReportsBytesSent) {
    metric_reporter::report_bytes_sent(1024);
    
    ASSERT_EQ(mock_monitor_->reported_counters.size(), 1);
    EXPECT_EQ(mock_monitor_->reported_counters[0].first,
              metric_names::BYTES_SENT);
    EXPECT_EQ(mock_monitor_->reported_counters[0].second, 1024);
}

TEST_F(MetricReporterTest, ReportsLatency) {
    metric_reporter::report_latency(42.5);
    
    ASSERT_EQ(mock_monitor_->reported_gauges.size(), 1);
    EXPECT_EQ(mock_monitor_->reported_gauges[0].first,
              metric_names::LATENCY_MS);
    EXPECT_DOUBLE_EQ(mock_monitor_->reported_gauges[0].second, 42.5);
}

3. Thread Safety Tests

TEST_F(MetricReporterTest, ConcurrentReporting) {
    std::vector<std::thread> threads;
    constexpr int kThreads = 10;
    constexpr int kIterations = 1000;
    
    for (int i = 0; i < kThreads; ++i) {
        threads.emplace_back([&] {
            for (int j = 0; j < kIterations; ++j) {
                metric_reporter::report_bytes_sent(100);
                metric_reporter::report_connection_accepted();
            }
        });
    }
    
    for (auto& t : threads) t.join();
    
    // Verify no crashes, data races
    EXPECT_EQ(mock_monitor_->reported_counters.size(), 
              kThreads * kIterations * 2);
}

4. Edge Cases

TEST_F(MetricReporterTest, ReportsZeroBytes) {
    metric_reporter::report_bytes_sent(0);
    EXPECT_EQ(mock_monitor_->reported_counters.size(), 1);
}

TEST_F(MetricReporterTest, ReportsMaxBytes) {
    metric_reporter::report_bytes_sent(SIZE_MAX);
    EXPECT_EQ(mock_monitor_->reported_counters[0].second, 
              static_cast<int64_t>(SIZE_MAX));
}

TEST_F(MetricReporterTest, ReportsEmptyErrorType) {
    metric_reporter::report_error("");
    EXPECT_EQ(mock_monitor_->reported_counters.size(), 1);
}

Integration Tests (test_metrics_integration.cpp)

TEST_F(MetricsIntegrationTest, ClientReportsMetricsOnConnect) {
    auto client = make_test_client();
    client->connect("localhost", 8080);
    
    // Verify connection metrics reported
    EXPECT_TRUE(has_metric(metric_names::CONNECTIONS_TOTAL));
}

TEST_F(MetricsIntegrationTest, ServerReportsAcceptMetrics) {
    auto server = make_test_server();
    auto client = make_test_client();
    
    server->start(8080);
    client->connect("localhost", 8080);
    
    EXPECT_TRUE(has_metric(metric_names::SERVER_ACCEPT_COUNT));
}

TEST_F(MetricsIntegrationTest, DataTransferReportsBytes) {
    // Setup connection...
    client->send({1, 2, 3, 4});
    
    EXPECT_TRUE(has_metric(metric_names::BYTES_SENT));
    EXPECT_GE(get_counter(metric_names::BYTES_SENT), 4);
}

Tasks

  • Create tests/unit/test_network_metrics.cpp
  • Create tests/integration/test_metrics_integration.cpp
  • Implement MockMonitor test helper
  • Add metric name constant tests
  • Add reporter method tests
  • Add thread safety tests
  • Add edge case tests
  • Add integration tests with real components
  • Verify metrics in CI

Acceptance Criteria

  • All metric name constants verified
  • All reporter methods tested
  • Thread safety verified with TSAN
  • Integration with monitoring system tested
  • >80% code coverage for metrics module
  • All tests pass in CI

Files to Create/Modify

  • New: tests/unit/test_network_metrics.cpp
  • New: tests/integration/test_metrics_integration.cpp
  • New: tests/helpers/mock_monitor.h

Related

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions