logo_cache_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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.
  4. #include "components/search_provider_logos/logo_cache.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <string>
  9. #include "base/bind.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"
  16. namespace search_provider_logos {
  17. LogoMetadata GetExampleMetadata() {
  18. LogoMetadata metadata;
  19. metadata.source_url = GURL("http://google.com/mylogo");
  20. metadata.fingerprint = "LC4JVIZ5HVITQFKH0V70";
  21. EXPECT_TRUE(base::Time::FromString("98-05-05 05:05:06 GMT",
  22. &metadata.expiration_time));
  23. metadata.can_show_after_expiration = true;
  24. metadata.type = LogoType::ANIMATED;
  25. metadata.short_link = GURL("https://g.co/");
  26. metadata.on_click_url = GURL("https://www.google.com/search?q=chicken");
  27. metadata.animated_url = GURL("http://www.google.com/logos/doodle.png");
  28. metadata.dark_animated_url =
  29. GURL("http://www.google.com/logos/dark_doodle.png");
  30. metadata.alt_text = "A logo about chickens";
  31. metadata.mime_type = "image/jpeg";
  32. metadata.dark_mime_type = "image/jpeg";
  33. metadata.dark_background_color = "#ABC123";
  34. metadata.log_url = GURL("https://www.google.com/ddllog?a=b");
  35. metadata.dark_log_url = GURL("https://www.google.com/ddllog?a=dark");
  36. metadata.cta_log_url = GURL("https://www.google.com/ddllog?c=d");
  37. metadata.dark_cta_log_url = GURL("https://www.google.com/ddllog?c=dark");
  38. metadata.share_button_x = 200;
  39. metadata.share_button_y = 100;
  40. metadata.share_button_opacity = 0.5;
  41. metadata.share_button_icon = "test_img";
  42. metadata.share_button_bg = "#ff22ff";
  43. metadata.dark_share_button_x = 150;
  44. metadata.dark_share_button_y = 50;
  45. metadata.dark_share_button_opacity = 0.7;
  46. metadata.dark_share_button_icon = "dark_test_img";
  47. metadata.dark_share_button_bg = "#22ff22";
  48. metadata.width_px = 500;
  49. metadata.height_px = 200;
  50. metadata.dark_width_px = 600;
  51. metadata.dark_height_px = 230;
  52. return metadata;
  53. }
  54. LogoMetadata GetExampleMetadata2() {
  55. LogoMetadata metadata;
  56. metadata.source_url = GURL("https://www.example.com/thebestlogo?size=large");
  57. metadata.fingerprint = "bh4PLHdnEaQAPxNGRyMao1rOmVFTXuOdVhdrMmPV";
  58. EXPECT_TRUE(base::Time::FromString("17-04-04 07:10:58 GMT",
  59. &metadata.expiration_time));
  60. metadata.can_show_after_expiration = false;
  61. metadata.type = LogoType::INTERACTIVE;
  62. metadata.on_click_url = GURL("http://www.example.co.uk/welcome.php#top");
  63. metadata.full_page_url =
  64. GURL("http://www.example.co.uk/welcome.php#fpdoodle");
  65. metadata.alt_text = "This is a logo";
  66. metadata.mime_type = "image/png";
  67. return metadata;
  68. }
  69. base::RefCountedString* CreateExampleImage(size_t num_bytes) {
  70. base::RefCountedString* encoded_image_str = new base::RefCountedString();
  71. std::string& str = encoded_image_str->data();
  72. str.resize(num_bytes);
  73. for (size_t i = 0; i < num_bytes; ++i)
  74. str[i] = static_cast<char>(i);
  75. return encoded_image_str;
  76. }
  77. std::unique_ptr<EncodedLogo> GetExampleLogo() {
  78. auto logo = std::make_unique<EncodedLogo>();
  79. logo->encoded_image = CreateExampleImage(837);
  80. logo->dark_encoded_image = CreateExampleImage(738);
  81. logo->metadata = GetExampleMetadata();
  82. return logo;
  83. }
  84. std::unique_ptr<EncodedLogo> GetExampleLogo2() {
  85. auto logo = std::make_unique<EncodedLogo>();
  86. logo->encoded_image = CreateExampleImage(345);
  87. logo->dark_encoded_image = CreateExampleImage(543);
  88. logo->metadata = GetExampleMetadata2();
  89. return logo;
  90. }
  91. std::unique_ptr<EncodedLogo> GetExampleLogoWithoutImage() {
  92. auto logo = std::make_unique<EncodedLogo>();
  93. logo->encoded_image = nullptr;
  94. logo->dark_encoded_image = nullptr;
  95. logo->metadata = GetExampleMetadata2();
  96. return logo;
  97. }
  98. void ExpectMetadataEqual(const LogoMetadata& expected_metadata,
  99. const LogoMetadata& actual_metadata) {
  100. EXPECT_EQ(expected_metadata.source_url, actual_metadata.source_url);
  101. EXPECT_EQ(expected_metadata.fingerprint, actual_metadata.fingerprint);
  102. EXPECT_EQ(expected_metadata.can_show_after_expiration,
  103. actual_metadata.can_show_after_expiration);
  104. EXPECT_EQ(expected_metadata.expiration_time, actual_metadata.expiration_time);
  105. EXPECT_EQ(expected_metadata.type, actual_metadata.type);
  106. EXPECT_EQ(expected_metadata.on_click_url, actual_metadata.on_click_url);
  107. EXPECT_EQ(expected_metadata.full_page_url, actual_metadata.full_page_url);
  108. EXPECT_EQ(expected_metadata.animated_url, actual_metadata.animated_url);
  109. EXPECT_EQ(expected_metadata.alt_text, actual_metadata.alt_text);
  110. EXPECT_EQ(expected_metadata.mime_type, actual_metadata.mime_type);
  111. EXPECT_EQ(expected_metadata.log_url, actual_metadata.log_url);
  112. EXPECT_EQ(expected_metadata.dark_log_url, actual_metadata.dark_log_url);
  113. EXPECT_EQ(expected_metadata.cta_log_url, actual_metadata.cta_log_url);
  114. EXPECT_EQ(expected_metadata.dark_cta_log_url,
  115. actual_metadata.dark_cta_log_url);
  116. EXPECT_EQ(expected_metadata.short_link, actual_metadata.short_link);
  117. EXPECT_EQ(expected_metadata.share_button_x, actual_metadata.share_button_x);
  118. EXPECT_EQ(expected_metadata.share_button_y, actual_metadata.share_button_y);
  119. EXPECT_EQ(expected_metadata.share_button_opacity,
  120. actual_metadata.share_button_opacity);
  121. EXPECT_EQ(expected_metadata.share_button_icon,
  122. actual_metadata.share_button_icon);
  123. EXPECT_EQ(expected_metadata.share_button_bg, actual_metadata.share_button_bg);
  124. EXPECT_EQ(expected_metadata.dark_share_button_x,
  125. actual_metadata.dark_share_button_x);
  126. EXPECT_EQ(expected_metadata.dark_share_button_y,
  127. actual_metadata.dark_share_button_y);
  128. EXPECT_EQ(expected_metadata.dark_share_button_opacity,
  129. actual_metadata.dark_share_button_opacity);
  130. EXPECT_EQ(expected_metadata.dark_share_button_icon,
  131. actual_metadata.dark_share_button_icon);
  132. EXPECT_EQ(expected_metadata.dark_share_button_bg,
  133. actual_metadata.dark_share_button_bg);
  134. EXPECT_EQ(expected_metadata.width_px, actual_metadata.width_px);
  135. EXPECT_EQ(expected_metadata.height_px, actual_metadata.height_px);
  136. EXPECT_EQ(expected_metadata.dark_width_px, actual_metadata.dark_width_px);
  137. EXPECT_EQ(expected_metadata.dark_height_px, actual_metadata.dark_height_px);
  138. EXPECT_EQ(expected_metadata.iframe_width_px, actual_metadata.iframe_width_px);
  139. EXPECT_EQ(expected_metadata.iframe_height_px,
  140. actual_metadata.iframe_height_px);
  141. EXPECT_EQ(expected_metadata.dark_background_color,
  142. actual_metadata.dark_background_color);
  143. }
  144. void ExpectLogosEqual(const EncodedLogo& expected_logo,
  145. const EncodedLogo& actual_logo) {
  146. ASSERT_TRUE(expected_logo.encoded_image.get());
  147. ASSERT_TRUE(actual_logo.encoded_image.get());
  148. EXPECT_TRUE(expected_logo.encoded_image->Equals(actual_logo.encoded_image));
  149. ASSERT_TRUE(expected_logo.dark_encoded_image.get());
  150. ASSERT_TRUE(actual_logo.dark_encoded_image.get());
  151. EXPECT_TRUE(
  152. expected_logo.dark_encoded_image->Equals(actual_logo.dark_encoded_image));
  153. ExpectMetadataEqual(expected_logo.metadata, actual_logo.metadata);
  154. }
  155. // Removes 1 byte from the end of the file at |path|.
  156. void ShortenFile(base::FilePath path) {
  157. base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_WRITE);
  158. int64_t file_length = file.GetLength();
  159. ASSERT_GT(file_length, 0);
  160. file.SetLength(file_length - 1);
  161. }
  162. class LogoCacheTest : public ::testing::Test {
  163. protected:
  164. void SetUp() override {
  165. ASSERT_TRUE(cache_parent_dir_.CreateUniqueTempDir());
  166. InitCache();
  167. }
  168. void InitCache() {
  169. cache_ = std::make_unique<LogoCache>(
  170. cache_parent_dir_.GetPath().Append(FILE_PATH_LITERAL("cache")));
  171. }
  172. void ExpectMetadata(const LogoMetadata* expected_metadata) {
  173. const LogoMetadata* retrieved_metadata = cache_->GetCachedLogoMetadata();
  174. if (expected_metadata) {
  175. ASSERT_TRUE(retrieved_metadata);
  176. ExpectMetadataEqual(*expected_metadata, *retrieved_metadata);
  177. } else {
  178. ASSERT_FALSE(retrieved_metadata);
  179. }
  180. }
  181. void ExpectLogo(const EncodedLogo* expected_logo) {
  182. std::unique_ptr<EncodedLogo> retrieved_logo(cache_->GetCachedLogo());
  183. if (expected_logo) {
  184. ASSERT_TRUE(retrieved_logo.get());
  185. ExpectLogosEqual(*expected_logo, *retrieved_logo);
  186. } else {
  187. ASSERT_FALSE(retrieved_logo);
  188. }
  189. }
  190. void ExpectLogoWithoutImage(const EncodedLogo* expected_logo) {
  191. std::unique_ptr<EncodedLogo> retrieved_logo(cache_->GetCachedLogo());
  192. ASSERT_TRUE(retrieved_logo.get());
  193. ASSERT_FALSE(retrieved_logo->encoded_image.get());
  194. ASSERT_FALSE(expected_logo->encoded_image.get());
  195. ExpectMetadataEqual(expected_logo->metadata, retrieved_logo->metadata);
  196. }
  197. // Deletes the existing LogoCache and creates a new one. This clears any
  198. // logo or metadata cached in memory to simulate restarting Chrome.
  199. void SimulateRestart() {
  200. InitCache();
  201. }
  202. std::unique_ptr<LogoCache> cache_;
  203. base::ScopedTempDir cache_parent_dir_;
  204. };
  205. // Tests -----------------------------------------------------------------------
  206. TEST(LogoCacheSerializationTest, SerializeMetadata) {
  207. LogoMetadata metadata = GetExampleMetadata();
  208. std::string metadata_str;
  209. int logo_num_bytes = 33;
  210. int dark_logo_num_bytes = 44;
  211. LogoCache::LogoMetadataToString(metadata, logo_num_bytes, dark_logo_num_bytes,
  212. &metadata_str);
  213. std::unique_ptr<LogoMetadata> metadata2 = LogoCache::LogoMetadataFromString(
  214. metadata_str, &logo_num_bytes, &dark_logo_num_bytes);
  215. ASSERT_TRUE(metadata2);
  216. ExpectMetadataEqual(metadata, *metadata2);
  217. }
  218. TEST(LogoCacheSerializationTest, DeserializeCorruptMetadata) {
  219. int logo_num_bytes = 33;
  220. int dark_logo_num_bytes = 44;
  221. std::unique_ptr<LogoMetadata> metadata = LogoCache::LogoMetadataFromString(
  222. "", &logo_num_bytes, &dark_logo_num_bytes);
  223. ASSERT_FALSE(metadata);
  224. LogoMetadata example_metadata = GetExampleMetadata2();
  225. std::string corrupt_str;
  226. LogoCache::LogoMetadataToString(example_metadata, logo_num_bytes,
  227. dark_logo_num_bytes, &corrupt_str);
  228. corrupt_str.append("@");
  229. metadata = LogoCache::LogoMetadataFromString(corrupt_str, &logo_num_bytes,
  230. &dark_logo_num_bytes);
  231. ASSERT_FALSE(metadata);
  232. }
  233. TEST_F(LogoCacheTest, StoreAndRetrieveMetadata) {
  234. // Expect no metadata at first.
  235. ExpectMetadata(nullptr);
  236. // Set initial metadata.
  237. std::unique_ptr<EncodedLogo> logo = GetExampleLogo();
  238. LogoMetadata& metadata = logo->metadata;
  239. cache_->SetCachedLogo(logo.get());
  240. ExpectMetadata(&metadata);
  241. // Update metadata.
  242. metadata.on_click_url = GURL("http://anotherwebsite.com");
  243. cache_->UpdateCachedLogoMetadata(metadata);
  244. ExpectMetadata(&metadata);
  245. // Read metadata back from disk.
  246. SimulateRestart();
  247. ExpectMetadata(&metadata);
  248. // Ensure metadata is cached in memory.
  249. base::DeleteFile(cache_->GetMetadataPath());
  250. ExpectMetadata(&metadata);
  251. }
  252. TEST_F(LogoCacheTest, StoreAndRetrieveLogo) {
  253. // Expect no metadata at first.
  254. ExpectLogo(nullptr);
  255. // Set initial logo.
  256. std::unique_ptr<EncodedLogo> logo = GetExampleLogo();
  257. cache_->SetCachedLogo(logo.get());
  258. ExpectLogo(logo.get());
  259. // Update logo to null.
  260. cache_->SetCachedLogo(nullptr);
  261. ExpectLogo(nullptr);
  262. // Read logo back from disk.
  263. SimulateRestart();
  264. ExpectLogo(nullptr);
  265. // Update logo.
  266. logo = GetExampleLogo2();
  267. cache_->SetCachedLogo(logo.get());
  268. ExpectLogo(logo.get());
  269. // Read logo back from disk.
  270. SimulateRestart();
  271. ExpectLogo(logo.get());
  272. }
  273. TEST_F(LogoCacheTest, StoreAndRetrieveLogoWithoutImage) {
  274. // Expect no metadata at first.
  275. ExpectLogo(nullptr);
  276. // Set initial logo.
  277. std::unique_ptr<EncodedLogo> logo = GetExampleLogoWithoutImage();
  278. cache_->SetCachedLogo(logo.get());
  279. ExpectLogoWithoutImage(logo.get());
  280. // Update logo to null.
  281. cache_->SetCachedLogo(nullptr);
  282. ExpectLogo(nullptr);
  283. // Read logo back from disk.
  284. SimulateRestart();
  285. ExpectLogo(nullptr);
  286. // Update logo.
  287. logo = GetExampleLogoWithoutImage();
  288. cache_->SetCachedLogo(logo.get());
  289. ExpectLogoWithoutImage(logo.get());
  290. // Read logo back from disk.
  291. SimulateRestart();
  292. ExpectLogoWithoutImage(logo.get());
  293. }
  294. TEST_F(LogoCacheTest, RetrieveCorruptMetadata) {
  295. // Set initial logo.
  296. std::unique_ptr<EncodedLogo> logo = GetExampleLogo2();
  297. cache_->SetCachedLogo(logo.get());
  298. ExpectLogo(logo.get());
  299. // Corrupt metadata and expect null for both logo and metadata.
  300. SimulateRestart();
  301. ShortenFile(cache_->GetMetadataPath());
  302. ExpectMetadata(nullptr);
  303. ExpectLogo(nullptr);
  304. // Ensure corrupt cache files are deleted.
  305. EXPECT_FALSE(base::PathExists(cache_->GetMetadataPath()));
  306. EXPECT_FALSE(base::PathExists(cache_->GetLogoPath()));
  307. }
  308. TEST_F(LogoCacheTest, RetrieveCorruptLogo) {
  309. // Set initial logo.
  310. std::unique_ptr<EncodedLogo> logo = GetExampleLogo();
  311. cache_->SetCachedLogo(logo.get());
  312. ExpectLogo(logo.get());
  313. // Corrupt logo and expect nullptr.
  314. SimulateRestart();
  315. ShortenFile(cache_->GetLogoPath());
  316. ExpectLogo(nullptr);
  317. // Once the logo is noticed to be null, the metadata should also be cleared.
  318. ExpectMetadata(nullptr);
  319. // Ensure corrupt cache files are deleted.
  320. EXPECT_FALSE(base::PathExists(cache_->GetMetadataPath()));
  321. EXPECT_FALSE(base::PathExists(cache_->GetLogoPath()));
  322. }
  323. } // namespace search_provider_logos