Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "components/metrics/persisted_logs.h" | |
| 6 | |
| 5 #include "base/base64.h" | 7 #include "base/base64.h" |
| 6 #include "base/md5.h" | |
| 7 #include "base/prefs/pref_registry_simple.h" | 8 #include "base/prefs/pref_registry_simple.h" |
| 8 #include "base/prefs/scoped_user_pref_update.h" | 9 #include "base/prefs/scoped_user_pref_update.h" |
| 9 #include "base/prefs/testing_pref_service.h" | 10 #include "base/prefs/testing_pref_service.h" |
| 11 #include "base/rand_util.h" | |
| 10 #include "base/sha1.h" | 12 #include "base/sha1.h" |
| 11 #include "base/values.h" | 13 #include "base/values.h" |
| 12 #include "components/metrics/persisted_logs.h" | 14 #include "components/metrics/compression_utils.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 16 |
| 15 namespace metrics { | 17 namespace metrics { |
| 16 | 18 |
| 17 namespace { | 19 namespace { |
| 18 | 20 |
| 19 const char kTestPrefName[] = "TestPref"; | 21 const char kTestPrefName[] = "TestPref"; |
| 22 const char kTestOldPrefName[] = "TestPrefOld"; | |
| 20 const size_t kLogCountLimit = 3; | 23 const size_t kLogCountLimit = 3; |
| 21 const size_t kLogByteLimit = 1000; | 24 const size_t kLogByteLimit = 1000; |
| 22 | 25 |
| 26 // Compresses |log_data| and returns the result. | |
| 27 std::string Compress(const std::string& log_data) { | |
| 28 std::string compressed_log_data; | |
| 29 EXPECT_TRUE(GzipCompress(log_data, &compressed_log_data)); | |
| 30 return compressed_log_data; | |
| 31 } | |
| 32 | |
| 33 // Generates and returns log data such that its size after compression is at | |
| 34 // least |min_compressed_size|. | |
| 35 std::string GenerateLogWithMinCompressedSize(size_t min_compressed_size) { | |
| 36 // Since the size check is done against a compressed log, generate enough | |
| 37 // data that compresses to larger than |log_size|. | |
| 38 std::string rand_bytes = base::RandBytesAsString(min_compressed_size); | |
| 39 while (Compress(rand_bytes).size() < min_compressed_size) | |
| 40 rand_bytes.append(base::RandBytesAsString(min_compressed_size)); | |
| 41 std::string base64_data_for_logging; | |
| 42 base::Base64Encode(rand_bytes, &base64_data_for_logging); | |
| 43 LOG(INFO) << "Using random data " << base64_data_for_logging; | |
|
Ilya Sherman
2014/06/10 23:38:39
nit: SCOPED_TRACE is better, as it only logs the o
Alexei Svitkine (slow)
2014/06/11 00:16:27
Done.
| |
| 44 return rand_bytes; | |
| 45 } | |
| 23 | 46 |
| 24 class PersistedLogsTest : public testing::Test { | 47 class PersistedLogsTest : public testing::Test { |
| 25 public: | 48 public: |
| 26 PersistedLogsTest() { | 49 PersistedLogsTest() { |
| 27 prefs_.registry()->RegisterListPref(kTestPrefName); | 50 prefs_.registry()->RegisterListPref(kTestPrefName); |
| 51 prefs_.registry()->RegisterListPref(kTestOldPrefName); | |
| 28 } | 52 } |
| 29 | 53 |
| 30 protected: | 54 protected: |
| 31 TestingPrefServiceSimple prefs_; | 55 TestingPrefServiceSimple prefs_; |
| 32 | 56 |
| 33 private: | 57 private: |
| 34 DISALLOW_COPY_AND_ASSIGN(PersistedLogsTest); | 58 DISALLOW_COPY_AND_ASSIGN(PersistedLogsTest); |
| 35 }; | 59 }; |
| 36 | 60 |
| 37 class TestPersistedLogs : public PersistedLogs { | 61 class TestPersistedLogs : public PersistedLogs { |
| 38 public: | 62 public: |
| 39 TestPersistedLogs(PrefService* service) | 63 TestPersistedLogs(PrefService* service, size_t min_log_bytes) |
| 40 : PersistedLogs(service, kTestPrefName, kLogCountLimit, kLogByteLimit, 0) { | 64 : PersistedLogs(service, kTestPrefName, kTestOldPrefName, kLogCountLimit, |
| 41 } | 65 min_log_bytes, 0) { |
| 42 | |
| 43 // Make a copy of the string and store the copy. | |
| 44 void StoreLogCopy(std::string tmp) { | |
| 45 StoreLog(&tmp); | |
| 46 } | 66 } |
| 47 | 67 |
| 48 // Stages and removes the next log, while testing it's value. | 68 // Stages and removes the next log, while testing it's value. |
| 49 void ExpectNextLog(const std::string& expected_log) { | 69 void ExpectNextLog(const std::string& expected_log) { |
| 50 StageLog(); | 70 StageLog(); |
| 51 EXPECT_EQ(staged_log(), expected_log); | 71 EXPECT_EQ(staged_log(), Compress(expected_log)); |
| 52 DiscardStagedLog(); | 72 DiscardStagedLog(); |
| 53 } | 73 } |
| 74 | |
| 75 private: | |
| 76 DISALLOW_COPY_AND_ASSIGN(TestPersistedLogs); | |
| 54 }; | 77 }; |
| 55 | 78 |
| 56 } // namespace | 79 } // namespace |
| 57 | 80 |
| 58 // Store and retrieve empty list_value. | 81 // Store and retrieve empty list_value. |
| 59 TEST_F(PersistedLogsTest, EmptyLogList) { | 82 TEST_F(PersistedLogsTest, EmptyLogList) { |
| 60 TestPersistedLogs persisted_logs(&prefs_); | 83 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 61 | 84 |
| 62 persisted_logs.SerializeLogs(); | 85 persisted_logs.SerializeLogs(); |
| 63 const base::ListValue* list_value = prefs_.GetList(kTestPrefName); | 86 const base::ListValue* list_value = prefs_.GetList(kTestPrefName); |
| 64 EXPECT_EQ(0U, list_value->GetSize()); | 87 EXPECT_EQ(0U, list_value->GetSize()); |
| 65 | 88 |
| 66 TestPersistedLogs result_persisted_logs(&prefs_); | 89 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 67 EXPECT_EQ(PersistedLogs::LIST_EMPTY, result_persisted_logs.DeserializeLogs()); | 90 EXPECT_EQ(PersistedLogs::LIST_EMPTY, result_persisted_logs.DeserializeLogs()); |
| 68 EXPECT_EQ(0U, result_persisted_logs.size()); | 91 EXPECT_EQ(0U, result_persisted_logs.size()); |
| 69 } | 92 } |
| 70 | 93 |
| 71 // Store and retrieve a single log value. | 94 // Store and retrieve a single log value. |
| 72 TEST_F(PersistedLogsTest, SingleElementLogList) { | 95 TEST_F(PersistedLogsTest, SingleElementLogList) { |
| 73 TestPersistedLogs persisted_logs(&prefs_); | 96 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 74 | 97 |
| 75 persisted_logs.StoreLogCopy("Hello world!"); | 98 persisted_logs.StoreLog("Hello world!"); |
| 76 persisted_logs.SerializeLogs(); | 99 persisted_logs.SerializeLogs(); |
| 77 | 100 |
| 78 const base::ListValue* list_value = prefs_.GetList(kTestPrefName); | 101 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 79 // |list_value| will now contain the following: | |
| 80 // [1, Base64Encode("Hello world!"), MD5("Hello world!")]. | |
| 81 ASSERT_EQ(3U, list_value->GetSize()); | |
| 82 | |
| 83 // Examine each element. | |
| 84 base::ListValue::const_iterator it = list_value->begin(); | |
| 85 int size = 0; | |
| 86 (*it)->GetAsInteger(&size); | |
| 87 EXPECT_EQ(1, size); | |
| 88 | |
| 89 ++it; | |
| 90 std::string str; | |
| 91 (*it)->GetAsString(&str); // Base64 encoded "Hello world!" string. | |
| 92 std::string encoded; | |
| 93 base::Base64Encode("Hello world!", &encoded); | |
| 94 EXPECT_TRUE(encoded == str); | |
| 95 | |
| 96 ++it; | |
| 97 (*it)->GetAsString(&str); // MD5 for encoded "Hello world!" string. | |
| 98 EXPECT_TRUE(base::MD5String(encoded) == str); | |
| 99 | |
| 100 ++it; | |
| 101 EXPECT_TRUE(it == list_value->end()); // Reached end of list_value. | |
| 102 | |
| 103 TestPersistedLogs result_persisted_logs(&prefs_); | |
| 104 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 102 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 105 result_persisted_logs.DeserializeLogs()); | 103 result_persisted_logs.DeserializeLogs()); |
| 106 EXPECT_EQ(1U, result_persisted_logs.size()); | 104 EXPECT_EQ(1U, result_persisted_logs.size()); |
| 105 | |
| 106 // Verify that the result log matches the initial log. | |
| 107 persisted_logs.StageLog(); | |
| 108 result_persisted_logs.StageLog(); | |
| 109 EXPECT_EQ(persisted_logs.staged_log(), result_persisted_logs.staged_log()); | |
| 110 EXPECT_EQ(persisted_logs.staged_log_hash(), | |
| 111 result_persisted_logs.staged_log_hash()); | |
| 107 } | 112 } |
| 108 | 113 |
| 109 // Store a set of logs over the length limit, but smaller than the min number of | 114 // Store a set of logs over the length limit, but smaller than the min number of |
| 110 // bytes. | 115 // bytes. |
| 111 TEST_F(PersistedLogsTest, LongButTinyLogList) { | 116 TEST_F(PersistedLogsTest, LongButTinyLogList) { |
| 112 TestPersistedLogs persisted_logs(&prefs_); | 117 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 113 | 118 |
| 114 size_t log_count = kLogCountLimit * 5; | 119 size_t log_count = kLogCountLimit * 5; |
| 115 for (size_t i = 0; i < log_count; ++i) | 120 for (size_t i = 0; i < log_count; ++i) |
| 116 persisted_logs.StoreLogCopy("x"); | 121 persisted_logs.StoreLog("x"); |
| 117 | 122 |
| 118 persisted_logs.SerializeLogs(); | 123 persisted_logs.SerializeLogs(); |
| 119 | 124 |
| 120 TestPersistedLogs result_persisted_logs(&prefs_); | 125 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 121 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 126 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 122 result_persisted_logs.DeserializeLogs()); | 127 result_persisted_logs.DeserializeLogs()); |
| 123 EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size()); | 128 EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size()); |
| 124 | 129 |
| 125 result_persisted_logs.ExpectNextLog("x"); | 130 result_persisted_logs.ExpectNextLog("x"); |
| 126 } | 131 } |
| 127 | 132 |
| 128 // Store a set of logs over the length limit, but that doesn't reach the minimum | 133 // Store a set of logs over the length limit, but that doesn't reach the minimum |
| 129 // number of bytes until after passing the length limit. | 134 // number of bytes until after passing the length limit. |
| 130 TEST_F(PersistedLogsTest, LongButSmallLogList) { | 135 TEST_F(PersistedLogsTest, LongButSmallLogList) { |
| 131 TestPersistedLogs persisted_logs(&prefs_); | 136 size_t log_count = kLogCountLimit * 5; |
| 137 size_t log_size = 50; | |
| 132 | 138 |
| 133 // Make log_count logs each slightly larger than | |
| 134 // kLogByteLimit / (log_count - 2) | |
| 135 // so that the minimum is reached before the oldest (first) two logs. | |
| 136 size_t log_count = kLogCountLimit * 5; | |
| 137 size_t log_size = (kLogByteLimit / (log_count - 2)) + 2; | |
| 138 persisted_logs.StoreLogCopy("one"); | |
| 139 persisted_logs.StoreLogCopy("two"); | |
| 140 std::string first_kept = "First to keep"; | 139 std::string first_kept = "First to keep"; |
| 141 first_kept.resize(log_size, ' '); | 140 first_kept.resize(log_size, ' '); |
| 142 persisted_logs.StoreLogCopy(first_kept); | 141 |
| 143 std::string blank_log = std::string(log_size, ' '); | 142 std::string blank_log = std::string(log_size, ' '); |
| 144 for (size_t i = persisted_logs.size(); i < log_count - 1; ++i) { | 143 |
| 145 persisted_logs.StoreLogCopy(blank_log); | |
| 146 } | |
| 147 std::string last_kept = "Last to keep"; | 144 std::string last_kept = "Last to keep"; |
| 148 last_kept.resize(log_size, ' '); | 145 last_kept.resize(log_size, ' '); |
| 149 persisted_logs.StoreLogCopy(last_kept); | |
| 150 | 146 |
| 147 // Set the byte limit enough to keep everything but the first two logs. | |
| 148 const size_t min_log_bytes = | |
| 149 Compress(first_kept).length() + Compress(last_kept).length() + | |
| 150 (log_count - 4) * Compress(blank_log).length(); | |
| 151 TestPersistedLogs persisted_logs(&prefs_, min_log_bytes); | |
| 152 | |
| 153 persisted_logs.StoreLog("one"); | |
| 154 persisted_logs.StoreLog("two"); | |
| 155 persisted_logs.StoreLog(first_kept); | |
| 156 for (size_t i = persisted_logs.size(); i < log_count - 1; ++i) { | |
| 157 persisted_logs.StoreLog(blank_log); | |
| 158 } | |
| 159 persisted_logs.StoreLog(last_kept); | |
| 151 persisted_logs.SerializeLogs(); | 160 persisted_logs.SerializeLogs(); |
| 152 | 161 |
| 153 TestPersistedLogs result_persisted_logs(&prefs_); | 162 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 154 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 163 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 155 result_persisted_logs.DeserializeLogs()); | 164 result_persisted_logs.DeserializeLogs()); |
| 156 EXPECT_EQ(persisted_logs.size() - 2, result_persisted_logs.size()); | 165 EXPECT_EQ(persisted_logs.size() - 2, result_persisted_logs.size()); |
| 157 | 166 |
| 158 result_persisted_logs.ExpectNextLog(last_kept); | 167 result_persisted_logs.ExpectNextLog(last_kept); |
| 159 while (result_persisted_logs.size() > 1) { | 168 while (result_persisted_logs.size() > 1) { |
| 160 result_persisted_logs.ExpectNextLog(blank_log); | 169 result_persisted_logs.ExpectNextLog(blank_log); |
| 161 } | 170 } |
| 162 result_persisted_logs.ExpectNextLog(first_kept); | 171 result_persisted_logs.ExpectNextLog(first_kept); |
| 163 } | 172 } |
| 164 | 173 |
| 165 // Store a set of logs within the length limit, but well over the minimum | 174 // Store a set of logs within the length limit, but well over the minimum |
| 166 // number of bytes. | 175 // number of bytes. |
| 167 TEST_F(PersistedLogsTest, ShortButLargeLogList) { | 176 TEST_F(PersistedLogsTest, ShortButLargeLogList) { |
| 168 TestPersistedLogs persisted_logs(&prefs_); | |
| 169 | |
| 170 // Make the total byte count about twice the minimum. | 177 // Make the total byte count about twice the minimum. |
| 171 size_t log_count = kLogCountLimit; | 178 size_t log_count = kLogCountLimit; |
| 172 size_t log_size = (kLogByteLimit / log_count) * 2; | 179 size_t log_size = (kLogByteLimit / log_count) * 2; |
| 173 std::string blank_log = std::string(log_size, ' '); | 180 std::string log_data = GenerateLogWithMinCompressedSize(log_size); |
| 181 | |
| 182 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); | |
| 174 for (size_t i = 0; i < log_count; ++i) { | 183 for (size_t i = 0; i < log_count; ++i) { |
| 175 persisted_logs.StoreLogCopy(blank_log); | 184 persisted_logs.StoreLog(log_data); |
| 176 } | 185 } |
| 177 | |
| 178 persisted_logs.SerializeLogs(); | 186 persisted_logs.SerializeLogs(); |
| 179 | 187 |
| 180 TestPersistedLogs result_persisted_logs(&prefs_); | 188 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 181 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 189 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 182 result_persisted_logs.DeserializeLogs()); | 190 result_persisted_logs.DeserializeLogs()); |
| 183 EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size()); | 191 EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size()); |
| 184 } | 192 } |
| 185 | 193 |
| 186 // Store a set of logs over the length limit, and over the minimum number of | 194 // Store a set of logs over the length limit, and over the minimum number of |
| 187 // bytes. | 195 // bytes. |
| 188 TEST_F(PersistedLogsTest, LongAndLargeLogList) { | 196 TEST_F(PersistedLogsTest, LongAndLargeLogList) { |
| 189 TestPersistedLogs persisted_logs(&prefs_); | 197 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 190 | 198 |
| 191 // Include twice the max number of logs. | 199 // Include twice the max number of logs. |
| 192 size_t log_count = kLogCountLimit * 2; | 200 size_t log_count = kLogCountLimit * 2; |
| 193 // Make the total byte count about four times the minimum. | 201 // Make the total byte count about four times the minimum. |
| 194 size_t log_size = (kLogByteLimit / log_count) * 4; | 202 size_t log_size = (kLogByteLimit / log_count) * 4; |
| 203 | |
| 195 std::string target_log = "First to keep"; | 204 std::string target_log = "First to keep"; |
| 196 target_log.resize(log_size, ' '); | 205 target_log += GenerateLogWithMinCompressedSize(log_size); |
| 197 std::string blank_log = std::string(log_size, ' '); | 206 |
| 207 std::string log_data = GenerateLogWithMinCompressedSize(log_size); | |
| 198 for (size_t i = 0; i < log_count; ++i) { | 208 for (size_t i = 0; i < log_count; ++i) { |
| 199 if (i == log_count - kLogCountLimit) | 209 if (i == log_count - kLogCountLimit) |
| 200 persisted_logs.StoreLogCopy(target_log); | 210 persisted_logs.StoreLog(target_log); |
| 201 else | 211 else |
| 202 persisted_logs.StoreLogCopy(blank_log); | 212 persisted_logs.StoreLog(log_data); |
| 203 } | 213 } |
| 204 | 214 |
| 205 persisted_logs.SerializeLogs(); | 215 persisted_logs.SerializeLogs(); |
| 206 | 216 |
| 207 TestPersistedLogs result_persisted_logs(&prefs_); | 217 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 208 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 218 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 209 result_persisted_logs.DeserializeLogs()); | 219 result_persisted_logs.DeserializeLogs()); |
| 210 EXPECT_EQ(kLogCountLimit, result_persisted_logs.size()); | 220 EXPECT_EQ(kLogCountLimit, result_persisted_logs.size()); |
| 211 | 221 |
| 212 while (result_persisted_logs.size() > 1) { | 222 while (result_persisted_logs.size() > 1) { |
| 213 result_persisted_logs.ExpectNextLog(blank_log); | 223 result_persisted_logs.ExpectNextLog(log_data); |
| 214 } | 224 } |
| 215 result_persisted_logs.ExpectNextLog(target_log); | 225 result_persisted_logs.ExpectNextLog(target_log); |
| 216 } | 226 } |
| 217 | 227 |
| 218 // Induce LIST_SIZE_TOO_SMALL corruption | |
| 219 TEST_F(PersistedLogsTest, SmallRecoveredListSize) { | |
| 220 TestPersistedLogs persisted_logs(&prefs_); | |
| 221 | |
| 222 persisted_logs.StoreLogCopy("Hello world!"); | |
| 223 | |
| 224 persisted_logs.SerializeLogs(); | |
| 225 | |
| 226 { | |
| 227 ListPrefUpdate update(&prefs_, kTestPrefName); | |
| 228 base::ListValue* list_value = update.Get(); | |
| 229 EXPECT_EQ(3U, list_value->GetSize()); | |
| 230 | |
| 231 // Remove last element. | |
| 232 list_value->Remove(list_value->GetSize() - 1, NULL); | |
| 233 EXPECT_EQ(2U, list_value->GetSize()); | |
| 234 } | |
| 235 | |
| 236 TestPersistedLogs result_persisted_logs(&prefs_); | |
| 237 EXPECT_EQ(PersistedLogs::LIST_SIZE_TOO_SMALL, | |
| 238 result_persisted_logs.DeserializeLogs()); | |
| 239 } | |
| 240 | |
| 241 // Remove size from the stored list_value. | |
| 242 TEST_F(PersistedLogsTest, RemoveSizeFromLogList) { | |
| 243 TestPersistedLogs persisted_logs(&prefs_); | |
| 244 | |
| 245 persisted_logs.StoreLogCopy("one"); | |
| 246 persisted_logs.StoreLogCopy("two"); | |
| 247 EXPECT_EQ(2U, persisted_logs.size()); | |
| 248 | |
| 249 persisted_logs.SerializeLogs(); | |
| 250 | |
| 251 { | |
| 252 ListPrefUpdate update(&prefs_, kTestPrefName); | |
| 253 base::ListValue* list_value = update.Get(); | |
| 254 EXPECT_EQ(4U, list_value->GetSize()); | |
| 255 | |
| 256 list_value->Remove(0, NULL); // Delete size (1st element). | |
| 257 EXPECT_EQ(3U, list_value->GetSize()); | |
| 258 } | |
| 259 | |
| 260 TestPersistedLogs result_persisted_logs(&prefs_); | |
| 261 EXPECT_EQ(PersistedLogs::LIST_SIZE_MISSING, | |
| 262 result_persisted_logs.DeserializeLogs()); | |
| 263 } | |
| 264 | |
| 265 // Corrupt size of stored list_value. | |
| 266 TEST_F(PersistedLogsTest, CorruptSizeOfLogList) { | |
| 267 TestPersistedLogs persisted_logs(&prefs_); | |
| 268 | |
| 269 persisted_logs.StoreLogCopy("Hello world!"); | |
| 270 | |
| 271 persisted_logs.SerializeLogs(); | |
| 272 | |
| 273 { | |
| 274 ListPrefUpdate update(&prefs_, kTestPrefName); | |
| 275 base::ListValue* list_value = update.Get(); | |
| 276 EXPECT_EQ(3U, list_value->GetSize()); | |
| 277 | |
| 278 // Change list_value size from 1 to 2. | |
| 279 EXPECT_TRUE(list_value->Set(0, base::Value::CreateIntegerValue(2))); | |
| 280 EXPECT_EQ(3U, list_value->GetSize()); | |
| 281 } | |
| 282 | |
| 283 TestPersistedLogs result_persisted_logs(&prefs_); | |
| 284 EXPECT_EQ(PersistedLogs::LIST_SIZE_CORRUPTION, | |
| 285 result_persisted_logs.DeserializeLogs()); | |
| 286 } | |
| 287 | |
| 288 // Corrupt checksum of stored list_value. | |
| 289 TEST_F(PersistedLogsTest, CorruptChecksumOfLogList) { | |
| 290 TestPersistedLogs persisted_logs(&prefs_); | |
| 291 | |
| 292 persisted_logs.StoreLogCopy("Hello world!"); | |
| 293 | |
| 294 persisted_logs.SerializeLogs(); | |
| 295 | |
| 296 { | |
| 297 ListPrefUpdate update(&prefs_, kTestPrefName); | |
| 298 base::ListValue* list_value = update.Get(); | |
| 299 EXPECT_EQ(3U, list_value->GetSize()); | |
| 300 | |
| 301 // Fetch checksum (last element) and change it. | |
| 302 std::string checksum; | |
| 303 EXPECT_TRUE((*(list_value->end() - 1))->GetAsString(&checksum)); | |
| 304 checksum[0] = (checksum[0] == 'a') ? 'b' : 'a'; | |
| 305 EXPECT_TRUE(list_value->Set(2, base::Value::CreateStringValue(checksum))); | |
| 306 EXPECT_EQ(3U, list_value->GetSize()); | |
| 307 } | |
| 308 | |
| 309 TestPersistedLogs result_persisted_logs(&prefs_); | |
| 310 EXPECT_EQ(PersistedLogs::CHECKSUM_CORRUPTION, | |
| 311 result_persisted_logs.DeserializeLogs()); | |
| 312 } | |
| 313 | |
| 314 // Check that the store/stage/discard functions work as expected. | 228 // Check that the store/stage/discard functions work as expected. |
| 315 TEST_F(PersistedLogsTest, Staging) { | 229 TEST_F(PersistedLogsTest, Staging) { |
| 316 TestPersistedLogs persisted_logs(&prefs_); | 230 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 317 std::string tmp; | 231 std::string tmp; |
| 318 | 232 |
| 319 EXPECT_FALSE(persisted_logs.has_staged_log()); | 233 EXPECT_FALSE(persisted_logs.has_staged_log()); |
| 320 persisted_logs.StoreLogCopy("one"); | 234 persisted_logs.StoreLog("one"); |
| 321 EXPECT_FALSE(persisted_logs.has_staged_log()); | 235 EXPECT_FALSE(persisted_logs.has_staged_log()); |
| 322 persisted_logs.StoreLogCopy("two"); | 236 persisted_logs.StoreLog("two"); |
| 323 persisted_logs.StageLog(); | 237 persisted_logs.StageLog(); |
| 324 EXPECT_TRUE(persisted_logs.has_staged_log()); | 238 EXPECT_TRUE(persisted_logs.has_staged_log()); |
| 325 EXPECT_EQ(persisted_logs.staged_log(), std::string("two")); | 239 EXPECT_EQ(persisted_logs.staged_log(), Compress("two")); |
| 326 persisted_logs.StoreLogCopy("three"); | 240 persisted_logs.StoreLog("three"); |
| 327 EXPECT_EQ(persisted_logs.staged_log(), std::string("two")); | 241 EXPECT_EQ(persisted_logs.staged_log(), Compress("two")); |
| 328 EXPECT_EQ(persisted_logs.size(), 2U); | 242 EXPECT_EQ(persisted_logs.size(), 2U); |
| 329 persisted_logs.DiscardStagedLog(); | 243 persisted_logs.DiscardStagedLog(); |
| 330 EXPECT_FALSE(persisted_logs.has_staged_log()); | 244 EXPECT_FALSE(persisted_logs.has_staged_log()); |
| 331 EXPECT_EQ(persisted_logs.size(), 2U); | 245 EXPECT_EQ(persisted_logs.size(), 2U); |
| 332 persisted_logs.StageLog(); | 246 persisted_logs.StageLog(); |
| 333 EXPECT_EQ(persisted_logs.staged_log(), std::string("three")); | 247 EXPECT_EQ(persisted_logs.staged_log(), Compress("three")); |
| 334 persisted_logs.DiscardStagedLog(); | 248 persisted_logs.DiscardStagedLog(); |
| 335 persisted_logs.StageLog(); | 249 persisted_logs.StageLog(); |
| 336 EXPECT_EQ(persisted_logs.staged_log(), std::string("one")); | 250 EXPECT_EQ(persisted_logs.staged_log(), Compress("one")); |
| 337 persisted_logs.DiscardStagedLog(); | 251 persisted_logs.DiscardStagedLog(); |
| 338 EXPECT_FALSE(persisted_logs.has_staged_log()); | 252 EXPECT_FALSE(persisted_logs.has_staged_log()); |
| 339 EXPECT_EQ(persisted_logs.size(), 0U); | 253 EXPECT_EQ(persisted_logs.size(), 0U); |
| 340 } | 254 } |
| 341 | 255 |
| 342 TEST_F(PersistedLogsTest, ProvisionalStoreStandardFlow) { | 256 TEST_F(PersistedLogsTest, ProvisionalStoreStandardFlow) { |
| 343 // Ensure that provisional store works, and discards the correct log. | 257 // Ensure that provisional store works, and discards the correct log. |
| 344 TestPersistedLogs persisted_logs(&prefs_); | 258 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 345 | 259 |
| 346 persisted_logs.StoreLogCopy("one"); | 260 persisted_logs.StoreLog("one"); |
| 347 persisted_logs.StageLog(); | 261 persisted_logs.StageLog(); |
| 348 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); | 262 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); |
| 349 persisted_logs.StoreLogCopy("two"); | 263 persisted_logs.StoreLog("two"); |
| 350 persisted_logs.DiscardLastProvisionalStore(); | 264 persisted_logs.DiscardLastProvisionalStore(); |
| 351 persisted_logs.SerializeLogs(); | 265 persisted_logs.SerializeLogs(); |
| 352 | 266 |
| 353 TestPersistedLogs result_persisted_logs(&prefs_); | 267 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 354 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 268 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 355 result_persisted_logs.DeserializeLogs()); | 269 result_persisted_logs.DeserializeLogs()); |
| 356 EXPECT_EQ(1U, result_persisted_logs.size()); | 270 EXPECT_EQ(1U, result_persisted_logs.size()); |
| 357 result_persisted_logs.ExpectNextLog("two"); | 271 result_persisted_logs.ExpectNextLog("two"); |
| 358 } | 272 } |
| 359 | 273 |
| 360 TEST_F(PersistedLogsTest, ProvisionalStoreNoop1) { | 274 TEST_F(PersistedLogsTest, ProvisionalStoreNoop1) { |
| 361 // Ensure that trying to drop a sent log is a no-op, even if another log has | 275 // Ensure that trying to drop a sent log is a no-op, even if another log has |
| 362 // since been staged. | 276 // since been staged. |
| 363 TestPersistedLogs persisted_logs(&prefs_); | 277 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 364 persisted_logs.DeserializeLogs(); | 278 persisted_logs.DeserializeLogs(); |
| 365 persisted_logs.StoreLogCopy("one"); | 279 persisted_logs.StoreLog("one"); |
| 366 persisted_logs.StageLog(); | 280 persisted_logs.StageLog(); |
| 367 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); | 281 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); |
| 368 persisted_logs.StageLog(); | 282 persisted_logs.StageLog(); |
| 369 persisted_logs.DiscardStagedLog(); | 283 persisted_logs.DiscardStagedLog(); |
| 370 persisted_logs.StoreLogCopy("two"); | 284 persisted_logs.StoreLog("two"); |
| 371 persisted_logs.StageLog(); | 285 persisted_logs.StageLog(); |
| 372 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE); | 286 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE); |
| 373 persisted_logs.DiscardLastProvisionalStore(); | 287 persisted_logs.DiscardLastProvisionalStore(); |
| 374 persisted_logs.SerializeLogs(); | 288 persisted_logs.SerializeLogs(); |
| 375 | 289 |
| 376 TestPersistedLogs result_persisted_logs(&prefs_); | 290 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 377 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 291 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 378 result_persisted_logs.DeserializeLogs()); | 292 result_persisted_logs.DeserializeLogs()); |
| 379 EXPECT_EQ(1U, result_persisted_logs.size()); | 293 EXPECT_EQ(1U, result_persisted_logs.size()); |
| 380 result_persisted_logs.ExpectNextLog("two"); | 294 result_persisted_logs.ExpectNextLog("two"); |
| 381 } | 295 } |
| 382 | 296 |
| 383 TEST_F(PersistedLogsTest, ProvisionalStoreNoop2) { | 297 TEST_F(PersistedLogsTest, ProvisionalStoreNoop2) { |
| 384 // Ensure that trying to drop more than once is a no-op | 298 // Ensure that trying to drop more than once is a no-op |
| 385 TestPersistedLogs persisted_logs(&prefs_); | 299 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 386 persisted_logs.DeserializeLogs(); | 300 persisted_logs.DeserializeLogs(); |
| 387 persisted_logs.StoreLogCopy("one"); | 301 persisted_logs.StoreLog("one"); |
| 388 persisted_logs.StageLog(); | 302 persisted_logs.StageLog(); |
| 389 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE); | 303 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE); |
| 390 persisted_logs.StoreLogCopy("two"); | 304 persisted_logs.StoreLog("two"); |
| 391 persisted_logs.StageLog(); | 305 persisted_logs.StageLog(); |
| 392 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); | 306 persisted_logs.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE); |
| 393 persisted_logs.DiscardLastProvisionalStore(); | 307 persisted_logs.DiscardLastProvisionalStore(); |
| 394 persisted_logs.DiscardLastProvisionalStore(); | 308 persisted_logs.DiscardLastProvisionalStore(); |
| 395 persisted_logs.SerializeLogs(); | 309 persisted_logs.SerializeLogs(); |
| 396 | 310 |
| 397 TestPersistedLogs result_persisted_logs(&prefs_); | 311 TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit); |
| 398 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, | 312 EXPECT_EQ(PersistedLogs::RECALL_SUCCESS, |
| 399 result_persisted_logs.DeserializeLogs()); | 313 result_persisted_logs.DeserializeLogs()); |
| 400 EXPECT_EQ(1U, result_persisted_logs.size()); | 314 EXPECT_EQ(1U, result_persisted_logs.size()); |
| 401 result_persisted_logs.ExpectNextLog("one"); | 315 result_persisted_logs.ExpectNextLog("one"); |
| 402 } | 316 } |
| 403 | 317 |
| 404 TEST_F(PersistedLogsTest, Hashes) { | 318 TEST_F(PersistedLogsTest, Encoding) { |
| 405 const char kFooText[] = "foo"; | 319 const char kFooText[] = "foo"; |
| 406 const std::string foo_hash = base::SHA1HashString(kFooText); | 320 const std::string foo_hash = base::SHA1HashString(kFooText); |
| 407 TestingPrefServiceSimple prefs_; | 321 |
| 408 prefs_.registry()->RegisterListPref(kTestPrefName); | 322 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit); |
| 409 TestPersistedLogs persisted_logs(&prefs_); | 323 persisted_logs.StoreLog(kFooText); |
| 410 persisted_logs.StoreLogCopy(kFooText); | |
| 411 persisted_logs.StageLog(); | 324 persisted_logs.StageLog(); |
| 325 | |
| 326 EXPECT_EQ(Compress(kFooText), persisted_logs.staged_log()); | |
| 412 EXPECT_EQ(foo_hash, persisted_logs.staged_log_hash()); | 327 EXPECT_EQ(foo_hash, persisted_logs.staged_log_hash()); |
| 413 } | 328 } |
| 414 | 329 |
| 415 } // namespace metrics | 330 } // namespace metrics |
| OLD | NEW |