blob: 1fce6737019fb205d2f03f86a0446b1793581e6e [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/reporting/health/health_module_files.h"
#include <string>
#include "base/containers/span.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::IsEmpty;
using ::testing::StrEq;
namespace reporting {
namespace {
constexpr char kBaseFileOne[] = "base_file_name";
constexpr char kUnmatchedBaseFile[] = "no_files_match_this";
constexpr int kInitialFiles = 3;
constexpr int kIntialRecordsPerFile = 5;
constexpr uint32_t kSimpleEnqueueRecordCallLineSize = 21u;
constexpr uint32_t kSmallMaxStorageSize = 70u;
constexpr uint32_t kLargeMaxStorageSize = 1000u;
constexpr uint32_t kFullMaxStorageSize = 20000u;
class HealthModuleFilesTest : public ::testing::Test {
protected:
void SetUp() override {
ASSERT_TRUE(directory_.CreateUniqueTempDir());
for (int i = 0; i < kInitialFiles; i++) {
const std::string file_name =
base::StrCat({kBaseFileOne, base::NumberToString(i)});
for (int k = 0; k < kIntialRecordsPerFile; k++) {
auto call = AddEnqueueRecordCall();
*initial_health_data_.add_history() = call;
ASSERT_TRUE(AppendLine(directory_.GetPath().AppendASCII(file_name),
base::HexEncode(base::as_byte_span(
call.SerializeAsString())))
.ok());
}
}
}
HealthDataHistory AddEnqueueRecordCall() {
HealthDataHistory history;
EnqueueRecordCall call;
call.set_priority(
static_cast<Priority>(priority_counter_++ % Priority_MAX + 1));
*history.mutable_enqueue_record_call() = call;
history.set_timestamp_seconds(base::Time::Now().ToTimeT());
return history;
}
base::ScopedTempDir directory_;
ERPHealthData initial_health_data_;
private:
int priority_counter_ = Priority_MIN;
};
TEST_F(HealthModuleFilesTest, TestCreation) {
ERPHealthData history;
std::unique_ptr<HealthModuleFiles> files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, kLargeMaxStorageSize);
ASSERT_TRUE(files != nullptr);
files->PopulateHistory(&history);
EXPECT_THAT(history.SerializeAsString(),
StrEq(initial_health_data_.SerializeAsString()));
ERPHealthData empty_history;
std::unique_ptr<HealthModuleFiles> no_files = HealthModuleFiles::Create(
directory_.GetPath(), kUnmatchedBaseFile, kLargeMaxStorageSize);
ASSERT_TRUE(no_files != nullptr);
no_files->PopulateHistory(&empty_history);
EXPECT_THAT(empty_history.history(), IsEmpty());
ERPHealthData small_history;
const uint32_t total_records_stored =
kSmallMaxStorageSize / kSimpleEnqueueRecordCallLineSize;
std::unique_ptr<HealthModuleFiles> small_files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, kSmallMaxStorageSize);
ASSERT_TRUE(small_files != nullptr);
small_files->PopulateHistory(&small_history);
int initial_size = initial_health_data_.history_size();
initial_health_data_.mutable_history()->DeleteSubrange(
0, initial_size - total_records_stored);
EXPECT_THAT(small_history.SerializeAsString(),
StrEq(initial_health_data_.SerializeAsString()));
std::unique_ptr<HealthModuleFiles> null_files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, /*max_storage_space=*/0);
ASSERT_TRUE(null_files == nullptr);
}
TEST_F(HealthModuleFilesTest, TestFullStorage) {
ERPHealthData history;
std::unique_ptr<HealthModuleFiles> files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, kFullMaxStorageSize);
static constexpr uint32_t total_records_stored =
kFullMaxStorageSize / kSimpleEnqueueRecordCallLineSize;
ASSERT_TRUE(files != nullptr);
for (int i = 0; i < 1000; i++) {
auto call = AddEnqueueRecordCall();
ASSERT_OK(files->Write(
base::HexEncode(base::as_byte_span(call.SerializeAsString()))));
if (i + total_records_stored >= 1000) {
*history.add_history() = call;
}
}
ERPHealthData got;
files->PopulateHistory(&got);
EXPECT_THAT(history.SerializeAsString(), StrEq(got.SerializeAsString()));
}
TEST_F(HealthModuleFilesTest, NotEnoughStorage) {
ERPHealthData history;
std::unique_ptr<HealthModuleFiles> files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, /*max_storage_space=*/1);
ASSERT_TRUE(files != nullptr);
files->PopulateHistory(&history);
ASSERT_THAT(history.history(), IsEmpty());
ASSERT_FALSE(files
->Write(base::HexEncode(base::as_byte_span(
AddEnqueueRecordCall().SerializeAsString())))
.ok());
files->PopulateHistory(&history);
ASSERT_THAT(history.history(), IsEmpty());
}
TEST_F(HealthModuleFilesTest, JustEnoughStorage) {
ERPHealthData history;
std::unique_ptr<HealthModuleFiles> files = HealthModuleFiles::Create(
directory_.GetPath(), kBaseFileOne, kSimpleEnqueueRecordCallLineSize);
ASSERT_TRUE(files != nullptr);
files->PopulateHistory(&history);
int initial_size = initial_health_data_.history_size();
initial_health_data_.mutable_history()->DeleteSubrange(0, initial_size - 1);
ASSERT_THAT(history.SerializeAsString(),
StrEq(initial_health_data_.SerializeAsString()));
history.mutable_history()->Clear();
auto call = AddEnqueueRecordCall();
*initial_health_data_.mutable_history(0) = call;
ASSERT_TRUE(
files
->Write(base::HexEncode(base::as_byte_span(call.SerializeAsString())))
.ok());
files->PopulateHistory(&history);
EXPECT_THAT(history.SerializeAsString(),
StrEq(initial_health_data_.SerializeAsString()));
}
} // namespace
} // namespace reporting