Commit c16d425a authored by Bartosz Fabianowski's avatar Bartosz Fabianowski Committed by Commit Bot

Add class that holds app push-install event log

This adds a class that holds a log of events related to a single
app's push install process. The class is not hooked up to anything
yet, so no log entries are read or written.

Bug: b/73277923
Test: unit_tests
Change-Id: I046f5c4871e1ae8867c96c3f6bd5c6cee31b8e01
Reviewed-on: https://chromium-review.googlesource.com/915924
Commit-Queue: Bartosz Fabianowski <bartfab@chromium.org>
Reviewed-by: default avatarJulian Pastarmov <pastarmovj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537639}
parent bc446d8e
......@@ -1342,6 +1342,8 @@ source_set("chromeos") {
"policy/server_backed_device_state.h",
"policy/server_backed_state_keys_broker.cc",
"policy/server_backed_state_keys_broker.h",
"policy/single_app_install_event_log.cc",
"policy/single_app_install_event_log.h",
"policy/status_uploader.cc",
"policy/status_uploader.h",
"policy/system_log_uploader.cc",
......@@ -1937,6 +1939,7 @@ source_set("unit_tests") {
"policy/remote_commands/device_command_set_volume_job_unittest.cc",
"policy/secondary_google_account_signin_policy_handler_unittest.cc",
"policy/server_backed_state_keys_broker_unittest.cc",
"policy/single_app_install_event_log_unittest.cc",
"policy/status_uploader_unittest.cc",
"policy/system_log_uploader_unittest.cc",
"policy/temp_certs_cache_nss_unittest.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/single_app_install_event_log.h"
#include <stddef.h>
#include <stdint.h>
#include "base/files/file.h"
namespace em = enterprise_management;
namespace policy {
namespace {
static const int kLogCapacity = 1024;
static const int kMaxBufferSize = 65536;
} // namespace
SingleAppInstallEventLog::SingleAppInstallEventLog(const std::string& package)
: package_(package) {}
SingleAppInstallEventLog::~SingleAppInstallEventLog() {}
void SingleAppInstallEventLog::Add(const em::AppInstallReportLogEvent& event) {
events_.push_back(event);
if (events_.size() > kLogCapacity) {
incomplete_ = true;
if (serialized_entries_ > -1) {
--serialized_entries_;
}
events_.pop_front();
}
}
bool SingleAppInstallEventLog::Load(
base::File* file,
std::unique_ptr<SingleAppInstallEventLog>* log) {
log->reset();
if (!file->IsValid()) {
return false;
}
ssize_t size;
if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&size), sizeof(size)) !=
sizeof(size) ||
size > kMaxBufferSize) {
return false;
}
std::unique_ptr<char[]> package_buffer = std::make_unique<char[]>(size);
if (file->ReadAtCurrentPos(package_buffer.get(), size) != size) {
return false;
}
*log = std::make_unique<SingleAppInstallEventLog>(
std::string(package_buffer.get(), size));
int64_t incomplete;
if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&incomplete),
sizeof(incomplete)) != sizeof(incomplete)) {
return false;
}
(*log)->incomplete_ = incomplete;
ssize_t entries;
if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&entries),
sizeof(entries)) != sizeof(entries)) {
return false;
}
for (ssize_t i = 0; i < entries; ++i) {
if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&size), sizeof(size)) !=
sizeof(size) ||
size > kMaxBufferSize) {
(*log)->incomplete_ = true;
return false;
}
if (size == 0) {
// Zero-size entries are written if serialization of a log entry fails.
// Skip these on read.
(*log)->incomplete_ = true;
continue;
}
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size);
if (file->ReadAtCurrentPos(buffer.get(), size) != size) {
(*log)->incomplete_ = true;
return false;
}
em::AppInstallReportLogEvent event;
if (event.ParseFromArray(buffer.get(), size)) {
(*log)->Add(event);
} else {
(*log)->incomplete_ = true;
}
}
return true;
}
bool SingleAppInstallEventLog::Store(base::File* file) const {
if (!file->IsValid()) {
return false;
}
ssize_t size = package_.size();
if (file->WriteAtCurrentPos(reinterpret_cast<const char*>(&size),
sizeof(size)) != sizeof(size)) {
return false;
}
if (file->WriteAtCurrentPos(package_.data(), size) != size) {
return false;
}
const int64_t incomplete = incomplete_;
if (file->WriteAtCurrentPos(reinterpret_cast<const char*>(&incomplete),
sizeof(incomplete)) != sizeof(incomplete)) {
return false;
}
const ssize_t entries = events_.size();
if (file->WriteAtCurrentPos(reinterpret_cast<const char*>(&entries),
sizeof(entries)) != sizeof(entries)) {
return false;
}
for (const em::AppInstallReportLogEvent& event : events_) {
size = event.ByteSizeLong();
std::unique_ptr<char[]> buffer;
if (size > kMaxBufferSize) {
// Log entry too large. Skip it.
size = 0;
} else {
buffer = std::make_unique<char[]>(size);
if (!event.SerializeToArray(buffer.get(), size)) {
// Log entry serialization failed. Skip it.
size = 0;
}
}
if (file->WriteAtCurrentPos(reinterpret_cast<const char*>(&size),
sizeof(size)) != sizeof(size) ||
(size && file->WriteAtCurrentPos(buffer.get(), size) != size)) {
return false;
}
}
return true;
}
void SingleAppInstallEventLog::Serialize(em::AppInstallReport* report) {
report->Clear();
report->set_package(package_);
report->set_incomplete(incomplete_);
for (const auto& event : events_) {
em::AppInstallReportLogEvent* const log_event = report->add_log();
*log_event = event;
}
serialized_entries_ = events_.size();
}
void SingleAppInstallEventLog::ClearSerialized() {
if (serialized_entries_ == -1) {
return;
}
events_.erase(events_.begin(), events_.begin() + serialized_entries_);
serialized_entries_ = -1;
incomplete_ = false;
}
} // namespace policy
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_POLICY_SINGLE_APP_INSTALL_EVENT_LOG_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_SINGLE_APP_INSTALL_EVENT_LOG_H_
#include <deque>
#include <memory>
#include <string>
#include "components/policy/proto/device_management_backend.pb.h"
#include "base/macros.h"
namespace base {
class File;
}
namespace policy {
// An event log for a single app's push-install process. The log can be stored
// on disk and serialized for upload to a server. The log is internally held in
// a round-robin buffer. A flag indicates whether any log entries were lost
// (e.g. entry too large or buffer wrapped around). Log entries are pruned and
// the flag is cleared after upload has completed.
class SingleAppInstallEventLog {
public:
explicit SingleAppInstallEventLog(const std::string& package);
~SingleAppInstallEventLog();
const std::string& package() const { return package_; }
int size() const { return events_.size(); }
bool empty() const { return events_.empty(); }
// Add a log entry. If the buffer is full, the oldest entry is removed and
// |incomplete_| is set.
void Add(const enterprise_management::AppInstallReportLogEvent& event);
// Restores the event log from |file| into |log|. Returns |true| if the
// self-delimiting format of the log was parsed successfully and further logs
// stored in the file may be loaded.
// |incomplete_| is set to |true| if it was set when storing the log to the
// file, the buffer wraps around or any log entries cannot be fully parsed. If
// not even the app name can be parsed, |log| is set to |nullptr|.
static bool Load(base::File* file,
std::unique_ptr<SingleAppInstallEventLog>* log);
// Stores the event log to |file|. Returns |true| if the log was written
// successfully in a self-delimiting manner and the file may be used to store
// further logs.
bool Store(base::File* file) const;
// Serializes the log to a protobuf for upload to a server. Records which
// entries were serialized so that they may be cleared after successful
// upload.
void Serialize(enterprise_management::AppInstallReport* report);
// Clears log entries that were previously serialized. Also clears
// |incomplete_| if all log entries added since serialization are still
// present in the log.
void ClearSerialized();
private:
// The app this event log pertains to.
const std::string package_;
// The buffer holding log entries.
std::deque<enterprise_management::AppInstallReportLogEvent> events_;
// Whether any log entries were lost (e.g. entry too large or buffer wrapped
// around).
bool incomplete_ = false;
// The number of entries that were serialized and can be cleared from the log
// after successful upload to the server, or -1 if none.
int serialized_entries_ = -1;
DISALLOW_COPY_AND_ASSIGN(SingleAppInstallEventLog);
};
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_SINGLE_APP_INSTALL_EVENT_LOG_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/single_app_install_event_log.h"
#include <stdint.h>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
namespace policy {
namespace {
static const int kLogCapacity = 1024;
static const char kPackageName[] = "com.example.app";
static const int64_t kTimestamp = 12345;
static const char kFileName[] = "event.log";
} // namespace
class SingleAppInstallEventLogTest : public testing::Test {
protected:
SingleAppInstallEventLogTest() {}
// testing::Test:
void SetUp() override {
log_.reset(new SingleAppInstallEventLog(kPackageName));
}
void VerifyHeader(bool incomplete) {
EXPECT_TRUE(report_.has_package());
EXPECT_EQ(kPackageName, report_.package());
EXPECT_TRUE(report_.has_incomplete());
EXPECT_EQ(incomplete, report_.incomplete());
}
void CreateFile() {
temp_dir_.reset(new base::ScopedTempDir);
ASSERT_TRUE(temp_dir_->CreateUniqueTempDir());
file_.reset(new base::File(temp_dir_->GetPath().Append(kFileName),
base::File::FLAG_CREATE_ALWAYS |
base::File::FLAG_WRITE |
base::File::FLAG_READ));
}
std::unique_ptr<SingleAppInstallEventLog> log_;
em::AppInstallReport report_;
std::unique_ptr<base::ScopedTempDir> temp_dir_;
std::unique_ptr<base::File> file_;
private:
DISALLOW_COPY_AND_ASSIGN(SingleAppInstallEventLogTest);
};
// Verify that the package name is returned correctly.
TEST_F(SingleAppInstallEventLogTest, GetPackage) {
EXPECT_EQ(kPackageName, log_->package());
}
// Do not add any log entries. Serialize the log. Verify that the serialization
// contains the the correct header data (package name, incomplete flag) and no
// log entries.
TEST_F(SingleAppInstallEventLogTest, SerializeEmpty) {
EXPECT_TRUE(log_->empty());
EXPECT_EQ(0, log_->size());
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
EXPECT_EQ(0, report_.log_size());
}
// Add a log entry. Verify that the entry is serialized correctly.
TEST_F(SingleAppInstallEventLogTest, AddAndSerialize) {
em::AppInstallReportLogEvent event;
event.set_timestamp(kTimestamp);
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
log_->Add(event);
EXPECT_FALSE(log_->empty());
EXPECT_EQ(1, log_->size());
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(1, report_.log_size());
std::string original_event;
event.SerializeToString(&original_event);
std::string log_event;
report_.log(0).SerializeToString(&log_event);
EXPECT_EQ(original_event, log_event);
}
// Add 10 log entries. Verify that they are serialized correctly. Then, clear
// the serialized log entries and verify that the log becomes empty.
TEST_F(SingleAppInstallEventLogTest, SerializeAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(10, log_->size());
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(10, report_.log_size());
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(i, report_.log(i).timestamp());
}
log_->ClearSerialized();
EXPECT_TRUE(log_->empty());
EXPECT_EQ(0, log_->size());
report_.Clear();
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
EXPECT_EQ(0, report_.log_size());
}
// Add 10 log entries. Serialize the log. Add 10 more log entries. Clear the
// serialized log entries. Verify that the log now contains the last 10 entries.
TEST_F(SingleAppInstallEventLogTest, SerializeAddAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(10, log_->size());
log_->Serialize(&report_);
for (int i = 10; i < 20; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(20, log_->size());
log_->ClearSerialized();
EXPECT_FALSE(log_->empty());
EXPECT_EQ(10, log_->size());
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(10, report_.log_size());
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(i + 10, report_.log(i).timestamp());
}
}
// Add more entries than the log has capacity for. Serialize the log. Verify
// that the serialization contains the most recent log entries and the
// incomplete flag is set. Then, clear the serialized log entries. Verify that
// the log becomes empty and the incomplete flag is unset.
TEST_F(SingleAppInstallEventLogTest, OverflowSerializeAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->Serialize(&report_);
VerifyHeader(true /* incomplete */);
ASSERT_EQ(kLogCapacity, report_.log_size());
for (int i = 0; i < kLogCapacity; ++i) {
EXPECT_EQ(i + 1, report_.log(i).timestamp());
}
log_->ClearSerialized();
EXPECT_TRUE(log_->empty());
EXPECT_EQ(0, log_->size());
report_.Clear();
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
EXPECT_EQ(0, report_.log_size());
}
// Add more entries than the log has capacity for. Serialize the log. Add one
// more log entry. Clear the serialized log entries. Verify that the log now
// contains the most recent entry and the incomplete flag is unset.
TEST_F(SingleAppInstallEventLogTest, OverflowSerializeAddAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->Serialize(&report_);
event.set_timestamp(kLogCapacity + 1);
log_->Add(event);
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->ClearSerialized();
EXPECT_FALSE(log_->empty());
EXPECT_EQ(1, log_->size());
report_.Clear();
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(1, report_.log_size());
EXPECT_EQ(kLogCapacity + 1, report_.log(0).timestamp());
}
// Add more entries than the log has capacity for. Serialize the log. Add
// exactly as many entries as the log has capacity for. Clear the serialized log
// entries. Verify that the log now contains the most recent entries and the
// incomplete flag is unset.
TEST_F(SingleAppInstallEventLogTest, OverflowSerializeFillAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->Serialize(&report_);
for (int i = 0; i < kLogCapacity; ++i) {
event.set_timestamp(kLogCapacity + i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->ClearSerialized();
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
report_.Clear();
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(kLogCapacity, report_.log_size());
for (int i = 0; i < kLogCapacity; ++i) {
EXPECT_EQ(i + kLogCapacity, report_.log(i).timestamp());
}
}
// Add more entries than the log has capacity for. Serialize the log. Add more
// entries than the log has capacity for. Clear the serialized log entries.
// Verify that the log now contains the most recent entries and the incomplete
// flag is set.
TEST_F(SingleAppInstallEventLogTest, OverflowSerializeOverflowAndClear) {
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->Serialize(&report_);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(kLogCapacity + i);
log_->Add(event);
}
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
log_->ClearSerialized();
EXPECT_FALSE(log_->empty());
EXPECT_EQ(kLogCapacity, log_->size());
report_.Clear();
log_->Serialize(&report_);
VerifyHeader(true /* incomplete */);
ASSERT_EQ(kLogCapacity, report_.log_size());
for (int i = 0; i < kLogCapacity; ++i) {
EXPECT_EQ(i + kLogCapacity + 1, report_.log(i).timestamp());
}
}
// Load log from a file that is not open. Verify that the operation fails.
TEST_F(SingleAppInstallEventLogTest, FailLoad) {
base::File invalid_file;
std::unique_ptr<SingleAppInstallEventLog> log =
std::make_unique<SingleAppInstallEventLog>(kPackageName);
EXPECT_FALSE(SingleAppInstallEventLog::Load(&invalid_file, &log));
EXPECT_FALSE(log);
}
// Add a log entry. Store the log to a file that is not open. Verify that the
// operation fails and the log is not modified.
TEST_F(SingleAppInstallEventLogTest, FailStore) {
em::AppInstallReportLogEvent event;
event.set_timestamp(0);
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
log_->Add(event);
EXPECT_FALSE(log_->empty());
EXPECT_EQ(1, log_->size());
base::File invalid_file;
EXPECT_FALSE(log_->Store(&invalid_file));
EXPECT_EQ(kPackageName, log_->package());
EXPECT_FALSE(log_->empty());
EXPECT_EQ(1, log_->size());
log_->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(1, report_.log_size());
EXPECT_EQ(0, report_.log(0).timestamp());
}
// Store an empty log. Load the log. Verify that that the log contents are
// loaded correctly.
TEST_F(SingleAppInstallEventLogTest, StoreEmptyAndLoad) {
ASSERT_NO_FATAL_FAILURE(CreateFile());
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
std::unique_ptr<SingleAppInstallEventLog> log;
EXPECT_TRUE(SingleAppInstallEventLog::Load(file_.get(), &log));
ASSERT_TRUE(log);
EXPECT_EQ(kPackageName, log->package());
EXPECT_TRUE(log->empty());
EXPECT_EQ(0, log->size());
log->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(0, report_.log_size());
}
// Populate and store a log. Load the log. Verify that that the log contents are
// loaded correctly.
TEST_F(SingleAppInstallEventLogTest, StoreAndLoad) {
ASSERT_NO_FATAL_FAILURE(CreateFile());
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
std::unique_ptr<SingleAppInstallEventLog> log;
EXPECT_TRUE(SingleAppInstallEventLog::Load(file_.get(), &log));
ASSERT_TRUE(log);
EXPECT_EQ(kPackageName, log->package());
EXPECT_FALSE(log->empty());
EXPECT_EQ(10, log->size());
log->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(10, report_.log_size());
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(i, report_.log(i).timestamp());
}
}
// Add more entries than the log has capacity for. Store the log. Load the log.
// Verify that the log is marked as incomplete.
TEST_F(SingleAppInstallEventLogTest, OverflowStoreAndLoad) {
ASSERT_NO_FATAL_FAILURE(CreateFile());
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < kLogCapacity + 1; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
std::unique_ptr<SingleAppInstallEventLog> log;
EXPECT_TRUE(SingleAppInstallEventLog::Load(file_.get(), &log));
ASSERT_TRUE(log);
EXPECT_EQ(kPackageName, log->package());
EXPECT_FALSE(log->empty());
EXPECT_EQ(kLogCapacity, log->size());
log->Serialize(&report_);
VerifyHeader(true /* incomplete */);
}
// Populate and serialize a log. Store the log. Load the log. Clear serialized
// entries in the loaded log. Verify that no entries are removed.
TEST_F(SingleAppInstallEventLogTest, SerializeStoreLoadAndClear) {
ASSERT_NO_FATAL_FAILURE(CreateFile());
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
log_->Serialize(&report_);
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
std::unique_ptr<SingleAppInstallEventLog> log;
EXPECT_TRUE(SingleAppInstallEventLog::Load(file_.get(), &log));
ASSERT_TRUE(log);
EXPECT_EQ(kPackageName, log->package());
EXPECT_FALSE(log->empty());
EXPECT_EQ(10, log->size());
log->ClearSerialized();
EXPECT_FALSE(log->empty());
EXPECT_EQ(10, log->size());
report_.Clear();
log->Serialize(&report_);
VerifyHeader(false /* incomplete */);
ASSERT_EQ(10, report_.log_size());
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(i, report_.log(i).timestamp());
}
}
// Add 20 log entries. Store the log. Truncate the file to the length of a log
// containing 10 log entries plus one byte. Load the log. Verify that the log
// contains the first 10 log entries and is marked as incomplete.
TEST_F(SingleAppInstallEventLogTest, LoadTruncated) {
ASSERT_NO_FATAL_FAILURE(CreateFile());
em::AppInstallReportLogEvent event;
event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i);
log_->Add(event);
}
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
const ssize_t size = file_->GetLength();
for (int i = 0; i < 10; ++i) {
event.set_timestamp(i + 10);
log_->Add(event);
}
log_->Store(file_.get());
file_->Seek(base::File::FROM_BEGIN, 0);
file_->SetLength(size + 1);
std::unique_ptr<SingleAppInstallEventLog> log;
EXPECT_FALSE(SingleAppInstallEventLog::Load(file_.get(), &log));
ASSERT_TRUE(log);
EXPECT_EQ(kPackageName, log->package());
EXPECT_FALSE(log->empty());
EXPECT_EQ(10, log->size());
report_.Clear();
log->Serialize(&report_);
VerifyHeader(true /* incomplete */);
ASSERT_EQ(10, report_.log_size());
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(i, report_.log(i).timestamp());
}
}
} // namespace policy
......@@ -1466,6 +1466,95 @@ message TpmVersionInfo {
optional string vendor_specific = 6;
}
// System state included with some log events.
message SystemState {
// VolumeInfo is reused from existing Chrome reporting.
repeated VolumeInfo volume_info = 1;
}
// A single entry in the push-install log for an app.
message AppInstallReportLogEvent {
// Enumerates the possible event types.
enum EventType {
// Request received by device
SERVER_REQUEST = 0;
// Request forwarded to CloudDPC
CLOUDDPC_REQUEST = 1;
// Request forwarded to CloudDPS
CLOUDDPS_REQUEST = 2;
// Response received from CloudDPS
CLOUDDPS_RESPONSE = 3;
// Log line written by Phonesky
PHONESKY_LOG = 4;
// Install success
SUCCESS = 5;
// Request canceled
CANCELED = 6;
// Connectivity state changed
CONNECTIVITY_CHANGE = 7;
// Session state changed
SESSION_STATE_CHANGE = 8;
}
// Enumerates the possible changes in session state.
enum SessionStateChangeType {
// Session starting
LOGIN = 0;
// Session ending
LOGOUT = 1;
// Suspending
SUSPEND = 2;
// Resuming
RESUME = 3;
}
// Timestamp, in milliseconds since epoch. Set for all log
// events.
optional int64 timestamp = 1;
// Event type. Set for all log events.
optional EventType event_type = 2;
// System state. Set for event types SERVER_REQUEST,
// CLOUDDPS_RESPONSE and SUCCESS.
optional SystemState system_state = 3;
// CloudDPS response. Set for event type CLOUDDPS_RESPONSE.
optional int32 clouddps_response = 4;
// Log line written by Phonesky. Set for event type PHONESKY_LOG.
optional string phonesky_log = 5;
// Network state. Set for SERVER_REQUEST and CONNECTIVITY_CHANGE.
optional NetworkState network_state = 6;
// Type of session state change. Set for SESSION_STATE_CHANGE.
optional SessionStateChangeType session_state_change_type = 7;
}
// Log bucket for an app.
message AppInstallReport {
// Package name of the app.
optional string package = 1;
// Whether the log is incomplete, e.g. due to the log ring buffer overflowing
// or disk corruption.
optional bool incomplete = 2;
// Log events for the app.
repeated AppInstallReportLogEvent log = 3;
}
// Push-install logs for all apps.
message AppInstallReportRequest {
// Log buckets for each app.
repeated AppInstallReport app_install_report = 1;
}
// Response from server after receiving a report on the status of app
// push-installs.
message AppInstallReportResponse {}
// Request from the DMAgent on the device to the DMServer. This is
// container for all requests from device to server. The overall HTTP
// request MUST be in the following format:
......@@ -1548,6 +1637,7 @@ message TpmVersionInfo {
// check_device_license: check_device_license_request
// active_directory_user_signin: active_directory_user_signin_request
// register_browser: register_browser_request
// app_install_report: app_install_report_request
//
message DeviceManagementRequest {
// Register request.
......@@ -1625,6 +1715,9 @@ message DeviceManagementRequest {
// A Chrome desktop report request.
optional ChromeDesktopReportRequest chrome_desktop_report_request = 24;
// A report on the status of app push-installs.
optional AppInstallReportRequest app_install_report_request = 25;
}
// Response from server to device.
......@@ -1751,4 +1844,7 @@ message DeviceManagementResponse {
// Response to a Chrome browser registration request.
optional RegisterBrowserResponse register_browser_response = 24;
// Response a report on the status of app push-installs
optional AppInstallReportResponse app_install_report_response = 25;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment