aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2023-07-07 15:27:03 -0400
committerZorro Lang <zlang@kernel.org>2023-07-09 20:51:17 +0800
commit8bab8ef9872ecf9bce7381b6e784063c92c2cad3 (patch)
tree3fb79a6658c0d7abf55eabd96329fac307060cb2
parent27211f9bb44b2fab8cd2b76bd57e20328c9480cf (diff)
downloadxfstests-dev-8bab8ef9872ecf9bce7381b6e784063c92c2cad3.tar.gz
report: safely update the result.xml file
After every single test, we rewrite result.xml from scratch. This ensures that the XML file is always in a valid, parseable state, even if the check script is killed or the machine crashes in the middle of a test. If the test is being run in a Cloud VM as a "spot" (Amazon, Azure, or GCE) or "preemptible" (Oracle) instance, the VM can be halted whenever the Cloud provider needs the capacity for customers who are willing to pay full price. ("Spot" instances can be 60% to 90% cheaper --- allowing the frugal kernel developer to get up to 10 times more testing for the same amount of money. :-) Since a "spot" VM can get terminated at any time, it is possible for the check script to be killed while it is in the middle of rewriting the result.xml file. If the result.xml file is only partially written, information regarding the tests run before VM termination will be lost. To address this race, write the new result.xml file as result.xml.new, and only rename it to result.xml after the XML file is fully written out. Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Zorro Lang <zlang@kernel.org>
-rw-r--r--common/report20
1 files changed, 12 insertions, 8 deletions
diff --git a/common/report b/common/report
index 9bfa09ecce..3c58f0e3c2 100644
--- a/common/report
+++ b/common/report
@@ -109,13 +109,16 @@ _xunit_make_section_report()
local notrun_count="$4"
local sect_time="$5"
local timestamp
+ local tmp_fn="$REPORT_DIR/result.xml.new"
+ local out_fn="$REPORT_DIR/result.xml"
if [ $sect_name == '-no-sections-' ]; then
sect_name='global'
fi
local report=$tmp.report.xunit.$sect_name.xml
+ rm -f "$tmp_fn"
# Header
- echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $REPORT_DIR/result.xml
+ echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > "$tmp_fn"
if [ -n "$test_start_time" ]; then
timestamp="$(date -Iseconds --date="$test_start_time")"
else
@@ -123,7 +126,7 @@ _xunit_make_section_report()
fi
local fstests_ns="https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git"
- cat >> $REPORT_DIR/result.xml << ENDL
+ cat >> "$tmp_fn" << ENDL
<testsuite
xmlns="$fstests_ns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -142,19 +145,20 @@ ENDL
__generate_report_vars
# Properties
- echo -e "\t<properties>" >> $REPORT_DIR/result.xml
+ echo -e "\t<properties>" >> "$tmp_fn"
(for key in "${!REPORT_VARS[@]}"; do
_xunit_add_property "$key" "${REPORT_VARS["$key"]}"
done;
for p in "${REPORT_ENV_LIST[@]}"; do
_xunit_add_property "$p" "${!p}"
- done) | sort >> $REPORT_DIR/result.xml
- echo -e "\t</properties>" >> $REPORT_DIR/result.xml
+ done) | sort >> "$tmp_fn"
+ echo -e "\t</properties>" >> "$tmp_fn"
if [ -f $report ]; then
- cat $report >> $REPORT_DIR/result.xml
+ cat $report >> "$tmp_fn"
fi
- echo "</testsuite>" >> $REPORT_DIR/result.xml
- echo "Xunit report: $REPORT_DIR/result.xml"
+ echo "</testsuite>" >> "$tmp_fn"
+ sync "$tmp_fn" && mv "$tmp_fn" "$out_fn"
+ echo "Xunit report: $out_fn"
}
_xunit_make_testcase_report()