blob: ca2658816ea2f302f6b91bc7bf7132b58e20ae48 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 "src/cobalt/bin/system-metrics/archivist_stats_fetcher_impl.h"
#include <fuchsia/diagnostics/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/gtest/test_loop_fixture.h>
#include <set>
#include <gtest/gtest.h>
#include <src/lib/fsl/vmo/strings.h>
#include "src/cobalt/bin/system-metrics/testing/fake_archive.h"
namespace {
const uint64_t kExpectedMetricCount = 22;
const char kExpectedArchiveOutput[] = R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"archive_accessor_connections_closed": 1,
"archive_accessor_connections_opened": 2,
"inspect_batch_iterator_connections_closed": 3,
"inspect_batch_iterator_connections_opened": 4,
"inspect_batch_iterator_get_next_errors": 5,
"inspect_batch_iterator_get_next_requests": 6,
"inspect_batch_iterator_get_next_responses": 7,
"inspect_batch_iterator_get_next_result_count": 8,
"inspect_batch_iterator_get_next_result_errors": 9,
"inspect_component_timeouts_count": 10,
"inspect_reader_servers_constructed": 11,
"inspect_reader_servers_destroyed": 12,
"lifecycle_batch_iterator_connections_closed": 13,
"lifecycle_batch_iterator_connections_opened": 14,
"lifecycle_batch_iterator_get_next_errors": 15,
"lifecycle_batch_iterator_get_next_requests": 16,
"lifecycle_batch_iterator_get_next_responses": 17,
"lifecycle_batch_iterator_get_next_result_count": 18,
"lifecycle_batch_iterator_get_next_result_errors": 19,
"lifecycle_component_timeouts_count": 20,
"lifecycle_reader_servers_constructed": 21,
"lifecycle_reader_servers_destroyed": 22,
"stream_diagnostics_requests": 23
},
"feedback_archive_accessor": {
"archive_accessor_connections_closed": 1,
"archive_accessor_connections_opened": 2,
"inspect_batch_iterator_connections_closed": 3,
"inspect_batch_iterator_connections_opened": 4,
"inspect_batch_iterator_get_next_errors": 5,
"inspect_batch_iterator_get_next_requests": 6,
"inspect_batch_iterator_get_next_responses": 7,
"inspect_batch_iterator_get_next_result_count": 8,
"inspect_batch_iterator_get_next_result_errors": 9,
"inspect_component_timeouts_count": 10,
"inspect_reader_servers_constructed": 11,
"inspect_reader_servers_destroyed": 12,
"lifecycle_batch_iterator_connections_closed": 13,
"lifecycle_batch_iterator_connections_opened": 14,
"lifecycle_batch_iterator_get_next_errors": 15,
"lifecycle_batch_iterator_get_next_requests": 16,
"lifecycle_batch_iterator_get_next_responses": 17,
"lifecycle_batch_iterator_get_next_result_count": 18,
"lifecycle_batch_iterator_get_next_result_errors": 19,
"lifecycle_component_timeouts_count": 20,
"lifecycle_reader_servers_constructed": 21,
"lifecycle_reader_servers_destroyed": 22,
"stream_diagnostics_requests": 23
}
}
}
}
)";
class TestArchivistStatsFetcherImpl : public cobalt::ArchivistStatsFetcherImpl {
public:
TestArchivistStatsFetcherImpl(async_dispatcher_t* dispatcher,
fit::function<fuchsia::diagnostics::ArchiveAccessorPtr()> callback)
: ArchivistStatsFetcherImpl(dispatcher, std::move(callback)) {}
};
class ArchivistStatsFetcherImplTest : public gtest::TestLoopFixture {
public:
ArchivistStatsFetcherImplTest()
: fake_archive_(kExpectedArchiveOutput),
test_fetcher_(
TestArchivistStatsFetcherImpl(dispatcher(), [this] { return BindArchive(); })) {}
protected:
fuchsia::diagnostics::ArchiveAccessorPtr BindArchive() {
fuchsia::diagnostics::ArchiveAccessorPtr ret;
archive_bindings_.AddBinding(&fake_archive_, ret.NewRequest());
return ret;
}
cobalt::FakeArchive fake_archive_;
TestArchivistStatsFetcherImpl test_fetcher_;
fidl::BindingSet<fuchsia::diagnostics::ArchiveAccessor> archive_bindings_;
};
// Ensure that the expected number of measurements are uploaded and that they do not get reuploaded
// if they did not change.
TEST_F(ArchivistStatsFetcherImplTest, MeasurementsDoNotRepeatSuccess) {
size_t count = 0;
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
count++;
return true;
});
RunLoopUntilIdle();
EXPECT_EQ(kExpectedMetricCount, count);
// Try loading again, since no metrics changed they will not be uploaded again.
count = 0;
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
count++;
return true;
});
EXPECT_EQ(0u, count);
}
// Ensure that all measurements are reuploaded if they fail.
TEST_F(ArchivistStatsFetcherImplTest, MeasurementsRepeatFailed) {
size_t count = 0;
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
count++;
return false;
});
RunLoopUntilIdle();
EXPECT_EQ(kExpectedMetricCount, count);
// Try fetching again. Since all metrics failed, they will all show up.
count = 0;
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
count++;
return true;
});
RunLoopUntilIdle();
EXPECT_EQ(kExpectedMetricCount, count);
}
// Ensure that updating multiple metrics over time works as expected.
TEST_F(ArchivistStatsFetcherImplTest, MetricsUpdatedOverTime) {
std::vector<uint64_t> values;
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"archive_accessor_connections_opened": 5
},
"feedback_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(5u, values[0]);
values.clear();
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"archive_accessor_connections_opened": 7
},
"feedback_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(2u, values[0]);
values.clear();
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"inspect_batch_iterator_get_next_errors": 10
},
"feedback_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(10u, values[0]);
values.clear();
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"archive_accessor_connections_opened": 8,
"inspect_batch_iterator_get_next_errors": 10
},
"feedback_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(1u, values[0]);
values.clear();
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"all_archive_accessor": {
"archive_accessor_connections_opened": 9,
"inspect_batch_iterator_get_next_errors": 11
},
"feedback_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(2u, values.size());
EXPECT_EQ(1u, values[0]);
EXPECT_EQ(1u, values[1]);
// New measurement, but for a different accessor.
values.clear();
fake_archive_ = cobalt::FakeArchive(R"(
{
"moniker": "bootstrap/archivist",
"payload": {
"root": {
"feedback_archive_accessor": {
"archive_accessor_connections_opened": 9
},
"all_archive_accessor": {}
}
}
})");
test_fetcher_.FetchMetrics([&](cobalt::ArchivistStatsFetcher::Measurement measurement) {
values.push_back(measurement.second);
return true;
});
RunLoopUntilIdle();
ASSERT_EQ(1u, values.size());
EXPECT_EQ(9u, values[0]);
}
} // namespace