GUACAMOLE-662: Merge fix handling of unit tests within buid.
This commit is contained in:
commit
aba7b987d3
15
.gitignore
vendored
15
.gitignore
vendored
@ -28,27 +28,16 @@ Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
build-aux/
|
||||
libtool
|
||||
m4/*
|
||||
!README
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
test-driver
|
||||
|
||||
# Test binaries
|
||||
tests/test_*
|
||||
!tests/test_*.[ch]
|
||||
|
||||
# Generated docs
|
||||
doc/doxygen-output
|
||||
|
25
Makefile.am
25
Makefile.am
@ -39,13 +39,11 @@ DIST_SUBDIRS = \
|
||||
src/protocols/rdp \
|
||||
src/protocols/ssh \
|
||||
src/protocols/telnet \
|
||||
src/protocols/vnc \
|
||||
tests
|
||||
src/protocols/vnc
|
||||
|
||||
SUBDIRS = \
|
||||
src/libguac \
|
||||
src/common \
|
||||
tests
|
||||
src/common
|
||||
|
||||
if ENABLE_COMMON_SSH
|
||||
SUBDIRS += src/common-ssh
|
||||
@ -91,13 +89,14 @@ if ENABLE_GUACLOG
|
||||
SUBDIRS += src/guaclog
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
.dockerignore \
|
||||
CONTRIBUTING \
|
||||
Dockerfile \
|
||||
LICENSE \
|
||||
NOTICE \
|
||||
bin/guacctl \
|
||||
doc/Doxyfile.in \
|
||||
src/guacd-docker
|
||||
EXTRA_DIST = \
|
||||
.dockerignore \
|
||||
CONTRIBUTING \
|
||||
Dockerfile \
|
||||
LICENSE \
|
||||
NOTICE \
|
||||
bin/guacctl \
|
||||
doc/Doxyfile.in \
|
||||
src/guacd-docker \
|
||||
util/generate-test-runner.pl
|
||||
|
||||
|
89
README-unit-testing.md
Normal file
89
README-unit-testing.md
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
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) $^ > $@
|
||||
|
||||
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.
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
AC_PREREQ([2.61])
|
||||
AC_INIT([guacamole-server], [1.0.0])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
@ -28,6 +29,9 @@ LT_INIT([dlopen])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Use TAP test driver for tests (part of automake)
|
||||
AC_REQUIRE_AUX_FILE([tap-driver.sh])
|
||||
|
||||
# Programs
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
@ -1299,11 +1303,12 @@ AM_CONDITIONAL([ENABLE_GUACLOG], [test "x${enable_guaclog}" = "xyes"])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
doc/Doxyfile
|
||||
tests/Makefile
|
||||
src/common/Makefile
|
||||
src/common/tests/Makefile
|
||||
src/common-ssh/Makefile
|
||||
src/terminal/Makefile
|
||||
src/libguac/Makefile
|
||||
src/libguac/tests/Makefile
|
||||
src/guacd/Makefile
|
||||
src/guacd/man/guacd.8
|
||||
src/guacd/man/guacd.conf.5
|
||||
|
9
src/common/.gitignore
vendored
Normal file
9
src/common/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Auto-generated test runner and binary
|
||||
_generated_runner.c
|
||||
test_common
|
||||
|
||||
# Test suite output
|
||||
*.log
|
||||
*.trs
|
||||
|
@ -27,6 +27,7 @@ AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
noinst_LTLIBRARIES = libguac_common.la
|
||||
SUBDIRS = . tests
|
||||
|
||||
noinst_HEADERS = \
|
||||
common/io.h \
|
||||
|
72
src/common/tests/Makefile.am
Normal file
72
src/common/tests/Makefile.am
Normal file
@ -0,0 +1,72 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim
|
||||
# into Makefile.in. Though the build system (GNU Autotools) automatically adds
|
||||
# its own license boilerplate to the generated Makefile.in, that boilerplate
|
||||
# does not apply to the transcluded portions of Makefile.am which are licensed
|
||||
# to you by the ASF under the Apache License, Version 2.0, as described above.
|
||||
#
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
#
|
||||
# Unit tests for libguac_common
|
||||
#
|
||||
|
||||
check_PROGRAMS = test_common
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
test_common_SOURCES = \
|
||||
iconv/convert.c \
|
||||
rect/clip_and_split.c \
|
||||
rect/constrain.c \
|
||||
rect/expand_to_grid.c \
|
||||
rect/extend.c \
|
||||
rect/init.c \
|
||||
rect/intersects.c \
|
||||
string/count_occurrences.c \
|
||||
string/split.c
|
||||
|
||||
test_common_CFLAGS = \
|
||||
-Werror -Wall -pedantic \
|
||||
@COMMON_INCLUDE@
|
||||
|
||||
test_common_LDADD = \
|
||||
@COMMON_LTLIB@ \
|
||||
@CUNIT_LIBS@
|
||||
|
||||
#
|
||||
# Autogenerate test runner
|
||||
#
|
||||
|
||||
GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl
|
||||
CLEANFILES = _generated_runner.c
|
||||
|
||||
_generated_runner.c: $(test_common_SOURCES)
|
||||
$(AM_V_GEN) $(GEN_RUNNER) $^ > $@
|
||||
|
||||
nodist_test_common_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
|
||||
|
@ -17,15 +17,75 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "common_suite.h"
|
||||
#include "common/iconv.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
static void test_conversion(
|
||||
/**
|
||||
* UTF8 for "papà è bello".
|
||||
*/
|
||||
unsigned char test_string_utf8[] = {
|
||||
'p', 'a', 'p', 0xC3, 0xA0, ' ',
|
||||
0xC3, 0xA8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF16 for "papà è bello".
|
||||
*/
|
||||
unsigned char test_string_utf16[] = {
|
||||
'p', 0x00, 'a', 0x00, 'p', 0x00, 0xE0, 0x00, ' ', 0x00,
|
||||
0xE8, 0x00, ' ', 0x00,
|
||||
'b', 0x00, 'e', 0x00, 'l', 0x00, 'l', 0x00, 'o', 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
/**
|
||||
* ISO-8859-1 for "papà è bello".
|
||||
*/
|
||||
unsigned char test_string_iso8859_1[] = {
|
||||
'p', 'a', 'p', 0xE0, ' ',
|
||||
0xE8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/**
|
||||
* CP1252 for "papà è bello".
|
||||
*/
|
||||
unsigned char test_string_cp1252[] = {
|
||||
'p', 'a', 'p', 0xE0, ' ',
|
||||
0xE8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that conversion between character sets using the given guac_iconv_read
|
||||
* and guac_iconv_write implementations matches expectations.
|
||||
*
|
||||
* @param reader
|
||||
* The guac_iconv_read implementation to use to read the input string.
|
||||
*
|
||||
* @param in_string
|
||||
* A pointer to the beginning of the input string.
|
||||
*
|
||||
* @param in_length
|
||||
* The size of the input string in bytes.
|
||||
*
|
||||
* @param writer
|
||||
* The guac_iconv_write implementation to use to write the output string
|
||||
* (the converted input string).
|
||||
*
|
||||
* @param out_string
|
||||
* A pointer to the beginning of a string which contains the expected
|
||||
* result of the conversion.
|
||||
*
|
||||
* @param out_length
|
||||
* The size of the expected result in bytes.
|
||||
*/
|
||||
static void verify_conversion(
|
||||
guac_iconv_read* reader, unsigned char* in_string, int in_length,
|
||||
guac_iconv_write* writer, unsigned char* out_string, int out_length) {
|
||||
|
||||
@ -50,77 +110,74 @@ static void test_conversion(
|
||||
|
||||
}
|
||||
|
||||
void test_guac_iconv() {
|
||||
|
||||
/* UTF8 for "papà è bello" */
|
||||
unsigned char test_string_utf8[] = {
|
||||
'p', 'a', 'p', 0xC3, 0xA0, ' ',
|
||||
0xC3, 0xA8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/* UTF16 for "papà è bello" */
|
||||
unsigned char test_string_utf16[] = {
|
||||
'p', 0x00, 'a', 0x00, 'p', 0x00, 0xE0, 0x00, ' ', 0x00,
|
||||
0xE8, 0x00, ' ', 0x00,
|
||||
'b', 0x00, 'e', 0x00, 'l', 0x00, 'l', 0x00, 'o', 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
/* ISO-8859-1 for "papà è bello" */
|
||||
unsigned char test_string_iso8859_1[] = {
|
||||
'p', 'a', 'p', 0xE0, ' ',
|
||||
0xE8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/* CP1252 for "papà è bello" */
|
||||
unsigned char test_string_cp1252[] = {
|
||||
'p', 'a', 'p', 0xE0, ' ',
|
||||
0xE8, ' ',
|
||||
'b', 'e', 'l', 'l', 'o',
|
||||
0x00
|
||||
};
|
||||
|
||||
/* UTF8 identity */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-8 to itself.
|
||||
*/
|
||||
void test_iconv__utf8_to_utf8() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF8, test_string_utf8, sizeof(test_string_utf8),
|
||||
GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8));
|
||||
}
|
||||
|
||||
/* UTF16 identity */
|
||||
test_conversion(
|
||||
GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16),
|
||||
GUAC_WRITE_UTF16, test_string_utf16, sizeof(test_string_utf16));
|
||||
|
||||
/* UTF8 to UTF16 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-16 to UTF-8.
|
||||
*/
|
||||
void test_iconv__utf8_to_utf16() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF8, test_string_utf8, sizeof(test_string_utf8),
|
||||
GUAC_WRITE_UTF16, test_string_utf16, sizeof(test_string_utf16));
|
||||
}
|
||||
|
||||
/* UTF16 to UTF8 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-16 to itself.
|
||||
*/
|
||||
void test_iconv__utf16_to_utf16() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16),
|
||||
GUAC_WRITE_UTF16, test_string_utf16, sizeof(test_string_utf16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-8 to UTF-16.
|
||||
*/
|
||||
void test_iconv__utf16_to_utf8() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16),
|
||||
GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8));
|
||||
}
|
||||
|
||||
/* UTF16 to ISO-8859-1 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-16 to ISO 8859-1.
|
||||
*/
|
||||
void test_iconv__utf16_to_iso8859_1() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16),
|
||||
GUAC_WRITE_ISO8859_1, test_string_iso8859_1, sizeof(test_string_iso8859_1));
|
||||
}
|
||||
|
||||
/* UTF16 to CP1252 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of UTF-16 to CP1252.
|
||||
*/
|
||||
void test_iconv__utf16_to_cp1252() {
|
||||
verify_conversion(
|
||||
GUAC_READ_UTF16, test_string_utf16, sizeof(test_string_utf16),
|
||||
GUAC_WRITE_CP1252, test_string_cp1252, sizeof(test_string_cp1252));
|
||||
}
|
||||
|
||||
/* CP1252 to UTF8 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of CP1252 to UTF-8.
|
||||
*/
|
||||
void test_iconv__cp1252_to_utf8() {
|
||||
verify_conversion(
|
||||
GUAC_READ_CP1252, test_string_cp1252, sizeof(test_string_cp1252),
|
||||
GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8));
|
||||
}
|
||||
|
||||
/* ISO-8859-1 to UTF8 */
|
||||
test_conversion(
|
||||
/**
|
||||
* Tests which verifies conversion of ISO 8859-1 to UTF-8.
|
||||
*/
|
||||
void test_iconv__iso8859_1_to_utf8() {
|
||||
verify_conversion(
|
||||
GUAC_READ_ISO8859_1, test_string_iso8859_1, sizeof(test_string_iso8859_1),
|
||||
GUAC_WRITE_UTF8, test_string_utf8, sizeof(test_string_utf8));
|
||||
|
156
src/common/tests/rect/clip_and_split.c
Normal file
156
src/common/tests/rect/clip_and_split.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
/**
|
||||
* Test which verifies that guac_common_rect_clip_and_split() divides a
|
||||
* rectangle into subrectangles after removing a "hole" rectangle.
|
||||
*/
|
||||
void test_rect__clip_and_split() {
|
||||
|
||||
int res;
|
||||
|
||||
guac_common_rect cut;
|
||||
guac_common_rect min;
|
||||
guac_common_rect rect;
|
||||
|
||||
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||
|
||||
/* Clip top */
|
||||
guac_common_rect_init(&rect, 10, 5, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(5, cut.y);
|
||||
CU_ASSERT_EQUAL(10, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(5, rect.height);
|
||||
|
||||
/* Clip bottom */
|
||||
guac_common_rect_init(&rect, 10, 15, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(20, cut.y);
|
||||
CU_ASSERT_EQUAL(10, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(15, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(5, rect.height);
|
||||
|
||||
/* Clip left */
|
||||
guac_common_rect_init(&rect, 5, 10, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(5, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Clip right */
|
||||
guac_common_rect_init(&rect, 15, 10, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(20, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(15, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(5, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/*
|
||||
* Test a rectangle which completely covers the hole.
|
||||
* Clip and split until done.
|
||||
*/
|
||||
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||
|
||||
/* Clip top */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(5, cut.y);
|
||||
CU_ASSERT_EQUAL(20, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(5, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(20, rect.width);
|
||||
CU_ASSERT_EQUAL(15, rect.height);
|
||||
|
||||
/* Clip left */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(15, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(15, rect.width);
|
||||
CU_ASSERT_EQUAL(15, rect.height);
|
||||
|
||||
/* Clip bottom */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(20, cut.y);
|
||||
CU_ASSERT_EQUAL(15, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(15, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Clip right */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(20, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Make sure nothing is left to do */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(0, res);
|
||||
|
||||
}
|
||||
|
@ -17,31 +17,27 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "client/client_suite.h"
|
||||
#include "common/common_suite.h"
|
||||
#include "protocol/suite.h"
|
||||
#include "util/util_suite.h"
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
/**
|
||||
* Test which verifies that guac_common_rect_constrain() restricts a given
|
||||
* rectangle to arbitrary bounds.
|
||||
*/
|
||||
void test_rect__constrain() {
|
||||
|
||||
int main() {
|
||||
guac_common_rect max;
|
||||
guac_common_rect rect;
|
||||
|
||||
/* Init registry */
|
||||
if (CU_initialize_registry() != CUE_SUCCESS)
|
||||
return CU_get_error();
|
||||
guac_common_rect_init(&rect, -10, -10, 110, 110);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_constrain(&rect, &max);
|
||||
|
||||
/* Register suites */
|
||||
register_protocol_suite();
|
||||
register_client_suite();
|
||||
register_util_suite();
|
||||
|
||||
/* Run tests */
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(100, rect.width);
|
||||
CU_ASSERT_EQUAL(100, rect.height);
|
||||
|
||||
}
|
||||
|
71
src/common/tests/rect/expand_to_grid.c
Normal file
71
src/common/tests/rect/expand_to_grid.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
/**
|
||||
* Test which verifies guac_common_rect_expand_to_grid() properly shifts and
|
||||
* resizes rectangles to fit an NxN grid.
|
||||
*/
|
||||
void test_rect__expand_to_grid() {
|
||||
|
||||
int cell_size = 16;
|
||||
|
||||
guac_common_rect max;
|
||||
guac_common_rect rect;
|
||||
|
||||
/* Simple adjustment */
|
||||
guac_common_rect_init(&rect, 0, 0, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
/* Adjustment with moving of rect */
|
||||
guac_common_rect_init(&rect, 75, 75, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(max.width - 32, rect.x);
|
||||
CU_ASSERT_EQUAL(max.height - 32, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
guac_common_rect_init(&rect, -5, -5, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
/* Adjustment with moving and clamping of rect */
|
||||
guac_common_rect_init(&rect, 0, 0, 25, 15);
|
||||
guac_common_rect_init(&max, 0, 5, 32, 15);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(max.x, rect.x);
|
||||
CU_ASSERT_EQUAL(max.y, rect.y);
|
||||
CU_ASSERT_EQUAL(max.width, rect.width);
|
||||
CU_ASSERT_EQUAL(max.height, rect.height);
|
||||
|
||||
}
|
||||
|
@ -17,39 +17,26 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#ifndef _GUAC_TEST_COMMON_SUITE_H
|
||||
#define _GUAC_TEST_COMMON_SUITE_H
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
/**
|
||||
* Test suite containing unit tests for the "common" utility library included
|
||||
* for the sake of simplifying guacamole-server development, but not included
|
||||
* as part of libguac.
|
||||
*
|
||||
* @file common_suite.h
|
||||
* Test which verifies that guac_common_rect_extend() expands the given
|
||||
* rectangle as necessary to contain at least the given bounds.
|
||||
*/
|
||||
void test_rect__extend() {
|
||||
|
||||
#include "config.h"
|
||||
guac_common_rect max;
|
||||
guac_common_rect rect;
|
||||
|
||||
/**
|
||||
* Registers the common test suite with CUnit.
|
||||
*/
|
||||
int register_common_suite();
|
||||
guac_common_rect_init(&rect, 10, 10, 90, 90);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_extend(&rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(100, rect.width);
|
||||
CU_ASSERT_EQUAL(100, rect.height);
|
||||
|
||||
/**
|
||||
* Unit test for string utility functions.
|
||||
*/
|
||||
void test_guac_string();
|
||||
|
||||
/**
|
||||
* Unit test for character conversion functions.
|
||||
*/
|
||||
void test_guac_iconv();
|
||||
|
||||
/**
|
||||
* Unit test for rectangle calculation functions.
|
||||
*/
|
||||
void test_guac_rect();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -17,16 +17,23 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#ifndef _GUAC_TEST_CLIENT_SUITE_H
|
||||
#define _GUAC_TEST_CLIENT_SUITE_H
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "config.h"
|
||||
/**
|
||||
* Test which verifies rectangle initialization via guac_common_rect_init().
|
||||
*/
|
||||
void test_rect__init() {
|
||||
|
||||
int register_client_suite();
|
||||
guac_common_rect max;
|
||||
|
||||
void test_layer_pool();
|
||||
void test_buffer_pool();
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
|
||||
#endif
|
||||
CU_ASSERT_EQUAL(0, max.x);
|
||||
CU_ASSERT_EQUAL(0, max.y);
|
||||
CU_ASSERT_EQUAL(100, max.width);
|
||||
CU_ASSERT_EQUAL(100, max.height);
|
||||
|
||||
}
|
||||
|
91
src/common/tests/rect/intersects.c
Normal file
91
src/common/tests/rect/intersects.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
/**
|
||||
* Test which verifies intersection testing via guac_common_rect_intersects().
|
||||
*/
|
||||
void test_rect__intersects() {
|
||||
|
||||
int res;
|
||||
|
||||
guac_common_rect min;
|
||||
guac_common_rect rect;
|
||||
|
||||
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||
|
||||
/* Rectangle intersection - empty
|
||||
* rectangle is outside */
|
||||
guac_common_rect_init(&rect, 25, 25, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(0, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rectangle is completely inside */
|
||||
guac_common_rect_init(&rect, 11, 11, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects UL */
|
||||
guac_common_rect_init(&rect, 8, 8, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects LR */
|
||||
guac_common_rect_init(&rect, 18, 18, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rect intersects along UL but inside */
|
||||
guac_common_rect_init(&rect, 10, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects along L but outside */
|
||||
guac_common_rect_init(&rect, 5, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rectangle intersects along LR but rest is inside */
|
||||
guac_common_rect_init(&rect, 15, 15, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects along R but rest is outside */
|
||||
guac_common_rect_init(&rect, 20, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle encloses min; which is a partial intersection */
|
||||
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
}
|
||||
|
@ -17,27 +17,17 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "common/string.h"
|
||||
|
||||
#ifndef _GUAC_TEST_PROTOCOL_SUITE_H
|
||||
#define _GUAC_TEST_PROTOCOL_SUITE_H
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Unicode (UTF-8) strings */
|
||||
|
||||
#define UTF8_1 "\xe7\x8a\xac" /* One character */
|
||||
#define UTF8_2 UTF8_1 "\xf0\x90\xac\x80" /* Two characters */
|
||||
#define UTF8_3 UTF8_2 "z" /* Three characters */
|
||||
#define UTF8_4 UTF8_3 "\xc3\xa1" /* Four characters */
|
||||
#define UTF8_8 UTF8_4 UTF8_4 /* Eight characters */
|
||||
|
||||
int register_protocol_suite();
|
||||
|
||||
void test_base64_decode();
|
||||
void test_instruction_parse();
|
||||
void test_instruction_read();
|
||||
void test_instruction_write();
|
||||
void test_nest_write();
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Test which verifies that guac_count_occurrences() counts the number of
|
||||
* occurrences of an arbitrary character within a given string.
|
||||
*/
|
||||
void test_string__guac_count_occurrences() {
|
||||
CU_ASSERT_EQUAL(4, guac_count_occurrences("this is a test string", 's'));
|
||||
CU_ASSERT_EQUAL(3, guac_count_occurrences("this is a test string", 'i'));
|
||||
CU_ASSERT_EQUAL(0, guac_count_occurrences("", 's'));
|
||||
}
|
||||
|
@ -17,26 +17,20 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "common_suite.h"
|
||||
#include "common/string.h"
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
void test_guac_string() {
|
||||
|
||||
char** tokens;
|
||||
|
||||
/* Test occurrence counting */
|
||||
CU_ASSERT_EQUAL(4, guac_count_occurrences("this is a test string", 's'));
|
||||
CU_ASSERT_EQUAL(3, guac_count_occurrences("this is a test string", 'i'));
|
||||
CU_ASSERT_EQUAL(0, guac_count_occurrences("", 's'));
|
||||
/**
|
||||
* Test which verifies that guac_split() splits a string on occurrences of a
|
||||
* given character.
|
||||
*/
|
||||
void test_string__split() {
|
||||
|
||||
/* Split test string */
|
||||
tokens = guac_split("this is a test string", ' ');
|
||||
|
||||
char** tokens = guac_split("this is a test string", ' ');
|
||||
CU_ASSERT_PTR_NOT_NULL(tokens);
|
||||
|
||||
/* Check resulting tokens */
|
||||
@ -57,7 +51,6 @@ void test_guac_string() {
|
||||
|
||||
CU_ASSERT_PTR_NULL(tokens[5]);
|
||||
|
||||
|
||||
/* Clean up */
|
||||
free(tokens[0]);
|
||||
free(tokens[1]);
|
44
src/libguac/.gitignore
vendored
44
src/libguac/.gitignore
vendored
@ -1,41 +1,9 @@
|
||||
|
||||
# Object code
|
||||
*.o
|
||||
*.so
|
||||
*.lo
|
||||
*.la
|
||||
# Auto-generated test runner and binary
|
||||
_generated_runner.c
|
||||
test_libguac
|
||||
|
||||
# gcov files
|
||||
*.gcda
|
||||
*.gcov
|
||||
*.gcno
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# Release files
|
||||
*.tar.gz
|
||||
|
||||
# Files currently being edited by vim or vi
|
||||
*.swp
|
||||
|
||||
# automake/autoconf
|
||||
.deps/
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
m4/*
|
||||
!README
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
# Test suite output
|
||||
*.log
|
||||
*.trs
|
||||
|
||||
|
@ -27,6 +27,7 @@ AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
lib_LTLIBRARIES = libguac.la
|
||||
SUBDIRS = . tests
|
||||
|
||||
libguacincdir = $(includedir)/guacamole
|
||||
|
||||
|
@ -26,41 +26,51 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
TESTS = test_libguac
|
||||
#
|
||||
# Unit tests for libguac
|
||||
#
|
||||
|
||||
check_PROGRAMS = test_libguac
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
noinst_HEADERS = \
|
||||
client/client_suite.h \
|
||||
common/common_suite.h \
|
||||
protocol/suite.h \
|
||||
util/util_suite.h
|
||||
test_libguac_SOURCES = \
|
||||
client/buffer_pool.c \
|
||||
client/layer_pool.c \
|
||||
parser/append.c \
|
||||
parser/read.c \
|
||||
pool/next_free.c \
|
||||
protocol/base64_decode.c \
|
||||
socket/fd_send_instruction.c \
|
||||
socket/nested_send_instruction.c \
|
||||
unicode/charsize.c \
|
||||
unicode/read.c \
|
||||
unicode/strlen.c \
|
||||
unicode/write.c
|
||||
|
||||
test_libguac_SOURCES = \
|
||||
test_libguac.c \
|
||||
client/client_suite.c \
|
||||
client/buffer_pool.c \
|
||||
client/layer_pool.c \
|
||||
common/common_suite.c \
|
||||
common/guac_iconv.c \
|
||||
common/guac_string.c \
|
||||
common/guac_rect.c \
|
||||
protocol/suite.c \
|
||||
protocol/base64_decode.c \
|
||||
protocol/instruction_parse.c \
|
||||
protocol/instruction_read.c \
|
||||
protocol/instruction_write.c \
|
||||
protocol/nest_write.c \
|
||||
util/util_suite.c \
|
||||
util/guac_pool.c \
|
||||
util/guac_unicode.c
|
||||
|
||||
test_libguac_CFLAGS = \
|
||||
-Werror -Wall -pedantic \
|
||||
@COMMON_INCLUDE@ \
|
||||
@LIBGUAC_INCLUDE@
|
||||
|
||||
test_libguac_LDADD = \
|
||||
@COMMON_LTLIB@ \
|
||||
@CUNIT_LIBS@ \
|
||||
@LIBGUAC_LTLIB@
|
||||
|
||||
#
|
||||
# Autogenerate test runner
|
||||
#
|
||||
|
||||
GEN_RUNNER = $(top_srcdir)/util/generate-test-runner.pl
|
||||
CLEANFILES = _generated_runner.c
|
||||
|
||||
_generated_runner.c: $(test_libguac_SOURCES)
|
||||
$(AM_V_GEN) $(GEN_RUNNER) $^ > $@
|
||||
|
||||
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
|
||||
|
@ -17,20 +17,23 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "client_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/layer.h>
|
||||
|
||||
void test_buffer_pool() {
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* Test which verifies that buffers can be allocated and freed using the pool
|
||||
* of buffers available to each guac_client, and that doing so does not disturb
|
||||
* the similar pool of layers.
|
||||
*/
|
||||
void test_client__buffer_pool() {
|
||||
|
||||
guac_client* client;
|
||||
|
||||
int i;
|
||||
int seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0};
|
||||
bool seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = { 0 };
|
||||
|
||||
guac_layer* layer;
|
||||
|
||||
@ -53,7 +56,7 @@ void test_buffer_pool() {
|
||||
|
||||
/* This should be a layer we have not seen yet */
|
||||
CU_ASSERT_FALSE(seen[-layer->index - 1]);
|
||||
seen[-layer->index - 1] = 1;
|
||||
seen[-layer->index - 1] = true;
|
||||
|
||||
guac_client_free_buffer(client, layer);
|
||||
|
@ -17,20 +17,23 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "client_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/layer.h>
|
||||
|
||||
void test_layer_pool() {
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* Test which verifies that layers can be allocated and freed using the pool
|
||||
* of layers available to each guac_client, and that doing so does not disturb
|
||||
* the similar pool of buffers.
|
||||
*/
|
||||
void test_client__layer_pool() {
|
||||
|
||||
guac_client* client;
|
||||
|
||||
int i;
|
||||
int seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0};
|
||||
bool seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0};
|
||||
|
||||
guac_layer* layer;
|
||||
|
||||
@ -53,7 +56,7 @@ void test_layer_pool() {
|
||||
|
||||
/* This should be a layer we have not seen yet */
|
||||
CU_ASSERT_FALSE(seen[layer->index - 1]);
|
||||
seen[layer->index - 1] = 1;
|
||||
seen[layer->index - 1] = true;
|
||||
|
||||
guac_client_free_layer(client, layer);
|
||||
|
@ -17,18 +17,18 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/parser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <guacamole/parser.h>
|
||||
|
||||
void test_instruction_parse() {
|
||||
/**
|
||||
* Test which verifies that guac_parser correctly parses Guacamole instructions
|
||||
* from arbitrary blocks of data passed to guac_parser_append().
|
||||
*/
|
||||
void test_parser__append() {
|
||||
|
||||
/* Allocate parser */
|
||||
guac_parser* parser = guac_parser_alloc();
|
||||
@ -52,6 +52,7 @@ void test_instruction_parse() {
|
||||
|
||||
}
|
||||
|
||||
/* Parse of instruction should be complete */
|
||||
CU_ASSERT_EQUAL(remaining, 18);
|
||||
CU_ASSERT_EQUAL(parser->state, GUAC_PARSE_COMPLETE);
|
||||
|
145
src/libguac/tests/parser/read.c
Normal file
145
src/libguac/tests/parser/read.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <guacamole/parser.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Test string which contains exactly four Unicode characters encoded in UTF-8.
|
||||
* This particular test string uses several characters which encode to multiple
|
||||
* bytes in UTF-8.
|
||||
*/
|
||||
#define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1"
|
||||
|
||||
/**
|
||||
* Writes a series of Guacamole instructions as raw bytes to the given file
|
||||
* descriptor. The instructions written correspond to the instructions verified
|
||||
* by read_expected_instructions(). The given file descriptor is automatically
|
||||
* closed as a result of calling this function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to write instructions to.
|
||||
*/
|
||||
static void write_instructions(int fd) {
|
||||
|
||||
char test_string[] = "4.test,6.a" UTF8_4 "b,"
|
||||
"5.12345,10.a" UTF8_4 UTF8_4 "c;"
|
||||
"5.test2,10.hellohello,15.worldworldworld;";
|
||||
|
||||
char* current = test_string;
|
||||
int remaining = sizeof(test_string) - 1;
|
||||
|
||||
/* Write all bytes in test string */
|
||||
while (remaining > 0) {
|
||||
|
||||
/* Bail out immediately if write fails (test will fail in parent
|
||||
* process due to failure to read) */
|
||||
int written = write(fd, current, remaining);
|
||||
if (written <= 0)
|
||||
break;
|
||||
|
||||
current += written;
|
||||
remaining -= written;
|
||||
|
||||
}
|
||||
|
||||
/* Done writing */
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and parses instructions from the given file descriptor using a
|
||||
* guac_socket and guac_parser, verfying that those instructions match the
|
||||
* series of Guacamole instructions expected to be written by
|
||||
* write_instructions(). The given file descriptor is automatically closed as a
|
||||
* result of calling this function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to read data from.
|
||||
*/
|
||||
static void read_expected_instructions(int fd) {
|
||||
|
||||
/* Open guac socket */
|
||||
guac_socket* socket = guac_socket_open(fd);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(socket);
|
||||
|
||||
/* Allocate parser */
|
||||
guac_parser* parser = guac_parser_alloc();
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(parser);
|
||||
|
||||
/* Read and validate first instruction */
|
||||
CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0);
|
||||
CU_ASSERT_STRING_EQUAL(parser->opcode, "test");
|
||||
CU_ASSERT_EQUAL_FATAL(parser->argc, 3);
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[0], "a" UTF8_4 "b");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[1], "12345");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[2], "a" UTF8_4 UTF8_4 "c");
|
||||
|
||||
/* Read and validate second instruction */
|
||||
CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0);
|
||||
CU_ASSERT_STRING_EQUAL(parser->opcode, "test2");
|
||||
CU_ASSERT_EQUAL_FATAL(parser->argc, 2);
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[0], "hellohello");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[1], "worldworldworld");
|
||||
|
||||
/* Done */
|
||||
guac_parser_free(parser);
|
||||
guac_socket_free(socket);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that guac_parser_read() correctly reads and parses instructions
|
||||
* received over a guac_socket. A child process is forked to write a series of
|
||||
* instructions which are read and verified by the parent process.
|
||||
*/
|
||||
void test_parser__read() {
|
||||
|
||||
int fd[2];
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
int read_fd = fd[0];
|
||||
int write_fd = fd[1];
|
||||
|
||||
/* Fork into writer process (child) and reader process (parent) */
|
||||
int childpid;
|
||||
CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1);
|
||||
|
||||
/* Attempt to write a series of instructions within the child process */
|
||||
if (childpid == 0) {
|
||||
close(read_fd);
|
||||
write_instructions(write_fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Read and verify the expected instructions within the parent process */
|
||||
close(write_fd);
|
||||
read_expected_instructions(read_fd);
|
||||
|
||||
}
|
||||
|
@ -17,20 +17,21 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/pool.h>
|
||||
|
||||
#define UNSEEN 0
|
||||
#define SEEN_PHASE_1 1
|
||||
#define SEEN_PHASE_2 2
|
||||
|
||||
/**
|
||||
* The number of unique integers to provide through the guac_pool instance
|
||||
* being tested.
|
||||
*/
|
||||
#define POOL_SIZE 128
|
||||
|
||||
void test_guac_pool() {
|
||||
/**
|
||||
* Test which verifies that guac_pool provides access to a given number of
|
||||
* unique integers, never repeating a retrieved integer until that integer
|
||||
* is returned to the pool.
|
||||
*/
|
||||
void test_pool__next_free() {
|
||||
|
||||
guac_pool* pool;
|
||||
|
||||
@ -53,8 +54,8 @@ void test_guac_pool() {
|
||||
CU_ASSERT_FATAL(value < POOL_SIZE);
|
||||
|
||||
/* This should be an integer we have not seen yet */
|
||||
CU_ASSERT_EQUAL(UNSEEN, seen[value]);
|
||||
seen[value] = SEEN_PHASE_1;
|
||||
CU_ASSERT_EQUAL(0, seen[value]);
|
||||
seen[value]++;
|
||||
|
||||
/* Return value to pool */
|
||||
guac_pool_free_int(pool, value);
|
||||
@ -71,9 +72,9 @@ void test_guac_pool() {
|
||||
CU_ASSERT_FATAL(value >= 0);
|
||||
CU_ASSERT_FATAL(value < POOL_SIZE);
|
||||
|
||||
/* This should be an integer we have seen already */
|
||||
CU_ASSERT_EQUAL(SEEN_PHASE_1, seen[value]);
|
||||
seen[value] = SEEN_PHASE_2;
|
||||
/* This should be an integer we have seen only once */
|
||||
CU_ASSERT_EQUAL(1, seen[value]);
|
||||
seen[value]++;
|
||||
|
||||
}
|
||||
|
@ -17,18 +17,14 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/protocol.h>
|
||||
|
||||
void test_base64_decode() {
|
||||
/**
|
||||
* Tests that libguac's in-place base64 decoding function properly decodes
|
||||
* valid base64 and fails for invalid base64.
|
||||
*/
|
||||
void test_protocol__decode_base64() {
|
||||
|
||||
/* Test strings */
|
||||
char test_HELLO[] = "SEVMTE8=";
|
136
src/libguac/tests/socket/fd_send_instruction.c
Normal file
136
src/libguac/tests/socket/fd_send_instruction.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Test string which contains exactly four Unicode characters encoded in UTF-8.
|
||||
* This particular test string uses several characters which encode to multiple
|
||||
* bytes in UTF-8.
|
||||
*/
|
||||
#define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1"
|
||||
|
||||
/**
|
||||
* Writes a series of Guacamole instructions using a normal guac_socket
|
||||
* wrapping the given file descriptor. The instructions written correspond to
|
||||
* the instructions verified by read_expected_instructions(). The given file
|
||||
* descriptor is automatically closed as a result of calling this function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to write instructions to.
|
||||
*/
|
||||
static void write_instructions(int fd) {
|
||||
|
||||
/* Open guac socket */
|
||||
guac_socket* socket = guac_socket_open(fd);
|
||||
|
||||
/* Write nothing if socket cannot be allocated (test will fail in parent
|
||||
* process due to failure to read) */
|
||||
if (socket == NULL) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write instructions */
|
||||
guac_protocol_send_name(socket, "a" UTF8_4 "b" UTF8_4 "c");
|
||||
guac_protocol_send_sync(socket, 12345);
|
||||
guac_socket_flush(socket);
|
||||
|
||||
/* Close and free socket */
|
||||
guac_socket_free(socket);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads raw bytes from the given file descriptor until no further bytes
|
||||
* remain, verfying that those bytes represent the series of Guacamole
|
||||
* instructions expected to be written by write_instructions(). The given
|
||||
* file descriptor is automatically closed as a result of calling this
|
||||
* function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to read data from.
|
||||
*/
|
||||
static void read_expected_instructions(int fd) {
|
||||
|
||||
char expected[] =
|
||||
"4.name,11.a" UTF8_4 "b" UTF8_4 "c;"
|
||||
"4.sync,5.12345;";
|
||||
|
||||
int numread;
|
||||
char buffer[1024];
|
||||
int offset = 0;
|
||||
|
||||
/* Read everything available into buffer */
|
||||
while ((numread = read(fd, &(buffer[offset]),
|
||||
sizeof(buffer) - offset)) > 0) {
|
||||
offset += numread;
|
||||
}
|
||||
|
||||
/* Verify length of read data */
|
||||
CU_ASSERT_EQUAL(offset, strlen(expected));
|
||||
|
||||
/* Add NULL terminator */
|
||||
buffer[offset] = '\0';
|
||||
|
||||
/* Read value should be equal to expected value */
|
||||
CU_ASSERT_STRING_EQUAL(buffer, expected);
|
||||
|
||||
/* File descriptor is no longer needed */
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the file descriptor implementation of guac_socket properly
|
||||
* implements writing of instructions. A child process is forked to write a
|
||||
* series of instructions which are read and verified by the parent process.
|
||||
*/
|
||||
void test_socket__fd_send_instruction() {
|
||||
|
||||
int fd[2];
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
int read_fd = fd[0];
|
||||
int write_fd = fd[1];
|
||||
|
||||
/* Fork into writer process (child) and reader process (parent) */
|
||||
int childpid;
|
||||
CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1);
|
||||
|
||||
/* Attempt to write a series of instructions within the child process */
|
||||
if (childpid == 0) {
|
||||
close(read_fd);
|
||||
write_instructions(write_fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Read and verify the expected instructions within the parent process */
|
||||
close(write_fd);
|
||||
read_expected_instructions(read_fd);
|
||||
|
||||
}
|
||||
|
149
src/libguac/tests/socket/nested_send_instruction.c
Normal file
149
src/libguac/tests/socket/nested_send_instruction.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Test string which contains exactly four Unicode characters encoded in UTF-8.
|
||||
* This particular test string uses several characters which encode to multiple
|
||||
* bytes in UTF-8.
|
||||
*/
|
||||
#define UTF8_4 "\xe7\x8a\xac\xf0\x90\xac\x80z\xc3\xa1"
|
||||
|
||||
/**
|
||||
* Writes a series of Guacamole instructions using a nested guac_socket
|
||||
* wrapping another guac_socket which writes to the given file descriptor. The
|
||||
* instructions written correspond to the instructions verified by
|
||||
* read_expected_instructions(). The given file descriptor is automatically
|
||||
* closed as a result of calling this function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to write instructions to.
|
||||
*/
|
||||
static void write_instructions(int fd) {
|
||||
|
||||
/* Open guac socket */
|
||||
guac_socket* socket = guac_socket_open(fd);
|
||||
|
||||
/* Write nothing if socket cannot be allocated (test will fail in parent
|
||||
* process due to failure to read) */
|
||||
if (socket == NULL) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Nest socket */
|
||||
guac_socket* nested_socket = guac_socket_nest(socket, 123);
|
||||
|
||||
/* Write nothing if nested socket cannot be allocated (test will fail in
|
||||
* parent process due to failure to read) */
|
||||
if (socket == NULL) {
|
||||
guac_socket_free(socket);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write instructions */
|
||||
guac_protocol_send_name(nested_socket, "a" UTF8_4 "b" UTF8_4 "c");
|
||||
guac_protocol_send_sync(nested_socket, 12345);
|
||||
|
||||
/* Close and free sockets */
|
||||
guac_socket_free(nested_socket);
|
||||
guac_socket_free(socket);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads raw bytes from the given file descriptor until no further bytes
|
||||
* remain, verfying that those bytes represent the series of Guacamole
|
||||
* instructions expected to be written by write_instructions(). The given
|
||||
* file descriptor is automatically closed as a result of calling this
|
||||
* function.
|
||||
*
|
||||
* @param fd
|
||||
* The file descriptor to read data from.
|
||||
*/
|
||||
static void read_expected_instructions(int fd) {
|
||||
|
||||
char expected[] =
|
||||
"4.nest,3.123,37."
|
||||
"4.name,11.a" UTF8_4 "b" UTF8_4 "c;"
|
||||
"4.sync,5.12345;"
|
||||
";";
|
||||
|
||||
int numread;
|
||||
char buffer[1024];
|
||||
int offset = 0;
|
||||
|
||||
/* Read everything available into buffer */
|
||||
while ((numread = read(fd, &(buffer[offset]),
|
||||
sizeof(buffer) - offset)) > 0) {
|
||||
offset += numread;
|
||||
}
|
||||
|
||||
/* Verify length of read data */
|
||||
CU_ASSERT_EQUAL(offset, strlen(expected));
|
||||
|
||||
/* Add NULL terminator */
|
||||
buffer[offset] = '\0';
|
||||
|
||||
/* Read value should be equal to expected value */
|
||||
CU_ASSERT_STRING_EQUAL(buffer, expected);
|
||||
|
||||
/* File descriptor is no longer needed */
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the nested socket implementation of guac_socket properly
|
||||
* implements writing of instructions. A child process is forked to write a
|
||||
* series of instructions which are read and verified by the parent process.
|
||||
*/
|
||||
void test_socket__nested_send_instruction() {
|
||||
|
||||
int fd[2];
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
int read_fd = fd[0];
|
||||
int write_fd = fd[1];
|
||||
|
||||
/* Fork into writer process (child) and reader process (parent) */
|
||||
int childpid;
|
||||
CU_ASSERT_NOT_EQUAL_FATAL((childpid = fork()), -1);
|
||||
|
||||
/* Attempt to write a series of instructions within the child process */
|
||||
if (childpid == 0) {
|
||||
close(read_fd);
|
||||
write_instructions(write_fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Read and verify the expected instructions within the parent process */
|
||||
close(write_fd);
|
||||
read_expected_instructions(read_fd);
|
||||
|
||||
}
|
||||
|
33
src/libguac/tests/unicode/charsize.c
Normal file
33
src/libguac/tests/unicode/charsize.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
/**
|
||||
* Test which verifies that guac_utf8_charsize() correctly determines the
|
||||
* length of UTF-8 characters from the leading byte of that character.
|
||||
*/
|
||||
void test_unicode__utf8_charsize() {
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_charsize('g'));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_charsize('\xC4'));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_charsize('\xE7'));
|
||||
CU_ASSERT_EQUAL(4, guac_utf8_charsize('\xF0'));
|
||||
}
|
||||
|
52
src/libguac/tests/unicode/read.c
Normal file
52
src/libguac/tests/unicode/read.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
/**
|
||||
* Test which verifies that guac_utf8_read() properly parses UTF-8.
|
||||
*/
|
||||
void test_unicode__utf8_read() {
|
||||
|
||||
int codepoint;
|
||||
|
||||
char buffer[16] =
|
||||
/* U+0065 */ "\x65"
|
||||
/* U+0654 */ "\xD9\x94"
|
||||
/* U+0876 */ "\xE0\xA1\xB6"
|
||||
/* U+12345 */ "\xF0\x92\x8D\x85";
|
||||
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_read(&(buffer[0]), 10, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0065, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_read(&(buffer[1]), 9, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0654, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_read(&(buffer[3]), 7, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0876, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(4, guac_utf8_read(&(buffer[6]), 4, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x12345, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(0, guac_utf8_read(&(buffer[10]), 0, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x12345, codepoint);
|
||||
|
||||
}
|
||||
|
@ -17,19 +17,8 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GUAC_TEST_UTIL_SUITE_H
|
||||
#define _GUAC_TEST_UTIL_SUITE_H
|
||||
|
||||
/**
|
||||
* Test suite containing unit tests for utility functions built into libguac.
|
||||
* These utility functions are included for convenience rather as integral
|
||||
* requirements of the core.
|
||||
*
|
||||
* @file util_suite.h
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
/**
|
||||
* A single Unicode character encoded as one byte with UTF-8.
|
||||
@ -52,24 +41,19 @@
|
||||
#define UTF8_4b "\xf0\x90\x84\xa3"
|
||||
|
||||
/**
|
||||
* Registers the utility test suite with CUnit.
|
||||
* Test which verifies that guac_utf8_strlen() properly calculates the length
|
||||
* of UTF-8 strings.
|
||||
*/
|
||||
int register_util_suite();
|
||||
|
||||
/**
|
||||
* Unit test for the guac_pool structure and related functions. The guac_pool
|
||||
* structure provides a consistent source of pooled integers. This unit test
|
||||
* checks that the associated functions behave as documented (returning
|
||||
* integers in the proper order, allocating new integers as necessary, etc.).
|
||||
*/
|
||||
void test_guac_pool();
|
||||
|
||||
/**
|
||||
* Unit test for libguac's Unicode convenience functions. This test checks that
|
||||
* the functions provided for determining string length, character length, and
|
||||
* for reading and writing UTF-8 behave as specified in the documentation.
|
||||
*/
|
||||
void test_guac_unicode();
|
||||
|
||||
#endif
|
||||
void test_unicode__utf8_strlen() {
|
||||
CU_ASSERT_EQUAL(0, guac_utf8_strlen(""));
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_strlen(UTF8_4b));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_4b UTF8_1b));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_2b UTF8_3b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_1b UTF8_3b UTF8_4b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_2b UTF8_1b UTF8_3b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_4b UTF8_2b UTF8_1b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_3b UTF8_4b UTF8_2b));
|
||||
CU_ASSERT_EQUAL(5, guac_utf8_strlen("hello"));
|
||||
CU_ASSERT_EQUAL(9, guac_utf8_strlen("guacamole"));
|
||||
}
|
||||
|
@ -17,36 +17,17 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
void test_guac_unicode() {
|
||||
/**
|
||||
* Test which verifies that guac_utf8_write() properly encodes Unicode
|
||||
* codepoints as UTF-8.
|
||||
*/
|
||||
void test_unicode__utf8_write() {
|
||||
|
||||
int codepoint;
|
||||
char buffer[16];
|
||||
|
||||
/* Test character length */
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_charsize(UTF8_1b[0]));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_charsize(UTF8_2b[0]));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_charsize(UTF8_3b[0]));
|
||||
CU_ASSERT_EQUAL(4, guac_utf8_charsize(UTF8_4b[0]));
|
||||
|
||||
/* Test string length */
|
||||
CU_ASSERT_EQUAL(0, guac_utf8_strlen(""));
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_strlen(UTF8_4b));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_4b UTF8_1b));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_strlen(UTF8_2b UTF8_3b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_1b UTF8_3b UTF8_4b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_2b UTF8_1b UTF8_3b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_4b UTF8_2b UTF8_1b));
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_strlen(UTF8_3b UTF8_4b UTF8_2b));
|
||||
CU_ASSERT_EQUAL(5, guac_utf8_strlen("hello"));
|
||||
CU_ASSERT_EQUAL(9, guac_utf8_strlen("guacamole"));
|
||||
|
||||
/* Test writes */
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_write(0x00065, &(buffer[0]), 10));
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_write(0x00654, &(buffer[1]), 9));
|
||||
@ -60,22 +41,5 @@ void test_guac_unicode() {
|
||||
CU_ASSERT(memcmp("\xE0\xA1\xB6", &(buffer[3]), 3) == 0); /* U+0876 */
|
||||
CU_ASSERT(memcmp("\xF0\x92\x8D\x85", &(buffer[6]), 4) == 0); /* U+12345 */
|
||||
|
||||
/* Test reads */
|
||||
|
||||
CU_ASSERT_EQUAL(1, guac_utf8_read(&(buffer[0]), 10, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0065, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(2, guac_utf8_read(&(buffer[1]), 9, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0654, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(3, guac_utf8_read(&(buffer[3]), 7, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x0876, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(4, guac_utf8_read(&(buffer[6]), 4, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x12345, codepoint);
|
||||
|
||||
CU_ASSERT_EQUAL(0, guac_utf8_read(&(buffer[10]), 0, &codepoint));
|
||||
CU_ASSERT_EQUAL(0x12345, codepoint);
|
||||
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "client_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
int client_suite_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_suite_cleanup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_client_suite() {
|
||||
|
||||
/* Add client test suite */
|
||||
CU_pSuite suite = CU_add_suite("client",
|
||||
client_suite_init, client_suite_cleanup);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
/* Add tests */
|
||||
if (
|
||||
CU_add_test(suite, "layer-pool", test_layer_pool) == NULL
|
||||
|| CU_add_test(suite, "buffer-pool", test_buffer_pool) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "common_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
int common_suite_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int common_suite_cleanup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_common_suite() {
|
||||
|
||||
/* Add common test suite */
|
||||
CU_pSuite suite = CU_add_suite("common",
|
||||
common_suite_init, common_suite_cleanup);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
/* Add tests */
|
||||
if (
|
||||
CU_add_test(suite, "guac-iconv", test_guac_iconv) == NULL
|
||||
|| CU_add_test(suite, "guac-string", test_guac_string) == NULL
|
||||
|| CU_add_test(suite, "guac-rect", test_guac_rect) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -1,289 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "common_suite.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
void test_guac_rect() {
|
||||
|
||||
guac_common_rect max;
|
||||
|
||||
/*
|
||||
* Test init method
|
||||
*/
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
CU_ASSERT_EQUAL(0, max.x);
|
||||
CU_ASSERT_EQUAL(0, max.y);
|
||||
CU_ASSERT_EQUAL(100, max.width);
|
||||
CU_ASSERT_EQUAL(100, max.height);
|
||||
|
||||
/*
|
||||
* Test constrain method
|
||||
*/
|
||||
guac_common_rect rect;
|
||||
guac_common_rect_init(&rect, -10, -10, 110, 110);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_constrain(&rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(100, rect.width);
|
||||
CU_ASSERT_EQUAL(100, rect.height);
|
||||
|
||||
/*
|
||||
* Test extend method
|
||||
*/
|
||||
guac_common_rect_init(&rect, 10, 10, 90, 90);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_extend(&rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(100, rect.width);
|
||||
CU_ASSERT_EQUAL(100, rect.height);
|
||||
|
||||
/*
|
||||
* Test adjust method
|
||||
*/
|
||||
int cell_size = 16;
|
||||
|
||||
/* Simple adjustment */
|
||||
guac_common_rect_init(&rect, 0, 0, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
/* Adjustment with moving of rect */
|
||||
guac_common_rect_init(&rect, 75, 75, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(max.width - 32, rect.x);
|
||||
CU_ASSERT_EQUAL(max.height - 32, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
guac_common_rect_init(&rect, -5, -5, 25, 25);
|
||||
guac_common_rect_init(&max, 0, 0, 100, 100);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(0, rect.x);
|
||||
CU_ASSERT_EQUAL(0, rect.y);
|
||||
CU_ASSERT_EQUAL(32, rect.width);
|
||||
CU_ASSERT_EQUAL(32, rect.height);
|
||||
|
||||
/* Adjustment with moving and clamping of rect */
|
||||
guac_common_rect_init(&rect, 0, 0, 25, 15);
|
||||
guac_common_rect_init(&max, 0, 5, 32, 15);
|
||||
guac_common_rect_expand_to_grid(cell_size, &rect, &max);
|
||||
CU_ASSERT_EQUAL(max.x, rect.x);
|
||||
CU_ASSERT_EQUAL(max.y, rect.y);
|
||||
CU_ASSERT_EQUAL(max.width, rect.width);
|
||||
CU_ASSERT_EQUAL(max.height, rect.height);
|
||||
|
||||
/*
|
||||
* Rectangle intersection tests
|
||||
*/
|
||||
guac_common_rect min;
|
||||
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||
|
||||
/* Rectangle intersection - empty
|
||||
* rectangle is outside */
|
||||
guac_common_rect_init(&rect, 25, 25, 5, 5);
|
||||
int res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(0, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rectangle is completely inside */
|
||||
guac_common_rect_init(&rect, 11, 11, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects UL */
|
||||
guac_common_rect_init(&rect, 8, 8, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects LR */
|
||||
guac_common_rect_init(&rect, 18, 18, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rect intersects along UL but inside */
|
||||
guac_common_rect_init(&rect, 10, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects along L but outside */
|
||||
guac_common_rect_init(&rect, 5, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - complete
|
||||
* rectangle intersects along LR but rest is inside */
|
||||
guac_common_rect_init(&rect, 15, 15, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(2, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle intersects along R but rest is outside */
|
||||
guac_common_rect_init(&rect, 20, 10, 5, 5);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/* Rectangle intersection - partial
|
||||
* rectangle encloses min; which is a partial intersection */
|
||||
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||
res = guac_common_rect_intersects(&rect, &min);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
|
||||
/*
|
||||
* Basic test of clip and split method
|
||||
*/
|
||||
guac_common_rect_init(&min, 10, 10, 10, 10);
|
||||
guac_common_rect cut;
|
||||
|
||||
/* Clip top */
|
||||
guac_common_rect_init(&rect, 10, 5, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(5, cut.y);
|
||||
CU_ASSERT_EQUAL(10, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(5, rect.height);
|
||||
|
||||
/* Clip bottom */
|
||||
guac_common_rect_init(&rect, 10, 15, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(20, cut.y);
|
||||
CU_ASSERT_EQUAL(10, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(15, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(5, rect.height);
|
||||
|
||||
/* Clip left */
|
||||
guac_common_rect_init(&rect, 5, 10, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(5, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Clip right */
|
||||
guac_common_rect_init(&rect, 15, 10, 10, 10);
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(20, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(15, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(5, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/*
|
||||
* Test a rectangle which completely covers the hole.
|
||||
* Clip and split until done.
|
||||
*/
|
||||
guac_common_rect_init(&rect, 5, 5, 20, 20);
|
||||
|
||||
/* Clip top */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(5, cut.y);
|
||||
CU_ASSERT_EQUAL(20, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(5, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(20, rect.width);
|
||||
CU_ASSERT_EQUAL(15, rect.height);
|
||||
|
||||
/* Clip left */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(5, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(15, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(15, rect.width);
|
||||
CU_ASSERT_EQUAL(15, rect.height);
|
||||
|
||||
/* Clip bottom */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(1, res);
|
||||
CU_ASSERT_EQUAL(10, cut.x);
|
||||
CU_ASSERT_EQUAL(20, cut.y);
|
||||
CU_ASSERT_EQUAL(15, cut.width);
|
||||
CU_ASSERT_EQUAL(5, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(15, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Clip right */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(20, cut.x);
|
||||
CU_ASSERT_EQUAL(10, cut.y);
|
||||
CU_ASSERT_EQUAL(5, cut.width);
|
||||
CU_ASSERT_EQUAL(10, cut.height);
|
||||
|
||||
CU_ASSERT_EQUAL(10, rect.x);
|
||||
CU_ASSERT_EQUAL(10, rect.y);
|
||||
CU_ASSERT_EQUAL(10, rect.width);
|
||||
CU_ASSERT_EQUAL(10, rect.height);
|
||||
|
||||
/* Make sure nothing is left to do */
|
||||
res = guac_common_rect_clip_and_split(&rect, &min, &cut);
|
||||
CU_ASSERT_EQUAL(0, res);
|
||||
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <guacamole/parser.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
void test_instruction_read() {
|
||||
|
||||
int rfd, wfd;
|
||||
int fd[2], childpid;
|
||||
|
||||
char test_string[] = "4.test,6.a" UTF8_4 "b,"
|
||||
"5.12345,10.a" UTF8_8 "c;"
|
||||
"5.test2,10.hellohello,15.worldworldworld;";
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
/* File descriptors */
|
||||
rfd = fd[0];
|
||||
wfd = fd[1];
|
||||
|
||||
/* Fork */
|
||||
if ((childpid = fork()) == -1) {
|
||||
/* ERROR */
|
||||
perror("fork");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child (pipe writer) */
|
||||
if (childpid != 0) {
|
||||
close(rfd);
|
||||
CU_ASSERT_EQUAL(
|
||||
write(wfd, test_string, sizeof(test_string)),
|
||||
sizeof(test_string)
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Parent (unit test) */
|
||||
else {
|
||||
|
||||
guac_socket* socket;
|
||||
guac_parser* parser;
|
||||
|
||||
close(wfd);
|
||||
|
||||
/* Open guac socket */
|
||||
socket = guac_socket_open(rfd);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(socket);
|
||||
|
||||
/* Allocate parser */
|
||||
parser = guac_parser_alloc();
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(parser);
|
||||
|
||||
/* Read instruction */
|
||||
CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0);
|
||||
|
||||
/* Validate contents */
|
||||
CU_ASSERT_STRING_EQUAL(parser->opcode, "test");
|
||||
CU_ASSERT_EQUAL_FATAL(parser->argc, 3);
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[0], "a" UTF8_4 "b");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[1], "12345");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[2], "a" UTF8_8 "c");
|
||||
|
||||
/* Read another instruction */
|
||||
CU_ASSERT_EQUAL_FATAL(guac_parser_read(parser, socket, 1000000), 0);
|
||||
|
||||
/* Validate contents */
|
||||
CU_ASSERT_STRING_EQUAL(parser->opcode, "test2");
|
||||
CU_ASSERT_EQUAL_FATAL(parser->argc, 2);
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[0], "hellohello");
|
||||
CU_ASSERT_STRING_EQUAL(parser->argv[1], "worldworldworld");
|
||||
|
||||
guac_parser_free(parser);
|
||||
guac_socket_free(socket);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
void test_instruction_write() {
|
||||
|
||||
int rfd, wfd;
|
||||
int fd[2], childpid;
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
/* File descriptors */
|
||||
rfd = fd[0];
|
||||
wfd = fd[1];
|
||||
|
||||
/* Fork */
|
||||
if ((childpid = fork()) == -1) {
|
||||
/* ERROR */
|
||||
perror("fork");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child (pipe writer) */
|
||||
if (childpid != 0) {
|
||||
|
||||
guac_socket* socket;
|
||||
|
||||
close(rfd);
|
||||
|
||||
/* Open guac socket */
|
||||
socket = guac_socket_open(wfd);
|
||||
|
||||
/* Write instruction */
|
||||
guac_protocol_send_name(socket, "a" UTF8_4 "b" UTF8_4 "c");
|
||||
guac_protocol_send_sync(socket, 12345);
|
||||
guac_socket_flush(socket);
|
||||
|
||||
guac_socket_free(socket);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Parent (unit test) */
|
||||
else {
|
||||
|
||||
char expected[] =
|
||||
"4.name,11.a" UTF8_4 "b" UTF8_4 "c;"
|
||||
"4.sync,5.12345;";
|
||||
|
||||
int numread;
|
||||
char buffer[1024];
|
||||
int offset = 0;
|
||||
|
||||
close(wfd);
|
||||
|
||||
/* Read everything available into buffer */
|
||||
while ((numread =
|
||||
read(rfd,
|
||||
&(buffer[offset]),
|
||||
sizeof(buffer)-offset)) != 0) {
|
||||
offset += numread;
|
||||
}
|
||||
|
||||
/* Add NULL terminator */
|
||||
buffer[offset] = '\0';
|
||||
|
||||
/* Read value should be equal to expected value */
|
||||
CU_ASSERT_STRING_EQUAL(buffer, expected);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
void test_nest_write() {
|
||||
|
||||
int rfd, wfd;
|
||||
int fd[2], childpid;
|
||||
|
||||
/* Create pipe */
|
||||
CU_ASSERT_EQUAL_FATAL(pipe(fd), 0);
|
||||
|
||||
/* File descriptors */
|
||||
rfd = fd[0];
|
||||
wfd = fd[1];
|
||||
|
||||
/* Fork */
|
||||
if ((childpid = fork()) == -1) {
|
||||
/* ERROR */
|
||||
perror("fork");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child (pipe writer) */
|
||||
if (childpid != 0) {
|
||||
|
||||
guac_socket* nested_socket;
|
||||
guac_socket* socket;
|
||||
|
||||
close(rfd);
|
||||
|
||||
/* Open guac socket */
|
||||
socket = guac_socket_open(wfd);
|
||||
|
||||
/* Nest socket */
|
||||
nested_socket = guac_socket_nest(socket, 0);
|
||||
|
||||
/* Write instruction */
|
||||
guac_protocol_send_name(nested_socket, "a" UTF8_4 "b" UTF8_4 "c");
|
||||
guac_protocol_send_sync(nested_socket, 12345);
|
||||
guac_socket_flush(nested_socket);
|
||||
guac_socket_flush(socket);
|
||||
|
||||
guac_socket_free(nested_socket);
|
||||
guac_socket_free(socket);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Parent (unit test) */
|
||||
else {
|
||||
|
||||
char expected[] =
|
||||
"4.nest,1.0,37."
|
||||
"4.name,11.a" UTF8_4 "b" UTF8_4 "c;"
|
||||
"4.sync,5.12345;"
|
||||
";";
|
||||
|
||||
int numread;
|
||||
char buffer[1024];
|
||||
int offset = 0;
|
||||
|
||||
close(wfd);
|
||||
|
||||
/* Read everything available into buffer */
|
||||
while ((numread =
|
||||
read(rfd,
|
||||
&(buffer[offset]),
|
||||
sizeof(buffer)-offset)) != 0) {
|
||||
offset += numread;
|
||||
}
|
||||
|
||||
/* Add NULL terminator */
|
||||
buffer[offset] = '\0';
|
||||
|
||||
/* Read value should be equal to expected value */
|
||||
CU_ASSERT_STRING_EQUAL(buffer, expected);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
int protocol_suite_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int protocol_suite_cleanup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_protocol_suite() {
|
||||
|
||||
/* Add protocol test suite */
|
||||
CU_pSuite suite = CU_add_suite("protocol",
|
||||
protocol_suite_init, protocol_suite_cleanup);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
/* Add tests */
|
||||
if (
|
||||
CU_add_test(suite, "base64-decode", test_base64_decode) == NULL
|
||||
|| CU_add_test(suite, "instruction-parse", test_instruction_parse) == NULL
|
||||
|| CU_add_test(suite, "instruction-read", test_instruction_read) == NULL
|
||||
|| CU_add_test(suite, "instruction-write", test_instruction_write) == NULL
|
||||
|| CU_add_test(suite, "nest-write", test_nest_write) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util_suite.h"
|
||||
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
int util_suite_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int util_suite_cleanup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_util_suite() {
|
||||
|
||||
/* Add util test suite */
|
||||
CU_pSuite suite = CU_add_suite("util",
|
||||
util_suite_init, util_suite_cleanup);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
/* Add tests */
|
||||
if (
|
||||
CU_add_test(suite, "guac-pool", test_guac_pool) == NULL
|
||||
|| CU_add_test(suite, "guac-unicode", test_guac_unicode) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
199
util/generate-test-runner.pl
Executable file
199
util/generate-test-runner.pl
Executable file
@ -0,0 +1,199 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
#
|
||||
# generate-test-runner.pl
|
||||
#
|
||||
# Generates a test runner for the .c files given on the command line. Each .c
|
||||
# file may declare any number of tests so long as each test uses CUnit and is
|
||||
# declared with the following convention:
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Absolutely all tests MUST follow the above convention if they are to be
|
||||
# picked up by this script. Functions which are not tests MUST NOT follow
|
||||
# the above convention.
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
my $num_tests = 0;
|
||||
my %test_suites = ();
|
||||
|
||||
# Parse all test declarations from given file
|
||||
while (<>) {
|
||||
if ((my $suite_name, my $test_name) = m/^void\s+test_(\w+)__(\w+)/) {
|
||||
$num_tests++;
|
||||
$test_suites{$suite_name} //= ();
|
||||
push @{$test_suites{$suite_name}}, $test_name;
|
||||
}
|
||||
}
|
||||
|
||||
# Bail out if there's nothing to write
|
||||
if ($num_tests == 0) {
|
||||
die "No unit tests... :(\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Common test runner header
|
||||
#
|
||||
|
||||
print <<'END';
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <CUnit/TestRun.h>
|
||||
|
||||
/**
|
||||
* The current test number, as required by the TAP format. This value is
|
||||
* automatically incremented by tap_log_test_completed() after each test is
|
||||
* run.
|
||||
*/
|
||||
int tap_test_number = 1;
|
||||
|
||||
/**
|
||||
* Logs the status of a CUnit test which just completed. This implementation
|
||||
* logs test completion in TAP format.
|
||||
*
|
||||
* @param test
|
||||
* The CUnit test which just completed.
|
||||
*
|
||||
* @param suite
|
||||
* The CUnit test suite associated with the test.
|
||||
*
|
||||
* @param failure
|
||||
* The head element of the test failure list, or NULL if the test passed.
|
||||
*/
|
||||
static void tap_log_test_completed(const CU_pTest test,
|
||||
const CU_pSuite suite, const CU_pFailureRecord failure) {
|
||||
|
||||
/* Log success/failure in TAP format */
|
||||
if (failure == NULL)
|
||||
printf("ok %i - [%s] %s: OK\n",
|
||||
tap_test_number, suite->pName, test->pName);
|
||||
else
|
||||
printf("not ok %i - [%s] %s: Assertion failed on %s:%i: %s\n",
|
||||
tap_test_number, suite->pName, test->pName,
|
||||
failure->strFileName, failure->uiLineNumber,
|
||||
failure->strCondition);
|
||||
|
||||
tap_test_number++;
|
||||
|
||||
}
|
||||
END
|
||||
|
||||
#
|
||||
# Prototypes for all test functions
|
||||
#
|
||||
|
||||
while ((my $suite_name, my $test_names) = each (%test_suites)) {
|
||||
print "\n/* Automatically-generated prototypes for the $suite_name suite */\n";
|
||||
foreach my $test_name (@{ $test_names }) {
|
||||
print "void test_${suite_name}__${test_name}();\n";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Beginning of main() function body for test runner
|
||||
#
|
||||
|
||||
print <<"END";
|
||||
|
||||
/* Automatically-generated test runner */
|
||||
int main() {
|
||||
|
||||
/* Init CUnit test registry */
|
||||
if (CU_initialize_registry() != CUE_SUCCESS)
|
||||
return CU_get_error();
|
||||
END
|
||||
|
||||
#
|
||||
# Within main(), register each test and its corresponding test suite
|
||||
#
|
||||
|
||||
while ((my $suite_name, my $test_names) = each (%test_suites)) {
|
||||
|
||||
print <<" END";
|
||||
|
||||
/* Create and register all tests for the $suite_name suite */
|
||||
CU_pSuite $suite_name = CU_add_suite("$suite_name", NULL, NULL);
|
||||
if ($suite_name == NULL
|
||||
END
|
||||
|
||||
foreach my $test_name (@{ $test_names }) {
|
||||
print <<" END";
|
||||
|| CU_add_test($suite_name, "$test_name", test_${suite_name}__${test_name}) == NULL
|
||||
END
|
||||
}
|
||||
|
||||
print <<" END";
|
||||
) goto cleanup;
|
||||
END
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# End of main() function
|
||||
#
|
||||
|
||||
print <<"END";
|
||||
|
||||
/* Force line-buffered output to ensure log messages are visible even if
|
||||
* a test crashes */
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
setvbuf(stderr, NULL, _IOLBF, 0);
|
||||
|
||||
/* Write TAP header */
|
||||
printf("1..$num_tests\\n");
|
||||
|
||||
/* Run all tests in all suites */
|
||||
CU_set_test_complete_handler(tap_log_test_completed);
|
||||
CU_run_all_tests();
|
||||
|
||||
cleanup:
|
||||
/* Tests complete */
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
||||
}
|
||||
END
|
||||
|
Loading…
Reference in New Issue
Block a user