1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#ifndef TESTTHAT_HPP
#define TESTTHAT_HPP
#define TESTTHAT_TOKEN_PASTE_IMPL(__X__, __Y__) __X__ ## __Y__
#define TESTTHAT_TOKEN_PASTE(__X__, __Y__) TESTTHAT_TOKEN_PASTE_IMPL(__X__, __Y__)
#define TESTTHAT_DISABLED_FUNCTION \
static void TESTTHAT_TOKEN_PASTE(testthat_disabled_test_, __LINE__) ()
/**
* Conditionally enable or disable 'testthat' + 'Catch'.
* Force 'testthat' to be enabled by defining TESTTHAT_ENABLED.
* Force 'testthat' to be disabled by defining TESTTHAT_DISABLED.
* TESTTHAT_DISABLED takes precedence.
* 'testthat' is disabled on Solaris by default.
*/
#if defined(__GNUC__) || defined(__clang__)
# define TESTTHAT_ENABLED
#endif
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__sun) || defined(__SVR4)
# define TESTTHAT_DISABLED
#endif
#ifndef TESTTHAT_ENABLED
# define TESTTHAT_DISABLED
#endif
/*
* Hide symbols containing static members on gcc, to work around issues
* with DLL unload due to static members in inline functions. This seems to only
* affect Linux. We never define this attribute on Windows, as MinGW has a known
* issue with this visibility attribute and ignores it with a warning.
* https://github.com/r-lib/devtools/issues/1832
* https://github.com/r-lib/testthat/issues/1672
*/
#if (defined(__GNUC__) && !defined(__MINGW32__)) || defined(__clang__)
# define TESTTHAT_ATTRIBUTE_HIDDEN __attribute__ ((visibility("hidden")))
#else
# define TESTTHAT_ATTRIBUTE_HIDDEN
#endif
#ifndef TESTTHAT_DISABLED
# define CATCH_CONFIG_PREFIX_ALL
# define CATCH_CONFIG_NOSTDOUT
# ifdef TESTTHAT_TEST_RUNNER
# define CATCH_CONFIG_RUNNER
# endif
# include <climits> // CHAR_MAX
# include <cstdio> // EOF
# ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wparentheses"
# endif
namespace Catch {
// Avoid 'R CMD check' warnings related to the use of 'std::rand()' and
// 'std::srand()'. Since we don't call any Catch APIs that use these
// functions, it suffices to just override them in the Catch namespace.
inline void srand(unsigned) {}
inline int rand() { return 42; }
// Catch has calls to 'exit' on failure, which upsets R CMD check.
// We won't bump into them during normal test execution so just override
// it in the Catch namespace before we include 'catch'.
inline void exit(int) throw() {}
}
# include "vendor/catch.h"
// Implement an output stream that avoids writing to stdout / stderr.
extern "C" void Rprintf(const char*, ...);
extern "C" void R_FlushConsole();
namespace testthat {
class r_streambuf : public std::streambuf {
public:
r_streambuf() {}
protected:
virtual std::streamsize xsputn(const char* s, std::streamsize n) {
if (n == 1)
Rprintf("%c", *s);
else
Rprintf("%.*s", static_cast<int>(n), s);
return n;
}
virtual int overflow(int c = EOF) {
if (c == EOF)
return c;
if (c > CHAR_MAX)
return c;
Rprintf("%c", (char) c);
return c;
}
virtual int sync() {
R_FlushConsole();
return 0;
}
};
class r_ostream : public std::ostream {
public:
r_ostream() : std::ostream(new r_streambuf) {}
~r_ostream() { delete rdbuf(); }
};
// Allow client packages to access the Catch::Session
// exported by testthat.
# ifdef CATCH_CONFIG_RUNNER
TESTTHAT_ATTRIBUTE_HIDDEN
inline Catch::Session& catchSession()
{
static Catch::Session instance;
return instance;
}
inline bool run_tests(bool use_xml)
{
if (use_xml) {
const char* argv[] = {"catch", "-r", "xml"};
return catchSession().run(3, argv) == 0;
} else {
return catchSession().run() == 0;
}
}
# endif // CATCH_CONFIG_RUNNER
} // namespace testthat
namespace Catch {
TESTTHAT_ATTRIBUTE_HIDDEN
inline std::ostream& cout()
{
static testthat::r_ostream instance;
return instance;
}
TESTTHAT_ATTRIBUTE_HIDDEN
inline std::ostream& cerr()
{
static testthat::r_ostream instance;
return instance;
}
} // namespace Catch
# ifdef TESTTHAT_TEST_RUNNER
// ERROR will be redefined by R; avoid compiler warnings
# ifdef ERROR
# undef ERROR
# endif
# include <R.h>
# include <Rinternals.h>
extern "C" SEXP run_testthat_tests(SEXP use_xml_sxp) {
bool use_xml = LOGICAL(use_xml_sxp)[0];
bool success = testthat::run_tests(use_xml);
return Rf_ScalarLogical(success);
}
# endif // TESTTHAT_TEST_RUNNER
# define context(__X__) CATCH_TEST_CASE(__X__ " | " __FILE__)
# define test_that CATCH_SECTION
# define expect_true CATCH_CHECK
# define expect_false CATCH_CHECK_FALSE
# define expect_error CATCH_CHECK_THROWS
# define expect_error_as CATCH_CHECK_THROWS_AS
#else // TESTTHAT_DISABLED
# define context(__X__) TESTTHAT_DISABLED_FUNCTION
# define test_that(__X__) if (false)
# define expect_true(__X__) (void) (__X__)
# define expect_false(__X__) (void) (__X__)
# define expect_error(__X__) (void) (__X__)
# define expect_error_as(__X__, __Y__) (void) (__X__)
# ifdef TESTTHAT_TEST_RUNNER
# include <R.h>
# include <Rinternals.h>
extern "C" SEXP run_testthat_tests() {
return Rf_ScalarLogical(true);
}
# endif // TESTTHAT_TEST_RUNNER
#endif // TESTTHAT_DISABLED
#endif /* TESTTHAT_HPP */
|