// Copyright 2019 The Fuchsia 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 "src/local_aggregation/aggregate_store.h"

#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <gtest/gtest.h>

#include "src/lib/util/clock.h"
#include "src/lib/util/datetime_util.h"
#include "src/lib/util/not_null.h"
#include "src/lib/util/proto_util.h"
#include "src/lib/util/testing/test_with_files.h"
#include "src/local_aggregation/aggregation_utils.h"
#include "src/local_aggregation/event_aggregator_mgr.h"
#include "src/local_aggregation/test_utils/test_event_aggregator_mgr.h"
#include "src/logger/logger_test_utils.h"
#include "src/logger/testing_constants.h"
#include "src/pb/event.pb.h"
#include "src/pb/metadata_builder.h"
#include "src/public/lib/registry_identifiers.h"
#include "src/registry/packed_event_codes.h"
#include "src/registry/project_configs.h"
#include "src/system_data/fake_system_data.h"

namespace cobalt {

using config::PackEventCodes;
using encoder::ClientSecret;
using logger::Encoder;
using logger::EventRecord;
using logger::MetricReportId;
using logger::ObservationWriter;
using logger::ProjectContext;
using logger::testing::CheckPerDeviceNumericObservations;
using logger::testing::CheckUniqueActivesObservations;
using logger::testing::ExpectedAggregationParams;
using logger::testing::ExpectedPerDeviceNumericObservations;
using logger::testing::ExpectedReportParticipationObservations;
using logger::testing::ExpectedUniqueActivesObservations;
using logger::testing::FakeObservationStore;
using logger::testing::FetchAggregatedObservations;
using logger::testing::GetTestProject;
using logger::testing::MakeAggregationKey;
using logger::testing::MakeExpectedReportParticipationObservations;
using logger::testing::MakeNullExpectedUniqueActivesObservations;
using logger::testing::TestUpdateRecipient;
using util::EncryptedMessageMaker;
using util::IncrementingSteadyClock;
using util::IncrementingSystemClock;
using util::SerializeToBase64;
using util::TimeToDayIndex;

namespace local_aggregation {

namespace {
// Number of seconds in a day
constexpr int kDay = 60 * 60 * 24;
// Number of seconds in an ideal year
constexpr int kYear = kDay * 365;

template <typename T>
std::string SerializeAsStringDeterministic(const T& message) {
  std::string s;
  {
    google::protobuf::io::StringOutputStream output(&s);
    google::protobuf::io::CodedOutputStream out(&output);
    out.SetSerializationDeterministic(true);
    message.SerializePartialToCodedStream(&out);
  }
  return s;
}

constexpr uint32_t kTestCustomerId = 34;
constexpr uint32_t kTestProjectId = 123;
constexpr uint32_t kTestMetricId = 1;
constexpr uint32_t kTestReportId = 3;
const lib::ReportIdentifier kTestReportIdentifier = lib::CustomerIdentifier(kTestCustomerId)
                                                        .ForProject(kTestProjectId)
                                                        .ForMetric(kTestMetricId)
                                                        .ForReport(kTestReportId);
constexpr uint64_t kTestEventCode = 1;
constexpr uint32_t kTestDayIndex = 56;
constexpr size_t kTestBackfillDays = 3;

// A map keyed by base64-encoded, serialized ReportAggregationKeys. The value at
// a key is a map of event codes to sets of day indices. Used in tests as
// a record, external to the LocalAggregateStore, of the activity logged for
// UNIQUE_N_DAY_ACTIVES reports.
using LoggedActivity = std::map<std::string, std::map<uint32_t, std::set<uint32_t>>>;

// A map used in tests as a record, external to the LocalAggregateStore, of the
// activity logged for PER_DEVICE_NUMERIC_STATS reports. The keys are, in
// descending order, serialized ReportAggregationKeys, components, event codes,
// and day indices. Each day index maps to a vector of numeric values that were
// logged for that day index..
using LoggedValues =
    std::map<std::string,
             std::map<std::string, std::map<uint32_t, std::map<uint32_t, std::vector<int64_t>>>>>;

std::unique_ptr<ProjectContext> GetProjectContextFor(const MetricDefinition& metric) {
  auto project_config = std::make_unique<ProjectConfig>();
  project_config->set_project_name("test_project");
  project_config->set_project_id(metric.project_id());
  *project_config->add_metrics() = metric;
  return std::make_unique<ProjectContext>(metric.customer_id(), "test_customer",
                                          std::move(project_config));
}

MetricDefinition GetMetricWithId(lib::MetricIdentifier metric) {
  MetricDefinition metric_definition;
  metric_definition.set_metric_name("test_metric");
  metric_definition.set_id(metric.metric_id());
  metric_definition.set_customer_id(metric.customer_id());
  metric_definition.set_project_id(metric.project_id());
  return metric_definition;
}

MetricDefinition GetEventOccurredMetric(lib::MetricIdentifier metric_id) {
  MetricDefinition metric_definition = GetMetricWithId(metric_id);
  metric_definition.set_metric_type(MetricDefinition::EVENT_OCCURRED);
  return metric_definition;
}

MetricDefinition GetEventCountMetric(lib::MetricIdentifier metric_id) {
  MetricDefinition metric_definition = GetMetricWithId(metric_id);
  metric_definition.set_metric_type(MetricDefinition::EVENT_COUNT);
  return metric_definition;
}

std::tuple<MetricDefinition, ReportDefinition> GetUniqueActivesMetricAndReport(
    lib::ReportIdentifier report_id) {
  ReportDefinition report_definition;
  report_definition.set_report_name("test_unique_actives_report");
  report_definition.set_id(report_id.report_id());
  report_definition.set_report_type(ReportDefinition::UNIQUE_N_DAY_ACTIVES);
  *report_definition.add_aggregation_window() = MakeDayWindow(1);

  MetricDefinition metric_definition = GetEventOccurredMetric(report_id.metric());
  *metric_definition.add_reports() = report_definition;

  return std::make_tuple(metric_definition, report_definition);
}

std::tuple<MetricDefinition, ReportDefinition> GetPerDeviceNumericStatsMetricAndReport(
    lib::ReportIdentifier report_id, ReportDefinition::OnDeviceAggregationType aggregation_type) {
  ReportDefinition report_definition;
  report_definition.set_report_name("test_per_device_numeric_stats_report");
  report_definition.set_id(report_id.report_id());
  report_definition.set_report_type(ReportDefinition::PER_DEVICE_NUMERIC_STATS);
  report_definition.set_aggregation_type(aggregation_type);
  *report_definition.add_aggregation_window() = MakeDayWindow(1);

  MetricDefinition metric_definition = GetEventCountMetric(report_id.metric());
  *metric_definition.add_reports() = report_definition;

  return std::make_tuple(metric_definition, report_definition);
}

std::tuple<MetricDefinition, ReportDefinition> GetNotLocallyAggregatedMetricAndReport(
    lib::ReportIdentifier report) {
  ReportDefinition report_definition;
  report_definition.set_report_name("test_report");
  report_definition.set_id(report.report_id());
  report_definition.set_report_type(ReportDefinition::SIMPLE_OCCURRENCE_COUNT);
  *report_definition.add_aggregation_window() = MakeDayWindow(1);

  MetricDefinition metric_definition = GetEventOccurredMetric(report.metric());
  *metric_definition.add_reports() = report_definition;

  return std::make_tuple(metric_definition, report_definition);
}

}  // namespace

// AggregateStoreTest creates an EventAggregator which sends its Observations
// to a FakeObservationStore. The EventAggregator is not pre-populated with
// aggregation configurations.
class AggregateStoreTest : public util::testing::TestWithFiles {
 protected:
  void SetUp() override {
    MakeTestFolder();
    observation_store_ = std::make_unique<FakeObservationStore>();
    update_recipient_ = std::make_unique<TestUpdateRecipient>();
    observation_encrypter_ = EncryptedMessageMaker::MakeUnencrypted();
    observation_writer_ = std::make_unique<ObservationWriter>(
        *observation_store_, update_recipient_.get(), observation_encrypter_.get());
    ResetEventAggregator();
  }

  void ResetEventAggregator() {
    // Pass this clock to the EventAggregator::Start method, if it is called.
    test_clock_ = std::make_unique<IncrementingSystemClock>(std::chrono::system_clock::duration(0));
    // Some tests generate observations for CurrentDayIndex() - kTestBackfillDays.
    test_clock_->set_time(std::chrono::system_clock::time_point(
        std::chrono::seconds(10ul * kYear - kTestBackfillDays * kDay)));
    // Use this to advance the clock in the tests.
    unowned_test_clock_ = test_clock_.get();
    validated_clock_ = std::make_unique<util::FakeValidatedClock>(test_clock_.get());
    validated_clock_->SetAccurate(true);
    metadata_builder_ = std::make_unique<MetadataBuilder>(system_data_, validated_clock_.get(),
                                                          system_data_cache_path(), fs());
    metadata_builder_->SnapshotSystemData();
    // Initialize it to 10 years after the beginning of time.
    test_clock_->set_time(std::chrono::system_clock::time_point(std::chrono::seconds(10 * kYear)));
    encoder_ = std::make_unique<Encoder>(ClientSecret::GenerateNewSecret(), *metadata_builder_);

    CobaltConfig cfg = {.client_secret = system_data::ClientSecret::GenerateNewSecret()};

    cfg.local_aggregation_backfill_days = 0;
    cfg.local_aggregate_proto_store_path = aggregate_store_path();
    cfg.obs_history_proto_store_path = obs_history_path();

    event_aggregator_mgr_ = std::make_unique<TestEventAggregatorManager>(
        cfg, fs(), *encoder_, *observation_writer_, *metadata_builder_);
    day_store_created_ = CurrentDayIndex();
    test_steady_clock_ = new IncrementingSteadyClock(std::chrono::system_clock::duration(0));
    event_aggregator_mgr_->SetSteadyClock(util::TESTONLY_TakeRawPointer(test_steady_clock_));
  }

  // Destruct the EventAggregator (thus calling EventAggregator::ShutDown())
  // before destructing the objects which the EventAggregator points to but does
  // not own.
  void TearDown() override { event_aggregator_mgr_.reset(); }

  // Advances |test_clock_| by |num_seconds| seconds.
  void AdvanceClock(int num_seconds) {
    unowned_test_clock_->increment_by(std::chrono::seconds(num_seconds));
    test_steady_clock_->increment_by(std::chrono::seconds(num_seconds));
  }

  // Returns the day index of the current day according to |test_clock_|, in
  // |time_zone|, without incrementing the clock.
  uint32_t CurrentDayIndex(MetricDefinition::TimeZonePolicy time_zone = MetricDefinition::UTC) {
    return TimeToDayIndex(std::chrono::system_clock::to_time_t(unowned_test_clock_->peek_now()),
                          time_zone);
  }

  size_t GetBackfillDays() { return event_aggregator_mgr_->aggregate_store_.backfill_days_; }

  void SetBackfillDays(size_t num_days) {
    event_aggregator_mgr_->aggregate_store_.backfill_days_ = num_days;
  }

  Status BackUpLocalAggregateStore() {
    return event_aggregator_mgr_->aggregate_store_.BackUpLocalAggregateStore();
  }

  Status BackUpObservationHistory() {
    return event_aggregator_mgr_->aggregate_store_.BackUpObservationHistory();
  }

  static LocalAggregateStore MakeNewLocalAggregateStore(
      uint32_t version = kCurrentLocalAggregateStoreVersion) {
    return AggregateStore::MakeNewLocalAggregateStore(version);
  }

  static AggregatedObservationHistoryStore MakeNewObservationHistoryStore(
      uint32_t version = kCurrentObservationHistoryStoreVersion) {
    return AggregateStore::MakeNewObservationHistoryStore(version);
  }

  static Status MaybeUpgradeLocalAggregateStore(LocalAggregateStore* store) {
    return AggregateStore::MaybeUpgradeLocalAggregateStore(store);
  }

  static Status MaybeUpgradeObservationHistoryStore(AggregatedObservationHistoryStore* store) {
    return AggregateStore::MaybeUpgradeObservationHistoryStore(store);
  }

  LocalAggregateStore CopyLocalAggregateStore() {
    return event_aggregator_mgr_->aggregate_store_.CopyLocalAggregateStore();
  }

  Status GenerateObservations(uint32_t final_day_index_utc, uint32_t final_day_index_local = 0u) {
    return event_aggregator_mgr_->aggregate_store_.GenerateObservations(final_day_index_utc,
                                                                        final_day_index_local);
  }

  bool IsReportInStore(lib::ReportIdentifier report) {
    std::string key;
    ReportAggregationKey key_data;
    key_data.set_customer_id(report.customer_id());
    key_data.set_project_id(report.project_id());
    key_data.set_metric_id(report.metric_id());
    key_data.set_report_id(report.report_id());
    SerializeToBase64(key_data, &key);

    auto locked = event_aggregator_mgr_->aggregate_store_.protected_aggregate_store_.lock();
    return locked->local_aggregate_store.by_report_key().count(key) > 0;
  }

  bool IsActive(lib::ReportIdentifier report, uint64_t event_code, uint32_t day_index) {
    std::string key;
    ReportAggregationKey key_data;
    key_data.set_customer_id(report.customer_id());
    key_data.set_project_id(report.project_id());
    key_data.set_metric_id(report.metric_id());
    key_data.set_report_id(report.report_id());
    SerializeToBase64(key_data, &key);

    auto locked = event_aggregator_mgr_->aggregate_store_.protected_aggregate_store_.lock();

    auto aggregates = locked->local_aggregate_store.by_report_key().find(key);
    if (aggregates == locked->local_aggregate_store.by_report_key().end()) {
      return false;
    }

    auto by_event_code =
        aggregates->second.unique_actives_aggregates().by_event_code().find(event_code);
    if (by_event_code == aggregates->second.unique_actives_aggregates().by_event_code().end()) {
      return false;
    }

    auto by_day_index = by_event_code->second.by_day_index().find(day_index);
    if (by_day_index == by_event_code->second.by_day_index().end()) {
      return false;
    }

    return by_day_index->second.activity_daily_aggregate().activity_indicator();
  }

  std::optional<int64_t> GetValue(lib::ReportIdentifier report, const std::string& component,
                                  uint64_t event_code, uint32_t day_index) {
    std::string key;
    ReportAggregationKey key_data;
    key_data.set_customer_id(report.customer_id());
    key_data.set_project_id(report.project_id());
    key_data.set_metric_id(report.metric_id());
    key_data.set_report_id(report.report_id());
    SerializeToBase64(key_data, &key);

    auto locked = event_aggregator_mgr_->aggregate_store_.protected_aggregate_store_.lock();

    auto aggregates = locked->local_aggregate_store.by_report_key().find(key);
    if (aggregates == locked->local_aggregate_store.by_report_key().end()) {
      return std::nullopt;
    }

    auto by_component = aggregates->second.numeric_aggregates().by_component().find(component);
    if (by_component == aggregates->second.numeric_aggregates().by_component().end()) {
      return std::nullopt;
    }

    auto by_event_code = by_component->second.by_event_code().find(event_code);
    if (by_event_code == by_component->second.by_event_code().end()) {
      return std::nullopt;
    }

    auto by_day_index = by_event_code->second.by_day_index().find(day_index);
    if (by_day_index == by_event_code->second.by_day_index().end()) {
      return std::nullopt;
    }

    return by_day_index->second.numeric_daily_aggregate().value();
  }

  AggregateStore& GetAggregateStore() { return event_aggregator_mgr_->aggregate_store_; }

  Status GarbageCollect(uint32_t day_index_utc, uint32_t day_index_local = 0u) {
    return event_aggregator_mgr_->aggregate_store_.GarbageCollect(day_index_utc, day_index_local);
  }

  void DoScheduledTasksNow() {
    // Steady values don't matter, just tell DoScheduledTasks to run everything.
    auto steady_time = std::chrono::steady_clock::now();
    event_aggregator_mgr_->next_generate_obs_ = steady_time;
    event_aggregator_mgr_->next_gc_ = steady_time;
    event_aggregator_mgr_->DoScheduledTasks(unowned_test_clock_->now(), steady_time);
  }

  // Clears the FakeObservationStore and resets the counts of Observations
  // received by the FakeObservationStore and the TestUpdateRecipient.
  void ResetObservationStore() {
    observation_store_->messages_received.clear();
    observation_store_->metadata_received.clear();
    observation_store_->ResetObservationCounter();
    update_recipient_->invocation_count = 0;
  }

  // Given a ProjectContext |project_context| and the MetricReportId of a
  // UNIQUE_N_DAY_ACTIVES report in |project_context|, as well as a day index
  // and an event code, adds an EventOccurredEvent to the EventAggregator for
  // that report, day index, and event code. If a non-null LoggedActivity map is
  // provided, updates the map with information about the logged Event.
  Status AddUniqueActivesEvent(std::shared_ptr<const ProjectContext> project_context,
                               const MetricReportId& metric_report_id, uint32_t day_index,
                               uint32_t event_code, LoggedActivity* logged_activity = nullptr) {
    auto event_record =
        EventRecord::MakeEventRecord(std::move(project_context), metric_report_id.first).value();
    event_record->event()->set_day_index(day_index);
    event_record->event()->mutable_event_occurred_event()->set_event_code(event_code);
    Status status = event_aggregator_mgr_->GetEventAggregator().AddUniqueActivesEvent(
        metric_report_id.second, *event_record);
    if (logged_activity == nullptr) {
      return status;
    }
    std::string key;
    if (!SerializeToBase64(MakeAggregationKey(*event_record->project_context(), metric_report_id),
                           &key)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Could not serialize");
    }
    (*logged_activity)[key][event_code].insert(day_index);
    return status;
  }

  // Given a ProjectContext |project_context| and the MetricReportId of an
  // EVENT_COUNT metric with a PER_DEVICE_NUMERIC_STATS report in
  // |project_context|, as well as a day index, a component string, and an event
  // code, adds a EventCountEvent to the EventAggregator for that report, day
  // index, component, and event code. If a non-null LoggedValues map is
  // provided, updates the map with information about the logged Event.
  Status AddPerDeviceEventCountEvent(std::shared_ptr<const ProjectContext> project_context,
                                     const MetricReportId& metric_report_id, uint32_t day_index,
                                     const std::string& component, uint32_t event_code,
                                     int64_t count, LoggedValues* logged_values = nullptr) {
    auto event_record =
        EventRecord::MakeEventRecord(std::move(project_context), metric_report_id.first).value();
    event_record->event()->set_day_index(day_index);
    EventCountEvent* event_count_event = event_record->event()->mutable_event_count_event();
    event_count_event->set_component(component);
    event_count_event->add_event_code(event_code);
    event_count_event->set_count(count);
    Status status = event_aggregator_mgr_->GetEventAggregator().AddEventCountEvent(
        metric_report_id.second, *event_record);
    if (logged_values == nullptr) {
      return status;
    }
    std::string key;
    if (!SerializeToBase64(MakeAggregationKey(*event_record->project_context(), metric_report_id),
                           &key)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Could not serialize");
    }
    (*logged_values)[key][component][event_code][day_index].push_back(count);
    return status;
  }

  // Given a ProjectContext |project_context| and the MetricReportId of an
  // ELAPSED_TIME metric with a PER_DEVICE_NUMERIC_STATS report in
  // |project_context|, as well as a day index, a component string, and an event
  // code, logs an ElapsedTimeEvent to the EventAggregator for that report, day
  // index, component, and event code. If a non-null LoggedValues map is
  // provided, updates the map with information about the logged Event.
  Status AddPerDeviceElapsedTimeEvent(std::shared_ptr<const ProjectContext> project_context,
                                      const MetricReportId& metric_report_id, uint32_t day_index,
                                      const std::string& component, uint32_t event_code,
                                      int64_t micros, LoggedValues* logged_values = nullptr) {
    auto event_record =
        EventRecord::MakeEventRecord(std::move(project_context), metric_report_id.first).value();
    event_record->event()->set_day_index(day_index);
    ElapsedTimeEvent* elapsed_time_event = event_record->event()->mutable_elapsed_time_event();
    elapsed_time_event->set_component(component);
    elapsed_time_event->add_event_code(event_code);
    elapsed_time_event->set_elapsed_micros(micros);
    Status status = event_aggregator_mgr_->GetEventAggregator().AddElapsedTimeEvent(
        metric_report_id.second, *event_record);
    if (logged_values == nullptr) {
      return status;
    }
    std::string key;
    if (!SerializeToBase64(MakeAggregationKey(*event_record->project_context(), metric_report_id),
                           &key)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Serialize failed");
    }
    (*logged_values)[key][component][event_code][day_index].push_back(micros);
    return status;
  }

  // Given a ProjectContext |project_context| and the MetricReportId of a
  // FRAME_RATE metric with a PER_DEVICE_NUMERIC_STATS report in
  // |project_context|, as well as a day index, a component string, and an event
  // code, logs a FrameRateEvent to the EventAggregator for that report, day
  // index, component, and event code. If a non-null LoggedValues map is
  // provided, updates the map with information about the logged Event.
  Status AddPerDeviceFrameRateEvent(std::shared_ptr<const ProjectContext> project_context,
                                    const MetricReportId& metric_report_id, uint32_t day_index,
                                    const std::string& component, uint32_t event_code, float fps,
                                    LoggedValues* logged_values = nullptr) {
    auto event_record =
        EventRecord::MakeEventRecord(std::move(project_context), metric_report_id.first).value();
    event_record->event()->set_day_index(day_index);
    FrameRateEvent* frame_rate_event = event_record->event()->mutable_frame_rate_event();
    frame_rate_event->set_component(component);
    frame_rate_event->add_event_code(event_code);
    int64_t frames_per_1000_seconds = std::lround(fps * 1000.0);
    frame_rate_event->set_frames_per_1000_seconds(frames_per_1000_seconds);
    Status status = event_aggregator_mgr_->GetEventAggregator().AddFrameRateEvent(
        metric_report_id.second, *event_record);
    if (logged_values == nullptr) {
      return status;
    }
    std::string key;
    if (!SerializeToBase64(MakeAggregationKey(*event_record->project_context(), metric_report_id),
                           &key)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Serialize failed");
    }
    (*logged_values)[key][component][event_code][day_index].push_back(frames_per_1000_seconds);
    return status;
  }

  // Given a ProjectContext |project_context| and the MetricReportId of a
  // MEMORY_USAGE metric with a PER_DEVICE_NUMERIC_STATS report in
  // |project_context|, as well as a day index, a component string, and an event
  // code, logs a MemoryUsageEvent to the EventAggregator for that report, day
  // index, component, and event code. If a non-null LoggedValues map is
  // provided, updates the map with information about the logged Event.
  Status AddPerDeviceMemoryUsageEvent(std::shared_ptr<const ProjectContext> project_context,
                                      const MetricReportId& metric_report_id, uint32_t day_index,
                                      const std::string& component,
                                      const std::vector<uint32_t>& event_codes, int64_t bytes,
                                      LoggedValues* logged_values = nullptr) {
    auto event_record =
        EventRecord::MakeEventRecord(std::move(project_context), metric_report_id.first).value();
    event_record->event()->set_day_index(day_index);
    MemoryUsageEvent* memory_usage_event = event_record->event()->mutable_memory_usage_event();
    memory_usage_event->set_component(component);
    for (auto event_code : event_codes) {
      memory_usage_event->add_event_code(event_code);
    }
    memory_usage_event->set_bytes(bytes);
    Status status = event_aggregator_mgr_->GetEventAggregator().AddMemoryUsageEvent(
        metric_report_id.second, *event_record);
    if (logged_values == nullptr) {
      return status;
    }
    std::string key;
    if (!SerializeToBase64(MakeAggregationKey(*event_record->project_context(), metric_report_id),
                           &key)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Serialize failed");
    }

    (*logged_values)[key][component][PackEventCodes(event_codes)][day_index].push_back(bytes);
    return status;
  }

  // Given a LoggedActivity map describing the events that have been logged
  // to the EventAggregator, checks whether the contents of the
  // LocalAggregateStore are as expected, accounting for any garbage
  // collection.
  //
  // logged_activity: a LoggedActivity representing event occurrences
  // since the LocalAggregateStore was created. All day indices should be
  // greater than or equal to |day_store_created_| and less than or equal to
  // |current_day_index|.
  //
  // current_day_index: The day index of the current day in the test's frame
  // of reference.
  bool CheckUniqueActivesAggregates(const LoggedActivity& logged_activity,
                                    uint32_t /*current_day_index*/) {
    auto local_aggregate_store = event_aggregator_mgr_->aggregate_store_.CopyLocalAggregateStore();
    // Check that the LocalAggregateStore contains no more UniqueActives
    // aggregates than |logged_activity| and |day_last_garbage_collected_|
    // should imply.
    for (const auto& report_pair : local_aggregate_store.by_report_key()) {
      const auto& aggregates = report_pair.second;
      if (aggregates.type_case() != ReportAggregates::kUniqueActivesAggregates) {
        continue;
      }
      const auto& report_key = report_pair.first;
      // Check whether this ReportAggregationKey is in |logged_activity|. If
      // not, expect that its by_event_code map is empty.
      auto report_activity = logged_activity.find(report_key);
      if (report_activity == logged_activity.end()) {
        EXPECT_TRUE(aggregates.unique_actives_aggregates().by_event_code().empty());
        if (!aggregates.unique_actives_aggregates().by_event_code().empty()) {
          return false;
        }
        break;
      }
      auto expected_events = report_activity->second;
      for (const auto& event_pair : aggregates.unique_actives_aggregates().by_event_code()) {
        // Check that this event code is in |logged_activity| under this
        // ReportAggregationKey.
        auto event_code = event_pair.first;
        auto event_activity = expected_events.find(event_code);
        EXPECT_NE(event_activity, expected_events.end());
        if (event_activity == expected_events.end()) {
          return false;
        }
        const auto& expected_days = event_activity->second;
        for (const auto& day_pair : event_pair.second.by_day_index()) {
          // Check that this day index is in |logged_activity| under this
          // ReportAggregationKey and event code.
          const auto& day_index = day_pair.first;
          auto day_activity = expected_days.find(day_index);
          EXPECT_NE(day_activity, expected_days.end());
          if (day_activity == expected_days.end()) {
            return false;
          }
          // Check that the day index is no earlier than is implied by the
          // dates of store creation and garbage collection.
          EXPECT_GE(day_index, EarliestAllowedDayIndex(aggregates.aggregation_config()));
          if (day_index < EarliestAllowedDayIndex(aggregates.aggregation_config())) {
            return false;
          }
        }
      }
    }

    // Check that the LocalAggregateStore contains aggregates for all events in
    // |logged_activity|, as long as they are recent enough to have survived any
    // garbage collection.
    for (const auto& logged_pair : logged_activity) {
      const auto& logged_key = logged_pair.first;
      const auto& logged_event_map = logged_pair.second;
      // Check that this ReportAggregationKey is in the LocalAggregateStore, and
      // that the aggregates are of the expected type.
      auto report_aggregates = local_aggregate_store.by_report_key().find(logged_key);
      EXPECT_NE(report_aggregates, local_aggregate_store.by_report_key().end());
      if (report_aggregates == local_aggregate_store.by_report_key().end()) {
        return false;
      }
      if (report_aggregates->second.type_case() != ReportAggregates::kUniqueActivesAggregates) {
        return false;
      }
      // Compute the earliest day index that should appear among the aggregates
      // for this report.
      auto earliest_allowed =
          EarliestAllowedDayIndex(report_aggregates->second.aggregation_config());
      for (const auto& logged_event_pair : logged_event_map) {
        const auto& logged_event_code = logged_event_pair.first;
        const auto& logged_days = logged_event_pair.second;
        // Check whether this event code is in the LocalAggregateStore
        // under this ReportAggregationKey. If not, check that all day indices
        // for this event code are smaller than the day index of the earliest
        // allowed aggregate.
        auto event_code_aggregates =
            report_aggregates->second.unique_actives_aggregates().by_event_code().find(
                logged_event_code);
        if (event_code_aggregates ==
            report_aggregates->second.unique_actives_aggregates().by_event_code().end()) {
          for (auto day_index : logged_days) {
            EXPECT_LT(day_index, earliest_allowed);
            if (day_index >= earliest_allowed) {
              return false;
            }
          }
          break;
        }
        // Check that all of the day indices in |logged_activity| under this
        // ReportAggregationKey and event code are in the
        // LocalAggregateStore, as long as they are recent enough to have
        // survived any garbage collection. Check that each aggregate has its
        // activity field set to true.
        for (const auto& logged_day_index : logged_days) {
          auto day_aggregate = event_code_aggregates->second.by_day_index().find(logged_day_index);
          if (logged_day_index >= earliest_allowed) {
            EXPECT_NE(day_aggregate, event_code_aggregates->second.by_day_index().end());
            if (day_aggregate == event_code_aggregates->second.by_day_index().end()) {
              return false;
            }
            EXPECT_TRUE(day_aggregate->second.activity_daily_aggregate().activity_indicator());
            if (!day_aggregate->second.activity_daily_aggregate().activity_indicator()) {
              return false;
            }
          }
        }
      }
    }
    return true;
  }

  bool CheckPerDeviceNumericAggregates(const LoggedValues& logged_values,
                                       uint32_t /*current_day_index*/) {
    auto local_aggregate_store = event_aggregator_mgr_->aggregate_store_.CopyLocalAggregateStore();
    // Check that the LocalAggregateStore contains no more PerDeviceNumeric
    // aggregates than |logged_values| and |day_last_garbage_collected_| should
    // imply.
    for (const auto& report_pair : local_aggregate_store.by_report_key()) {
      const auto& aggregates = report_pair.second;
      if (aggregates.type_case() != ReportAggregates::kNumericAggregates) {
        continue;
      }
      const auto& report_key = report_pair.first;
      // Check whether this ReportAggregationKey is in |logged_values|. If not,
      // expect that its by_component map is empty.
      auto report_values = logged_values.find(report_key);
      if (report_values == logged_values.end()) {
        EXPECT_TRUE(aggregates.numeric_aggregates().by_component().empty());
        if (!aggregates.numeric_aggregates().by_component().empty()) {
          return false;
        }
        break;
      }
      auto expected_components = report_values->second;
      for (const auto& component_pair : aggregates.numeric_aggregates().by_component()) {
        // Check that this component is in |logged_values| under this
        // ReportAggregationKey.
        auto component = component_pair.first;
        auto component_values = expected_components.find(component);
        EXPECT_NE(component_values, expected_components.end());
        if (component_values == expected_components.end()) {
          return false;
        }
        const auto& expected_events = component_values->second;
        for (const auto& event_pair : component_pair.second.by_event_code()) {
          // Check that this event code is in |logged_values| under this
          // ReportAggregationKey and component.
          const auto& event_code = event_pair.first;
          auto event_values = expected_events.find(event_code);
          EXPECT_NE(event_values, expected_events.end());
          if (event_values == expected_events.end()) {
            return false;
          }
          const auto& expected_days = event_values->second;
          for (const auto& day_pair : event_pair.second.by_day_index()) {
            // Check that this day index is in |logged_values| under this
            // ReportAggregationKey, component, and event code.
            const auto& day_index = day_pair.first;
            auto day_value = expected_days.find(day_index);
            EXPECT_NE(day_value, expected_days.end());
            if (day_value == expected_days.end()) {
              return false;
            }
            // Check that the day index is no earlier than is implied by the
            // dates of store creation and garbage collection.
            EXPECT_GE(day_index, EarliestAllowedDayIndex(aggregates.aggregation_config()));
            if (day_index < EarliestAllowedDayIndex(aggregates.aggregation_config())) {
              return false;
            }
          }
        }
      }
    }

    // Check that the LocalAggregateStore contains aggregates for all values in
    // |logged_values|, as long as they are recent enough to have survived any
    // garbage collection.
    for (const auto& logged_pair : logged_values) {
      const auto& logged_key = logged_pair.first;
      const auto& logged_component_map = logged_pair.second;
      // Check that this ReportAggregationKey is in the LocalAggregateStore, and
      // that the aggregates are of the expected type.
      auto report_aggregates = local_aggregate_store.by_report_key().find(logged_key);
      EXPECT_NE(report_aggregates, local_aggregate_store.by_report_key().end());
      if (report_aggregates == local_aggregate_store.by_report_key().end()) {
        return false;
      }
      if (report_aggregates->second.type_case() != ReportAggregates::kNumericAggregates) {
        return false;
      }
      const auto& aggregation_type =
          report_aggregates->second.aggregation_config().report().aggregation_type();
      // Compute the earliest day index that should appear among the aggregates
      // for this report.
      auto earliest_allowed =
          EarliestAllowedDayIndex(report_aggregates->second.aggregation_config());
      for (const auto& logged_component_pair : logged_component_map) {
        const auto& logged_component = logged_component_pair.first;
        const auto& logged_event_code_map = logged_component_pair.second;
        // Check whether this component is in the LocalAggregateStore under this
        // ReportAggregationKey. If not, check that all day indices for all
        // entries in |logged_values| under this component are smaller than the
        // day index of the earliest allowed aggregate.
        bool component_found = false;
        auto component_aggregates =
            report_aggregates->second.numeric_aggregates().by_component().find(logged_component);
        if (component_aggregates !=
            report_aggregates->second.numeric_aggregates().by_component().end()) {
          component_found = true;
        }
        for (const auto& logged_event_pair : logged_event_code_map) {
          const auto& logged_event_code = logged_event_pair.first;
          const auto& logged_day_map = logged_event_pair.second;
          // Check whether this event code is in the LocalAggregateStore under
          // this ReportAggregationKey. If not, check that all day indices in
          // |logged_values| under this component are smaller than the day index
          // of the earliest allowed aggregate.
          bool event_code_found = false;
          if (component_found) {
            auto event_code_aggregates =
                component_aggregates->second.by_event_code().find(logged_event_code);
            if (event_code_aggregates != component_aggregates->second.by_event_code().end()) {
              event_code_found = true;
            }
            if (event_code_found) {
              // Check that all of the day indices in |logged_values| under this
              // ReportAggregationKey, component, and event code are in the
              // LocalAggregateStore, as long as they are recent enough to have
              // survived any garbage collection. Check that each aggregate has
              // the expected value.
              for (const auto& logged_day_pair : logged_day_map) {
                auto logged_day_index = logged_day_pair.first;
                auto logged_values = logged_day_pair.second;
                auto day_aggregate =
                    event_code_aggregates->second.by_day_index().find(logged_day_index);
                if (logged_day_index >= earliest_allowed) {
                  EXPECT_NE(day_aggregate, event_code_aggregates->second.by_day_index().end());
                  if (day_aggregate == event_code_aggregates->second.by_day_index().end()) {
                    return false;
                  }
                  int64_t aggregate_from_logged_values = 0;
                  for (size_t index = 0; index < logged_values.size(); index++) {
                    switch (aggregation_type) {
                      case ReportDefinition::SUM:
                        aggregate_from_logged_values += logged_values[index];
                        break;
                      case ReportDefinition::MAX:
                        aggregate_from_logged_values =
                            std::max(aggregate_from_logged_values, logged_values[index]);
                        break;
                      case ReportDefinition::MIN:
                        if (index == 0) {
                          aggregate_from_logged_values = logged_values[0];
                        }
                        aggregate_from_logged_values =
                            std::min(aggregate_from_logged_values, logged_values[index]);
                        break;
                      default:
                        return false;
                    }
                  }
                  EXPECT_EQ(day_aggregate->second.numeric_daily_aggregate().value(),
                            aggregate_from_logged_values);
                  if (day_aggregate->second.numeric_daily_aggregate().value() !=
                      aggregate_from_logged_values) {
                    return false;
                  }
                }
              }
            }
          }
          if (!component_found | !event_code_found) {
            for (const auto& logged_day_pair : logged_day_map) {
              auto logged_day_index = logged_day_pair.first;
              EXPECT_LT(logged_day_index, earliest_allowed);
              if (logged_day_index >= earliest_allowed) {
                return false;
              }
            }
            break;
          }
        }
      }
    }

    return true;
  }

  // Given the AggregationConfig of a locally aggregated report, returns the
  // earliest (smallest) day index for which an aggregate may exist in the
  // LocalAggregateStore for that report, accounting for garbage
  // collection and the number of backfill days.
  uint32_t EarliestAllowedDayIndex(const AggregationConfig& config) {
    // If the LocalAggregateStore has never been garbage-collected, then the
    // earliest allowed day index is just the day when the store was created,
    // minus the number of backfill days.
    auto backfill_days = GetBackfillDays();
    EXPECT_GE(day_store_created_, backfill_days)
        << "The day index of store creation must be larger than the number "
           "of backfill days.";
    if (day_last_garbage_collected_ == 0u) {
      return day_store_created_ - backfill_days;
    }
    uint32_t max_aggregation_days = 1;
    for (const auto& window : config.aggregation_window()) {
      if (window.units_case() == OnDeviceAggregationWindow::kDays &&
          window.days() > max_aggregation_days) {
        max_aggregation_days = window.days();
      }
    }
    // Otherwise, it is the later of:
    // (a) The day index on which the store was created minus the number
    // of backfill days.
    // (b) The day index for which the store was last garbage-collected
    // minus the number of backfill days, minus the largest window size in
    // the report associated to |config|, plus 1.
    EXPECT_GE(day_last_garbage_collected_, backfill_days)
        << "The day index of last garbage collection must be larger than "
           "the number of backfill days.";

    if (day_last_garbage_collected_ - backfill_days < (max_aggregation_days + 1)) {
      return day_store_created_ - backfill_days;
    }
    return (day_store_created_ < (day_last_garbage_collected_ - max_aggregation_days + 1))
               ? (day_last_garbage_collected_ - backfill_days - max_aggregation_days + 1)
               : day_store_created_ - backfill_days;
  }

  std::unique_ptr<TestEventAggregatorManager> event_aggregator_mgr_;
  std::unique_ptr<ObservationWriter> observation_writer_;
  std::unique_ptr<MetadataBuilder> metadata_builder_;
  std::unique_ptr<Encoder> encoder_;
  std::unique_ptr<EncryptedMessageMaker> observation_encrypter_;
  std::unique_ptr<TestUpdateRecipient> update_recipient_;
  std::unique_ptr<FakeObservationStore> observation_store_;
  std::unique_ptr<IncrementingSystemClock> test_clock_;
  IncrementingSystemClock* unowned_test_clock_;
  std::unique_ptr<util::FakeValidatedClock> validated_clock_;
  IncrementingSteadyClock* test_steady_clock_;
  // The day index on which the LocalAggregateStore was last
  // garbage-collected. A value of 0 indicates that the store has never been
  // garbage-collected.
  uint32_t day_last_garbage_collected_ = 0u;
  // The day index on which the LocalAggregateStore was created.
  uint32_t day_store_created_ = 0u;

 private:
  system_data::FakeSystemData system_data_;
};

// Creates an EventAggregator and provides it with a ProjectContext generated
// from a registry.
class AggregateStoreTestWithProjectContext : public AggregateStoreTest {
 protected:
  explicit AggregateStoreTestWithProjectContext(const std::string& registry_var_name) {
    project_context_ = GetTestProject(registry_var_name);
  }

  void SetUp() override {
    AggregateStoreTest::SetUp();
    event_aggregator_mgr_->GetEventAggregator().UpdateAggregationConfigs(*project_context_);
  }

  // Adds an EventOccurredEvent to the local aggregations for the MetricReportId of a locally
  // aggregated report of the ProjectContext. Overrides the method
  // AggregateStoreTest::AddUniqueActivesEvent.
  Status AddUniqueActivesEvent(const MetricReportId& metric_report_id, uint32_t day_index,
                               uint32_t event_code, LoggedActivity* logged_activity = nullptr) {
    return AggregateStoreTest::AddUniqueActivesEvent(project_context_, metric_report_id, day_index,
                                                     event_code, logged_activity);
  }

  // Logs a EventCountEvent for the MetricReportId of a locally
  // aggregated report of the ProjectContext. Overrides the method
  // AggregateStoreTest::AddPerDeviceEventCountEvent.
  Status AddPerDeviceEventCountEvent(const MetricReportId& metric_report_id, uint32_t day_index,
                                     const std::string& component, uint32_t event_code,
                                     int64_t count, LoggedValues* logged_values = nullptr) {
    return AggregateStoreTest::AddPerDeviceEventCountEvent(
        project_context_, metric_report_id, day_index, component, event_code, count, logged_values);
  }

  // Adds an ElapsedTimeEvent to the local aggregations for the MetricReportId of a locally
  // aggregated report of the ProjectContext. Overrides the method
  // AggregateStoreTest::AddPerDeviceElapsedTimeEvent.
  Status AddPerDeviceElapsedTimeEvent(const MetricReportId& metric_report_id, uint32_t day_index,
                                      const std::string& component, uint32_t event_code,
                                      int64_t micros, LoggedValues* logged_values = nullptr) {
    return AggregateStoreTest::AddPerDeviceElapsedTimeEvent(project_context_, metric_report_id,
                                                            day_index, component, event_code,
                                                            micros, logged_values);
  }

  // Logs a FrameRateEvent for the MetricReportId of a locally
  // aggregated report of the ProjectContext. Overrides the method
  // AggregateStoreTest::AddPerDeviceFrameRateEvent.
  Status AddPerDeviceFrameRateEvent(const MetricReportId& metric_report_id, uint32_t day_index,
                                    const std::string& component, uint32_t event_code, float fps,
                                    LoggedValues* logged_values = nullptr) {
    return AggregateStoreTest::AddPerDeviceFrameRateEvent(
        project_context_, metric_report_id, day_index, component, event_code, fps, logged_values);
  }

  // Adds a MemoryUsageEvent to the local aggregations for the MetricReportId of a locally
  // aggregated report of the ProjectContext. Overrides the method
  // AggregateStoreTest::AddPerDeviceMemoryUsageEvent.
  Status AddPerDeviceMemoryUsageEvent(const MetricReportId& metric_report_id, uint32_t day_index,
                                      const std::string& component,
                                      const std::vector<uint32_t>& event_codes, int64_t bytes,
                                      LoggedValues* logged_values = nullptr) {
    return AggregateStoreTest::AddPerDeviceMemoryUsageEvent(project_context_, metric_report_id,
                                                            day_index, component, event_codes,
                                                            bytes, logged_values);
  }

 private:
  // A ProjectContext wrapping the MetricDefinitions passed to the
  // constructor in |metric_string|.
  std::shared_ptr<ProjectContext> project_context_;
};

// Creates an EventAggregator and provides it with a ProjectContext generated
// from test_registries/unique_actives_test_registry.yaml. All metrics in this
// registry are of type EVENT_OCCURRED and have a UNIQUE_N_DAY_ACTIVES report.
class UniqueActivesAggregateStoreTest : public AggregateStoreTestWithProjectContext {
 protected:
  UniqueActivesAggregateStoreTest()
      : AggregateStoreTestWithProjectContext(
            logger::testing::unique_actives::kCobaltRegistryBase64) {}
};

// Creates an EventAggregator and provides it with a ProjectContext generated
// from test_registries/unique_actives_noise_free_test_registry.yaml. All
// metrics in this registry are of type EVENT_OCCURRED and have a
// UNIQUE_N_DAY_ACTIVES report with local_privacy_noise_level NONE.
class UniqueActivesNoiseFreeAggregateStoreTest : public AggregateStoreTestWithProjectContext {
 protected:
  UniqueActivesNoiseFreeAggregateStoreTest()
      : AggregateStoreTestWithProjectContext(
            logger::testing::unique_actives_noise_free::kCobaltRegistryBase64) {}
};

// Creates an EventAggregator and provides it with a ProjectContext generated
// from test_registries/per_device_numeric_stats_test_registry.yaml. All metrics
// in this registry are of type EVENT_COUNT and have a PER_DEVICE_NUMERIC_STATS
// report.
class PerDeviceNumericAggregateStoreTest : public AggregateStoreTestWithProjectContext {
 protected:
  PerDeviceNumericAggregateStoreTest()
      : AggregateStoreTestWithProjectContext(
            logger::testing::per_device_numeric_stats::kCobaltRegistryBase64) {}
};

// Creates an EventAggregator and provides it with a ProjectContext generated
// from test_registries/mixed_time_zone_test_registry.yaml. This registry
// contains multiple MetricDefinitions with different time zone policies.
class NoiseFreeMixedTimeZoneAggregateStoreTest : public AggregateStoreTestWithProjectContext {
 protected:
  NoiseFreeMixedTimeZoneAggregateStoreTest()
      : AggregateStoreTestWithProjectContext(
            logger::testing::mixed_time_zone::kCobaltRegistryBase64) {}
};

class PerDeviceHistogramAggregateStoreTest : public AggregateStoreTestWithProjectContext {
 protected:
  PerDeviceHistogramAggregateStoreTest()
      : AggregateStoreTestWithProjectContext(
            logger::testing::per_device_histogram::kCobaltRegistryBase64) {}
};

class AggregateStoreWorkerTest : public AggregateStoreTest {
 protected:
  void SetUp() override { AggregateStoreTest::SetUp(); }

  void ShutDownWorkerThread() { event_aggregator_mgr_->ShutDown(); }

  bool in_shutdown_state() { return (shutdown_flag_set() && !worker_joinable()); }

  bool in_run_state() { return (!shutdown_flag_set() && worker_joinable()); }

  bool shutdown_flag_set() {
    return event_aggregator_mgr_->protected_worker_thread_controller_.const_lock()->shut_down;
  }

  bool worker_joinable() { return event_aggregator_mgr_->worker_thread_.joinable(); }
};

// Tests that the Read() method of each ConsistentProtoStore is called once
// during construction of the EventAggregator.
TEST_F(AggregateStoreTest, ReadProtosFromFiles) {
  EXPECT_EQ(1, fs().TimesRead(aggregate_store_path()));
  EXPECT_EQ(1, fs().TimesRead(obs_history_path()));
}

// Tests that the BackUp*() methods return a positive status, and checks that
// the Write() method of a ConsistentProtoStore is called once when its
// respective BackUp*() method is called.
TEST_F(AggregateStoreTest, BackUpProtos) {
  EXPECT_EQ(StatusCode::OK, BackUpLocalAggregateStore().error_code());
  EXPECT_EQ(StatusCode::OK, BackUpObservationHistory().error_code());
  EXPECT_EQ(1, fs().TimesWritten(aggregate_store_path()));
  EXPECT_EQ(1, fs().TimesWritten(obs_history_path()));
}

// MaybeUpgradeLocalAggregateStore should return an OK status if the version is current. The store
// should not change.
TEST_F(AggregateStoreTest, MaybeUpgradeLocalAggregateStoreCurrent) {
  auto store = MakeNewLocalAggregateStore();
  std::string store_before = SerializeAsStringDeterministic(store);
  ASSERT_EQ(kCurrentLocalAggregateStoreVersion, store.version());
  EXPECT_EQ(StatusCode::OK, MaybeUpgradeLocalAggregateStore(&store).error_code());
  EXPECT_EQ(store_before, SerializeAsStringDeterministic(store));
}

// MaybeUpgradeLocalAggregateStore should return StatusCode::INVALID_ARGUMENT if it is not
// possible to upgrade to the current version.
TEST_F(AggregateStoreTest, MaybeUpgradeLocalAggregateStoreUnsupported) {
  const uint32_t kFutureVersion = kCurrentLocalAggregateStoreVersion + 1;
  auto store = MakeNewLocalAggregateStore(kFutureVersion);
  ASSERT_EQ(kFutureVersion, store.version());
  EXPECT_EQ(StatusCode::INVALID_ARGUMENT, MaybeUpgradeLocalAggregateStore(&store).error_code());
}

// It should be possible to upgrade the LocalAggregateStore from v0 to the current version. The
// version number should be updated and the contents of window_size in each AggregationConfigs
// should be moved to aggregation_window, preserving their order.
TEST_F(AggregateStoreTest, MaybeUpgradeLocalAggregateStoreFromV0) {
  const uint32_t kVersionZero = 0;
  const std::vector<int32_t> kWindowSizes = {1, 7, 30};
  const std::string kKey = "some_report_key";

  // Make a v0 LocalAggregateStore with one report.
  auto store = MakeNewLocalAggregateStore(kVersionZero);
  ReportAggregates report_aggregates;
  for (auto window_size : kWindowSizes) {
    report_aggregates.mutable_aggregation_config()->add_window_size(window_size);
  }
  (*store.mutable_by_report_key())[kKey] = report_aggregates;

  // Make the expected upgraded store.
  auto expected_store = MakeNewLocalAggregateStore(kCurrentLocalAggregateStoreVersion);
  ReportAggregates expected_report_aggregates;
  for (int32_t window_size : kWindowSizes) {
    *expected_report_aggregates.mutable_aggregation_config()->add_aggregation_window() =
        MakeDayWindow(window_size);
  }
  (*expected_store.mutable_by_report_key())[kKey] = expected_report_aggregates;

  // Upgrade and check that the upgraded store is as expected.
  EXPECT_EQ(StatusCode::OK, MaybeUpgradeLocalAggregateStore(&store).error_code());
  EXPECT_EQ(SerializeAsStringDeterministic(expected_store), SerializeAsStringDeterministic(store));
}

// MaybeUpgradeObservationHistoryStore should return an OK status if the version is current. The
// store should not change.
TEST_F(AggregateStoreTest, MaybeUpgradeObservationHistoryStoreCurrent) {
  auto store = MakeNewObservationHistoryStore();
  std::string store_before = SerializeAsStringDeterministic(store);
  ASSERT_EQ(kCurrentObservationHistoryStoreVersion, store.version());
  EXPECT_EQ(StatusCode::OK, MaybeUpgradeObservationHistoryStore(&store).error_code());
  EXPECT_EQ(store_before, SerializeAsStringDeterministic(store));
}

// MaybeUpgradeObservationHistoryStore should return logger::kInvalidArguments if it is not
// possible to upgrade to the current version.
TEST_F(AggregateStoreTest, MaybeUpgradeObservationHistoryStoreUnsupported) {
  const uint32_t kFutureVersion = kCurrentObservationHistoryStoreVersion + 1;
  auto store = MakeNewObservationHistoryStore(kFutureVersion);
  ASSERT_EQ(kFutureVersion, store.version());
  EXPECT_EQ(StatusCode::INVALID_ARGUMENT, MaybeUpgradeObservationHistoryStore(&store).error_code());
}

// MaybeInsertReportConfig successfully updates the store.
TEST_F(AggregateStoreTest, MaybeInsertReportConfig) {
  auto [metric, report] = GetUniqueActivesMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_FALSE(IsReportInStore(kTestReportIdentifier));
  ASSERT_EQ(
      StatusCode::OK,
      GetAggregateStore().MaybeInsertReportConfig(*project_context, metric, report).error_code());
  EXPECT_TRUE(IsReportInStore(kTestReportIdentifier));
}

// MaybeInsertReportConfig returns kOK when the same config is inserted twice.
TEST_F(AggregateStoreTest, MaybeInsertReportConfigTwice) {
  auto [metric, report] = GetUniqueActivesMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_FALSE(IsReportInStore(kTestReportIdentifier));
  ASSERT_EQ(
      StatusCode::OK,
      GetAggregateStore().MaybeInsertReportConfig(*project_context, metric, report).error_code());
  ASSERT_EQ(
      StatusCode::OK,
      GetAggregateStore().MaybeInsertReportConfig(*project_context, metric, report).error_code());
  EXPECT_TRUE(IsReportInStore(kTestReportIdentifier));
}

// MaybeInsertReportConfig fails due to the fact that the given report does not have an
// aggregation window.
TEST_F(AggregateStoreTest, MaybeInsertReportConfigFail) {
  auto [metric, report] = GetNotLocallyAggregatedMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_FALSE(IsReportInStore(kTestReportIdentifier));
  ASSERT_EQ(
      StatusCode::INVALID_ARGUMENT,
      GetAggregateStore().MaybeInsertReportConfig(*project_context, metric, report).error_code());
}

// The Aggregate store sets the record for an event to active using SetActive.
TEST_F(AggregateStoreTest, SetActive) {
  auto [metric, report] = GetUniqueActivesMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());

  EXPECT_FALSE(IsActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex));
  ASSERT_EQ(StatusCode::OK, GetAggregateStore()
                                .SetActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex)
                                .error_code());
  EXPECT_TRUE(IsActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex));
}

// SetActive returns kOK when the same config is inserted twice.
TEST_F(AggregateStoreTest, SetActiveTwice) {
  auto [metric, report] = GetUniqueActivesMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());
  EXPECT_FALSE(IsActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex));

  ASSERT_EQ(StatusCode::OK, GetAggregateStore()
                                .SetActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex)
                                .error_code());
  ASSERT_EQ(StatusCode::OK, GetAggregateStore()
                                .SetActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex)
                                .error_code());
  EXPECT_TRUE(IsActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex));
}

// SetActive fails due to the fact that UpdateAggregationConfigs was not called for the given
// report does not have an aggregation.
TEST_F(AggregateStoreTest, SetActiveFail) {
  auto [metric, report] = GetNotLocallyAggregatedMetricAndReport(kTestReportIdentifier);
  auto project_context = GetProjectContextFor(metric);

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());
  ASSERT_EQ(StatusCode::INVALID_ARGUMENT,
            GetAggregateStore()
                .SetActive(kTestReportIdentifier, kTestEventCode, kTestDayIndex)
                .error_code());
}

// The Aggregate store updates the local store with the sum of two values when the aggregation is
// of type SUM.
TEST_F(AggregateStoreTest, UpdateAggregationSUM) {
  auto [metric, report] =
      GetPerDeviceNumericStatsMetricAndReport(kTestReportIdentifier, ReportDefinition::SUM);
  auto project_context = GetProjectContextFor(metric);

  const int64_t kFirstValue = 3;
  const int64_t kSecondValue = 7;

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());

  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kFirstValue)
                                .error_code());
  EXPECT_EQ(kFirstValue, GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kSecondValue)
                                .error_code());
  EXPECT_EQ(kSecondValue + kFirstValue,
            GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
}

// The Aggregate store updates the local store with the sum of two values when the aggregation is
// of type MAX.
TEST_F(AggregateStoreTest, UpdateAggregationMAX) {
  auto [metric, report] =
      GetPerDeviceNumericStatsMetricAndReport(kTestReportIdentifier, ReportDefinition::MAX);
  auto project_context = GetProjectContextFor(metric);

  const int64_t kFirstValue = 3;
  const int64_t kSecondValue = 7;

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());

  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kFirstValue)
                                .error_code());
  EXPECT_EQ(kFirstValue, GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kSecondValue)
                                .error_code());
  EXPECT_EQ(kSecondValue, GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
}
// The Aggregate store updates the local store with the sum of two values when the aggregation is
// of type MIN.
TEST_F(AggregateStoreTest, UpdateAggregationMIN) {
  auto [metric, report] =
      GetPerDeviceNumericStatsMetricAndReport(kTestReportIdentifier, ReportDefinition::MIN);
  auto project_context = GetProjectContextFor(metric);

  const int64_t kFirstValue = 3;
  const int64_t kSecondValue = 7;

  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());

  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kFirstValue)
                                .error_code());
  EXPECT_EQ(kFirstValue, GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
  EXPECT_EQ(StatusCode::OK, GetAggregateStore()
                                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode,
                                                        kTestDayIndex, kSecondValue)
                                .error_code());
  EXPECT_EQ(kFirstValue, GetValue(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex));
}

// UpdateAggregationConfigs fails due to the fact that UpdateAggregationConfigs was not called for
// the given report.
TEST_F(AggregateStoreTest, UpdateAggregationFail) {
  auto [metric, report] =
      GetPerDeviceNumericStatsMetricAndReport(kTestReportIdentifier, ReportDefinition::SUM);
  auto project_context = GetProjectContextFor(metric);

  ASSERT_EQ(StatusCode::INVALID_ARGUMENT,
            GetAggregateStore()
                .UpdateNumericAggregate(kTestReportIdentifier, "", kTestEventCode, kTestDayIndex,
                                        /*value*/ 4)
                .error_code());
}

TEST_F(AggregateStoreTest, SetUniqueActivesLastGeneratedDayIndex) {
  const std::string kReportKey = "test_key";
  const int64_t kFirstValue = 3;

  EXPECT_EQ(0u,
            GetAggregateStore().GetUniqueActivesLastGeneratedDayIndex(kReportKey, kTestEventCode,
                                                                      /*aggregation_days*/ 1));
  GetAggregateStore().SetUniqueActivesLastGeneratedDayIndex(kReportKey, kTestEventCode,
                                                            /*aggregation_days*/ 1, kFirstValue);
  EXPECT_EQ(kFirstValue,
            GetAggregateStore().GetUniqueActivesLastGeneratedDayIndex(kReportKey, kTestEventCode,
                                                                      /*aggregation_days*/ 1));
}
TEST_F(AggregateStoreTest, SetPerDeviceNumericLastGeneratedDayIndex) {
  const std::string kReportKey = "test_key";
  const int64_t kFirstValue = 3;

  EXPECT_EQ(0u, GetAggregateStore().GetPerDeviceNumericLastGeneratedDayIndex(
                    kReportKey, "", kTestEventCode,
                    /*aggregation_days*/ 1));
  GetAggregateStore().SetPerDeviceNumericLastGeneratedDayIndex(kReportKey, "", kTestEventCode,
                                                               /*aggregation_days*/ 1, kFirstValue);
  EXPECT_EQ(kFirstValue, GetAggregateStore().GetPerDeviceNumericLastGeneratedDayIndex(
                             kReportKey, "", kTestEventCode,
                             /*aggregation_days*/ 1));
}
TEST_F(AggregateStoreTest, SetReportParticipationLastGeneratedDayIndex) {
  const std::string kReportKey = "test_key";
  const int64_t kFirstValue = 3;

  EXPECT_EQ(0u, GetAggregateStore().GetReportParticipationLastGeneratedDayIndex(kReportKey));
  GetAggregateStore().SetReportParticipationLastGeneratedDayIndex(kReportKey, kFirstValue);
  EXPECT_EQ(kFirstValue,
            GetAggregateStore().GetReportParticipationLastGeneratedDayIndex(kReportKey));
}

// Tests that EventAggregator::GenerateObservations() returns a positive
// status and that the expected number of Observations is generated when no
// Events have been logged to the EventAggregator.
TEST_F(AggregateStoreTest, GenerateObservationsNoEvents) {
  // Provide the all_report_types test registry to the EventAggregator.
  auto project_context = GetTestProject(logger::testing::all_report_types::kCobaltRegistryBase64);
  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());
  // Generate locally aggregated Observations for the current day index.
  EXPECT_EQ(StatusCode::OK, GenerateObservations(CurrentDayIndex()).error_code());
  std::vector<Observation> observations(0);
  EXPECT_TRUE(FetchAggregatedObservations(
      &observations, logger::testing::all_report_types::kExpectedAggregationParams,
      *observation_store_, update_recipient_.get()));
}

// Tests that EventAggregator::GenerateObservations() only generates
// Observations the first time it is called for a given day index.
TEST_F(AggregateStoreTest, GenerateObservationsTwice) {
  // Provide the all_report_types test registry to the EventAggregator.
  auto project_context = GetTestProject(logger::testing::all_report_types::kCobaltRegistryBase64);
  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());
  // Check that Observations are generated when GenerateObservations is called
  // for the current day index for the first time.
  auto current_day_index = CurrentDayIndex();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(current_day_index).error_code());
  std::vector<Observation> observations(0);
  EXPECT_TRUE(FetchAggregatedObservations(
      &observations, logger::testing::all_report_types::kExpectedAggregationParams,
      *observation_store_, update_recipient_.get()));
  // Check that no Observations are generated when GenerateObservations is
  // called for the currentday index for the second time.
  ResetObservationStore();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(current_day_index).error_code());
  EXPECT_EQ(0u, observation_store_->messages_received.size());
}

// When the LocalAggregateStore contains one ReportAggregates proto and that
// proto is empty, GenerateObservations should return success but generate no
// observations.
TEST_F(AggregateStoreTest, GenerateObservationsFromBadStore) {
  auto bad_store = std::make_unique<LocalAggregateStore>();
  (*bad_store->mutable_by_report_key())["some_key"] = ReportAggregates();
  auto stream = fs().NewProtoOutputStream(aggregate_store_path()).value();
  EXPECT_TRUE(bad_store->SerializeToZeroCopyStream(stream.get()));
  // Read the bad store in to the EventAggregator.
  ResetEventAggregator();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(CurrentDayIndex()).error_code());
  EXPECT_EQ(0u, observation_store_->messages_received.size());
}

// When the LocalAggregateStore contains one empty ReportAggregates proto and
// some valid ReportAggregates, GenerateObservations should produce observations
// for the valid ReportAggregates.
TEST_F(AggregateStoreTest, GenerateObservationsFromBadStoreMultiReport) {
  auto bad_store = std::make_unique<LocalAggregateStore>();
  (*bad_store->mutable_by_report_key())["some_key"] = ReportAggregates();
  auto stream = fs().NewProtoOutputStream(aggregate_store_path()).value();
  EXPECT_TRUE(bad_store->SerializeToZeroCopyStream(stream.get()));
  // Read the bad store in to the EventAggregator.
  ResetEventAggregator();
  // Provide the all_report_types test registry to the EventAggregator.
  auto project_context = GetTestProject(logger::testing::all_report_types::kCobaltRegistryBase64);
  EXPECT_EQ(StatusCode::OK, event_aggregator_mgr_->GetEventAggregator()
                                .UpdateAggregationConfigs(*project_context)
                                .error_code());
  EXPECT_EQ(StatusCode::OK, GenerateObservations(CurrentDayIndex()).error_code());
  std::vector<Observation> observations(0);
  EXPECT_TRUE(FetchAggregatedObservations(
      &observations, logger::testing::all_report_types::kExpectedAggregationParams,
      *observation_store_, update_recipient_.get()));
}

// When the LocalAggregateStore contains one ReportAggregates proto and that
// proto is empty, GarbageCollect should return success.
TEST_F(AggregateStoreTest, GarbageCollectBadStore) {
  auto bad_store = std::make_unique<LocalAggregateStore>();
  (*bad_store->mutable_by_report_key())["some_key"] = ReportAggregates();
  auto stream = fs().NewProtoOutputStream(aggregate_store_path()).value();
  EXPECT_TRUE(bad_store->SerializeToZeroCopyStream(stream.get()));
  // Read the bad store in to the EventAggregator.
  ResetEventAggregator();
  EXPECT_EQ(StatusCode::OK, GarbageCollect(CurrentDayIndex()).error_code());
}

// Tests GarbageCollect() for UniqueActivesReportAggregates.
//
// For each value of N in the range [0, 34], logs some UniqueActivesEvents
// each day for N consecutive days and then garbage-collects the
// LocalAggregateStore. After garbage collection, verifies the contents of
// the LocalAggregateStore.
TEST_F(UniqueActivesAggregateStoreTest, GarbageCollect) {
  uint32_t max_days_before_gc = 35;
  for (uint32_t days_before_gc = 0; days_before_gc < max_days_before_gc; days_before_gc++) {
    SetUp();
    day_last_garbage_collected_ = 0u;
    LoggedActivity logged_activity;
    for (uint32_t offset = 0; offset < days_before_gc; offset++) {
      auto day_index = CurrentDayIndex();
      for (const auto& metric_report_id :
           logger::testing::unique_actives::kExpectedAggregationParams.metric_report_ids) {
        // Add 2 events to the local aggregations with event code 0.
        EXPECT_EQ(
            StatusCode::OK,
            AddUniqueActivesEvent(metric_report_id, day_index, 0u, &logged_activity).error_code());
        EXPECT_EQ(
            StatusCode::OK,
            AddUniqueActivesEvent(metric_report_id, day_index, 0u, &logged_activity).error_code());
        if (offset < 3) {
          // Add 1 event to the local aggregations with event code 1.
          EXPECT_EQ(StatusCode::OK,
                    AddUniqueActivesEvent(metric_report_id, day_index, 1u, &logged_activity)
                        .error_code());
        }
      }
      AdvanceClock(kDay);
    }
    auto end_day_index = CurrentDayIndex();
    EXPECT_EQ(StatusCode::OK, GarbageCollect(end_day_index).error_code());
    day_last_garbage_collected_ = end_day_index;
    EXPECT_TRUE(CheckUniqueActivesAggregates(logged_activity, end_day_index));
    TearDown();
  }
}

// Tests that EventAggregator::GenerateObservations() returns a positive
// status and that the expected number of Observations is generated after
// some UniqueActivesEvents have been logged, without any garbage
// collection.
//
// For 35 days, logs 2 events each day for the NetworkActivity_UniqueDevices
// reports and 2 events for the FeaturesActive_UniqueDevices report, all
// with event code 0.
//
// Each day, calls GenerateObservations() with the day index of the previous
// day. Checks that a positive status is returned and that the
// FakeObservationStore has received the expected number of new observations
// for each locally aggregated report ID in the unique_actives registry.
TEST_F(UniqueActivesAggregateStoreTest, GenerateObservations) {
  int num_days = 35;
  std::vector<Observation> observations(0);
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    observations.clear();
    ResetObservationStore();
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
    EXPECT_TRUE(FetchAggregatedObservations(
        &observations, logger::testing::unique_actives::kExpectedAggregationParams,
        *observation_store_, update_recipient_.get()));
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kNetworkActivityWindowSizeMetricReportId,
                    day_index, 0u)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddUniqueActivesEvent(
              logger::testing::unique_actives::kNetworkActivityAggregationWindowMetricReportId,
              day_index, 0u)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kFeaturesActiveMetricReportId, day_index, 0u)
                    .error_code());
    }
    AdvanceClock(kDay);
  }
  observations.clear();
  ResetObservationStore();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(CurrentDayIndex() - 1).error_code());
  EXPECT_TRUE(FetchAggregatedObservations(
      &observations, logger::testing::unique_actives::kExpectedAggregationParams,
      *observation_store_, update_recipient_.get()));
}

// Tests that GenerateObservations() returns a positive status and that the
// expected number of Observations is generated each day when Events are
// logged for UNIQUE_N_DAY_ACTIVES reports over multiple days, and when the
// LocalAggregateStore is garbage-collected each day.
//
// For 35 days, logs 2 events each day for the NetworkActivity_UniqueDevices
// reports and 2 events for the FeaturesActive_UniqueDevices report, all
// with event code 0.
//
// Each day following the first day, calls GenerateObservations() and then
// GarbageCollect() with the day index of the current day. Checks that
// positive statuses are returned and that the FakeObservationStore has
// received the expected number of new observations for each locally
// aggregated report ID in the unique_actives registry.
TEST_F(UniqueActivesAggregateStoreTest, GenerateObservationsWithGc) {
  int num_days = 35;
  std::vector<Observation> observations(0);
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    observations.clear();
    ResetObservationStore();
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
    EXPECT_TRUE(FetchAggregatedObservations(
        &observations, logger::testing::unique_actives::kExpectedAggregationParams,
        *observation_store_, update_recipient_.get()));
    EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kNetworkActivityWindowSizeMetricReportId,
                    day_index, 0u)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddUniqueActivesEvent(
              logger::testing::unique_actives::kNetworkActivityAggregationWindowMetricReportId,
              day_index, 0u)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kFeaturesActiveMetricReportId, day_index, 0u)
                    .error_code());
    }
    AdvanceClock(kDay);
  }
  observations.clear();
  ResetObservationStore();
  auto day_index = CurrentDayIndex();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
  EXPECT_TRUE(FetchAggregatedObservations(
      &observations, logger::testing::unique_actives::kExpectedAggregationParams,
      *observation_store_, update_recipient_.get()));
  EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
}

// Tests that GenerateObservations() returns a positive status and that the
// expected number of Observations is generated when events are logged over
// multiple days and some of those days' Observations are backfilled, without
// any garbage collection of the LocalAggregateStore.
//
// Sets the |backfill_days_| field of the EventAggregator to 3.
//
// Logging pattern:
// For 35 days, logs 2 events each day for the
// NetworkActivity_UniqueDevices reports and 2 events for the
// FeaturesActive_UniqueDevices report, all with event code 0.
//
// Observation generation pattern:
// Calls GenerateObservations() on the 1st through 5th and the 7th out of
// every 10 days, for 35 days.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on
// the first day of every 10 (the day index for which GenerateObservations()
// was called, plus 3 days of backfill), that 1 day's worth of Observations
// are generated on the 2nd through 5th day of every 10, that 2 days'
// worth of Observations are generated on the 7th day of every 10 (the
// day index for which GenerateObservations() was called, plus 1 day of
// backfill), and that no Observations are generated on the remaining days.
TEST_F(UniqueActivesAggregateStoreTest, GenerateObservationsWithBackfill) {
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Adds 2 events to the local aggregations each day for 35 days. Call GenerateObservations() on
  // the first 5 day indices, and the 7th, out of every 10.
  for (int offset = 0; offset < 35; offset++) {
    auto day_index = CurrentDayIndex();
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kNetworkActivityWindowSizeMetricReportId,
                    day_index, 0u)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddUniqueActivesEvent(
              logger::testing::unique_actives::kNetworkActivityAggregationWindowMetricReportId,
              day_index, 0u)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kFeaturesActiveMetricReportId, day_index, 0u)
                    .error_code());
    }
    observation_store_->ResetObservationCounter();
    if (offset % 10 < 5 || offset % 10 == 6) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    }
    auto num_new_obs = observation_store_->num_observations_added();
    EXPECT_GE(num_new_obs, 0u);
    // Check that the expected daily number of Observations was generated.
    switch (offset % 10) {
      case 0:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs *
                      (kTestBackfillDays + 1),
                  num_new_obs);
        break;
      case 1:
      case 2:
      case 3:
      case 4:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs,
                  num_new_obs);
        break;
      case 6:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs * 2,
                  num_new_obs);
        break;
      default:
        EXPECT_EQ(0u, num_new_obs);
    }
    AdvanceClock(kDay);
  }
}

// Tests that GenerateObservations() returns a positive status and that the
// expected number of Observations is generated when events are logged over
// multiple days and some of those days' Observations are backfilled, and when
// the LocalAggregateStore is garbage-collected after each call to
// GenerateObservations().
//
// Sets the |backfill_days_| field of the EventAggregator to 3.
//
// Logging pattern:
// For 35 days, logs 2 events each day for the
// NetworkActivity_UniqueDevices reports and 2 events for the
// FeaturesActive_Unique_Devices report, all with event code 0.
//
// Observation generation pattern:
// Calls GenerateObservations() on the 1st through 5th and the 7th out of
// every 10 days, for 35 days. Garbage-collects the LocalAggregateStore after
// each call.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on
// the first day of every 10 (the day index for which GenerateObservations()
// was called, plus 3 days of backfill), that 1 day's worth of Observations
// are generated on the 2nd through 5th day of every 10, that 2 days'
// worth of Observations are generated on the 7th day of every 10 (the
// day index for which GenerateObservations() was called, plus 1 day of
// backfill), and that no Observations are generated on the remaining days.
TEST_F(UniqueActivesAggregateStoreTest, GenerateObservationsWithBackfillAndGc) {
  int num_days = 35;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Adds 2 events to the local aggregations each day for 35 days. Call GenerateObservations() on
  // the first 5 day indices, and the 7th, out of every 10.
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kNetworkActivityWindowSizeMetricReportId,
                    day_index, 0u)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddUniqueActivesEvent(
              logger::testing::unique_actives::kNetworkActivityAggregationWindowMetricReportId,
              day_index, 0u)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddUniqueActivesEvent(
                    logger::testing::unique_actives::kFeaturesActiveMetricReportId, day_index, 0u)
                    .error_code());
    }
    observation_store_->ResetObservationCounter();
    if (offset % 10 < 5 || offset % 10 == 6) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
      EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
    }
    auto num_new_obs = observation_store_->num_observations_added();
    EXPECT_GE(num_new_obs, 0u);
    // Check that the expected daily number of Observations was generated.
    // This expected number is some multiple of the daily_num_obs field of
    // |kUniqueActivesExpectedParams|, depending on the number of days which
    // should have been backfilled when GenerateObservations() was called.
    switch (offset % 10) {
      case 0:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs *
                      (kTestBackfillDays + 1),
                  num_new_obs);
        break;
      case 1:
      case 2:
      case 3:
      case 4:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs,
                  num_new_obs);
        break;
      case 6:
        EXPECT_EQ(logger::testing::unique_actives::kExpectedAggregationParams.daily_num_obs * 2,
                  num_new_obs);
        break;
      default:
        EXPECT_EQ(0u, num_new_obs);
    }
    AdvanceClock(kDay);
  }
}

// Checks that UniqueActivesObservations with the expected values (i.e.,
// non-active for all UNIQUE_N_DAY_ACTIVES reports, for all window sizes and
// event codes) are generated when no Events have been logged to the
// EventAggregator.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest, CheckObservationValuesNoEvents) {
  auto current_day_index = CurrentDayIndex();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(current_day_index).error_code());
  auto expected_obs = MakeNullExpectedUniqueActivesObservations(
      logger::testing::unique_actives_noise_free::kExpectedAggregationParams, current_day_index);
  EXPECT_TRUE(
      CheckUniqueActivesObservations(expected_obs, *observation_store_, update_recipient_.get()));
}

// Checks that UniqueActivesObservations with the expected values are
// generated when GenerateObservations() is called for a single day index
// after logging some events for UNIQUE_N_DAY_ACTIVES reports for that day
// index, without any garbage collection or backfill.
//
// Logging pattern:
// Logs 2 occurrences of event code 0 for the FeaturesActives_UniqueDevices
// report, and 1 occurrence of event code 1 for the
// EventsOccurred_UniqueDevices report, all on the same day.
//
// Observation generation pattern:
// Calls GenerateObservations() after logging all events.
//
// Expected numbers of Observations:
// The expected number of Observations is the daily_num_obs field of
// |logger::testing::unique_actives_noise_free::kExpectedAggregationParams|.
//
// Expected Observation values:
// All Observations should be labeled with the day index on which the events
// were logged.
//
// For the FeaturesActive_UniqueDevices report, expect activity indicators:
//
// window size        active for event codes
// ------------------------------------------
// 1                           0
// 7                           0
// 30                          0
//
// For the EventsOccurred_UniqueDevices report, expected activity indicators:
// window size        active for event codes
// ------------------------------------------
// 1                           1
// 7                           1
//
// All other Observations should be of inactivity.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest, CheckObservationValuesSingleDay) {
  auto day_index = CurrentDayIndex();
  // Adds several events to the local aggregations on |day_index|.
  EXPECT_EQ(
      StatusCode::OK,
      AddUniqueActivesEvent(
          logger::testing::unique_actives_noise_free::kFeaturesActiveMetricReportId, day_index, 0u)
          .error_code());
  EXPECT_EQ(
      StatusCode::OK,
      AddUniqueActivesEvent(
          logger::testing::unique_actives_noise_free::kFeaturesActiveMetricReportId, day_index, 0u)
          .error_code());
  EXPECT_EQ(
      StatusCode::OK,
      AddUniqueActivesEvent(
          logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId, day_index, 1u)
          .error_code());
  // Generate locally aggregated Observations for |day_index|.
  EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());

  // Form the expected observations.
  auto expected_obs = MakeNullExpectedUniqueActivesObservations(
      logger::testing::unique_actives_noise_free::kExpectedAggregationParams, day_index);
  expected_obs[{logger::testing::unique_actives_noise_free::kFeaturesActiveMetricReportId,
                day_index}] = {{1, {true, false, false, false, false}},
                               {7, {true, false, false, false, false}},
                               {28, {true, false, false, false, false}},
                               {30, {true, false, false, false, false}}};
  expected_obs[{logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId,
                day_index}] = {{1, {false, true, false, false, false}},
                               {7, {false, true, false, false, false}}};

  // Check the contents of the FakeObservationStore.
  EXPECT_TRUE(
      CheckUniqueActivesObservations(expected_obs, *observation_store_, update_recipient_.get()));
}

// Checks that UniqueActivesObservations with the expected values are
// generated when some events have been logged for a UNIQUE_N_DAY_ACTIVES
// report over multiple days and GenerateObservations() is called each
// day, without garbage collection or backfill.
//
// Logging pattern:
// Logs events for the EventsOccurred_UniqueDevices report (whose parent
// metric has max_event_code = 4) for 10 days, according to the following
// pattern:
//
// * Never log event code 0.
// * On the i-th day (0-indexed) of logging, log an event for event code k,
// 1 <= k < 5, if 3*k divides i.
//
// Observation generation pattern:
// Each day following the first day, generates Observations for the previous
// day index.
//
// Expected number of Observations:
// Each call to GenerateObservations should generate a number of Observations
// equal to the daily_num_obs field of
// |testing::unique_actives_noise_free::kExpectedAggregationParams|.
//
// Expected Observation values:
// The EventsOccurred_UniqueDevices report has window sizes 1 and 7, and
// the expected activity indicators of Observations for that report on the
// i-th day are:
//
// (i, window size)            active for event codes
// ------------------------------------------------------
// (0, 1)                           1, 2, 3, 4
// (0, 7)                           1, 2, 3, 4
// (1, 1)                          ---
// (1, 7)                           1, 2, 3, 4
// (2, 1)                          ---
// (2, 7)                           1, 2, 3, 4
// (3, 1)                           1
// (3, 7)                           1, 2, 3, 4
// (4, 1)                          ---
// (4, 7)                           1, 2, 3, 4
// (5, 1)                          ---
// (5, 7)                           1, 2, 3, 4
// (6, 1)                           1, 2
// (6, 7)                           1, 2, 3, 4
// (7, 1)                          ---
// (7, 7)                           1, 2
// (8, 1)                          ---
// (8, 7)                           1, 2
// (9, 1)                           1, 3
// (9, 7)                           1, 2, 3
//
// All Observations for all other locally aggregated reports should be
// observations of non-occurrence.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest, CheckObservationValuesMultiDay) {
  auto start_day_index = CurrentDayIndex();
  // Form expected Obsevations for the 10 days of logging.
  uint32_t num_days = 10;
  std::vector<ExpectedUniqueActivesObservations> expected_obs(num_days);
  const auto& expected_id =
      logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId;
  for (uint32_t offset = 0; offset < num_days; offset++) {
    expected_obs[offset] = MakeNullExpectedUniqueActivesObservations(
        logger::testing::unique_actives_noise_free::kExpectedAggregationParams,
        start_day_index + offset);
  }
  expected_obs[0][{expected_id, start_day_index}] = {{1, {false, true, true, true, true}},
                                                     {7, {false, true, true, true, true}}};
  expected_obs[1][{expected_id, start_day_index + 1}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[2][{expected_id, start_day_index + 2}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[3][{expected_id, start_day_index + 3}] = {{1, {false, true, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[4][{expected_id, start_day_index + 4}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[5][{expected_id, start_day_index + 5}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[6][{expected_id, start_day_index + 6}] = {{1, {false, true, true, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[7][{expected_id, start_day_index + 7}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, false, false}}};
  expected_obs[8][{expected_id, start_day_index + 8}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, false, false}}};
  expected_obs[9][{expected_id, start_day_index + 9}] = {{1, {false, true, false, true, false}},
                                                         {7, {false, true, true, true, false}}};

  for (uint32_t offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    for (uint32_t event_code = 1;
         event_code <
         logger::testing::unique_actives_noise_free::kExpectedAggregationParams.num_event_codes.at(
             expected_id);
         event_code++) {
      if (offset % (3 * event_code) == 0) {
        EXPECT_EQ(StatusCode::OK,
                  AddUniqueActivesEvent(expected_id, day_index, event_code).error_code());
      }
    }
    // Clear the FakeObservationStore.
    ResetObservationStore();
    // Generate locally aggregated Observations.
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    // Check the generated Observations against the expectation.
    EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[offset], *observation_store_,
                                               update_recipient_.get()));
    AdvanceClock(kDay);
  }
}

// Checks that UniqueActivesObservations with the expected values are
// generated when some events have been logged for a UNIQUE_N_DAY_ACTIVES
// report over multiple days and GenerateObservations() is called each
// day, and when the LocalAggregateStore is garbage-collected after each call
// to GenerateObservations().
//
// Logging pattern:
// Logs events for the EventsOccurred_UniqueDevices report (whose parent
// metric has max_event_code = 4) for 10 days, according to the following
// pattern:
//
// * Never log event code 0.
// * On the i-th day (0-indexed) of logging, log an event for event code k,
// 1 <= k < 5, if 3*k divides i.
//
// Observation generation pattern:
// Each day following the first day, generates Observations for the previous
// day index.
//
// Expected number of Observations:
// Each call to GenerateObservations should generate a number of Observations
// equal to the daily_num_obs field of
// |logger::testing::unique_actives_noise_free::kExpectedAggregationParams|.
//
// Expected Observation values:
// The EventsOccurred_UniqueDevices report has window sizes 1 and 7, and
// the expected activity indicators of Observations for that report on the
// i-th day are:
//
// (i, window size)            active for event codes
// ------------------------------------------------------
// (0, 1)                           1, 2, 3, 4
// (0, 7)                           1, 2, 3, 4
// (1, 1)                          ---
// (1, 7)                           1, 2, 3, 4
// (2, 1)                          ---
// (2, 7)                           1, 2, 3, 4
// (3, 1)                           1
// (3, 7)                           1, 2, 3, 4
// (4, 1)                          ---
// (4, 7)                           1, 2, 3, 4
// (5, 1)                          ---
// (5, 7)                           1, 2, 3, 4
// (6, 1)                           1, 2
// (6, 7)                           1, 2, 3, 4
// (7, 1)                          ---
// (7, 7)                           1, 2
// (8, 1)                          ---
// (8, 7)                           1, 2
// (9, 1)                           1, 3
// (9, 7)                           1, 2, 3
//
// All Observations for all other locally aggregated reports should be
// observations of non-occurrence.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest,
       CheckObservationValuesMultiDayWithGarbageCollection) {
  auto start_day_index = CurrentDayIndex();
  // Form expected Observations for the 10 days of logging.
  uint32_t num_days = 10;
  std::vector<ExpectedUniqueActivesObservations> expected_obs(num_days);
  const auto& expected_id =
      logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId;

  for (uint32_t offset = 0; offset < num_days; offset++) {
    expected_obs[offset] = MakeNullExpectedUniqueActivesObservations(
        logger::testing::unique_actives_noise_free::kExpectedAggregationParams,
        start_day_index + offset);
  }
  expected_obs[0][{expected_id, start_day_index}] = {{1, {false, true, true, true, true}},
                                                     {7, {false, true, true, true, true}}};
  expected_obs[1][{expected_id, start_day_index + 1}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[2][{expected_id, start_day_index + 2}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[3][{expected_id, start_day_index + 3}] = {{1, {false, true, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[4][{expected_id, start_day_index + 4}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[5][{expected_id, start_day_index + 5}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[6][{expected_id, start_day_index + 6}] = {{1, {false, true, true, false, false}},
                                                         {7, {false, true, true, true, true}}};
  expected_obs[7][{expected_id, start_day_index + 7}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, false, false}}};
  expected_obs[8][{expected_id, start_day_index + 8}] = {{1, {false, false, false, false, false}},
                                                         {7, {false, true, true, false, false}}};
  expected_obs[9][{expected_id, start_day_index + 9}] = {{1, {false, true, false, true, false}},
                                                         {7, {false, true, true, true, false}}};

  for (uint32_t offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    for (uint32_t event_code = 1;
         event_code <
         logger::testing::unique_actives_noise_free::kExpectedAggregationParams.num_event_codes.at(
             expected_id);
         event_code++) {
      if (offset % (3 * event_code) == 0) {
        EXPECT_EQ(StatusCode::OK,
                  AddUniqueActivesEvent(expected_id, day_index, event_code).error_code());
      }
    }
    // Advance |test_clock_| by 1 day.
    AdvanceClock(kDay);
    // Clear the FakeObservationStore.
    ResetObservationStore();
    // Generate locally aggregated Observations and garbage-collect the
    // LocalAggregateStore, both for the previous day as measured by
    // |test_clock_|. Back up the LocalAggregateStore and
    // AggregatedObservationHistoryStore.
    DoScheduledTasksNow();
    // Check the generated Observations against the expectation.
    EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[offset], *observation_store_,
                                               update_recipient_.get()));
  }
}

// Tests that the expected UniqueActivesObservations are generated when events
// are logged over multiple days and when Observations are backfilled for some
// days during that period, without any garbage-collection of the
// LocalAggregateStore.
//
// The test sets the number of backfill days to 3.
//
// Logging pattern:
// Events for the EventsOccurred_UniqueDevices report are logged over the days
// |start_day_index| to |start_day_index + 8| according to the following
// pattern:
//
// * For i = 0 to i = 4, log an event with event code i on day
// |start_day_index + i| and |start_day_index + 2*i|.
//
// Observation generation pattern:
// The test calls GenerateObservations() on day |start_day_index + i| for i =
// 0 through i = 5 and for i = 8, skipping the days |start_day_index + 6| and
// |start_day_index + 7|.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on the
// first day (the day index for which GenerateObservations() was called, plus
// 3 days of backfill), that 1 day's worth of Observations is generated on the
// 2nd through 6th day, that 3 days' worth of Observations are generated on
// the 9th day (the day index for which GenerateObservations() was called,
// plus 2 days of backfill), and that no Observations are generated on the
// remaining days.
//
// Expected Observation values:
// The expected activity indicators of Observations for the
// EventsOccurred_UniqueDevices report for the i-th day of logging are:
//
// (i, window size)           active for event codes
// -------------------------------------------------------------------------
// (0, 1)                           0
// (0, 7)                           0
// (1, 1)                           1
// (1, 7)                           0, 1
// (2, 1)                           1, 2
// (2, 7)                           0, 1, 2
// (3, 1)                           3
// (3, 7)                           0, 1, 2, 3
// (4, 1)                           2, 4
// (4, 7)                           0, 1, 2, 3, 4
// (5, 1)                          ---
// (5, 7)                           0, 1, 2, 3, 4
// (6, 1)                           3
// (6, 7)                           0, 1, 2, 3, 4
// (7, 1)                          ---
// (7, 7)                           1, 2, 3, 4
// (8, 1)                           4
// (8, 7)                           1, 2, 3, 4
//
// All other Observations should be of non-activity.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest, CheckObservationValuesWithBackfill) {
  auto start_day_index = CurrentDayIndex();
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  const auto& expected_id =
      logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId;
  const auto& expected_params =
      logger::testing::unique_actives_noise_free::kExpectedAggregationParams;
  // Add eventsto the local aggregations for 9 days. Call GenerateObservations() on the first 6
  // day indices, and the 9th.
  for (uint32_t offset = 0; offset < 9; offset++) {
    auto day_index = CurrentDayIndex();
    ResetObservationStore();
    for (uint32_t event_code = 0; event_code < expected_params.num_event_codes.at(expected_id);
         event_code++) {
      if (event_code == offset || (2 * event_code) == offset) {
        EXPECT_EQ(StatusCode::OK,
                  AddUniqueActivesEvent(expected_id, day_index, event_code).error_code());
      }
    }
    if (offset < 6 || offset == 8) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    }
    // Make the set of Observations which are expected to be generated on
    // |start_day_index + offset| and check it against the contents of the
    // FakeObservationStore.
    ExpectedUniqueActivesObservations expected_obs;
    switch (offset) {
      case 0: {
        for (uint32_t day_index = start_day_index - kTestBackfillDays; day_index <= start_day_index;
             day_index++) {
          for (const auto& pair :
               MakeNullExpectedUniqueActivesObservations(expected_params, day_index)) {
            expected_obs.insert(pair);
          }
        }
        expected_obs[{expected_id, start_day_index}] = {{1, {true, false, false, false, false}},
                                                        {7, {true, false, false, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 1: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 1);
        expected_obs[{expected_id, start_day_index + 1}] = {{1, {false, true, false, false, false}},
                                                            {7, {true, true, false, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 2: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 2);
        expected_obs[{expected_id, start_day_index + 2}] = {{1, {false, true, true, false, false}},
                                                            {7, {true, true, true, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 3: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 3);
        expected_obs[{expected_id, start_day_index + 3}] = {{1, {false, false, false, true, false}},
                                                            {7, {true, true, true, true, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 4: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 4);
        expected_obs[{expected_id, start_day_index + 4}] = {{1, {false, false, true, false, true}},
                                                            {7, {true, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 5: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 5);
        expected_obs[{expected_id, start_day_index + 5}] = {
            {1, {false, false, false, false, false}}, {7, {true, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 8: {
        for (uint32_t day_index = start_day_index + 6; day_index <= start_day_index + 8;
             day_index++) {
          for (const auto& pair :
               MakeNullExpectedUniqueActivesObservations(expected_params, day_index)) {
            expected_obs.insert(pair);
          }
        }
        expected_obs[{expected_id, start_day_index + 6}] = {{1, {false, false, false, true, false}},
                                                            {7, {true, true, true, true, true}}};
        expected_obs[{expected_id, start_day_index + 7}] = {
            {1, {false, false, false, false, false}}, {7, {false, true, true, true, true}}};
        expected_obs[{expected_id, start_day_index + 8}] = {{1, {false, false, false, false, true}},
                                                            {7, {false, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      default:
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
    }
    AdvanceClock(kDay);
  }
}

// Tests that the expected UniqueActivesObservations are generated when events
// are logged over multiple days and when Observations are backfilled for some
// days during that period, and when the LocalAggregateStore is
// garbage-collected after each call to GenerateObservations().
//
// The test sets the number of backfill days to 3.
//
// Logging pattern:
// Events for the EventsOccurred_UniqueDevices report are logged over the days
// |start_day_index| to |start_day_index + 8| according to the following
// pattern:
//
// * For i = 0 to i = 4, log an event with event code i on day
// |start_day_index + i| and |start_day_index + 2*i|.
//
// Observation generation pattern:
// The test calls GenerateObservations() on day |start_day_index + i| for i =
// 0 through i = 5 and for i = 8, skipping the days |start_day_index + 6| and
// |start_day_index + 7|.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on the
// first day (the day index for which GenerateObservations() was called, plus
// 3 days of backfill), that 1 day's worth of Observations is generated on the
// 2nd through 6th day, that 3 days' worth of Observations are generated on
// the 9th day (the day index for which GenerateObservations() was called,
// plus 2 days of backfill), and that no Observations are generated on the
// remaining days.
//
// Expected Observation values:
// The expected activity indicators of Observations for the
// EventsOccurred_UniqueDevices report for the i-th day of logging are:
//
// (i, window size)           active for event codes
// -------------------------------------------------------------------------
// (0, 1)                           0
// (0, 7)                           0
// (1, 1)                           1
// (1, 7)                           0, 1
// (2, 1)                           1, 2
// (2, 7)                           0, 1, 2
// (3, 1)                           3
// (3, 7)                           0, 1, 2, 3
// (4, 1)                           2, 4
// (4, 7)                           0, 1, 2, 3, 4
// (5, 1)                          ---
// (5, 7)                           0, 1, 2, 3, 4
// (6, 1)                           3
// (6, 7)                           0, 1, 2, 3, 4
// (7, 1)                          ---
// (7, 7)                           1, 2, 3, 4
// (8, 1)                           4
// (8, 7)                           1, 2, 3, 4
//
// All other Observations should be of non-activity.
TEST_F(UniqueActivesNoiseFreeAggregateStoreTest, CheckObservationValuesWithBackfillAndGc) {
  auto start_day_index = CurrentDayIndex();
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);

  const auto& expected_id =
      logger::testing::unique_actives_noise_free::kEventsOccurredMetricReportId;
  const auto& expected_params =
      logger::testing::unique_actives_noise_free::kExpectedAggregationParams;

  // Add events to the local aggregations for 9 days. Call GenerateObservations() on the first 6
  // day indices, and the 9th.
  for (uint32_t offset = 0; offset < 8; offset++) {
    auto day_index = CurrentDayIndex();
    ResetObservationStore();
    for (uint32_t event_code = 0; event_code < expected_params.num_event_codes.at(expected_id);
         event_code++) {
      if (event_code == offset || (2 * event_code) == offset) {
        EXPECT_EQ(StatusCode::OK,
                  AddUniqueActivesEvent(expected_id, day_index, event_code).error_code());
      }
    }
    // Advance |test_clock_| by 1 day.
    AdvanceClock(kDay);
    if (offset < 6 || offset == 9) {
      // Generate Observations and garbage-collect, both for the previous day
      // index according to |test_clock_|. Back up the LocalAggregateStore and
      // the AggregatedObservationHistoryStore.
      DoScheduledTasksNow();
    }
    // Make the set of Observations which are expected to be generated on
    // |start_day_index + offset| and check it against the contents of the
    // FakeObservationStore.
    ExpectedUniqueActivesObservations expected_obs;
    switch (offset) {
      case 0: {
        for (uint32_t day_index = start_day_index - kTestBackfillDays; day_index <= start_day_index;
             day_index++) {
          for (const auto& pair :
               MakeNullExpectedUniqueActivesObservations(expected_params, day_index)) {
            expected_obs.insert(pair);
          }
        }
        expected_obs[{expected_id, start_day_index}] = {{1, {true, false, false, false, false}},
                                                        {7, {true, false, false, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 1: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 1);
        expected_obs[{expected_id, start_day_index + 1}] = {{1, {false, true, false, false, false}},
                                                            {7, {true, true, false, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 2: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 2);
        expected_obs[{expected_id, start_day_index + 2}] = {{1, {false, true, true, false, false}},
                                                            {7, {true, true, true, false, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 3: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 3);
        expected_obs[{expected_id, start_day_index + 3}] = {{1, {false, false, false, true, false}},
                                                            {7, {true, true, true, true, false}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 4: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 4);
        expected_obs[{expected_id, start_day_index + 4}] = {{1, {false, false, true, false, true}},
                                                            {7, {true, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 5: {
        expected_obs =
            MakeNullExpectedUniqueActivesObservations(expected_params, start_day_index + 5);
        expected_obs[{expected_id, start_day_index + 5}] = {
            {1, {false, false, false, false, false}}, {7, {true, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      case 8: {
        for (uint32_t day_index = start_day_index + 6; day_index <= start_day_index + 8;
             day_index++) {
          for (const auto& pair :
               MakeNullExpectedUniqueActivesObservations(expected_params, day_index)) {
            expected_obs.insert(pair);
          }
        }
        expected_obs[{expected_id, start_day_index + 6}] = {{1, {false, false, false, true, false}},
                                                            {7, {true, true, true, true, true}}};
        expected_obs[{expected_id, start_day_index + 7}] = {
            {1, {false, false, false, false, false}}, {7, {false, true, true, true, true}}};
        expected_obs[{expected_id, start_day_index + 8}] = {{1, {false, false, false, false, true}},
                                                            {7, {false, true, true, true, true}}};
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
        break;
      }
      default:
        EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs, *observation_store_,
                                                   update_recipient_.get()));
    }
  }
}

// Tests GarbageCollect() for PerDeviceNumericReportAggregates.
//
// For each value of N in the range [0, 34], logs some events for
// PerDeviceNumeric reports each day for N consecutive days, and then
// garbage-collects the LocalAggregateStore. After garbage collection, verifies
// the contents of the LocalAggregateStore.
TEST_F(PerDeviceNumericAggregateStoreTest, GarbageCollect) {
  uint32_t max_days_before_gc = 35;
  for (uint32_t days_before_gc = 0; days_before_gc < max_days_before_gc; days_before_gc++) {
    SetUp();
    day_last_garbage_collected_ = 0u;
    LoggedValues logged_values;
    std::vector<MetricReportId> count_metric_report_ids = {
        logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
        logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId,
        logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId};
    std::vector<MetricReportId> elapsed_time_metric_report_ids = {
        logger::testing::per_device_numeric_stats::kStreamingTimeTotalMetricReportId,
        logger::testing::per_device_numeric_stats::kStreamingTimeMinMetricReportId,
        logger::testing::per_device_numeric_stats::kStreamingTimeMaxMetricReportId};
    MetricReportId frame_rate_metric_report_id =
        logger::testing::per_device_numeric_stats::kLoginModuleFrameRateMinMetricReportId;
    MetricReportId memory_usage_metric_report_id =
        logger::testing::per_device_numeric_stats::kLedgerMemoryUsageMaxMetricReportId;
    for (uint32_t offset = 0; offset < days_before_gc; offset++) {
      auto day_index = CurrentDayIndex();
      for (const auto& id : count_metric_report_ids) {
        for (const auto& component : {"component_A", "component_B", "component_C"}) {
          // Adds 2 events to the local aggregations with event code 0, for each component A, B,
          // C.
          EXPECT_EQ(StatusCode::OK,
                    AddPerDeviceEventCountEvent(id, day_index, component, 0u, 2, &logged_values)
                        .error_code());
          EXPECT_EQ(StatusCode::OK,
                    AddPerDeviceEventCountEvent(id, day_index, component, 0u, 3, &logged_values)
                        .error_code());
        }
        if (offset < 3) {
          // Adds 1 event to the local aggregations for component D and event code 1.
          EXPECT_EQ(StatusCode::OK,
                    AddPerDeviceEventCountEvent(id, day_index, "component_D", 1u, 4, &logged_values)
                        .error_code());
        }
      }
      for (const auto& id : elapsed_time_metric_report_ids) {
        for (const auto& component : {"component_A", "component_B", "component_C"}) {
          // Add 2 events to the local aggregations with event code 0, for each component A, B, C.
          EXPECT_EQ(StatusCode::OK,
                    AddPerDeviceElapsedTimeEvent(id, day_index, component, 0u, 2, &logged_values)
                        .error_code());
          EXPECT_EQ(StatusCode::OK,
                    AddPerDeviceElapsedTimeEvent(id, day_index, component, 0u, 3, &logged_values)
                        .error_code());
        }
        if (offset < 3) {
          // Add 1 event to the local aggregations for component D and event code 1.
          EXPECT_EQ(StatusCode::OK, AddPerDeviceElapsedTimeEvent(id, day_index, "component_D", 1u,
                                                                 4, &logged_values)
                                        .error_code());
        }
      }
      for (const auto& component : {"component_A", "component_B"}) {
        EXPECT_EQ(StatusCode::OK, AddPerDeviceFrameRateEvent(frame_rate_metric_report_id, day_index,
                                                             component, 0u, 2.25, &logged_values)
                                      .error_code());
        EXPECT_EQ(StatusCode::OK, AddPerDeviceFrameRateEvent(frame_rate_metric_report_id, day_index,
                                                             component, 0u, 1.75, &logged_values)
                                      .error_code());
        EXPECT_EQ(StatusCode::OK,
                  AddPerDeviceMemoryUsageEvent(memory_usage_metric_report_id, day_index, component,
                                               std::vector<uint32_t>{0u, 0u}, 300, &logged_values)
                      .error_code());
        EXPECT_EQ(StatusCode::OK,
                  AddPerDeviceMemoryUsageEvent(memory_usage_metric_report_id, day_index, component,
                                               std::vector<uint32_t>{1u, 0u}, 300, &logged_values)
                      .error_code());
      }
      AdvanceClock(kDay);
    }
    auto end_day_index = CurrentDayIndex();
    EXPECT_EQ(StatusCode::OK, GarbageCollect(end_day_index).error_code());
    day_last_garbage_collected_ = end_day_index;
    EXPECT_TRUE(CheckPerDeviceNumericAggregates(logged_values, end_day_index));
    TearDown();
  }
}

// Tests that EventAggregator::GenerateObservations() returns a positive
// status and that the expected number of Observations is generated after
// some EventCountEvents have been logged for PerDeviceNumericStats reports, without
// any garbage collection.
//
// For 35 days, logs a positive number of events each day for the
// ConnectionFailures_PerDeviceNumericStats report with "component_A" and for
// the SettingsChanged_PerDeviceNumericStats reports with "component_B", all with
// event code 0.
//
// Each day, calls GenerateObservations() with the day index of the previous
// day. Checks that a positive status is returned and that the
// FakeObservationStore has received the expected number of new observations
// for each locally aggregated report ID in the per_device_numeric_stats test
// registry.
TEST_F(PerDeviceNumericAggregateStoreTest, GenerateObservations) {
  int num_days = 1;
  std::vector<Observation> observations(0);
  ExpectedAggregationParams expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    observations.clear();
    ResetObservationStore();
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
    EXPECT_TRUE(FetchAggregatedObservations(&observations, expected_params, *observation_store_,
                                            update_recipient_.get()));
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddPerDeviceEventCountEvent(
              logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
              day_index, "component_B", 0u, 5)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                                kSettingsChangedAggregationWindowMetricReportId,
                                            day_index, "component_B", 0u, 5)
                    .error_code());
    }
    // If this is the first time we're logging events, update the expected
    // numbers of generated Observations to account for the logged events.
    // For each report, for each aggregation window, expect 1 Observation more than if
    // no events had been logged.
    if (offset == 0) {
      expected_params.daily_num_obs += 5;
      expected_params.num_obs_per_report
          [logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId] += 1;
      expected_params.num_obs_per_report
          [logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId] +=
          2;
      expected_params.num_obs_per_report[logger::testing::per_device_numeric_stats::
                                             kSettingsChangedAggregationWindowMetricReportId] += 2;
    }
    AdvanceClock(kDay);
  }
  observations.clear();
  ResetObservationStore();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(CurrentDayIndex() - 1).error_code());
  EXPECT_TRUE(FetchAggregatedObservations(&observations, expected_params, *observation_store_,
                                          update_recipient_.get()));
}

// Tests that EventAggregator::GenerateObservations() returns a positive
// status and that the expected number of Observations is generated after
// some EventCountEvents have been logged for PerDeviceNumeric reports over multiple
// days, and when the LocalAggregateStore is garbage-collected each day.
//
// For 35 days, logs a positive number of events each day for the
// ConnectionFailures_PerDeviceNumeric report with "component_A" and for
// the SettingsChanged_PerDeviceNumeric report with "component_B", all with
// event code 0.
//
// Each day, calls GenerateObservations() with the day index of the previous
// day. Checks that a positive status is returned and that the
// FakeObservationStore has received the expected number of new observations
// for each locally aggregated report ID in the per_device_numeric_stats test
// registry.
TEST_F(PerDeviceNumericAggregateStoreTest, GenerateObservationsWithGc) {
  int num_days = 35;
  std::vector<Observation> observations(0);
  ExpectedAggregationParams expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    observations.clear();
    ResetObservationStore();
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
    EXPECT_TRUE(FetchAggregatedObservations(&observations, expected_params, *observation_store_,
                                            update_recipient_.get()));
    EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddPerDeviceEventCountEvent(
              logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
              day_index, "component_B", 0u, 5)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                                kSettingsChangedAggregationWindowMetricReportId,
                                            day_index, "component_B", 0u, 5)
                    .error_code());
    }
    // If this is the first time we're logging events, update the expected
    // numbers of generated Observations to account for the logged events.
    // For each report, for each window size, expect 1 Observation more than if
    // no events had been logged.
    if (offset == 0) {
      expected_params.daily_num_obs += 5;
      expected_params.num_obs_per_report
          [logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId] += 1;
      expected_params.num_obs_per_report
          [logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId] +=
          2;
      expected_params.num_obs_per_report[logger::testing::per_device_numeric_stats::
                                             kSettingsChangedAggregationWindowMetricReportId] += 2;
    }
    AdvanceClock(kDay);
  }
  observations.clear();
  ResetObservationStore();
  auto day_index = CurrentDayIndex();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index - 1).error_code());
  EXPECT_TRUE(FetchAggregatedObservations(&observations, expected_params, *observation_store_,
                                          update_recipient_.get()));
  EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
}

// Tests that GenerateObservations() returns a positive status and that the
// expected number of Observations is generated when events are logged over
// multiple days and some of those days' Observations are backfilled, without
// any garbage collection of the LocalAggregateStore.
//
// Sets the |backfill_days_| field of the EventAggregator to 3.
//
// Logging pattern:
// For 35 days, logs 2 events each day for the
// ConnectionFailures_PerDeviceCount report and 2 events for the
// SettingsChanged_PerDeviceCount report, all with event code 0.
//
// Observation generation pattern:
// Calls GenerateObservations() on the 1st through 5th and the 7th out of
// every 10 days, for 35 days.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on
// the first day of every 10 (the day index for which GenerateObservations()
// was called, plus 3 days of backfill), that 1 day's worth of Observations
// are generated on the 2nd through 5th day of every 10, that 2 days'
// worth of Observations are generated on the 7th day of every 10 (the
// day index for which GenerateObservations() was called, plus 1 day of
// backfill), and that no Observations are generated on the remaining days.
TEST_F(PerDeviceNumericAggregateStoreTest, GenerateObservationsWithBackfill) {
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Add 2 events to the local aggregations each day for 35 days. Call GenerateObservations() on
  // the first 5 day indices, and the 7th, out of every 10.
  for (int offset = 0; offset < 35; offset++) {
    auto day_index = CurrentDayIndex();
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddPerDeviceEventCountEvent(
              logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
              day_index, "component_B", 0u, 5)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                                kSettingsChangedAggregationWindowMetricReportId,
                                            day_index, "component_B", 0u, 5)
                    .error_code());
    }
    auto num_obs_before = observation_store_->messages_received.size();
    if (offset % 10 < 5 || offset % 10 == 6) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    }
    auto num_obs_after = observation_store_->messages_received.size();
    EXPECT_GE(num_obs_after, num_obs_before);
    // Check that the expected daily number of Observations was generated.
    switch (offset % 10) {
      case 0:
        // If this is the first day of logging, expect 3 Observations for each
        // day in the backfill period and 8 Observations for the current day.
        if (offset == 0) {
          EXPECT_EQ((expected_params.daily_num_obs * kTestBackfillDays) +
                        expected_params.daily_num_obs + 5,
                    num_obs_after - num_obs_before);
        } else {
          // If this is another day whose offset is a multiple of 10, expect 8
          // Observations for each day in the backfill period as well as the
          // current day.
          EXPECT_EQ((expected_params.daily_num_obs + 5) * (kTestBackfillDays + 1),
                    num_obs_after - num_obs_before);
        }
        break;
      case 1:
      case 2:
      case 3:
      case 4:
        // Expect 8 Observations for this day.
        EXPECT_EQ(expected_params.daily_num_obs + 5, num_obs_after - num_obs_before);
        break;
      case 6:
        // Expect 8 Observations for each of today and yesterday.
        EXPECT_EQ((expected_params.daily_num_obs + 5) * 2, num_obs_after - num_obs_before);
        break;
      default:
        EXPECT_EQ(num_obs_after, num_obs_before);
    }
    AdvanceClock(kDay);
  }
}

// Tests that GenerateObservations() returns a positive status and that the
// expected number of Observations is generated when events are logged over
// multiple days and some of those days' Observations are backfilled, and when
// the LocalAggregateStore is garbage-collected after each call to
// GenerateObservations().
//
// Sets the |backfill_days_| field of the EventAggregator to 3.
//
// Logging pattern:
// For 35 days, logs 2 events each day for the
// ConnectionFailures_PerDeviceNumeric report with "component_A" and 2 events
// for the SettingsChanged_PerDeviceNumeric reports with "component_B", all with
// event code 0.
//
// Observation generation pattern:
// Calls GenerateObservations() on the 1st through 5th and the 7th out of
// every 10 days, for 35 days. Garbage-collects the LocalAggregateStore after
// each call.
//
// Expected numbers of Observations:
// It is expected that 4 days' worth of Observations are generated on
// the first day of every 10 (the day index for which GenerateObservations()
// was called, plus 3 days of backfill), that 1 day's worth of Observations
// are generated on the 2nd through 5th day of every 10, that 2 days'
// worth of Observations are generated on the 7th day of every 10 (the
// day index for which GenerateObservations() was called, plus 1 day of
// backfill), and that no Observations are generated on the remaining days.
TEST_F(PerDeviceNumericAggregateStoreTest, GenerateObservationsWithBackfillAndGc) {
  int num_days = 35;
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Add 2 events to the local aggregations each day for 35 days. Call GenerateObservations() on
  // the first 5 day indices, and the 7th, out of every 10.
  for (int offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    for (int i = 0; i < 2; i++) {
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(
                    logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                    day_index, "component_A", 0u, 1)
                    .error_code());
      EXPECT_EQ(
          StatusCode::OK,
          AddPerDeviceEventCountEvent(
              logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
              day_index, "component_B", 0u, 5)
              .error_code());
      EXPECT_EQ(StatusCode::OK,
                AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                                kSettingsChangedAggregationWindowMetricReportId,
                                            day_index, "component_B", 0u, 5)
                    .error_code());
    }
    auto num_obs_before = observation_store_->messages_received.size();
    if (offset % 10 < 5 || offset % 10 == 6) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
      EXPECT_EQ(StatusCode::OK, GarbageCollect(day_index).error_code());
    }
    auto num_obs_after = observation_store_->messages_received.size();
    EXPECT_GE(num_obs_after, num_obs_before);
    // Check that the expected daily number of Observations was generated.
    switch (offset % 10) {
      case 0:
        // If this is the first day of logging, expect 3 Observations for each
        // day in the backfill period and 8 Observations for the current day.
        if (offset == 0) {
          EXPECT_EQ((expected_params.daily_num_obs * kTestBackfillDays) +
                        expected_params.daily_num_obs + 5,
                    num_obs_after - num_obs_before);
        } else {
          // If this is another day whose offset is a multiple of 10, expect 8
          // Observations for each day in the backfill period as well as the
          // current day.
          EXPECT_EQ((expected_params.daily_num_obs + 5) * (kTestBackfillDays + 1),
                    num_obs_after - num_obs_before);
        }
        break;
      case 1:
      case 2:
      case 3:
      case 4:
        // Expect 8 Observations for this day.
        EXPECT_EQ(expected_params.daily_num_obs + 5, num_obs_after - num_obs_before);
        break;
      case 6:
        // Expect 6 Observations for each of today and yesterday.
        EXPECT_EQ((expected_params.daily_num_obs + 5) * 2, num_obs_after - num_obs_before);
        break;
      default:
        EXPECT_EQ(num_obs_after, num_obs_before);
    }
    AdvanceClock(kDay);
  }
}

// Generate Observations without logging any events, and check that the
// resulting Observations are as expected: 1 ReportParticipationObservation for
// each PER_DEVICE_NUMERIC_STATS report in the config, and no
// PerDeviceNumericObservations.
TEST_F(PerDeviceNumericAggregateStoreTest, CheckObservationValuesNoEvents) {
  const auto current_day_index = CurrentDayIndex();
  EXPECT_EQ(StatusCode::OK, GenerateObservations(current_day_index).error_code());
  const auto& expected_report_participation_obs = MakeExpectedReportParticipationObservations(
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams, current_day_index);
  EXPECT_TRUE(CheckPerDeviceNumericObservations({}, expected_report_participation_obs,
                                                *observation_store_, update_recipient_.get()));
}

// Check that the expected PerDeviceNumericObservations and
// ReportParticipationObservations are generated when GenerateObservations() is
// called after logging some EventCountEvents and ElapsedTimeEvents for
// PER_DEVICE_NUMERIC_STATS reports over a single day index.
TEST_F(PerDeviceNumericAggregateStoreTest, CheckObservationValuesSingleDay) {
  const auto day_index = CurrentDayIndex();
  // Add several events to the local aggregations on |day_index|.
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                day_index, "component_A", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                day_index, "component_B", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                day_index, "component_A", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId,
                day_index, "component_A", 1u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
                day_index, "component_C", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
                day_index, "component_C", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                            kSettingsChangedAggregationWindowMetricReportId,
                                        day_index, "component_C", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(logger::testing::per_device_numeric_stats::
                                            kSettingsChangedAggregationWindowMetricReportId,
                                        day_index, "component_C", 0u, 5)
                .error_code());

  std::vector<MetricReportId> streaming_time_ids = {
      logger::testing::per_device_numeric_stats::kStreamingTimeTotalMetricReportId,
      logger::testing::per_device_numeric_stats::kStreamingTimeMinMetricReportId,
      logger::testing::per_device_numeric_stats::kStreamingTimeMaxMetricReportId};
  for (const auto& id : streaming_time_ids) {
    EXPECT_EQ(StatusCode::OK,
              AddPerDeviceElapsedTimeEvent(id, day_index, "component_D", 0u, 15).error_code());
    EXPECT_EQ(StatusCode::OK,
              AddPerDeviceElapsedTimeEvent(id, day_index, "component_D", 1u, 5).error_code());
    EXPECT_EQ(StatusCode::OK,
              AddPerDeviceElapsedTimeEvent(id, day_index, "component_D", 0u, 10).error_code());
  }
  // Generate locally aggregated Observations for |day_index|.
  EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());

  // Form the expected Observations.
  auto expected_report_participation_obs = MakeExpectedReportParticipationObservations(
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams, day_index);
  ExpectedPerDeviceNumericObservations expected_per_device_numeric_obs;
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kConnectionFailuresMetricReportId, day_index}][1] =
      {{"component_A", 0u, 10}, {"component_A", 1u, 5}, {"component_B", 0u, 5}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
      day_index}][7] = {{"component_C", 0u, 10}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kSettingsChangedWindowSizeMetricReportId,
      day_index}][30] = {{"component_C", 0u, 10}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId,
      day_index}][7] = {{"component_C", 0u, 10}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId,
      day_index}][30] = {{"component_C", 0u, 10}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeTotalMetricReportId, day_index}][1] =
      {{"component_D", 0u, 25}, {"component_D", 1u, 5}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeTotalMetricReportId, day_index}][7] =
      {{"component_D", 0u, 25}, {"component_D", 1u, 5}};
  // The 7-day minimum value for the StreamingTime metric is 0 for all event
  // codes and components, so we don't expect a PerDeviceNumericObservation with
  // a 7-day window for the StreamingTime_PerDeviceMin report.
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeMinMetricReportId, day_index}][1] = {
      {"component_D", 0u, 10}, {"component_D", 1u, 5}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeMinMetricReportId, day_index}][7] = {
      {"component_D", 0u, 10}, {"component_D", 1u, 5}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeMaxMetricReportId, day_index}][1] = {
      {"component_D", 0u, 15}, {"component_D", 1u, 5}};
  expected_per_device_numeric_obs[{
      logger::testing::per_device_numeric_stats::kStreamingTimeMaxMetricReportId, day_index}][7] = {
      {"component_D", 0u, 15}, {"component_D", 1u, 5}};

  EXPECT_TRUE(CheckPerDeviceNumericObservations(expected_per_device_numeric_obs,
                                                expected_report_participation_obs,
                                                *observation_store_, update_recipient_.get()));
}

// Checks that PerDeviceNumericObservations with the expected values are
// generated when some events have been logged for an EVENT_COUNT metric with
// a PER_DEVICE_NUMERIC_STATS report over multiple days and
// GenerateObservations() is called each day, without garbage collection or
// backfill.
//
// Logged events for the SettingsChanged_PerDeviceCount report on the i-th
// day:
//
//  i            (component, event code, count)
// -----------------------------------------------------------------------
//  0
//  1          ("A", 1, 3)
//  2          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
//  3          ("A", 1, 3)
//  4          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//  5          ("A", 1, 3)
//  6          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
//  7          ("A", 1, 3)
//  8          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//  9          ("A", 1, 3)
//
// Expected PerDeviceNumericObservations for the
// SettingsChanged_PerDeviceNumeric report on the i-th day:
//
// (i, window size)          (component, event code, count)
// -----------------------------------------------------------------------
// (0, 7)
// (0, 30)
// (1, 7)     ("A", 1,  3)
// (1, 30)    ("A", 1,  3)
// (2, 7)     ("A", 1,  6),  ("A", 2,  3), ("B", 1, 2)
// (2, 30)    ("A", 1,  6),  ("A", 2,  3), ("B", 1, 2)
// (3, 7)     ("A", 1,  9),  ("A", 2,  3), ("B", 1, 2)
// (3, 30)    ("A", 1,  9),  ("A", 2,  3), ("B", 1, 2)
// (4, 7)     ("A", 1, 12),  ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (4, 30)    ("A", 1, 12),  ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (5, 7)     ("A", 1, 15),  ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (5, 30)    ("A", 1, 15),  ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (6, 7)     ("A", 1, 18),  ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (6, 30)    ("A", 1, 18),  ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (7, 7)     ("A", 1, 21),  ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (7, 30)    ("A", 1, 21),  ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (8, 7)     ("A", 1, 21),  ("A", 2, 12), ("B", 1, 8), ("B", 2, 4)
// (8, 30)    ("A", 1, 24),  ("A", 2, 12), ("B", 1, 8), ("B", 2, 4)
// (9, 7)     ("A", 1, 21),  ("A", 2,  9), ("B", 1, 6), ("B", 2, 4)
// (9, 30)    ("A", 1, 27),  ("A", 2, 12), ("B", 1, 8), ("B", 2, 4)
//
// In addition, expect 1 ReportParticipationObservation each day for each of
// the reports in the registry.
TEST_F(PerDeviceNumericAggregateStoreTest, CheckObservationValuesMultiDay) {
  auto start_day_index = CurrentDayIndex();
  const auto& expected_id =
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId;
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Form expected Observations for the 10 days of logging.
  uint32_t num_days = 10;
  std::vector<ExpectedPerDeviceNumericObservations> expected_per_device_numeric_obs(num_days);
  std::vector<ExpectedReportParticipationObservations> expected_report_participation_obs(num_days);
  for (uint32_t offset = 0; offset < num_days; offset++) {
    expected_report_participation_obs[offset] =
        MakeExpectedReportParticipationObservations(expected_params, start_day_index + offset);
  }
  expected_per_device_numeric_obs[0] = {};
  expected_per_device_numeric_obs[1][{expected_id, start_day_index + 1}] = {{7, {{"A", 1u, 3}}},
                                                                            {30, {{"A", 1u, 3}}}};
  expected_per_device_numeric_obs[2][{expected_id, start_day_index + 2}] = {
      {7, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}},
      {30, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}}};
  expected_per_device_numeric_obs[3][{expected_id, start_day_index + 3}] = {
      {7, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}},
      {30, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}}};
  expected_per_device_numeric_obs[4][{expected_id, start_day_index + 4}] = {
      {7, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[5][{expected_id, start_day_index + 5}] = {
      {7, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[6][{expected_id, start_day_index + 6}] = {
      {7, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[7][{expected_id, start_day_index + 7}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[8][{expected_id, start_day_index + 8}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}},
      {30, {{"A", 1u, 24}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};
  expected_per_device_numeric_obs[9][{expected_id, start_day_index + 9}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 4}}},
      {30, {{"A", 1u, 27}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};

  for (uint32_t offset = 0; offset < 1; offset++) {
    auto day_index = CurrentDayIndex();
    for (uint32_t event_code = 1; event_code < 3; event_code++) {
      if (offset > 0 && offset % event_code == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "A", event_code, 3).error_code());
      }
      if (offset > 0 && offset % (2 * event_code) == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "B", event_code, 2).error_code());
      }
    }
    // Clear the FakeObservationStore.
    ResetObservationStore();
    // Generate locally aggregated Observations.
    EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    EXPECT_TRUE(CheckPerDeviceNumericObservations(expected_per_device_numeric_obs[offset],
                                                  expected_report_participation_obs[offset],
                                                  *observation_store_, update_recipient_.get()))
        << "offset = " << offset;
    AdvanceClock(kDay);
  }
}

// Repeat the CheckObservationValuesMultiDay test, this time calling
// GarbageCollect() after each call to GenerateObservations.
//
// The logging pattern and set of Observations for each day index is the same
// as in PerDeviceNumericAggregateStoreTest::CheckObservationValuesMultiDay.
// See that test for documentation.
TEST_F(PerDeviceNumericAggregateStoreTest, CheckObservationValuesMultiDayWithGarbageCollection) {
  auto start_day_index = CurrentDayIndex();
  const auto& expected_id =
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId;
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Form expected Observations for the 10 days of logging.
  uint32_t num_days = 10;
  std::vector<ExpectedPerDeviceNumericObservations> expected_per_device_numeric_obs(num_days);
  std::vector<ExpectedReportParticipationObservations> expected_report_participation_obs(num_days);
  for (uint32_t offset = 0; offset < num_days; offset++) {
    expected_report_participation_obs[offset] =
        MakeExpectedReportParticipationObservations(expected_params, start_day_index + offset);
  }
  expected_per_device_numeric_obs[0] = {};
  expected_per_device_numeric_obs[1][{expected_id, start_day_index + 1}] = {{7, {{"A", 1u, 3}}},
                                                                            {30, {{"A", 1u, 3}}}};
  expected_per_device_numeric_obs[2][{expected_id, start_day_index + 2}] = {
      {7, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}},
      {30, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}}};
  expected_per_device_numeric_obs[3][{expected_id, start_day_index + 3}] = {
      {7, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}},
      {30, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}}};
  expected_per_device_numeric_obs[4][{expected_id, start_day_index + 4}] = {
      {7, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[5][{expected_id, start_day_index + 5}] = {
      {7, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[6][{expected_id, start_day_index + 6}] = {
      {7, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[7][{expected_id, start_day_index + 7}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
      {30, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
  expected_per_device_numeric_obs[8][{expected_id, start_day_index + 8}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}},
      {30, {{"A", 1u, 24}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};
  expected_per_device_numeric_obs[9][{expected_id, start_day_index + 9}] = {
      {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 4}}},
      {30, {{"A", 1u, 27}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};

  for (uint32_t offset = 0; offset < 10; offset++) {
    auto day_index = CurrentDayIndex();
    for (uint32_t event_code = 1; event_code < 3; event_code++) {
      if (offset > 0 && offset % event_code == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "A", event_code, 3).error_code());
      }
      if (offset > 0 && offset % (2 * event_code) == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "B", event_code, 2).error_code());
      }
    }
    // Advance |test_clock_| by 1 day.
    AdvanceClock(kDay);
    // Clear the FakeObservationStore.
    ResetObservationStore();
    // Generate locally aggregated Observations and garbage-collect the
    // LocalAggregateStore, both for the previous day as measured by
    // |test_clock_|. Back up the LocalAggregateStore and
    // AggregatedObservationHistoryStore.
    DoScheduledTasksNow();
    EXPECT_TRUE(CheckPerDeviceNumericObservations(expected_per_device_numeric_obs[offset],
                                                  expected_report_participation_obs[offset],
                                                  *observation_store_, update_recipient_.get()));
  }
}

// Tests that the expected PerDeviceNumericObservations are generated when
// events are logged over multiple days for an EVENT_COUNT
// metric with a PER_DEVICE_NUMERIC_STATS report, when Observations are
// backfilled for some days during that period, without any garbage-collection
// of the LocalAggregateStore.
//
// The logging pattern and set of Observations for each day index is the same
// as in PerDeviceNumericAggregateStoreTest::CheckObservationValuesMultiDay.
// See that test for documentation.
TEST_F(PerDeviceNumericAggregateStoreTest, CheckObservationValuesWithBackfill) {
  auto start_day_index = CurrentDayIndex();
  const auto& expected_id =
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId;
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Add events to the local aggregations for 9 days. Call GenerateObservations() on the first 6
  // day indices, and the 9th.
  uint32_t num_days = 9;
  for (uint32_t offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    ResetObservationStore();
    for (uint32_t event_code = 1; event_code < 3; event_code++) {
      if (offset > 0 && (offset % event_code == 0)) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "A", event_code, 3).error_code());
      }
      if (offset > 0 && offset % (2 * event_code) == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "B", event_code, 2).error_code());
      }
    }
    if (offset < 6 || offset == 8) {
      EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
    }
    // Make the set of Observations which are expected to be generated on
    // |start_day_index + offset| and check it against the contents of the
    // FakeObservationStore.
    ExpectedPerDeviceNumericObservations expected_per_device_numeric_obs;
    ExpectedReportParticipationObservations expected_report_participation_obs;
    switch (offset) {
      case 0: {
        for (uint32_t day_index = start_day_index - kTestBackfillDays; day_index <= start_day_index;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 1: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {{7, {{"A", 1u, 3}}},
                                                                     {30, {{"A", 1u, 3}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 2: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {30, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 3: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {30, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 4: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 5: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 8: {
        expected_per_device_numeric_obs[{expected_id, start_day_index + 6}] = {
            {7, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{expected_id, start_day_index + 7}] = {
            {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{expected_id, start_day_index + 8}] = {
            {7, {{"A", 1u, 21}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}},
            {30, {{"A", 1u, 24}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};
        for (uint32_t day_index = start_day_index + 6; day_index <= start_day_index + 8;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      default:
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
    }
    AdvanceClock(kDay);
  }
}

// Tests that the expected Observations are generated for
// PerDeviceNumericStats reports when events are logged for over multiple days
// for an EVENT_COUNT metric with a PER_DEVICE_NUMERIC_STATS report, when
// Observations are backfilled for some days during that period, and when the
// LocalAggregatedStore is garbage-collected after each call to
// GenerateObservations().
//
// The logging pattern and set of Observations for each day index is the same
// as in PerDeviceNumericAggregateStoreTest::CheckObservationValuesMultiDay.
// See that test for documentation.
TEST_F(PerDeviceNumericAggregateStoreTest, EventCountCheckObservationValuesWithBackfillAndGc) {
  auto start_day_index = CurrentDayIndex();
  const auto& expected_id =
      logger::testing::per_device_numeric_stats::kSettingsChangedAggregationWindowMetricReportId;
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Add events to the local aggregations for 9 days. Call GenerateObservations() on the first 6
  // day indices, and the 9th.
  uint32_t num_days = 9;
  for (uint32_t offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    ResetObservationStore();
    for (uint32_t event_code = 1; event_code < 3; event_code++) {
      if (offset > 0 && (offset % event_code == 0)) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "A", event_code, 3).error_code());
      }
      if (offset > 0 && offset % (2 * event_code) == 0) {
        EXPECT_EQ(
            StatusCode::OK,
            AddPerDeviceEventCountEvent(expected_id, day_index, "B", event_code, 2).error_code());
      }
    }
    // Advance |test_clock_| by 1 day.
    AdvanceClock(kDay);
    if (offset < 6 || offset == 8) {
      // Generate Observations and garbage-collect, both for the previous day
      // index according to |test_clock_|. Back up the LocalAggregateStore and
      // the AggregatedObservationHistoryStore.
      DoScheduledTasksNow();
    }
    // Make the set of Observations which are expected to be generated on
    // |start_day_index + offset| and check it against the contents of the
    // FakeObservationStore.
    ExpectedPerDeviceNumericObservations expected_per_device_numeric_obs;
    ExpectedReportParticipationObservations expected_report_participation_obs;
    switch (offset) {
      case 0: {
        for (uint32_t day_index = start_day_index - kTestBackfillDays; day_index <= start_day_index;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 1: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {{7, {{"A", 1u, 3}}},
                                                                     {30, {{"A", 1u, 3}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 2: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {30, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 3: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {30, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 4: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 5: {
        expected_per_device_numeric_obs[{expected_id, day_index}] = {
            {7, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 8: {
        expected_per_device_numeric_obs[{expected_id, start_day_index + 6}] = {
            {7, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{expected_id, start_day_index + 7}] = {
            {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}},
            {30, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{expected_id, start_day_index + 8}] = {
            {7, {{"A", 1u, 21}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}},
            {30, {{"A", 1u, 24}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};
        for (uint32_t day_index = start_day_index + 6; day_index <= start_day_index + 8;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      default:
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
    }
  }
}

// Tests that the expected Observations are generated for
// PerDeviceNumericStats reports when events are logged for over multiple days
// for an ELAPSED_TIME metric with PER_DEVICE_NUMERIC_STATS reports with
// multiple aggregation types, when Observations are backfilled for some days
// during that period, and when the LocalAggregatedStore is garbage-collected
// after each call to GenerateObservations().
//
// Logged events for the StreamingTime_PerDevice{Total, Min, Max} reports on the
// i-th day:
//
//  i            (component, event code, count)
// -----------------------------------------------------------------------
//  0
//  1          ("A", 1, 3)
//  2          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
//  3          ("A", 1, 3)
//  4          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//  5          ("A", 1, 3)
//  6          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
//  7          ("A", 1, 3)
//  8          ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//
// Expected PerDeviceNumericObservations for the
// StreamingTime_PerDeviceTotal report on the i-th day:
//
// (day, window size)            (event code, component, total)
// ---------------------------------------------------------------------------
// (0, 1)
// (0, 7)
// (1, 1)     ("A", 1,  3)
// (1, 7)     ("A", 1,  3)
// (2, 1)     ("A", 1,  3), ("A", 2,  3), ("B", 1, 2)
// (2, 7)     ("A", 1,  6), ("A", 2,  3), ("B", 1, 2)
// (3, 1)     ("A", 1,  3)
// (3, 7)     ("A", 1,  9), ("A", 2,  3), ("B", 1, 2)
// (4, 1)     ("A", 1,  3), ("A", 2,  3), ("B", 1, 2), ("B", 2, 2)
// (4, 7)     ("A", 1, 12), ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (5, 1)     ("A", 1,  3)
// (5, 7)     ("A", 1, 15), ("A", 2,  6), ("B", 1, 4), ("B", 2, 2)
// (6, 1)     ("A", 1,  3), ("A", 2,  3), ("B", 1, 2)
// (6, 7)     ("A", 1, 18), ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (7, 1)     ("A", 1,  3)
// (7, 7)     ("A", 1, 21), ("A", 2,  9), ("B", 1, 6), ("B", 2, 2)
// (8, 1)     ("A", 1,  3), ("A", 2,  3), ("B", 1, 2), ("B", 2, 2)
// (8, 7)     ("A", 1, 21), ("A", 2, 12), ("B", 1, 8), ("B", 2, 4)
//
// Expected PerDeviceNumericObservations for the
// StreamingTime_PerDeviceMin report on the i-th day:
//
// (day, window size)            (event code, component, total)
// ---------------------------------------------------------------------------
// (0, 1)
// (0. 7)
// (1, 1)     ("A", 1, 3)
// (1, 7)     ("A", 1, 3)
// (2, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (2, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (3, 1)     ("A", 1, 3)
// (3, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (4, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (4, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (5, 1)     ("A", 1, 3)
// (5, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (6, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (6, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (7, 1)     ("A", 1, 3)
// (7, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (8, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (8, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//
// Expected PerDeviceNumericObservations for the
// StreamingTime_PerDeviceMax report on the i-th day:
//
// (day, window size)            (event code, component, total)
// ---------------------------------------------------------------------------
// (0, 1)
// (0. 7)
// (1, 1)     ("A", 1, 3)
// (1, 7)     ("A", 1, 3)
// (2, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (2, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (3, 1)     ("A", 1, 3)
// (3, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (4, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (4, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (5, 1)     ("A", 1, 3)
// (5, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (6, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2)
// (6, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (7, 1)     ("A", 1, 3)
// (7, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (8, 1)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
// (8, 7)     ("A", 1, 3), ("A", 2, 3), ("B", 1, 2), ("B", 2, 2)
//
// In addition, expect 1 ReportParticipationObservation each day for each
// report in the registry.
TEST_F(PerDeviceNumericAggregateStoreTest, ElapsedTimeCheckObservationValuesWithBackfillAndGc) {
  auto start_day_index = CurrentDayIndex();
  const auto& total_report_id =
      logger::testing::per_device_numeric_stats::kStreamingTimeTotalMetricReportId;
  const auto& min_report_id =
      logger::testing::per_device_numeric_stats::kStreamingTimeMinMetricReportId;
  const auto& max_report_id =
      logger::testing::per_device_numeric_stats::kStreamingTimeMaxMetricReportId;
  std::vector<MetricReportId> streaming_time_ids = {total_report_id, min_report_id, max_report_id};
  const auto& expected_params =
      logger::testing::per_device_numeric_stats::kExpectedAggregationParams;
  // Set |backfill_days_| to 3.
  SetBackfillDays(kTestBackfillDays);
  // Add events to the local aggregations for 9 days. Call GenerateObservations() on the first 6
  // day indices, and the 9th.
  uint32_t num_days = 9;
  for (uint32_t offset = 0; offset < num_days; offset++) {
    auto day_index = CurrentDayIndex();
    ResetObservationStore();
    for (uint32_t event_code = 1; event_code < 3; event_code++) {
      for (const auto& report_id : streaming_time_ids) {
        if (offset > 0 && (offset % event_code == 0)) {
          EXPECT_EQ(
              StatusCode::OK,
              AddPerDeviceElapsedTimeEvent(report_id, day_index, "A", event_code, 3).error_code());
        }
        if (offset > 0 && offset % (2 * event_code) == 0) {
          EXPECT_EQ(
              StatusCode::OK,
              AddPerDeviceElapsedTimeEvent(report_id, day_index, "B", event_code, 2).error_code());
        }
      }
    }

    // Advance |test_clock_| by 1 day.
    AdvanceClock(kDay);
    if (offset < 6 || offset == 8) {
      // Generate Observations and garbage-collect, both for the previous day
      // index according to |test_clock_|. Back up the LocalAggregateStore and
      // the AggregatedObservationHistoryStore.
      DoScheduledTasksNow();
    }
    // Make the set of Observations which are expected to be generated on
    // |start_day_index + offset| and check it against the contents of the
    // FakeObservationStore.
    ExpectedPerDeviceNumericObservations expected_per_device_numeric_obs;
    ExpectedReportParticipationObservations expected_report_participation_obs;
    switch (offset) {
      case 0: {
        for (uint32_t day_index = start_day_index - kTestBackfillDays; day_index <= start_day_index;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 1: {
        expected_per_device_numeric_obs[{total_report_id, day_index}] = {{1, {{"A", 1u, 3}}},
                                                                         {7, {{"A", 1u, 3}}}};
        expected_per_device_numeric_obs[{min_report_id, day_index}] = {{1, {{"A", 1u, 3}}},
                                                                       {7, {{"A", 1u, 3}}}};
        expected_per_device_numeric_obs[{max_report_id, day_index}] = {{1, {{"A", 1u, 3}}},
                                                                       {7, {{"A", 1u, 3}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(expected_per_device_numeric_obs,
                                                      expected_report_participation_obs,
                                                      *observation_store_, update_recipient_.get()))
            << "day 1";
        break;
      }
      case 2: {
        expected_per_device_numeric_obs[{total_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 6}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 3: {
        expected_per_device_numeric_obs[{total_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 9}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 4: {
        expected_per_device_numeric_obs[{total_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 12}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, day_index}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 5: {
        expected_per_device_numeric_obs[{total_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 15}, {"A", 2u, 6}, {"B", 1u, 4}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, day_index}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_report_participation_obs =
            MakeExpectedReportParticipationObservations(expected_params, day_index);
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      case 8: {
        expected_per_device_numeric_obs[{total_report_id, start_day_index + 6}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 18}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{total_report_id, start_day_index + 7}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 21}, {"A", 2u, 9}, {"B", 1u, 6}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{total_report_id, start_day_index + 8}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 21}, {"A", 2u, 12}, {"B", 1u, 8}, {"B", 2u, 4}}}};

        expected_per_device_numeric_obs[{min_report_id, start_day_index + 6}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, start_day_index + 7}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{min_report_id, start_day_index + 8}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};

        expected_per_device_numeric_obs[{max_report_id, start_day_index + 6}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, start_day_index + 7}] = {
            {1, {{"A", 1u, 3}}}, {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};
        expected_per_device_numeric_obs[{max_report_id, start_day_index + 8}] = {
            {1, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}},
            {7, {{"A", 1u, 3}, {"A", 2u, 3}, {"B", 1u, 2}, {"B", 2u, 2}}}};

        for (uint32_t day_index = start_day_index + 6; day_index <= start_day_index + 8;
             day_index++) {
          for (const auto& pair :
               MakeExpectedReportParticipationObservations(expected_params, day_index)) {
            expected_report_participation_obs.insert(pair);
          }
        }
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
        break;
      }
      default:
        EXPECT_TRUE(CheckPerDeviceNumericObservations(
            expected_per_device_numeric_obs, expected_report_participation_obs, *observation_store_,
            update_recipient_.get()));
    }
  }
}

// Check that GenerateObservations returns an OK status after some events have been logged for a
// PerDeviceHistogram report.
TEST_F(PerDeviceHistogramAggregateStoreTest, GenerateObservations) {
  const auto day_index = CurrentDayIndex();
  // Add several events to the local aggregations on |day_index|.
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_histogram::kSettingsChangedMetricReportId, day_index,
                "component_C", 0u, 5)
                .error_code());
  EXPECT_EQ(StatusCode::OK,
            AddPerDeviceEventCountEvent(
                logger::testing::per_device_histogram::kSettingsChangedMetricReportId, day_index,
                "component_C", 0u, 5)
                .error_code());

  // Generate locally aggregated Observations for |day_index|.
  EXPECT_EQ(StatusCode::OK, GenerateObservations(day_index).error_code());
}

// Tests GenerateObservations() and GarbageCollect() in the case where the
// LocalAggregateStore contains aggregates for metrics with both UTC and LOCAL
// time zone policies, and where the day index in local time may be less than
// the day index in UTC.
TEST_F(NoiseFreeMixedTimeZoneAggregateStoreTest, LocalBeforeUTC) {
  std::vector<ExpectedUniqueActivesObservations> expected_obs(3);
  // Begin at a time when the current day index is the same in both UTC and local time. Add 1
  // event to the local aggregations for event code 0 for each of the 2 reports, then generate
  // Observations and garbage-collect for the previous day index in each of UTC and local time.
  auto start_day_index = CurrentDayIndex();
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index, 0u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index, 0u);
  GenerateObservations(start_day_index - 1, start_day_index - 1);
  GarbageCollect(start_day_index - 1, start_day_index - 1);
  // Form the expected contents of the FakeObservationStore.
  // Since no events were logged on the previous day and no Observations have
  // been generated for that day yet, expect Observations of non-activity for
  // all event codes, for both reports.
  expected_obs[0] = MakeNullExpectedUniqueActivesObservations(
      logger::testing::mixed_time_zone::kExpectedAggregationParams, start_day_index - 1);
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[0], *observation_store_,
                                             update_recipient_.get()));
  ResetObservationStore();
  // Advance the day index in UTC, but not in local time, and log 1 event for
  // event code 1 for each of the 2 reports. Generate Observations and
  // garbage-collect for the previous day in each of UTC and local time.
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index, 1u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index + 1, 1u);
  GenerateObservations(start_day_index, start_day_index - 1);
  GarbageCollect(start_day_index, start_day_index - 1);
  // Form the expected contents of the FakeObservationStore. Since
  // Observations have already been generated for the
  // DeviceBoots_UniqueDevices report for |start_day_index - 1|, expect no
  // Observations for that report.
  expected_obs[1][{logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                   start_day_index}] = {{1, {true, false, false}}};
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[1], *observation_store_,
                                             update_recipient_.get()));
  ResetObservationStore();
  // Advance the day index in local time so that it is equal to the day index in UTC. Add 1 event
  // to the local aggregations for event code 2 for each of the 2 reports, then generate
  // Observations and garbage-collect for the previous day in each of UTC and local time.
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index + 1, 2u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index + 1, 2u);
  GenerateObservations(start_day_index, start_day_index);
  GarbageCollect(start_day_index, start_day_index);
  // Form the expected contents of the FakeObservationStore. Since
  // Observations have already been generated for the
  // FeaturesActive_UniqueDevices report for day |start_day_index|, expect no
  // Observations for that report.
  expected_obs[2][{logger::testing::mixed_time_zone::kDeviceBootsMetricReportId, start_day_index}] =
      {{1, {true, true, false}}};
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[2], *observation_store_,
                                             update_recipient_.get()));
}

// Tests GenerateObservations() and GarbageCollect() in the case where the
// LocalAggregateStore contains aggregates for metrics with both UTC and LOCAL
// time zone policies, and where the day index in UTC may be less than
// the day index in local time.
TEST_F(NoiseFreeMixedTimeZoneAggregateStoreTest, LocalAfterUTC) {
  std::vector<ExpectedUniqueActivesObservations> expected_obs(3);
  // Begin at a time when the current day index is the same in both UTC and local time. Add 1
  // event to the local aggregations for event code 0 for each of the 2 reports, then generate
  // Observations and garbage-collect for the previous day index in each of UTC and local time.
  auto start_day_index = CurrentDayIndex();
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index, 0u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index, 0u);
  GenerateObservations(start_day_index - 1, start_day_index - 1);
  GarbageCollect(start_day_index - 1, start_day_index - 1);
  // Form the expected contents of the FakeObservationStore.
  // Since no events were logged on the previous day and no Observations have
  // been generated for that day yet, expect Observations of non-activity for
  // all event codes, for both reports.
  expected_obs[0] = MakeNullExpectedUniqueActivesObservations(
      logger::testing::mixed_time_zone::kExpectedAggregationParams, start_day_index - 1);
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[0], *observation_store_,
                                             update_recipient_.get()));
  ResetObservationStore();
  // Advance the day index in local time, but not in UTC, and log 1 event for
  // event code 1 for each of the 2 reports. Generate Observations and
  // garbage-collect for the previous day in each of UTC and local time.
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index + 1, 1u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index, 1u);
  GenerateObservations(start_day_index - 1, start_day_index);
  GarbageCollect(start_day_index - 1, start_day_index);
  // Form the expected contents of the FakeObservationStore. Since
  // Observations have already been generated for the
  // FeaturesActive_UniqueDevices report for |start_day_index - 1|, expect no
  // Observations for that report.
  expected_obs[1][{logger::testing::mixed_time_zone::kDeviceBootsMetricReportId, start_day_index}] =
      {{1, {true, false, false}}};
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[1], *observation_store_,
                                             update_recipient_.get()));
  ResetObservationStore();
  // Advance the day index in UTC so that it is equal to the day index in local time. Add 1 event
  // to the local aggregations for event code 2 for each of the 2 reports, then generate
  // Observations and garbage-collect for the previous day in each of UTC and local time.
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kDeviceBootsMetricReportId,
                        start_day_index + 1, 2u);
  AddUniqueActivesEvent(logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                        start_day_index + 1, 2u);
  GenerateObservations(start_day_index, start_day_index);
  GarbageCollect(start_day_index, start_day_index);
  // Form the expected contents of the FakeObservationStore. Since
  // Observations have already been generated for the
  // DeviceBoots_UniqueDevices report for day |start_day_index|, expect no
  // Observations for that report.
  expected_obs[2][{logger::testing::mixed_time_zone::kFeaturesActiveMetricReportId,
                   start_day_index}] = {{1, {true, true, false}}};
  EXPECT_TRUE(CheckUniqueActivesObservations(expected_obs[2], *observation_store_,
                                             update_recipient_.get()));
}
}  // namespace local_aggregation
}  // namespace cobalt
