Repository: envoyproxy/envoy
File: test/server/hot_restarting_parent_test.cc (C++)

Code before:
      .WillOnce(ReturnRef(address));
  EXPECT_CALL(listener_config, bindToPort()).WillOnce(Return(false));

  HotRestartMessage::Request request;
  request.mutable_pass_listen_socket()->set_address("tcp://0.0.0.0:80");
  HotRestartMessage message = hot_restarting_parent_.getListenSocketsForChild(request);
  EXPECT_EQ(-1, message.reply().pass_listen_socket().fd());
}

// Verifies that hot restart socket hand-off succeeds when the network namespace is included
// in the PassListenSocket request, matching the listener's namespaced address.
TEST_F(HotRestartingParentTest, GetListenSocketsForChildNetworkNamespaceMatch) {
  MockListenerManager listener_manager;
  Network::MockListenerConfig listener_config;
  MockOptions options;
  std::vector<std::reference_wrapper<Network::ListenerConfig>> listeners;
  InSequence s;
  listeners.push_back(std::ref(*static_cast<Network::ListenerConfig*>(&listener_config)));
  EXPECT_CALL(server_, listenerManager()).WillOnce(ReturnRef(listener_manager));
  EXPECT_CALL(listener_manager, listeners(ListenerManager::ListenerState::ACTIVE))
      .WillOnce(Return(listeners));
  EXPECT_CALL(listener_config, listenSocketFactories());
  // Create an address with a network namespace set.
  Network::Address::InstanceConstSharedPtr address(
      new Network::Address::Ipv4Instance(Network::Address::Ipv4Instance("0.0.0.0", 80),
                                         absl::optional<std::string>("/var/run/netns/ns1")));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      localAddress())
      .WillOnce(ReturnRef(address));
  EXPECT_CALL(listener_config, bindToPort()).WillOnce(Return(true));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      socketType())
      .WillOnce(Return(Network::Socket::Type::Stream));
  EXPECT_CALL(server_, options()).WillOnce(ReturnRef(options));
  EXPECT_CALL(options, concurrency()).WillOnce(Return(1));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      getListenSocket(_));

  // The request carries the network namespace, so the resolved address will match.
  HotRestartMessage::Request request;
  request.mutable_pass_listen_socket()->set_address("tcp://0.0.0.0:80");
  request.mutable_pass_listen_socket()->set_network_namespace("/var/run/netns/ns1");
  HotRestartMessage message = hot_restarting_parent_.getListenSocketsForChild(request);
  EXPECT_EQ(0, message.reply().pass_listen_socket().fd());
}

// Verifies that hot restart socket hand-off fails when a different network namespace is
// specified in the request compared to what the listener has configured.

Review comment (bug):
```suggestion
  Network::Address::InstanceConstSharedPtr address = std::make_shared<Network::Address::Ipv4Instance>("0.0.0.0", 80, nullptr, absl::optional<std::string>("/var/run/netns/ns1"));
```

Code after:
      .WillOnce(ReturnRef(address));
  EXPECT_CALL(listener_config, bindToPort()).WillOnce(Return(false));

  HotRestartMessage::Request request;
  request.mutable_pass_listen_socket()->set_address("tcp://0.0.0.0:80");
  HotRestartMessage message = hot_restarting_parent_.getListenSocketsForChild(request);
  EXPECT_EQ(-1, message.reply().pass_listen_socket().fd());
}

// Verifies that hot restart socket hand-off succeeds when the network namespace is included
// in the PassListenSocket request, matching the listener's namespaced address.
TEST_F(HotRestartingParentTest, GetListenSocketsForChildNetworkNamespaceMatch) {
  MockListenerManager listener_manager;
  Network::MockListenerConfig listener_config;
  MockOptions options;
  std::vector<std::reference_wrapper<Network::ListenerConfig>> listeners;
  InSequence s;
  listeners.push_back(std::ref(*static_cast<Network::ListenerConfig*>(&listener_config)));
  EXPECT_CALL(server_, listenerManager()).WillOnce(ReturnRef(listener_manager));
  EXPECT_CALL(listener_manager, listeners(ListenerManager::ListenerState::ACTIVE))
      .WillOnce(Return(listeners));
  EXPECT_CALL(listener_config, listenSocketFactories());
  // Create an address with a network namespace set.
  Network::Address::InstanceConstSharedPtr address =
      std::make_shared<Network::Address::Ipv4Instance>(
          "0.0.0.0", 80, nullptr, absl::optional<std::string>("/var/run/netns/ns1"));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      localAddress())
      .WillOnce(ReturnRef(address));
  EXPECT_CALL(listener_config, bindToPort()).WillOnce(Return(true));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      socketType())
      .WillOnce(Return(Network::Socket::Type::Stream));
  EXPECT_CALL(server_, options()).WillOnce(ReturnRef(options));
  EXPECT_CALL(options, concurrency()).WillOnce(Return(1));
  EXPECT_CALL(
      *static_cast<Network::MockListenSocketFactory*>(listener_config.socket_factories_[0].get()),
      getListenSocket(_));

  // The request carries the network namespace, so the resolved address will match.
  HotRestartMessage::Request request;
  request.mutable_pass_listen_socket()->set_address("tcp://0.0.0.0:80");
  request.mutable_pass_listen_socket()->set_network_namespace("/var/run/netns/ns1");
  HotRestartMessage message = hot_restarting_parent_.getListenSocketsForChild(request);
  EXPECT_EQ(0, message.reply().pass_listen_socket().fd());
}

// Verifies that hot restart socket hand-off fails when a different network namespace is
// specified in the request compared to what the listener has configured.