Files
datastore/ci/tests/test_log_parser.py
Groene AI 83af6ba7c0 CI: drop dangling stack-trace promise from parsed failure names
The praktika failure-log parser builds the failure name (CIDB test_name,
shown in CI reports) from the first line of the matched error. Exception
messages end that line with ", Stack trace (when copying this message,
always include the lines below):", but the frames it promises are on the
following log lines, which the name never includes. The reported name then
ends with the "always include the lines below:" promise and no lines after
it (only " (STID: ...)").

Cut the marker off the name. The stack frames are still kept in the
separate "Stack trace:" section of the failure info, so no diagnostic
information is lost. This mirrors the server-side fix in commit a11cdca398
("Don't print empty stack trace section in exception messages").
2026-06-14 23:20:51 +00:00

119 lines
5.1 KiB
Python

import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
from ci.jobs.scripts.log_parser import FuzzerLogParser
_ASAN_CHECK_FAILED_STDERR = """\
==2138==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
AddressSanitizer: CHECK failed: sanitizer_allocator_secondary.h:200 "((nearest_chunk)) < ((h->map_beg + h->map_size))" (0x7b44c2461000, 0x0) (tid=3005)
#0 0x55b9822b6021 in __asan::CheckUnwind() asan_rtl.cpp
#1 0x55b9822cedcb in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) sanitizer_termination.cpp
#2 0x55b9b8db9bc7 in DB::ExceptionKeepingTransform::work() src/Processors/Transforms/ExceptionKeepingTransform.cpp:189:42
#3 0x55b9b85a724d in DB::executeJob(DB::ExecutingGraph::Node*, DB::ReadProgressCallback*) src/Processors/Executors/ExecutionThreadContext.cpp:54:28
#4 0x55b9b85a724d in DB::ExecutionThreadContext::executeTask() src/Processors/Executors/ExecutionThreadContext.cpp:103:9
#5 0x55b9b85728d8 in DB::PipelineExecutor::executeStepImpl(unsigned long, DB::IAcquiredSlot*, std::__1::atomic<bool>*) src/Processors/Executors/PipelineExecutor.cpp:363:26
#6 0x55b9b8571ae1 in DB::PipelineExecutor::executeStep(std::__1::atomic<bool>*) src/Processors/Executors/PipelineExecutor.cpp:191:5
#7 0x55b9b85cb318 in DB::PushingPipelineExecutor::finish() src/Processors/Executors/PushingPipelineExecutor.cpp:131:47
#8 0x7f4ae1fdb8cf misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
dpkg: error processing package clickhouse-server (--install):
"""
def test_parse_failure_prefers_asan_check_failed_over_server_assertion(tmp_path):
server_log = tmp_path / "clickhouse-server.err.log"
stderr_log = tmp_path / "stderr.log"
server_log.write_text(
"2026.06.09 00:00:00.000000 [ 1 ] {} <Fatal> Application: "
"Assertion 'px != 0' failed.\n",
encoding="utf-8",
)
stderr_log.write_text(
"AddressSanitizer: CHECK failed: sanitizer_allocator_secondary.h:200 "
"\"((nearest_chunk)) < ((h->map_beg + h->map_size))\" "
"(0x7b44c2461000, 0x0) (tid=3005)\n"
" <empty stack>\n"
"\n"
"dpkg: error processing package clickhouse-server (--install):\n",
encoding="utf-8",
)
parser = FuzzerLogParser(
server_log=str(server_log),
stderr_log=str(stderr_log),
fuzzer_log="",
)
result_name, info, files = parser.parse_failure()
assert result_name == "AddressSanitizer (STID: None)"
assert "AddressSanitizer: CHECK failed:" in info
assert "Assertion 'px != 0' failed" not in info
assert "dpkg" not in info
assert files == []
def test_parse_failure_asan_check_failed_with_stack_trace(tmp_path):
server_log = tmp_path / "clickhouse-server.err.log"
stderr_log = tmp_path / "stderr.log"
server_log.write_text(
"2026.06.09 00:00:00.000000 [ 1 ] {} <Fatal> Application: "
"Assertion 'px != 0' failed.\n",
encoding="utf-8",
)
stderr_log.write_text(_ASAN_CHECK_FAILED_STDERR, encoding="utf-8")
parser = FuzzerLogParser(
server_log=str(server_log),
stderr_log=str(stderr_log),
fuzzer_log="",
)
result_name, info, files = parser.parse_failure()
assert result_name == "AddressSanitizer (STID: 1288-3bd5)"
assert "AddressSanitizer: CHECK failed:" in info
assert "Assertion 'px != 0' failed" not in info
assert "dpkg" not in info
assert files == []
def test_parse_failure_logical_error_name_drops_dangling_stack_trace_marker(tmp_path):
server_log = tmp_path / "clickhouse-server.err.log"
server_log.write_text(
"2026.06.14 20:00:01.000000 [ 200 ] {} <Fatal> : Logical error: "
"'std::exception. Code: 1001, type: std::__1::future_error, "
"e.what() = The associated promise has been destructed prior to the "
"associated state becoming ready., Stack trace (when copying this "
"message, always include the lines below):\n"
"\n"
"0. ./contrib/llvm-project/libcxx/include/future:509:25: "
"std::promise<void>::~promise() @ 0x000000002cbf6d04\n"
"2026.06.14 20:00:02.000000 [ 200 ] {} <Fatal> BaseDaemon: Stack trace:\n"
"2026.06.14 20:00:02.000000 [ 200 ] {} <Fatal> BaseDaemon: "
"1. ./src/Common/Exception.cpp:60: DB::abortOnFailedAssertion() @ 0x14d2262e\n",
encoding="utf-8",
)
parser = FuzzerLogParser(
server_log=str(server_log),
stderr_log="",
fuzzer_log="",
)
result_name, info, files = parser.parse_failure()
# The failure name must not end with the "always include the lines below):"
# promise when no frames follow it (the first log line is all the name has).
assert "always include the lines below" not in result_name
assert result_name.startswith("Logical error: 'std::exception.")
assert "The associated promise has been destructed" in result_name
assert "(STID:" in result_name
# The frames are still preserved in the separate stack-trace section of the info.
assert "abortOnFailedAssertion" in info