1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/search_provider_logos/logo_cache.h"
10 #include "base/callback.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace search_provider_logos
{
19 LogoMetadata
GetExampleMetadata() {
20 LogoMetadata metadata
;
21 metadata
.source_url
= "http://google.com/mylogo";
22 metadata
.fingerprint
= "LC4JVIZ5HVITQFKH0V70";
23 EXPECT_TRUE(base::Time::FromString("98-05-05 05:05:06 GMT",
24 &metadata
.expiration_time
));
25 metadata
.can_show_after_expiration
= true;
26 metadata
.on_click_url
= "https://www.google.com/search?q=chicken";
27 metadata
.animated_url
= "http://www.google.com/logos/doodle.png";
28 metadata
.alt_text
= "A logo about chickens";
29 metadata
.mime_type
= "image/jpeg";
33 LogoMetadata
GetExampleMetadata2() {
34 LogoMetadata metadata
;
35 metadata
.source_url
= "https://www.example.com/thebestlogo?size=large";
36 metadata
.fingerprint
= "bh4PLHdnEaQAPxNGRyMao1rOmVFTXuOdVhdrMmPV";
37 EXPECT_TRUE(base::Time::FromString("17-04-04 07:10:58 GMT",
38 &metadata
.expiration_time
));
39 metadata
.can_show_after_expiration
= false;
40 metadata
.on_click_url
= "http://www.example.co.uk/welcome.php#top";
41 metadata
.alt_text
= "This is a logo";
42 metadata
.mime_type
= "image/png";
46 base::RefCountedString
* CreateExampleImage(size_t num_bytes
) {
47 base::RefCountedString
* encoded_image_str
= new base::RefCountedString();
48 std::string
& str
= encoded_image_str
->data();
49 str
.resize(num_bytes
);
50 for (size_t i
= 0; i
< num_bytes
; ++i
)
51 str
[i
] = static_cast<char>(i
);
52 return encoded_image_str
;
55 EncodedLogo
GetExampleLogo() {
57 logo
.encoded_image
= CreateExampleImage(837);
58 logo
.metadata
= GetExampleMetadata();
62 EncodedLogo
GetExampleLogo2() {
64 logo
.encoded_image
= CreateExampleImage(345);
65 logo
.metadata
= GetExampleMetadata2();
69 void ExpectMetadataEqual(const LogoMetadata
& expected_metadata
,
70 const LogoMetadata
& actual_metadata
) {
71 EXPECT_EQ(expected_metadata
.source_url
, actual_metadata
.source_url
);
72 EXPECT_EQ(expected_metadata
.fingerprint
, actual_metadata
.fingerprint
);
73 EXPECT_EQ(expected_metadata
.can_show_after_expiration
,
74 actual_metadata
.can_show_after_expiration
);
75 EXPECT_EQ(expected_metadata
.expiration_time
, actual_metadata
.expiration_time
);
76 EXPECT_EQ(expected_metadata
.on_click_url
, actual_metadata
.on_click_url
);
77 EXPECT_EQ(expected_metadata
.animated_url
, actual_metadata
.animated_url
);
78 EXPECT_EQ(expected_metadata
.alt_text
, actual_metadata
.alt_text
);
79 EXPECT_EQ(expected_metadata
.mime_type
, actual_metadata
.mime_type
);
82 void ExpectLogosEqual(const EncodedLogo
& expected_logo
,
83 const EncodedLogo
& actual_logo
) {
84 ASSERT_TRUE(expected_logo
.encoded_image
.get());
85 ASSERT_TRUE(actual_logo
.encoded_image
.get());
86 EXPECT_TRUE(expected_logo
.encoded_image
->Equals(actual_logo
.encoded_image
));
87 ExpectMetadataEqual(expected_logo
.metadata
, actual_logo
.metadata
);
90 // Removes 1 byte from the end of the file at |path|.
91 void ShortenFile(base::FilePath path
) {
92 base::File
file(path
, base::File::FLAG_OPEN
| base::File::FLAG_WRITE
);
93 int64 file_length
= file
.GetLength();
94 ASSERT_NE(file_length
, 0);
95 file
.SetLength(file_length
- 1);
98 class LogoCacheTest
: public ::testing::Test
{
100 void SetUp() override
{
101 ASSERT_TRUE(cache_parent_dir_
.CreateUniqueTempDir());
106 cache_
.reset(new LogoCache(
107 cache_parent_dir_
.path().Append(FILE_PATH_LITERAL("cache"))));
110 void ExpectMetadata(const LogoMetadata
* expected_metadata
) {
111 const LogoMetadata
* retrieved_metadata
= cache_
->GetCachedLogoMetadata();
112 if (expected_metadata
) {
113 ASSERT_TRUE(retrieved_metadata
!= NULL
);
114 ExpectMetadataEqual(*expected_metadata
, *retrieved_metadata
);
116 ASSERT_TRUE(retrieved_metadata
== NULL
);
120 void ExpectLogo(const EncodedLogo
* expected_logo
) {
121 scoped_ptr
<EncodedLogo
> retrieved_logo(cache_
->GetCachedLogo());
123 ASSERT_TRUE(retrieved_logo
.get() != NULL
);
124 ExpectLogosEqual(*expected_logo
, *retrieved_logo
);
126 ASSERT_TRUE(retrieved_logo
.get() == NULL
);
130 // Deletes the existing LogoCache and creates a new one. This clears any
131 // logo or metadata cached in memory to simulate restarting Chrome.
132 void SimulateRestart() {
136 scoped_ptr
<LogoCache
> cache_
;
137 base::ScopedTempDir cache_parent_dir_
;
140 // Tests -----------------------------------------------------------------------
142 TEST(LogoCacheSerializationTest
, SerializeMetadata
) {
143 LogoMetadata metadata
= GetExampleMetadata();
144 std::string metadata_str
;
145 int logo_num_bytes
= 33;
146 LogoCache::LogoMetadataToString(metadata
, logo_num_bytes
, &metadata_str
);
147 scoped_ptr
<LogoMetadata
> metadata2
=
148 LogoCache::LogoMetadataFromString(metadata_str
, &logo_num_bytes
);
149 ASSERT_TRUE(metadata2
);
150 ExpectMetadataEqual(metadata
, *metadata2
);
153 TEST(LogoCacheSerializationTest
, DeserializeCorruptMetadata
) {
154 int logo_num_bytes
= 33;
155 scoped_ptr
<LogoMetadata
> metadata
=
156 LogoCache::LogoMetadataFromString("", &logo_num_bytes
);
157 ASSERT_TRUE(metadata
.get() == NULL
);
159 LogoMetadata example_metadata
= GetExampleMetadata2();
160 std::string corrupt_str
;
161 LogoCache::LogoMetadataToString(
162 example_metadata
, logo_num_bytes
, &corrupt_str
);
163 corrupt_str
.append("@");
164 metadata
= LogoCache::LogoMetadataFromString(corrupt_str
, &logo_num_bytes
);
165 ASSERT_TRUE(metadata
.get() == NULL
);
168 TEST_F(LogoCacheTest
, StoreAndRetrieveMetadata
) {
169 // Expect no metadata at first.
170 ExpectMetadata(NULL
);
172 // Set initial metadata.
173 EncodedLogo logo
= GetExampleLogo();
174 LogoMetadata
& metadata
= logo
.metadata
;
175 cache_
->SetCachedLogo(&logo
);
176 ExpectMetadata(&metadata
);
179 metadata
.on_click_url
= "http://anotherwebsite.com";
180 cache_
->UpdateCachedLogoMetadata(metadata
);
181 ExpectMetadata(&metadata
);
183 // Read metadata back from disk.
185 ExpectMetadata(&metadata
);
187 // Ensure metadata is cached in memory.
188 base::DeleteFile(cache_
->GetMetadataPath(), false);
189 ExpectMetadata(&metadata
);
192 TEST_F(LogoCacheTest
, StoreAndRetrieveLogo
) {
193 // Expect no metadata at first.
197 EncodedLogo logo
= GetExampleLogo();
198 cache_
->SetCachedLogo(&logo
);
201 // Update logo to NULL.
202 cache_
->SetCachedLogo(NULL
);
205 // Read logo back from disk.
210 logo
= GetExampleLogo2();
211 cache_
->SetCachedLogo(&logo
);
214 // Read logo back from disk.
219 TEST_F(LogoCacheTest
, RetrieveCorruptMetadata
) {
221 EncodedLogo logo
= GetExampleLogo2();
222 cache_
->SetCachedLogo(&logo
);
225 // Corrupt metadata and expect NULL for both logo and metadata.
227 ShortenFile(cache_
->GetMetadataPath());
228 ExpectMetadata(NULL
);
231 // Ensure corrupt cache files are deleted.
232 EXPECT_FALSE(base::PathExists(cache_
->GetMetadataPath()));
233 EXPECT_FALSE(base::PathExists(cache_
->GetLogoPath()));
236 TEST_F(LogoCacheTest
, RetrieveCorruptLogo
) {
238 EncodedLogo logo
= GetExampleLogo();
239 cache_
->SetCachedLogo(&logo
);
242 // Corrupt logo and expect NULL.
244 ShortenFile(cache_
->GetLogoPath());
246 // Once the logo is noticed to be NULL, the metadata should also be cleared.
247 ExpectMetadata(NULL
);
249 // Ensure corrupt cache files are deleted.
250 EXPECT_FALSE(base::PathExists(cache_
->GetMetadataPath()));
251 EXPECT_FALSE(base::PathExists(cache_
->GetLogoPath()));
254 } // namespace search_provider_logos