diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Renumber the test scripts into themed ranges
t000x the ground the suite stands on: git version, html validity, the cache t01xx page content, one script per page t02xx features that cut across pages: filters, submodule links, dates, limits t03xx defence, the security regressions and the $HOME promise t04xx the helper tools under tools/
Diffstat (limited to 'tests/t0003-cache.sh')
-rwxr-xr-xtests/t0003-cache.sh200
1 file changed, 200 insertions, 0 deletions
diff --git a/tests/t0003-cache.sh b/tests/t0003-cache.sh
new file mode 100755
index 0000000..ca85d97
--- /dev/null
+++ b/tests/t0003-cache.sh
@@ -0,0 +1,200 @@
+#!/bin/sh
+
+# Exercises the cache, which keeps a rendered page in a slot on disk and
+# replays it for the next request that asks for the same thing. The first three
+# tests set cache-size to nothing, to one slot and to the full table in turn,
+# then count what the requests left behind. The rest cover the two ways a slot
+# can come out wrong, a page longer than the output buffer and a key too long
+# to be read back.
+
+test_description='Validate cache'
+. ./setup.sh
+
+test_expect_success 'verify cache-size=0' '
+
+ rm -f cache/* &&
+ sed -e "s/cache-size=1021$/cache-size=0/" cgitrc >cgitrc.tmp &&
+ mv -f cgitrc.tmp cgitrc &&
+ cgit_url "" &&
+ cgit_url "foo" &&
+ cgit_url "foo/refs" &&
+ cgit_url "foo/tree" &&
+ cgit_url "foo/log" &&
+ cgit_url "foo/diff" &&
+ cgit_url "foo/patch" &&
+ cgit_url "bar" &&
+ cgit_url "bar/refs" &&
+ cgit_url "bar/tree" &&
+ cgit_url "bar/log" &&
+ cgit_url "bar/diff" &&
+ cgit_url "bar/patch" &&
+ ls cache >output &&
+ test_line_count = 0 output
+'
+
+test_expect_success 'verify cache-size=1' '
+
+ rm -f cache/* &&
+ sed -e "s/cache-size=0$/cache-size=1/" cgitrc >cgitrc.tmp &&
+ mv -f cgitrc.tmp cgitrc &&
+ cgit_url "" &&
+ cgit_url "foo" &&
+ cgit_url "foo/refs" &&
+ cgit_url "foo/tree" &&
+ cgit_url "foo/log" &&
+ cgit_url "foo/diff" &&
+ cgit_url "foo/patch" &&
+ cgit_url "bar" &&
+ cgit_url "bar/refs" &&
+ cgit_url "bar/tree" &&
+ cgit_url "bar/log" &&
+ cgit_url "bar/diff" &&
+ cgit_url "bar/patch" &&
+ ls cache >output &&
+ test_line_count = 1 output
+'
+
+test_expect_success 'verify cache-size=1021' '
+
+ rm -f cache/* &&
+ sed -e "s/cache-size=1$/cache-size=1021/" cgitrc >cgitrc.tmp &&
+ mv -f cgitrc.tmp cgitrc &&
+ cgit_url "" &&
+ cgit_url "foo" &&
+ cgit_url "foo/refs" &&
+ cgit_url "foo/tree" &&
+ cgit_url "foo/log" &&
+ cgit_url "foo/diff" &&
+ cgit_url "foo/patch" &&
+ cgit_url "bar" &&
+ cgit_url "bar/refs" &&
+ cgit_url "bar/tree" &&
+ cgit_url "bar/log" &&
+ cgit_url "bar/diff" &&
+ cgit_url "bar/patch" &&
+ ls cache >output &&
+ test_line_count = 13 output &&
+ cgit_url "foo/ls_cache" >output.full &&
+ strip_headers <output.full >output &&
+ test_line_count = 13 output &&
+ cgit_url "foo/ls_cache" >output.second &&
+ test_cmp output.full output.second
+'
+
+# Page output is buffered, so a slot only holds the whole page if the buffer is
+# emptied before the size of what was generated is taken. The blob set up here
+# is larger than one buffer, so a missing flush would leave the cached copy cut
+# short.
+test_expect_success 'set up a repo with a page larger than the output buffer' '
+ mkrepo repos/bigpage 1 &&
+ (
+ cd repos/bigpage &&
+ awk "BEGIN{for(i=0;i<20000;i++) print \"line \" i \" of the big file\"}" >big.txt &&
+ git add big.txt &&
+ git commit -m "add big.txt"
+ ) &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-root=$PWD/cache2" &&
+ echo "cache-size=64" &&
+ echo "enable-tree-linenumbers=1" &&
+ echo "repo.url=bigpage" &&
+ echo "repo.path=$PWD/repos/bigpage/.git"
+ } >bigrc &&
+ rm -rf cache2 && mkdir cache2
+'
+
+bigpage_query()
+{
+ CGIT_CONFIG="$PWD/bigrc" QUERY_STRING="$1" cgit
+}
+
+test_expect_success 'the first request fills the slot and the second replays it' '
+ bigpage_query "url=bigpage/tree/big.txt" >big.first &&
+ test $(wc -c <big.first) -gt 65536 &&
+ bigpage_query "url=bigpage/tree/big.txt" >big.second &&
+ strip_headers <big.first >big.first.body &&
+ strip_headers <big.second >big.second.body &&
+ test_cmp big.first.body big.second.body
+'
+
+test_expect_success 'the cached body matches one generated with the cache off' '
+ sed -e "s/^cache-size=64$/cache-size=0/" bigrc >bignocache &&
+ CGIT_CONFIG="$PWD/bignocache" QUERY_STRING="url=bigpage/tree/big.txt" cgit >big.nocache &&
+ strip_headers <big.nocache >big.nocache.body &&
+ # The footer carries the time the page was generated, which the two runs
+ # cannot agree on.
+ sed -e "s/generated by .*//" big.nocache.body >big.nocache.timeless &&
+ sed -e "s/generated by .*//" big.second.body >big.cached.timeless &&
+ test_cmp big.nocache.timeless big.cached.timeless
+'
+
+test_expect_success 'the page ends where it should, so nothing was dropped' '
+ tail -c 200 big.second.body | grep "</html>"
+'
+
+# A slot stores its key ahead of the content and only the first few kilobytes of
+# it are read back, so a key longer than that could never match. A request
+# carrying one used to leave a slot behind on every visit that nothing could
+# ever go on to use.
+test_expect_success 'an over-long cache key leaves no slot behind' '
+ rm -rf cache3 && mkdir cache3 &&
+ sed -e "s|^cache-root=.*|cache-root=$PWD/cache3|" bigrc >bigkeyrc &&
+ long=$(awk "BEGIN{s=\"\";for(i=0;i<6000;i++)s=s \"k\"; print s}") &&
+ CGIT_CONFIG="$PWD/bigkeyrc" QUERY_STRING="url=bigpage/&q=$long" cgit >key.out 2>key.err &&
+ grep "</html>" key.out &&
+ ls cache3 >key.slots &&
+ test_line_count = 0 key.slots
+'
+
+test_expect_success 'an ordinary key still fills a slot' '
+ rm -rf cache3 && mkdir cache3 &&
+ CGIT_CONFIG="$PWD/bigkeyrc" QUERY_STRING="url=bigpage/" cgit >/dev/null &&
+ ls cache3 >key.slots &&
+ test_line_count = 1 key.slots
+'
+
+# An error page fired after rendering began abandons the fill with part of
+# the page already written into the lock file. That fragment must be
+# discarded along with the file, not replayed to the visitor behind the
+# error page. A commit whose parent object is missing renders its whole
+# info table before the diff machinery fails, which makes it the trigger.
+test_expect_success 'set up a repo missing a parent object' '
+ mkrepo repos/broken 2 &&
+ parent=$(git -C repos/broken rev-parse HEAD^) &&
+ tip=$(git -C repos/broken rev-parse HEAD) &&
+ rm "repos/broken/.git/objects/$(echo "$parent" | cut -c1-2)/$(echo "$parent" | cut -c3-)" &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-root=$PWD/cache4" &&
+ echo "cache-size=64" &&
+ echo "repo.url=broken" &&
+ echo "repo.path=$PWD/repos/broken/.git"
+ } >brokenrc &&
+ rm -rf cache4 && mkdir cache4
+'
+
+test_expect_success 'an error after output began replays none of it' '
+ CGIT_CONFIG="$PWD/brokenrc" QUERY_STRING="url=broken/commit/&id=$tip" \
+ cgit >broken.out &&
+ grep "Bad commit" broken.out &&
+ test $(grep -c "^Status:" broken.out) = 1 &&
+ ls cache4 >broken.slots &&
+ test_line_count = 0 broken.slots
+'
+
+# An error page reports a condition the repository may grow out of, and a
+# request pinned to an object id would cache it under the never-expiring
+# static ttl. Asking for a commit that does not exist yet must therefore
+# leave nothing behind, or the real page could never appear once it does.
+test_expect_success 'an error page leaves no slot behind' '
+ rm -rf cache3 && mkdir cache3 &&
+ CGIT_CONFIG="$PWD/bigkeyrc" \
+ QUERY_STRING="url=bigpage/commit/&id=0123456789abcdef0123456789abcdef01234567" \
+ cgit >error.out &&
+ grep "Bad commit reference" error.out &&
+ ls cache3 >error.slots &&
+ test_line_count = 0 error.slots
+'
+
+test_done