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 "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/files/file_util.h" | 6 #include "base/files/file_util.h" |
7 #include "base/files/scoped_file.h" | 7 #include "base/files/scoped_file.h" |
8 #include "base/files/scoped_temp_dir.h" | 8 #include "base/files/scoped_temp_dir.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/statistics_recorder.h" | |
11 #include "base/test/histogram_tester.h" | |
10 #include "sql/connection.h" | 12 #include "sql/connection.h" |
11 #include "sql/meta_table.h" | 13 #include "sql/meta_table.h" |
14 #include "sql/proxy.h" | |
12 #include "sql/statement.h" | 15 #include "sql/statement.h" |
13 #include "sql/test/error_callback_support.h" | 16 #include "sql/test/error_callback_support.h" |
14 #include "sql/test/scoped_error_ignorer.h" | 17 #include "sql/test/scoped_error_ignorer.h" |
15 #include "sql/test/test_helpers.h" | 18 #include "sql/test/test_helpers.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "third_party/sqlite/sqlite3.h" | 20 #include "third_party/sqlite/sqlite3.h" |
18 | 21 |
22 namespace sql { | |
23 namespace test { | |
24 | |
25 // Allow a test to add a SQLite function in a scoped context. | |
26 class ScopedScalarFunction { | |
27 public: | |
28 ScopedScalarFunction(sql::Connection& db, | |
29 const char* function_name, | |
30 int args, | |
31 void (*func)(sqlite3_context*,int,sqlite3_value**)) | |
32 : db_(db.db_), function_name_(function_name) { | |
33 sql::sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8, | |
34 NULL, func, NULL, NULL, NULL); | |
35 } | |
36 ~ScopedScalarFunction() { | |
37 sql::sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8, | |
38 NULL, NULL, NULL, NULL, NULL); | |
39 } | |
40 | |
41 private: | |
42 sqlite3* db_; | |
43 const char* function_name_; | |
44 | |
45 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction); | |
46 }; | |
47 | |
48 // Allow a test to add a SQLite commit hook in a scoped context. | |
49 class ScopedCommitHook { | |
50 public: | |
51 ScopedCommitHook(sql::Connection& db, int(*func)(void*), void* arg) | |
52 : db_(db.db_) { | |
53 sql::sqlite3_commit_hook(db_, func, arg); | |
54 } | |
55 ~ScopedCommitHook() { | |
56 sql::sqlite3_commit_hook(db_, NULL, NULL); | |
57 } | |
58 | |
59 private: | |
60 sqlite3* db_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook); | |
63 }; | |
64 | |
65 } // namespace test | |
66 } // namespace sql | |
67 | |
19 namespace { | 68 namespace { |
20 | 69 |
70 // Construct an EXPECT_BETWEEN() macro. | |
71 ::testing::AssertionResult IntBetweenPredFormat(const char* expr_low, | |
72 const char* expr_target, | |
73 const char* expr_high, | |
74 int low, | |
75 int target, | |
76 int high) { | |
77 if (low <= target && target < high) | |
78 return ::testing::AssertionSuccess(); | |
79 | |
80 return ::testing::AssertionFailure() | |
81 << "Expected: (" << expr_low << ") <= (" << expr_target | |
82 << ") < (" << expr_high << "), where\n" | |
83 << expr_low << " evaluates to " << low << ",\n" | |
84 << expr_target << " evaluates to " << target << ",\n" | |
85 << expr_high << " evaluates to " << high << "."; | |
86 } | |
87 #define EXPECT_BETWEEN(low, target, high) \ | |
88 EXPECT_PRED_FORMAT3(IntBetweenPredFormat, low, target, high) | |
89 | |
90 | |
21 // Helper to return the count of items in sqlite_master. Return -1 in | 91 // Helper to return the count of items in sqlite_master. Return -1 in |
22 // case of error. | 92 // case of error. |
23 int SqliteMasterCount(sql::Connection* db) { | 93 int SqliteMasterCount(sql::Connection* db) { |
24 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; | 94 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; |
25 sql::Statement s(db->GetUniqueStatement(kMasterCount)); | 95 sql::Statement s(db->GetUniqueStatement(kMasterCount)); |
26 return s.Step() ? s.ColumnInt(0) : -1; | 96 return s.Step() ? s.ColumnInt(0) : -1; |
27 } | 97 } |
28 | 98 |
29 // Track the number of valid references which share the same pointer. | 99 // Track the number of valid references which share the same pointer. |
30 // This is used to allow testing an implicitly use-after-free case by | 100 // This is used to allow testing an implicitly use-after-free case by |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 ~ScopedUmaskSetter() { umask(old_umask_); } | 154 ~ScopedUmaskSetter() { umask(old_umask_); } |
85 private: | 155 private: |
86 mode_t old_umask_; | 156 mode_t old_umask_; |
87 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); | 157 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); |
88 }; | 158 }; |
89 #endif | 159 #endif |
90 | 160 |
91 class SQLConnectionTest : public testing::Test { | 161 class SQLConnectionTest : public testing::Test { |
92 public: | 162 public: |
93 void SetUp() override { | 163 void SetUp() override { |
164 // Any macro histograms which fire before the recorder is initialized cannot | |
165 // be tested. So this needs to be ahead of Open(). | |
166 base::StatisticsRecorder::Initialize(); | |
167 | |
94 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 168 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
95 db_path_ = temp_dir_.path().AppendASCII("SQLConnectionTest.db"); | 169 db_path_ = temp_dir_.path().AppendASCII("SQLConnectionTest.db"); |
96 ASSERT_TRUE(db_.Open(db_path_)); | 170 ASSERT_TRUE(db_.Open(db_path_)); |
97 } | 171 } |
98 | 172 |
99 void TearDown() override { db_.Close(); } | 173 void TearDown() override { db_.Close(); } |
100 | 174 |
101 sql::Connection& db() { return db_; } | 175 sql::Connection& db() { return db_; } |
102 const base::FilePath& db_path() { return db_path_; } | 176 const base::FilePath& db_path() { return db_path_; } |
103 | 177 |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 EXPECT_TRUE(db().FullIntegrityCheck(&messages)); | 972 EXPECT_TRUE(db().FullIntegrityCheck(&messages)); |
899 EXPECT_LT(1u, messages.size()); | 973 EXPECT_LT(1u, messages.size()); |
900 EXPECT_NE(kOk, messages[0]); | 974 EXPECT_NE(kOk, messages[0]); |
901 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); | 975 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
902 } | 976 } |
903 | 977 |
904 // TODO(shess): CorruptTableOrIndex could be used to produce a | 978 // TODO(shess): CorruptTableOrIndex could be used to produce a |
905 // file that would pass the quick check and fail the full check. | 979 // file that would pass the quick check and fail the full check. |
906 } | 980 } |
907 | 981 |
982 // Test Sqlite.Stats histogram for execute-oriented calls. | |
983 TEST_F(SQLConnectionTest, EventsExecute) { | |
984 // Re-open with histogram tag. | |
985 db().Close(); | |
986 db().set_histogram_tag("Test"); | |
987 ASSERT_TRUE(db().Open(db_path())); | |
988 | |
989 // Open() uses Execute() extensively, don't track those calls. | |
990 base::HistogramTester tester; | |
991 | |
992 const char kHistogramName[] = "Sqlite.Stats.Test"; | |
993 const char kGlobalHistogramName[] = "Sqlite.Stats"; | |
994 | |
995 ASSERT_TRUE(db().BeginTransaction()); | |
996 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
997 EXPECT_TRUE(db().Execute(kCreateSql)); | |
998 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')")); | |
999 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')")); | |
1000 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')")); | |
1001 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')")); | |
1002 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')")); | |
1003 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');" | |
1004 "INSERT INTO foo VALUES (16, 'text');" | |
1005 "INSERT INTO foo VALUES (17, 'text');" | |
1006 "INSERT INTO foo VALUES (18, 'text');" | |
1007 "INSERT INTO foo VALUES (19, 'text')")); | |
1008 ASSERT_TRUE(db().CommitTransaction()); | |
1009 ASSERT_TRUE(db().BeginTransaction()); | |
1010 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')")); | |
1011 db().RollbackTransaction(); | |
1012 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')")); | |
1013 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')")); | |
1014 | |
1015 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2 | |
1016 // inserts outside transaction. | |
1017 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10); | |
1018 tester.ExpectBucketCount(kGlobalHistogramName, | |
1019 sql::Connection::EVENT_EXECUTE, 10); | |
1020 | |
1021 // All of the executes, with the multi-statement inserts broken out, plus one | |
1022 // for each begin, commit, and rollback. | |
1023 tester.ExpectBucketCount(kHistogramName, | |
1024 sql::Connection::EVENT_STATEMENT_RUN, 18); | |
1025 tester.ExpectBucketCount(kGlobalHistogramName, | |
1026 sql::Connection::EVENT_STATEMENT_RUN, 18); | |
1027 | |
1028 tester.ExpectBucketCount(kHistogramName, | |
1029 sql::Connection::EVENT_STATEMENT_ROWS, 0); | |
1030 tester.ExpectBucketCount(kGlobalHistogramName, | |
1031 sql::Connection::EVENT_STATEMENT_ROWS, 0); | |
1032 tester.ExpectBucketCount(kHistogramName, | |
1033 sql::Connection::EVENT_STATEMENT_SUCCESS, 18); | |
1034 tester.ExpectBucketCount(kGlobalHistogramName, | |
1035 sql::Connection::EVENT_STATEMENT_SUCCESS, 18); | |
1036 | |
1037 // The 2 inserts outside the transaction. | |
1038 tester.ExpectBucketCount(kHistogramName, | |
1039 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2); | |
1040 tester.ExpectBucketCount(kGlobalHistogramName, | |
1041 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2); | |
1042 | |
1043 // 11 inserts inside transactions. | |
1044 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11); | |
1045 tester.ExpectBucketCount(kGlobalHistogramName, | |
1046 sql::Connection::EVENT_CHANGES, 11); | |
1047 | |
1048 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2); | |
1049 tester.ExpectBucketCount(kGlobalHistogramName, | |
1050 sql::Connection::EVENT_BEGIN, 2); | |
1051 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1); | |
1052 tester.ExpectBucketCount(kGlobalHistogramName, | |
1053 sql::Connection::EVENT_COMMIT, 1); | |
1054 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1); | |
1055 tester.ExpectBucketCount(kGlobalHistogramName, | |
1056 sql::Connection::EVENT_ROLLBACK, 1); | |
1057 } | |
1058 | |
1059 // Test Sqlite.Stats histogram for prepared statements. | |
1060 TEST_F(SQLConnectionTest, EventsStatement) { | |
1061 // Re-open with histogram tag. | |
1062 db().Close(); | |
1063 db().set_histogram_tag("Test"); | |
1064 ASSERT_TRUE(db().Open(db_path())); | |
1065 | |
1066 const char kHistogramName[] = "Sqlite.Stats.Test"; | |
1067 const char kGlobalHistogramName[] = "Sqlite.Stats"; | |
1068 | |
1069 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
1070 EXPECT_TRUE(db().Execute(kCreateSql)); | |
1071 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')")); | |
1072 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')")); | |
1073 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')")); | |
1074 | |
1075 { | |
1076 base::HistogramTester tester; | |
1077 | |
1078 { | |
1079 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo")); | |
1080 while (s.Step()) { | |
1081 } | |
1082 } | |
1083 | |
1084 tester.ExpectBucketCount(kHistogramName, | |
1085 sql::Connection::EVENT_STATEMENT_RUN, 1); | |
1086 tester.ExpectBucketCount(kGlobalHistogramName, | |
1087 sql::Connection::EVENT_STATEMENT_RUN, 1); | |
1088 tester.ExpectBucketCount(kHistogramName, | |
1089 sql::Connection::EVENT_STATEMENT_ROWS, 3); | |
1090 tester.ExpectBucketCount(kGlobalHistogramName, | |
1091 sql::Connection::EVENT_STATEMENT_ROWS, 3); | |
1092 tester.ExpectBucketCount(kHistogramName, | |
1093 sql::Connection::EVENT_STATEMENT_SUCCESS, 1); | |
1094 tester.ExpectBucketCount(kGlobalHistogramName, | |
1095 sql::Connection::EVENT_STATEMENT_SUCCESS, 1); | |
1096 } | |
1097 | |
1098 { | |
1099 base::HistogramTester tester; | |
1100 | |
1101 { | |
1102 sql::Statement s(db().GetUniqueStatement( | |
1103 "SELECT value FROM foo WHERE id > 10")); | |
1104 while (s.Step()) { | |
1105 } | |
1106 } | |
1107 | |
1108 tester.ExpectBucketCount(kHistogramName, | |
1109 sql::Connection::EVENT_STATEMENT_RUN, 1); | |
1110 tester.ExpectBucketCount(kGlobalHistogramName, | |
1111 sql::Connection::EVENT_STATEMENT_RUN, 1); | |
1112 tester.ExpectBucketCount(kHistogramName, | |
1113 sql::Connection::EVENT_STATEMENT_ROWS, 2); | |
1114 tester.ExpectBucketCount(kGlobalHistogramName, | |
1115 sql::Connection::EVENT_STATEMENT_ROWS, 2); | |
1116 tester.ExpectBucketCount(kHistogramName, | |
1117 sql::Connection::EVENT_STATEMENT_SUCCESS, 1); | |
1118 tester.ExpectBucketCount(kGlobalHistogramName, | |
1119 sql::Connection::EVENT_STATEMENT_SUCCESS, 1); | |
1120 } | |
1121 } | |
1122 | |
1123 // SQLite function to sleep for the passed number of milliseconds. | |
1124 void sqlite_sleep(sqlite3_context* context, int argc, sqlite3_value** argv) { | |
1125 int milliseconds = argc > 0 ? sqlite3_value_int(argv[0]) : 1000; | |
1126 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(milliseconds)); | |
1127 sqlite3_result_int(context, milliseconds); | |
1128 } | |
1129 | |
1130 // Sleep for a set period of time at commit. | |
1131 int sleep_commit_hook(void* arg) { | |
1132 int64 milliseconds = reinterpret_cast<int64>(arg); | |
1133 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(milliseconds)); | |
1134 return SQLITE_OK; | |
1135 } | |
1136 | |
1137 // Test Sqlite.*Time histograms. | |
1138 TEST_F(SQLConnectionTest, Times) { | |
1139 // Re-open with histogram tag. Use an in-memory database to minimize variance | |
1140 // due to filesystem. | |
1141 db().Close(); | |
1142 db().set_histogram_tag("Test"); | |
1143 ASSERT_TRUE(db().OpenInMemory()); | |
Scott Hess - ex-Googler
2015/05/21 23:42:37
I am having second thoughts about this test. I wa
rmcilroy
2015/05/22 08:48:23
Yeah I agree, I was a bit worried about these test
Scott Hess - ex-Googler
2015/05/22 21:22:14
OK, most recent patch mocks out the time source.
| |
1144 | |
1145 const char kCommitTime[] = "Sqlite.CommitTime.Test"; | |
1146 const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test"; | |
1147 const char kUpdateTime[] = "Sqlite.UpdateTime.Test"; | |
1148 const char kQueryTime[] = "Sqlite.QueryTime.Test"; | |
1149 | |
1150 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
1151 EXPECT_TRUE(db().Execute(kCreateSql)); | |
1152 | |
1153 // Function to inject pauses into statements. | |
1154 sql::test::ScopedScalarFunction scoper(db(), "millisleep", 1, sqlite_sleep); | |
1155 | |
1156 // Test that SQLite isn't just super slow. | |
1157 { | |
1158 base::HistogramTester tester; | |
1159 | |
1160 EXPECT_TRUE(db().Execute("SELECT millisleep(1)")); | |
1161 | |
1162 scoped_ptr<base::HistogramSamples> samples( | |
1163 tester.GetHistogramSamplesSinceCreation(kQueryTime)); | |
1164 ASSERT_TRUE(samples); | |
1165 EXPECT_BETWEEN(0, samples->sum(), 10); | |
1166 } | |
1167 | |
1168 // Read-only query allocates time to query, but not others. | |
1169 { | |
1170 base::HistogramTester tester; | |
1171 | |
1172 EXPECT_TRUE(db().Execute("SELECT millisleep(100)")); | |
1173 | |
1174 scoped_ptr<base::HistogramSamples> samples( | |
1175 tester.GetHistogramSamplesSinceCreation(kQueryTime)); | |
1176 ASSERT_TRUE(samples); | |
1177 EXPECT_BETWEEN(100, samples->sum(), 110); | |
1178 | |
1179 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime); | |
1180 EXPECT_TRUE(!samples || samples->sum() == 0); | |
1181 | |
1182 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime); | |
1183 EXPECT_TRUE(!samples || samples->sum() == 0); | |
1184 | |
1185 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime); | |
1186 EXPECT_TRUE(!samples || samples->sum() == 0); | |
1187 } | |
1188 | |
1189 // Autocommit query allocates time to query, update, and autocommit. | |
1190 { | |
1191 base::HistogramTester tester; | |
1192 | |
1193 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, millisleep(100))")); | |
1194 | |
1195 scoped_ptr<base::HistogramSamples> samples( | |
1196 tester.GetHistogramSamplesSinceCreation(kQueryTime)); | |
1197 ASSERT_TRUE(samples); | |
1198 EXPECT_BETWEEN(100, samples->sum(), 110); | |
1199 | |
1200 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime); | |
1201 ASSERT_TRUE(samples); | |
1202 EXPECT_BETWEEN(100, samples->sum(), 110); | |
1203 | |
1204 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime); | |
1205 EXPECT_TRUE(!samples || samples->sum() == 0); | |
1206 | |
1207 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime); | |
1208 ASSERT_TRUE(samples); | |
1209 EXPECT_BETWEEN(100, samples->sum(), 110); | |
1210 } | |
1211 | |
1212 // Explicit transaction allocates query time to query and update, and commit | |
1213 // time to all three. | |
1214 { | |
1215 base::HistogramTester tester; | |
1216 | |
1217 { | |
1218 // Make the commit slow. | |
1219 sql::test::ScopedCommitHook scoped_hook( | |
1220 db(), sleep_commit_hook, reinterpret_cast<void*>(100)); | |
1221 ASSERT_TRUE(db().BeginTransaction()); | |
1222 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, millisleep(100))")); | |
1223 EXPECT_TRUE(db().CommitTransaction()); | |
1224 } | |
1225 | |
1226 scoped_ptr<base::HistogramSamples> samples( | |
1227 tester.GetHistogramSamplesSinceCreation(kQueryTime)); | |
1228 ASSERT_TRUE(samples); | |
1229 EXPECT_BETWEEN(200, samples->sum(), 220); | |
1230 | |
1231 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime); | |
1232 ASSERT_TRUE(samples); | |
1233 EXPECT_BETWEEN(200, samples->sum(), 220); | |
1234 | |
1235 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime); | |
1236 ASSERT_TRUE(samples); | |
1237 EXPECT_BETWEEN(100, samples->sum(), 110); | |
1238 | |
1239 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime); | |
1240 EXPECT_TRUE(!samples || samples->sum() == 0); | |
1241 } | |
1242 } | |
1243 | |
908 } // namespace | 1244 } // namespace |
OLD | NEW |