diff --git a/.gitignore b/.gitignore index 2468476e..1d166b12 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,10 @@ missing mkinstalldirs *.tar.gz config.h.in~ + +# Ignore test output files +/tests/*.log +/tests/*.trs + +# Ignore auxiliary files +/tap-driver.sh diff --git a/Makefile.am b/Makefile.am index 26f4cae3..d1131949 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = foreign dist-zip ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src conf doc web admin win32 examples +SUBDIRS = src conf doc web admin win32 examples tests EXTRA_DIST = README.md HACKING m4/acx_pthread.m4 m4/ogg.m4 \ m4/theora.m4 m4/vorbis.m4 m4/speex.m4 \ diff --git a/configure.ac b/configure.ac index 1061da5d..86663921 100644 --- a/configure.ac +++ b/configure.ac @@ -3,6 +3,7 @@ AC_INIT([Icecast], [2.4.99.2], [icecast@xiph.org]) AC_PREREQ([2.54]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_MACRO_DIR([m4]) +AC_REQUIRE_AUX_FILE([tap-driver.sh]) dnl Process this file with autoconf to produce a configure script. AM_INIT_AUTOMAKE @@ -10,6 +11,7 @@ AM_CONFIG_HEADER([config.h]) AM_MAINTAINER_MODE AC_PROG_CC +AC_PROG_AWK AC_CANONICAL_HOST AC_PROG_LIBTOOL AC_SYS_LARGEFILE @@ -163,4 +165,4 @@ AC_OUTPUT([Makefile conf/Makefile src/Makefile src/common/avl/Makefile src/common/httpp/Makefile src/common/thread/Makefile src/common/log/Makefile src/common/net/Makefile src/common/timing/Makefile doc/Makefile web/Makefile web/assets/Makefile web/assets/css/Makefile web/assets/font/Makefile -admin/Makefile admin/includes/Makefile win32/Makefile examples/Makefile]) +admin/Makefile admin/includes/Makefile win32/Makefile examples/Makefile tests/Makefile]) diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..e445847d --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in + +TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ + $(top_srcdir)/tap-driver.sh + +TESTS = \ + startup.test \ + admin.test + +EXTRA_DIST = $(TESTS) + +EXTRA_DIST += \ + icecast.xml \ + on-connect.sh diff --git a/tests/admin-tests.sh b/tests/admin-tests.sh deleted file mode 100755 index eba336bf..00000000 --- a/tests/admin-tests.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash - -testdir=$(dirname "$0") -test -n "$testdir" && cd "$testdir" || exit - -ICECAST_BASE_URL="http://localhost:8000/" - -RETURN=0 -MOUNT_LISTENER_AUTH="foo.ogg" -MOUNT_SOURCE_AUTH="test.ogg" - -AUTH_MOUNT="foobar:hackmemore" -AUTH_SOURCE="source:hackme" -AUTH_ADMIN="admin:hackme" - -L_USER="foo" -L_PASS="bar" -L_AUTH="$L_USER:$L_PASS" - -echo "Starting Icecast" -../src/icecast -c ./icecast.xml 2> /dev/null & -ICECAST_PID=$! -sleep 5 - -echo "Starting Source client on /$MOUNT_LISTENER_AUTH" -ffmpeg -loglevel panic -re -f lavfi -i "sine=frequency=1000" -content_type application/ogg "icecast://$AUTH_SOURCE@127.0.0.1:8000/$MOUNT_LISTENER_AUTH" & -SOURCE1_PID=$! - -echo "Starting Source client on /$MOUNT_SOURCE_AUTH" -ffmpeg -loglevel panic -re -f lavfi -i "sine=frequency=1000" -content_type application/ogg "icecast://$AUTH_MOUNT@127.0.0.1:8000/$MOUNT_SOURCE_AUTH" & -SOURCE2_PID=$! - -function test_endpoint { - echo " CURL $1" - if test "x$3" == "x"; then - res=$(curl -m 5 -o /dev/null -D - "$ICECAST_BASE_URL$1" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') - else - res=$(curl -m 5 -u "$3" -o /dev/null -D - "$ICECAST_BASE_URL$1" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') - fi - if test "$(echo "$res" | cut -d$' ' -f1)" -eq "$2"; then - printf " \e[92mOK\e[39m" - echo " [$res]" - else - printf " \e[91mFAIL\e[39m" - echo " [$res] Expected: $2" - RETURN=1 - fi -} - -echo -echo "Testing admin/manageauth endpoint" -test_endpoint "admin/manageauth?id=4&username=$L_USER&password=$L_PASS&action=add" 401 -test_endpoint "admin/manageauth?id=99&username=$L_USER&password=$L_PASS&action=add" 401 -test_endpoint "admin/manageauth?id=99&username=$L_USER&password=$L_PASS&action=add" 404 "$AUTH_ADMIN" -test_endpoint "admin/manageauth?id=4&username=$L_USER&password=$L_PASS&action=add" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/buildm3u endpoint" -test_endpoint "admin/buildm3u?username=$L_USER&password=$L_PASS&mount=%2F$MOUNT_LISTENER_AUTH" 200 -test_endpoint "admin/buildm3u?username=something&password=foo&mount=%2F$MOUNT_LISTENER_AUTH" 200 - -echo -echo "Testing admin/stats endpoint" -test_endpoint "admin/stats" 401 -test_endpoint "admin/stats" 401 "$AUTH_SOURCE" -test_endpoint "admin/stats" 401 "$L_AUTH" -test_endpoint "admin/stats" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/listclients endpoint" -test_endpoint "admin/listclients" 401 -test_endpoint "admin/listclients" 401 "$AUTH_SOURCE" -test_endpoint "admin/listclients" 401 "$L_AUTH" -test_endpoint "admin/listclients" 400 "$AUTH_ADMIN" -test_endpoint "admin/listclients?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/moveclients endpoint" -test_endpoint "admin/moveclients" 401 -test_endpoint "admin/moveclients" 401 "$AUTH_SOURCE" -test_endpoint "admin/moveclients" 401 "$L_AUTH" -test_endpoint "admin/moveclients" 400 "$AUTH_ADMIN" -test_endpoint "admin/moveclients?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/updatemetadata endpoint" -test_endpoint "admin/updatemetadata" 401 -test_endpoint "admin/updatemetadata" 401 "$AUTH_SOURCE" -test_endpoint "admin/updatemetadata" 401 "$L_AUTH" -test_endpoint "admin/updatemetadata" 400 "$AUTH_ADMIN" -test_endpoint "admin/updatemetadata?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/metadata endpoint" -test_endpoint "admin/metadata" 401 -test_endpoint "admin/metadata" 401 "$AUTH_SOURCE" -test_endpoint "admin/metadata" 401 "$L_AUTH" -test_endpoint "admin/metadata" 400 "$AUTH_ADMIN" -test_endpoint "admin/metadata?mount=%2F$MOUNT_LISTENER_AUTH&mode=updinfo&charset=UTF-8&song=Test1" 200 "$AUTH_SOURCE" -test_endpoint "admin/metadata?mount=%2F$MOUNT_LISTENER_AUTH&mode=updinfo&charset=UTF-8&song=Test2" 200 "$AUTH_ADMIN" -test_endpoint "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test1" 401 "$AUTH_SOURCE" -test_endpoint "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test2" 200 "$AUTH_ADMIN" -test_endpoint "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test3" 200 "$AUTH_MOUNT" - -echo -echo "Testing admin/listmounts endpoint" -test_endpoint "admin/listmounts" 401 -test_endpoint "admin/listmounts" 401 "$AUTH_SOURCE" -test_endpoint "admin/listmounts" 401 "$L_AUTH" -test_endpoint "admin/listmounts" 200 "$AUTH_ADMIN" -test_endpoint "admin/listmounts?mount=%2F$MOUNT_LISTENER_AUTH" 400 "$AUTH_ADMIN" - -echo -echo "Testing mountpoint which requires auth" -test_endpoint "$MOUNT_LISTENER_AUTH" 401 -test_endpoint "$MOUNT_LISTENER_AUTH" 401 "$AUTH_SOURCE" -test_endpoint "$MOUNT_LISTENER_AUTH" 200 "$L_AUTH" -test_endpoint "$MOUNT_LISTENER_AUTH" 401 "$AUTH_ADMIN" - -echo -echo "Testing mountpoint which doesn't require auth" -test_endpoint "$MOUNT_SOURCE_AUTH" 200 -test_endpoint "$MOUNT_SOURCE_AUTH" 200 "$AUTH_SOURCE" -test_endpoint "$MOUNT_SOURCE_AUTH" 200 "$L_AUTH" -test_endpoint "$MOUNT_SOURCE_AUTH" 200 "$AUTH_ADMIN" - -echo -echo "Testing admin/killsource endpoint" -test_endpoint "admin/killsource" 401 -test_endpoint "admin/killsource" 401 "$AUTH_SOURCE" -test_endpoint "admin/killsource" 401 "$L_AUTH" -test_endpoint "admin/killsource" 400 "$AUTH_ADMIN" -test_endpoint "admin/killsource?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" - -echo -echo "All tests done" -echo - -if kill $SOURCE1_PID; then - echo "Terminated SOURCE1" -fi -if kill $SOURCE2_PID; then - echo "Terminated SOURCE2" -fi - -if kill $ICECAST_PID; then - echo "Terminated Icecast" -fi - -exit $RETURN diff --git a/tests/admin.test b/tests/admin.test new file mode 100755 index 00000000..e41cdbad --- /dev/null +++ b/tests/admin.test @@ -0,0 +1,184 @@ +#!/bin/bash + +testdir=$(dirname "$0") +test -n "$testdir" && cd "$testdir" || exit + +ICECAST_BASE_URL="http://localhost:8000/" +counter=1 +MOUNT_LISTENER_AUTH="foo.ogg" +MOUNT_SOURCE_AUTH="test.ogg" + +AUTH_MOUNT="foobar:hackmemore" +AUTH_SOURCE="source:hackme" +AUTH_ADMIN="admin:hackme" + +L_USER="foo" +L_PASS="bar" +L_AUTH="$L_USER:$L_PASS" + +echo "# Starting Icecast" +../src/icecast -c ./icecast.xml 2> /dev/null & +ICECAST_PID=$! +sleep 5 + +echo "# Starting Source client on /$MOUNT_LISTENER_AUTH" +ffmpeg -loglevel panic -re -f lavfi -i "sine=frequency=1000" -content_type application/ogg "icecast://$AUTH_SOURCE@127.0.0.1:8000/$MOUNT_LISTENER_AUTH" & +SOURCE1_PID=$! + +echo "# Starting Source client on /$MOUNT_SOURCE_AUTH" +ffmpeg -loglevel panic -re -f lavfi -i "sine=frequency=1000" -content_type application/ogg "icecast://$AUTH_MOUNT@127.0.0.1:8000/$MOUNT_SOURCE_AUTH" & +SOURCE2_PID=$! + +function test_endpoint { + echo "# CURL $2" + if test "x$4" == "x"; then + res=$(curl -m 5 -o /dev/null -D - "$ICECAST_BASE_URL$2" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') + else + res=$(curl -m 5 -u "$4" -o /dev/null -D - "$ICECAST_BASE_URL$2" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') + fi + if test "$(echo "$res" | cut -d$' ' -f1)" -eq "$3"; then + echo "# OK [$res]" + echo "ok $counter - $1" + else + echo " FAIL [$res] Expected: $3" + echo "not ok $counter - $1" + fi + ((counter++)) +} + +function test_sourcing { + echo "# CURL $2" + if test "x$4" == "x"; then + res=$(curl -X PUT -m 5 -d /dev/random -o /dev/null -D - "$ICECAST_BASE_URL$2" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') + else + res=$(dd if=/dev/urandom bs=8 count=32 2>/dev/null | curl -X PUT -m 5 -H "Content-Type: application/octet-stream" --data-binary "@-" -v -u "$4" -o /dev/null -D - "$ICECAST_BASE_URL$2" 2>/dev/null | head -n 1 | cut -d$' ' -f2- | tr -d '\r\n') + fi + if test "$(echo "$res" | cut -d$' ' -f1)" -eq "$3"; then + echo "# OK [$res]" + echo "ok $counter - $1" + else + echo "# FAIL [$res] Expected: $3" + echo "not ok $counter - $1" + fi + ((counter++)) +} + +echo "#" +echo "# Testing admin/manageauth endpoint" +test_endpoint "manageauth-add-noauth" "admin/manageauth?id=4&username=$L_USER&password=$L_PASS&action=add" 401 +test_endpoint "manageauth-add-invalid-noauth" "admin/manageauth?id=99&username=$L_USER&password=$L_PASS&action=add" 401 +test_endpoint "manageauth-add-invalid" "admin/manageauth?id=99&username=$L_USER&password=$L_PASS&action=add" 404 "$AUTH_ADMIN" +test_endpoint "manageauth-add-valid" "admin/manageauth?id=4&username=$L_USER&password=$L_PASS&action=add" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/buildm3u endpoint" +test_endpoint "buildm3u-user" "admin/buildm3u?username=$L_USER&password=$L_PASS&mount=%2F$MOUNT_LISTENER_AUTH" 200 +test_endpoint "buildm3u-fakeuser" "admin/buildm3u?username=something&password=foo&mount=%2F$MOUNT_LISTENER_AUTH" 200 + +echo "#" +echo "# Testing admin/stats endpoint" +test_endpoint "stats-noauth" "admin/stats" 401 +test_endpoint "stats-sourceauth" "admin/stats" 401 "$AUTH_SOURCE" +test_endpoint "stats-listenerauth" "admin/stats" 401 "$L_AUTH" +test_endpoint "stats-adminauth" "admin/stats" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/listclients endpoint" +test_endpoint "listclients-noauth" "admin/listclients" 401 +test_endpoint "listclients-sourceauth" "admin/listclients" 401 "$AUTH_SOURCE" +test_endpoint "listclients-listenerauth" "admin/listclients" 401 "$L_AUTH" +test_endpoint "listclients-adminauth-invalid" "admin/listclients" 400 "$AUTH_ADMIN" +test_endpoint "listclients-adminauth" "admin/listclients?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/moveclients endpoint" +test_endpoint "moveclients-noauth" "admin/moveclients" 401 +test_endpoint "moveclients-sourceauth" "admin/moveclients" 401 "$AUTH_SOURCE" +test_endpoint "moveclients-listenerauth" "admin/moveclients" 401 "$L_AUTH" +test_endpoint "moveclients-adminauth-invalid" "admin/moveclients" 400 "$AUTH_ADMIN" +test_endpoint "moveclients-adminauth" "admin/moveclients?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/updatemetadata endpoint" +test_endpoint "updatemetadata-noauth" "admin/updatemetadata" 401 +test_endpoint "updatemetadata-sourceauth" "admin/updatemetadata" 401 "$AUTH_SOURCE" +test_endpoint "updatemetadata-listenerauth" "admin/updatemetadata" 401 "$L_AUTH" +test_endpoint "updatemetadata-adminauth-invalid" "admin/updatemetadata" 400 "$AUTH_ADMIN" +test_endpoint "updatemetadata-adminauth" "admin/updatemetadata?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/metadata endpoint" +test_endpoint "metadata-noauth" "admin/metadata" 401 +test_endpoint "metadata-sourceauth" "admin/metadata" 401 "$AUTH_SOURCE" +test_endpoint "metadata-listenerauth" "admin/metadata" 401 "$L_AUTH" +test_endpoint "metadata-adminauth-invalid" "admin/metadata" 400 "$AUTH_ADMIN" +test_endpoint "metadata-sourceauth" "admin/metadata?mount=%2F$MOUNT_LISTENER_AUTH&mode=updinfo&charset=UTF-8&song=Test1" 200 "$AUTH_SOURCE" +test_endpoint "metadata-adminauth" "admin/metadata?mount=%2F$MOUNT_LISTENER_AUTH&mode=updinfo&charset=UTF-8&song=Test2" 200 "$AUTH_ADMIN" +test_endpoint "metadata-sourceauth" "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test1" 401 "$AUTH_SOURCE" +test_endpoint "metadata-adminauth" "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test2" 200 "$AUTH_ADMIN" +test_endpoint "metadata-mountauth" "admin/metadata?mount=%2F$MOUNT_SOURCE_AUTH&mode=updinfo&charset=UTF-8&song=Test3" 200 "$AUTH_MOUNT" + +echo "#" +echo "# Testing admin/listmounts endpoint" +test_endpoint "listmounts-noauth" "admin/listmounts" 401 +test_endpoint "listmounts-sourceauth" "admin/listmounts" 401 "$AUTH_SOURCE" +test_endpoint "listmounts-listenerauth" "admin/listmounts" 401 "$L_AUTH" +test_endpoint "listmounts-adminauth" "admin/listmounts" 200 "$AUTH_ADMIN" +test_endpoint "listmounts-adminauth-mount" "admin/listmounts?mount=%2F$MOUNT_LISTENER_AUTH" 400 "$AUTH_ADMIN" + +echo "#" +echo "# Testing mountpoint which requires auth" +test_endpoint "authmount-noauth" "$MOUNT_LISTENER_AUTH" 401 +test_endpoint "authmount-sourceauth" "$MOUNT_LISTENER_AUTH" 401 "$AUTH_SOURCE" +test_endpoint "authmount-listenerauth" "$MOUNT_LISTENER_AUTH" 200 "$L_AUTH" +test_endpoint "authmount-adminauth" "$MOUNT_LISTENER_AUTH" 401 "$AUTH_ADMIN" + +echo "#" +echo "# Testing mountpoint which doesn't require auth" +test_endpoint "mount-noauth" "$MOUNT_SOURCE_AUTH" 200 +test_endpoint "mount-sourceauth" "$MOUNT_SOURCE_AUTH" 200 "$AUTH_SOURCE" +test_endpoint "mount-listenerauth" "$MOUNT_SOURCE_AUTH" 200 "$L_AUTH" +test_endpoint "mount-adminauth" "$MOUNT_SOURCE_AUTH" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing admin/killsource endpoint" +test_endpoint "killsource-noauth" "admin/killsource" 401 +test_endpoint "killsource-sourceauth" "admin/killsource" 401 "$AUTH_SOURCE" +test_endpoint "killsource-listenerauth" "admin/killsource" 401 "$L_AUTH" +test_endpoint "killsource-adminauth-invalid" "admin/killsource" 400 "$AUTH_ADMIN" +test_endpoint "killsource-adminauth" "admin/killsource?mount=%2F$MOUNT_LISTENER_AUTH" 200 "$AUTH_ADMIN" + +echo "#" +echo "# Testing on-connect handling with probing" +test_sourcing "on-connect-test-noauth" "test-on-connect.ogg" 401 +if [ -f "on-connect-success" ]; then + echo "# FAIL: on-connect triggered, even though it should not!" + rm "on-connect-success" +fi +test_sourcing "on-connect-test-sourceauth" "test-on-connect.ogg" 200 "$AUTH_SOURCE" +if [ -f "on-connect-success" ]; then + echo "# OK: on-connect triggered!" + rm "on-connect-success" +else + echo "# FAIL: on-connect not triggered!" +fi + +echo "#" +echo "# All tests done, cleanup..." +echo "#" + +rm "myauth" + +if kill $SOURCE1_PID > /dev/null 2>&1; then + echo "# Terminated SOURCE1" +fi +if kill $SOURCE2_PID > /dev/null 2>&1; then + echo "# Terminated SOURCE2" +fi + +if kill $ICECAST_PID > /dev/null 2>&1; then + echo "# Terminated Icecast" +fi + +echo "1..$(((counter-1)))" # Number of tests to be executed. +exit 0 diff --git a/tests/icecast.xml b/tests/icecast.xml index 3e0503f5..d1b4a313 100644 --- a/tests/icecast.xml +++ b/tests/icecast.xml @@ -41,6 +41,11 @@ hackmemore + + /test-on-connect.ogg + on-connect.sh + + /foo.ogg diff --git a/tests/on-connect.sh b/tests/on-connect.sh new file mode 100755 index 00000000..3a288f1b --- /dev/null +++ b/tests/on-connect.sh @@ -0,0 +1,3 @@ +#!/bin/bash +touch "on-connect-success" +exit 0 diff --git a/tests/startup.test b/tests/startup.test new file mode 100755 index 00000000..720a9c08 --- /dev/null +++ b/tests/startup.test @@ -0,0 +1,19 @@ +#!/bin/sh +../src/icecast -c ./icecast.xml 2> /dev/null & +ICECAST_PID=$! +echo 'ok 1 - Icecast started' +sleep 3 + +if kill -0 $ICECAST_PID > /dev/null 2>&1; then + echo 'ok 2 - Icecast running' +else + echo 'not ok 2 - Icecast not running' +fi + +if kill $ICECAST_PID > /dev/null 2>&1; then + echo 'ok 3 - Icecast stopped' +else + echo 'not ok 3 - Icecast not stopped' +fi + +echo 1..3 # Number of tests to be executed.