Skip to content

Commit d79efe6

Browse files
convert log-only test validations to assertive expect() checks across 10 test files
Replace LUISA_ERROR/LUISA_INFO pass/fail patterns with boost.ut expect() assertions so test failures are CI-detectable. Changes: - test_logging: add 4 custom-sink assertion tests - test_nested_callable: check() and state logs to expect() - test_callable: enable commented assertion with tolerance - test_soa, test_soa_simple, test_soa_subview: LUISA_ERROR to expect() - test_decoupled_look_back: separate expect() for exclusive/inclusive - test_warp: LUISA_ERROR to expect(all_correct) - test_softmax: add expect(sum ≈ 1/N) for uniform input - test_byte_buffer: add readback verification expect() for both paths
1 parent 743f1f1 commit d79efe6

File tree

10 files changed

+220
-107
lines changed

10 files changed

+220
-107
lines changed

src/tests/unit/core/test_logging.cpp

Lines changed: 180 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,229 @@
1-
// Test for logging functionality.
2-
// This test verifies that the logging system works correctly with different
3-
// log levels, formats, and macros.
4-
51
#include "ut/ut.hpp"
62
#include <luisa/core/logging.h>
73
#include <luisa/core/stl/string.h>
84
#include <luisa/core/stl/vector.h>
5+
#include <mutex>
96

107
using namespace boost::ut;
118
using namespace boost::ut::literals;
129

13-
// Simple test to verify logging doesn't crash and produces output
10+
#ifndef LUISA_CUSTOM_LOGGER
11+
12+
struct CapturedMessage {
13+
luisa::string level;
14+
luisa::string message;
15+
};
16+
17+
static inline const auto _reg_logging_custom_sink = [] {
18+
"logging_custom_sink_captures_messages"_test = [] {
19+
std::mutex mtx;
20+
luisa::vector<CapturedMessage> captured;
21+
22+
auto sink = luisa::detail::create_sink_with_callback(
23+
[&](const char *level, const char *message) {
24+
std::lock_guard lock{mtx};
25+
captured.push_back({luisa::string{level}, luisa::string{message}});
26+
});
27+
28+
auto &logger = luisa::detail::default_logger();
29+
auto original_sinks = logger.sinks();
30+
logger.sinks().clear();
31+
logger.sinks().push_back(sink);
32+
luisa::log_level_verbose();
33+
34+
luisa::log_verbose("verbose_msg_42");
35+
luisa::log_info("info_msg_100");
36+
luisa::log_warning("warning_msg_xyz");
37+
luisa::log_flush();
38+
39+
logger.sinks() = original_sinks;
40+
luisa::log_level_verbose();
41+
42+
expect(captured.size() >= 3u) << "expected at least 3 captured messages, got " << captured.size();
43+
44+
bool found_verbose = false, found_info = false, found_warning = false;
45+
for (auto &cm : captured) {
46+
if (cm.message.find("verbose_msg_42") != luisa::string::npos) found_verbose = true;
47+
if (cm.message.find("info_msg_100") != luisa::string::npos) found_info = true;
48+
if (cm.message.find("warning_msg_xyz") != luisa::string::npos) found_warning = true;
49+
}
50+
expect(found_verbose) << "custom sink should capture verbose message";
51+
expect(found_info) << "custom sink should capture info message";
52+
expect(found_warning) << "custom sink should capture warning message";
53+
};
54+
return 0;
55+
}();
56+
57+
static inline const auto _reg_logging_level_filtering = [] {
58+
"logging_level_filtering_via_sink"_test = [] {
59+
std::mutex mtx;
60+
luisa::vector<CapturedMessage> captured;
61+
62+
auto sink = luisa::detail::create_sink_with_callback(
63+
[&](const char *level, const char *message) {
64+
std::lock_guard lock{mtx};
65+
captured.push_back({luisa::string{level}, luisa::string{message}});
66+
});
67+
68+
auto &logger = luisa::detail::default_logger();
69+
auto original_sinks = logger.sinks();
70+
logger.sinks().clear();
71+
logger.sinks().push_back(sink);
72+
73+
luisa::log_level_warning();
74+
captured.clear();
75+
76+
luisa::log_verbose("should_be_filtered_verbose");
77+
luisa::log_info("should_be_filtered_info");
78+
luisa::log_warning("should_appear_warning");
79+
luisa::log_flush();
80+
81+
logger.sinks() = original_sinks;
82+
luisa::log_level_verbose();
83+
84+
bool found_filtered_verbose = false;
85+
bool found_filtered_info = false;
86+
bool found_warning = false;
87+
for (auto &cm : captured) {
88+
if (cm.message.find("should_be_filtered_verbose") != luisa::string::npos) found_filtered_verbose = true;
89+
if (cm.message.find("should_be_filtered_info") != luisa::string::npos) found_filtered_info = true;
90+
if (cm.message.find("should_appear_warning") != luisa::string::npos) found_warning = true;
91+
}
92+
expect(!found_filtered_verbose) << "verbose should be filtered at warning level";
93+
expect(!found_filtered_info) << "info should be filtered at warning level";
94+
expect(found_warning) << "warning should pass at warning level";
95+
};
96+
return 0;
97+
}();
98+
99+
static inline const auto _reg_logging_add_sink = [] {
100+
"logging_add_sink_preserves_existing"_test = [] {
101+
std::mutex mtx;
102+
luisa::vector<CapturedMessage> captured;
103+
104+
auto sink = luisa::detail::create_sink_with_callback(
105+
[&](const char *level, const char *message) {
106+
std::lock_guard lock{mtx};
107+
captured.push_back({luisa::string{level}, luisa::string{message}});
108+
});
109+
110+
luisa::detail::default_logger_add_sink(sink);
111+
luisa::log_level_verbose();
112+
113+
luisa::log_info("add_sink_test_msg");
114+
luisa::log_flush();
115+
116+
auto &sinks = luisa::detail::default_logger().sinks();
117+
sinks.erase(std::remove(sinks.begin(), sinks.end(), sink), sinks.end());
118+
119+
bool found = false;
120+
for (auto &cm : captured) {
121+
if (cm.message.find("add_sink_test_msg") != luisa::string::npos) found = true;
122+
}
123+
expect(found) << "added sink should capture messages alongside default sink";
124+
};
125+
return 0;
126+
}();
127+
128+
static inline const auto _reg_logging_formatted_args = [] {
129+
"logging_formatted_args_in_sink"_test = [] {
130+
std::mutex mtx;
131+
luisa::vector<CapturedMessage> captured;
132+
133+
auto sink = luisa::detail::create_sink_with_callback(
134+
[&](const char *level, const char *message) {
135+
std::lock_guard lock{mtx};
136+
captured.push_back({luisa::string{level}, luisa::string{message}});
137+
});
138+
139+
auto &logger = luisa::detail::default_logger();
140+
auto original_sinks = logger.sinks();
141+
logger.sinks().clear();
142+
logger.sinks().push_back(sink);
143+
luisa::log_level_verbose();
144+
145+
luisa::log_info("answer is {}", 42);
146+
luisa::log_info("pi is {:.2f}", 3.14159);
147+
luisa::log_info("bool={}, str={}", true, "hello");
148+
luisa::log_flush();
149+
150+
logger.sinks() = original_sinks;
151+
luisa::log_level_verbose();
152+
153+
bool found_42 = false, found_pi = false, found_bool = false;
154+
for (auto &cm : captured) {
155+
if (cm.message.find("answer is 42") != luisa::string::npos) found_42 = true;
156+
if (cm.message.find("pi is 3.14") != luisa::string::npos) found_pi = true;
157+
if (cm.message.find("bool=true") != luisa::string::npos) found_bool = true;
158+
}
159+
expect(found_42) << "formatted int arg should appear in sink";
160+
expect(found_pi) << "formatted float arg should appear in sink";
161+
expect(found_bool) << "formatted bool/string args should appear in sink";
162+
};
163+
return 0;
164+
}();
165+
166+
#endif
167+
14168
static inline const auto _luisa_reg_logging_basic_functionality = [] {
15-
boost::ut::detail::test{"test", "logging basic functionality"} = [] {
16-
// Test basic log functions with simple messages
169+
"logging_basic_no_crash"_test = [] {
170+
luisa::log_level_verbose();
17171
luisa::log_verbose("Verbose message from test");
18172
luisa::log_info("Info message from test");
19173
luisa::log_warning("Warning message from test");
20-
21-
// Test formatted log messages
22174
luisa::log_verbose("Verbose with args: {}, {}", 42, 3.14);
23175
luisa::log_info("Info with args: {}, {}", "test_string", true);
24176
luisa::log_warning("Warning with args: {}, {}", 'a', 123u);
25-
26-
// Test flush
27177
luisa::log_flush();
178+
expect(true) << "basic logging calls completed without crash";
28179
};
29180
return 0;
30181
}();
31182

32183
static inline const auto _luisa_reg_logging_macros = [] {
33-
boost::ut::detail::test{"test", "logging macros"} = [] {
34-
// Test all logging macros
184+
"logging_macros_no_crash"_test = [] {
185+
luisa::log_level_verbose();
35186
LUISA_VERBOSE("Macro verbose message");
36187
LUISA_INFO("Macro info message");
37188
LUISA_WARNING("Macro warning message");
38-
39-
// Test macros with format arguments
40189
LUISA_VERBOSE("Verbose macro: {}, {}", 1, 2);
41190
LUISA_INFO("Info macro: {}, {}, {}", "a", "b", "c");
42191
LUISA_WARNING("Warning macro: value = {}", 3.14159);
192+
expect(true) << "logging macros completed without crash";
43193
};
44194
return 0;
45195
}();
46196

47197
static inline const auto _luisa_reg_logging_with_location_macros = [] {
48-
boost::ut::detail::test{"test", "logging with location macros"} = [] {
49-
// Test location macros
198+
"logging_location_macros_no_crash"_test = [] {
199+
luisa::log_level_verbose();
50200
LUISA_VERBOSE_WITH_LOCATION("Verbose with location: {}", 100);
51201
LUISA_INFO_WITH_LOCATION("Info with location: {}", 200);
52202
LUISA_WARNING_WITH_LOCATION("Warning with location: {}", 300);
203+
expect(true) << "location macros completed without crash";
53204
};
54205
return 0;
55206
}();
56207

57-
static inline const auto _luisa_reg_logging_log_level_changes = [] {
58-
boost::ut::detail::test{"test", "logging log level changes"} = [] {
59-
// Save current log level (we can't query it, but we can test setting doesn't crash)
60-
61-
// Test all log level functions
208+
static inline const auto _luisa_reg_logging_log_level_transitions = [] {
209+
"logging_level_transitions_no_crash"_test = [] {
62210
luisa::log_level_verbose();
63-
LUISA_VERBOSE("This verbose should be visible after log_level_verbose()");
64-
65211
luisa::log_level_info();
66-
LUISA_VERBOSE("This verbose should be hidden after log_level_info()");
67-
LUISA_INFO("This info should be visible after log_level_info()");
68-
69212
luisa::log_level_warning();
70-
LUISA_VERBOSE("This verbose should be hidden after log_level_warning()");
71-
LUISA_INFO("This info should be hidden after log_level_warning()");
72-
LUISA_WARNING("This warning should be visible after log_level_warning()");
73-
74213
luisa::log_level_error();
75-
LUISA_VERBOSE("This verbose should be hidden after log_level_error()");
76-
LUISA_INFO("This info should be hidden after log_level_error()");
77-
LUISA_WARNING("This warning should be hidden after log_level_error()");
78-
79-
// Reset to verbose for other tests
214+
luisa::log_level_verbose();
215+
luisa::log_level_warning();
216+
luisa::log_level_info();
80217
luisa::log_level_verbose();
81218
luisa::log_flush();
219+
expect(true) << "rapid level transitions completed without crash";
82220
};
83221
return 0;
84222
}();
85223

86224
static inline const auto _luisa_reg_logging_complex_format_strings = [] {
87-
boost::ut::detail::test{"test", "logging complex format strings"} = [] {
88-
// Test various format specifiers
225+
"logging_complex_format_strings"_test = [] {
226+
luisa::log_level_verbose();
89227
LUISA_INFO("Integer: {}", -123456);
90228
LUISA_INFO("Unsigned: {}", 123456u);
91229
LUISA_INFO("Float: {}", 3.14159265f);
@@ -97,27 +235,24 @@ static inline const auto _luisa_reg_logging_complex_format_strings = [] {
97235
LUISA_INFO("Binary: {:b}", 170);
98236
LUISA_INFO("Scientific: {:e}", 12345.6789);
99237
LUISA_INFO("Fixed: {:.2f}", 3.14159);
238+
expect(true) << "complex format strings completed without crash";
100239
};
101240
return 0;
102241
}();
103242

104243
static inline const auto _luisa_reg_logging_empty_and_special_messages = [] {
105-
boost::ut::detail::test{"test", "logging empty and special messages"} = [] {
106-
// Test empty message (via format)
244+
"logging_empty_and_special_messages"_test = [] {
245+
luisa::log_level_verbose();
107246
LUISA_INFO("");
108-
109-
// Test message with special characters
110247
LUISA_INFO("Special chars: \t\n\r!@#$%^&*()_+-=[]{}|;':\",./<>?");
111-
112-
// Test message with braces
113248
LUISA_INFO("Braces: {{escaped}}, {{{{nested}}}}");
114249

115-
// Test long message
116250
luisa::string long_message;
117251
for (int i = 0; i < 100; ++i) {
118252
long_message += "This is a long message repeated multiple times. ";
119253
}
120254
LUISA_INFO("Long message: {}", long_message);
255+
expect(long_message.size() > 4000u) << "long message should be substantial";
121256
};
122257
return 0;
123258
}();

src/tests/unit/dsl/test_callable.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,17 @@ void test_callable(Device &device) {
9999
results[0], results[1], results[2], results[3],
100100
results[n - 2u], results[n - 1u]);
101101

102-
// for (size_t i = 0u; i < n; i++) {
103-
// LUISA_ASSERT(results[i] == data[i] + 3.0f, "Results mismatch.");
104-
// }
102+
bool all_correct = true;
103+
for (size_t i = 0u; i < n; i++) {
104+
float expected = data[i] + 3.0f;
105+
if (std::abs(results[i] - expected) > 1e-4f) {
106+
if (all_correct) {
107+
LUISA_WARNING("Callable result mismatch at [{}]: got {} expected {}", i, results[i], expected);
108+
}
109+
all_correct = false;
110+
}
111+
}
112+
expect(all_correct) << "callable composition should produce correct results (data[i] + 3.0f)";
105113
}
106114

107115
static inline const auto reg = [] {

src/tests/unit/dsl/test_nested_callable.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ static constexpr uint N = 1024u;
4949
static void check(const char *name,
5050
const std::vector<float> &result,
5151
const std::vector<float> &expected) {
52-
bool ok = true;
5352
uint mismatch_count = 0u;
5453
for (uint i = 0u; i < result.size(); i++) {
5554
float diff = std::abs(result[i] - expected[i]);
@@ -59,18 +58,9 @@ static void check(const char *name,
5958
name, i, result[i], expected[i], diff);
6059
}
6160
mismatch_count++;
62-
ok = false;
6361
}
6462
}
65-
if (!ok && mismatch_count > 5u) {
66-
LUISA_WARNING("{}: ... and {} more mismatches (total {}/{})",
67-
name, mismatch_count - 5u, mismatch_count, (uint)result.size());
68-
}
69-
if (ok) {
70-
LUISA_INFO("{}: PASSED", name);
71-
} else {
72-
LUISA_WARNING("{}: FAILED ({}/{} mismatches)", name, mismatch_count, (uint)result.size());
73-
}
63+
expect(mismatch_count == 0u) << name << ": " << mismatch_count << "/" << result.size() << " mismatches";
7464
}
7565

7666
// ── LCG matching the path tracer ─────────────────────────────────────
@@ -431,7 +421,7 @@ int test_nested_callable(Device &device) {
431421
state_ok = false;
432422
}
433423
}
434-
LUISA_INFO("test12_lcg_state_writeback: {}", state_ok ? "PASSED" : "FAILED");
424+
expect(state_ok) << "test12_lcg_state_writeback";
435425
}
436426

437427
// ================================================================
@@ -732,7 +722,7 @@ int test_nested_callable(Device &device) {
732722
state_ok = false;
733723
}
734724
}
735-
LUISA_INFO("test20_lcg_state_final: {}", state_ok ? "PASSED" : "FAILED");
725+
expect(state_ok) << "test20_lcg_state_final";
736726
}
737727

738728
LUISA_INFO("All nested callable tests completed.");

src/tests/unit/dsl/test_soa.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,11 @@ int test_soa(Device &device) {
112112
auto any_wrong = false;
113113
for (auto i = 0u; i < n; i++) {
114114
if (host_upload[i] != host_download[i]) {
115-
LUISA_WARNING("SOA upload/download mismatch at index {}\n"
116-
" Expected: {}\n"
117-
" Actual: {}",
118-
i, host_upload[i], host_download[i]);
115+
LUISA_WARNING("SOA upload/download mismatch at index {}", i);
119116
any_wrong = true;
120117
}
121118
}
122-
if (any_wrong) {
123-
LUISA_ERROR("SOA upload/download mismatch.");
124-
} else {
125-
LUISA_INFO("SOA upload/download test passed.");
126-
}
119+
expect(!any_wrong) << "soa_upload_download_roundtrip";
127120

128121
return 0;
129122
}

0 commit comments

Comments
 (0)