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/t0204-limits.sh')
-rwxr-xr-xtests/t0204-limits.sh182
1 file changed, 182 insertions, 0 deletions
diff --git a/tests/t0204-limits.sh b/tests/t0204-limits.sh
new file mode 100755
index 0000000..f09c290
--- /dev/null
+++ b/tests/t0204-limits.sh
@@ -0,0 +1,182 @@
+#!/bin/sh
+
+# Checks the ceilings a config can put on a page, that is the caps on refs
+# listed, on the lines and the files a diff renders inline, and on the size
+# of a blob any view will inflate, along with the clamp on how long an index
+# query may be. Crossing one of these has to trim the page or point the
+# reader at somewhere better suited, never drop the request, so each case
+# watches what survives as closely as what is left out. The last case is the
+# same idea applied to a filter, which degrades to escaped text rather than
+# failing when its highlighting library is absent.
+
+test_description='Check the ref listing and diff size limits'
+. ./setup.sh
+
+if [ $CGIT_HAS_LUA -eq 1 ]; then
+ test_set_prereq LUA
+fi
+
+# The limits only show themselves against content that crosses them, so the
+# fixture carries more branches and tags than max-ref-count allows and a
+# commit whose oversized file diff sits beside a small one, which is what
+# tells a per file limit apart from a whole page one.
+test_expect_success 'set up limit fixtures' '
+ mkrepo repos/limits 1 &&
+ (
+ cd repos/limits &&
+ seq 1 60 >big.c &&
+ printf "int x;\n" >small.c &&
+ git add -A &&
+ git commit -m sources &&
+ seq 301 360 >big.c &&
+ printf "int y;\n" >small.c &&
+ git commit -am change &&
+ for i in 1 2 3; do git branch branch-$i || exit 1; done &&
+ for i in 1 2 3; do git tag tag-$i || exit 1; done
+ ) &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "max-ref-count=2" &&
+ echo "max-diff-lines=20" &&
+ echo "max-diff-files=0" &&
+ echo "repo.url=limits" &&
+ echo "repo.path=$PWD/repos/limits/.git"
+ } >limitrc &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "max-diff-files=1" &&
+ echo "repo.url=limits" &&
+ echo "repo.path=$PWD/repos/limits/.git"
+ } >limitfilesrc
+'
+
+limitq() { CGIT_CONFIG="$PWD/limitrc" QUERY_STRING="$1" cgit; }
+
+# An index query is compared against every repository the listing holds, so
+# an enormous one multiplies out across the whole index. Clamping it rather
+# than refusing it keeps the cost bounded without making an ordinary search
+# behave any differently.
+test_expect_success 'an enormous query is clamped, not rejected' '
+ long=$(awk "BEGIN{s=\"\";for(i=0;i<4000;i++)s=s \"a\"; print s}") &&
+ test ${#long} -eq 4000 &&
+ cgit_query "q=$long" >tmp &&
+ grep "</html>" tmp &&
+ longest=$(grep -o "aaaa*" tmp | awk "{print length}" | sort -n | tail -1) &&
+ test "$longest" -eq 512
+'
+
+test_expect_success 'an ordinary query still filters the index' '
+ cgit_query "q=foo" >tmp &&
+ grep "foo" tmp &&
+ ! grep ">bar<" tmp
+'
+
+# The combined refs page caps branches and tags separately, and the pages it
+# hands the overflow to page on their own, so a limit that leaked between the
+# two sections would show up as the wrong link or the wrong count here.
+test_expect_success 'refs page lists max-ref-count branches and tags' '
+ limitq "url=limits/refs/" >tmp &&
+ test $(grep -c "log/?h=" tmp) -eq 2 &&
+ test $(grep -c "/tag/?h=tag-" tmp) -eq 2
+'
+
+test_expect_success 'refs page links each overflow to its own category' '
+ grep "refs/heads" tmp &&
+ grep "refs/tags" tmp
+'
+
+test_expect_success 'branch page paginates independently' '
+ limitq "url=limits/refs/heads/" >tmp &&
+ test $(grep -c "log/?h=" tmp) -eq 2 &&
+ grep "\[next\]" tmp &&
+ limitq "url=limits/refs/heads/&ofs=2" >tmp &&
+ grep "\[prev\]" tmp &&
+ ! grep "/tag/?h=tag-" tmp
+'
+
+test_expect_success 'tag page paginates independently' '
+ limitq "url=limits/refs/tags/&ofs=2" >tmp &&
+ grep "/tag/?h=tag-" tmp &&
+ grep "\[prev\]" tmp &&
+ ! grep "log/?h=" tmp
+'
+
+# A file that busts max-diff-lines is replaced by a link to its own page,
+# where the reader asked for that one file and the limit no longer applies.
+# The rest of the commit still renders, so one huge file cannot hide the
+# small change beside it.
+test_expect_success 'oversized file diff is replaced by a link' '
+ limitq "url=limits/commit/" >tmp &&
+ grep "too large to be rendered inline" tmp &&
+ grep "View it on its own page" tmp
+'
+
+test_expect_success 'small file in the same commit still renders inline' '
+ grep "class=.add.>+int y;" tmp
+'
+
+test_expect_success 'the single-file diff page always renders in full' '
+ limitq "url=limits/diff/big.c" >tmp &&
+ grep "class=.hunk." tmp &&
+ ! grep "too large to be rendered inline" tmp
+'
+
+# max-diff-files counts the files in a commit rather than the lines in one,
+# so it drops the whole body back to the diffstat while a request naming a
+# single file stays unaffected.
+test_expect_success 'a commit changing too many files shows stat only' '
+ CGIT_CONFIG="$PWD/limitfilesrc" QUERY_STRING="url=limits/commit/" cgit >tmp &&
+ grep "too large to be rendered inline" tmp &&
+ ! grep "class=.hunk." tmp
+'
+
+test_expect_success 'the single-file page is not limited by max-diff-files' '
+ CGIT_CONFIG="$PWD/limitfilesrc" QUERY_STRING="url=limits/diff/small.c" cgit >tmp &&
+ grep "class=.hunk." tmp
+'
+
+# The diff views must not inflate a blob past max-blob-size merely to render
+# it, which is the same defence the tree and plain views make and is easy to
+# miss on this path. Such a file is reported as binary instead.
+test_expect_success 'a diff of an oversized blob is not inlined' '
+ mkrepo repos/blobdiff 1 &&
+ (
+ cd repos/blobdiff &&
+ awk "BEGIN{for(i=0;i<400;i++)print \"aaaaaaaa\"}" >big.txt &&
+ git add -A &&
+ git commit -m add &&
+ awk "BEGIN{for(i=0;i<401;i++)print \"aaaaaaaa\"}" >big.txt &&
+ git commit -am change
+ ) &&
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "max-blob-size=1" &&
+ echo "repo.url=blobdiff" &&
+ echo "repo.path=$PWD/repos/blobdiff/.git"
+ } >blobdiffrc &&
+ sha=$(git -C repos/blobdiff rev-parse HEAD) &&
+ CGIT_CONFIG="$PWD/blobdiffrc" QUERY_STRING="url=blobdiff/commit/&id=$sha" cgit >tmp &&
+ grep "Binary files differ" tmp &&
+ ! grep "aaaaaaaa" tmp
+'
+
+# A missing scintillua leaves the shipped filter with nothing to highlight
+# with, and a filter that failed there would take the whole page down with
+# it, so it has to hand the source back escaped instead.
+test_expect_success LUA 'highlight filter passes text through without scintillua' '
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "source-filter=lua:$(cd ../../custom/extensions && pwd)/syntax-highlight.lua" &&
+ echo "repo.url=limits" &&
+ echo "repo.path=$PWD/repos/limits/.git"
+ } >hlrc &&
+ CGIT_SCINTILLUA_PATH=/nonexistent CGIT_CONFIG="$PWD/hlrc" \
+ QUERY_STRING="url=limits/tree/small.c" cgit >tmp &&
+ grep "int y;" tmp
+'
+
+test_done