blob: a86b4b5b99f2138ee3bece592c901397768ec094 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "chrome/browser/policy/messaging_layer/upload/upload_provider.h"
#include <list>
#include <memory>
#include <utility>
#include "base/memory/ref_counted.h"
#include "base/task/thread_pool.h"
#include "base/test/protobuf_matchers.h"
#include "base/test/task_environment.h"
#include "chrome/browser/policy/messaging_layer/upload/fake_upload_client.h"
#include "chrome/browser/policy/messaging_layer/upload/upload_client.h"
#include "chrome/browser/policy/messaging_layer/util/reporting_server_connector.h"
#include "chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.h"
#include "chrome/browser/policy/messaging_layer/util/test_request_payload.h"
#include "chrome/browser/policy/messaging_layer/util/test_response_payload.h"
#include "chrome/browser/policy/messaging_layer/util/upload_declarations.h"
#include "components/policy/core/common/cloud/dm_token.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/reporting/resources/resource_manager.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/status_macros.h"
#include "components/reporting/util/test_support_callbacks.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::base::test::EqualsProto;
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::SizeIs;
using ::testing::WithArgs;
namespace reporting {
namespace {
// CloudPolicyClient and UploadClient are not usable outside of a managed
// environment, to sidestep this we override the functions that normally build
// and retrieve these clients and provide a MockCloudPolicyClient and a
// FakeUploadClient.
class TestEncryptedReportingUploadProvider
: public EncryptedReportingUploadProvider {
public:
TestEncryptedReportingUploadProvider(
ReportSuccessfulUploadCallback report_successful_upload_cb,
EncryptionKeyAttachedCallback encryption_key_attached_cb,
UpdateConfigInMissiveCallback update_config_in_missive_cb)
: EncryptedReportingUploadProvider(
report_successful_upload_cb,
encryption_key_attached_cb,
update_config_in_missive_cb,
/*upload_client_builder_cb=*/
base::BindRepeating(&FakeUploadClient::Create)) {}
};
class EncryptedReportingUploadProviderTest : public ::testing::Test {
public:
MOCK_METHOD(void, ReportSuccessfulUpload, (SequenceInformation, bool), ());
MOCK_METHOD(void, EncryptionKeyCallback, (SignedEncryptionInfo), ());
MOCK_METHOD(void,
UpdateConfigInMissiveCallback,
(ListOfBlockedDestinations),
());
protected:
void SetUp() override {
memory_resource_ =
base::MakeRefCounted<ResourceManager>(4u * 1024LLu * 1024LLu); // 4 MiB
test_env_ = std::make_unique<ReportingServerConnector::TestEnvironment>();
service_provider_ = std::make_unique<TestEncryptedReportingUploadProvider>(
base::BindRepeating(
&EncryptedReportingUploadProviderTest::ReportSuccessfulUpload,
base::Unretained(this)),
base::BindRepeating(
&EncryptedReportingUploadProviderTest::EncryptionKeyCallback,
base::Unretained(this)),
base::BindRepeating(&EncryptedReportingUploadProviderTest::
UpdateConfigInMissiveCallback,
base::Unretained(this)));
record_.set_encrypted_wrapped_record("TEST_DATA");
auto* sequence_information = record_.mutable_sequence_information();
sequence_information->set_sequencing_id(42);
sequence_information->set_generation_id(1701);
sequence_information->set_priority(Priority::SLOW_BATCH);
}
void TearDown() override {
test_env_.reset();
EXPECT_THAT(memory_resource_->GetUsed(), Eq(0uL));
}
StatusOr<std::list<int64_t>> CallRequestUploadEncryptedRecord(
bool need_encryption_key,
std::vector<EncryptedRecord> records,
ScopedReservation scoped_reservation) {
test::TestEvent<StatusOr<std::list<int64_t>>> enqueued_event;
service_provider_->RequestUploadEncryptedRecords(
need_encryption_key, std::move(records), std::move(scoped_reservation),
enqueued_event.cb());
return enqueued_event.result();
}
// Must be initialized before any other class member.
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<ReportingServerConnector::TestEnvironment> test_env_;
EncryptedRecord record_;
scoped_refptr<ResourceManager> memory_resource_;
std::unique_ptr<TestEncryptedReportingUploadProvider> service_provider_;
};
// TODO(b/289375752): Test is flaky across platforms.
TEST_F(EncryptedReportingUploadProviderTest,
DISABLED_SuccessfullyUploadsRecord) {
test::TestMultiEvent<SequenceInformation, bool /*force*/> uploaded_event;
EXPECT_CALL(*this, ReportSuccessfulUpload(_, _))
.WillOnce([&uploaded_event](SequenceInformation seq_info, bool force) {
std::move(uploaded_event.cb()).Run(std::move(seq_info), force);
});
std::vector<EncryptedRecord> records;
records.emplace_back(record_);
ScopedReservation record_reservation(records.back().ByteSizeLong(),
memory_resource_);
EXPECT_TRUE(record_reservation.reserved());
const auto enqueued_result = CallRequestUploadEncryptedRecord(
/*need_encryption_key=*/false, std::move(records),
std::move(record_reservation));
EXPECT_OK(enqueued_result) << enqueued_result.error();
EXPECT_THAT(enqueued_result.value(),
ElementsAre(record_.sequence_information().sequencing_id()));
task_environment_.RunUntilIdle();
ASSERT_THAT(*test_env_->url_loader_factory()->pending_requests(), SizeIs(1));
base::Value::Dict request_body = test_env_->request_body(0);
EXPECT_THAT(request_body, IsDataUploadRequestValid());
test_env_->SimulateResponseForRequest(0);
auto uploaded_result = uploaded_event.result();
EXPECT_THAT(std::get<0>(uploaded_result),
EqualsProto(record_.sequence_information()));
EXPECT_FALSE(std::get<1>(uploaded_result)); // !force
}
} // namespace
} // namespace reporting