/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Pete Woods */ #include #include #include #include #include using namespace std; namespace lomiri { namespace gmenuharness { namespace { static void printLocation(ostream& ss, const vector& location, bool first) { for (int i : location) { ss << " "; if (first) { ss << i; } else { ss << " "; } } ss << " "; } struct compare_vector { bool operator()(const vector& a, const vector& b) const { auto p1 = a.begin(); auto p2 = b.begin(); while (p1 != a.end()) { if (p2 == b.end()) { return false; } if (*p2 > *p1) { return true; } if (*p1 > *p2) { return false; } ++p1; ++p2; } if (p2 != b.end()) { return true; } return false; } }; } struct MatchResult::Priv { bool m_success = true; map, vector, compare_vector> m_failures; chrono::time_point m_timeout = chrono::system_clock::now() + chrono::seconds(10); }; MatchResult::MatchResult() : p(new Priv) { } MatchResult::MatchResult(MatchResult&& other) { *this = move(other); } MatchResult::MatchResult(const MatchResult& other) : p(new Priv) { *this = other; } MatchResult& MatchResult::operator=(const MatchResult& other) { p->m_success = other.p->m_success; p->m_failures= other.p->m_failures; return *this; } MatchResult& MatchResult::operator=(MatchResult&& other) { p = move(other.p); return *this; } MatchResult MatchResult::createChild() const { MatchResult child; child.p->m_timeout = p->m_timeout; return child; } void MatchResult::failure(const vector& location, const string& message) { p->m_success = false; auto it = p->m_failures.find(location); if (it == p->m_failures.end()) { it = p->m_failures.insert(make_pair(location, vector())).first; } it->second.emplace_back(message); } void MatchResult::merge(const MatchResult& other) { p->m_success &= other.p->m_success; for (const auto& e : other.p->m_failures) { p->m_failures.insert(make_pair(e.first, e.second)); } } bool MatchResult::success() const { return p->m_success; } bool MatchResult::hasTimedOut() const { auto now = chrono::system_clock::now(); return (now >= p->m_timeout); } string MatchResult::concat_failures() const { stringstream ss; ss << "Failed expectations:" << endl; for (const auto& failure : p->m_failures) { bool first = true; for (const string& s: failure.second) { printLocation(ss, failure.first, first); first = false; ss << s << endl; } } return ss.str(); } } // namespace gmenuharness } // namespace lomiri