// 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. // Test support library for request payloads. #ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_TEST_REQUEST_PAYLOAD_H_ #define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_TEST_REQUEST_PAYLOAD_H_ #include <list> #include <ostream> #include <sstream> #include <string> #include <string_view> #include <type_traits> #include "base/containers/flat_map.h" #include "base/values.h" #include "testing/gmock/include/gmock/gmock.h" namespace reporting { AllOfArray; Matcher; MatchResultListener; // Matcher interface for each request validity matcher. A request validity // matcher is a matcher that verifies one aspect of the general validity of a // request JSON object. class RequestValidityMatcherInterface { … }; // attachEncryptionSettings must be of bool type and true. class AttachEncryptionSettingsMatcher : public RequestValidityMatcherInterface { … }; // attachEncryptionSettings must be absent. class NoAttachEncryptionSettingsMatcher : public RequestValidityMatcherInterface { … }; // ConfigurationFileVersion must be of bool type and true. class ConfigurationFileVersionMatcher : public RequestValidityMatcherInterface { … }; // ConfigurationFileVersion must be absent. class NoConfigurationFileVersionMatcher : public RequestValidityMatcherInterface { … }; // source must be of string type. class SourceMatcher : public RequestValidityMatcherInterface { … }; // source must be absent. class NoSourceMatcher : public RequestValidityMatcherInterface { … }; // encryptedRecord must be a list. This matcher is recommended to be applies // before verifying the details of any record (e.g., via |RecordMatcher|) to // generate more readable error messages. class EncryptedRecordMatcher : public RequestValidityMatcherInterface { … }; // requestId must be a hexadecimal number represented as a string. class RequestIdMatcher : public RequestValidityMatcherInterface { … }; // Base class of all matchers that verify one aspect of a record. class RecordMatcher : public RequestValidityMatcherInterface { … }; // Verify the encryptedWrappedRecord field of each record. class EncryptedWrappedRecordRecordMatcher : public RecordMatcher { … }; // Verify the absence of the encryptedWrappedRecord field of each record. class NoEncryptedWrappedRecordRecordMatcher : public RecordMatcher { … }; // Verify the sequenceInformation field of each record. class SequenceInformationRecordMatcher : public RecordMatcher { … }; // Verify the compressionInformation field of each record. class CompressionInformationMatcher : public RecordMatcher { … }; // Build a matcher that can be used to verify the general validity of a // request matcher while accommodating the variety of requirements (e.g., // some verification must be loosen because the request is intentionally // malformed for a particular test case). To use this class, call // CreateDataUpload() or CreateEmpty() to create an instance. Adapt matchers by // calling AppendMatcher() or RemoveMatcher(). // // For the document of what response payload should look like, search for // "{{{Note}}} ERP Request Payload Overview" in the codebase. template <class T = base::Value::Dict> class RequestValidityMatcherBuilder { … }; class RequestContainingRecordMatcher { … }; // The following matcher functions templated because we expect the tested // request comes in different forms, including their referenceness (gtest need // the matcher type to also match references to some extent). As long as the // type can be cast to a |base::Value::Dict| object, this matcher should work. // Match a data upload request that is valid. This matcher is intended to be // called for most tested data upload requests to verify whether the request is // valid on some basic fronts, such as containing an "encryptedRecord" key, etc. // // To enable or skip some part of the validity checks (e.g., because your test // case intentionally creates a malformed request), instead of using this // wrapper, you must call // // RequestValidityMatcherBuilder<>::CreateDataUpload() // .AppendMatcher(...) // .RemoveMatcher(...) // ... // .Build() template <class T = base::Value::Dict> Matcher<T> IsDataUploadRequestValid() { … } // Match an encryption key-request upload request that is valid. If need_key is // false, this matcher will ensure the request does not request an encryption // key. template <class T = base::Value::Dict> Matcher<T> IsEncryptionKeyRequestUploadRequestValid(bool need_key = true) { … } // Match a configuration file request upload request that is valid. If // request_config_file is false, this matcher will ensure the request does not // request a configuration file. template <class T = base::Value::Dict> Matcher<T> IsConfigurationFileRequestUploadRequestValid( bool request_config_file = false) { … } // Match a source upload request that is valid. template <class T = base::Value::Dict> Matcher<T> IsSourceRequestUploadRequestValid( bool client_automated_test = false) { … } // Match a gap upload request that is valid. template <class T = base::Value::Dict> Matcher<T> IsGapUploadRequestValid() { … } // Match a single record within a payload that is valid. template <class T = base::Value::Dict> Matcher<T> IsRecordValid() { … } // Match a request that contains the given record |matched_record_json|. The // match will be successful as long as any record in the request contains // |matched_record_json| as a sub-dictionary -- they are not required to equal. // In this way, you can specify only part of the record of interest (e.g., omit // "encryptedWrappedRecord"). template <class T = base::Value::Dict> Matcher<T> DoesRequestContainRecord(std::string_view matched_record_json) { … } } // namespace reporting #endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_TEST_REQUEST_PAYLOAD_H_