blob: bfe5410e5523bc6f255c66c952a25d46b8b7a033 [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 "src/developer/memory/metrics/digest.h"
#include <gtest/gtest.h>
#include "src/developer/memory/metrics/tests/test_utils.h"
namespace memory {
namespace test {
using DigestUnitTest = testing::Test;
struct ExpectedBucket {
std::string name;
uint64_t size;
};
void ConfirmBuckets(const Digest& digest, const std::vector<ExpectedBucket>& expected_buckets) {
std::vector<Bucket> buckets_copy = digest.buckets();
for (size_t i = 0; i < expected_buckets.size(); ++i) {
const auto& expected_bucket = expected_buckets.at(i);
bool found = false;
for (size_t j = 0; j < buckets_copy.size(); ++j) {
const auto& bucket = buckets_copy.at(j);
if (expected_bucket.name == bucket.name()) {
EXPECT_EQ(expected_bucket.size, bucket.size()) << "Bucket name: " << expected_bucket.name;
buckets_copy.erase(buckets_copy.begin() + j);
found = true;
break;
}
}
EXPECT_TRUE(found) << "Bucket name: " << expected_bucket.name;
}
for (const auto& unmatched_bucket : buckets_copy) {
EXPECT_TRUE(false) << "Unmatched bucket: " << unmatched_bucket.name();
}
}
TEST_F(DigestUnitTest, VMONames) {
Capture c;
TestUtils::CreateCapture(&c, {
.vmos =
{
{.koid = 1, .name = "a1", .committed_bytes = 100},
{.koid = 2, .name = "b1", .committed_bytes = 200},
},
.processes =
{
{.koid = 1, .name = "p1", .vmos = {1}},
{.koid = 2, .name = "q1", .vmos = {2}},
},
});
Digester digester({{"A", ".*", "a.*"}, {"B", ".*", "b.*"}});
Digest d(c, &digester);
ConfirmBuckets(d, {{"B", 200U}, {"A", 100U}});
EXPECT_EQ(0U, d.undigested_vmos().size());
} // namespace test
TEST_F(DigestUnitTest, ProcessNames) {
Capture c;
TestUtils::CreateCapture(&c, {
.vmos =
{
{.koid = 1, .name = "a1", .committed_bytes = 100},
{.koid = 2, .name = "b1", .committed_bytes = 200},
},
.processes =
{
{.koid = 1, .name = "p1", .vmos = {1}},
{.koid = 2, .name = "q1", .vmos = {2}},
},
});
Digester digester({{"P", "p.*", ".*"}, {"Q", "q.*", ".*"}});
Digest d(c, &digester);
ConfirmBuckets(d, {{"Q", 200U}, {"P", 100U}});
EXPECT_EQ(0U, d.undigested_vmos().size());
}
TEST_F(DigestUnitTest, Undigested) {
Capture c;
TestUtils::CreateCapture(&c, {
.vmos =
{
{.koid = 1, .name = "a1", .committed_bytes = 100},
{.koid = 2, .name = "b1", .committed_bytes = 200},
},
.processes =
{
{.koid = 1, .name = "p1", .vmos = {1}},
{.koid = 2, .name = "q1", .vmos = {2}},
},
});
Digester digester({{"A", ".*", "a.*"}});
Digest d(c, &digester);
ASSERT_EQ(1U, d.undigested_vmos().size());
ASSERT_NE(d.undigested_vmos().end(), d.undigested_vmos().find(2U));
ConfirmBuckets(d, {{"A", 100U}, {"Undigested", 200U}});
} // namespace test
TEST_F(DigestUnitTest, Kernel) {
// Test kernel stats.
Capture c;
TestUtils::CreateCapture(&c, {
.kmem =
{
.total_bytes = 1000,
.wired_bytes = 10,
.total_heap_bytes = 20,
.mmu_overhead_bytes = 30,
.ipc_bytes = 40,
.other_bytes = 50,
.free_bytes = 100,
},
});
Digester digester({});
Digest d(c, &digester);
EXPECT_EQ(0U, d.undigested_vmos().size());
ConfirmBuckets(d, {{"Kernel", 150U}, {"Free", 100U}});
}
TEST_F(DigestUnitTest, Orphaned) {
// Test kernel stats.
Capture c;
TestUtils::CreateCapture(&c, {
.kmem =
{
.total_bytes = 1000,
.vmo_bytes = 300,
},
.vmos =
{
{.koid = 1, .name = "a1", .committed_bytes = 100},
},
.processes =
{
{.koid = 1, .name = "p1", .vmos = {1}},
},
});
Digester digester({{"A", ".*", "a.*"}});
Digest d(c, &digester);
EXPECT_EQ(0U, d.undigested_vmos().size());
ConfirmBuckets(d, {{"A", 100U}, {"Orphaned", 200U}, {"Kernel", 0U}, {"Free", 0U}});
}
TEST_F(DigestUnitTest, DefaultBuckets) {
// Test kernel stats.
Capture c;
TestUtils::CreateCapture(
&c, {.vmos =
{
{.koid = 1, .name = "uncompressed-bootfs", .committed_bytes = 1},
{.koid = 2, .name = "magma_create_buffer", .committed_bytes = 2},
{.koid = 3, .name = "SysmemAmlogicProtectedPool", .committed_bytes = 3},
{.koid = 4, .name = "SysmemContiguousPool", .committed_bytes = 4},
{.koid = 5, .name = "test", .committed_bytes = 5},
{.koid = 6, .name = "test", .committed_bytes = 6},
{.koid = 7, .name = "test", .committed_bytes = 7},
{.koid = 8, .name = "dart", .committed_bytes = 8},
{.koid = 9, .name = "test", .committed_bytes = 9},
{.koid = 10, .name = "test", .committed_bytes = 10},
{.koid = 11, .name = "test", .committed_bytes = 11},
{.koid = 12, .name = "test", .committed_bytes = 12},
{.koid = 13, .name = "test", .committed_bytes = 13},
{.koid = 14, .name = "test", .committed_bytes = 14},
{.koid = 15, .name = "test", .committed_bytes = 15},
{.koid = 16, .name = "test", .committed_bytes = 16},
{.koid = 17, .name = "test", .committed_bytes = 17},
{.koid = 18, .name = "test", .committed_bytes = 18},
{.koid = 19, .name = "test", .committed_bytes = 19},
{.koid = 20, .name = "test", .committed_bytes = 20},
{.koid = 21, .name = "test", .committed_bytes = 21},
{.koid = 22, .name = "test", .committed_bytes = 22},
{.koid = 23, .name = "blob-123", .committed_bytes = 23, .num_children = 0},
{.koid = 24, .name = "blob-abc", .committed_bytes = 24, .num_children = 1},
{.koid = 25, .name = "Mali JIT memory", .committed_bytes = 25},
{.koid = 26, .name = "MagmaProtectedSysmem", .committed_bytes = 26},
},
.processes = {
{.koid = 1, .name = "bin/bootsvc", .vmos = {1}},
{.koid = 2, .name = "test", .vmos = {2, 25, 26}},
{.koid = 3, .name = "driver_host:pdev:00:00:1b", .vmos = {3, 4}},
{.koid = 4, .name = "fshost.cm", .vmos = {5}},
{.koid = 5, .name = "/boot/bin/minfs", .vmos = {6}},
{.koid = 6, .name = "/boot/bin/blobfs", .vmos = {7, 23, 24}},
{.koid = 7, .name = "io.flutter.product_runner.aot", .vmos = {8, 9}},
{.koid = 10, .name = "kronk.cmx", .vmos = {10}},
{.koid = 8, .name = "web_engine_exe:renderer", .vmos = {11}},
{.koid = 9, .name = "web_engine_exe:gpu", .vmos = {12}},
{.koid = 11, .name = "scenic.cmx", .vmos = {13}},
{.koid = 12, .name = "driver_host:pdev:05:00:f", .vmos = {14}},
{.koid = 13, .name = "netstack.cmx", .vmos = {15}},
{.koid = 14, .name = "pkgfs", .vmos = {16}},
{.koid = 15, .name = "cast_agent.cmx", .vmos = {17}},
{.koid = 16, .name = "archivist.cm", .vmos = {18}},
{.koid = 17, .name = "cobalt.cmx", .vmos = {19}},
{.koid = 18, .name = "audio_core.cmx", .vmos = {20}},
{.koid = 19, .name = "context_provider.cmx", .vmos = {21}},
{.koid = 20, .name = "new", .vmos = {22}},
}});
Digester digester;
Digest d(c, &digester);
EXPECT_EQ(1U, d.undigested_vmos().size());
ConfirmBuckets(d, {
{"Web", 23U},
{"Context", 21U},
{"Audio", 20U},
{"Cobalt", 19U},
{"Archivist", 18U},
{"Cast", 17U},
{"Pkgfs", 16U},
{"Netstack", 15U},
{"Amlogic", 14U},
{"Scenic", 13U},
{"Kronk", 10U},
{"Flutter", 9U},
{"FlutterApps", 8U},
{"Blobfs", 31U},
{"Minfs", 6U},
{"Fshost", 5U},
{"ContiguousPool", 4U},
{"ProtectedPool", 3U},
{"Graphics", 2U + 25U + 26U},
{"ZBI Buffer", 1U},
{"BlobfsInactive", 23U},
{"Undigested", 22U},
});
}
} // namespace test
} // namespace memory