cgit — Testing
Overview
cgit has a shell-based test suite in the tests/ directory. Tests use
Git's own test framework (test-lib.sh) and exercise cgit by invoking the
CGI binary with simulated HTTP requests.
Source location: cgit/tests/.
Test Framework
The test harness is built on Git's test-lib.sh, sourced from the vendored
Git tree at git/t/test-lib.sh. This provides:
- TAP-compatible output
- Test assertions (
test_expect_success,test_expect_failure) - Temporary directory management (
trashdirectories) - Color-coded pass/fail reporting
setup.sh
All test scripts source tests/setup.sh, which provides:
# Core test helpers
prepare_tests() # Create repos and config file
run_test() # Execute a single test case
cgit_query() # Invoke cgit with a query string
cgit_url() # Invoke cgit with a virtual URL
strip_headers() # Remove HTTP headers from CGI output
Invoking cgit
Tests invoke cgit as a CGI binary by setting environment variables:
cgit_query()
{
CGIT_CONFIG="$PWD/cgitrc" QUERY_STRING="$1" cgit
}
cgit_url()
{
CGIT_CONFIG="$PWD/cgitrc" QUERY_STRING="url=$1" cgit
}
The cgit binary is on PATH (prepended by setup.sh). The response includes
HTTP headers followed by HTML content. strip_headers() removes the
headers for content-only assertions.
Test Repository Setup
setup_repos() creates test repositories:
setup_repos()
{
rm -rf cache
mkdir -p cache
mkrepo repos/foo 5 # 5 commits
mkrepo repos/bar 50 commit-graph # 50 commits with commit-graph
mkrepo repos/foo+bar 10 testplus # 10 commits + special chars
mkrepo "repos/with space" 2 # repo with spaces in name
mkrepo repos/filter 5 testplus # for filter tests
}
mkrepo()
mkrepo() {
name=$1
count=$2
test_create_repo "$name"
(
cd "$name"
n=1
while test $n -le $count; do
echo $n >file-$n
git add file-$n
git commit -m "commit $n"
n=$(expr $n + 1)
done
case "$3" in
testplus)
echo "hello" >a+b
git add a+b
git commit -m "add a+b"
git branch "1+2"
;;
commit-graph)
git commit-graph write
;;
esac
)
}
Test Configuration
A cgitrc file is generated in the test directory with:
virtual-root=/
cache-root=$PWD/cache
cache-size=1021
snapshots=tar.gz tar.bz tar.lz tar.xz tar.zst zip
enable-log-filecount=1
enable-log-linecount=1
summary-log=5
summary-branches=5
summary-tags=5
clone-url=git://example.org/$CGIT_REPO_URL.git
enable-filter-overrides=1
root-coc=$PWD/site-coc.txt
root-cla=$PWD/site-cla.txt
root-homepage=https://projecttick.org
root-homepage-title=Project Tick
root-link=GitHub|https://github.com/example
root-link=GitLab|https://gitlab.com/example
root-link=Codeberg|https://codeberg.org/example
repo.url=foo
repo.path=$PWD/repos/foo/.git
repo.url=bar
repo.path=$PWD/repos/bar/.git
repo.desc=the bar repo
repo.url=foo+bar
repo.path=$PWD/repos/foo+bar/.git
repo.desc=the foo+bar repo
# ...
Test Scripts
Test File Naming
Tests follow the convention tNNNN-description.sh:
| Test | Description |
|---|---|
t0001-validate-git-versions.sh |
Verify Git version compatibility |
t0010-validate-html.sh |
Validate HTML output |
t0020-validate-cache.sh |
Test cache system |
t0101-index.sh |
Repository index page |
t0102-summary.sh |
Repository summary page |
t0103-log.sh |
Log view |
t0104-tree.sh |
Tree view |
t0105-commit.sh |
Commit view |
t0106-diff.sh |
Diff view |
t0107-snapshot.sh |
Snapshot downloads |
t0108-patch.sh |
Patch view |
t0109-gitconfig.sh |
Git config integration |
t0110-rawdiff.sh |
Raw diff output |
t0111-filter.sh |
Filter system |
t0112-coc.sh |
Code of Conduct page |
t0113-cla.sh |
CLA page |
t0114-root-homepage.sh |
Root homepage links |
Number Ranges
| Range | Category |
|---|---|
t0001-t0099 |
Infrastructure/validation tests |
t0100-t0199 |
Feature tests |
Running Tests
All Tests
cd cgit/tests
make
The Makefile discovers all t*.sh files and runs them:
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
all: $(T)
$(T):
@'$(SHELL_PATH_SQ)' $@ $(CGIT_TEST_OPTS)
Individual Tests
# Run a single test
./t0101-index.sh
# With verbose output
./t0101-index.sh -v
# With Valgrind
./t0101-index.sh --valgrind
Test Options
Options are passed via CGIT_TEST_OPTS or command-line arguments:
| Option | Description |
|---|---|
-v, --verbose |
Show test details |
--valgrind |
Run cgit under Valgrind |
--debug |
Show shell trace |
Valgrind Support
setup.sh intercepts the --valgrind flag and configures Valgrind
instrumentation via a wrapper script in tests/valgrind/:
if test -n "$cgit_valgrind"; then
GIT_VALGRIND="$TEST_DIRECTORY/valgrind"
CGIT_VALGRIND=$(cd ../valgrind && pwd)
PATH="$CGIT_VALGRIND/bin:$PATH"
fi
Test Patterns
HTML Content Assertion
run_test 'repo index contains foo' '
cgit_url "/" | strip_headers | grep -q "foo"
'
HTTP Header Assertion
run_test 'content type is text/html' '
cgit_url "/" | head -1 | grep -q "Content-Type: text/html"
'
Snapshot Download
run_test 'snapshot is valid tar.gz' '
cgit_url "/foo/snapshot/foo-master.tar.gz" | strip_headers | \
gunzip | tar tf - >/dev/null
'
Negative Assertion
run_test 'no 404 on valid repo' '
! cgit_url "/foo" | grep -q "404"
'
Lua Filter Conditional
if [ $CGIT_HAS_LUA -eq 1 ]; then
run_test 'lua filter works' '
cgit_url "/filter-lua/about/" | strip_headers | grep -q "filtered"
'
fi
Test Filter Scripts
The tests/filters/ directory contains simple filter scripts for testing:
dump.sh
A passthrough filter that copies stdin to stdout, used to verify filter invocation:
#!/bin/sh
cat
dump.lua
Lua equivalent of the dump filter:
function filter_open(...)
end
function write(str)
html(str)
end
function filter_close()
return 0
end
Cleanup
cd cgit/tests
make clean
Removes the trash directories created by tests.
Writing New Tests
- Create a new file
tNNNN-description.sh - Source
setup.shand callprepare_tests:
#!/bin/sh
. ./setup.sh
prepare_tests "my new feature"
run_test 'description of test case' '
cgit_url "/foo/my-page/" | strip_headers | grep -q "expected"
'
- Make it executable:
chmod +x tNNNN-description.sh - Run:
./tNNNN-description.sh -v
CI Integration
Tests are run as part of the CI pipeline. The ci/ directory contains
Nix-based CI configuration that builds cgit and runs the test suite in a
reproducible environment.