chromium/chrome/browser/policy/messaging_layer/util/test_request_payload.h

// 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_