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