blob: 11a86e2e16a7c4e9ba24ae7b1bf4fcee0e99cfff [file] [log] [blame]
// Copyright 2025 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/developer/memory/monitor/logger.h"
#include <lib/inspect/cpp/reader.h>
#include <lib/inspect/testing/cpp/inspect.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/developer/memory/metrics/tests/test_utils.h"
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
namespace memory {
namespace {
using inspect::testing::ChildrenMatch;
using inspect::testing::NameMatches;
using inspect::testing::NodeMatches;
class LoggerInspectTest : public gtest::TestLoopFixture {};
zx_status_t GetCapture(Capture* capture) {
TestUtils::CreateCapture(
capture,
{
.kmem =
{
.total_bytes = 1000,
.free_bytes = 100,
.wired_bytes = 10,
.vmo_bytes = 700,
},
.vmos =
{
{.koid = 1, .name = "a1", .committed_bytes = 100, .committed_scaled_bytes = 100},
{.koid = 2, .name = "b1", .committed_bytes = 200, .committed_scaled_bytes = 200},
{.koid = 3, .name = "c1", .committed_bytes = 300, .committed_scaled_bytes = 300},
},
.processes =
{
{.koid = 1, .name = "p1", .vmos = {1}},
{.koid = 2, .name = "q1", .vmos = {2}},
},
});
return {};
}
void GetDigest(const Capture& capture, Digest* digest) {
Digester digester({{"A", ".*", "a.*"}, {"B", ".*", "b.*"}});
digester.Digest(capture, digest);
}
TEST_F(LoggerInspectTest, MemoryBuckets) {
// |capture_on_pressure_change=true| so that setting the pressure level fills in the buckets.
// Arbitrary non-zero capture_delay so that the test does not loop for ever.
memory_monitor_config::Config config{{.capture_on_pressure_change = true,
.critical_capture_delay_s = 1000,
.imminent_oom_capture_delay_s = 1000,
.normal_capture_delay_s = 1000,
.warning_capture_delay_s = 1000}};
inspect::Inspector inspector;
monitor::Logger logger{dispatcher(), std::nullopt, &GetCapture,
&GetDigest, &config, inspector.GetRoot().CreateChild("logger")};
// Trigger pressure change to capture a log.
logger.SetPressureLevel(pressure_signaler::kWarning);
// Let the logger drain its internal task queue.
RunLoopUntilIdle();
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
// We expect the following hierarchy:
// root
// |
// logger
// / \
// buckets measurements
// | (prop.) | (node)
// (bucket names) [measurements]
// TODO(https://fxbug.dev/394289215): Use inspect StringArray property matcher once available.
EXPECT_THAT(hierarchy,
// root
testing::AllOf(NodeMatches(NameMatches("root")),
ChildrenMatch(testing::ElementsAre(
testing::AllOf(NodeMatches(NameMatches("logger")),
ChildrenMatch(testing::ElementsAre(
// measurements
NodeMatches(NameMatches("measurements")))))))));
}
} // namespace
} // namespace memory