Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2025 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include <gmock/gmock.h> | ||
4 | #include <gtest/gtest.h> | ||
5 | |||
6 | #include <ast/ASTNodes.h> | ||
7 | #include <util/BlockAllocator.h> | ||
8 | #include <util/CodeLoc.h> | ||
9 | #include <util/Memory.h> | ||
10 | |||
11 | namespace spice::testing { | ||
12 | |||
13 | using namespace spice::compiler; | ||
14 | |||
15 | static size_t destructedDummyNodes = 0; | ||
16 | |||
17 | class DummyNode final : public ASTNode { | ||
18 | // Constructors | ||
19 | using ASTNode::ASTNode; | ||
20 | |||
21 | // Destructors | ||
22 | 101008 | ~DummyNode() override { destructedDummyNodes++; } | |
23 | |||
24 | // Visitor methods | ||
25 | − | std::any accept(AbstractASTVisitor *visitor) override { return {}; } // LCOV_EXCL_LINE | |
26 | − | std::any accept(ParallelizableASTVisitor *visitor) const override { return {}; } // LCOV_EXCL_LINE | |
27 | |||
28 | // Other methods | ||
29 | ✗ | GET_CHILDREN(); | |
30 | }; | ||
31 | static constexpr size_t DUMMY_NODE_SIZE = sizeof(DummyNode); | ||
32 | static_assert(DUMMY_NODE_SIZE == 48, "DummyNode size has changed. Update test accordingly."); | ||
33 | |||
34 | class MockMemoryManager final : public MemoryManager { | ||
35 | public: | ||
36 |
2/4✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 11 not taken.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 9 not taken.
|
7 | MOCK_METHOD(byte *, allocate, (size_t size), (const override)); |
37 |
2/4✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 11 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 9 not taken.
|
5 | MOCK_METHOD(void, deallocate, (byte * ptr), (const override)); |
38 | }; | ||
39 | |||
40 | 4 | TEST(BlockAllocatorTest, TestBlockAllocatorLarge) { | |
41 | 1 | destructedDummyNodes = 0; // Reset destruction counter | |
42 | static constexpr size_t NODE_COUNT = 100'000; // 100.000 * 48 bytes = 4.8 MB | ||
43 | |||
44 | { | ||
45 | // Create allocator, that can hold 5 nodes per block | ||
46 | 1 | constexpr DefaultMemoryManager memoryManager; | |
47 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 174 not taken.
|
1 | BlockAllocator<ASTNode> alloc(memoryManager, DUMMY_NODE_SIZE * 5); |
48 | |||
49 | // Allocate nodes | ||
50 | 1 | std::vector<ASTNode *> nodes; | |
51 |
2/2✓ Branch 57 → 4 taken 100000 times.
✓ Branch 57 → 58 taken 1 time.
|
100001 | for (size_t i = 0; i < NODE_COUNT; i++) { |
52 |
2/4✓ Branch 4 → 5 taken 100000 times.
✗ Branch 4 → 116 not taken.
✓ Branch 5 → 6 taken 100000 times.
✗ Branch 5 → 116 not taken.
|
100000 | auto node = alloc.allocate<DummyNode>(CodeLoc(i, 1)); |
53 |
3/12✓ Branch 6 → 7 taken 100000 times.
✗ Branch 6 → 117 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 16 taken 100000 times.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 123 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 120 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 118 not taken.
✓ Branch 18 → 19 taken 100000 times.
✗ Branch 18 → 21 not taken.
|
100000 | ASSERT_NE(nullptr, node); |
54 |
1/2✓ Branch 20 → 22 taken 100000 times.
✗ Branch 20 → 127 not taken.
|
100000 | nodes.push_back(node); |
55 |
4/14✓ Branch 22 → 23 taken 100000 times.
✗ Branch 22 → 136 not taken.
✓ Branch 23 → 24 taken 100000 times.
✗ Branch 23 → 136 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 33 taken 100000 times.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 133 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 130 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 128 not taken.
✓ Branch 35 → 36 taken 100000 times.
✗ Branch 35 → 38 not taken.
|
100000 | ASSERT_EQ(i, nodes.at(i)->codeLoc.line); |
56 |
4/14✓ Branch 37 → 39 taken 100000 times.
✗ Branch 37 → 146 not taken.
✓ Branch 39 → 40 taken 100000 times.
✗ Branch 39 → 137 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 49 taken 100000 times.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 143 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 140 not taken.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 138 not taken.
✓ Branch 51 → 52 taken 100000 times.
✗ Branch 51 → 54 not taken.
|
100000 | ASSERT_EQ(1, nodes.at(i)->codeLoc.col); |
57 | } | ||
58 | |||
59 | // Check if stats are correct | ||
60 |
3/12✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 149 not taken.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 69 taken 1 time.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 155 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 152 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 150 not taken.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 75 not taken.
|
1 | ASSERT_EQ(NODE_COUNT, alloc.getAllocationCount()); |
61 |
3/12✓ Branch 74 → 76 taken 1 time.
✗ Branch 74 → 159 not taken.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 85 taken 1 time.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 166 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 163 not taken.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 161 not taken.
✓ Branch 87 → 88 taken 1 time.
✗ Branch 87 → 90 not taken.
|
1 | ASSERT_EQ(6'000'000, alloc.getTotalAllocatedSize()); |
62 | |||
63 | // Block Allocator gets destructed here and with that, all allocated nodes should be destructed | ||
64 |
2/4✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 94 not taken.
✓ Branch 96 → 97 taken 1 time.
✗ Branch 96 → 99 not taken.
|
1 | } |
65 | |||
66 |
3/12✓ Branch 98 → 100 taken 1 time.
✗ Branch 98 → 183 not taken.
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 109 taken 1 time.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 180 not taken.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 177 not taken.
✗ Branch 105 → 106 not taken.
✗ Branch 105 → 175 not taken.
✓ Branch 111 → 112 taken 1 time.
✗ Branch 111 → 114 not taken.
|
1 | ASSERT_EQ(NODE_COUNT, destructedDummyNodes); |
67 | } | ||
68 | |||
69 | 4 | TEST(BlockAllocatorTest, TestBlockAllocatorUnevenBlockSize) { | |
70 | 1 | destructedDummyNodes = 0; // Reset destruction counter | |
71 | static constexpr size_t NODE_COUNT = 1'000; // 1.000 * 48 bytes = 48 KB | ||
72 | |||
73 | { | ||
74 | // Create allocator, that can hold 4.5 nodes per block | ||
75 | 1 | constexpr DefaultMemoryManager memoryManager; | |
76 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 174 not taken.
|
1 | BlockAllocator<ASTNode> alloc(memoryManager, DUMMY_NODE_SIZE * 4.5); |
77 | |||
78 | // Allocate nodes | ||
79 | 1 | std::vector<ASTNode *> nodes; | |
80 |
2/2✓ Branch 57 → 4 taken 1000 times.
✓ Branch 57 → 58 taken 1 time.
|
1001 | for (size_t i = 0; i < NODE_COUNT; i++) { |
81 |
2/4✓ Branch 4 → 5 taken 1000 times.
✗ Branch 4 → 116 not taken.
✓ Branch 5 → 6 taken 1000 times.
✗ Branch 5 → 116 not taken.
|
1000 | auto node = alloc.allocate<DummyNode>(CodeLoc(i, 1)); |
82 |
3/12✓ Branch 6 → 7 taken 1000 times.
✗ Branch 6 → 117 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 16 taken 1000 times.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 123 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 120 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 118 not taken.
✓ Branch 18 → 19 taken 1000 times.
✗ Branch 18 → 21 not taken.
|
1000 | ASSERT_NE(nullptr, node); |
83 |
1/2✓ Branch 20 → 22 taken 1000 times.
✗ Branch 20 → 127 not taken.
|
1000 | nodes.push_back(node); |
84 |
4/14✓ Branch 22 → 23 taken 1000 times.
✗ Branch 22 → 136 not taken.
✓ Branch 23 → 24 taken 1000 times.
✗ Branch 23 → 136 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 33 taken 1000 times.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 133 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 130 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 128 not taken.
✓ Branch 35 → 36 taken 1000 times.
✗ Branch 35 → 38 not taken.
|
1000 | ASSERT_EQ(i, nodes.at(i)->codeLoc.line); |
85 |
4/14✓ Branch 37 → 39 taken 1000 times.
✗ Branch 37 → 146 not taken.
✓ Branch 39 → 40 taken 1000 times.
✗ Branch 39 → 137 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 49 taken 1000 times.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 143 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 140 not taken.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 138 not taken.
✓ Branch 51 → 52 taken 1000 times.
✗ Branch 51 → 54 not taken.
|
1000 | ASSERT_EQ(1, nodes.at(i)->codeLoc.col); |
86 | } | ||
87 | |||
88 | // Check if stats are correct | ||
89 |
3/12✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 149 not taken.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 69 taken 1 time.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 155 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 152 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 150 not taken.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 75 not taken.
|
1 | ASSERT_EQ(NODE_COUNT, alloc.getAllocationCount()); |
90 |
3/12✓ Branch 74 → 76 taken 1 time.
✗ Branch 74 → 159 not taken.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 85 taken 1 time.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 166 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 163 not taken.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 161 not taken.
✓ Branch 87 → 88 taken 1 time.
✗ Branch 87 → 90 not taken.
|
1 | ASSERT_EQ(54'000, alloc.getTotalAllocatedSize()); |
91 | |||
92 | // Block Allocator gets destructed here and with that, all allocated nodes should be destructed | ||
93 |
2/4✓ Branch 92 → 93 taken 1 time.
✗ Branch 92 → 94 not taken.
✓ Branch 96 → 97 taken 1 time.
✗ Branch 96 → 99 not taken.
|
1 | } |
94 | |||
95 |
3/12✓ Branch 98 → 100 taken 1 time.
✗ Branch 98 → 183 not taken.
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 109 taken 1 time.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 180 not taken.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 177 not taken.
✗ Branch 105 → 106 not taken.
✗ Branch 105 → 175 not taken.
✓ Branch 111 → 112 taken 1 time.
✗ Branch 111 → 114 not taken.
|
1 | ASSERT_EQ(NODE_COUNT, destructedDummyNodes); |
96 | } | ||
97 | |||
98 | 4 | TEST(BlockAllocatorTest, TestBlockAllocatorOOM) { | |
99 | 1 | destructedDummyNodes = 0; // Reset destruction counter | |
100 | static constexpr size_t NODE_COUNT = 10; // 10 * 48 bytes = 0.48 KB | ||
101 | |||
102 | // Prepare mock methods | ||
103 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 278 not taken.
|
1 | MockMemoryManager mockMemoryManager; |
104 | |||
105 | // Make sure, that the memory manager returns nullptr when trying to allocate the fifth block | ||
106 |
1/2✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 276 not taken.
|
1 | ::testing::InSequence s; |
107 | 4 | auto mallocCallback = [](size_t size) { return static_cast<byte *>(malloc(size)); }; | |
108 |
7/14✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 142 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 140 not taken.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 137 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 137 not taken.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 137 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 136 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 134 not taken.
|
1 | EXPECT_CALL(mockMemoryManager, allocate(::testing::_)).Times(4).WillRepeatedly(mallocCallback); |
109 |
8/16✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 153 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 151 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 148 not taken.
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 148 not taken.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 148 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 146 not taken.
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 146 not taken.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 144 not taken.
|
1 | EXPECT_CALL(mockMemoryManager, allocate(::testing::_)).Times(1).WillOnce(::testing::Return(nullptr)); |
110 |
7/14✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 164 not taken.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 162 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 159 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 159 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 159 not taken.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 157 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 155 not taken.
|
1 | EXPECT_CALL(mockMemoryManager, deallocate(::testing::_)).Times(4).WillRepeatedly(::testing::Invoke(free)); |
111 | |||
112 | { | ||
113 | // Create allocator, that can hold 2 nodes per block | ||
114 |
1/2✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 263 not taken.
|
1 | BlockAllocator<ASTNode> alloc(mockMemoryManager, DUMMY_NODE_SIZE * 2.25); |
115 | |||
116 | try { | ||
117 | // Allocate nodes | ||
118 | 1 | std::vector<ASTNode *> nodes; | |
119 |
1/2✓ Branch 94 → 41 taken 9 times.
✗ Branch 94 → 95 not taken.
|
9 | for (size_t i = 0; i < NODE_COUNT; i++) { |
120 |
3/4✓ Branch 41 → 42 taken 9 times.
✗ Branch 41 → 166 not taken.
✓ Branch 42 → 43 taken 8 times.
✓ Branch 42 → 166 taken 1 time.
|
9 | auto node = alloc.allocate<DummyNode>(CodeLoc(i, 1)); |
121 |
3/12✓ Branch 43 → 44 taken 8 times.
✗ Branch 43 → 167 not taken.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 53 taken 8 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 173 not taken.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 170 not taken.
✗ Branch 49 → 50 not taken.
✗ Branch 49 → 168 not taken.
✓ Branch 55 → 56 taken 8 times.
✗ Branch 55 → 58 not taken.
|
8 | ASSERT_NE(nullptr, node); |
122 |
1/2✓ Branch 57 → 59 taken 8 times.
✗ Branch 57 → 177 not taken.
|
8 | nodes.push_back(node); |
123 |
4/14✓ Branch 59 → 60 taken 8 times.
✗ Branch 59 → 186 not taken.
✓ Branch 60 → 61 taken 8 times.
✗ Branch 60 → 186 not taken.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 70 taken 8 times.
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 183 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 180 not taken.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 178 not taken.
✓ Branch 72 → 73 taken 8 times.
✗ Branch 72 → 75 not taken.
|
8 | ASSERT_EQ(i, nodes.at(i)->codeLoc.line); |
124 |
4/14✓ Branch 74 → 76 taken 8 times.
✗ Branch 74 → 196 not taken.
✓ Branch 76 → 77 taken 8 times.
✗ Branch 76 → 187 not taken.
✗ Branch 78 → 79 not taken.
✓ Branch 78 → 86 taken 8 times.
✗ Branch 79 → 80 not taken.
✗ Branch 79 → 193 not taken.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 190 not taken.
✗ Branch 82 → 83 not taken.
✗ Branch 82 → 188 not taken.
✓ Branch 88 → 89 taken 8 times.
✗ Branch 88 → 91 not taken.
|
8 | ASSERT_EQ(1, nodes.at(i)->codeLoc.col); |
125 | } | ||
126 | − | FAIL(); // LCOV_EXCL_LINE - Should not reach this point | |
127 |
1/2✗ Branch 208 → 209 not taken.
✓ Branch 208 → 210 taken 1 time.
|
2 | } catch (CompilerError &ce) { |
128 |
1/2✓ Branch 211 → 212 taken 1 time.
✗ Branch 211 → 258 not taken.
|
1 | std::stringstream ss; |
129 |
1/2✓ Branch 212 → 213 taken 1 time.
✗ Branch 212 → 256 not taken.
|
1 | ss << "[Error|Compiler]:\n"; |
130 |
1/2✓ Branch 213 → 214 taken 1 time.
✗ Branch 213 → 256 not taken.
|
1 | ss << "An out of memory error occurred: Could not allocate memory for BlockAllocator. Already allocated 4 blocks."; |
131 |
4/14✓ Branch 215 → 216 taken 1 time.
✗ Branch 215 → 245 not taken.
✓ Branch 216 → 217 taken 1 time.
✗ Branch 216 → 243 not taken.
✗ Branch 219 → 220 not taken.
✓ Branch 219 → 227 taken 1 time.
✗ Branch 220 → 221 not taken.
✗ Branch 220 → 252 not taken.
✗ Branch 222 → 223 not taken.
✗ Branch 222 → 249 not taken.
✗ Branch 223 → 224 not taken.
✗ Branch 223 → 247 not taken.
✓ Branch 229 → 230 taken 1 time.
✗ Branch 229 → 232 not taken.
|
1 | ASSERT_EQ(ss.str(), ce.what()); |
132 |
2/4✓ Branch 234 → 235 taken 1 time.
✗ Branch 234 → 237 not taken.
✓ Branch 239 → 240 taken 1 time.
✗ Branch 239 → 241 not taken.
|
2 | } |
133 | |||
134 | // Block Allocator gets destructed here and with that, all allocated nodes should be destructed | ||
135 |
1/2✓ Branch 104 → 105 taken 1 time.
✗ Branch 104 → 107 not taken.
|
1 | } |
136 | |||
137 |
3/12✓ Branch 106 → 108 taken 1 time.
✗ Branch 106 → 264 not taken.
✗ Branch 109 → 110 not taken.
✓ Branch 109 → 117 taken 1 time.
✗ Branch 110 → 111 not taken.
✗ Branch 110 → 270 not taken.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 267 not taken.
✗ Branch 113 → 114 not taken.
✗ Branch 113 → 265 not taken.
✓ Branch 119 → 120 taken 1 time.
✗ Branch 119 → 122 not taken.
|
1 | ASSERT_EQ(8, destructedDummyNodes); // Only 8 blocks were constructed until the OOM error occurred |
138 |
1/2✓ Branch 121 → 123 taken 1 time.
✗ Branch 121 → 274 not taken.
|
1 | ::testing::Mock::VerifyAndClearExpectations(&mockMemoryManager); |
139 |
2/4✓ Branch 125 → 126 taken 1 time.
✗ Branch 125 → 127 not taken.
✓ Branch 129 → 130 taken 1 time.
✗ Branch 129 → 132 not taken.
|
1 | } |
140 | |||
141 | } // namespace spice::testing | ||
142 |