Skip to content

Commit c6d4a73

Browse files
committed
test(ci): isolate macOS Android install and diagnose Windows record rename
1 parent c3123c8 commit c6d4a73

4 files changed

Lines changed: 42 additions & 4 deletions

File tree

‎.github/workflows/ci-macos-e2e.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ jobs:
5252
timeout-minutes: 60
5353
env:
5454
E2E_SHARD: ${{ matrix.shard }}/${{ matrix.shards }}
55+
# 721 installs the large NDK in its own bounded step below. Running it in
56+
# the ordinary shard duplicates the download and can fail before linking.
57+
E2E_EXCLUDE: 721_*.sh
5558
E2E_TIMINGS: tests/e2e/timings/macos.tsv
5659
E2E_REPORT: ${{ github.workspace }}/e2e-report-${{ matrix.image == 'macos-15' && 'macos' || matrix.image }}-${{ matrix.shard }}.tsv
5760
# NOTE: no MCPP_VERBOSE — the e2e suite asserts mcpp's default quiet

‎src/build/schedule/compiler_transaction.cpp‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,17 @@ bool replace_record(const fs::path& path,std::string_view bytes,std::string* dia
2525
if(written&&closed) {
2626
auto renamed=os::fs::rename(temporary,path,true);
2727
if(renamed)return true;
28-
if(diagnostic)*diagnostic=std::format("rename temporary (condition {}, native {})",
29-
static_cast<int>(renamed.error().code),renamed.error().native);
28+
if(diagnostic) {
29+
// The OpenKal condition does not retain the Windows NTSTATUS. These
30+
// observations distinguish a blocked replacement from a source or
31+
// parent failure without exposing private build paths in CI logs.
32+
std::error_code sourceError, targetError;
33+
const auto source=fs::symlink_status(temporary,sourceError);
34+
const auto target=fs::symlink_status(path,targetError);
35+
*diagnostic=std::format("rename temporary (condition {}, native {}; source regular {} ec {}; target exists {} ec {})",
36+
static_cast<int>(renamed.error().code),renamed.error().native,
37+
fs::is_regular_file(source),sourceError.value(),fs::exists(target),targetError.value());
38+
}
3039
} else if(!written) {
3140
fail("write/flush temporary");
3241
} else {

‎tests/e2e/run_all.sh‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@ report() {
468468
}
469469
if [[ -n "${E2E_REPORT:-}" ]]; then : > "$E2E_REPORT"; fi
470470

471-
# E2E_LIST=1 prints the tests this invocation would run (after E2E_ONLY and the
472-
# shard, before the capability check) and exits, so a shard's membership can be
471+
# E2E_LIST=1 prints the tests this invocation would run (after E2E_ONLY,
472+
# E2E_EXCLUDE and the shard, before the capability check) and exits, so a shard's membership can be
473473
# read without running it.
474474
if [[ "${E2E_LIST:-}" == "1" ]]; then
475475
for test in "$HERE"/[0-9]*.sh; do
@@ -478,6 +478,10 @@ if [[ "${E2E_LIST:-}" == "1" ]]; then
478478
# shellcheck disable=SC2053 -- glob match is the point
479479
[[ "$name" == $E2E_ONLY ]] || continue
480480
fi
481+
if [[ -n "${E2E_EXCLUDE:-}" ]]; then
482+
# shellcheck disable=SC2053 -- glob match is the point
483+
[[ "$name" == $E2E_EXCLUDE ]] && continue
484+
fi
481485
if (( SHARD_TOTAL > 1 )); then in_shard "$name" || continue; fi
482486
echo "$name"
483487
done
@@ -496,6 +500,15 @@ for test in "$HERE"/[0-9]*.sh; do
496500
if (( SHARD_TOTAL > 1 )); then
497501
in_shard "$name" || continue
498502
fi
503+
if [[ -n "${E2E_EXCLUDE:-}" ]]; then
504+
# shellcheck disable=SC2053 -- glob match is the point
505+
if [[ "$name" == $E2E_EXCLUDE ]]; then
506+
echo "SKIP: $name (owned by a dedicated workflow step)"
507+
((SKIP++))
508+
report skip "$name" 0 "owned by a dedicated workflow step"
509+
continue
510+
fi
511+
fi
499512
echo
500513
missing_cap="$(check_requires "$test")"
501514
if [[ -n "$missing_cap" ]]; then

‎tests/unit/test_compiler_transaction.cpp‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,19 @@ TEST(CompilerTransaction, FailedRenameReportsTheStageAndPreservesItsTarget) {
237237
EXPECT_TRUE(diagnostic.starts_with("rename temporary (condition "))<<diagnostic;
238238
EXPECT_TRUE(fs::is_directory(t.root/"record"));
239239
}
240+
TEST(CompilerTransaction, ReaderHeldTargetKeepsAnAtomicRecord) {
241+
Transaction t;
242+
const auto record=t.root/"record";
243+
std::ofstream(record)<<"old";
244+
std::ifstream held(record,std::ios::binary);
245+
ASSERT_TRUE(held);
246+
std::string diagnostic;
247+
const bool replaced=tx::replace_record(record,"new",&diagnostic);
248+
std::cout<<"READING reader-held record replacement: "
249+
<<(replaced?"replaced":diagnostic)<<'\n';
250+
EXPECT_EQ(Transaction::contents(record),replaced?"new":"old");
251+
EXPECT_EQ(std::string(std::istreambuf_iterator<char>(held),std::istreambuf_iterator<char>()),"old");
252+
}
240253
TEST(CompilerTransaction, RecordOpenAppearanceDriver) {
241254
if(!mcpp::invocation::get("MCPP_TEST_RECORD_OPEN_DRIVER"))GTEST_SKIP()<<"subprocess driver";
242255
auto record=tx::read("record","schema");

0 commit comments

Comments
 (0)