Commit 5ff94a42 authored by Sebastien's avatar Sebastien Committed by Commit Bot

GamesService: Added logic to identify the actual Highlighted Game.

The HighlightedGamesStore is now using the HighlightedGamesResponse data file
to identify the currently highlighted Web game.

Bug: 1018201
Change-Id: I65270363b6eb3cec9bced7b3bc84af0caaafee72
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1954151
Commit-Queue: Sebastien Lalancette <seblalancette@chromium.org>
Reviewed-by: default avatarTommy Martino <tmartino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#724774}
parent ace03755
......@@ -8,6 +8,7 @@
#include <utility>
#include "base/memory/singleton.h"
#include "base/time/default_clock.h"
#include "chrome/browser/profiles/profile.h"
#include "components/games/core/catalog_store.h"
#include "components/games/core/games_service_impl.h"
......@@ -40,7 +41,8 @@ KeyedService* GamesServiceFactory::BuildServiceInstanceFor(
Profile* profile = Profile::FromBrowserContext(context);
return new GamesServiceImpl(std::make_unique<CatalogStore>(),
std::make_unique<HighlightedGamesStore>(),
std::make_unique<HighlightedGamesStore>(
base::DefaultClock::GetInstance()),
profile->GetPrefs());
}
......
......@@ -39,6 +39,7 @@ source_set("unit_tests") {
"data_files_parser_unittest.cc",
"games_prefs_unittest.cc",
"games_service_impl_unittest.cc",
"games_utils_unittest.cc",
"highlighted_games_store_unittest.cc",
]
deps = [
......
......@@ -61,8 +61,7 @@ TEST_F(CatalogStoreTest, UpdateCatalogAsync_Success_WithCache_AndClearCache) {
run_loop.Run();
ASSERT_TRUE(catalog_store_->cached_catalog());
EXPECT_TRUE(
test::AreProtosEqual(fake_catalog, *catalog_store_->cached_catalog()));
test::ExpectProtosEqual(fake_catalog, *catalog_store_->cached_catalog());
catalog_store_->ClearCache();
......
......@@ -48,7 +48,7 @@ TEST_F(DataFilesParserTest, TryParseCatalog_Success) {
base::Optional<GamesCatalog> test_catalog =
parser_.TryParseCatalog(temp_dir_.GetPath());
ASSERT_TRUE(test_catalog.has_value());
EXPECT_TRUE(test::AreProtosEqual(expected_catalog, test_catalog.value()));
test::ExpectProtosEqual(expected_catalog, test_catalog.value());
}
TEST_F(DataFilesParserTest, TryParseHighlightedGames_FileDoesNotExist) {
......@@ -71,7 +71,7 @@ TEST_F(DataFilesParserTest, TryParseHighlightedGames_Success) {
base::Optional<HighlightedGamesResponse> test_response =
parser_.TryParseHighlightedGames(temp_dir_.GetPath());
ASSERT_TRUE(test_response.has_value());
EXPECT_TRUE(test::AreProtosEqual(expected_response, test_response.value()));
test::ExpectProtosEqual(expected_response, test_response.value());
}
} // namespace games
......@@ -81,7 +81,7 @@ TEST_F(GamesServiceImplTest, GetHighlightedGame_NotInstalled) {
games_service_->GetHighlightedGame(base::BindLambdaForTesting(
[&run_loop](ResponseCode code, const Game game) {
EXPECT_EQ(ResponseCode::kFileNotFound, code);
EXPECT_TRUE(test::AreProtosEqual(game, Game()));
test::ExpectProtosEqual(Game(), game);
run_loop.Quit();
}));
......@@ -99,7 +99,7 @@ TEST_F(GamesServiceImplTest, GetHighlightedGame_RetrievesFromCache) {
games_service_->GetHighlightedGame(base::BindLambdaForTesting(
[&fake_game, &run_loop](ResponseCode code, const Game game) {
EXPECT_EQ(ResponseCode::kSuccess, code);
EXPECT_TRUE(test::AreProtosEqual(game, fake_game));
test::ExpectProtosEqual(fake_game, game);
run_loop.Quit();
}));
......@@ -136,7 +136,7 @@ TEST_F(GamesServiceImplTest, GetHighlightedGame_Success) {
const games::GamesCatalog& catalog,
base::OnceClosure done_callback) {
EXPECT_TRUE(games_service_->is_updating());
ASSERT_TRUE(test::AreProtosEqual(fake_catalog, catalog));
test::ExpectProtosEqual(fake_catalog, catalog);
// Invoke the done callback to signal that the HighlightedStore is done
// processing.
......
......@@ -14,4 +14,15 @@ const base::FilePath GetHighlightedGamesPath(const base::FilePath& dir) {
return dir.Append(kHighlightedGamesFileName);
}
base::Optional<Game> TryFindGameById(int id, const GamesCatalog& catalog) {
base::Optional<Game> optional_game;
for (const Game& game : catalog.games()) {
if (game.id() == id) {
optional_game = game;
break;
}
}
return optional_game;
}
} // namespace games
......@@ -5,15 +5,21 @@
#ifndef COMPONENTS_GAMES_CORE_GAMES_UTILS_H_
#define COMPONENTS_GAMES_CORE_GAMES_UTILS_H_
#include "components/games/core/games_constants.h"
#include "base/files/file_path.h"
#include "base/optional.h"
#include "components/games/core/games_constants.h"
#include "components/games/core/proto/game.pb.h"
#include "components/games/core/proto/games_catalog.pb.h"
namespace games {
const base::FilePath GetGamesCatalogPath(const base::FilePath& dir);
const base::FilePath GetHighlightedGamesPath(const base::FilePath& dir);
// Tries to find a game with the given |id| in the |catalog|. If no game has
// that ID, then we're returning an empty optional instance.
base::Optional<Game> TryFindGameById(int id, const GamesCatalog& catalog);
} // namespace games
#endif // COMPONENTS_GAMES_CORE_GAMES_UTILS_H_
// Copyright 2019 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/games/core/games_utils.h"
#include "components/games/core/proto/games_catalog.pb.h"
#include "components/games/core/proto/highlighted_games.pb.h"
#include "components/games/core/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace games {
class GamesUtilsTest : public testing::Test {};
TEST_F(GamesUtilsTest, TryFindGameById_NotFound) {
GamesCatalog catalog = test::CreateCatalogWithTwoGames();
int notfound_id = -1;
EXPECT_FALSE(TryFindGameById(notfound_id, catalog));
}
TEST_F(GamesUtilsTest, TryFindGameById_Found) {
GamesCatalog catalog = test::CreateCatalogWithTwoGames();
Game expected_game = catalog.games().at(1);
auto found_game = TryFindGameById(expected_game.id(), catalog);
ASSERT_TRUE(found_game.has_value());
test::ExpectProtosEqual(expected_game, found_game.value());
}
} // namespace games
......@@ -8,19 +8,29 @@
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task_runner_util.h"
#include "components/games/core/games_utils.h"
#include "components/games/core/proto/date.pb.h"
namespace games {
HighlightedGamesStore::HighlightedGamesStore()
: HighlightedGamesStore(std::make_unique<DataFilesParser>()) {}
namespace {
bool TryConvertTime(const Date& date_proto, base::Time* out_time) {
return base::Time::FromUTCExploded(
{date_proto.year(), date_proto.month(), 0, date_proto.day()}, out_time);
}
} // namespace
HighlightedGamesStore::HighlightedGamesStore(base::Clock* clock)
: HighlightedGamesStore(std::make_unique<DataFilesParser>(), clock) {}
HighlightedGamesStore::HighlightedGamesStore(
std::unique_ptr<DataFilesParser> data_files_parser)
std::unique_ptr<DataFilesParser> data_files_parser,
base::Clock* clock)
: data_files_parser_(std::move(data_files_parser)),
task_runner_(
base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
base::TaskPriority::USER_VISIBLE})) {
}
base::TaskPriority::USER_VISIBLE})),
clock_(clock) {}
HighlightedGamesStore::~HighlightedGamesStore() = default;
......@@ -37,11 +47,21 @@ void HighlightedGamesStore::ProcessAsync(const base::FilePath& install_dir,
}
base::Optional<Game> HighlightedGamesStore::TryGetFromCache() {
base::Optional<Game> cached_game;
if (cached_highlighted_game_) {
cached_game = *cached_highlighted_game_;
base::Optional<Game> optional_game;
if (!cached_highlighted_game_ || !cached_game_) {
return optional_game;
}
if (IsCurrent(*cached_highlighted_game_)) {
optional_game = *cached_game_;
} else {
// Current game is outdated, clear cache.
cached_highlighted_game_.reset();
cached_game_.reset();
}
return cached_game;
return optional_game;
}
void HighlightedGamesStore::SetPendingCallback(
......@@ -60,8 +80,12 @@ HighlightedGamesStore::GetHighlightedGamesResponse(
// Must run file IO on the thread pool.
DCHECK(task_runner_->RunsTasksInCurrentSequence());
// TODO(crbug.com/1018201): Add data file parsing logic.
return std::make_unique<HighlightedGamesResponse>();
base::Optional<HighlightedGamesResponse> response_proto =
data_files_parser_->TryParseHighlightedGames(install_dir);
if (!response_proto.has_value()) {
return nullptr;
}
return std::make_unique<HighlightedGamesResponse>(response_proto.value());
}
void HighlightedGamesStore::OnHighlightedGamesResponseParsed(
......@@ -74,10 +98,33 @@ void HighlightedGamesStore::OnHighlightedGamesResponseParsed(
return;
}
// TODO(crbug.com/1018201): Add highlighted game parsing logic. For now, we'll
// just return the first game from the catalog.
cached_highlighted_game_ = std::make_unique<const Game>(catalog.games(0));
RespondAndInvoke(ResponseCode::kSuccess, *cached_highlighted_game_,
if (!response) {
RespondAndInvoke(ResponseCode::kFileNotFound, Game(),
std::move(done_callback));
return;
}
// Try to find the game of the day for today.
for (const HighlightedGame& hg : response->games()) {
if (IsCurrent(hg)) {
// Try to update the cache with this game.
base::Optional<Game> game = TryFindGameById(hg.game_id(), catalog);
if (!game) {
RespondAndInvoke(ResponseCode::kInvalidData, Game(),
std::move(done_callback));
return;
}
cached_game_ = std::make_unique<Game>(game.value());
cached_highlighted_game_ = std::make_unique<HighlightedGame>(hg);
RespondAndInvoke(ResponseCode::kSuccess, *cached_game_,
std::move(done_callback));
return;
}
}
// Failed to find the game of the day.
RespondAndInvoke(ResponseCode::kInvalidData, Game(),
std::move(done_callback));
}
......@@ -95,4 +142,25 @@ void HighlightedGamesStore::RespondAndInvoke(ResponseCode code,
std::move(done_callback).Run();
}
bool HighlightedGamesStore::IsCurrent(const HighlightedGame& highlighted_game) {
base::Time start_date;
if (!TryConvertTime(highlighted_game.start_date(), &start_date)) {
// TODO(crbug.com/1018201): Log bad data.
return false;
}
base::Time end_date;
if (!TryConvertTime(highlighted_game.end_date(), &end_date)) {
// TODO(crbug.com/1018201): Log bad data.
return false;
}
if (start_date > end_date) {
// TODO(crbug.com/1018201): Log bad data.
return false;
}
return clock_->Now() >= start_date && clock_->Now() < end_date;
}
} // namespace games
......@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/clock.h"
#include "components/games/core/data_files_parser.h"
#include "components/games/core/games_types.h"
#include "components/games/core/proto/games_catalog.pb.h"
......@@ -24,11 +25,12 @@ namespace games {
// and then calculating and caching the currently highlighted game.
class HighlightedGamesStore {
public:
explicit HighlightedGamesStore();
explicit HighlightedGamesStore(base::Clock* clock);
// For unit tests.
explicit HighlightedGamesStore(
std::unique_ptr<DataFilesParser> data_files_parser);
std::unique_ptr<DataFilesParser> data_files_parser,
base::Clock* clock);
virtual ~HighlightedGamesStore();
......@@ -66,12 +68,16 @@ class HighlightedGamesStore {
void Respond(ResponseCode code, const Game& game);
bool IsCurrent(const HighlightedGame& highlighted_game);
std::unique_ptr<DataFilesParser> data_files_parser_;
// Task runner delegating tasks to the ThreadPool.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<const Game> cached_highlighted_game_;
base::Clock* clock_;
std::unique_ptr<HighlightedGame> cached_highlighted_game_;
std::unique_ptr<Game> cached_game_;
base::Optional<HighlightedGameCallback> pending_callback_;
base::WeakPtrFactory<HighlightedGamesStore> weak_ptr_factory_{this};
......
......@@ -21,41 +21,111 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
namespace games {
namespace {
GamesCatalog CreateCatalogWithTwoGames() {
return test::CreateGamesCatalog(
{test::CreateGame(/*id=*/1), test::CreateGame(/*id=*/2)});
void SetDateProtoTo(Date* date_proto, const base::Time& time) {
base::Time::Exploded exploded;
time.UTCExplode(&exploded);
date_proto->set_year(exploded.year);
date_proto->set_month(exploded.month);
date_proto->set_day(exploded.day_of_month);
}
} // namespace
class HighlightedGamesStoreTest : public testing::Test {
protected:
void SetUp() override {
ResetClock();
auto mock_parser = std::make_unique<test::MockDataFilesParser>();
mock_parser_ = mock_parser.get();
highlighted_games_store_ = std::make_unique<HighlightedGamesStore>(
std::make_unique<test::MockDataFilesParser>());
std::move(mock_parser), &mock_clock_);
AssertCacheEmpty();
}
void ResetClock() {
base::Time fake_time;
ASSERT_TRUE(
base::Time::FromString("Wed, 16 Nov 1994, 00:00:00", &fake_time));
mock_clock_.MockNow(fake_time);
}
void AssertCacheEmpty() {
base::Optional<Game> test_cache =
highlighted_games_store_->TryGetFromCache();
ASSERT_FALSE(test_cache.has_value());
}
void AddValidHighlightedGame(HighlightedGamesResponse* response, int id) {
// Set a highlighted game around the currently mocked time to make sure its
// valid.
HighlightedGame fake_highlighted_game;
fake_highlighted_game.set_game_id(id);
SetDateProtoTo(fake_highlighted_game.mutable_start_date(),
mock_clock_.Now() - base::TimeDelta::FromDays(1));
SetDateProtoTo(fake_highlighted_game.mutable_end_date(),
mock_clock_.Now() + base::TimeDelta::FromDays(1));
response->mutable_games()->Add(std::move(fake_highlighted_game));
}
void ExpectProcessAsyncFailure(ResponseCode expected_code,
const GamesCatalog& catalog) {
base::RunLoop run_loop;
// We'll use the barrier closure to make sure both the pending callback and
// the done callbacks were invoked upon success.
auto barrier_closure = base::BarrierClosure(
2, base::BindLambdaForTesting([&run_loop]() { run_loop.Quit(); }));
highlighted_games_store_->SetPendingCallback(base::BindLambdaForTesting(
[&expected_code, &barrier_closure](ResponseCode code, const Game game) {
test::ExpectProtosEqual(Game(), game);
EXPECT_EQ(expected_code, code);
barrier_closure.Run();
}));
highlighted_games_store_->ProcessAsync(
fake_install_dir_, catalog,
base::BindLambdaForTesting(
[&barrier_closure]() { barrier_closure.Run(); }));
run_loop.Run();
AssertCacheEmpty();
}
// TaskEnvironment is used instead of SingleThreadTaskEnvironment since we
// post a task to the thread pool.
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<HighlightedGamesStore> highlighted_games_store_;
test::MockDataFilesParser* mock_parser_;
test::MockClock mock_clock_;
base::FilePath fake_install_dir_ =
base::FilePath(FILE_PATH_LITERAL("some/path"));
};
TEST_F(HighlightedGamesStoreTest, ProcessAsync_Success_WithCache) {
GamesCatalog fake_catalog = CreateCatalogWithTwoGames();
TEST_F(HighlightedGamesStoreTest,
ProcessAsync_Success_WithCache_AndCacheExpiry) {
GamesCatalog fake_catalog = test::CreateCatalogWithTwoGames();
Game fake_selected_game = fake_catalog.games().at(1);
HighlightedGamesResponse fake_response;
AddValidHighlightedGame(&fake_response, fake_selected_game.id());
EXPECT_CALL(*mock_parser_, TryParseHighlightedGames(fake_install_dir_))
.WillOnce([&fake_response](const base::FilePath& install_dir) {
return base::Optional<HighlightedGamesResponse>(fake_response);
});
base::RunLoop run_loop;
......@@ -64,10 +134,10 @@ TEST_F(HighlightedGamesStoreTest, ProcessAsync_Success_WithCache) {
auto barrier_closure = base::BarrierClosure(
2, base::BindLambdaForTesting([&run_loop]() { run_loop.Quit(); }));
highlighted_games_store_->SetPendingCallback(base::BindLambdaForTesting(
[&barrier_closure, &fake_catalog](ResponseCode code, const Game game) {
// For now, we're only returning the first game from the catalog.
EXPECT_TRUE(test::AreProtosEqual(fake_catalog.games().at(0), game));
highlighted_games_store_->SetPendingCallback(
base::BindLambdaForTesting([&barrier_closure, &fake_selected_game](
ResponseCode code, const Game game) {
test::ExpectProtosEqual(fake_selected_game, game);
EXPECT_EQ(ResponseCode::kSuccess, code);
barrier_closure.Run();
}));
......@@ -80,8 +150,14 @@ TEST_F(HighlightedGamesStoreTest, ProcessAsync_Success_WithCache) {
// Now the game should be cached.
auto test_cache = highlighted_games_store_->TryGetFromCache();
EXPECT_TRUE(test_cache);
EXPECT_TRUE(
test::AreProtosEqual(fake_catalog.games().at(0), test_cache.value()));
test::ExpectProtosEqual(fake_selected_game, test_cache.value());
// Days going by...
mock_clock_.AdvanceDays(4);
// Now the highlighted game should be highlighted no more (we went past its
// end date).
AssertCacheEmpty();
}
TEST_F(HighlightedGamesStoreTest, ProcessAsync_InvalidData) {
......@@ -95,7 +171,7 @@ TEST_F(HighlightedGamesStoreTest, ProcessAsync_InvalidData) {
highlighted_games_store_->SetPendingCallback(base::BindLambdaForTesting(
[&barrier_closure](ResponseCode code, const Game game) {
EXPECT_TRUE(test::AreProtosEqual(Game(), game));
test::ExpectProtosEqual(Game(), game);
EXPECT_EQ(ResponseCode::kInvalidData, code);
barrier_closure.Run();
}));
......@@ -110,7 +186,16 @@ TEST_F(HighlightedGamesStoreTest, ProcessAsync_InvalidData) {
}
TEST_F(HighlightedGamesStoreTest, ProcessAsync_NoCallback_Caches) {
GamesCatalog fake_catalog = CreateCatalogWithTwoGames();
GamesCatalog fake_catalog = test::CreateCatalogWithTwoGames();
Game fake_selected_game = fake_catalog.games().at(1);
HighlightedGamesResponse fake_response;
AddValidHighlightedGame(&fake_response, fake_selected_game.id());
EXPECT_CALL(*mock_parser_, TryParseHighlightedGames(fake_install_dir_))
.WillOnce([&fake_response](const base::FilePath& install_dir) {
return base::Optional<HighlightedGamesResponse>(fake_response);
});
base::RunLoop run_loop;
......@@ -121,10 +206,57 @@ TEST_F(HighlightedGamesStoreTest, ProcessAsync_NoCallback_Caches) {
run_loop.Run();
// Even if we didn't have any pending callback, the game should now be cached.
auto test_cache = highlighted_games_store_->TryGetFromCache();
EXPECT_TRUE(test_cache);
EXPECT_TRUE(
test::AreProtosEqual(fake_catalog.games().at(0), test_cache.value()));
base::Optional<Game> test_cache = highlighted_games_store_->TryGetFromCache();
ASSERT_TRUE(test_cache.has_value());
test::ExpectProtosEqual(fake_selected_game, test_cache.value());
}
TEST_F(HighlightedGamesStoreTest, ProcessAsync_NoHighlightedGamesResponse) {
GamesCatalog fake_catalog = test::CreateCatalogWithTwoGames();
// Mock as if we couldn't find the highlighted games response data file.
EXPECT_CALL(*mock_parser_, TryParseHighlightedGames(fake_install_dir_))
.WillOnce(
[](const base::FilePath& install_dir) { return base::nullopt; });
ExpectProcessAsyncFailure(ResponseCode::kFileNotFound, fake_catalog);
}
TEST_F(HighlightedGamesStoreTest, ProcessAsync_CurrentGameIdNotFoundInCatalog) {
GamesCatalog fake_catalog = test::CreateCatalogWithTwoGames();
// No game has ID 99 in our fake catalog.
HighlightedGamesResponse fake_response;
AddValidHighlightedGame(&fake_response, 99);
EXPECT_CALL(*mock_parser_, TryParseHighlightedGames(fake_install_dir_))
.WillOnce([&fake_response](const base::FilePath& install_dir) {
return base::Optional<HighlightedGamesResponse>(fake_response);
});
ExpectProcessAsyncFailure(ResponseCode::kInvalidData, fake_catalog);
}
TEST_F(HighlightedGamesStoreTest, ProcessAsync_NoCurrentGame) {
GamesCatalog fake_catalog = test::CreateCatalogWithTwoGames();
// Create a future HighlightedGame.
HighlightedGame fake_highlighted_game;
fake_highlighted_game.set_game_id(fake_catalog.games().at(0).id());
SetDateProtoTo(fake_highlighted_game.mutable_start_date(),
mock_clock_.Now() + base::TimeDelta::FromDays(1));
SetDateProtoTo(fake_highlighted_game.mutable_end_date(),
mock_clock_.Now() + base::TimeDelta::FromDays(2));
HighlightedGamesResponse fake_response;
fake_response.mutable_games()->Add(std::move(fake_highlighted_game));
EXPECT_CALL(*mock_parser_, TryParseHighlightedGames(fake_install_dir_))
.WillOnce([&fake_response](const base::FilePath& install_dir) {
return base::Optional<HighlightedGamesResponse>(fake_response);
});
ExpectProcessAsyncFailure(ResponseCode::kInvalidData, fake_catalog);
}
TEST_F(HighlightedGamesStoreTest, HandleCatalogFailure_CallsCallback) {
......@@ -133,7 +265,7 @@ TEST_F(HighlightedGamesStoreTest, HandleCatalogFailure_CallsCallback) {
highlighted_games_store_->SetPendingCallback(base::BindLambdaForTesting(
[&expected_code, &callback_called](ResponseCode code, const Game game) {
EXPECT_EQ(expected_code, code);
EXPECT_TRUE(test::AreProtosEqual(Game(), game));
test::ExpectProtosEqual(Game(), game);
callback_called = true;
}));
......
......@@ -15,5 +15,6 @@ static_library("test_support") {
"//components/games/core",
"//components/games/core/proto",
"//testing/gmock",
"//testing/gtest",
]
}
......@@ -20,8 +20,23 @@ void MockCatalogStore::set_cached_catalog(const GamesCatalog* catalog) {
}
MockHighlightedGamesStore::MockHighlightedGamesStore()
: HighlightedGamesStore(nullptr) {}
: HighlightedGamesStore(nullptr, nullptr) {}
MockHighlightedGamesStore::~MockHighlightedGamesStore() = default;
MockClock::MockClock() {}
MockClock::~MockClock() = default;
void MockClock::MockNow(const base::Time& fake_time) {
mock_now_ = fake_time;
}
base::Time MockClock::Now() const {
return mock_now_;
}
void MockClock::AdvanceDays(int days) {
mock_now_ += base::TimeDelta::FromDays(days);
}
} // namespace test
} // namespace games
......@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/optional.h"
#include "base/time/clock.h"
#include "components/games/core/catalog_store.h"
#include "components/games/core/data_files_parser.h"
#include "components/games/core/games_types.h"
......@@ -58,6 +59,21 @@ class MockHighlightedGamesStore : public HighlightedGamesStore {
MOCK_METHOD1(HandleCatalogFailure, void(ResponseCode));
};
class MockClock : public base::Clock {
public:
explicit MockClock();
~MockClock() override;
void MockNow(const base::Time& fake_time);
base::Time Now() const override;
void AdvanceDays(int days);
protected:
base::Time mock_now_;
};
} // namespace test
} // namespace games
......
......@@ -4,6 +4,8 @@
#include "components/games/core/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace games {
namespace test {
......@@ -21,6 +23,11 @@ GamesCatalog CreateGamesCatalogWithOneGame() {
return CreateGamesCatalog({CreateGame()});
}
GamesCatalog CreateCatalogWithTwoGames() {
return test::CreateGamesCatalog(
{test::CreateGame(/*id=*/1), test::CreateGame(/*id=*/2)});
}
Game CreateGame(int id) {
Game game;
game.set_id(id);
......@@ -55,9 +62,9 @@ HighlightedGamesResponse CreateHighlightedGamesResponse() {
return highlighted_games;
}
bool AreProtosEqual(const google::protobuf::MessageLite& lhs,
const google::protobuf::MessageLite& rhs) {
return lhs.SerializeAsString() == rhs.SerializeAsString();
void ExpectProtosEqual(const google::protobuf::MessageLite& expected,
const google::protobuf::MessageLite& actual) {
EXPECT_EQ(expected.SerializeAsString(), actual.SerializeAsString());
}
} // namespace test
......
......@@ -20,14 +20,16 @@ GamesCatalog CreateGamesCatalog(std::vector<Game> games);
GamesCatalog CreateGamesCatalogWithOneGame();
GamesCatalog CreateCatalogWithTwoGames();
Game CreateGame(int id = 1);
Date CreateDate(int year, int month, int day);
HighlightedGamesResponse CreateHighlightedGamesResponse();
bool AreProtosEqual(const google::protobuf::MessageLite& lhs,
const google::protobuf::MessageLite& rhs);
void ExpectProtosEqual(const google::protobuf::MessageLite& expected,
const google::protobuf::MessageLite& actual);
} // namespace test
} // namespace games
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment