
Unit testing and guacamole-server
=================================

Unit tests within guacamole-server are implemented using the following:

* automake, which allows arbitrary tests to be declared within `Makefile.am`
  and uses `make check` to run those tests.
* CUnit (libcunit), a unit testing framework.
* `util/generate-test-runner.pl`, a Perl script which generates a test runner
  written in C which leverages CUnit, running the unit tests declared in each
  of the given `.c` files. The generated test runner produces output in [TAP
  format](https://testanything.org/) which is consumed by the TAP test driver
  provided by automake.

Writing unit tests
------------------

All unit tests should be within reasonably-isolated C source files, with each
logical test having its own function of the form:

    void test_SUITENAME__TESTNAME() {
        ...
    }

where `TESTNAME` is the arbitrary name of the test and `SUITENAME` is the
arbitrary name of the test suite that this test belongs to.

**This naming convention is required by `generate-test-runner.pl`.** Absolutely
all tests MUST follow the above convention if they are to be picked up and
organized by the test runner generation script. Functions which are not tests
MUST NOT follow the above convention so that they are _not_ picked up mistakenly
by the test runner generator as if they were tests.

The `Makefile.am` for a subproject which contains such tests is typically
modified to contain a sections like the following:

    #
    # Unit tests for myproj
    #

    check_PROGRAMS = test_myproj
    TESTS = $(check_PROGRAMS)

    test_myproj_SOURCES =      \
        ...all source files...

    test_myproj_CFLAGS =        \
        -Werror -Wall -pedantic \
        ...other flags...

    test_myproj_LDADD = \
        ...libraries...

    #
    # Autogenerate test runner
    #

    GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl
    CLEANFILES = _generated_runner.c

    _generated_runner.c: $(test_myproj_SOURCES)
    	$(AM_V_GEN) $(GEN_RUNNER) $(test_myproj_SOURCES) > $@

    nodist_test_libguac_SOURCES = \
        _generated_runner.c

    # Use automake's TAP test driver for running any tests
    LOG_DRIVER =                \
        env AM_TAP_AWK='$(AWK)' \
        $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh

The above declares ...

* ... that a binary, `test_myproj` should be built from the given sources.
  Note that `test_myproj_SOURCES` contains only the source which was actually
  written by hand while `nodist_test_myproj_SOURCES` contains only the source
  which was generated by `generate-test-runner.pl`.
* ... that this `test_myproj` binary should be run to test this project when
  `make check` is run, and that automake's TAP driver should be used to
  consume its output.
* ... that the `_generated_runner.c` source file is generated dynamically
  (through running `generate-test-runner.pl` on all non-generated test source)
  and should not be distributed as part of the source archive.

With tests following the above naming convention in place, and with the
necessary changes made to the applicable `Makefile.am`, all tests will be
run automatically when `make check` is run.

