| /* | /* | ||||
| * Catch v2.7.1 | |||||
| * Generated: 2019-04-05 18:22:37.720122 | |||||
| * Catch v2.7.2 | |||||
| * Generated: 2019-04-22 23:13:14.687465 | |||||
| * ---------------------------------------------------------- | * ---------------------------------------------------------- | ||||
| * This file has been merged from multiple headers. Please don't edit it directly | * This file has been merged from multiple headers. Please don't edit it directly | ||||
| * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. | * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. | ||||
| #define CATCH_VERSION_MAJOR 2 | #define CATCH_VERSION_MAJOR 2 | ||||
| #define CATCH_VERSION_MINOR 7 | #define CATCH_VERSION_MINOR 7 | ||||
| #define CATCH_VERSION_PATCH 1 | |||||
| #define CATCH_VERSION_PATCH 2 | |||||
| #ifdef __clang__ | #ifdef __clang__ | ||||
| # pragma clang system_header | # pragma clang system_header | ||||
| // The following functions create the actual matcher objects. | // The following functions create the actual matcher objects. | ||||
| // The user has to explicitly specify type to the function, because | // The user has to explicitly specify type to the function, because | ||||
| // infering std::function<bool(T const&)> is hard (but possible) and | |||||
| // inferring std::function<bool(T const&)> is hard (but possible) and | |||||
| // requires a lot of TMP. | // requires a lot of TMP. | ||||
| template<typename T> | template<typename T> | ||||
| Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { | Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { | ||||
| namespace Matchers { | namespace Matchers { | ||||
| namespace Vector { | namespace Vector { | ||||
| namespace Detail { | |||||
| template <typename InputIterator, typename T> | |||||
| size_t count(InputIterator first, InputIterator last, T const& item) { | |||||
| size_t cnt = 0; | |||||
| for (; first != last; ++first) { | |||||
| if (*first == item) { | |||||
| ++cnt; | |||||
| } | |||||
| } | |||||
| return cnt; | |||||
| } | |||||
| template <typename InputIterator, typename T> | |||||
| bool contains(InputIterator first, InputIterator last, T const& item) { | |||||
| for (; first != last; ++first) { | |||||
| if (*first == item) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| template<typename T> | template<typename T> | ||||
| struct ContainsElementMatcher : MatcherBase<std::vector<T>> { | struct ContainsElementMatcher : MatcherBase<std::vector<T>> { | ||||
| std::vector<T> const& m_comparator; | std::vector<T> const& m_comparator; | ||||
| }; | }; | ||||
| template<typename T> | |||||
| struct ApproxMatcher : MatcherBase<std::vector<T>> { | |||||
| ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {} | |||||
| bool match(std::vector<T> const &v) const override { | |||||
| if (m_comparator.size() != v.size()) | |||||
| return false; | |||||
| for (std::size_t i = 0; i < v.size(); ++i) | |||||
| if (m_comparator[i] != approx(v[i])) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| std::string describe() const override { | |||||
| return "is approx: " + ::Catch::Detail::stringify( m_comparator ); | |||||
| } | |||||
| template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | |||||
| ApproxMatcher& epsilon( T const& newEpsilon ) { | |||||
| approx.epsilon(newEpsilon); | |||||
| return *this; | |||||
| } | |||||
| template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | |||||
| ApproxMatcher& margin( T const& newMargin ) { | |||||
| approx.margin(newMargin); | |||||
| return *this; | |||||
| } | |||||
| template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | |||||
| ApproxMatcher& scale( T const& newScale ) { | |||||
| approx.scale(newScale); | |||||
| return *this; | |||||
| } | |||||
| std::vector<T> const& m_comparator; | |||||
| mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); | |||||
| }; | |||||
| template<typename T> | template<typename T> | ||||
| struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { | struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { | ||||
| UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} | UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} | ||||
| if (m_target.size() != vec.size()) { | if (m_target.size() != vec.size()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| auto lfirst = m_target.begin(), llast = m_target.end(); | |||||
| auto rfirst = vec.begin(), rlast = vec.end(); | |||||
| // Cut common prefix to optimize checking of permuted parts | |||||
| while (lfirst != llast && *lfirst == *rfirst) { | |||||
| ++lfirst; ++rfirst; | |||||
| } | |||||
| if (lfirst == llast) { | |||||
| return true; | |||||
| } | |||||
| for (auto mid = lfirst; mid != llast; ++mid) { | |||||
| // Skip already counted items | |||||
| if (Detail::contains(lfirst, mid, *mid)) { | |||||
| continue; | |||||
| } | |||||
| size_t num_vec = Detail::count(rfirst, rlast, *mid); | |||||
| if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); | |||||
| } | } | ||||
| std::string describe() const override { | std::string describe() const override { | ||||
| return Vector::EqualsMatcher<T>( comparator ); | return Vector::EqualsMatcher<T>( comparator ); | ||||
| } | } | ||||
| template<typename T> | |||||
| Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) { | |||||
| return Vector::ApproxMatcher<T>( comparator ); | |||||
| } | |||||
| template<typename T> | template<typename T> | ||||
| Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { | Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { | ||||
| return Vector::UnorderedEqualsMatcher<T>(target); | return Vector::UnorderedEqualsMatcher<T>(target); | ||||
| public: | public: | ||||
| NamePattern( std::string const& name ); | NamePattern( std::string const& name ); | ||||
| virtual ~NamePattern(); | virtual ~NamePattern(); | ||||
| virtual bool matches( TestCaseInfo const& testCase ) const override; | |||||
| bool matches( TestCaseInfo const& testCase ) const override; | |||||
| private: | private: | ||||
| WildcardPattern m_wildcardPattern; | WildcardPattern m_wildcardPattern; | ||||
| }; | }; | ||||
| public: | public: | ||||
| TagPattern( std::string const& tag ); | TagPattern( std::string const& tag ); | ||||
| virtual ~TagPattern(); | virtual ~TagPattern(); | ||||
| virtual bool matches( TestCaseInfo const& testCase ) const override; | |||||
| bool matches( TestCaseInfo const& testCase ) const override; | |||||
| private: | private: | ||||
| std::string m_tag; | std::string m_tag; | ||||
| }; | }; | ||||
| public: | public: | ||||
| ExcludedPattern( PatternPtr const& underlyingPattern ); | ExcludedPattern( PatternPtr const& underlyingPattern ); | ||||
| virtual ~ExcludedPattern(); | virtual ~ExcludedPattern(); | ||||
| virtual bool matches( TestCaseInfo const& testCase ) const override; | |||||
| bool matches( TestCaseInfo const& testCase ) const override; | |||||
| private: | private: | ||||
| PatternPtr m_underlyingPattern; | PatternPtr m_underlyingPattern; | ||||
| }; | }; | ||||
| std::vector<std::string> const& getTestsOrTags() const override; | std::vector<std::string> const& getTestsOrTags() const override; | ||||
| std::vector<std::string> const& getSectionsToRun() const override; | std::vector<std::string> const& getSectionsToRun() const override; | ||||
| virtual TestSpec const& testSpec() const override; | |||||
| TestSpec const& testSpec() const override; | |||||
| bool hasTestFilters() const override; | bool hasTestFilters() const override; | ||||
| bool showHelp() const; | bool showHelp() const; | ||||
| class ReporterFactory : public IReporterFactory { | class ReporterFactory : public IReporterFactory { | ||||
| virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { | |||||
| IStreamingReporterPtr create( ReporterConfig const& config ) const override { | |||||
| return std::unique_ptr<T>( new T( config ) ); | return std::unique_ptr<T>( new T( config ) ); | ||||
| } | } | ||||
| virtual std::string getDescription() const override { | |||||
| std::string getDescription() const override { | |||||
| return T::getDescription(); | return T::getDescription(); | ||||
| } | } | ||||
| }; | }; | ||||
| class ListenerFactory : public IReporterFactory { | class ListenerFactory : public IReporterFactory { | ||||
| virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { | |||||
| IStreamingReporterPtr create( ReporterConfig const& config ) const override { | |||||
| return std::unique_ptr<T>( new T( config ) ); | return std::unique_ptr<T>( new T( config ) ); | ||||
| } | } | ||||
| virtual std::string getDescription() const override { | |||||
| std::string getDescription() const override { | |||||
| return std::string(); | return std::string(); | ||||
| } | } | ||||
| }; | }; | ||||
| public: | public: | ||||
| static TrackerContext& instance(); | |||||
| ITracker& startRun(); | ITracker& startRun(); | ||||
| void endRun(); | void endRun(); | ||||
| return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); | return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); | ||||
| } | } | ||||
| void Approx::setMargin(double margin) { | |||||
| CATCH_ENFORCE(margin >= 0, | |||||
| "Invalid Approx::margin: " << margin << '.' | |||||
| void Approx::setMargin(double newMargin) { | |||||
| CATCH_ENFORCE(newMargin >= 0, | |||||
| "Invalid Approx::margin: " << newMargin << '.' | |||||
| << " Approx::Margin has to be non-negative."); | << " Approx::Margin has to be non-negative."); | ||||
| m_margin = margin; | |||||
| m_margin = newMargin; | |||||
| } | } | ||||
| void Approx::setEpsilon(double epsilon) { | |||||
| CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0, | |||||
| "Invalid Approx::epsilon: " << epsilon << '.' | |||||
| void Approx::setEpsilon(double newEpsilon) { | |||||
| CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, | |||||
| "Invalid Approx::epsilon: " << newEpsilon << '.' | |||||
| << " Approx::epsilon has to be in [0, 1]"); | << " Approx::epsilon has to be in [0, 1]"); | ||||
| m_epsilon = epsilon; | |||||
| m_epsilon = newEpsilon; | |||||
| } | } | ||||
| } // end namespace Detail | } // end namespace Detail | ||||
| m_suffix = false; | m_suffix = false; | ||||
| auto width = m_column.m_width - indent(); | auto width = m_column.m_width - indent(); | ||||
| m_end = m_pos; | m_end = m_pos; | ||||
| if (line()[m_pos] == '\n') { | |||||
| ++m_end; | |||||
| } | |||||
| while (m_end < line().size() && line()[m_end] != '\n') | while (m_end < line().size() && line()[m_end] != '\n') | ||||
| ++m_end; | ++m_end; | ||||
| m_stream( openStream() ) | m_stream( openStream() ) | ||||
| { | { | ||||
| TestSpecParser parser(ITagAliasRegistry::get()); | TestSpecParser parser(ITagAliasRegistry::get()); | ||||
| if (data.testsOrTags.empty()) { | |||||
| parser.parse("~[.]"); // All not hidden tests | |||||
| } | |||||
| else { | |||||
| if (!data.testsOrTags.empty()) { | |||||
| m_hasTestFilters = true; | m_hasTestFilters = true; | ||||
| for( auto const& testOrTags : data.testsOrTags ) | for( auto const& testOrTags : data.testsOrTags ) | ||||
| parser.parse( testOrTags ); | parser.parse( testOrTags ); | ||||
| originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); | originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); | ||||
| } | } | ||||
| virtual void use( Colour::Code _colourCode ) override { | |||||
| void use( Colour::Code _colourCode ) override { | |||||
| switch( _colourCode ) { | switch( _colourCode ) { | ||||
| case Colour::None: return setTextAttribute( originalForegroundAttributes ); | case Colour::None: return setTextAttribute( originalForegroundAttributes ); | ||||
| case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); | case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); | ||||
| // https://github.com/philsquared/Catch/pull/131 | // https://github.com/philsquared/Catch/pull/131 | ||||
| class PosixColourImpl : public IColourImpl { | class PosixColourImpl : public IColourImpl { | ||||
| public: | public: | ||||
| virtual void use( Colour::Code _colourCode ) override { | |||||
| void use( Colour::Code _colourCode ) override { | |||||
| switch( _colourCode ) { | switch( _colourCode ) { | ||||
| case Colour::None: | case Colour::None: | ||||
| case Colour::White: return setColour( "[0m" ); | case Colour::White: return setColour( "[0m" ); | ||||
| class Context : public IMutableContext, NonCopyable { | class Context : public IMutableContext, NonCopyable { | ||||
| public: // IContext | public: // IContext | ||||
| virtual IResultCapture* getResultCapture() override { | |||||
| IResultCapture* getResultCapture() override { | |||||
| return m_resultCapture; | return m_resultCapture; | ||||
| } | } | ||||
| virtual IRunner* getRunner() override { | |||||
| IRunner* getRunner() override { | |||||
| return m_runner; | return m_runner; | ||||
| } | } | ||||
| virtual IConfigPtr const& getConfig() const override { | |||||
| IConfigPtr const& getConfig() const override { | |||||
| return m_config; | return m_config; | ||||
| } | } | ||||
| virtual ~Context() override; | |||||
| ~Context() override; | |||||
| public: // IMutableContext | public: // IMutableContext | ||||
| virtual void setResultCapture( IResultCapture* resultCapture ) override { | |||||
| void setResultCapture( IResultCapture* resultCapture ) override { | |||||
| m_resultCapture = resultCapture; | m_resultCapture = resultCapture; | ||||
| } | } | ||||
| virtual void setRunner( IRunner* runner ) override { | |||||
| void setRunner( IRunner* runner ) override { | |||||
| m_runner = runner; | m_runner = runner; | ||||
| } | } | ||||
| virtual void setConfig( IConfigPtr const& config ) override { | |||||
| void setConfig( IConfigPtr const& config ) override { | |||||
| m_config = config; | m_config = config; | ||||
| } | } | ||||
| # include <stdbool.h> | # include <stdbool.h> | ||||
| # include <sys/types.h> | # include <sys/types.h> | ||||
| # include <unistd.h> | # include <unistd.h> | ||||
| # include <sys/sysctl.h> | |||||
| # include <cstddef> | # include <cstddef> | ||||
| # include <ostream> | # include <ostream> | ||||
| namespace Catch { | |||||
| #ifdef __apple_build_version__ | |||||
| // These headers will only compile with AppleClang (XCode) | |||||
| // For other compilers (Clang, GCC, ... ) we need to exclude them | |||||
| # include <sys/sysctl.h> | |||||
| #endif | |||||
| namespace Catch { | |||||
| #ifdef __apple_build_version__ | |||||
| // The following function is taken directly from the following technical note: | // The following function is taken directly from the following technical note: | ||||
| // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html | |||||
| // https://developer.apple.com/library/archive/qa/qa1361/_index.html | |||||
| // Returns true if the current process is being debugged (either | // Returns true if the current process is being debugged (either | ||||
| // running under the debugger or has a debugger attached post facto). | // running under the debugger or has a debugger attached post facto). | ||||
| bool isDebuggerActive(){ | bool isDebuggerActive(){ | ||||
| int mib[4]; | int mib[4]; | ||||
| struct kinfo_proc info; | struct kinfo_proc info; | ||||
| std::size_t size; | std::size_t size; | ||||
| return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); | return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); | ||||
| } | } | ||||
| #else | |||||
| bool isDebuggerActive() { | |||||
| // We need to find another way to determine this for non-appleclang compilers on macOS | |||||
| return false; | |||||
| } | |||||
| #endif | |||||
| } // namespace Catch | } // namespace Catch | ||||
| #elif defined(CATCH_PLATFORM_LINUX) | #elif defined(CATCH_PLATFORM_LINUX) | ||||
| public: | public: | ||||
| ~ExceptionTranslatorRegistry(); | ~ExceptionTranslatorRegistry(); | ||||
| virtual void registerTranslator( const IExceptionTranslator* translator ); | virtual void registerTranslator( const IExceptionTranslator* translator ); | ||||
| virtual std::string translateActiveException() const override; | |||||
| std::string translateActiveException() const override; | |||||
| std::string tryTranslators() const; | std::string tryTranslators() const; | ||||
| private: | private: | ||||
| if (strerror_s(buffer, errno)) { | if (strerror_s(buffer, errno)) { | ||||
| CATCH_RUNTIME_ERROR("Could not translate errno to a string"); | CATCH_RUNTIME_ERROR("Could not translate errno to a string"); | ||||
| } | } | ||||
| CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer); | |||||
| CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); | |||||
| } | } | ||||
| } | } | ||||
| #else | #else | ||||
| auto const& allTestCases = getAllTestCasesSorted(*config); | auto const& allTestCases = getAllTestCasesSorted(*config); | ||||
| for (auto const& testCase : allTestCases) { | for (auto const& testCase : allTestCases) { | ||||
| if (!context.aborting() && matchTest(testCase, testSpec, *config)) | |||||
| bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) || | |||||
| (testSpec.hasFilters() && matchTest(testCase, testSpec, *config)); | |||||
| if (!context.aborting() && matching) | |||||
| totals += context.runTest(testCase); | totals += context.runTest(testCase); | ||||
| else | else | ||||
| context.reporter().skipTest(testCase); | context.reporter().skipTest(testCase); | ||||
| void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { | void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { | ||||
| CATCH_ENFORCE( !isReservedTag(tag), | CATCH_ENFORCE( !isReservedTag(tag), | ||||
| "Tag name: [" << tag << "] is not allowed.\n" | "Tag name: [" << tag << "] is not allowed.\n" | ||||
| << "Tag names starting with non alpha-numeric characters are reserved\n" | |||||
| << "Tag names starting with non alphanumeric characters are reserved\n" | |||||
| << _lineInfo ); | << _lineInfo ); | ||||
| } | } | ||||
| } | } | ||||
| std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { | std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { | ||||
| std::vector<TestCase> filtered; | std::vector<TestCase> filtered; | ||||
| filtered.reserve( testCases.size() ); | filtered.reserve( testCases.size() ); | ||||
| for( auto const& testCase : testCases ) | |||||
| if( matchTest( testCase, testSpec, config ) ) | |||||
| filtered.push_back( testCase ); | |||||
| for (auto const& testCase : testCases) { | |||||
| if ((!testSpec.hasFilters() && !testCase.isHidden()) || | |||||
| (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { | |||||
| filtered.push_back(testCase); | |||||
| } | |||||
| } | |||||
| return filtered; | return filtered; | ||||
| } | } | ||||
| std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { | std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { | ||||
| ITracker::~ITracker() = default; | ITracker::~ITracker() = default; | ||||
| TrackerContext& TrackerContext::instance() { | |||||
| static TrackerContext s_instance; | |||||
| return s_instance; | |||||
| } | |||||
| ITracker& TrackerContext::startRun() { | ITracker& TrackerContext::startRun() { | ||||
| m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); | m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); | ||||
| m_currentTracker = nullptr; | m_currentTracker = nullptr; | ||||
| } | } | ||||
| Version const& libraryVersion() { | Version const& libraryVersion() { | ||||
| static Version version( 2, 7, 1, "", 0 ); | |||||
| static Version version( 2, 7, 2, "", 0 ); | |||||
| return version; | return version; | ||||
| } | } | ||||
| void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { | void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { | ||||
| CumulativeReporterBase::testRunStarting( runInfo ); | CumulativeReporterBase::testRunStarting( runInfo ); | ||||
| xml.startElement( "testsuites" ); | xml.startElement( "testsuites" ); | ||||
| if ( m_config->hasTestFilters() || m_config->rngSeed() != 0 ) | |||||
| xml.startElement("properties"); | |||||
| if ( m_config->hasTestFilters() ) { | |||||
| xml.scopedElement( "property" ) | |||||
| .writeAttribute( "name" , "filters" ) | |||||
| .writeAttribute( "value" , serializeFilters( m_config->getTestsOrTags() ) ); | |||||
| } | |||||
| if( m_config->rngSeed() != 0 ) { | |||||
| xml.scopedElement( "property" ) | |||||
| .writeAttribute( "name", "random-seed" ) | |||||
| .writeAttribute( "value", m_config->rngSeed() ); | |||||
| xml.endElement(); | |||||
| } | |||||
| } | } | ||||
| void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { | void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { | ||||
| void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { | void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { | ||||
| XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); | XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); | ||||
| TestGroupStats const& stats = groupNode.value; | TestGroupStats const& stats = groupNode.value; | ||||
| xml.writeAttribute( "name", stats.groupInfo.name ); | xml.writeAttribute( "name", stats.groupInfo.name ); | ||||
| xml.writeAttribute( "errors", unexpectedExceptions ); | xml.writeAttribute( "errors", unexpectedExceptions ); | ||||
| xml.writeAttribute( "time", suiteTime ); | xml.writeAttribute( "time", suiteTime ); | ||||
| xml.writeAttribute( "timestamp", getCurrentTimestamp() ); | xml.writeAttribute( "timestamp", getCurrentTimestamp() ); | ||||
| // Write properties if there are any | |||||
| if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { | |||||
| auto properties = xml.scopedElement("properties"); | |||||
| if (m_config->hasTestFilters()) { | |||||
| xml.scopedElement("property") | |||||
| .writeAttribute("name", "filters") | |||||
| .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); | |||||
| } | |||||
| if (m_config->rngSeed() != 0) { | |||||
| xml.scopedElement("property") | |||||
| .writeAttribute("name", "random-seed") | |||||
| .writeAttribute("value", m_config->rngSeed()); | |||||
| } | |||||
| } | |||||
| // Write test cases | // Write test cases | ||||
| for( auto const& child : groupNode.children ) | for( auto const& child : groupNode.children ) | ||||
| writeTestCase( *child ); | writeTestCase( *child ); |