C++ Utilities 5.23.0
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 "../misc/traits.h"
6
7#include <iomanip>
8#include <optional>
9#include <ostream>
10#include <string>
11
12namespace CppUtilities {
13
17enum class WorkingCopyMode {
19 NoCopy,
20 Cleanup,
21};
22
24public:
25 // construction/destruction
26 explicit TestApplication();
27 explicit TestApplication(int argc, const char *const *argv);
29 operator bool() const;
30
31 // helper for tests
32 std::string testFilePath(const std::string &relativeTestFilePath) const;
33 std::string testDirPath(const std::string &relativeTestDirPath) const;
34 std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
35 std::string workingCopyPathAs(const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath,
36 WorkingCopyMode mode = WorkingCopyMode::CreateCopy) const;
37#ifdef PLATFORM_UNIX
38 int execApp(const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1) const;
39#endif
40
41 // read-only accessors
42 const std::vector<std::string> &testFilePaths() const;
43 const std::string &workingDirectory() const;
44 const char *applicationPath();
45 bool unitsSpecified() const;
46 const std::vector<const char *> &units() const;
47 bool onlyListUnits() const;
48
49 // static read-only accessors
50 static const TestApplication *instance();
51 static const char *appPath();
52
53private:
54 static std::string readTestfilePathFromEnv();
55 static std::vector<std::string> readTestfilePathFromSrcRef();
56
57 ArgumentParser m_parser;
58 OperationArgument m_listArg;
59 OperationArgument m_runArg;
60 ConfigValueArgument m_testFilesPathArg;
61 ConfigValueArgument m_applicationPathArg;
62 ConfigValueArgument m_workingDirArg;
63 ConfigValueArgument m_unitsArg;
64 std::vector<std::string> m_testFilesPaths;
65 std::string m_workingDir;
66 bool m_valid;
67 static TestApplication *s_instance;
68};
69
76inline TestApplication::operator bool() const
77{
78 return m_valid;
79}
80
85{
86 return TestApplication::s_instance;
87}
88
92inline const char *TestApplication::appPath()
93{
94 return s_instance ? s_instance->applicationPath() : "";
95}
96
100inline const std::vector<std::string> &TestApplication::testFilePaths() const
101{
102 return m_testFilesPaths;
103}
104
108inline const std::string &TestApplication::workingDirectory() const
109{
110 return m_workingDir;
111}
112
117{
118 return m_applicationPathArg.firstValue() ? m_applicationPathArg.firstValue() : "";
119}
120
125{
126 return m_unitsArg.isPresent();
127}
128
133inline const std::vector<const char *> &TestApplication::units() const
134{
135 return m_unitsArg.values();
136}
137
142{
143 return m_listArg.isPresent();
144}
145
150inline CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
151{
152 return TestApplication::instance()->testFilePath(relativeTestFilePath);
153}
154
159inline CPP_UTILITIES_EXPORT std::string testDirPath(const std::string &relativeTestDirPath)
160{
161 return TestApplication::instance()->testDirPath(relativeTestDirPath);
162}
163
168inline CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy)
169{
170 return TestApplication::instance()->workingCopyPathAs(relativeTestFilePath, relativeTestFilePath, mode);
171}
172
178 const std::string &relativeTestFilePath, const std::string &relativeWorkingCopyPath, WorkingCopyMode mode = WorkingCopyMode::CreateCopy)
179{
180 return TestApplication::instance()->workingCopyPathAs(relativeTestFilePath, relativeWorkingCopyPath, mode);
181}
182
183#ifdef PLATFORM_UNIX
189inline CPP_UTILITIES_EXPORT int execApp(const char *const *args, std::string &output, std::string &errors)
190{
191 return TestApplication::instance()->execApp(args, output, errors);
192}
193
194CPP_UTILITIES_EXPORT int execHelperApp(
195 const char *appPath, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
196CPP_UTILITIES_EXPORT int execHelperAppInSearchPath(
197 const char *appName, const char *const *args, std::string &output, std::string &errors, bool suppressLogging = false, int timeout = -1);
198#endif // PLATFORM_UNIX
199
203template <typename Optional, Traits::EnableIf<Traits::IsSpecializationOf<Optional, std::optional>> * = nullptr>
204inline std::ostream &operator<<(std::ostream &out, const Optional &optional)
205{
206 if (optional.has_value()) {
207 return out << *optional;
208 } else {
209 return out << "[no value]";
210 }
211}
212
217template <typename T> class AsHexNumber {
218public:
221 : value(value)
222 {
223 }
224 const T &value;
225};
226
230template <typename T> bool operator==(const AsHexNumber<T> &lhs, const AsHexNumber<T> &rhs)
231{
232 return lhs.value == rhs.value;
233}
234
238template <typename T> std::ostream &operator<<(std::ostream &out, const AsHexNumber<T> &value)
239{
240 return out << '0' << 'x' << std::hex << std::setfill('0') << std::setw(2) << unsigned(value.value) << std::dec;
241}
242
247template <typename T> AsHexNumber<T> asHexNumber(const T &value)
248{
249 return AsHexNumber<T>(value);
250}
251
257template <typename T, Traits::EnableIf<std::is_integral<T>> * = nullptr> AsHexNumber<T> integralsAsHexNumber(const T &value)
258{
259 return AsHexNumber<T>(value);
260}
261
267template <typename T, Traits::DisableIf<std::is_integral<T>> * = nullptr> const T &integralsAsHexNumber(const T &value)
268{
269 return value;
270}
271
280#define TESTUTILS_ASSERT_EXEC(args) TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, 0)
281
290#define TESTUTILS_ASSERT_EXEC_EXIT_STATUS(args, expectedExitStatus) \
291 { \
292 const auto status = execApp(args, stdout, stderr); \
293 if (!WIFEXITED(status)) { \
294 CPPUNIT_FAIL(::CppUtilities::argsToString("app did not terminate normally\nstdout: ", stdout, "\nstderr: ", stderr)); \
295 } \
296 if (const auto exitStatus = WEXITSTATUS(status); exitStatus != expectedExitStatus) { \
297 CPPUNIT_FAIL(::CppUtilities::argsToString( \
298 "app exited with status ", exitStatus, " (expected ", expectedExitStatus, ")\nstdout: ", stdout, "\nstderr: ", stderr)); \
299 } \
300 }
301
306#define TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, regexFlags, actualString) \
307 (CPPUNIT_NS::Asserter::failIf(!(std::regex_match(actualString, std::regex(expectedRegex, regexFlags))), \
308 CPPUNIT_NS::Message( \
309 CppUtilities::argsToString('\"', actualString, "\"\n not like\n\"", expectedRegex, '\"'), "Expression: " #actualString, message), \
310 CPPUNIT_SOURCELINE()))
311
316#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString) \
317 TESTUTILS_ASSERT_LIKE_FLAGS(message, expectedRegex, std::regex::ECMAScript, actualString)
318
322template <typename Pair, CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsSpecializationOf<Pair, std::pair>> * = nullptr>
323inline std::ostream &operator<<(std::ostream &out, const Pair &pair)
324{
325 return out << "key: " << pair.first << "; value: " << pair.second << '\n';
326}
327
331template <typename Iteratable, Traits::EnableIf<Traits::IsIteratable<Iteratable>, Traits::Not<Traits::IsString<Iteratable>>> * = nullptr>
332inline std::ostream &operator<<(std::ostream &out, const Iteratable &iteratable)
333{
334 out << '\n';
335 std::size_t index = 0;
336 for (const auto &item : iteratable) {
337 out << std::setw(2) << index << ':' << ' ' << integralsAsHexNumber(item) << '\n';
338 ++index;
339 }
340 return out;
341}
342
346namespace Literals {
351constexpr std::size_t operator"" _st(unsigned long long size)
352{
353 return static_cast<std::size_t>(size);
354}
355
360constexpr std::uint64_t operator"" _uint64(unsigned long long size)
361{
362 return static_cast<std::uint64_t>(size);
363}
364
369constexpr std::int64_t operator"" _int64(unsigned long long size)
370{
371 return static_cast<std::int64_t>(size);
372}
373} // namespace Literals
374} // namespace CppUtilities
375
376#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:217
AsHexNumber(const T &value)
Constructs a new instance; use asHexNumber() for convenience instead.
Definition testutils.h:220
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:23
bool onlyListUnits() const
Returns whether the test application should only list available units and not actually run any tests.
Definition testutils.h:141
const std::vector< const char * > & units() const
Returns the specified test units.
Definition testutils.h:133
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:92
const std::vector< std::string > & testFilePaths() const
Returns the list of directories to look for test files.
Definition testutils.h:100
bool unitsSpecified() const
Returns whether particular units have been specified.
Definition testutils.h:124
const char * applicationPath()
Returns the application path or an empty string if no application path has been set.
Definition testutils.h:116
const std::string & workingDirectory() const
Returns the directory which is supposed to used for storing files created by tests.
Definition testutils.h:108
static const TestApplication * instance()
Returns the current TestApplication instance.
Definition testutils.h:84
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:150
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath, WorkingCopyMode mode=WorkingCopyMode::CreateCopy)
Convenience function to invoke TestApplication::workingCopyPath().
Definition testutils.h:168
WorkingCopyMode
The WorkingCopyMode enum specifies additional options to influence behavior of TestApplication::worki...
Definition testutils.h:17
CPP_UTILITIES_EXPORT std::string testDirPath(const std::string &relativeTestDirPath)
Convenience function to invoke TestApplication::testDirPath().
Definition testutils.h:159
CPP_UTILITIES_EXPORT std::ostream & operator<<(std::ostream &out, Indentation indentation)
bool operator==(const AsHexNumber< T > &lhs, const AsHexNumber< T > &rhs)
Provides operator == required by CPPUNIT_ASSERT_EQUAL.
Definition testutils.h:230
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:247
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:177
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:257