DEFINE_PROTO_FUZZER(const test::common::http::ConnManagerImplTestCase& input) {
  try {
    TestUtility::validate(input);
  } catch (const ProtoValidationException& e) {
    ENVOY_LOG_MISC(debug, "ProtoValidationException: {}", e.what());
    return;
  } catch (const Envoy::ProtobufMessage::DeprecatedProtoFieldException& e) {
    ENVOY_LOG_MISC(debug, "DeprecatedProtoFieldException: {}", e.what());
    return;
  }

  FuzzConfig config(input.forward_client_cert());
  NiceMock<Network::MockDrainDecision> drain_close;
  NiceMock<Random::MockRandomGenerator> random;
  Stats::SymbolTableImpl symbol_table;
  Http::ContextImpl http_context(symbol_table);
  NiceMock<Runtime::MockLoader> runtime;
  NiceMock<LocalInfo::MockLocalInfo> local_info;
  NiceMock<Upstream::MockClusterManager> cluster_manager;
  NiceMock<Network::MockReadFilterCallbacks> filter_callbacks;
  NiceMock<Server::MockOverloadManager> overload_manager;
  auto ssl_connection = std::make_shared<Ssl::MockConnectionInfo>();
  bool connection_alive = true;

  ON_CALL(filter_callbacks.connection_, ssl()).WillByDefault(Return(ssl_connection));
  ON_CALL(Const(filter_callbacks.connection_), ssl()).WillByDefault(Return(ssl_connection));
  ON_CALL(filter_callbacks.connection_, close(_))
      .WillByDefault(InvokeWithoutArgs([&connection_alive] { connection_alive = false; }));
  filter_callbacks.connection_.stream_info_.downstream_address_provider_->setLocalAddress(
      std::make_shared<Network::Address::Ipv4Instance>("127.0.0.1"));
  filter_callbacks.connection_.stream_info_.downstream_address_provider_->setRemoteAddress(
      std::make_shared<Network::Address::Ipv4Instance>("0.0.0.0"));

  ConnectionManagerImpl conn_manager(config, drain_close, random, http_context, runtime, local_info,
                                     cluster_manager, overload_manager, config.time_system_);
  conn_manager.initializeReadFilterCallbacks(filter_callbacks);

  std::vector<FuzzStreamPtr> streams;

  for (const auto& action : input.actions()) {
    ENVOY_LOG_MISC(trace, "action {} with {} streams", action.DebugString(), streams.size());
    if (!connection_alive) {
      ENVOY_LOG_MISC(trace, "skipping due to dead connection");
      break;
    }

    switch (action.action_selector_case()) {
    case test::common::http::Action::kNewStream: {
      streams.emplace_back(new FuzzStream(
          conn_manager, config,
          Fuzz::fromHeaders<TestRequestHeaderMapImpl>(action.new_stream().request_headers(),
                                                      /* ignore_headers =*/{}, {":authority"}),
          action.new_stream().status(), action.new_stream().end_stream()));
      break;
    }
    case test::common::http::Action::kStreamAction: {
      const auto& stream_action = action.stream_action();
      if (streams.empty()) {
        break;
      }
      (*std::next(streams.begin(), stream_action.stream_id() % streams.size()))
          ->streamAction(stream_action);
      break;
    }
    default:
      // Maybe nothing is set?
      break;
    }
  }

  filter_callbacks.connection_.raiseEvent(Network::ConnectionEvent::LocalClose);
  filter_callbacks.connection_.dispatcher_.clearDeferredDeleteList();
}
DEFINE_PROTO_FUZZER(const test::common::http::ConnManagerImplTestCase& input) {
  try {
    TestUtility::validate(input);
  } catch (const ProtoValidationException& e) {
    ENVOY_LOG_MISC(debug, "ProtoValidationException: {}", e.what());
    return;
  } catch (const Envoy::ProtobufMessage::DeprecatedProtoFieldException& e) {
    ENVOY_LOG_MISC(debug, "DeprecatedProtoFieldException: {}", e.what());
    return;
  }

  FuzzConfig config(input.forward_client_cert());
  NiceMock<Network::MockDrainDecision> drain_close;
  NiceMock<Random::MockRandomGenerator> random;
  Stats::SymbolTableImpl symbol_table;
  Http::ContextImpl http_context(symbol_table);
  NiceMock<Runtime::MockLoader> runtime;
  NiceMock<LocalInfo::MockLocalInfo> local_info;
  NiceMock<Upstream::MockClusterManager> cluster_manager;
  NiceMock<Network::MockReadFilterCallbacks> filter_callbacks;
  NiceMock<Server::MockOverloadManager> overload_manager;
  auto ssl_connection = std::make_shared<Ssl::MockConnectionInfo>();
  bool connection_alive = true;

  ON_CALL(filter_callbacks.connection_, ssl()).WillByDefault(Return(ssl_connection));
  ON_CALL(Const(filter_callbacks.connection_), ssl()).WillByDefault(Return(ssl_connection));
  ON_CALL(filter_callbacks.connection_, close(_))
      .WillByDefault(InvokeWithoutArgs([&connection_alive] { connection_alive = false; }));
  filter_callbacks.connection_.stream_info_.downstream_address_provider_->setLocalAddress(
      std::make_shared<Network::Address::Ipv4Instance>("127.0.0.1"));
  filter_callbacks.connection_.stream_info_.downstream_address_provider_->setRemoteAddress(
      std::make_shared<Network::Address::Ipv4Instance>("0.0.0.0"));

  ConnectionManagerImpl conn_manager(config, drain_close, random, http_context, runtime, local_info,
                                     cluster_manager, overload_manager, config.time_system_);
  conn_manager.initializeReadFilterCallbacks(filter_callbacks);

  std::vector<FuzzStreamPtr> streams;

  for (const auto& action : input.actions()) {
    ENVOY_LOG_MISC(trace, "action {} with {} streams", action.DebugString(), streams.size());
    if (!connection_alive) {
      ENVOY_LOG_MISC(trace, "skipping due to dead connection");
      break;
    }

    switch (action.action_selector_case()) {
    case test::common::http::Action::kNewStream: {
      streams.emplace_back(new FuzzStream(
          conn_manager, config,
          Fuzz::fromHeaders<TestRequestHeaderMapImpl>(action.new_stream().request_headers(),
                                                       {}, {":authority"}),
          action.new_stream().status(), action.new_stream().end_stream()));
      break;
    }
    case test::common::http::Action::kStreamAction: {
      const auto& stream_action = action.stream_action();
      if (streams.empty()) {
        break;
      }
      (*std::next(streams.begin(), stream_action.stream_id() % streams.size()))
          ->streamAction(stream_action);
      break;
    }
    default:
       
      break;
    }
  }

  filter_callbacks.connection_.raiseEvent(Network::ConnectionEvent::LocalClose);
  filter_callbacks.connection_.dispatcher_.clearDeferredDeleteList();
}