/*
* Check: a unit test framework for C
* Copyright (C) 2001, 2002 Arien Malec
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "../lib/libcompat.h"
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <check.h>
#include "check_error.h"
#include "check_str.h"
#include "check_check.h"
static char errm[200];
static void fixture_sub_setup (void)
{
ck_abort_msg("Test failure in fixture");
}
static SRunner *fixture_sr;
void setup_fixture (void)
{
TCase *tc;
Suite *fixture_s;
fixture_s = suite_create("Fix Sub");
tc = tcase_create("Fix Sub");
tcase_add_unchecked_fixture(tc, fixture_sub_setup, NULL);
suite_add_tcase (fixture_s, tc);
fixture_sr = srunner_create(fixture_s);
srunner_run_all(fixture_sr,CK_VERBOSE);
}
void teardown_fixture (void)
{
srunner_free(fixture_sr);
}
START_TEST(test_fixture_fail_counts)
{
int nrun, nfail;
nrun = srunner_ntests_run(fixture_sr);
nfail = srunner_ntests_failed(fixture_sr);
ck_assert_msg (nrun == 1 && nfail == 1,
"Counts for run and fail for fixture failure not correct");
}
END_TEST
START_TEST(test_print_counts)
{
char *srstat = sr_stat_str(fixture_sr);
const char *exp = "0%: Checks: 1, Failures: 1, Errors: 0";
ck_assert_msg(strcmp(srstat, exp) == 0,
"SRunner stat string incorrect with setup failure");
free(srstat);
}
END_TEST
START_TEST(test_setup_failure_msg)
{
TestResult **tra;
char *trm;
const char *trmexp = "check_check_fixture.c:36:S:Fix Sub:unchecked_setup:0: Test failure in fixture";
tra = srunner_failures(fixture_sr);
trm = tr_str(tra[0]);
free(tra);
if (strstr(trm, trmexp) == 0) {
snprintf(errm, sizeof(errm),
"Bad setup tr msg (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
}
END_TEST
#if defined(HAVE_FORK) && HAVE_FORK==1
int testval_up;
int testval_down;
static void sub_ch_setup_norm (void)
{
testval_up += 2;
}
static void sub_ch_teardown_norm(void)
{
testval_down += 2;
}
START_TEST(test_sub_ch_setup_norm)
{
if (testval_up == 1)
ck_abort_msg("Setup not run correctly");
else if (testval_up > 3)
ck_abort_msg("Test side-effects persist across runs");
testval_up++;
}
END_TEST
START_TEST(test_ch_setup)
{
TCase *tc;
Suite *s;
SRunner *sr;
s = suite_create("Fixture Norm Sub");
tc = tcase_create("Fixture Norm Sub");
sr = srunner_create(s);
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_ch_setup_norm);
tcase_add_test(tc,test_sub_ch_setup_norm);
tcase_add_checked_fixture(tc,sub_ch_setup_norm,sub_ch_teardown_norm);
srunner_run_all(sr, CK_VERBOSE);
ck_assert_msg(srunner_ntests_failed(sr) == 0,
"Checked setup not being run correctly");
srunner_free(sr);
}
END_TEST
static void setup_sub_fail (void)
{
ck_abort_msg("Failed setup"); /* check_check_fixture.c:130 */
}
static void teardown_sub_fail (void)
{
ck_abort_msg("Failed teardown");
}
static void setup_sub_signal (void)
{
mark_point();
raise(SIGFPE);
}
static void teardown_sub_signal(void)
{
mark_point();
raise(SIGFPE);
}
START_TEST(test_sub_fail)
{
ck_abort_msg("Should never run");
}
END_TEST
START_TEST(test_sub_pass)
{
ck_assert_msg(1 == 1, "Always pass");
}
END_TEST
START_TEST(test_ch_setup_fail)
{
TCase *tc;
Suite *s;
SRunner *sr;
TestResult ** tr;
char *strstat;
char *trm;
s = suite_create("Setup Fail");
tc = tcase_create("Setup Fail");
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_fail);
tcase_add_checked_fixture(tc,setup_sub_fail, NULL);
sr = srunner_create(s);
srunner_run_all(sr,CK_VERBOSE);
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked setup failure");
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked setup failure");
strstat= sr_stat_str(sr);
ck_assert_msg(strcmp(strstat,
"0%: Checks: 1, Failures: 1, Errors: 0") == 0,
"SRunner stat string incorrect with checked setup failure");
free(strstat);
tr = srunner_failures(sr);
trm = tr_str(tr[0]);
/* Search for check_check_fixture.c:150 if this fails. */
if (strstr(trm,
"check_check_fixture.c:150:S:Setup Fail:test_sub_fail:0: Failed setup")
== 0) {
snprintf(errm, sizeof(errm),
"Bad failed checked setup tr msg (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
free(tr);
}
END_TEST
START_TEST(test_ch_setup_fail_nofork)
{
TCase *tc;
Suite *s;
SRunner *sr;
s = suite_create("Setup Fail Nofork");
tc = tcase_create("Setup Fail Nofork");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_sub_fail);
tcase_add_checked_fixture(tc, setup_sub_fail, NULL);
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_VERBOSE);
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked setup failure");
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked setup failure");
srunner_free(sr);
}
END_TEST
START_TEST(test_ch_setup_fail_nofork_2)
{
TCase *tc;
Suite *s;
SRunner *sr;
s = suite_create("Setup Fail Nofork 2");
tc = tcase_create("Setup Fail Nofork 2");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_sub_fail);
tcase_add_checked_fixture(tc, sub_ch_setup_norm, NULL);
tcase_add_checked_fixture(tc, setup_sub_fail, NULL);
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_VERBOSE);
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked setup failure");
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked setup failure");
srunner_free(sr);
}
END_TEST
START_TEST(test_ch_setup_pass_nofork)
{
TCase *tc;
Suite *s;
SRunner *sr;
s = suite_create("Setup Pass Multiple fixtures");
tc = tcase_create("Setup Pass Multiple fixtures");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_sub_pass);
tcase_add_checked_fixture(tc, sub_ch_setup_norm, sub_ch_teardown_norm);
tcase_add_checked_fixture(tc, sub_ch_setup_norm, sub_ch_teardown_norm);
tcase_add_checked_fixture(tc, sub_ch_setup_norm, sub_ch_teardown_norm);
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
testval_up = 1;
testval_down = 1;
srunner_run_all(sr, CK_VERBOSE);
ck_assert_msg(testval_up == 7, "Multiple setups failed");
ck_assert_msg(testval_down == 7, "Multiple teardowns failed");
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked setup failure");
ck_assert_msg (srunner_ntests_failed(sr) == 0,
"Failure counts not correct for checked setup failure");
srunner_free(sr);
}
END_TEST
/* This test currently does not work on Cygwin, as it results in a
* SIGSEGV instead of a SIGFPE. However, a simple program that installs
* a SIGFPE handler then raise(SIGFPE) works as expected. Further
* investigation is necessary. */
#if !defined(__CYGWIN__)
/*
* This test will fail without fork, as it results in a checked
* fixture raising a signal, which terminates the test runner early.
*/
START_TEST(test_ch_setup_sig)
{
TCase *tc;
Suite *s;
SRunner *sr;
TestResult **tr;
char *strstat;
char *trm;
s = suite_create("Setup Sig");
tc = tcase_create("Setup Sig");
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_fail);
tcase_add_checked_fixture(tc,setup_sub_signal, NULL);
sr = srunner_create(s);
srunner_run_all(sr,CK_VERBOSE);
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked setup signal");
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked setup signal");
strstat= sr_stat_str(sr);
ck_assert_msg(strcmp(strstat,
"0%: Checks: 1, Failures: 0, Errors: 1") == 0,
"SRunner stat string incorrect with checked setup signal");
free(strstat);
tr = srunner_failures(sr);
trm = tr_str(tr[0]);
if (strstr(trm,
"check_check_fixture.c:160:S:Setup Sig:test_sub_fail:0: "
"(after this point) Received signal 8")
== 0) {
snprintf(errm, sizeof(errm),
"Msg was (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
srunner_free(sr);
free(tr);
}
END_TEST
#endif /* !defined(__CYGWIN__) */
static void sub_ch_setup_dual_1(void)
{
ck_assert_msg(testval_up == 1, "Wrong start value");
testval_up += 2;
}
static void sub_ch_setup_dual_2(void)
{
ck_assert_msg(testval_up == 3, "First setup failed");
testval_up += 3;
}
START_TEST(test_sub_two_setups)
{
ck_assert_msg(testval_up == 6, "Multiple setups failed");
}
END_TEST
/*
* This test will not work without fork, as checked fixtures are
* not supported
*/
START_TEST(test_ch_setup_two_setups_fork)
{
TCase *tc;
Suite *s;
SRunner *sr;
s = suite_create("Fixture Two setups");
tc = tcase_create("Fixture Two setups");
sr = srunner_create(s);
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_two_setups);
tcase_add_checked_fixture(tc,sub_ch_setup_dual_1,NULL);
tcase_add_checked_fixture(tc,sub_ch_setup_dual_2,NULL);
testval_up = 1;
srunner_run_all(sr, CK_VERBOSE);
ck_assert_msg(srunner_ntests_failed(sr) == 0,
"Problem with several setups");
srunner_free(sr);
}
END_TEST
START_TEST(test_ch_teardown_fail)
{
TCase *tc;
Suite *s;
SRunner *sr;
TestResult **tr;
char *strstat;
char *trm;
s = suite_create("Teardown Fail");
tc = tcase_create("Teardown Fail");
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_pass);
tcase_add_checked_fixture(tc,NULL, teardown_sub_fail);
sr = srunner_create(s);
srunner_run_all(sr,CK_VERBOSE);
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked teardown failure");
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked teardown failure");
strstat= sr_stat_str(sr);
ck_assert_msg(strcmp(strstat,
"0%: Checks: 1, Failures: 1, Errors: 0") == 0,
"SRunner stat string incorrect with checked setup failure");
free(strstat);
tr = srunner_failures(sr);
trm = tr_str(tr[0]);
if (strstr(trm,
"check_check_fixture.c:155:S:Teardown Fail:test_sub_pass:0: Failed teardown")
== 0) {
snprintf(errm, sizeof(errm),
"Bad failed checked teardown tr msg (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
free(tr);
}
END_TEST
START_TEST(test_ch_teardown_fail_nofork)
{
TCase *tc;
Suite *s;
SRunner *sr;
TestResult **tr;
char *strstat;
char *trm;
s = suite_create("Teardown Fail No Fork");
tc = tcase_create("Teardown Fail No Fork");
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_pass);
tcase_add_checked_fixture(tc,NULL, teardown_sub_fail);
sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr,CK_VERBOSE);
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked teardown failure");
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked teardown failure");
strstat= sr_stat_str(sr);
ck_assert_msg(strcmp(strstat,
"0%: Checks: 1, Failures: 1, Errors: 0") == 0,
"SRunner stat string incorrect with checked setup failure");
free(strstat);
tr = srunner_failures(sr);
trm = tr_str(tr[0]);
if (strstr(trm,
"check_check_fixture.c:155:S:Teardown Fail No Fork:test_sub_pass:0: Failed teardown")
== 0) {
snprintf(errm, sizeof(errm),
"Bad failed checked teardown tr msg (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
free(tr);
}
END_TEST
/* This test currently does not work on Cygwin, as it results in a
* SIGSEGV instead of a SIGFPE. However, a simple program that installs
* a SIGFPE handler then raise(SIGFPE) works as expected. Further
* investigation is necessary. */
#if !defined(__CYGWIN__)
/*
* This test will fail without fork, as it results in a checked
* fixture raising a signal, which terminates the test runner early.
*/
START_TEST(test_ch_teardown_sig)
{
TCase *tc;
Suite *s;
SRunner *sr;
TestResult **tr;
char *strstat;
char *trm;
s = suite_create("Teardown Sig");
tc = tcase_create("Teardown Sig");
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_pass);
tcase_add_checked_fixture(tc,NULL, teardown_sub_signal);
sr = srunner_create(s);
srunner_run_all(sr,CK_VERBOSE);
ck_assert_msg (srunner_ntests_failed(sr) == 1,
"Failure counts not correct for checked teardown signal");
ck_assert_msg (srunner_ntests_run(sr) == 1,
"Test run counts not correct for checked teardown signal");
strstat= sr_stat_str(sr);
ck_assert_msg(strcmp(strstat,
"0%: Checks: 1, Failures: 0, Errors: 1") == 0,
"SRunner stat string incorrect with checked teardown signal");
free(strstat);
tr = srunner_failures(sr);
trm = tr_str(tr[0]);
if (strstr(trm,
"check_check_fixture.c:166:S:Teardown Sig:test_sub_pass:0: "
"(after this point) Received signal 8")
== 0) {
snprintf(errm, sizeof(errm),
"Bad msg (%s)", trm);
ck_abort_msg (errm);
}
free(trm);
srunner_free(sr);
free(tr);
}
END_TEST
#endif /* !defined(__CYGWIN__) */
/* Teardowns are run in reverse order */
static void sub_ch_teardown_dual_1(void)
{
ck_assert_msg(testval_down == 6, "Second teardown failed");
}
static void sub_ch_teardown_dual_2(void)
{
ck_assert_msg(testval_down == 3, "First teardown failed");
testval_down += 3;
}
START_TEST(test_sub_two_teardowns)
{
testval_down += 2;
}
END_TEST
/*
* This test will not work without fork, as checked fixtures are
* not supported
*/
START_TEST(test_ch_teardown_two_teardowns_fork)
{
TCase *tc;
Suite *s;
SRunner *sr;
int nr_of_failures;
char errm[1024] = {0};
s = suite_create("Fixture Two teardowns");
tc = tcase_create("Fixture Two teardowns");
sr = srunner_create(s);
suite_add_tcase(s, tc);
tcase_add_test(tc,test_sub_two_teardowns);
tcase_add_checked_fixture(tc,NULL,sub_ch_teardown_dual_1);
tcase_add_checked_fixture(tc,NULL,sub_ch_teardown_dual_2);
testval_down = 1;
srunner_run_all(sr, CK_VERBOSE);
nr_of_failures = srunner_ntests_failed(sr);
if (nr_of_failures > 0) {
TestResult **tra = srunner_failures(sr);
int i;
for (i = 0; i < nr_of_failures; i++) {
char *trm = tr_str(tra[i]);
if (strlen(errm) + strlen(trm) > 1022) {
free(trm);
break;
}
strcat(errm, trm);
strcat(errm, "\n");
free(trm);
}
free(tra);
}
ck_assert_msg(nr_of_failures == 0, "Problem with several teardowns\n %s",
errm);
srunner_free(sr);
}
END_TEST
#endif /* HAVE_FORK */
Suite *make_fixture_suite (void)
{
Suite *s;
TCase *tc;
s = suite_create("Fixture");
tc = tcase_create("Core");
suite_add_tcase (s, tc);
tcase_add_test(tc,test_fixture_fail_counts);
tcase_add_test(tc,test_print_counts);
tcase_add_test(tc,test_setup_failure_msg);
#if defined(HAVE_FORK) && HAVE_FORK==1
/*
* This test assumes that CK_FORK is being used,
* as it tests that side effects from checked
* fixtures do not persist between tests.
*/
tcase_add_test(tc,test_ch_setup);
tcase_add_test(tc,test_ch_setup_fail);
tcase_add_test(tc,test_ch_setup_fail_nofork);
tcase_add_test(tc,test_ch_setup_fail_nofork_2);
tcase_add_test(tc,test_ch_setup_pass_nofork);
#if !defined(__CYGWIN__)
tcase_add_test(tc,test_ch_setup_sig);
#endif /* !defined(__CYGWIN__) */
tcase_add_test(tc,test_ch_setup_two_setups_fork);
tcase_add_test(tc,test_ch_teardown_fail);
tcase_add_test(tc,test_ch_teardown_fail_nofork);
#if !defined(__CYGWIN__)
tcase_add_test(tc,test_ch_teardown_sig);
#endif /* !defined(__CYGWIN__) */
tcase_add_test(tc,test_ch_teardown_two_teardowns_fork);
#endif
return s;
}