tests: Add tests for remote summary update races
authorDan Nicholson <nicholson@endlessm.com>
Thu, 2 Aug 2018 18:58:56 +0000 (13:58 -0500)
committerAtomic Bot <atomic-devel@projectatomic.io>
Tue, 14 Aug 2018 13:38:11 +0000 (13:38 +0000)
There have been subtle bugs in the past when a client pulls while the
remote server is updating the summary. The client may get the old
summary and new signature or vice versa. Add tests to simulate this
behavior to make sure there aren't regressions in the future.

Closes: #1698
Approved by: cgwalters

tests/test-pull-summary-sigs.sh

index c6d04f41b9001cd5e0a87147e63a035ca73b4f4f..77ff844414c152cf92267d200fa4899ac6ca38fa 100755 (executable)
@@ -23,7 +23,7 @@ set -euo pipefail
 
 . $(dirname $0)/libtest.sh
 
-echo "1..7"
+echo "1..9"
 
 COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}"
 setup_fake_remote_repo1 "archive" "${COMMIT_SIGN}"
@@ -151,4 +151,83 @@ grep static-deltas summary.txt > static-deltas.txt
 assert_file_has_content static-deltas.txt \
   $(${OSTREE} --repo=repo rev-parse origin:main)
 
+## Tests for handling of cached summaries while racing with remote summary updates
+
+# Make 2 different but valid summary/signature pairs to test races with
+${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u ${COMMIT_SIGN}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{,.1}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{,.1}
+mkdir ${test_tmpdir}/ostree-srv/even-another-files
+cd ${test_tmpdir}/ostree-srv/even-another-files
+echo 'hello world even another object' > even-another-hello-world
+${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo commit ${COMMIT_SIGN} -b even-another -s "A commit" -m "Another Commit body"
+${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u ${COMMIT_SIGN}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{,.2}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{,.2}
+cd ${test_tmpdir}
+
+# Reset to the old valid summary and pull to cache it
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.1,}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.1,}
+repo_reinit
+${OSTREE} --repo=repo pull origin main
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.1 >&2
+
+# Simulate a pull race where the client gets the old summary and the new
+# summary signature since it was generated on the server between the
+# requests
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.2,}
+if ${OSTREE} --repo=repo pull origin main 2>err.txt; then
+    assert_not_reached "Successful pull with old summary"
+fi
+assert_file_has_content err.txt "none are in trusted keyring"
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.1 >&2
+
+# Publish correct summary and check that subsequent pull succeeds
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.2,}
+${OSTREE} --repo=repo pull origin main
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.2 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.2 >&2
+
+echo "ok pull with signed summary remote old summary"
+
+# Reset to the old valid summary and pull to cache it
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.1,}
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.1,}
+repo_reinit
+${OSTREE} --repo=repo pull origin main
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.1 >&2
+
+# Simulate a pull race where the client gets the new summary and the old
+# summary signature. This is unlikely to happen except if the web server
+# is caching the old signature. This should succeed because the cached
+# old summary is used.
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.2,}
+${OSTREE} --repo=repo pull origin main
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.1 >&2
+
+# Publish correct signature and check that subsequent pull succeeds
+cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.2,}
+${OSTREE} --repo=repo pull origin main
+assert_has_file repo/tmp/cache/summaries/origin
+assert_has_file repo/tmp/cache/summaries/origin.sig
+cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.2 >&2
+cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.2 >&2
+
+echo "ok pull with signed summary remote old summary signature"
+
 libtest_cleanup_gpg