#include "chromeos/printing/printer_config_cache.h"
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/simple_test_clock.h"
#include "base/test/task_environment.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "net/http/http_status_code.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
const char kKnownGoodResourceURL[] =
"https://printerconfigurations.googleusercontent.com/chromeos_printing/"
"known-good";
const char kKnownGoodResourceContent[] = "yakisaba";
const char kKnownBadResourceURL[] =
"https://printerconfigurations.googleusercontent.com/chromeos_printing/"
"known-bad";
constexpr base::TimeDelta kTestingIncrement = base::Seconds(1LL);
constexpr base::Time kUnusedTimeOfFetch;
MATCHER_P(TimeInsensitiveFetchResultEquals, expected, "") {
return arg.succeeded == expected.succeeded && arg.key == expected.key &&
arg.contents == expected.contents;
}
MATCHER_P(FetchResultEquals, expected, "") {
return arg.succeeded == expected.succeeded && arg.key == expected.key &&
arg.contents == expected.contents &&
arg.time_of_fetch == expected.time_of_fetch;
}
class PrinterConfigCacheTest : public ::testing::Test {
public:
PrinterConfigCacheTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
cache_(PrinterConfigCache::Create(
&clock_,
base::BindLambdaForTesting([&]() {
return reinterpret_cast<network::mojom::URLLoaderFactory*>(
&loader_factory_);
}),
false)) {}
void SetUp() override {
loader_factory_.AddResponse(kKnownGoodResourceURL,
kKnownGoodResourceContent);
loader_factory_.AddResponse(kKnownBadResourceURL, "",
net::HTTP_NOT_ACCEPTABLE);
}
void CaptureFetchResult(base::RepeatingClosure quit_closure,
const PrinterConfigCache::FetchResult& result) {
fetched_results_.push_back(result);
if (quit_closure) {
quit_closure.Run();
}
}
void AdvanceClock(base::TimeDelta amount = kTestingIncrement) {
clock_.Advance(amount);
}
protected:
std::vector<PrinterConfigCache::FetchResult> fetched_results_;
network::TestURLLoaderFactory loader_factory_;
base::test::TaskEnvironment task_environment_;
base::SimpleTestClock clock_;
std::unique_ptr<PrinterConfigCache> cache_;
};
TEST_F(PrinterConfigCacheTest, SucceedAtSingleFetch) {
base::RunLoop run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this), run_loop.QuitClosure())));
run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 1ULL);
EXPECT_THAT(
fetched_results_.front(),
TimeInsensitiveFetchResultEquals(PrinterConfigCache::FetchResult::Success(
"known-good", "yakisaba", kUnusedTimeOfFetch)));
}
TEST_F(PrinterConfigCacheTest, FailAtSingleFetch) {
base::RunLoop run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-bad", base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this), run_loop.QuitClosure())));
run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 1ULL);
EXPECT_THAT(fetched_results_.front(),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Failure("known-bad")));
}
TEST_F(PrinterConfigCacheTest, RefreshSubsequentFetch) {
base::RunLoop first_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
first_run_loop.QuitClosure())));
first_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 1ULL);
loader_factory_.AddResponse(kKnownGoodResourceURL, "one Argentinian peso");
base::RunLoop second_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
second_run_loop.QuitClosure())));
second_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 2ULL);
EXPECT_THAT(
fetched_results_,
testing::ElementsAre(
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success(
"known-good", "one Argentinian peso", kUnusedTimeOfFetch))));
}
TEST_F(PrinterConfigCacheTest, LocallyPerformSubsequentFetch) {
base::RunLoop first_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
first_run_loop.QuitClosure())));
first_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 1ULL);
loader_factory_.AddResponse(kKnownGoodResourceURL, "apologize darn you");
base::RunLoop second_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good",
base::Seconds(1LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
base::RepeatingClosure())));
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(3600LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this), base::RepeatingClosure())));
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(86400LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this), base::RepeatingClosure())));
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good",
base::Seconds(0LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
second_run_loop.QuitClosure())));
second_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 5ULL);
EXPECT_THAT(
fetched_results_,
testing::ElementsAre(
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success(
"known-good", "apologize darn you", kUnusedTimeOfFetch))));
}
TEST_F(PrinterConfigCacheTest, FetchExpirationIsRespected) {
base::RunLoop first_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(32LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
first_run_loop.QuitClosure())));
first_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 1ULL);
const base::Time time_zero = clock_.Now();
AdvanceClock(base::Seconds(31LL));
base::RunLoop second_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(32LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
second_run_loop.QuitClosure())));
second_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 2ULL);
AdvanceClock(base::Seconds(1));
base::RunLoop third_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good",
base::Seconds(32LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
third_run_loop.QuitClosure())));
third_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 3ULL);
const base::Time time_of_third_fetch = clock_.Now();
EXPECT_THAT(fetched_results_,
testing::ElementsAre(
FetchResultEquals(PrinterConfigCache::FetchResult::Success(
"known-good", "yakisaba", time_zero)),
FetchResultEquals(PrinterConfigCache::FetchResult::Success(
"known-good", "yakisaba", time_zero)),
FetchResultEquals(PrinterConfigCache::FetchResult::Success(
"known-good", "yakisaba", time_of_third_fetch))));
}
TEST_F(PrinterConfigCacheTest, DropLocalContents) {
base::RunLoop first_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(604800LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
first_run_loop.QuitClosure())));
first_run_loop.Run();
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&PrinterConfigCache::Drop,
base::Unretained(cache_.get()), "known-good"));
loader_factory_.AddResponse(kKnownGoodResourceURL, "ultimate dogeza");
base::RunLoop second_run_loop;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()),
"known-good", base::Seconds(18748800LL),
base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult,
base::Unretained(this),
second_run_loop.QuitClosure())));
second_run_loop.Run();
ASSERT_EQ(fetched_results_.size(), 2ULL);
EXPECT_THAT(
fetched_results_,
testing::ElementsAre(
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success("known-good", "yakisaba",
kUnusedTimeOfFetch)),
TimeInsensitiveFetchResultEquals(
PrinterConfigCache::FetchResult::Success(
"known-good", "ultimate dogeza", kUnusedTimeOfFetch))));
}
}
}