blob: cdc7fa604c919a4252231ec54c7591ad123ef45f [file] [log] [blame]
// Copyright 2019 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 <lib/inspect/cpp/inspect.h>
#include <lib/zx/time.h>
#include <unistd.h>
#include <iterator>
#include <limits>
#include <set>
#include <vector>
#include <fs/metrics/histograms.h>
#include <zxtest/zxtest.h>
namespace fs_metrics {
namespace {
class HistogramsTest : public zxtest::Test {
public:
HistogramsTest() : inspector_() {}
protected:
inspect::Inspector inspector_;
};
constexpr zx::duration kDuration = zx::nsec(5);
const std::vector<EventOptions>& GetOptionsSets() {
constexpr int64_t kBlockCounts[] = {std::numeric_limits<int64_t>::min(), 1, 5, 31, 32,
std::numeric_limits<int64_t>::max()};
constexpr int64_t kNodeDepths[] = {
std::numeric_limits<int64_t>::min(), 1, 2, 4, 8, 16, 32, 64, 128,
std::numeric_limits<int64_t>::max()};
constexpr int64_t kNodeDegrees[] = {
std::numeric_limits<int64_t>::min(), 1, 2, 4, 8, 16, 32, 64, 128, 1024, 1024 * 1024,
std::numeric_limits<int64_t>::max()};
constexpr bool kBuffered[] = {true, false};
constexpr bool kSuccess[] = {true, false};
static std::vector<EventOptions> option_set;
option_set.reserve(std::size(kBlockCounts) * std::size(kNodeDepths) * std::size(kNodeDegrees) *
std::size(kBuffered) * std::size(kSuccess));
for (auto block_count : kBlockCounts) {
for (auto node_depth : kNodeDepths) {
for (auto node_degree : kNodeDegrees) {
for (auto buffered : kBuffered) {
for (auto success : kSuccess) {
EventOptions options;
options.block_count = block_count;
options.node_degree = node_degree;
options.node_depth = node_depth;
options.success = success;
options.buffered = buffered;
option_set.push_back(options);
}
}
}
}
}
return option_set;
}
TEST_F(HistogramsTest, AllOptionsAreValid) {
Histograms histograms = Histograms(&inspector_.GetRoot());
std::set<uint64_t> histogram_ids;
std::vector<fs_metrics::Event> all_events;
all_events.insert(all_events.end(), kVnodeEvents, kVnodeEvents + kVnodeEventCount);
all_events.insert(all_events.end(), kJournalEvents, kJournalEvents + kJournalEventCount);
for (auto operation : all_events) {
uint64_t prev_size = histogram_ids.size();
for (auto option_set : GetOptionsSets()) {
uint64_t histogram_id = histograms.GetHistogramId(operation, option_set);
ASSERT_GE(histogram_id, 0);
ASSERT_LT(histogram_id, histograms.GetHistogramCount());
histogram_ids.insert(histogram_id);
histograms.Record(histogram_id, kDuration);
}
ASSERT_EQ(histograms.GetHistogramCount(operation), histogram_ids.size() - prev_size,
" Operation Histogram Count is wrong. %lu", static_cast<uint64_t>(operation));
}
ASSERT_EQ(histogram_ids.size(), histograms.GetHistogramCount(),
"Failed to cover all histograms with all options set.");
}
TEST_F(HistogramsTest, DefaultLatencyEventSmokeTest) {
Histograms histograms = Histograms(&inspector_.GetRoot());
std::set<uint64_t> histogram_ids;
// This is will log an event with default options for every operation, which would crash with
// unitialized memory.
for (auto operation : kVnodeEvents) {
histograms.NewLatencyEvent(operation);
}
}
TEST_F(HistogramsTest, InvalidOptionsReturnsHistogramCount) {
Histograms histograms = Histograms(&inspector_.GetRoot());
ASSERT_EQ(histograms.GetHistogramId(Event::kDataCorruption, EventOptions()),
histograms.GetHistogramCount());
ASSERT_EQ(histograms.GetHistogramId(Event::kCompression, EventOptions()),
histograms.GetHistogramCount());
uint32_t invalid_event = static_cast<uint32_t>(Event::kInvalidEvent) + 1;
ASSERT_EQ(histograms.GetHistogramId(static_cast<Event>(invalid_event), EventOptions()),
histograms.GetHistogramCount());
}
TEST_F(HistogramsTest, SizeIsMultipleOfPageSize) {
Histograms histograms = Histograms(&inspector_.GetRoot());
ASSERT_EQ(Histograms::Size() % PAGE_SIZE, 0);
}
} // namespace
} // namespace fs_metrics