1 //===-- MemoryTreeTests.cpp -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "support/MemoryTree.h" 10 #include "support/TestTracer.h" 11 #include "support/Trace.h" 12 #include "llvm/Support/Allocator.h" 13 #include "gmock/gmock.h" 14 #include "gtest/gtest.h" 15 #include <ostream> 16 17 namespace clang { 18 namespace clangd { 19 namespace { 20 using testing::Contains; 21 using testing::ElementsAre; 22 using testing::IsEmpty; 23 using testing::UnorderedElementsAre; 24 25 MATCHER_P2(WithNameAndSize, Name, Size, "") { 26 return arg.first == Name && 27 arg.getSecond().total() == static_cast<size_t>(Size); 28 } 29 30 TEST(MemoryTree, Basics) { 31 MemoryTree MT; 32 EXPECT_EQ(MT.total(), 0U); 33 EXPECT_THAT(MT.children(), IsEmpty()); 34 35 MT.addUsage(42); 36 EXPECT_EQ(MT.total(), 42U); 37 EXPECT_THAT(MT.children(), IsEmpty()); 38 39 MT.child("leaf").addUsage(1); 40 EXPECT_EQ(MT.total(), 43U); 41 EXPECT_THAT(MT.children(), UnorderedElementsAre(WithNameAndSize("leaf", 1))); 42 43 // child should be idempotent. 44 MT.child("leaf").addUsage(1); 45 EXPECT_EQ(MT.total(), 44U); 46 EXPECT_THAT(MT.children(), UnorderedElementsAre(WithNameAndSize("leaf", 2))); 47 } 48 49 TEST(MemoryTree, DetailedNodesWithoutDetails) { 50 MemoryTree MT; 51 MT.detail("should_be_ignored").addUsage(2); 52 EXPECT_THAT(MT.children(), IsEmpty()); 53 EXPECT_EQ(MT.total(), 2U); 54 55 // Make sure children from details are merged. 56 MT.detail("first_detail").child("leaf").addUsage(1); 57 MT.detail("second_detail").child("leaf").addUsage(1); 58 EXPECT_THAT(MT.children(), Contains(WithNameAndSize("leaf", 2))); 59 } 60 61 TEST(MemoryTree, DetailedNodesWithDetails) { 62 llvm::BumpPtrAllocator Alloc; 63 MemoryTree MT(&Alloc); 64 65 { 66 auto &Detail = MT.detail("first_detail"); 67 Detail.child("leaf").addUsage(1); 68 EXPECT_THAT(MT.children(), Contains(WithNameAndSize("first_detail", 1))); 69 EXPECT_THAT(Detail.children(), Contains(WithNameAndSize("leaf", 1))); 70 } 71 72 { 73 auto &Detail = MT.detail("second_detail"); 74 Detail.child("leaf").addUsage(1); 75 EXPECT_THAT(MT.children(), Contains(WithNameAndSize("second_detail", 1))); 76 EXPECT_THAT(Detail.children(), Contains(WithNameAndSize("leaf", 1))); 77 } 78 } 79 80 TEST(MemoryTree, Record) { 81 trace::TestTracer Tracer; 82 static constexpr llvm::StringLiteral MetricName = "memory_usage"; 83 static constexpr trace::Metric OutMetric(MetricName, trace::Metric::Value, 84 "component_name"); 85 auto AddNodes = [](MemoryTree Root) { 86 Root.child("leaf").addUsage(1); 87 88 { 89 auto &Detail = Root.detail("detail"); 90 Detail.addUsage(1); 91 Detail.child("leaf").addUsage(1); 92 auto &Child = Detail.child("child"); 93 Child.addUsage(1); 94 Child.child("leaf").addUsage(1); 95 } 96 97 { 98 auto &Child = Root.child("child"); 99 Child.addUsage(1); 100 Child.child("leaf").addUsage(1); 101 } 102 return Root; 103 }; 104 105 llvm::BumpPtrAllocator Alloc; 106 record(AddNodes(MemoryTree(&Alloc)), "root", OutMetric); 107 EXPECT_THAT(Tracer.takeMetric(MetricName, "root"), ElementsAre(7)); 108 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.leaf"), ElementsAre(1)); 109 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.detail"), ElementsAre(4)); 110 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.detail.leaf"), 111 ElementsAre(1)); 112 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.detail.child"), 113 ElementsAre(2)); 114 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.detail.child.leaf"), 115 ElementsAre(1)); 116 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.child"), ElementsAre(2)); 117 EXPECT_THAT(Tracer.takeMetric(MetricName, "root.child.leaf"), ElementsAre(1)); 118 } 119 } // namespace 120 } // namespace clangd 121 } // namespace clang 122