C++ Utilities: tests/testutils.h Source File

C++ Utilities 5.34.2 Useful C++ classes and routines such as argument parser, IO and conversion utilities

Loading...
Searching...
No Matches
testutils.h
Go to the documentation of this file.
1#ifndef TESTUTILS_H
2#define TESTUTILS_H
3
4#include "../application/argumentparser.h"
5#include "../chrono/format.h"
6#include "../misc/traits.h"
7
8#include <iomanip>
9#include <optional>
10#include <ostream>
11#include <string>
12
13#if defined(PLATFORM_UNIX) || defined(CPP_UTILITIES_BOOST_PROCESS)
14#define CPP_UTILITIES_HAS_EXEC_APP
15#endif
16
17// ensure CppUnit's macros produce unique variable names when doing unity builds
18#if defined(__COUNTER__)
19#undef CPPUNIT_UNIQUE_COUNTER
20#define CPPUNIT_UNIQUE_COUNTER __COUNTER__
21#endif
22
23namespace CppUtilities {
24
28 enum class WorkingCopyMode {
29 CreateCopy,
30 NoCopy,
31 Cleanup,
32};
33
34 class CPP_UTILITIES_EXPORT TestApplication {
35public:
36 // construction/destruction
37 explicit TestApplication();
38 explicit TestApplication(int argc, const char *const *argv);
39 ~TestApplication();
40 operator bool() const;
41
42 // helper for tests
43 std::string testFilePath(const std::string &relativeTestFilePath) const;
44 std::string testDirPath(const std::string &relativeTestDirPath) const;
45 std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
46 std::string workingCopyPathAs(const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath,
47 WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
48#ifdef CPP_UTILITIES_HAS_EXEC_APP
49 int execApp(const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1) const;
50#endif
51
52 // read-only accessors
53 const std::vector<std::string> &testFilePaths() const;
54 const std::string &workingDirectory() const;
55 const char *applicationPath();
56 bool unitsSpecified() const;
57 const std::vector<const char *> &units() const;
58 bool onlyListUnits() const;
59
60 // static read-only accessors
61 static const TestApplication *instance();
62 static const char *appPath();
63
64private:
65 static std::string readTestfilePathFromEnv();
66 static std::vector<std::string> readTestfilePathFromSrcRef();
67
68 ArgumentParser m_parser;
69 OperationArgument m_listArg;
70 OperationArgument m_runArg;
71 ConfigValueArgument m_testFilesPathArg;
72 ConfigValueArgument m_applicationPathArg;
73 ConfigValueArgument m_workingDirArg;
74 ConfigValueArgument m_unitsArg;
75 std::vector<std::string> m_testFilesPaths;
76 std::string m_workingDir;
77 bool m_valid;
78 static TestApplication *s_instance;
79};
80
87 inline TestApplication::operator bool() const
88{
89 return m_valid;
90}
91
95 inline const TestApplication *TestApplication::instance()
96{
97 return TestApplication::s_instance;
98}
99
103 inline const char *TestApplication::appPath()
104{
105 return s_instance ? s_instance->applicationPath() : "";
106}
107
111 inline const std::vector<std::string> &TestApplication::testFilePaths() const
112{
113 return m_testFilesPaths;
114}
115
119 inline const std::string &TestApplication::workingDirectory() const
120{
121 return m_workingDir;
122}
123
127 inline const char *TestApplication::applicationPath()
128{
129 return m_applicationPathArg.firstValue() ? m_applicationPathArg.firstValue() : "";
130}
131
135 inline bool TestApplication::unitsSpecified() const
136{
137 return m_unitsArg.isPresent();
138}
139
144 inline const std::vector<const char *> &TestApplication::units() const
145{
146 return m_unitsArg.values();
147}
148
152 inline bool TestApplication::onlyListUnits() const
153{
154 return m_listArg.isPresent();
155}
156
161 inline CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
162{
163 return TestApplication::instance()->testFilePath(relativeTestFilePath);
164}
165
170 inline CPP_UTILITIES_EXPORT std::string testDirPath(const std::string &relativeTestDirPath)
171{
172 return TestApplication::instance()->testDirPath(relativeTestDirPath);
173}
174
179 inline CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy)
180{
181 return TestApplication::instance()->workingCopyPathAs(relativeTestFilePath, relativeTestFilePath, mode);
182}
183
188 inline CPP_UTILITIES_EXPORT std::string workingCopyPathAs(
189 const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy)
190{
191 return TestApplication::instance()->workingCopyPathAs(relativeTestFilePath, relativeWorkingCopyPath, mode);
192}
193
194#ifdef CPP_UTILITIES_HAS_EXEC_APP
200inline CPP_UTILITIES_EXPORT int execApp(const char *const *args, std::string &output, std::string &errors)
201{
202 return TestApplication::instance()->execApp(args, output, errors);
203}
204
205 CPP_UTILITIES_EXPORT int execHelperApp(
206 const char *appPath, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
207 CPP_UTILITIES_EXPORT int execHelperAppInSearchPath(
208 const char *appName, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
209#endif
210
214template <typename Optional, Traits::EnableIf<Traits::IsSpecializationOf<Optional, std::optional>> * = nullptr>
215 inline std::ostream &operator<<(std::ostream &out, const Optional &optional)
216{
217 if (optional.has_value()) {
218 return out << *optional;
219 } else {
220 return out << "[no value]";
221 }
222}
223
228 template <typename T> class AsHexNumber {
229public:
231 AsHexNumber(const T &value)
232 : value(value)
233 {
234 }
235 const T &value;
236};
237
241 template <typename T> bool operator==(const AsHexNumber<T> &lhs, const AsHexNumber<T> &rhs)
242{
243 return lhs.value == rhs.value;
244}
245
249 template <typename T> std::ostream &operator<<(std::ostream &out, const AsHexNumber<T> &value)
250{
251 return out << '0' << 'x' << std::hex << std::setfill('0') << std::setw(2) << unsigned(value.value) << std::dec;
252}
253
258 template <typename T> AsHexNumber<T> asHexNumber(const T &value)
259{
260 return AsHexNumber<T>(value);
261}
262
268 template <typename T, Traits::EnableIf<std::is_integral<T>> * = nullptr> AsHexNumber<T> integralsAsHexNumber(const T &value)
269{
270 return AsHexNumber<T>(value);
271}
272
278 template <typename T, Traits::DisableIf<std::is_integral<T>> * = nullptr> const T &integralsAsHexNumber(const T &value)
279{
280 return value;
281}
282
291#define TESTUTILS_ASSERT_EXEC(args) TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, 0)
292
301#ifdef CPP_UTILITIES_BOOST_PROCESS
302#define TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, expectedExitStatus) \
303 { \
304 const auto status = execApp(args, stdout, stderr); \
305 if (status != expectedExitStatus) { \
306 CPPUNIT_FAIL(::CppUtilities::argsToString( \
307 "app exited with status ", status, " (expected ", expectedExitStatus, ")\nstdout: ", stdout, "\nstderr: ", stderr)); \
308 } \
309 }
310#else
311#define TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, expectedExitStatus) \
312 { \
313 const auto status = execApp(args, stdout, stderr); \
314 if (!WIFEXITED(status)) { \
315 CPPUNIT_FAIL(::CppUtilities::argsToString("app did not terminate normally\nstdout: ", stdout, "\nstderr: ", stderr)); \
316 } \
317 if (const auto exitStatus = WEXITSTATUS(status); exitStatus != expectedExitStatus) { \
318 CPPUNIT_FAIL(::CppUtilities::argsToString( \
319 "app exited with status ", exitStatus, " (expected ", expectedExitStatus, ")\nstdout: ", stdout, "\nstderr: ", stderr)); \
320 } \
321 }
322#endif
323
328#define TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, regexFlags, actualString) \
329 CPPUNIT_ASSERT_MESSAGE( \
330 CppUtilities::argsToString('\"', actualString, "\"\n not like\n\"", expectedRegex, '\"', "\n\nExpression: " #actualString, message), \
331 (std::regex_match(actualString, std::regex(expectedRegex, regexFlags))))
332
336#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString) \
337 TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, std::regex::ECMAScript, actualString)
338
342template <typename Pair, CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsSpecializationOf<Pair, std::pair>> * = nullptr>
343inline std::ostream &operator<<(std::ostream &out, const Pair &pair)
344{
345 return out << "key: " << pair.first << "; value: " << pair.second << '\n';
346}
347
351template <typename Iteratable, Traits::EnableIf<Traits::IsIteratable<Iteratable>, Traits::Not<Traits::IsString<Iteratable>>> * = nullptr>
352inline std::ostream &operator<<(std::ostream &out, const Iteratable &iteratable)
353{
354 out << '\n';
355 std::size_t index = 0;
356 for (const auto &item : iteratable) {
357 out << std::setw(2) << index << ':' << ' ' << integralsAsHexNumber(item) << '\n';
358 ++index;
359 }
360 return out;
361}
362
366namespace Literals {
371constexpr std::size_t operator""_st(unsigned long long size)
372{
373 return static_cast<std::size_t>(size);
374}
375
380constexpr std::uint64_t operator""_uint64(unsigned long long size)
381{
382 return static_cast<std::uint64_t>(size);
383}
384
389constexpr std::int64_t operator""_int64(unsigned long long size)
390{
391 return static_cast<std::int64_t>(size);
392}
393} // namespace Literals
394} // namespace CppUtilities
395
396#endif // TESTUTILS_H
argumentparser.h
CppUtilities::ArgumentParser
The ArgumentParser class provides a means for handling command line arguments.
Definition argumentparser.h:457
CppUtilities::AsHexNumber
The AsHexNumber class allows printing values asserted with cppunit (or similar test framework) using ...
Definition testutils.h:228
CppUtilities::AsHexNumber::AsHexNumber
AsHexNumber(const T &value)
Constructs a new instance; use asHexNumber() for convenience instead.
Definition testutils.h:231
CppUtilities::AsHexNumber::value
const T & value
Definition testutils.h:235
CppUtilities::ConfigValueArgument
The ConfigValueArgument class is an Argument where setCombinable() is true by default.
Definition argumentparser.h:441
CppUtilities::OperationArgument
The OperationArgument class is an Argument where denotesOperation() is true by default.
Definition argumentparser.h:436
CppUtilities::TestApplication::onlyListUnits
bool onlyListUnits() const
Returns whether the test application should only list available units and not actually run any tests.
Definition testutils.h:152
CppUtilities::TestApplication::units
const std::vector< const char * > & units() const
Returns the specified test units.
Definition testutils.h:144
CppUtilities::TestApplication::workingCopyPath
std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy) const
Returns the full path to a working copy of the test file with the specified relativeTestFilePath.
Definition testutils.cpp:299
CppUtilities::TestApplication::testFilePath
std::string testFilePath(const std::string &relativeTestFilePath) const
Returns the full path of the test file with the specified relativeTestFilePath.
Definition testutils.cpp:262
CppUtilities::TestApplication::appPath
static const char * appPath()
Returns the application path or an empty string if no application path has been set.
Definition testutils.h:103
CppUtilities::TestApplication::testFilePaths
const std::vector< std::string > & testFilePaths() const
Returns the list of directories to look for test files.
Definition testutils.h:111
CppUtilities::TestApplication::TestApplication
TestApplication()
Constructs a TestApplication instance without further arguments.
Definition testutils.cpp:140
CppUtilities::TestApplication::unitsSpecified
bool unitsSpecified() const
Returns whether particular units have been specified.
Definition testutils.h:135
CppUtilities::TestApplication::applicationPath
const char * applicationPath()
Returns the application path or an empty string if no application path has been set.
Definition testutils.h:127
CppUtilities::TestApplication::workingDirectory
const std::string & workingDirectory() const
Returns the directory which is supposed to used for storing files created by tests.
Definition testutils.h:119
CppUtilities::TestApplication::instance
static const TestApplication * instance()
Returns the current TestApplication instance.
Definition testutils.h:95
CppUtilities::TestApplication::workingCopyPathAs
std::string workingCopyPathAs(const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy) const
Returns the full path to a working copy of the test file with the specified relativeTestFilePath.
Definition testutils.cpp:318
CppUtilities::TestApplication::testDirPath
std::string testDirPath(const std::string &relativeTestDirPath) const
Returns the full path of the test directory with the specified relativeTestDirPath.
Definition testutils.cpp:280
format.h
CPP_UTILITIES_EXPORT
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
Definition global.h:14
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition argumentparser.h:18
CppUtilities::testFilePath
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::testFilePath().
Definition testutils.h:161
CppUtilities::workingCopyPath
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPath().
Definition testutils.h:179
CppUtilities::WorkingCopyMode
WorkingCopyMode
The WorkingCopyMode enum specifies additional options to influence behavior of TestApplication::worki...
Definition testutils.h:28
CppUtilities::WorkingCopyMode::CreateCopy
@ CreateCopy
Definition testutils.h:29
CppUtilities::WorkingCopyMode::Cleanup
@ Cleanup
Definition testutils.h:31
CppUtilities::WorkingCopyMode::NoCopy
@ NoCopy
Definition testutils.h:30
CppUtilities::testDirPath
CPP_UTILITIES_EXPORT std::string testDirPath(const std::string &relativeTestDirPath)
Convenience function to invoke TestApplication::testDirPath().
Definition testutils.h:170
CppUtilities::operator<<
CPP_UTILITIES_EXPORT std::ostream & operator<<(std::ostream &out, Indentation indentation)
Definition commandlineutils.h:88
CppUtilities::operator==
bool operator==(const AsHexNumber< T > &lhs, const AsHexNumber< T > &rhs)
Provides operator == required by CPPUNIT_ASSERT_EQUAL.
Definition testutils.h:241
CppUtilities::asHexNumber
AsHexNumber< T > asHexNumber(const T &value)
Wraps a value to be printed using the hex system in the error case when asserted with cppunit (or sim...
Definition testutils.h:258
CppUtilities::workingCopyPathAs
CPP_UTILITIES_EXPORT std::string workingCopyPathAs(const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPathAs().
Definition testutils.h:188
CppUtilities::integralsAsHexNumber
AsHexNumber< T > integralsAsHexNumber(const T &value)
Wraps a value to be printed using the hex system in the error case when asserted with cppunit (or sim...
Definition testutils.h:268
traits.h