Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
debug_log.test.cpp
Go to the documentation of this file.
2
3#include <cstdint>
4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
6
17
18using ::testing::ElementsAre;
19using ::testing::ReturnRef;
20using ::testing::SizeIs;
21using ::testing::StrictMock;
22
23namespace bb::avm2::simulation {
24
25namespace {
26
27TEST(DebugLogSimulationTest, Basic)
28{
29 StrictMock<MockMemory> memory;
30 std::vector<std::string> log_messages;
31 DebugLogger debug_logger(
32 DebugLogLevel::INFO, 9, [&log_messages](const std::string& message) { log_messages.push_back(message); });
33
34 AztecAddress contract_address = 42;
39
40 std::array<MemoryValue, 5> message_data = {
41 MemoryValue::from<FF>('H'), // 'H'
42 MemoryValue::from<FF>('e'), // 'e'
43 MemoryValue::from<FF>('l'), // 'l'
44 MemoryValue::from<FF>('l'), // 'l'
45 MemoryValue::from<FF>('o'), // 'o'
46 };
47 uint16_t message_size = message_data.size();
48
49 std::array<MemoryValue, 2> fields_data = { MemoryValue::from<FF>(42), MemoryValue::from<FF>(123) };
50 uint32_t fields_size = fields_data.size();
51
52 MemoryValue level = MemoryValue::from<uint8_t>(static_cast<uint8_t>(DebugLogLevel::FATAL));
53
54 MemoryValue fields_size_value = MemoryValue::from<uint32_t>(fields_size);
55
56 EXPECT_CALL(memory, get(level_offset)).WillOnce(ReturnRef(level));
57 EXPECT_CALL(memory, get(fields_size_offset)).WillOnce(ReturnRef(fields_size_value));
58 for (uint32_t i = 0; i < message_size; ++i) {
59 EXPECT_CALL(memory, get(message_offset + i)).WillOnce(ReturnRef(message_data[i]));
60 }
61
62 for (uint32_t i = 0; i < fields_size; ++i) {
63 EXPECT_CALL(memory, get(fields_offset + i)).WillOnce(ReturnRef(fields_data[i]));
64 }
65
66 debug_logger.debug_log(
68
69 EXPECT_THAT(log_messages, ElementsAre("DEBUGLOG(fatal): Hello: [0x2a, 0x7b]"));
70 EXPECT_THAT(debug_logger.dump_logs(), ElementsAre(DebugLog{ contract_address, "fatal", "Hello", { 42, 123 } }));
71}
72
73TEST(DebugLogSimulationTest, MaxMemoryReadsExceeded)
74{
75 StrictMock<MockMemory> memory;
76 std::vector<std::string> log_messages;
77 DebugLogger debug_logger(
78 DebugLogLevel::INFO, 8, [&log_messages](const std::string& message) { log_messages.push_back(message); });
79
80 AztecAddress contract_address = 42;
85 uint16_t message_size = 5;
86 uint32_t fields_size = 2;
87
88 MemoryValue level = MemoryValue::from<uint8_t>(static_cast<uint8_t>(DebugLogLevel::FATAL));
89
90 MemoryValue fields_size_value = MemoryValue::from<uint32_t>(fields_size);
91
92 EXPECT_CALL(memory, get(level_offset)).WillOnce(ReturnRef(level));
93 EXPECT_CALL(memory, get(fields_size_offset)).WillOnce(ReturnRef(fields_size_value));
94
95 EXPECT_THROW(
96 debug_logger.debug_log(
98 std::runtime_error);
99
100 EXPECT_THAT(log_messages, SizeIs(0));
101 EXPECT_THAT(debug_logger.dump_logs(), SizeIs(0));
102}
103
104TEST(DebugLogSimulationTest, CumulativeMaxMemoryReadsExceeded)
105{
106 StrictMock<MockMemory> memory;
107 std::vector<std::string> log_messages;
108 // Each DEBUGLOG below consumes 5 reads (1 level + 1 fields_size + 2 message + 1 field). A budget of 9 admits the
109 // first call but must reject the second, since the limit is cumulative across the whole simulation.
110 DebugLogger debug_logger(
111 DebugLogLevel::INFO, 9, [&log_messages](const std::string& message) { log_messages.push_back(message); });
112
113 AztecAddress contract_address = 42;
118
119 std::array<MemoryValue, 2> message_data = {
120 MemoryValue::from<FF>('H'), // 'H'
121 MemoryValue::from<FF>('i'), // 'i'
122 };
123 uint16_t message_size = message_data.size();
124
125 std::array<MemoryValue, 1> fields_data = { MemoryValue::from<FF>(42) };
126 uint32_t fields_size = fields_data.size();
127
128 MemoryValue level = MemoryValue::from<uint8_t>(static_cast<uint8_t>(DebugLogLevel::FATAL));
129 MemoryValue fields_size_value = MemoryValue::from<uint32_t>(fields_size);
130
131 // Both calls read the level and fields_size; only the first call gets far enough to read the message and fields
132 // (the second throws on the cumulative bounds check before any further reads).
133 EXPECT_CALL(memory, get(level_offset)).Times(2).WillRepeatedly(ReturnRef(level));
134 EXPECT_CALL(memory, get(fields_size_offset)).Times(2).WillRepeatedly(ReturnRef(fields_size_value));
135 for (uint32_t i = 0; i < message_size; ++i) {
136 EXPECT_CALL(memory, get(message_offset + i)).WillOnce(ReturnRef(message_data[i]));
137 }
138 for (uint32_t i = 0; i < fields_size; ++i) {
139 EXPECT_CALL(memory, get(fields_offset + i)).WillOnce(ReturnRef(fields_data[i]));
140 }
141
142 // First call is within budget (5 <= 9) and succeeds.
143 debug_logger.debug_log(
145
146 // Second call would push the cumulative total to 10 > 9 and must throw.
147 EXPECT_THROW(
148 debug_logger.debug_log(
150 std::runtime_error);
151
152 // Only the first log was recorded.
153 EXPECT_THAT(log_messages, ElementsAre("DEBUGLOG(fatal): Hi: [0x2a]"));
154 EXPECT_THAT(debug_logger.dump_logs(), SizeIs(1));
155}
156
157TEST(DebugLogSimulationTest, InvalidLevel)
158{
159 StrictMock<MockMemory> memory;
160 std::vector<std::string> log_messages;
161 DebugLogger debug_logger(
162 DebugLogLevel::INFO, 9, [&log_messages](const std::string& message) { log_messages.push_back(message); });
163
164 AztecAddress contract_address = 42;
169
170 std::array<MemoryValue, 5> message_data = {
171 MemoryValue::from<FF>('H'), // 'H'
172 MemoryValue::from<FF>('e'), // 'e'
173 MemoryValue::from<FF>('l'), // 'l'
174 MemoryValue::from<FF>('l'), // 'l'
175 MemoryValue::from<FF>('o'), // 'o'
176 };
177 uint16_t message_size = message_data.size();
178
179 std::array<MemoryValue, 2> fields_data = { MemoryValue::from<FF>(42), MemoryValue::from<FF>(123) };
180 uint32_t fields_size = fields_data.size();
181
182 MemoryValue level = MemoryValue::from<uint8_t>(static_cast<uint8_t>(42));
183
184 MemoryValue fields_size_value = MemoryValue::from<uint32_t>(fields_size);
185
186 EXPECT_CALL(memory, get(level_offset)).WillOnce(ReturnRef(level));
187 EXPECT_CALL(memory, get(fields_size_offset)).WillOnce(ReturnRef(fields_size_value));
188 for (uint32_t i = 0; i < message_size; ++i) {
189 EXPECT_CALL(memory, get(message_offset + i)).WillOnce(ReturnRef(message_data[i]));
190 }
191
192 for (uint32_t i = 0; i < fields_size; ++i) {
193 EXPECT_CALL(memory, get(fields_offset + i)).WillOnce(ReturnRef(fields_data[i]));
194 }
195
196 EXPECT_THROW(
197 debug_logger.debug_log(
199 std::runtime_error);
200
201 EXPECT_THAT(log_messages, SizeIs(0));
202 EXPECT_THAT(debug_logger.dump_logs(), SizeIs(0));
203}
204
205TEST(DebugLogSimulationTest, LogLevel)
206{
207 StrictMock<MockMemory> memory;
208 std::vector<std::string> log_messages;
209 DebugLogger debug_logger(
210 DebugLogLevel::INFO, 9, [&log_messages](const std::string& message) { log_messages.push_back(message); });
211
212 AztecAddress contract_address = 42;
217
218 std::array<MemoryValue, 1> message_data = {
219 MemoryValue::from<FF>('A'), // 'A'
220 };
221 uint16_t message_size = message_data.size();
222
223 std::array<MemoryValue, 1> fields_data = { MemoryValue::from<FF>(42) };
224 uint32_t fields_size = fields_data.size();
225
226 MemoryValue level = MemoryValue::from<uint8_t>(static_cast<uint8_t>(DebugLogLevel::VERBOSE));
227
228 MemoryValue fields_size_value = MemoryValue::from<uint32_t>(fields_size);
229
230 EXPECT_CALL(memory, get(level_offset)).WillOnce(ReturnRef(level));
231 EXPECT_CALL(memory, get(fields_size_offset)).WillOnce(ReturnRef(fields_size_value));
232 for (uint32_t i = 0; i < message_size; ++i) {
233 EXPECT_CALL(memory, get(message_offset + i)).WillOnce(ReturnRef(message_data[i]));
234 }
235
236 for (uint32_t i = 0; i < fields_size; ++i) {
237 EXPECT_CALL(memory, get(fields_offset + i)).WillOnce(ReturnRef(fields_data[i]));
238 }
239
240 debug_logger.debug_log(
242
243 // Not logged to stdout
244 EXPECT_THAT(log_messages, SizeIs(0));
245 // But recorded in the debug logs vector
246 EXPECT_THAT(debug_logger.dump_logs(), ElementsAre(DebugLog{ contract_address, "verbose", "A", { 42 } }));
247}
248
249} // namespace
250
251} // namespace bb::avm2::simulation
LogLevel
Definition log.hpp:63
AVM range check gadget for witness generation.
TaggedValue MemoryValue
uint32_t MemoryAddress
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory