commit 6ae16afd7eb87b9d1ae10d16f29e1a66649decc7 from: Stefan Sperling date: Mon Oct 31 07:39:41 2022 UTC add a test suite for gotd(8); check basic clone and send functionality commit - 1c9d898d6c7c6c8681e8e191ebe2c01b8d066f6e commit + 6ae16afd7eb87b9d1ae10d16f29e1a66649decc7 blob - fe7db9a3d673041a04256447d4b529fc4109ed8c blob + 99d51d96d08b0d903c4f125505849210d5da93b2 --- Makefile +++ Makefile @@ -55,4 +55,7 @@ server-install: ${MAKE} -C gotd install ${MAKE} -C gotsh install +server-regress: + ${MAKE} -C regress/gotd + .include blob - b970ee903b827d35f5b176c68200ec092a13d4e8 blob + 6e6a2e8391b5ff02c1bdb7753f0ec1b51a1ff8a9 --- README +++ README @@ -76,7 +76,9 @@ See the following manual page files for information ab $ man -l gotctl/gotctl.8 $ man -l gotsh/gotsh.1 +See regress/gotd/README for information about running the server test suite. + Game of Trees Web (Gotweb) is a CGI program which displays repository data and is designed to work with httpd(8) and slowcgi(8). It requires the Kristaps Dzonsons kcgi library, version 0.12.0 or greater. blob - /dev/null blob + 7c2992be4f288b02a06aa7cc8ee97b9df22737f2 (mode 644) --- /dev/null +++ regress/gotd/Makefile @@ -0,0 +1,63 @@ +REGRESS_TARGETS=test_repo_read test_repo_write +NOOBJ=Yes + +.PHONY: ensure_root prepare_test_repo check_test_repo start_gotd + +GOTD_TEST_ROOT=/tmp +GOTD_DEVUSER?=gotdev +GOTD_DEVUSER_HOME!=userinfo $(GOTD_DEVUSER) | grep ^dir | awk '{print $$2}' +GOTD_TEST_REPO!?=mktemp -d "$(GOTD_TEST_ROOT)/gotd-test-repo-XXXXXXXXX" +GOTD_TEST_REPO_URL=ssh://${GOTD_DEVUSER}@127.0.0.1/test-repo + +GOTD_TEST_USER?=${LOGNAME} +GOTD_TEST_USER_HOME!=userinfo $(GOTD_TEST_USER) | grep ^dir | awk '{print $$2}' + +# gotd.conf parameters +GOTD_USER?=got +GOTD_GROUP?=gotsh +GOTD_SOCK=${GOTD_DEVUSER_HOME}/gotd.sock + +GOTD_START_CMD=../../gotd/obj/gotd -vv -f $(PWD)/gotd.conf +GOTD_STOP_CMD=../../gotctl/obj/gotctl -f $(GOTD_SOCK) stop +GOTD_TRAP=trap "$(GOTD_STOP_CMD)" HUP INT QUIT PIPE TERM + +GOTD_TEST_ENV=GOTD_TEST_ROOT=$(GOTD_TEST_ROOT) \ + GOTD_TEST_REPO_URL=$(GOTD_TEST_REPO_URL) \ + GOTD_TEST_REPO=$(GOTD_TEST_REPO) \ + GOTD_SOCK=$(GOTD_SOCK) \ + HOME=$(GOTD_TEST_USER_HOME) \ + PATH=$(GOTD_TEST_USER_HOME)/bin:$(PATH) + +ensure_root: + @if [[ `id -u` -ne 0 ]]; then \ + echo gotd test suite must be run by root >&2; \ + false; \ + fi + +start_gotd: ensure_root + @echo 'unix_socket "$(GOTD_SOCK)"' > $(PWD)/gotd.conf + @echo "unix_group $(GOTD_GROUP)" >> $(PWD)/gotd.conf + @echo "user $(GOTD_USER)" >> $(PWD)/gotd.conf + @echo 'repository "test-repo" {' >> $(PWD)/gotd.conf + @echo ' path "$(GOTD_TEST_REPO)"' >> $(PWD)/gotd.conf + @echo "}" >> $(PWD)/gotd.conf + @$(GOTD_TRAP); $(GOTD_START_CMD) + @$(GOTD_TRAP); sleep .5 + +prepare_test_repo: ensure_root + @chown ${GOTD_USER} "${GOTD_TEST_REPO}" + @su -m ${GOTD_USER} -c 'env $(GOTD_TEST_ENV) sh ./prepare_test_repo.sh' + +test_repo_read: prepare_test_repo start_gotd + @-$(GOTD_TRAP); su ${GOTD_TEST_USER} -c \ + 'env $(GOTD_TEST_ENV) sh ./repo_read.sh' + @$(GOTD_STOP_CMD) 2>/dev/null + @su -m ${GOTD_USER} -c 'env $(GOTD_TEST_ENV) sh ./check_test_repo.sh' + +test_repo_write: prepare_test_repo start_gotd + @-$(GOTD_TRAP); su ${GOTD_TEST_USER} -c \ + 'env $(GOTD_TEST_ENV) sh ./repo_write.sh' + @$(GOTD_STOP_CMD) 2>/dev/null + @su -m ${GOTD_USER} -c 'env $(GOTD_TEST_ENV) sh ./check_test_repo.sh' + +.include blob - /dev/null blob + e45f172997d4e491bc2a34fe0494284c43c94cfb (mode 644) --- /dev/null +++ regress/gotd/README @@ -0,0 +1,57 @@ +Running server regression tests requires some manual system preparation. + +Two dedicated user accounts and a group must be created. Password login +for these users should be disabled by passing a blank password to useradd +and confirming useradd's question about disabling passwords with 'yes'. + + $ doas adduser got + $ doas adduser gotdev + $ doas addgroup gotsh + +The above user and group names correspond to defaults used by the test suite. +If needed, the defaults can be overridden on by passing values for the +following variables to make(1): GOTD_USER, GOTD_DEVUSER, GOTD_GROUP + +An SSH key must be added to ~gotdev/.ssh/authorized_keys, such that the +following command succeeds non-interactively: + + $ ssh gotdev@127.0.0.1 + +The login shell of the gotdev user should be set to gotsh(1). +It is recommended to run the test suite using a locally built gotsh binary, +rather than /usr/local/bin/gotsh (which might be using messages in an +out-of-date format on the gotd socket). +For this to work, $HOME/bin/gotsh must be added to /etc/shells first. + + $ doas usermod -s $HOME/bin/gotsh gotdev + +If adding this file to /etc/shells is a problem, a locally built gotsh +binary can be made available in the command search path of the gotdev +user under the names git-receive-pack and git-upload-pack. When made +available in a non-standard PATH directory such as ~gotdev/bin, the +gotdev user's PATH must be set appropriately in sshd_config (see below). + +Tests will run the locally built gotd binary found in gotd/obj/gotd. +The test suite creates the corresponding gotd socket in ~gotdev/gotd.sock. +To make this work, the GOTD_UNIX_SOCKET variable must be set by sshd +when the gotdev user logs in. The following should be added to the file +/etc/ssh/sshd_config: + + Match User gotdev + SetEnv GOTD_UNIX_SOCKET=/home/gotdev/gotd.sock + # The following line is not needed when gotsh is used as login shell: + SetEnv PATH=/home/gotdev/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin + DisableForwarding yes + PermitTTY no + +sshd must be restarted for configuration changes to take effect: + + $ doas rcctl restart sshd + +The server test suite can now be run from the top-level directory: + + $ doas pkg_add git # if not already done + $ doas make server-regress + +The suite must be started as root in order to be able to start and stop gotd. +The test suite switches to non-root users as appropriate. blob - /dev/null blob + dfb810129ddb968ff5a57845ede251ff9daead91 (mode 644) --- /dev/null +++ regress/gotd/check_test_repo.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Copyright (c) 2022 Stefan Sperling +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +. ../cmdline/common.sh + +git_fsck "${GOTD_TEST_REPO}" "${GOTD_TEST_REPO}" blob - /dev/null blob + 016110f9a8369c7d2288fbc68fa858b04c36f2c4 (mode 644) --- /dev/null +++ regress/gotd/common.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Copyright (c) 2022 Stefan Sperling +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +test_init() +{ + local testname="$1" + local no_tree="$2" + if [ -z "$testname" ]; then + echo "No test name provided" >&2 + return 1 + fi + local testroot=`mktemp -d "$GOTD_TEST_ROOT/gotd-test-$testname-XXXXXXXX"` + mkdir $testroot/repo + git_init $testroot/repo + if [ -z "$no_tree" ]; then + make_test_tree $testroot/repo + (cd $repo && git add .) + git_commit $testroot/repo -m "adding the test tree" + fi + echo "$testroot" +} + +test_done() +{ + local testroot="$1" + local result="$2" + if [ "$result" = "0" ]; then + test_cleanup "$testroot" || return 1 + if [ -z "$GOT_TEST_QUIET" ]; then + echo "ok" + fi + elif echo "$result" | grep -q "^xfail"; then + # expected test failure; test reproduces an unfixed bug + echo "$result" + test_cleanup "$testroot" || return 1 + else + echo "test failed; leaving test data in $testroot" + fi +} blob - /dev/null blob + 712a02a775533761863f614cf975ef0dae5a8b49 (mode 644) --- /dev/null +++ regress/gotd/prepare_test_repo.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (c) 2022 Stefan Sperling +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +. ../cmdline/common.sh + +if [ -e "${GOTD_TEST_REPO}" ]; then + rm -rf "${GOTD_TEST_REPO}" +fi + +gotadmin init "${GOTD_TEST_REPO}" + +test_tree=`mktemp -d "${GOTD_TEST_ROOT}/gotd-test-tree-XXXXXXXXX"` +make_test_tree "$test_tree" +got import -m "import the test tree" -r "${GOTD_TEST_REPO}" "$test_tree" \ + > /dev/null +rm -r "$test_tree" # TODO: trap blob - /dev/null blob + 82df572967b423dd79abedbe9e1315e14be9b6bf (mode 644) --- /dev/null +++ regress/gotd/repo_read.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# +# Copyright (c) 2022 Stefan Sperling +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +. ../cmdline/common.sh +. ./common.sh + +test_clone_basic() { + local testroot=`test_init clone_basic 1` + + cp -r ${GOTD_TEST_REPO} $testroot/repo-copy + + got clone -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone + ret=$? + if [ $ret -ne 0 ]; then + echo "got clone failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + # Verify that the clone operation worked fine. + git_fsck "$testroot" "$testroot/repo-clone" + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" "1" + return 1 + fi + + got tree -R -r "$testroot/repo-clone" > $testroot/stdout + cat > $testroot/stdout.expected < $testroot/stdout + echo -n > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + +test_parseargs "$@" +run_test test_clone_basic blob - /dev/null blob + 9ae1427dc0f407b85f6caeec7b424406e17b7cac (mode 644) --- /dev/null +++ regress/gotd/repo_write.sh @@ -0,0 +1,114 @@ +#!/bin/sh +# +# Copyright (c) 2022 Stefan Sperling +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +. ../cmdline/common.sh +. ./common.sh + +test_send_basic() { + local testroot=`test_init send_basic 1` + + ls -R ${GOTD_TEST_REPO} > $testroot/repo-list.before + + got clone -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone + ret=$? + if [ $ret -ne 0 ]; then + echo "got clone failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + got checkout -q $testroot/repo-clone $testroot/wt >/dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "got checkout failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + mkdir $testroot/wt/psi + echo "new" > $testroot/wt/psi/new + (cd $testroot/wt && got add psi/new > /dev/null) + echo "more alpha" >> $testroot/wt/alpha + (cd $testroot/wt && got commit -m 'make changes' > /dev/null) + + got send -q -r $testroot/repo-clone + ret=$? + if [ $ret -ne 0 ]; then + echo "got send failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + # Verify that the send operation worked fine. + got clone -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone2 + ret=$? + if [ $ret -ne 0 ]; then + echo "got clone failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + got tree -R -r $testroot/repo-clone2 > $testroot/stdout + cat > $testroot/stdout.expected < $testroot/repo-list.after + diff -u $testroot/repo-list.before $testroot/repo-list.after \ + > $testroot/repo-list.diff + grep '^+[^+]' < $testroot/repo-list.diff > $testroot/repo-list.newlines + nplus=`wc -l < $testroot/repo-list.newlines | tr -d ' '` + if [ "$nplus" != "2" ]; then + echo "$nplus new files created" + test_done "$testroot" "$ret" + return 1 + fi + egrep -q '\+pack-[a-f0-9]{40}.pack' $testroot/repo-list.newlines + ret=$? + if [ $ret -ne 0 ]; then + echo "new pack file not found in ${GOTD_TEST_REPO}" + cat $testroot/repo-list.newlines + test_done "$testroot" "$ret" + return 1 + fi + egrep -q '\+pack-[a-f0-9]{40}.idx' $testroot/repo-list.newlines + ret=$? + if [ $ret -ne 0 ]; then + echo "new pack index not found in ${GOTD_TEST_REPO}" + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + +test_parseargs "$@" +run_test test_send_basic