Repository: envoyproxy/envoy
File: test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc (C++)

Code before:

  EXPECT_THAT(upstream_request_->headers(), Not(ContainsHeader("match-header", _)));
  upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, false);
  upstream_request_->encodeData(100, true);

  processResponseHeadersMessage(
      *grpc_upstreams_[0], false, [](const HttpHeaders& headers, HeadersResponse&) {
        Http::TestRequestHeaderMapImpl expected_response_headers{{":status", "200"}};
        EXPECT_THAT(headers.headers(), HeaderProtosEqual(expected_response_headers));
        return true;
      });

  verifyDownstreamResponse(*response, 200);

  const std::string log_content = waitForAccessLog(tunnel_access_log_path_);
  EXPECT_FALSE(log_content.empty());
  EXPECT_THAT(log_content, testing::HasSubstr("request_header_call_status"));
  EXPECT_THAT(log_content, testing::HasSubstr("request_header_latency_us"));
  EXPECT_THAT(log_content, testing::HasSubstr("response_header_call_status"));
  EXPECT_THAT(log_content, testing::HasSubstr("response_header_latency_us"));
}

// Test the ability of the filter to completely replace a request message with a new
// request message.
TEST_P(ExtProcIntegrationTest, ExtProcLoggingInfoContinueAndReplace) {
  auto access_log_path = TestEnvironment::temporaryPath(TestUtility::uniqueFilename());
  proto_config_.mutable_processing_mode()->set_request_header_mode(ProcessingMode::SEND);

  config_helper_.addConfigModifier([&](HttpConnectionManager& cm) {
    auto* access_log = cm.add_access_log();
    access_log->set_name("accesslog");
    envoy::extensions::access_loggers::file::v3::FileAccessLog access_log_config;
    access_log_config.set_path(access_log_path);
    auto* json_format = access_log_config.mutable_log_format()->mutable_json_format();
    // Test field extraction for coverage.
    (*json_format->mutable_fields())["field_request_header_cr"].set_string_value(
        "%FILTER_STATE(envoy.filters.http.ext_proc:FIELD:request_header_continue_and_replace)%");
    (*json_format->mutable_fields())["field_response_header_cr"].set_string_value(
        "%FILTER_STATE(envoy.filters.http.ext_proc:FIELD:response_header_continue_and_replace)%");
    (*json_format->mutable_fields())["field_immeidate_response"].set_string_value(
        "%FILTER_STATE(envoy.filters.http.ext_proc:FIELD:immediate_response)%");
    access_log->mutable_typed_config()->PackFrom(access_log_config);
  });
  initializeConfig();
  HttpIntegrationTest::initialize();
  auto response = sendDownstreamRequestWithBody("Replace this!", absl::nullopt);
  processRequestHeadersMessage(
      *grpc_upstreams_[0], true, [](const HttpHeaders&, HeadersResponse& headers_resp) {
        headers_resp.mutable_response()->mutable_body_mutation()->set_body("Hello, Server!");
        // This special status tells us to replace the whole request
        headers_resp.mutable_response()->set_status(CommonResponse::CONTINUE_AND_REPLACE);

Review comment (suggestion):
we probably should think about sharing the common code between tests.  e.g., ExtProcLoggingInfoGRPCTimeout, to improve the code maintenance. 

ext_proc_integration_test has grown significantly 

Code after:
  // Configure mode override allow list.
  auto* added_mode = proto_config_.add_allowed_override_modes();
  added_mode->set_request_body_mode(ProcessingMode::NONE);
  added_mode = proto_config_.add_allowed_override_modes();
  added_mode->set_request_body_mode(ProcessingMode::STREAMED);
  added_mode->set_response_header_mode(ProcessingMode::SKIP);
  initializeConfig();
  HttpIntegrationTest::initialize();

  std::string body_str = std::string(10, 'a');
  auto response = sendDownstreamRequestWithBody(body_str, absl::nullopt);

  // Process request header message.
  processGenericMessage(
      *grpc_upstreams_[0], true, [](const ProcessingRequest&, ProcessingResponse& resp) {
        resp.mutable_request_headers();
        resp.mutable_mode_override()->set_response_header_mode(ProcessingMode::SKIP);
        resp.mutable_mode_override()->set_request_body_mode(ProcessingMode::STREAMED);
        return true;
      });

  // ext_proc server will receive the body message since the processing body mode has been
  // overridden from `ProcessingMode::NONE` to `ProcessingMode::STREAMED`
  processRequestBodyMessage(*grpc_upstreams_[0], false, [](const HttpBody& body, BodyResponse&) {
    EXPECT_TRUE(body.end_of_stream());
    return true;
  });
  handleUpstreamRequest();
  verifyDownstreamResponse(*response, 200);
}

TEST_P(ExtProcIntegrationTest, ModeOverrideDisallowed) {
  proto_config_.mutable_processing_mode()->set_request_body_mode(ProcessingMode::STREAMED);
  proto_config_.mutable_processing_mode()->set_response_header_mode(ProcessingMode::SKIP);
  proto_config_.set_allow_mode_override(true);
  // Configure mode override allow list.
  auto* added_mode = proto_config_.add_allowed_override_modes();
  added_mode->set_request_body_mode(ProcessingMode::BUFFERED);
  added_mode->set_response_header_mode(ProcessingMode::SKIP);
  initializeConfig();
  HttpIntegrationTest::initialize();

  std::string body_str = std::string(10, 'a');
  auto response = sendDownstreamRequestWithBody(body_str, absl::nullopt);

  // Process request header message.
  processGenericMessage(
      *grpc_upstreams_[0], true, [](const ProcessingRequest&, ProcessingResponse& resp) {
        resp.mutable_request_headers();
        resp.mutable_mode_override()->set_response_header_mode(ProcessingMode::SKIP);
        resp.mutable_mode_override()->set_request_body_mode(ProcessingMode::NONE);