OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
9 #include "base/files/file_enumerator.h" | 9 #include "base/files/file_enumerator.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 // Implicit index on [meta], index on [favicons], index on | 71 // Implicit index on [meta], index on [favicons], index on |
72 // [favicon_bitmaps], two indices on [icon_mapping]. | 72 // [favicon_bitmaps], two indices on [icon_mapping]. |
73 EXPECT_EQ(5u, sql::test::CountSQLIndices(db)); | 73 EXPECT_EQ(5u, sql::test::CountSQLIndices(db)); |
74 | 74 |
75 // [key] and [value]. | 75 // [key] and [value]. |
76 EXPECT_EQ(2u, sql::test::CountTableColumns(db, "meta")); | 76 EXPECT_EQ(2u, sql::test::CountTableColumns(db, "meta")); |
77 | 77 |
78 // [id], [url], and [icon_type]. | 78 // [id], [url], and [icon_type]. |
79 EXPECT_EQ(3u, sql::test::CountTableColumns(db, "favicons")); | 79 EXPECT_EQ(3u, sql::test::CountTableColumns(db, "favicons")); |
80 | 80 |
81 // [id], [icon_id], [last_updated], [image_data], [width], and [height]. | 81 // [id], [icon_id], [last_updated], [image_data], [width], [height] and |
82 EXPECT_EQ(6u, sql::test::CountTableColumns(db, "favicon_bitmaps")); | 82 // [last_requested]. |
83 EXPECT_EQ(7u, sql::test::CountTableColumns(db, "favicon_bitmaps")); | |
83 | 84 |
84 // [id], [page_url], and [icon_id]. | 85 // [id], [page_url], and [icon_id]. |
85 EXPECT_EQ(3u, sql::test::CountTableColumns(db, "icon_mapping")); | 86 EXPECT_EQ(3u, sql::test::CountTableColumns(db, "icon_mapping")); |
86 } | 87 } |
87 | 88 |
88 void VerifyDatabaseEmpty(sql::Connection* db) { | 89 void VerifyDatabaseEmpty(sql::Connection* db) { |
89 size_t rows = 0; | 90 size_t rows = 0; |
90 EXPECT_TRUE(sql::test::CountTableRows(db, "favicons", &rows)); | 91 EXPECT_TRUE(sql::test::CountTableRows(db, "favicons", &rows)); |
91 EXPECT_EQ(0u, rows); | 92 EXPECT_EQ(0u, rows); |
92 EXPECT_TRUE(sql::test::CountTableRows(db, "favicon_bitmaps", &rows)); | 93 EXPECT_TRUE(sql::test::CountTableRows(db, "favicon_bitmaps", &rows)); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 EXPECT_NE(0, id); | 207 EXPECT_NE(0, id); |
207 | 208 |
208 EXPECT_NE(0, db.AddIconMapping(url, id)); | 209 EXPECT_NE(0, db.AddIconMapping(url, id)); |
209 std::vector<IconMapping> icon_mappings; | 210 std::vector<IconMapping> icon_mappings; |
210 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings)); | 211 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mappings)); |
211 EXPECT_EQ(1u, icon_mappings.size()); | 212 EXPECT_EQ(1u, icon_mappings.size()); |
212 EXPECT_EQ(url, icon_mappings.front().page_url); | 213 EXPECT_EQ(url, icon_mappings.front().page_url); |
213 EXPECT_EQ(id, icon_mappings.front().icon_id); | 214 EXPECT_EQ(id, icon_mappings.front().icon_id); |
214 } | 215 } |
215 | 216 |
217 TEST_F(ThumbnailDatabaseTest, LastRequestedTime) { | |
218 ThumbnailDatabase db(NULL); | |
219 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
220 db.BeginTransaction(); | |
221 | |
222 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | |
223 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | |
224 | |
225 GURL url("http://google.com"); | |
226 base::Time now = base::Time::Now(); | |
227 favicon_base::FaviconID id = | |
228 db.AddFavicon(url, favicon_base::TOUCH_ICON, favicon, now, gfx::Size()); | |
229 EXPECT_NE(0, id); | |
pkotwicz
2015/03/27 17:27:33
Nit: EXPECT_NE -> ASSERT_NE
ASSERT_NE will cause t
Roger McFarlane (Chromium)
2015/03/28 00:13:29
Done.
| |
230 | |
231 // Fetching the last requested time of a non-existent bitmap should fail. | |
232 base::Time last_requested = base::Time::UnixEpoch(); | |
233 EXPECT_FALSE(db.GetFaviconBitmapLastRequestedTime(id + 1, &last_requested)); | |
234 EXPECT_EQ(last_requested, base::Time::UnixEpoch()); // Remains unchanged. | |
235 | |
236 // Fetching the last requested time of a bitmap that has no last request | |
237 // should return a null timestamp. | |
238 last_requested = base::Time::UnixEpoch(); | |
239 EXPECT_TRUE(db.GetFaviconBitmapLastRequestedTime(id, &last_requested)); | |
240 EXPECT_TRUE(last_requested.is_null()); | |
241 | |
242 // Setting the last requested time of an existing bitmap should succeed, and | |
243 // the set time should be returned by the corresponding "Get". | |
244 last_requested = base::Time::UnixEpoch(); | |
245 EXPECT_TRUE(db.SetFaviconBitmapLastRequestedTime(id, now)); | |
246 EXPECT_TRUE(db.GetFaviconBitmapLastRequestedTime(id, &last_requested)); | |
247 EXPECT_EQ(last_requested, now); | |
248 } | |
249 | |
216 TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) { | 250 TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) { |
217 ThumbnailDatabase db(NULL); | 251 ThumbnailDatabase db(NULL); |
218 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 252 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
219 db.BeginTransaction(); | 253 db.BeginTransaction(); |
220 | 254 |
221 GURL url("http://google.com"); | 255 GURL url("http://google.com"); |
222 favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); | 256 favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); |
223 | 257 |
224 EXPECT_LT(0, db.AddIconMapping(url, id)); | 258 EXPECT_LT(0, db.AddIconMapping(url, id)); |
225 std::vector<IconMapping> icon_mapping; | 259 std::vector<IconMapping> icon_mapping; |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 kBlob1)); | 774 kBlob1)); |
741 EXPECT_TRUE(CheckPageHasIcon(db.get(), | 775 EXPECT_TRUE(CheckPageHasIcon(db.get(), |
742 kPageUrl3, | 776 kPageUrl3, |
743 favicon_base::TOUCH_ICON, | 777 favicon_base::TOUCH_ICON, |
744 kIconUrl3, | 778 kIconUrl3, |
745 kLargeSize, | 779 kLargeSize, |
746 sizeof(kBlob2), | 780 sizeof(kBlob2), |
747 kBlob2)); | 781 kBlob2)); |
748 } | 782 } |
749 | 783 |
784 // Test loading version 8 database. | |
785 TEST_F(ThumbnailDatabaseTest, Version8) { | |
786 scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v8.sql"); | |
787 ASSERT_TRUE(db.get() != NULL); | |
788 VerifyTablesAndColumns(&db->db_); | |
789 | |
790 EXPECT_TRUE(CheckPageHasIcon(db.get(), | |
791 kPageUrl1, | |
792 favicon_base::FAVICON, | |
793 kIconUrl1, | |
794 kLargeSize, | |
795 sizeof(kBlob1), | |
796 kBlob1)); | |
797 EXPECT_TRUE(CheckPageHasIcon(db.get(), | |
798 kPageUrl2, | |
799 favicon_base::FAVICON, | |
800 kIconUrl2, | |
801 kLargeSize, | |
802 sizeof(kBlob2), | |
803 kBlob2)); | |
804 EXPECT_TRUE(CheckPageHasIcon(db.get(), | |
805 kPageUrl3, | |
806 favicon_base::FAVICON, | |
807 kIconUrl1, | |
808 kLargeSize, | |
809 sizeof(kBlob1), | |
810 kBlob1)); | |
811 EXPECT_TRUE(CheckPageHasIcon(db.get(), | |
812 kPageUrl3, | |
813 favicon_base::TOUCH_ICON, | |
814 kIconUrl3, | |
815 kLargeSize, | |
816 sizeof(kBlob2), | |
817 kBlob2)); | |
818 } | |
819 | |
750 TEST_F(ThumbnailDatabaseTest, Recovery) { | 820 TEST_F(ThumbnailDatabaseTest, Recovery) { |
751 // This code tests the recovery module in concert with Chromium's | 821 // This code tests the recovery module in concert with Chromium's |
752 // custom recover virtual table. Under USE_SYSTEM_SQLITE, this is | 822 // custom recover virtual table. Under USE_SYSTEM_SQLITE, this is |
753 // not available. This is detected dynamically because corrupt | 823 // not available. This is detected dynamically because corrupt |
754 // databases still need to be handled, perhaps by Raze(), and the | 824 // databases still need to be handled, perhaps by Raze(), and the |
755 // recovery module is an obvious layer to abstract that to. | 825 // recovery module is an obvious layer to abstract that to. |
756 // TODO(shess): Handle that case for real! | 826 // TODO(shess): Handle that case for real! |
757 if (!sql::Recovery::FullRecoverySupported()) | 827 if (!sql::Recovery::FullRecoverySupported()) |
758 return; | 828 return; |
759 | 829 |
760 // Create an example database. | 830 // Create an example database. |
761 { | 831 { |
762 EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v7.sql")); | 832 EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v8.sql")); |
763 | 833 |
764 sql::Connection raw_db; | 834 sql::Connection raw_db; |
765 EXPECT_TRUE(raw_db.Open(file_name_)); | 835 EXPECT_TRUE(raw_db.Open(file_name_)); |
766 VerifyTablesAndColumns(&raw_db); | 836 VerifyTablesAndColumns(&raw_db); |
767 } | 837 } |
768 | 838 |
769 // Test that the contents make sense after clean open. | 839 // Test that the contents make sense after clean open. |
770 { | 840 { |
771 ThumbnailDatabase db(NULL); | 841 ThumbnailDatabase db(NULL); |
772 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 842 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
877 favicon_base::FAVICON, | 947 favicon_base::FAVICON, |
878 kIconUrl1, | 948 kIconUrl1, |
879 kLargeSize, | 949 kLargeSize, |
880 sizeof(kBlob1), | 950 sizeof(kBlob1), |
881 kBlob1)); | 951 kBlob1)); |
882 | 952 |
883 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | 953 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
884 } | 954 } |
885 } | 955 } |
886 | 956 |
957 TEST_F(ThumbnailDatabaseTest, Recovery7) { | |
958 // This code tests the recovery module in concert with Chromium's | |
959 // custom recover virtual table. Under USE_SYSTEM_SQLITE, this is | |
960 // not available. This is detected dynamically because corrupt | |
961 // databases still need to be handled, perhaps by Raze(), and the | |
962 // recovery module is an obvious layer to abstract that to. | |
963 // TODO(shess): Handle that case for real! | |
964 if (!sql::Recovery::FullRecoverySupported()) | |
965 return; | |
966 | |
967 // Create an example database without loading into ThumbnailDatabase | |
968 // (which would upgrade it). | |
969 EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v7.sql")); | |
970 | |
971 // Corrupt the |icon_mapping.page_url| index by deleting an element | |
972 // from the backing table but not the index. | |
973 { | |
974 sql::Connection raw_db; | |
975 EXPECT_TRUE(raw_db.Open(file_name_)); | |
976 ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db)); | |
977 } | |
978 const char kIndexName[] = "icon_mapping_page_url_idx"; | |
979 const char kDeleteSql[] = | |
980 "DELETE FROM icon_mapping WHERE page_url = 'http://yahoo.com/'"; | |
981 EXPECT_TRUE( | |
982 sql::test::CorruptTableOrIndex(file_name_, kIndexName, kDeleteSql)); | |
983 | |
984 // Database should be corrupt at the SQLite level. | |
985 { | |
986 sql::Connection raw_db; | |
987 EXPECT_TRUE(raw_db.Open(file_name_)); | |
988 ASSERT_NE("ok", sql::test::IntegrityCheck(&raw_db)); | |
989 } | |
990 | |
991 // Open the database and access the corrupt index. Note that this upgrades | |
992 // the database. | |
993 { | |
994 sql::ScopedErrorIgnorer ignore_errors; | |
995 ignore_errors.IgnoreError(SQLITE_CORRUPT); | |
996 ThumbnailDatabase db(NULL); | |
997 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
998 | |
999 // Data for kPageUrl2 was deleted, but the index entry remains, | |
1000 // this will throw SQLITE_CORRUPT. The corruption handler will | |
1001 // recover the database and poison the handle, so the outer call | |
1002 // fails. | |
1003 EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL)); | |
1004 | |
1005 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | |
1006 } | |
1007 | |
1008 // Check that the database is recovered at the SQLite level. | |
1009 { | |
1010 sql::Connection raw_db; | |
1011 EXPECT_TRUE(raw_db.Open(file_name_)); | |
1012 ASSERT_EQ("ok", sql::test::IntegrityCheck(&raw_db)); | |
1013 | |
1014 // Check that the expected tables exist. | |
1015 VerifyTablesAndColumns(&raw_db); | |
1016 } | |
1017 | |
1018 // Database should also be recovered at higher levels. | |
1019 { | |
1020 ThumbnailDatabase db(NULL); | |
1021 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
1022 | |
1023 // Now this fails because there is no mapping. | |
1024 EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL)); | |
1025 | |
1026 // Other data was retained by recovery. | |
1027 EXPECT_TRUE(CheckPageHasIcon(&db, | |
1028 kPageUrl1, | |
1029 favicon_base::FAVICON, | |
1030 kIconUrl1, | |
1031 kLargeSize, | |
1032 sizeof(kBlob1), | |
1033 kBlob1)); | |
1034 } | |
1035 | |
1036 // Corrupt the database again by adjusting the header. | |
1037 EXPECT_TRUE(sql::test::CorruptSizeInHeader(file_name_)); | |
1038 | |
1039 // Database is unusable at the SQLite level. | |
1040 { | |
1041 sql::ScopedErrorIgnorer ignore_errors; | |
1042 ignore_errors.IgnoreError(SQLITE_CORRUPT); | |
1043 sql::Connection raw_db; | |
1044 EXPECT_TRUE(raw_db.Open(file_name_)); | |
1045 EXPECT_FALSE(raw_db.IsSQLValid("PRAGMA integrity_check")); | |
1046 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | |
1047 } | |
1048 | |
1049 // Database should be recovered during open. | |
1050 { | |
1051 sql::ScopedErrorIgnorer ignore_errors; | |
1052 ignore_errors.IgnoreError(SQLITE_CORRUPT); | |
1053 ThumbnailDatabase db(NULL); | |
1054 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
1055 | |
1056 EXPECT_FALSE(db.GetIconMappingsForPageURL(kPageUrl2, NULL)); | |
1057 EXPECT_TRUE(CheckPageHasIcon(&db, | |
1058 kPageUrl1, | |
1059 favicon_base::FAVICON, | |
1060 kIconUrl1, | |
1061 kLargeSize, | |
1062 sizeof(kBlob1), | |
1063 kBlob1)); | |
1064 | |
1065 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | |
1066 } | |
1067 } | |
1068 | |
887 TEST_F(ThumbnailDatabaseTest, Recovery6) { | 1069 TEST_F(ThumbnailDatabaseTest, Recovery6) { |
888 // TODO(shess): See comment at top of Recovery test. | 1070 // TODO(shess): See comment at top of Recovery test. |
889 if (!sql::Recovery::FullRecoverySupported()) | 1071 if (!sql::Recovery::FullRecoverySupported()) |
890 return; | 1072 return; |
891 | 1073 |
892 // Create an example database without loading into ThumbnailDatabase | 1074 // Create an example database without loading into ThumbnailDatabase |
893 // (which would upgrade it). | 1075 // (which would upgrade it). |
894 EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v6.sql")); | 1076 EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v6.sql")); |
895 | 1077 |
896 // Corrupt the database by adjusting the header. This form of corruption will | 1078 // Corrupt the database by adjusting the header. This form of corruption will |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1003 ThumbnailDatabase db(NULL); | 1185 ThumbnailDatabase db(NULL); |
1004 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); | 1186 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); |
1005 | 1187 |
1006 // Verify that the resulting schema is correct, whether it | 1188 // Verify that the resulting schema is correct, whether it |
1007 // involved razing the file or fixing things in place. | 1189 // involved razing the file or fixing things in place. |
1008 VerifyTablesAndColumns(&db.db_); | 1190 VerifyTablesAndColumns(&db.db_); |
1009 } | 1191 } |
1010 } | 1192 } |
1011 | 1193 |
1012 } // namespace history | 1194 } // namespace history |
OLD | NEW |