// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/sync_sessions/test_matchers.h" #include "components/sessions/core/session_id.h" #include "components/sync/model/entity_data.h" #include "components/sync/protocol/session_specifics.pb.h" #include "components/sync_sessions/synced_session.h" namespace sync_sessions { namespace { using testing::ContainerEq; using testing::ElementsAreArray; using testing::Matcher; using testing::MatcherInterface; using testing::MatchResultListener; using testing::PrintToString; class MatchesHeaderMatcher : public MatcherInterface { public: MatchesHeaderMatcher(Matcher session_tag, Matcher> window_ids, Matcher> tab_ids) : session_tag_(session_tag), window_ids_(window_ids), tab_ids_(tab_ids) {} bool MatchAndExplain(const sync_pb::SessionSpecifics& actual, MatchResultListener* listener) const override { if (!actual.has_header()) { *listener << " which is not a header entity"; return false; } if (actual.tab_node_id() != -1) { *listener << " which has a valid tab node ID: " << actual.tab_node_id(); return false; } if (!session_tag_.MatchAndExplain(actual.session_tag(), listener)) { *listener << " which contains an unexpected session tag: " << actual.session_tag(); return false; } std::vector actual_window_ids; std::vector actual_tab_ids; for (const auto& window : actual.header().window()) { actual_window_ids.push_back(window.window_id()); actual_tab_ids.insert(actual_tab_ids.end(), window.tab().begin(), window.tab().end()); } if (!window_ids_.MatchAndExplain(actual_window_ids, listener)) { *listener << " which contains unexpected windows: " << PrintToString(actual_window_ids); return false; } if (!tab_ids_.MatchAndExplain(actual_tab_ids, listener)) { *listener << " which contains unexpected tabs: " << PrintToString(actual_tab_ids); return false; } return true; } void DescribeTo(::std::ostream* os) const override { *os << "matches expected header"; } void DescribeNegationTo(::std::ostream* os) const override { *os << "does not match expected header"; } private: Matcher session_tag_; Matcher> window_ids_; Matcher> tab_ids_; }; class MatchesTabMatcher : public MatcherInterface { public: MatchesTabMatcher(Matcher session_tag, Matcher window_id, Matcher tab_id, Matcher tab_node_id, Matcher> urls) : session_tag_(session_tag), window_id_(window_id), tab_id_(tab_id), tab_node_id_(tab_node_id), urls_(urls) {} bool MatchAndExplain(const sync_pb::SessionSpecifics& actual, MatchResultListener* listener) const override { if (!actual.has_tab()) { *listener << " which is not a tab entity"; return false; } if (!session_tag_.MatchAndExplain(actual.session_tag(), listener)) { *listener << " which contains an unexpected session tag: " << actual.session_tag(); return false; } if (!window_id_.MatchAndExplain(actual.tab().window_id(), listener)) { *listener << " which contains an unexpected window ID: " << actual.tab().window_id(); return false; } if (!tab_id_.MatchAndExplain(actual.tab().tab_id(), listener)) { *listener << " which contains an unexpected tab ID: " << actual.tab().tab_id(); return false; } if (!tab_node_id_.MatchAndExplain(actual.tab_node_id(), listener)) { *listener << " which contains an unexpected tab node ID: " << actual.tab_node_id(); return false; } std::vector actual_urls; for (const sync_pb::TabNavigation& navigation : actual.tab().navigation()) { actual_urls.push_back(navigation.virtual_url()); } if (!urls_.MatchAndExplain(actual_urls, listener)) { *listener << " which contains unexpected navigation URLs"; return false; } return true; } void DescribeTo(::std::ostream* os) const override { *os << "matches expected tab"; } void DescribeNegationTo(::std::ostream* os) const override { *os << "does not match expected tab"; } private: Matcher session_tag_; Matcher window_id_; Matcher tab_id_; Matcher tab_node_id_; Matcher> urls_; }; class MatchesSyncedSessionMatcher : public MatcherInterface { public: MatchesSyncedSessionMatcher( Matcher session_tag, Matcher>> window_id_to_tabs) : session_tag_(session_tag), window_id_to_tabs_(window_id_to_tabs) {} bool MatchAndExplain(const SyncedSession* actual, MatchResultListener* listener) const override { if (!actual) { *listener << " which is null"; return false; } if (!session_tag_.MatchAndExplain(actual->session_tag, listener)) { *listener << " which contains an unexpected session tag: " << actual->session_tag; return false; } std::map> actual_window_id_to_tabs; for (const auto& id_and_window : actual->windows) { const SessionID actual_window_id = id_and_window.first; if (actual_window_id != id_and_window.second->wrapped_window.window_id) { *listener << " which has an inconsistent window representation"; return false; } actual_window_id_to_tabs.emplace(actual_window_id.id(), std::vector()); for (const auto& tab : id_and_window.second->wrapped_window.tabs) { actual_window_id_to_tabs[actual_window_id.id()].push_back( tab->tab_id.id()); } } if (!window_id_to_tabs_.MatchAndExplain(actual_window_id_to_tabs, listener)) { return false; } return true; } void DescribeTo(::std::ostream* os) const override { *os << "matches expected synced session"; } void DescribeNegationTo(::std::ostream* os) const override { *os << "does not match expected synced session"; } private: Matcher session_tag_; Matcher>> window_id_to_tabs_; }; } // namespace Matcher MatchesHeader( Matcher session_tag, Matcher> window_ids, Matcher> tab_ids) { return testing::MakeMatcher( new MatchesHeaderMatcher(session_tag, window_ids, tab_ids)); } Matcher MatchesHeader( Matcher session_tag, const std::vector& window_ids, const std::vector& tab_ids) { return MatchesHeader(session_tag, ElementsAreArray(window_ids), ElementsAreArray(tab_ids)); } Matcher MatchesTab( Matcher session_tag, Matcher window_id, Matcher tab_id, Matcher tab_node_id, Matcher> urls) { return testing::MakeMatcher( new MatchesTabMatcher(session_tag, window_id, tab_id, tab_node_id, urls)); } Matcher MatchesTab( Matcher session_tag, Matcher window_id, Matcher tab_id, Matcher tab_node_id, const std::vector& urls) { return MatchesTab(session_tag, window_id, tab_id, tab_node_id, ElementsAreArray(urls)); } Matcher MatchesSyncedSession( Matcher session_tag, Matcher>> window_id_to_tabs) { return testing::MakeMatcher( new MatchesSyncedSessionMatcher(session_tag, window_id_to_tabs)); } Matcher MatchesSyncedSession( Matcher session_tag, const std::map>& window_id_to_tabs) { return MatchesSyncedSession(session_tag, ContainerEq(window_id_to_tabs)); } } // namespace sync_sessions