blob: efe5c24d1547f8b7b3ee6d19e2a78131c32d8a7a [file] [log] [blame]
// 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_