C++ Utilities 5.24.5
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
5#include "../misc/traits.h"
6
7#include <iomanip>
8#include <optional>
9#include <ostream>
10#include <string>
11
12#if defined(PLATFORM_UNIX) || defined(CPP_UTILITIES_BOOST_PROCESS)
13#define CPP_UTILITIES_HAS_EXEC_APP
14#endif
15
16namespace CppUtilities {
17
21enum class WorkingCopyMode {
23 NoCopy,
24 Cleanup,
25};
26
28public:
29 // construction/destruction
30 explicit TestApplication();
31 explicit TestApplication(int argc, const char *const *argv);
33 operator bool() const;
34
35 // helper for tests
36 std::string testFilePath(const std::string &relativeTestFilePath) const;
37 std::string testDirPath(const std::string &relativeTestDirPath) const;
38 std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
39 std::string workingCopyPathAs(const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath,
40 WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
41#ifdef CPP_UTILITIES_HAS_EXEC_APP
42 int execApp(const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1) const;
43#endif
44
45 // read-only accessors
46 const std::vector<std::string> &testFilePaths() const;
47 const std::string &workingDirectory() const;
48 const char *applicationPath();
49 bool unitsSpecified() const;
50 const std::vector<const char *> &units() const;
51 bool onlyListUnits() const;
52
53 // static read-only accessors
54 static const TestApplication *instance();
55 static const char *appPath();
56
57private:
58 static std::string readTestfilePathFromEnv();
59 static std::vector<std::string> readTestfilePathFromSrcRef();
60
61 ArgumentParser m_parser;
62 OperationArgument m_listArg;
63 OperationArgument m_runArg;
64 ConfigValueArgument m_testFilesPathArg;
65 ConfigValueArgument m_applicationPathArg;
66 ConfigValueArgument m_workingDirArg;
67 ConfigValueArgument m_unitsArg;
68 std::vector<std::string> m_testFilesPaths;
69 std::string m_workingDir;
70 bool m_valid;
71 static TestApplication *s_instance;
72};
73
80inline TestApplication::operator bool() const
81{
82 return m_valid;
83}
84
89{
90 return TestApplication::s_instance;
91}
92
96inline const char *TestApplication::appPath()
97{
98 return s_instance ? s_instance->applicationPath() : "";
99}
100
104inline const std::vector<std::string> &TestApplication::testFilePaths() const
105{
106 return m_testFilesPaths;
107}
108
112inline const std::string &TestApplication::workingDirectory() const
113{
114 return m_workingDir;
115}
116
121{
122 return m_applicationPathArg.firstValue() ? m_applicationPathArg.firstValue() : "";
123}
124
129{
130 return m_unitsArg.isPresent();
131}
132
137inline const std::vector<const char *> &TestApplication::units() const
138{
139 return m_unitsArg.values();
140}
141
146{
147 return m_listArg.isPresent();
148}
149
158
167
176
186
187#ifdef CPP_UTILITIES_HAS_EXEC_APP
193inline CPP_UTILITIES_EXPORT int execApp(const char *const *args, std::string &output, std::string &errors)
194{
195 return TestApplication::instance()->execApp(args, output, errors);
196}
197
199 const char *appPath, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
201 const char *appName, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
202#endif
203
207template <typename Optional, Traits::EnableIf<Traits::IsSpecializationOf<Optional, std::optional>> * = nullptr>
208inline std::ostream &operator<<(std::ostream &out, const Optional &optional)
209{
210 if (optional.has_value()) {
211 return out << *optional;
212 } else {
213 return out << "[no value]";
214 }
215}
216
221template <typename T> class AsHexNumber {
222public:
225 : value(value)
226 {
227 }
228 const T &value;
229};
230
234template <typename T> bool operator==(const AsHexNumber<T> &lhs, const AsHexNumber<T> &rhs)
235{
236 return lhs.value == rhs.value;
237}
238
242template <typename T> std::ostream &operator<<(std::ostream &out, const AsHexNumber<T> &value)
243{
244 return out << '0' << 'x' << std::hex << std::setfill('0') << std::setw(2) << unsigned(value.value) << std::dec;
245}
246
251template <typename T> AsHexNumber<T> asHexNumber(const T &value)
252{
253 return AsHexNumber<T>(value);
254}
255
261template <typename T, Traits::EnableIf<std::is_integral<T>> * = nullptr> AsHexNumber<T> integralsAsHexNumber(const T &value)
262{
263 return AsHexNumber<T>(value);
264}
265
271template <typename T, Traits::DisableIf<std::is_integral<T>> * = nullptr> const T &integralsAsHexNumber(const T &value)
272{
273 return value;
274}
275
284#define TESTUTILS_ASSERT_EXEC(args) TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, 0)
285
294#ifdef CPP_UTILITIES_BOOST_PROCESS
295#define TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, expectedExitStatus) \
296 { \
297 const auto status = execApp(args, stdout, stderr); \
298 if (status != expectedExitStatus) { \
299 CPPUNIT_FAIL(::CppUtilities::argsToString( \
300 "app exited with status ", status, " (expected ", expectedExitStatus, ")\nstdout: ", stdout, "\nstderr: ", stderr)); \
301 } \
302 }
303#else
304#define TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, expectedExitStatus) \
305 { \
306 const auto status = execApp(args, stdout, stderr); \
307 if (!WIFEXITED(status)) { \
308 CPPUNIT_FAIL(::CppUtilities::argsToString("app did not terminate normally\nstdout: ", stdout, "\nstderr: ", stderr)); \
309 } \
310 if (const auto exitStatus = WEXITSTATUS(status); exitStatus != expectedExitStatus) { \
311 CPPUNIT_FAIL(::CppUtilities::argsToString( \
312 "app exited with status ", exitStatus, " (expected ", expectedExitStatus, ")\nstdout: ", stdout, "\nstderr: ", stderr)); \
313 } \
314 }
315#endif
316
321#define TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, regexFlags, actualString) \
322 (CPPUNIT_NS::Asserter::failIf(!(std::regex_match(actualString, std::regex(expectedRegex, regexFlags))), \
323 CPPUNIT_NS::Message( \
324 CppUtilities::argsToString('\"', actualString, "\"\n not like\n\"", expectedRegex, '\"'), "Expression: " #actualString, message), \
325 CPPUNIT_SOURCELINE()))
326
331#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString) \
332 TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, std::regex::ECMAScript, actualString)
333
337template <typename Pair, CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsSpecializationOf<Pair, std::pair>> * = nullptr>
338inline std::ostream &operator<<(std::ostream &out, const Pair &pair)
339{
340 return out << "key: " << pair.first << "; value: " << pair.second << '\n';
341}
342
346template <typename Iteratable, Traits::EnableIf<Traits::IsIteratable<Iteratable>, Traits::Not<Traits::IsString<Iteratable>>> * = nullptr>
347inline std::ostream &operator<<(std::ostream &out, const Iteratable &iteratable)
348{
349 out << '\n';
350 std::size_t index = 0;
351 for (const auto &item : iteratable) {
352 out << std::setw(2) << index << ':' << ' ' << integralsAsHexNumber(item) << '\n';
353 ++index;
354 }
355 return out;
356}
357
361namespace Literals {
366constexpr std::size_t operator"" _st(unsigned long long size)
367{
368 return static_cast<std::size_t>(size);
369}
370
375constexpr std::uint64_t operator"" _uint64(unsigned long long size)
376{
377 return static_cast<std::uint64_t>(size);
378}
379
384constexpr std::int64_t operator"" _int64(unsigned long long size)
385{
386 return static_cast<std::int64_t>(size);
387}
388} // namespace Literals
389} // namespace CppUtilities
390
391#endif // TESTUTILS_H
The ArgumentParser class provides a means for handling command line arguments.
const char * firstValue() const
Returns the first parameter value of the first occurrence of the argument.
const std::vector< const char * > & values(std::size_t occurrence=0) const
Returns the parameter values for the specified occurrence of argument.
bool isPresent() const
Returns an indication whether the argument could be detected when parsing.
The AsHexNumber class allows printing values asserted with cppunit (or similar test framework) using ...
Definition testutils.h:221
AsHexNumber(const T &value)
Constructs a new instance; use asHexNumber() for convenience instead.
Definition testutils.h:224
The ConfigValueArgument class is an Argument where setCombinable() is true by default.
The OperationArgument class is an Argument where denotesOperation() is true by default.
The TestApplication class simplifies writing test applications that require opening test files.
Definition testutils.h:27
bool onlyListUnits() const
Returns whether the test application should only list available units and not actually run any tests.
Definition testutils.h:145
const std::vector< const char * > & units() const
Returns the specified test units.
Definition testutils.h:137
std::string testFilePath(const std::string &relativeTestFilePath) const
Returns the full path of the test file with the specified relativeTestFilePath.
static const char * appPath()
Returns the application path or an empty string if no application path has been set.
Definition testutils.h:96
const std::vector< std::string > & testFilePaths() const
Returns the list of directories to look for test files.
Definition testutils.h:104
bool unitsSpecified() const
Returns whether particular units have been specified.
Definition testutils.h:128
const char * applicationPath()
Returns the application path or an empty string if no application path has been set.
Definition testutils.h:120
const std::string & workingDirectory() const
Returns the directory which is supposed to used for storing files created by tests.
Definition testutils.h:112
static const TestApplication * instance()
Returns the current TestApplication instance.
Definition testutils.h:88
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.
std::string testDirPath(const std::string &relativeTestDirPath) const
Returns the full path of the test directory with the specified relativeTestDirPath.
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
Definition global.h:13
Contains all utilities provides by the c++utilities library.
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::testFilePath().
Definition testutils.h:154
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPath().
Definition testutils.h:172
WorkingCopyMode
The WorkingCopyMode enum specifies additional options to influence behavior of TestApplication::worki...
Definition testutils.h:21
CPP_UTILITIES_EXPORT std::string testDirPath(const std::string &relativeTestDirPath)
Convenience function to invoke TestApplication::testDirPath().
Definition testutils.h:163
CPP_UTILITIES_EXPORT std::ostream & operator<<(std::ostream &out, Indentation indentation)
IntegralType stringToNumber(const StringType &string, BaseType base=10)
Converts the given string to an unsigned/signed number assuming string uses the specified base.
bool operator==(const AsHexNumber< T > &lhs, const AsHexNumber< T > &rhs)
Provides operator == required by CPPUNIT_ASSERT_EQUAL.
Definition testutils.h:234
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:251
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:181
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:261