1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_HISTORY_HELPER_H_
#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_HISTORY_HELPER_H_
#include <map>
#include <vector>
#include "chrome/browser/sync/test/integration/fake_server_match_status_checker.h"
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "components/history/core/browser/history_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace history {
void PrintTo(const VisitRow& row, std::ostream* os);
} // namespace history
namespace sync_pb {
void PrintTo(const HistorySpecifics& history, std::ostream* os);
} // namespace sync_pb
namespace history_helper {
// Matchers for sync_pb::HistorySpecifics.
MATCHER_P(UrlIs, url, "") {
if (arg.redirect_entries_size() != 1) {
return false;
}
return arg.redirect_entries(0).url() == url;
}
MATCHER_P2(UrlsAre, url1, url2, "") {
if (arg.redirect_entries_size() != 2) {
return false;
}
return arg.redirect_entries(0).url() == url1 &&
arg.redirect_entries(1).url() == url2;
}
MATCHER_P(CoreTransitionIs, transition, "") {
return arg.page_transition().core_transition() == transition;
}
MATCHER(IsChainStart, "") {
return !arg.redirect_chain_start_incomplete();
}
MATCHER(IsChainEnd, "") {
return !arg.redirect_chain_end_incomplete();
}
MATCHER(HasReferringVisit, "") {
return arg.originator_referring_visit_id() != 0;
}
MATCHER(HasOpenerVisit, "") {
return arg.originator_opener_visit_id() != 0;
}
MATCHER(HasReferrerURL, "") {
return !arg.referrer_url().empty();
}
MATCHER_P(ReferrerURLIs, referrer_url, "") {
return arg.referrer_url() == referrer_url;
}
MATCHER(HasVisitDuration, "") {
return arg.visit_duration_micros() > 0;
}
MATCHER(HasHttpResponseCode, "") {
return arg.http_response_code() > 0;
}
MATCHER(StandardFieldsArePopulated, "") {
// Checks all fields that should never be empty/unset/default. Some fields can
// be legitimately empty, or are set after an entity is first created.
// May be legitimately empty:
// redirect_entries.title (may simply be empty)
// redirect_entries.redirect_type (empty if it's not a redirect)
// originator_referring_visit_id, originator_opener_visit_id (may not exist)
// root_task_id, parent_task_id (not always set)
// http_response_code (unset for replaced navigations)
// Populated later:
// visit_duration_micros, page_language, password_state
return arg.visit_time_windows_epoch_micros() > 0 &&
!arg.originator_cache_guid().empty() &&
arg.redirect_entries_size() > 0 &&
arg.redirect_entries(0).originator_visit_id() > 0 &&
!arg.redirect_entries(0).url().empty() && arg.has_browser_type() &&
arg.window_id() > 0 && arg.tab_id() > 0 && arg.task_id() > 0;
}
// Matchers for history::VisitRow.
MATCHER_P(VisitRowIdIs, visit_id, "") {
return arg.visit_id == visit_id;
}
MATCHER(VisitRowHasDuration, "") {
return !arg.visit_duration.is_zero();
}
MATCHER_P(VisitRowDurationIs, duration, "") {
return arg.visit_duration == duration;
}
// Gets the URLRow for a specific URL from a specific sync profile. Returns
// false if the URL was not found in the history DB.
bool GetUrlFromClient(int index, const GURL& url, history::URLRow* row);
// Similar, but queries by URL ID rather than URL.
bool GetUrlFromClient(int index, history::URLID url_id, history::URLRow* row);
// Gets the visits for a URL from a specific sync profile.
history::VisitVector GetVisitsFromClient(int index, history::URLID id);
// Gets the visits for a URL from a specific sync profile. Like above, but
// takes a GURL instead of URLID. Returns empty vector if |url| is not returned
// by GetUrlFromClient().
history::VisitVector GetVisitsForURLFromClient(int index, const GURL& url);
// As above, but return `AnnotatedVisit` instead of just `VisitRow`.
std::vector<history::AnnotatedVisit> GetAnnotatedVisitsFromClient(
int index,
history::URLID id);
std::vector<history::AnnotatedVisit> GetAnnotatedVisitsForURLFromClient(
int index,
const GURL& url);
history::VisitVector GetRedirectChainFromClient(int index,
history::VisitRow final_visit);
// Adds a URL to the history DB for a specific sync profile (just registers a
// new visit if the URL already exists) using a TYPED PageTransition.
void AddUrlToHistory(int index, const GURL& url);
// Adds a URL to the history DB for a specific sync profile (just registers a
// new visit if the URL already exists), using the passed PageTransition.
void AddUrlToHistoryWithTransition(int index,
const GURL& url,
ui::PageTransition transition,
history::VisitSource source);
// Adds a URL to the history DB for a specific sync profile (just registers a
// new visit if the URL already exists), using the passed PageTransition and
// timestamp.
void AddUrlToHistoryWithTimestamp(int index,
const GURL& url,
ui::PageTransition transition,
history::VisitSource source,
const base::Time& timestamp);
// A helper class that waits for entries in the local history DB that match the
// given matchers.
// Note that this only checks URLs that were passed in - any additional URLs in
// the DB (and their corresponding visits) are ignored.
class LocalHistoryMatchChecker : public SingleClientStatusChangeChecker {
public:
using Matcher = testing::Matcher<std::vector<history::VisitRow>>;
explicit LocalHistoryMatchChecker(int profile_index,
syncer::SyncServiceImpl* service,
const std::map<GURL, Matcher>& matchers);
~LocalHistoryMatchChecker() override;
// StatusChangeChecker implementation.
bool IsExitConditionSatisfied(std::ostream* os) override;
// syncer::SyncServiceObserver implementation.
void OnSyncCycleCompleted(syncer::SyncService* sync) override;
private:
const int profile_index_;
const std::map<GURL, Matcher> matchers_;
};
// A helper class that waits for the HISTORY entities on the FakeServer to match
// a given GMock matcher.
class ServerHistoryMatchChecker
: public fake_server::FakeServerMatchStatusChecker {
public:
using Matcher = testing::Matcher<std::vector<sync_pb::HistorySpecifics>>;
explicit ServerHistoryMatchChecker(const Matcher& matcher);
~ServerHistoryMatchChecker() override;
ServerHistoryMatchChecker(const ServerHistoryMatchChecker&) = delete;
ServerHistoryMatchChecker& operator=(const ServerHistoryMatchChecker&) =
delete;
// FakeServer::Observer overrides.
void OnCommit(syncer::DataTypeSet committed_data_types) override;
// StatusChangeChecker overrides.
bool IsExitConditionSatisfied(std::ostream* os) override;
private:
const Matcher matcher_;
};
} // namespace history_helper
#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_HISTORY_HELPER_H_
|