123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/metrics/unsent_log_store.h"
- #include <stddef.h>
- #include <limits>
- #include "base/base64.h"
- #include "base/hash/sha1.h"
- #include "base/rand_util.h"
- #include "base/values.h"
- #include "components/metrics/unsent_log_store_metrics_impl.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/scoped_user_pref_update.h"
- #include "components/prefs/testing_pref_service.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/zlib/google/compression_utils.h"
- namespace metrics {
- namespace {
- const char kTestPrefName[] = "TestPref";
- const char kTestMetaDataPrefName[] = "TestMetaDataPref";
- const size_t kLogCountLimit = 3;
- const size_t kLogByteLimit = 1000;
- // Compresses |log_data| and returns the result.
- std::string Compress(const std::string& log_data) {
- std::string compressed_log_data;
- EXPECT_TRUE(compression::GzipCompress(log_data, &compressed_log_data));
- return compressed_log_data;
- }
- // Generates and returns log data such that its size after compression is at
- // least |min_compressed_size|.
- std::string GenerateLogWithMinCompressedSize(size_t min_compressed_size) {
- // Since the size check is done against a compressed log, generate enough
- // data that compresses to larger than |log_size|.
- std::string rand_bytes = base::RandBytesAsString(min_compressed_size);
- while (Compress(rand_bytes).size() < min_compressed_size)
- rand_bytes.append(base::RandBytesAsString(min_compressed_size));
- std::string base64_data_for_logging;
- base::Base64Encode(rand_bytes, &base64_data_for_logging);
- SCOPED_TRACE(testing::Message()
- << "Using random data " << base64_data_for_logging);
- return rand_bytes;
- }
- class UnsentLogStoreTest : public testing::Test {
- public:
- UnsentLogStoreTest() {
- prefs_.registry()->RegisterListPref(kTestPrefName);
- prefs_.registry()->RegisterDictionaryPref(kTestMetaDataPrefName);
- }
- UnsentLogStoreTest(const UnsentLogStoreTest&) = delete;
- UnsentLogStoreTest& operator=(const UnsentLogStoreTest&) = delete;
- protected:
- TestingPrefServiceSimple prefs_;
- };
- class TestUnsentLogStoreMetrics : public UnsentLogStoreMetrics {
- public:
- TestUnsentLogStoreMetrics() = default;
- void RecordLastUnsentLogMetadataMetrics(int unsent_samples_count,
- int sent_samples_count,
- int persisted_size_in_kb) override {
- unsent_samples_count_ = unsent_samples_count;
- sent_samples_count_ = sent_samples_count;
- persisted_size_in_kb_ = persisted_size_in_kb;
- }
- int unsent_samples_count() const { return unsent_samples_count_; }
- int sent_samples_count() const { return sent_samples_count_; }
- int persisted_size_in_kb() const { return persisted_size_in_kb_; }
- private:
- int unsent_samples_count_ = 0;
- int sent_samples_count_ = 0;
- int persisted_size_in_kb_ = 0;
- };
- class TestUnsentLogStore : public UnsentLogStore {
- public:
- TestUnsentLogStore(PrefService* service, size_t min_log_bytes)
- : UnsentLogStore(std::make_unique<UnsentLogStoreMetricsImpl>(),
- service,
- kTestPrefName,
- nullptr,
- kLogCountLimit,
- min_log_bytes,
- /* max_log_size= */ 0,
- std::string()) {}
- TestUnsentLogStore(PrefService* service,
- size_t min_log_bytes,
- const std::string& signing_key)
- : UnsentLogStore(std::make_unique<UnsentLogStoreMetricsImpl>(),
- service,
- kTestPrefName,
- nullptr,
- kLogCountLimit,
- min_log_bytes,
- /* max_log_size = */ 0,
- signing_key) {}
- TestUnsentLogStore(std::unique_ptr<UnsentLogStoreMetrics> metrics,
- PrefService* service,
- size_t max_log_size)
- : UnsentLogStore(std::move(metrics),
- service,
- kTestPrefName,
- kTestMetaDataPrefName,
- kLogCountLimit,
- /* min_log_bytes= */ 1,
- max_log_size,
- std::string()) {}
- TestUnsentLogStore(const TestUnsentLogStore&) = delete;
- TestUnsentLogStore& operator=(const TestUnsentLogStore&) = delete;
- // Stages and removes the next log, while testing it's value.
- void ExpectNextLog(const std::string& expected_log) {
- StageNextLog();
- EXPECT_EQ(staged_log(), Compress(expected_log));
- DiscardStagedLog();
- }
- };
- } // namespace
- // Store and retrieve empty list_value.
- TEST_F(UnsentLogStoreTest, EmptyLogList) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- EXPECT_EQ(0U, prefs_.GetValueList(kTestPrefName).size());
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(0U, result_unsent_log_store.size());
- }
- // Store and retrieve a single log value.
- TEST_F(UnsentLogStoreTest, SingleElementLogList) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- unsent_log_store.StoreLog("Hello world!", log_metadata);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, result_unsent_log_store.size());
- // Verify that the result log matches the initial log.
- unsent_log_store.StageNextLog();
- result_unsent_log_store.StageNextLog();
- EXPECT_EQ(unsent_log_store.staged_log(),
- result_unsent_log_store.staged_log());
- EXPECT_EQ(unsent_log_store.staged_log_hash(),
- result_unsent_log_store.staged_log_hash());
- EXPECT_EQ(unsent_log_store.staged_log_signature(),
- result_unsent_log_store.staged_log_signature());
- EXPECT_EQ(unsent_log_store.staged_log_timestamp(),
- result_unsent_log_store.staged_log_timestamp());
- }
- // Store a set of logs over the length limit, but smaller than the min number of
- // bytes. This should leave the logs unchanged.
- TEST_F(UnsentLogStoreTest, LongButTinyLogList) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- size_t log_count = kLogCountLimit * 5;
- for (size_t i = 0; i < log_count; ++i)
- unsent_log_store.StoreLog("x", log_metadata);
- EXPECT_EQ(log_count, unsent_log_store.size());
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- EXPECT_EQ(log_count, unsent_log_store.size());
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(unsent_log_store.size(), result_unsent_log_store.size());
- result_unsent_log_store.ExpectNextLog("x");
- }
- // Store a set of logs over the length limit, but that doesn't reach the minimum
- // number of bytes until after passing the length limit.
- TEST_F(UnsentLogStoreTest, LongButSmallLogList) {
- size_t log_count = kLogCountLimit * 5;
- size_t log_size = 50;
- LogMetadata log_metadata;
- std::string first_kept = "First to keep";
- first_kept.resize(log_size, ' ');
- std::string blank_log = std::string(log_size, ' ');
- std::string last_kept = "Last to keep";
- last_kept.resize(log_size, ' ');
- // Set the byte limit enough to keep everything but the first two logs.
- const size_t min_log_bytes = Compress(first_kept).length() +
- Compress(last_kept).length() +
- (log_count - 4) * Compress(blank_log).length();
- TestUnsentLogStore unsent_log_store(&prefs_, min_log_bytes);
- unsent_log_store.StoreLog("one", log_metadata);
- unsent_log_store.StoreLog("two", log_metadata);
- unsent_log_store.StoreLog(first_kept, log_metadata);
- for (size_t i = unsent_log_store.size(); i < log_count - 1; ++i) {
- unsent_log_store.StoreLog(blank_log, log_metadata);
- }
- unsent_log_store.StoreLog(last_kept, log_metadata);
- size_t original_size = unsent_log_store.size();
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- // New size has been reduced.
- EXPECT_EQ(original_size - 2, unsent_log_store.size());
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- // Prefs should be the same size.
- EXPECT_EQ(unsent_log_store.size(), result_unsent_log_store.size());
- result_unsent_log_store.ExpectNextLog(last_kept);
- while (result_unsent_log_store.size() > 1) {
- result_unsent_log_store.ExpectNextLog(blank_log);
- }
- result_unsent_log_store.ExpectNextLog(first_kept);
- }
- // Store a set of logs within the length limit, but well over the minimum
- // number of bytes. This should leave the logs unchanged.
- TEST_F(UnsentLogStoreTest, ShortButLargeLogList) {
- // Make the total byte count about twice the minimum.
- size_t log_count = kLogCountLimit;
- size_t log_size = (kLogByteLimit / log_count) * 2;
- std::string log_data = GenerateLogWithMinCompressedSize(log_size);
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- for (size_t i = 0; i < log_count; ++i) {
- unsent_log_store.StoreLog(log_data, log_metadata);
- }
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- // Both have expected number of logs (original amount).
- EXPECT_EQ(kLogCountLimit, unsent_log_store.size());
- EXPECT_EQ(kLogCountLimit, result_unsent_log_store.size());
- }
- // Store a set of logs over the length limit, and over the minimum number of
- // bytes. This will trim the set of logs.
- TEST_F(UnsentLogStoreTest, LongAndLargeLogList) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- // Include twice the max number of logs.
- size_t log_count = kLogCountLimit * 2;
- // Make the total byte count about four times the minimum.
- size_t log_size = (kLogByteLimit / log_count) * 4;
- std::string target_log = "First to keep";
- target_log += GenerateLogWithMinCompressedSize(log_size);
- std::string log_data = GenerateLogWithMinCompressedSize(log_size);
- LogMetadata log_metadata;
- for (size_t i = 0; i < log_count; ++i) {
- if (i == log_count - kLogCountLimit)
- unsent_log_store.StoreLog(target_log, log_metadata);
- else
- unsent_log_store.StoreLog(log_data, log_metadata);
- }
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- // Both original log and persisted are reduced to limit.
- EXPECT_EQ(kLogCountLimit, unsent_log_store.size());
- EXPECT_EQ(kLogCountLimit, result_unsent_log_store.size());
- while (result_unsent_log_store.size() > 1) {
- result_unsent_log_store.ExpectNextLog(log_data);
- }
- result_unsent_log_store.ExpectNextLog(target_log);
- }
- // Store a set of logs over the length limit, and over the minimum number of
- // bytes. The first log will be a staged log that should be trimmed away. This
- // should make the log store not have a staged log anymore.
- TEST_F(UnsentLogStoreTest, TrimStagedLog) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- // Make each log byte count the limit.
- size_t log_size = kLogByteLimit;
- // Create a target log that will be the staged log that we want to trim away.
- std::string target_log = "First that should be trimmed";
- target_log += GenerateLogWithMinCompressedSize(log_size);
- LogMetadata log_metadata;
- unsent_log_store.StoreLog(target_log, log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_TRUE(unsent_log_store.has_staged_log());
- // Add |kLogCountLimit| additional logs.
- std::string log_data = GenerateLogWithMinCompressedSize(log_size);
- for (size_t i = 0; i < kLogCountLimit; ++i) {
- unsent_log_store.StoreLog(log_data, log_metadata);
- }
- EXPECT_EQ(kLogCountLimit + 1, unsent_log_store.size());
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- // Verify that the first log (the staged one) was trimmed away, and that the
- // log store does not consider to have any staged log anymore. The other logs
- // are not trimmed because the most recent logs are prioritized and we trim
- // until we have |kLogCountLimit| logs.
- EXPECT_EQ(kLogCountLimit, unsent_log_store.size());
- EXPECT_FALSE(unsent_log_store.has_staged_log());
- // Verify that all of the logs in the log store are not the |target_log|.
- while (unsent_log_store.size() > 0) {
- unsent_log_store.ExpectNextLog(log_data);
- }
- }
- // Verifies that when calling TrimAndPersistUnsentLogs() with
- // |overwrite_in_memory_store| set to false, the in memory log store is
- // unaffected.
- TEST_F(UnsentLogStoreTest,
- TrimAndPersistUnsentLogs_DoNotOverwriteInMemoryStore) {
- TestUnsentLogStore unsent_log_store(
- std::make_unique<UnsentLogStoreMetricsImpl>(), &prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- std::string log_data = GenerateLogWithMinCompressedSize(kLogByteLimit + 1);
- unsent_log_store.StoreLog(log_data, log_metadata);
- unsent_log_store.TrimAndPersistUnsentLogs(
- /*overwrite_in_memory_store=*/false);
- // Verify that the log store still contains the log.
- EXPECT_EQ(1U, unsent_log_store.size());
- unsent_log_store.ExpectNextLog(log_data);
- // Verify that the log was trimmed when persisted to memory.
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(0U, result_unsent_log_store.size());
- }
- // Verifies that TrimAndPersistUnsentLogs() maintains the log order.
- TEST_F(UnsentLogStoreTest, TrimAndPersistUnsentLogs_MaintainsLogOrder) {
- TestUnsentLogStore unsent_log_store(
- std::make_unique<UnsentLogStoreMetricsImpl>(), &prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- unsent_log_store.StoreLog("1", log_metadata);
- unsent_log_store.StoreLog(GenerateLogWithMinCompressedSize(kLogByteLimit + 1),
- log_metadata);
- unsent_log_store.StoreLog("2", log_metadata);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- // Verify that only the second log was trimmed (since it was over the max log
- // size), and that the log order was maintained. I.e., "2" should be the most
- // recent log, followed by "1".
- EXPECT_EQ(2U, unsent_log_store.size());
- unsent_log_store.ExpectNextLog("2");
- unsent_log_store.ExpectNextLog("1");
- // Similarly, verify that the order was also maintained in persistent memory.
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(2U, result_unsent_log_store.size());
- result_unsent_log_store.ExpectNextLog("2");
- result_unsent_log_store.ExpectNextLog("1");
- }
- // Verifies that calling TrimAndPersistUnsentLogs() clears the pref list before
- // writing the trimmed logs list.
- TEST_F(UnsentLogStoreTest, TrimAndPersistUnsentLogs_OverwritesPrefs) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- unsent_log_store.StoreLog("Hello world!", log_metadata);
- // Call TrimAndPersistUnsentLogs(). The log should not be trimmed.
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, result_unsent_log_store.size());
- // Verify that the result log matches the initial log.
- result_unsent_log_store.ExpectNextLog("Hello world!");
- // Call TrimAndPersistUnsentLogs() and load the persisted logs once again.
- // There should still only be one log.
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store2(&prefs_, kLogByteLimit);
- result_unsent_log_store2.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, result_unsent_log_store2.size());
- // Verify that the result log matches the initial log.
- result_unsent_log_store2.ExpectNextLog("Hello world!");
- }
- // Check that the store/stage/discard functions work as expected.
- TEST_F(UnsentLogStoreTest, Staging) {
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- std::string tmp;
- EXPECT_FALSE(unsent_log_store.has_staged_log());
- unsent_log_store.StoreLog("one", log_metadata);
- EXPECT_FALSE(unsent_log_store.has_staged_log());
- unsent_log_store.StoreLog("two", log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_TRUE(unsent_log_store.has_staged_log());
- EXPECT_EQ(unsent_log_store.staged_log(), Compress("two"));
- unsent_log_store.StoreLog("three", log_metadata);
- EXPECT_EQ(unsent_log_store.staged_log(), Compress("two"));
- EXPECT_EQ(unsent_log_store.size(), 3U);
- unsent_log_store.DiscardStagedLog();
- EXPECT_FALSE(unsent_log_store.has_staged_log());
- EXPECT_EQ(unsent_log_store.size(), 2U);
- unsent_log_store.StageNextLog();
- EXPECT_EQ(unsent_log_store.staged_log(), Compress("three"));
- unsent_log_store.DiscardStagedLog();
- unsent_log_store.StageNextLog();
- EXPECT_EQ(unsent_log_store.staged_log(), Compress("one"));
- unsent_log_store.DiscardStagedLog();
- EXPECT_FALSE(unsent_log_store.has_staged_log());
- EXPECT_EQ(unsent_log_store.size(), 0U);
- }
- TEST_F(UnsentLogStoreTest, DiscardOrder) {
- // Ensure that the correct log is discarded if new logs are pushed while
- // a log is staged.
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata;
- unsent_log_store.StoreLog("one", log_metadata);
- unsent_log_store.StageNextLog();
- unsent_log_store.StoreLog("two", log_metadata);
- unsent_log_store.DiscardStagedLog();
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
- result_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, result_unsent_log_store.size());
- result_unsent_log_store.ExpectNextLog("two");
- }
- TEST_F(UnsentLogStoreTest, Hashes) {
- const char kFooText[] = "foo";
- const std::string foo_hash = base::SHA1HashString(kFooText);
- LogMetadata log_metadata;
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog(kFooText, log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_EQ(Compress(kFooText), unsent_log_store.staged_log());
- EXPECT_EQ(foo_hash, unsent_log_store.staged_log_hash());
- }
- TEST_F(UnsentLogStoreTest, Signatures) {
- const char kFooText[] = "foo";
- LogMetadata log_metadata;
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog(kFooText, log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_EQ(Compress(kFooText), unsent_log_store.staged_log());
- // The expected signature as a base 64 encoded string. The value was obtained
- // by running the test with an empty expected_signature_base64 and taking the
- // actual value from the test failure message. Can be verifying by the
- // following python code:
- // import hmac, hashlib, base64
- // key = ''
- // print(base64.b64encode(
- // hmac.new(key, msg='foo', digestmod=hashlib.sha256).digest()).decode())
- std::string expected_signature_base64 =
- "DA2Y9+PZ1F5y6Id7wbEEMn77nAexjy/+ztdtgTB/H/8=";
- std::string actual_signature_base64;
- base::Base64Encode(unsent_log_store.staged_log_signature(),
- &actual_signature_base64);
- EXPECT_EQ(expected_signature_base64, actual_signature_base64);
- // Test a different key results in a different signature.
- std::string key = "secret key, don't tell anyone";
- TestUnsentLogStore unsent_log_store_different_key(&prefs_, kLogByteLimit,
- key);
- unsent_log_store_different_key.StoreLog(kFooText, log_metadata);
- unsent_log_store_different_key.StageNextLog();
- EXPECT_EQ(Compress(kFooText), unsent_log_store_different_key.staged_log());
- // Base 64 encoded signature obtained in similar fashion to previous
- // signature. To use previous python code change:
- // key = "secret key, don't tell anyone"
- expected_signature_base64 = "DV7z8wdDrjLkQrCzrXR3UjWsR3/YVM97tIhMnhUvfXM=";
- base::Base64Encode(unsent_log_store_different_key.staged_log_signature(),
- &actual_signature_base64);
- EXPECT_EQ(expected_signature_base64, actual_signature_base64);
- }
- TEST_F(UnsentLogStoreTest, StoreLogWithUserId) {
- const char foo_text[] = "foo";
- const uint64_t user_id = 12345L;
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata(absl::nullopt, user_id);
- unsent_log_store.StoreLog(foo_text, log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_EQ(Compress(foo_text), unsent_log_store.staged_log());
- EXPECT_EQ(unsent_log_store.staged_log_user_id().value(), user_id);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- // Reads persisted logs from new log store.
- TestUnsentLogStore read_unsent_log_store(&prefs_, kLogByteLimit);
- read_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, read_unsent_log_store.size());
- // Ensure that the user_id was parsed correctly.
- read_unsent_log_store.StageNextLog();
- EXPECT_EQ(user_id, read_unsent_log_store.staged_log_user_id().value());
- }
- TEST_F(UnsentLogStoreTest, StoreLogWithLargeUserId) {
- const char foo_text[] = "foo";
- const uint64_t large_user_id = std::numeric_limits<uint64_t>::max();
- TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- LogMetadata log_metadata(absl::nullopt, large_user_id);
- unsent_log_store.StoreLog(foo_text, log_metadata);
- unsent_log_store.StageNextLog();
- EXPECT_EQ(Compress(foo_text), unsent_log_store.staged_log());
- EXPECT_EQ(unsent_log_store.staged_log_user_id().value(), large_user_id);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- // Reads persisted logs from new log store.
- TestUnsentLogStore read_unsent_log_store(&prefs_, kLogByteLimit);
- read_unsent_log_store.LoadPersistedUnsentLogs();
- EXPECT_EQ(1U, read_unsent_log_store.size());
- // Ensure that the user_id was parsed correctly.
- read_unsent_log_store.StageNextLog();
- EXPECT_EQ(large_user_id, read_unsent_log_store.staged_log_user_id().value());
- }
- TEST_F(UnsentLogStoreTest, UnsentLogMetadataMetrics) {
- std::unique_ptr<TestUnsentLogStoreMetrics> metrics =
- std::make_unique<TestUnsentLogStoreMetrics>();
- TestUnsentLogStoreMetrics* m = metrics.get();
- TestUnsentLogStore unsent_log_store(std::move(metrics), &prefs_,
- kLogByteLimit * 10);
- // Prepare 4 logs.
- const char kFooText[] = "foo";
- const base::HistogramBase::Count kFooSampleCount = 3;
- // The |foobar_log| whose compressed size is over 1kb will be staged first, so
- // the persisted_size_in_kb shall be reduced by 1kb afterwards.
- std::string foobar_log = GenerateLogWithMinCompressedSize(1024);
- const base::HistogramBase::Count kFooBarSampleCount = 5;
- // The |oversize_log| shall not be persisted.
- std::string oversize_log =
- GenerateLogWithMinCompressedSize(kLogByteLimit * 10 + 1);
- const base::HistogramBase::Count kOversizeLogSampleCount = 50;
- // The log without the SampleCount will not be counted to metrics.
- const char kNoSampleLog[] = "no sample log";
- LogMetadata log_metadata_with_oversize_sample(kOversizeLogSampleCount,
- absl::nullopt);
- unsent_log_store.StoreLog(oversize_log, log_metadata_with_oversize_sample);
- LogMetadata log_metadata_with_no_sample;
- unsent_log_store.StoreLog(kNoSampleLog, log_metadata_with_no_sample);
- LogMetadata log_metadata_foo_sample(kFooSampleCount, absl::nullopt);
- unsent_log_store.StoreLog(kFooText, log_metadata_foo_sample);
- // The foobar_log will be staged first.
- LogMetadata log_metadata_foo_bar_sample(kFooBarSampleCount, absl::nullopt);
- unsent_log_store.StoreLog(foobar_log, log_metadata_foo_bar_sample);
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- unsent_log_store.RecordMetaDataMetrics();
- // The |oversize_log| was ignored, the kNoSampleLog won't be counted to
- // metrics,
- EXPECT_EQ(kFooSampleCount + kFooBarSampleCount, m->unsent_samples_count());
- EXPECT_EQ(0, m->sent_samples_count());
- EXPECT_EQ(2, m->persisted_size_in_kb());
- // Pretend to send log.
- unsent_log_store.StageNextLog();
- unsent_log_store.MarkStagedLogAsSent();
- unsent_log_store.DiscardStagedLog();
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- unsent_log_store.RecordMetaDataMetrics();
- // The |foobar_log| shall be sent.
- EXPECT_EQ(kFooSampleCount, m->unsent_samples_count());
- EXPECT_EQ(kFooBarSampleCount, m->sent_samples_count());
- EXPECT_EQ(1, m->persisted_size_in_kb());
- // Pretend |kFooText| upload failure.
- unsent_log_store.StageNextLog();
- unsent_log_store.DiscardStagedLog();
- unsent_log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
- unsent_log_store.RecordMetaDataMetrics();
- // Verify the failed upload wasn't added to the sent samples count.
- EXPECT_EQ(0, m->unsent_samples_count());
- EXPECT_EQ(kFooBarSampleCount, m->sent_samples_count());
- EXPECT_EQ(1, m->persisted_size_in_kb());
- }
- } // namespace metrics
|