text:
using testing::_;
using testing::AtLeast;
using testing::InSequence;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;
using testing::ReturnNew;
using testing::ReturnRef;

namespace Envoy {
namespace Upstream {

// Friend class of HdsDelegate, making it easier to access private fields
class HdsDelegateFriend {
public:
  // Allows access to private function processMessage
  void processPrivateMessage(
      HdsDelegate& hd,
      std::unique_ptr<envoy::service::health::v3::HealthCheckSpecifier>&& message) {
    hd.processMessage(std::move(message));
  };
  HdsDelegateStats getStats(HdsDelegate& hd) { return hd.stats_; };
};

class HdsTest : public testing::Test {
protected:
  HdsTest()
      : retry_timer_(new Event::MockTimer()), server_response_timer_(new Event::MockTimer()),
        async_client_(new Grpc::MockAsyncClient()),
        api_(Api::createApiForTest(stats_store_, random_)),
        ssl_context_manager_(api_->timeSource()) {
    ON_CALL(server_context_, api()).WillByDefault(ReturnRef(*api_));
    node_.set_id("hds-node");
  }

  // Checks if the cluster counters are correct
  void checkHdsCounters(int requests, int responses, int errors, int updates) {
    auto stats = hds_delegate_friend_.getStats(*hds_delegate_);
    EXPECT_EQ(requests, stats.requests_.value());
    EXPECT_LE(responses, stats.responses_.value());
    EXPECT_EQ(errors, stats.errors_.value());
    EXPECT_EQ(updates, stats.updates_.value());
  }

  // Creates an HdsDelegate
  void createHdsDelegate() {
    InSequence s;
    EXPECT_CALL(server_context_.dispatcher_, createTimer_(_))
        .WillOnce(Invoke([this](Event::TimerCb timer_cb) {
          retry_timer_cb_ = timer_cb;
          return retry_timer_;
        }));
    // First call will set up the response timer for assertions, all other future calls
    // just return a new timer that we won't keep track of.
    EXPECT_CALL(server_context_.dispatcher_, createTimer_(_))
        .Times(AtLeast(1))
        .WillOnce(Invoke([this](Event::TimerCb timer_cb) {
          server_response_timer_cb_ = timer_cb;
          return server_response_timer_;
        }))
        .WillRepeatedly(testing::ReturnNew<NiceMock<Event::MockTimer>>());

    hds_delegate_ = std::make_unique<HdsDelegate>(
        server_context_, stats_store_, Grpc::RawAsyncClientPtr(async_client_), stats_store_,
        ssl_context_manager_, test_factory_);
  }

  void expectCreateClientConnection() {
    // Create a new mock connection for each call to createClientConnection.
    EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _))
        .WillRepeatedly(Invoke(
            [](Network::Address::InstanceConstSharedPtr, Network::Address::InstanceConstSharedPtr,
               Network::TransportSocketPtr&, const Network::ConnectionSocket::OptionsSharedPtr&) {
              Network::MockClientConnection* connection =
                  new NiceMock<Network::MockClientConnection>();

              // pretend our endpoint was connected to.
              connection->raiseEvent(Network::ConnectionEvent::Connected);

              // return this new, connected endpoint.
              return connection;
            }));
  }

  // Creates a HealthCheckSpecifier message that contains one endpoint and one
  // healthcheck
  envoy::service::health::v3::HealthCheckSpecifier* createSimpleMessage() {
    envoy::service::health::v3::HealthCheckSpecifier* msg =
        new envoy::service::health::v3::HealthCheckSpecifier;
    msg->mutable_interval()->set_seconds(1);

    auto* health_check = msg->add_cluster_health_checks();
    health_check->set_cluster_name("anna");
    health_check->add_health_checks()->mutable_timeout()->set_seconds(1);
    health_check->mutable_health_checks(0)->mutable_interval()->set_seconds(1);
    health_check->mutable_health_checks(0)->mutable_unhealthy_threshold()->set_value(2);
    health_check->mutable_health_checks(0)->mutable_healthy_threshold()->set_value(2);
    health_check->mutable_health_checks(0)->mutable_grpc_health_check();
    health_check->mutable_health_checks(0)->mutable_http_health_check()->set_codec_client_type(
        envoy::type::v3::HTTP1);
    health_check->mutable_health_checks(0)->mutable_http_health_check()->set_path("/healthcheck");

    auto* locality_endpoints = health_check->add_locality_endpoints();
    // add locality information to this endpoint set of one endpoint.
    auto* locality = locality_endpoints->mutable_locality();
    locality->set_region("middle_earth");
    locality->set_zone("shire");
    locality->set_sub_zone("hobbiton");

    // add one endpoint to this locality grouping.
    auto* socket_address =
        locality_endpoints->add_endpoints()->mutable_address()->mutable_socket_address();
    socket_address->set_address("127.0.0.0");
    socket_address->set_port_value(1234);

    return msg;
  }

  // Creates a HealthCheckSpecifier message that contains several clusters, endpoints, localities,
  // with only one health check type.
  std::unique_ptr<envoy::service::health::v3::HealthCheckSpecifier>
  createComplexSpecifier(uint32_t n_clusters, uint32_t n_localities, uint32_t n_endpoints,
                         bool disable_hc = false) {
    // Final specifier to return.
    std::unique_ptr<envoy::service::health::v3::HealthCheckSpecifier> msg =
        std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();

    // set interval.
    msg->mutable_interval()->set_seconds(1);

    for (uint32_t cluster_num = 0; cluster_num < n_clusters; cluster_num++) {
      // add a cluster with a name by iteration, with path /healthcheck
      auto* health_check = msg->add_cluster_health_checks();
      health_check->set_cluster_name(absl::StrCat("anna", cluster_num));
      health_check->add_health_checks()->mutable_timeout()->set_seconds(1);

      auto* health_check_info = health_check->mutable_health_checks(0);
      health_check_info->mutable_interval()->set_seconds(1);
      health_check_info->mutable_unhealthy_threshold()->set_value(2);
      health_check_info->mutable_healthy_threshold()->set_value(2);

      auto* health_check_http = health_check_info->mutable_http_health_check();
      health_check_http->set_codec_client_type(envoy::type::v3::HTTP1);
      health_check_http->set_path("/healthcheck");

      // add some locality groupings with iterative names for verification.
      for (uint32_t loc_num = 0; loc_num < n_localities; loc_num++) {
        auto* locality_endpoints = health_check->add_locality_endpoints();

        // set the locality information for this group.
        auto* locality = locality_endpoints->mutable_locality();
        locality->set_region(absl::StrCat("region", cluster_num));
        locality->set_zone(absl::StrCat("zone", loc_num));
        locality->set_sub_zone(absl::StrCat("subzone", loc_num));

        // add some endpoints to the locality group with iterative naming for verification.
        for (uint32_t endpoint_num = 0; endpoint_num < n_endpoints; endpoint_num++) {
          auto* endpoint = locality_endpoints->add_endpoints();

          auto* socket_address = endpoint->mutable_address()->mutable_socket_address();
          socket_address->set_address(
              absl::StrCat("127.", cluster_num, ".", loc_num, ".", endpoint_num));
          socket_address->set_port_value(1234);
          endpoint->mutable_health_check_config()->set_disable_active_health_check(disable_hc);
        }
      }
    }

    return msg;
  }

  void
  addTransportSocketMatches(envoy::service::health::v3::ClusterHealthCheck* cluster_health_check,
                            std::string match, std::string criteria) {
    // Add transport socket matches to specified cluster and its first health check.
    const std::string match_yaml = absl::StrFormat(
        R"EOF(
transport_socket_matches:
- name: "test_socket"
  match:
    %s: "true"
  transport_socket:
    name: "envoy.transport_sockets.raw_buffer"
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer
)EOF",
        match);
    cluster_health_check->MergeFrom(
        TestUtility::parseYaml<envoy::service::health::v3::ClusterHealthCheck>(match_yaml));

    // Add transport socket match criteria to our health check, for filtering matches.
    const std::string criteria_yaml = absl::StrFormat(
        R"EOF(
transport_socket_match_criteria:
  %s: "true"
)EOF",
        criteria);
    cluster_health_check->mutable_health_checks(0)->MergeFrom(
        TestUtility::parseYaml<envoy::config::core::v3::HealthCheck>(criteria_yaml));
  }

  NiceMock<Server::Configuration::MockServerFactoryContext> server_context_;
  Event::SimulatedTimeSystem time_system_;
  envoy::config::core::v3::Node node_;
  Stats::IsolatedStoreImpl stats_store_;
  MockClusterInfoFactory test_factory_;

  std::unique_ptr<Upstream::HdsDelegate> hds_delegate_;
  HdsDelegateFriend hds_delegate_friend_;

  Event::MockTimer* retry_timer_;
  Event::TimerCb retry_timer_cb_;
  Event::MockTimer* server_response_timer_;
  Event::TimerCb server_response_timer_cb_;

  std::shared_ptr<Upstream::MockClusterInfo> cluster_info_{
      new NiceMock<Upstream::MockClusterInfo>()};
  std::unique_ptr<envoy::service::health::v3::HealthCheckSpecifier> message;
  Grpc::MockAsyncStream async_stream_;
  Grpc::MockAsyncClient* async_client_;
  Api::ApiPtr api_;
  Extensions::TransportSockets::Tls::ContextManagerImpl ssl_context_manager_;
  NiceMock<Random::MockRandomGenerator> random_;
};

// Test that HdsDelegate builds and sends initial message correctly
TEST_F(HdsTest, HealthCheckRequest) {
  envoy::service::health::v3::HealthCheckRequestOrEndpointHealthResponse request;
  request.mutable_health_check_request()->mutable_node()->set_id("hds-node");
  request.mutable_health_check_request()->mutable_capability()->add_health_check_protocols(
      envoy::service::health::v3::Capability::HTTP);
  request.mutable_health_check_request()->mutable_capability()->add_health_check_protocols(
      envoy::service::health::v3::Capability::TCP);

  EXPECT_CALL(server_context_.local_info_, node()).WillOnce(ReturnRef(node_));
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(Grpc::ProtoBufferEq(request), false));
  createHdsDelegate();
}

// Test if processMessage processes endpoints from a HealthCheckSpecifier
// message correctly
TEST_F(HdsTest, TestProcessMessageEndpoints) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  // - Cluster "anna0" with 3 endpoints
  // - Cluster "anna1" with 3 endpoints
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  for (int i = 0; i < 2; i++) {
    auto* health_check = message->add_cluster_health_checks();
    health_check->set_cluster_name("anna" + std::to_string(i));
    for (int j = 0; j < 3; j++) {
      auto* address = health_check->add_locality_endpoints()->add_endpoints()->mutable_address();
      address->mutable_socket_address()->set_address("127.0.0." + std::to_string(i));
      address->mutable_socket_address()->set_port_value(1234 + j);
    }
  }

  // Process message
  EXPECT_CALL(test_factory_, createClusterInfo(_)).Times(2).WillRepeatedly(Return(cluster_info_));
  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  // Check Correctness
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) {
      auto& host =
          hds_delegate_->hdsClusters()[i]->prioritySet().hostSetsPerPriority()[0]->hosts()[j];
      EXPECT_EQ(host->address()->ip()->addressAsString(), "127.0.0." + std::to_string(i));
      EXPECT_EQ(host->address()->ip()->port(), 1234 + j);
    }
  }
}

TEST_F(HdsTest, TestHdsCluster) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  auto* health_check = message->add_cluster_health_checks();
  health_check->set_cluster_name("test_cluster");
  auto* address = health_check->add_locality_endpoints()->add_endpoints()->mutable_address();
  address->mutable_socket_address()->set_address("127.0.0.2");
  address->mutable_socket_address()->set_port_value(1234);

  // Process message
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_));
  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  EXPECT_EQ(hds_delegate_->hdsClusters()[0]->initializePhase(),
            Upstream::Cluster::InitializePhase::Primary);

  // HdsCluster uses health_checkers_ instead.
  EXPECT_TRUE(hds_delegate_->hdsClusters()[0]->healthChecker() == nullptr);

  // outlier detector is always null for HdsCluster.
  EXPECT_TRUE(hds_delegate_->hdsClusters()[0]->outlierDetector() == nullptr);
  const auto* hds_cluster = hds_delegate_->hdsClusters()[0].get();
  EXPECT_TRUE(hds_cluster->outlierDetector() == nullptr);
}

// Test if processMessage processes health checks from a HealthCheckSpecifier
// message correctly
TEST_F(HdsTest, TestProcessMessageHealthChecks) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  // - Cluster "minkowski0" with 2 health_checks
  // - Cluster "minkowski1" with 3 health_checks
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  for (int i = 0; i < 2; i++) {
    auto* health_check = message->add_cluster_health_checks();
    health_check->set_cluster_name("minkowski" + std::to_string(i));
    for (int j = 0; j < i + 2; j++) {
      auto hc = health_check->add_health_checks();
      hc->mutable_timeout()->set_seconds(i);
      hc->mutable_interval()->set_seconds(j);
      hc->mutable_unhealthy_threshold()->set_value(j + 1);
      hc->mutable_healthy_threshold()->set_value(j + 1);
      hc->mutable_grpc_health_check();
      hc->mutable_http_health_check()->set_codec_client_type(envoy::type::v3::HTTP1);
      hc->mutable_http_health_check()->set_path("/healthcheck");
    }
  }

  // Process message
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));

  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  // Check Correctness
  EXPECT_EQ(hds_delegate_->hdsClusters()[0]->healthCheckers().size(), 2);
  EXPECT_EQ(hds_delegate_->hdsClusters()[1]->healthCheckers().size(), 3);
}

// Test if processMessage exits gracefully upon receiving a malformed message
TEST_F(HdsTest, TestProcessMessageMissingFields) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message.reset(createSimpleMessage());
  // remove healthy threshold field to create an error
  message->mutable_cluster_health_checks(0)->mutable_health_checks(0)->clear_healthy_threshold();

  // call onReceiveMessage function for testing. Should increment stat_ errors upon
  // getting a bad message
  hds_delegate_->onReceiveMessage(std::move(message));

  // Ensure that we never enabled the response timer that would start health checks,
  // since this config was invalid.
  EXPECT_FALSE(server_response_timer_->enabled_);

  // ensure that no partial information was stored in hds_clusters_
  EXPECT_TRUE(hds_delegate_->hdsClusters().empty());

  // Check Correctness by verifying one request and one error has been generated in stat_
  EXPECT_EQ(hds_delegate_friend_.getStats(*hds_delegate_).errors_.value(), 1);
  EXPECT_EQ(hds_delegate_friend_.getStats(*hds_delegate_).requests_.value(), 1);
}

// Test if processMessage exits gracefully upon receiving a malformed message
// There was a previous valid config, so we go back to that.
TEST_F(HdsTest, TestProcessMessageMissingFieldsWithFallback) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message.reset(createSimpleMessage());

  Network::MockClientConnection* connection = new NiceMock<Network::MockClientConnection>();
  EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _))
      .WillRepeatedly(Return(connection));
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(2);
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_));
  EXPECT_CALL(*connection, setBufferLimits(_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  connection->raiseEvent(Network::ConnectionEvent::Connected);

  // Create a invalid message
  message.reset(createSimpleMessage());

  // set this address to be distinguishable from the previous message in sendResponse()
  message->mutable_cluster_health_checks(0)
      ->mutable_locality_endpoints(0)
      ->mutable_endpoints(0)
      ->mutable_address()
      ->mutable_socket_address()
      ->set_address("9.9.9.9");

  // remove healthy threshold field to create an error
  message->mutable_cluster_health_checks(0)->mutable_health_checks(0)->clear_healthy_threshold();

  // Pass invalid message through. Should increment stat_ errors upon
  // getting a bad message.
  hds_delegate_->onReceiveMessage(std::move(message));

  // Ensure that the timer is enabled since there was a previous valid specifier.
  EXPECT_TRUE(server_response_timer_->enabled_);

  // read the response and check that it is pinging the old
  // address 127.0.0.0 instead of the new 9.9.9.9
  auto response = hds_delegate_->sendResponse();
  EXPECT_EQ(response.endpoint_health_response()
                .endpoints_health(0)
                .endpoint()
                .address()
                .socket_address()
                .address(),
            "127.0.0.0");

  // Check Correctness by verifying one request and one error has been generated in stat_
  EXPECT_EQ(hds_delegate_friend_.getStats(*hds_delegate_).errors_.value(), 1);
  EXPECT_EQ(hds_delegate_friend_.getStats(*hds_delegate_).requests_.value(), 2);
}

// Test if sendResponse() retains the structure of all endpoints ingested in the specifier
// from onReceiveMessage(). This verifies that all endpoints are grouped by the correct
// cluster and the correct locality.
TEST_F(HdsTest, TestSendResponseMultipleEndpoints) {
  // number of clusters, localities by cluster, and endpoints by locality
  // to build and verify off of.
  const uint32_t NumClusters = 2;
  const uint32_t NumLocalities = 2;
  const uint32_t NumEndpoints = 2;

  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = createComplexSpecifier(NumClusters, NumLocalities, NumEndpoints);

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(2);
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));

  // Carry over cluster name on a call to createClusterInfo,
  // in the same way that the prod factory does.
  EXPECT_CALL(test_factory_, createClusterInfo(_))
      .WillRepeatedly(Invoke([](const ClusterInfoFactory::CreateClusterInfoParams& params) {
        std::shared_ptr<Upstream::MockClusterInfo> cluster_info{
            new NiceMock<Upstream::MockClusterInfo>()};
        // copy name for use in sendResponse() in HdsCluster

        cluster_info->name_ = params.cluster_.name();
        return cluster_info;
      }));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_))
      .Times(NumClusters * NumLocalities * NumEndpoints);

  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));

  // read response and verify fields
  const auto response = hds_delegate_->sendResponse().endpoint_health_response();

  ASSERT_EQ(response.cluster_endpoints_health_size(), NumClusters);

  for (uint32_t i = 0; i < NumClusters; i++) {
    const auto& cluster = response.cluster_endpoints_health(i);

    // Expect the correct cluster name by index
    EXPECT_EQ(cluster.cluster_name(), absl::StrCat("anna", i));

    // Every cluster should have two locality groupings
    ASSERT_EQ(cluster.locality_endpoints_health_size(), NumLocalities);

    for (uint32_t j = 0; j < NumLocalities; j++) {
      // Every locality should have a number based on its index
      const auto& loc_group = cluster.locality_endpoints_health(j);
      EXPECT_EQ(loc_group.locality().region(), absl::StrCat("region", i));
      EXPECT_EQ(loc_group.locality().zone(), absl::StrCat("zone", j));
      EXPECT_EQ(loc_group.locality().sub_zone(), absl::StrCat("subzone", j));

      // Every locality should have two endpoints.
      ASSERT_EQ(loc_group.endpoints_health_size(), NumEndpoints);

      for (uint32_t k = 0; k < NumEndpoints; k++) {

        // every endpoint's address is based on all 3 index values.
        const auto& endpoint_health = loc_group.endpoints_health(k);
        EXPECT_EQ(endpoint_health.endpoint().address().socket_address().address(),
                  absl::StrCat("127.", i, ".", j, ".", k));
        EXPECT_EQ(endpoint_health.health_status(), envoy::config::core::v3::UNHEALTHY);
      }
    }
  }
  EXPECT_EQ(response.endpoints_health_size(), NumClusters * NumLocalities * NumEndpoints);
}

// Tests OnReceiveMessage given a minimal HealthCheckSpecifier message
TEST_F(HdsTest, TestMinimalOnReceiveMessage) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  // Process message
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  hds_delegate_->onReceiveMessage(std::move(message));
}

// Test that a transport_socket_matches and transport_socket_match_criteria filter as expected to
// build the correct TransportSocketFactory based on these fields.
TEST_F(HdsTest, TestSocketContext) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message with transport sockets.
  message.reset(createSimpleMessage());
  addTransportSocketMatches(message->mutable_cluster_health_checks(0), "test_match", "test_match");

  Network::MockClientConnection* connection = new NiceMock<Network::MockClientConnection>();
  EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _))
      .WillRepeatedly(Return(connection));

  // Pull out socket_matcher object normally internal to createClusterInfo, to test that a matcher
  // would match the expected socket.
  std::unique_ptr<TransportSocketMatcherImpl> socket_matcher;
  EXPECT_CALL(test_factory_, createClusterInfo(_))
      .WillRepeatedly(Invoke([&](const ClusterInfoFactory::CreateClusterInfoParams& params) {
        // Build scope, factory_context as does ProdClusterInfoFactory.
        Envoy::Stats::ScopeSharedPtr scope =
            params.stats_.createScope(fmt::format("cluster.{}.", params.cluster_.name()));
        Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context(
            params.server_context_, params.ssl_context_manager_, *scope,
            params.server_context_.clusterManager(), params.stats_,
            params.server_context_.messageValidationVisitor());

        // Create a mock socket_factory for the scope of this unit test.
        std::unique_ptr<Envoy::Network::UpstreamTransportSocketFactory> socket_factory =
            std::make_unique<Network::MockTransportSocketFactory>();

        // set socket_matcher object in test scope.
        socket_matcher = std::make_unique<Envoy::Upstream::TransportSocketMatcherImpl>(
            params.cluster_.transport_socket_matches(), factory_context, socket_factory, *scope);

        // But still use the fake cluster_info_.
        return cluster_info_;
      }));

  EXPECT_CALL(*connection, setBufferLimits(_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_));

  // Process message.
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  hds_delegate_->onReceiveMessage(std::move(message));

  // pretend our endpoint was connected to.
  connection->raiseEvent(Network::ConnectionEvent::Connected);

  // Get our health checker to match against.
  const auto clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(clusters.size(), 1);
  const auto hcs = clusters[0]->healthCheckers();
  ASSERT_EQ(hcs.size(), 1);

  // Check that our match hits.
  HealthCheckerImplBase* health_checker_base = dynamic_cast<HealthCheckerImplBase*>(hcs[0].get());
  const auto match =
      socket_matcher->resolve(health_checker_base->transportSocketMatchMetadata().get());
  EXPECT_EQ(match.name_, "test_socket");
}

// Tests OnReceiveMessage given a HealthCheckSpecifier message without interval field
TEST_F(HdsTest, TestDefaultIntervalOnReceiveMessage) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  // notice that interval field is intentionally left undefined

  // Process message
  EXPECT_CALL(*server_response_timer_, enableTimer(std::chrono::milliseconds(1000), _))
      .Times(AtLeast(1));
  hds_delegate_->onReceiveMessage(std::move(message));
}

// Tests that SendResponse responds to the server in a timely fashion
// given a minimal HealthCheckSpecifier message
TEST_F(HdsTest, TestMinimalSendResponse) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  // Process message and send 2 responses
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _)).Times(2);
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();
  server_response_timer_cb_();
}

TEST_F(HdsTest, TestStreamConnectionFailure) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _))
      .WillOnce(Return(nullptr))
      .WillOnce(Return(nullptr))
      .WillOnce(Return(nullptr))
      .WillOnce(Return(nullptr))
      .WillOnce(Return(nullptr))
      .WillOnce(Return(&async_stream_));

  EXPECT_CALL(random_, random()).WillOnce(Return(1000005)).WillRepeatedly(Return(654321));
  EXPECT_CALL(*retry_timer_, enableTimer(std::chrono::milliseconds(5), _));
  EXPECT_CALL(*retry_timer_, enableTimer(std::chrono::milliseconds(321), _));
  EXPECT_CALL(*retry_timer_, enableTimer(std::chrono::milliseconds(2321), _));
  EXPECT_CALL(*retry_timer_, enableTimer(std::chrono::milliseconds(6321), _));
  EXPECT_CALL(*retry_timer_, enableTimer(std::chrono::milliseconds(14321), _));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));

  // Test connection failure and retry
  createHdsDelegate();
  retry_timer_cb_();
  retry_timer_cb_();
  retry_timer_cb_();
  retry_timer_cb_();
  retry_timer_cb_();
}

// TODO(lilika): Add unit tests for HdsDelegate::sendResponse() with healthy and
// unhealthy endpoints.

// Tests that SendResponse responds to the server correctly given
// a HealthCheckSpecifier message that contains a single endpoint
// which times out
TEST_F(HdsTest, TestSendResponseOneEndpointTimeout) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message.reset(createSimpleMessage());

  Network::MockClientConnection* connection_ = new NiceMock<Network::MockClientConnection>();
  EXPECT_CALL(server_context_.dispatcher_, createClientConnection_(_, _, _, _))
      .WillRepeatedly(Return(connection_));
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(2);
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_));
  EXPECT_CALL(*connection_, setBufferLimits(_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  connection_->raiseEvent(Network::ConnectionEvent::Connected);

  // Send Response
  auto msg = hds_delegate_->sendResponse();

  // Correctness
  EXPECT_EQ(msg.endpoint_health_response().endpoints_health(0).health_status(),
            envoy::config::core::v3::UNHEALTHY);
  EXPECT_EQ(msg.endpoint_health_response()
                .endpoints_health(0)
                .endpoint()
                .address()
                .socket_address()
                .address(),
            "127.0.0.0");
  EXPECT_EQ(msg.endpoint_health_response()
                .endpoints_health(0)
                .endpoint()
                .address()
                .socket_address()
                .port_value(),
            1234);
}

// Check to see if two of the same specifier does not get parsed twice in a row.
TEST_F(HdsTest, TestSameSpecifier) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message.reset(createSimpleMessage());

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Try to change the specifier, but it is the same.
  message.reset(createSimpleMessage());
  hds_delegate_->onReceiveMessage(std::move(message));

  // Check to see that HDS got two requests, but only used the specifier one time.
  checkHdsCounters(2, 0, 0, 1);

  // Try to change the specifier, but use a new specifier this time.
  message = createComplexSpecifier(1, 1, 2);
  hds_delegate_->onReceiveMessage(std::move(message));

  // Check that both requests and updates increased, meaning we did an update.
  checkHdsCounters(3, 0, 0, 2);
}

// Test to see that if a cluster is added or removed, the ones that did not change are reused.
TEST_F(HdsTest, TestClusterChange) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = createComplexSpecifier(2, 1, 1);

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Get cluster shared pointers to make sure they are the same memory addresses, that we reused
  // them.
  auto original_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(original_clusters.size(), 2);

  // Add a third cluster to the specifier. The first two should reuse pointers.
  message = createComplexSpecifier(3, 1, 1);
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get the new clusters list from HDS.
  auto new_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(new_clusters.size(), 3);

  // Make sure our first two clusters are at the same address in memory as before.
  for (int i = 0; i < 2; i++) {
    EXPECT_EQ(new_clusters[i], original_clusters[i]);
  }

  message = createComplexSpecifier(3, 1, 1);

  // Remove the first element, change the order of the last two elements.
  message->mutable_cluster_health_checks()->SwapElements(0, 2);
  message->mutable_cluster_health_checks()->RemoveLast();
  // Sanity check.
  ASSERT_EQ(message->cluster_health_checks_size(), 2);

  // Send this new specifier.
  hds_delegate_->onReceiveMessage(std::move(message));

  // Check to see that even if we changed the order, we get the expected pointers.
  auto final_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(final_clusters.size(), 2);

  // Compare first cluster in the new list is the same as the last in the previous list,
  // and that the second cluster in the new list is the same as the second in the previous.
  for (int i = 0; i < 2; i++) {
    EXPECT_EQ(final_clusters[i], new_clusters[2 - i]);
  }

  // Check to see that HDS got three requests, and updated three times with it.
  checkHdsCounters(3, 0, 0, 3);
}

// Edit one of two cluster's endpoints by adding and removing.
TEST_F(HdsTest, TestUpdateEndpoints) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message, and later add/remove endpoints from the second cluster.
  message.reset(createSimpleMessage());
  message->MergeFrom(*createComplexSpecifier(1, 1, 2));

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Save list of hosts/endpoints for comparison later.
  auto original_hosts = hds_delegate_->hdsClusters()[1]->hosts();
  ASSERT_EQ(original_hosts.size(), 2);

  // Add 3 endpoints to the specifier's second cluster. The first in the list should reuse pointers.
  message.reset(createSimpleMessage());
  message->MergeFrom(*createComplexSpecifier(1, 1, 5));
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get the new clusters list from HDS.
  auto new_hosts = hds_delegate_->hdsClusters()[1]->hosts();
  ASSERT_EQ(new_hosts.size(), 5);

  // Make sure our first two endpoints are at the same address in memory as before.
  for (int i = 0; i < 2; i++) {
    EXPECT_EQ(original_hosts[i], new_hosts[i]);
  }
  EXPECT_TRUE(original_hosts[0] != new_hosts[2]);

  // This time, have 4 endpoints, 2 each under 2 localities.
  // The first locality will be reused, so its 2 endpoints will be as well.
  // The second locality is new so we should be getting 2 new endpoints.
  // Since the first locality had 5 but now has 2, we are removing 3.
  // 2 ADDED, 3 REMOVED, 2 REUSED.
  message.reset(createSimpleMessage());
  message->MergeFrom(*createComplexSpecifier(1, 2, 2));
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get this new list of hosts.
  auto final_hosts = hds_delegate_->hdsClusters()[1]->hosts();
  ASSERT_EQ(final_hosts.size(), 4);

  // Ensure the first two elements in the new list are reused.
  for (int i = 0; i < 2; i++) {
    EXPECT_EQ(new_hosts[i], final_hosts[i]);
  }

  // Ensure the first last two elements in the new list are different then the previous list.
  for (int i = 2; i < 4; i++) {
    EXPECT_TRUE(new_hosts[i] != final_hosts[i]);
  }

  // Check to see that HDS got three requests, and updated three times with it.
  checkHdsCounters(3, 0, 0, 3);
}

// Skip the endpoints with disabled active health check during message processing.
TEST_F(HdsTest, TestUpdateEndpointsWithActiveHCflag) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message, and later add/remove endpoints from the second cluster.
  message.reset(createSimpleMessage());
  message->MergeFrom(*createComplexSpecifier(1, 1, 2));

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Save list of hosts/endpoints for comparison later.
  auto original_hosts = hds_delegate_->hdsClusters()[1]->hosts();
  ASSERT_EQ(original_hosts.size(), 2);

  // Ignoring the endpoints with disabled active health check.
  message.reset(createSimpleMessage());
  message->MergeFrom(*createComplexSpecifier(1, 1, 2, true));
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get the new clusters list from HDS.
  auto new_hosts = hds_delegate_->hdsClusters()[1]->hosts();
  ASSERT_EQ(new_hosts.size(), 0);
}

// Test adding, reusing, and removing health checks.
TEST_F(HdsTest, TestUpdateHealthCheckers) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message with two different health checkers.
  message.reset(createSimpleMessage());
  auto new_hc = message->mutable_cluster_health_checks(0)->add_health_checks();
  new_hc->MergeFrom(message->mutable_cluster_health_checks(0)->health_checks(0));
  new_hc->mutable_http_health_check()->set_path("/different_path");

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Save list of health checkers for use later.
  auto original_hcs = hds_delegate_->hdsClusters()[0]->healthCheckers();
  ASSERT_EQ(original_hcs.size(), 2);

  // Create a new specifier, but make the second health checker different and add a third.
  // Then reverse the order so the first one is at the end, testing the hashing works as expected.
  message.reset(createSimpleMessage());
  auto new_hc0 = message->mutable_cluster_health_checks(0)->add_health_checks();
  new_hc0->MergeFrom(message->mutable_cluster_health_checks(0)->health_checks(0));
  new_hc0->mutable_http_health_check()->set_path("/path0");
  auto new_hc1 = message->mutable_cluster_health_checks(0)->add_health_checks();
  new_hc1->MergeFrom(message->mutable_cluster_health_checks(0)->health_checks(0));
  new_hc1->mutable_http_health_check()->set_path("/path1");
  message->mutable_cluster_health_checks(0)->mutable_health_checks()->SwapElements(0, 2);
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get the new health check list from HDS.
  auto new_hcs = hds_delegate_->hdsClusters()[0]->healthCheckers();
  ASSERT_EQ(new_hcs.size(), 3);

  // Make sure our first hc from the original list is the same as the third in the new list.
  EXPECT_EQ(original_hcs[0], new_hcs[2]);
  EXPECT_TRUE(original_hcs[1] != new_hcs[1]);

  // Check to see that HDS got two requests, and updated two times with it.
  checkHdsCounters(2, 0, 0, 2);
}

// Test to see that if clusters with an empty name get used, there are two clusters.
// Also test to see that if two clusters with the same non-empty name are used, only have
// One cluster.
TEST_F(HdsTest, TestClusterSameName) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  message = createComplexSpecifier(2, 1, 1);
  // Set both clusters to have an empty name.
  message->mutable_cluster_health_checks(0)->set_cluster_name("");
  message->mutable_cluster_health_checks(1)->set_cluster_name("");

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, false));
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillRepeatedly(Return(cluster_info_));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  // Process message
  hds_delegate_->onReceiveMessage(std::move(message));
  hds_delegate_->sendResponse();

  // Get the clusters from HDS
  auto original_clusters = hds_delegate_->hdsClusters();

  // Make sure that even though they have the same name, since they are empty there are two and they
  // do not point to the same thing.
  ASSERT_EQ(original_clusters.size(), 2);
  ASSERT_TRUE(original_clusters[0] != original_clusters[1]);

  // Create message with 3 clusters this time so we force an update.
  message = createComplexSpecifier(3, 1, 1);
  // Set both clusters to have empty names empty name.
  message->mutable_cluster_health_checks(0)->set_cluster_name("");
  message->mutable_cluster_health_checks(1)->set_cluster_name("");

  // Test that we still get requested number of clusters, even with repeated names on update since
  // they are empty.
  hds_delegate_->onReceiveMessage(std::move(message));
  auto new_clusters = hds_delegate_->hdsClusters();

  // Check that since the names are empty, we do not reuse and just reconstruct.
  ASSERT_EQ(new_clusters.size(), 3);
  ASSERT_TRUE(original_clusters[0] != new_clusters[0]);
  ASSERT_TRUE(original_clusters[1] != new_clusters[1]);

  // Create a new message.
  message = createComplexSpecifier(2, 1, 1);
  // Set both clusters to have the same, non-empty name.
  message->mutable_cluster_health_checks(0)->set_cluster_name("anna");
  message->mutable_cluster_health_checks(1)->set_cluster_name("anna");

  hds_delegate_->onReceiveMessage(std::move(message));

  // Check that since they both have the same name, only one of them gets used.
  auto final_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(final_clusters.size(), 1);

  // Check to see that HDS got three requests, and updated three times with it.
  checkHdsCounters(3, 0, 0, 3);
}

// Test that a transport_socket_matches and transport_socket_match_criteria filter fail when not
// matching, and then after an update the same cluster is used but now matches.
TEST_F(HdsTest, TestUpdateSocketContext) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create a new active connection on request, setting its status to connected
  // to mock a found endpoint.
  expectCreateClientConnection();

  // Pull out socket_matcher object normally internal to createClusterInfo, to test that a matcher
  // would match the expected socket.
  std::vector<std::unique_ptr<TransportSocketMatcherImpl>> socket_matchers;
  EXPECT_CALL(test_factory_, createClusterInfo(_))
      .WillRepeatedly(Invoke([&](const ClusterInfoFactory::CreateClusterInfoParams& params) {
        // Build scope, factory_context as does ProdClusterInfoFactory.
        Envoy::Stats::ScopeSharedPtr scope =
            params.stats_.createScope(fmt::format("cluster.{}.", params.cluster_.name()));
        Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context(
            params.server_context_, params.ssl_context_manager_, *scope,
            params.server_context_.clusterManager(), params.stats_,
            params.server_context_.messageValidationVisitor());

        // Create a mock socket_factory for the scope of this unit test.
        std::unique_ptr<Envoy::Network::UpstreamTransportSocketFactory> socket_factory =
            std::make_unique<Network::MockTransportSocketFactory>();

        // set socket_matcher object in test scope.
        socket_matchers.push_back(std::make_unique<Envoy::Upstream::TransportSocketMatcherImpl>(
            params.cluster_.transport_socket_matches(), factory_context, socket_factory, *scope));

        // But still use the fake cluster_info_.
        return cluster_info_;
      }));
  EXPECT_CALL(server_context_.dispatcher_, deferredDelete_(_)).Times(AtLeast(1));
  EXPECT_CALL(*server_response_timer_, enableTimer(_, _)).Times(AtLeast(1));

  // Create Message, with a non-valid match and process.
  message.reset(createSimpleMessage());
  addTransportSocketMatches(message->mutable_cluster_health_checks(0), "bad_match", "test_match");
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get our health checker to match against.
  const auto first_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(first_clusters.size(), 1);
  const auto first_hcs = first_clusters[0]->healthCheckers();
  ASSERT_EQ(first_hcs.size(), 1);

  // Check that our fails so it uses default.
  HealthCheckerImplBase* first_health_checker_base =
      dynamic_cast<HealthCheckerImplBase*>(first_hcs[0].get());
  const auto first_match =
      socket_matchers[0]->resolve(first_health_checker_base->transportSocketMatchMetadata().get());
  EXPECT_EQ(first_match.name_, "default");

  // Create a new Message, this time with a good match.
  message.reset(createSimpleMessage());
  addTransportSocketMatches(message->mutable_cluster_health_checks(0), "test_match", "test_match");
  hds_delegate_->onReceiveMessage(std::move(message));

  // Get our new health checker to match against.
  const auto second_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(second_clusters.size(), 1);
  // Check that this new pointer is actually the same pointer to the first cluster.
  ASSERT_EQ(second_clusters[0], first_clusters[0]);
  const auto second_hcs = second_clusters[0]->healthCheckers();
  ASSERT_EQ(second_hcs.size(), 1);

  // Check that since we made no change to our health checkers, the pointer was reused.
  EXPECT_EQ(first_hcs[0], second_hcs[0]);

  // Check that our match hits.
  HealthCheckerImplBase* second_health_checker_base =
      dynamic_cast<HealthCheckerImplBase*>(second_hcs[0].get());
  ASSERT_EQ(socket_matchers.size(), 2);
  const auto second_match =
      socket_matchers[1]->resolve(second_health_checker_base->transportSocketMatchMetadata().get());
  EXPECT_EQ(second_match.name_, "test_socket");

  // Create a new Message, this we leave the transport socket the same but change the health check's
  // filter. This means that the health checker changes but the transport_socket_matches in the
  // ClusterHealthCheck does not.
  message.reset(createSimpleMessage());
  addTransportSocketMatches(message->mutable_cluster_health_checks(0), "test_match",
                            "something_new");

  hds_delegate_->onReceiveMessage(std::move(message));
  // Get our new health checker to match against.
  const auto third_clusters = hds_delegate_->hdsClusters();
  ASSERT_EQ(third_clusters.size(), 1);
  // Check that this new pointer is actually the same pointer to the first cluster.
  ASSERT_EQ(third_clusters[0], first_clusters[0]);
  const auto third_hcs = third_clusters[0]->healthCheckers();
  ASSERT_EQ(third_hcs.size(), 1);

  // Check that since we made a change to our HC, it is a new pointer.
  EXPECT_TRUE(first_hcs[0] != third_hcs[0]);

  HealthCheckerImplBase* third_health_checker_base =
      dynamic_cast<HealthCheckerImplBase*>(third_hcs[0].get());

  // Check that our socket matchers is still a size 2. This is because createClusterInfo(_) is never
  // called again since there was no update to transportSocketMatches.
  ASSERT_EQ(socket_matchers.size(), 2);
  const auto third_match =
      socket_matchers[1]->resolve(third_health_checker_base->transportSocketMatchMetadata().get());
  // Since this again does not match, it uses default.
  EXPECT_EQ(third_match.name_, "default");
}

TEST_F(HdsTest, TestCustomHealthCheckPortWhenCreate) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  // - Cluster "anna" with 3 lb_endpoints
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  auto* health_check = message->add_cluster_health_checks();
  health_check->set_cluster_name("anna");
  for (int i = 0; i < 3; i++) {
    auto* endpoint = health_check->add_locality_endpoints()->add_endpoints();
    endpoint->mutable_health_check_config()->set_port_value(4321 + i);
    auto* address = endpoint->mutable_address();
    address->mutable_socket_address()->set_address("127.0.0.1");
    address->mutable_socket_address()->set_port_value(1234 + i);
  }

  // Process message
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_));
  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  // Check Correctness
  for (int i = 0; i < 3; i++) {
    auto& host =
        hds_delegate_->hdsClusters()[0]->prioritySet().hostSetsPerPriority()[0]->hosts()[i];
    EXPECT_EQ(host->address()->ip()->port(), 1234 + i);
    EXPECT_EQ(host->healthCheckAddress()->ip()->port(), 4321 + i);
  }
}

TEST_F(HdsTest, TestCustomHealthCheckPortWhenUpdate) {
  EXPECT_CALL(*async_client_, startRaw(_, _, _, _)).WillOnce(Return(&async_stream_));
  EXPECT_CALL(async_stream_, sendMessageRaw_(_, _));
  createHdsDelegate();

  // Create Message
  // - Cluster "anna" with 1 lb_endpoints with 3 endpoints
  message = std::make_unique<envoy::service::health::v3::HealthCheckSpecifier>();
  message->mutable_interval()->set_seconds(1);

  auto* health_check = message->add_cluster_health_checks();
  health_check->set_cluster_name("anna");
  auto* lb_endpoint = health_check->add_locality_endpoints();
  for (int i = 0; i < 3; i++) {
    auto* endpoint = lb_endpoint->add_endpoints();
    auto* address = endpoint->mutable_address();
    address->mutable_socket_address()->set_address("127.0.0.1");
    address->mutable_socket_address()->set_port_value(1234 + i);
  }

  // Process message
  EXPECT_CALL(test_factory_, createClusterInfo(_)).WillOnce(Return(cluster_info_));
  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  for (int i = 0; i < 3; i++) {
    auto& host =
        hds_delegate_->hdsClusters()[0]->prioritySet().hostSetsPerPriority()[0]->hosts()[i];
    EXPECT_EQ(host->address()->ip()->port(), 1234 + i);
    EXPECT_EQ(host->healthCheckAddress()->ip()->port(), 1234 + i);
  }

  // Set custom health config port
  for (int i = 0; i < 3; i++) {
    auto* endpoint =
        message->mutable_cluster_health_checks(0)->mutable_locality_endpoints(0)->mutable_endpoints(
            i);
    endpoint->mutable_health_check_config()->set_port_value(4321 + i);
  }

  // Process updating message
  hds_delegate_friend_.processPrivateMessage(*hds_delegate_, std::move(message));

  // Check Correctness
  for (int i = 0; i < 3; i++) {
    auto& host =
        hds_delegate_->hdsClusters()[0]->prioritySet().hostSetsPerPriority()[0]->hosts()[i];
    EXPECT_EQ(host->address()->ip()->port(), 1234 + i);
    EXPECT_EQ(host->healthCheckAddress()->ip()->port(), 4321 + i);
  }
}

} // namespace Upstream
} // namespace Envoy


text:
export enum ImagesActionsTypes {
  FETCH_IMAGES = 'FETCH_IMAGES',
  FETCH_IMAGES_SUCCESS = 'FETCH_IMAGES_SUCCESS',
  FETCH_IMAGES_ERROR = 'FETCH_IMAGES_ERROR',
};

redpajama_set_name: RedPajamaGithub


text:
package de.jpaw.bonaparte.refs;

import de.jpaw.util.ApplicationException;

public class PersistenceException extends ApplicationException {
    private static final long serialVersionUID = 61705245543364726L;

    private static final int ERROR_CODE_OFFSET = 14000;                                             // offset for all codes in this class
    private static final int OFFSET = (CL_DATABASE_ERROR * CLASSIFICATION_FACTOR) + ERROR_CODE_OFFSET; // offset for all codes in this class

    static public final int RECORD_DOES_NOT_EXIST        = OFFSET + 1;
    static public final int RECORD_ALREADY_EXISTS        = OFFSET + 2;
    static public final int DUPLICATE_UNIQUE_INDEX       = OFFSET + 3;
    static public final int UNKNOWN_INDEX_TYPE           = OFFSET + 4;
    static public final int NO_TRANSACTION               = OFFSET + 5;
    static public final int READONLY                     = OFFSET + 6;
    static public final int NO_RECORD_FOR_INDEX          = (CL_PARAMETER_ERROR * CLASSIFICATION_FACTOR) + ERROR_CODE_OFFSET + 7;
    static public final int NO_PRIMARY_KEY               = OFFSET + 8;
    static public final int RECORD_DOES_NOT_EXIST_ILE    = (CL_INTERNAL_LOGIC_ERROR * CLASSIFICATION_FACTOR) + ERROR_CODE_OFFSET + 9;

    static {
        codeToDescription.put(RECORD_DOES_NOT_EXIST     , "No record for primary key found");
        codeToDescription.put(RECORD_ALREADY_EXISTS     , "Value for primary key already exists");
        codeToDescription.put(DUPLICATE_UNIQUE_INDEX    , "Value of unique index already exists");
        codeToDescription.put(UNKNOWN_INDEX_TYPE        , "Not known as a unique index");
        codeToDescription.put(NO_TRANSACTION            , "Not active transaction");
        codeToDescription.put(READONLY                  , "Entity is readonly via this API");
        codeToDescription.put(NO_RECORD_FOR_INDEX       , "No record has been found for the provided index");
        codeToDescription.put(NO_PRIMARY_KEY            , "No primary key provided for create or update operation");
        codeToDescription.put(RECORD_DOES_NOT_EXIST_ILE , "No record for primary key found, but this should not have happened");
    }

    private final long key;
    private final String entityName;
    private final String indexName;
    private final String indexValue;

    public PersistenceException(int errorCode, long key, String entityName) {
        this(errorCode, key, entityName, null, null);
    }

    public PersistenceException(int errorCode, long key, String entityName, String indexName, String indexValue) {
        super(errorCode, "Entity " + entityName
                + (key > 0L ? ", key " + key : "")
                + (indexName != null ? ", index " + indexName : "")
                + (indexValue != null ? ", index = " + indexValue : ""));
        this.key = key;
        this.entityName = entityName;
        this.indexName = indexName;
        this.indexValue = indexValue;
    }

    public long getKey() {
        return key;
    }

    public String getEntityName() {
        return entityName;
    }

    public String getIndexName() {
        return indexName;
    }

    public String getIndexValue() {
        return indexValue;
    }
}


text:
package com.ysheng.auth.frontend.test.resource;

import com.ysheng.auth.frontend.resource.ResponseBuilder;
import com.ysheng.auth.model.api.ApiList;
import com.ysheng.auth.model.api.client.Client;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * Tests for {@link com.ysheng.auth.frontend.resource.ResponseBuilder}.
 */
public class ResponseBuilderTest {

  @Test(dataProvider = "ResponseEntity")
  public void succeedsToBuild(Object entity) {
    Response response = ResponseBuilder.build(
        Response.Status.CREATED,
        entity);

    assertThat(response.getStatus(), equalTo(Response.Status.CREATED.getStatusCode()));
    assertThat(response.getEntity(), equalTo(entity));

    if (entity != null) {
      assertThat(response.getMediaType(), equalTo(MediaType.APPLICATION_JSON_TYPE));
    }
  }

  @DataProvider(name = "ResponseEntity")
  public Object[][] provideResponseEntity() {
    return new Object[][] {
        { null },
        { new Client() },
        { new ApiList<Client>() }
    };
  }
}


text:
static NSComparator const ASTCompare = ^NSComparisonResult(id a, id b) {
    return [a compare:b];
};

#pragma mark - Min

id __ASTMin_NSDictionary(NSDictionary *dict) {
    return ASTMin(dict.allValues);
}

id __ASTMin_NSDictionary_comparator(NSDictionary *dict, NSComparator comparator) {
    return ASTMin(dict.allValues, comparator);
}

id __ASTMin_NSFastEnumeration(id<NSFastEnumeration> collection) {
    return ASTMin(collection, ASTCompare);
}

id __ASTMin_NSFastEnumeration_comparator(id<NSFastEnumeration> collection, NSComparator comparator) {
    NSCParameterAssert(comparator != nil);

    return ASTReduce(collection, ^id(id a, id b) {
        return comparator(a, b) == NSOrderedAscending ? a : b;
    });
}

#pragma mark - Max

id __ASTMax_NSDictionary(NSDictionary *dict) {
    return ASTMax(dict.allValues);
}

id __ASTMax_NSDictionary_comparator(NSDictionary *dict, NSComparator comparator) {
    return ASTMax(dict.allValues, comparator);
}

id __ASTMax_NSFastEnumeration(id<NSFastEnumeration> collection) {
    return ASTMax(collection, ASTCompare);
}

id __ASTMax_NSFastEnumeration_comparator(id<NSFastEnumeration> collection, NSComparator comparator) {
    NSCParameterAssert(comparator != nil);

    return ASTReduce(collection, ^id(id a, id b) {
        return comparator(a, b) == NSOrderedDescending ? a : b;
    });
}


text:
#ifndef XTRAS_HPP_
#define XTRAS_HPP_

#include <QObject>
#include <qvariant.h>
#include <QDeclarativeListProperty>
#include <QStringList>

class Xtras: public QObject
{
	Q_OBJECT

	Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged FINAL)
	Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL)

	Q_PROPERTY(QStringList textStringList READ textStringList  WRITE setTextStringList NOTIFY textStringListChanged FINAL)
	// QVariantList to get easy access from QML to int Array
	Q_PROPERTY(QVariantList valuesList READ valuesList  WRITE setValuesList NOTIFY valuesListChanged FINAL)

public:
	Xtras(QObject *parent = 0);

	void fillFromMap(const QVariantMap& xtrasMap);
	void fillFromForeignMap(const QVariantMap& xtrasMap);
	void fillFromCacheMap(const QVariantMap& xtrasMap);

	void prepareNew();

	bool isValid();

	Q_INVOKABLE
	QVariantMap toMap();
	QVariantMap toForeignMap();
	QVariantMap toCacheMap();

	int id() const;
	void setId(int id);
	QString name() const;
	void setName(QString name);

	Q_INVOKABLE
	void addToTextStringList(const QString& stringValue);

	Q_INVOKABLE
	bool removeFromTextStringList(const QString& stringValue);

	Q_INVOKABLE
	int textCount();

	QStringList textStringList();
	void setTextStringList(const QStringList& text);

	Q_INVOKABLE
	void addToValuesList(const int& intValue);

	Q_INVOKABLE
	bool removeFromValuesList(const int& intValue);

	Q_INVOKABLE
	int valuesCount();

	// access from C++ to values
	QList<int> values();
	void setValues(QList<int> values);
	// access from QML to values (array of int)
	QVariantList valuesList();
	void setValuesList(const QVariantList& values);

	virtual ~Xtras();

	Q_SIGNALS:

	void idChanged(int id);
	void nameChanged(QString name);
	void textStringListChanged(QStringList text);
	void addedToTextStringList(QString stringValue);
	void removedFromTextStringList(QString stringValue);
	void valuesListChanged(QVariantList values);
	void addedToValuesList(int intValue);
	void removedFromValuesList(int intValue);

private:

	int mId;
	QString mName;
	QStringList mTextStringList;
	QList<int> mValues;

	Q_DISABLE_COPY (Xtras)
};
Q_DECLARE_METATYPE(Xtras*)

#endif /* XTRAS_HPP_ */


text:
package org.apache.hadoop.hbase.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.PrivateCellUtil;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.shaded.com.google.protobuf.InvalidProtocolBufferException;
import org.apache.hadoop.hbase.shaded.com.google.protobuf.UnsafeByteOperations;
import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos;
import org.apache.hadoop.hbase.util.Bytes;

/**
 * This filter is used for selecting only those keys with columns that matches
 * a particular prefix. For example, if prefix is 'an', it will pass keys will
 * columns like 'and', 'anti' but not keys with columns like 'ball', 'act'.
 */
@InterfaceAudience.Public
public class MultipleColumnPrefixFilter extends FilterBase {
  protected byte [] hint = null;
  protected TreeSet<byte []> sortedPrefixes = createTreeSet();
  private final static int MAX_LOG_PREFIXES = 5;

  public MultipleColumnPrefixFilter(final byte [][] prefixes) {
    if (prefixes != null) {
      for (int i = 0; i < prefixes.length; i++) {
        if (!sortedPrefixes.add(prefixes[i]))
          throw new IllegalArgumentException ("prefixes must be distinct");
      }
    }
  }

  public byte [][] getPrefix() {
    int count = 0;
    byte [][] temp = new byte [sortedPrefixes.size()][];
    for (byte [] prefixes : sortedPrefixes) {
      temp [count++] = prefixes;
    }
    return temp;
  }

  @Override
  public boolean filterRowKey(Cell cell) throws IOException {
    // Impl in FilterBase might do unnecessary copy for Off heap backed Cells.
    return false;
  }

  @Deprecated
  @Override
  public ReturnCode filterKeyValue(final Cell c) {
    return filterCell(c);
  }

  @Override
  public ReturnCode filterCell(final Cell c) {
    if (sortedPrefixes.isEmpty()) {
      return ReturnCode.INCLUDE;
    } else {
      return filterColumn(c);
    }
  }

  public ReturnCode filterColumn(Cell cell) {
    byte [] qualifier = CellUtil.cloneQualifier(cell);
    TreeSet<byte []> lesserOrEqualPrefixes =
      (TreeSet<byte []>) sortedPrefixes.headSet(qualifier, true);

    if (lesserOrEqualPrefixes.size() != 0) {
      byte [] largestPrefixSmallerThanQualifier = lesserOrEqualPrefixes.last();

      if (Bytes.startsWith(qualifier, largestPrefixSmallerThanQualifier)) {
        return ReturnCode.INCLUDE;
      }

      if (lesserOrEqualPrefixes.size() == sortedPrefixes.size()) {
        return ReturnCode.NEXT_ROW;
      } else {
        hint = sortedPrefixes.higher(largestPrefixSmallerThanQualifier);
        return ReturnCode.SEEK_NEXT_USING_HINT;
      }
    } else {
      hint = sortedPrefixes.first();
      return ReturnCode.SEEK_NEXT_USING_HINT;
    }
  }

  public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
    byte [][] prefixes = new byte [filterArguments.size()][];
    for (int i = 0 ; i < filterArguments.size(); i++) {
      byte [] columnPrefix = ParseFilter.removeQuotesFromByteArray(filterArguments.get(i));
      prefixes[i] = columnPrefix;
    }
    return new MultipleColumnPrefixFilter(prefixes);
  }

  /**
   * @return The filter serialized using pb
   */
  public byte [] toByteArray() {
    FilterProtos.MultipleColumnPrefixFilter.Builder builder =
      FilterProtos.MultipleColumnPrefixFilter.newBuilder();
    for (byte [] element : sortedPrefixes) {
      if (element != null) builder.addSortedPrefixes(UnsafeByteOperations.unsafeWrap(element));
    }
    return builder.build().toByteArray();
  }

  /**
   * @param pbBytes A pb serialized {@link MultipleColumnPrefixFilter} instance
   * @return An instance of {@link MultipleColumnPrefixFilter} made from bytes
   * @throws DeserializationException
   * @see #toByteArray
   */
  public static MultipleColumnPrefixFilter parseFrom(final byte [] pbBytes)
  throws DeserializationException {
    FilterProtos.MultipleColumnPrefixFilter proto;
    try {
      proto = FilterProtos.MultipleColumnPrefixFilter.parseFrom(pbBytes);
    } catch (InvalidProtocolBufferException e) {
      throw new DeserializationException(e);
    }
    int numPrefixes = proto.getSortedPrefixesCount();
    byte [][] prefixes = new byte[numPrefixes][];
    for (int i = 0; i < numPrefixes; ++i) {
      prefixes[i] = proto.getSortedPrefixes(i).toByteArray();
    }

    return new MultipleColumnPrefixFilter(prefixes);
  }

  /**
   * @param o the other filter to compare with
   * @return true if and only if the fields of the filter that are serialized
   * are equal to the corresponding fields in other.  Used for testing.
   */
  boolean areSerializedFieldsEqual(Filter o) {
    if (o == this) return true;
    if (!(o instanceof MultipleColumnPrefixFilter)) return false;

    MultipleColumnPrefixFilter other = (MultipleColumnPrefixFilter)o;
    return this.sortedPrefixes.equals(other.sortedPrefixes);
  }

  @Override
  public Cell getNextCellHint(Cell cell) {
    return PrivateCellUtil.createFirstOnRowCol(cell, hint, 0, hint.length);
  }

  public TreeSet<byte []> createTreeSet() {
    return new TreeSet<>(new Comparator<Object>() {
        @Override
          public int compare (Object o1, Object o2) {
          if (o1 == null || o2 == null)
            throw new IllegalArgumentException ("prefixes can't be null");

          byte [] b1 = (byte []) o1;
          byte [] b2 = (byte []) o2;
          return Bytes.compareTo (b1, 0, b1.length, b2, 0, b2.length);
        }
      });
  }

  @Override
  public String toString() {
    return toString(MAX_LOG_PREFIXES);
  }

  protected String toString(int maxPrefixes) {
    StringBuilder prefixes = new StringBuilder();

    int count = 0;
    for (byte[] ba : this.sortedPrefixes) {
      if (count >= maxPrefixes) {
        break;
      }
      ++count;
      prefixes.append(Bytes.toStringBinary(ba));
      if (count < this.sortedPrefixes.size() && count < maxPrefixes) {
        prefixes.append(", ");
      }
    }

    return String.format("%s (%d/%d): [%s]", this.getClass().getSimpleName(),
        count, this.sortedPrefixes.size(), prefixes.toString());
  }
}


text:
//  (C) Copyright Edward Diener 2011-2015
//  Use, modification and distribution are subject to the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt).

#if !defined(BOOST_VMD_DETAIL_SETUP_HPP)
#define BOOST_VMD_DETAIL_SETUP_HPP

#include <boost/preprocessor/config/config.hpp>

#if defined(BOOST_VMD_MSVC)
#undef BOOST_VMD_MSVC
#endif
#if defined(BOOST_VMD_MSVC_V8)
#undef BOOST_VMD_MSVC_V8
#endif
#if BOOST_PP_VARIADICS
#define BOOST_VMD_MSVC BOOST_PP_VARIADICS_MSVC
#if BOOST_VMD_MSVC && defined(_MSC_VER) && _MSC_VER == 1400
#define BOOST_VMD_MSVC_V8 1
#else
#define BOOST_VMD_MSVC_V8 0
#endif /* BOOST_VMD_MSVC  && defined(_MSC_VER) && _MSC_VER == 1400 */
#if !defined(BOOST_VMD_ASSERT_DATA)
#if defined(NDEBUG)
#define BOOST_VMD_ASSERT_DATA 0
#else
#define BOOST_VMD_ASSERT_DATA 1
#endif /* NDEBUG */
#endif /* BOOST_VMD_ASSERT_DATA */
#else
#define BOOST_VMD_MSVC 0
#define BOOST_VMD_MSVC_V8 0
#if defined(BOOST_VMD_ASSERT_DATA)
#undef BOOST_VMD_ASSERT_DATA
#endif
#define BOOST_VMD_ASSERT_DATA 0
#endif /* BOOST_PP_VARIADICS */

#endif /* BOOST_VMD_DETAIL_SETUP_HPP */


text:
<?php
/*
|--------------------|
|      SORTING       |
|--------------------|
*/

$equal_search    = array('category_active_status', 'category_visibility_status');
$default_sort_by = "category_order";

$pgdata = page_init($equal_search,$default_sort_by); // static/general.php

$page             = $pgdata['page'];
$query_per_page   = $pgdata['query_per_page'];
$sort_by          = $pgdata['sort_by'];
$first_record     = $pgdata['first_record'];
$search_parameter = $pgdata['search_parameter'];
$search_value     = $pgdata['search_value'];
$search_query     = $pgdata['search_query'];
$search           = $pgdata['search'];

$parent_id        = $_REQUEST['cid'];
$parent           = get_parent($parent_id);

$full_order  = count_category($parent['relation_level'] + 1, $parent_id, $search_query, $sort_by ,$query_per_page);
$total_query = $full_order['total_query'];
$total_page  = ceil($full_order['total_query'] / $query_per_page);

// CALL FUNCTION
$listing_order = get_categories($parent['relation_level'] + 1, $parent_id, $search_query, $sort_by, $first_record ,$query_per_page);

// HANDLING ARROW SORTING
if($_REQUEST['srt'] == "category_name DESC"){
   $arr_order_number = "";
}else if($_REQUEST['srt'] == "category_name"){
   $arr_order_number = "";
}else{
   $arr_order_number = "";
}

// STORED VALUE
echo "<input type=\"hidden\" name=\"url\" id=\"url\" class=\"hidden\" value=\"http://".$_SERVER['HTTP_HOST'].get_dirname($_SERVER['PHP_SELF'])."/child-category-view/".$_REQUEST['cid']."/".$_REQUEST['cname']."\">\n";
echo "<input type=\"hidden\" name=\"page\" id=\"page\" class=\"hidden\" value=\"".$page."\" /> \n";
echo "<input type=\"hidden\" name=\"query_per_page\" id=\"query_per_page\" class=\"hidden\" value=\"".$query_per_page."\" /> \n";
echo "<input type=\"hidden\" name=\"total_page\" id=\"total_page\" class=\"hidden\" value=\"".ceil($full_order['total_query'] / $query_per_page)."\" /> \n";
echo "<input type=\"hidden\" name=\"sort_by\" id=\"sort_by\" class=\"hidden\" value=\"".$sort_by."\" /> \n";
echo "<input type=\"hidden\" name=\"search\" id=\"search\" class=\"hidden\" value=\"".$search_parameter."-".$search_value."\" /> \n";

/* -- BUTTON RESET -- */
if(empty($search_parameter)){
   $reset = "hidden";
}else{
   $reset = "";
}

if($_POST['category-action'] == "delete"){

   if($_POST['category-option'] == "yes"){
      //echo "Deleted";
   }else if($_POST['category-option'] == "no"){
      //echo "Save";
   }

}else if($_POST['category-action'] == "save"){

   if($_POST['category-option'] == "yes"){
      //echo "save yes";
   }else if($_POST['category-option'] == "no"){
      //echo "Save no";
   }

}

if($_POST['btn_child_tagging'] == "Save Changes"){

   $conn = connDB();

   $category_name        = $_POST['category_name'];
   $category_description = $_POST['category_description'];
   $post_active_status   = $_POST['active_status'];
   $visibility_status    = $_POST['visibility_status'];
   $category_parent      = $_POST['category_parent'];
   $category_id          = $_POST['cat_id'];

   if(empty($category_id)){
      $get_order = mysql_query("SELECT * from tbl_tags ORDER BY category_order DESC",$conn);

	  if (mysql_num_rows($get_order)!=null){
         $get_order_array = mysql_fetch_array($get_order);
	     $category_order  = $get_order_array["category_order"]*1+1;
      }

	  mysql_query(" INSERT INTO tbl_tags
	                (category_name,category_order,category_active_status,category_visibility_status)
				    VALUES('$category_name','$category_order','$post_active_status','$visibility_status')",$conn);

      $get_id = mysql_query("SELECT * from tbl_tags WHERE category_name = '$category_name' ORDER BY category_id DESC",$conn);

      if (mysql_num_rows($get_id)!=null){
         $get_id_array = mysql_fetch_array($get_id);
	     $category_id  = $get_id_array["category_id"];
      }

	  $parent_array = array();
	  $get_parent   = mysql_query("SELECT * from tbl_tags_relation WHERE category_child='$category_parent'",$conn);

	  if (mysql_num_rows($get_parent)!=null){

		 for($counter=1;$counter<=mysql_num_rows($get_parent);$counter++){
	        $get_parent_array = mysql_fetch_array($get_parent);
		    $tmp_level        = $get_parent_array["relation_level"];
		    $tmp_parent       = $get_parent_array["category_parent"];
		    $parent_array[$tmp_level]=$tmp_parent;
         }

      }

	  mysql_query("INSERT INTO tbl_tags_relation(category_child,category_parent,relation_level) VALUES('$category_id','$category_parent','1')",$conn);

	  foreach($parent_array as $level => $parent){
	     $new_level = $level*1+1;
	     mysql_query("INSERT INTO tbl_tags_relation(category_child,category_parent,relation_level)VALUES('$category_id','$parent','$new_level')",$conn);

		 if ($parent=='top'){
            $category_level = $level;
         }

      }

   //}else if(!empty($category_id)){
      mysql_query("UPDATE tbl_tags SET category_level = '$category_level' WHERE category_id = '$category_id'",$conn);

	  $_SESSION['alert'] = "success";
	  $_SESSION['msg']   = "Item(s) has been successfully added.";

   }else if(!empty($category_id)){

	   $new_id          = mysql_query("SELECT MAX(category_id) AS new_id FROM tbl_tags",$conn);

	   $new_id = (int) $new_id['new_id'] + 1;
	   $update_product  = mysql_query("UPDATE tbl_product SET `product_category` = '$new_id' WHERE `product_category` = '$category_id' MAX(category_id) AS new_id FROM tbl_tag",$conn);

	   $delete_relation = mysql_query("DELETE FROM tbl_tags_relation WHERE `category_child` = '$category_id'",$conn);
	   $delete_root     = mysql_query("DELETE FROM tbl_tags WHERE `category_id` = '$category_id'",$conn);

	  /* UPDATE */

      $get_order = mysql_query("SELECT * from tbl_tags ORDER BY category_order DESC",$conn);

	  if (mysql_num_rows($get_order)!=null){
         $get_order_array = mysql_fetch_array($get_order);
	     $category_order  = $get_order_array["category_order"]*1+1;
      }

	  mysql_query(" INSERT INTO tbl_tags
	                (category_name,category_order,category_active_status,category_visibility_status)
				    VALUES('$category_name','$category_order','$post_active_status','$visibility_status')",$conn);

      $get_id = mysql_query("SELECT * from tbl_tags WHERE category_name = '$category_name' ORDER BY category_id DESC",$conn);

      if (mysql_num_rows($get_id)!=null){
         $get_id_array = mysql_fetch_array($get_id);
	     $category_id  = $get_id_array["category_id"];
      }

	  $parent_array = array();
	  $get_parent   = mysql_query("SELECT * from tbl_tags_relation WHERE category_child='$category_parent'",$conn);

	  if (mysql_num_rows($get_parent)!=null){

		 for($counter=1;$counter<=mysql_num_rows($get_parent);$counter++){
	        $get_parent_array = mysql_fetch_array($get_parent);
		    $tmp_level        = $get_parent_array["relation_level"];
		    $tmp_parent       = $get_parent_array["category_parent"];
		    $parent_array[$tmp_level]=$tmp_parent;
         }

      }

	  mysql_query("INSERT INTO tbl_tags_relation(category_child,category_parent,relation_level) VALUES('$category_id','$category_parent','1')",$conn);

	  foreach($parent_array as $level => $parent){
	     $new_level = $level*1+1;
	     mysql_query("INSERT INTO tbl_tags_relation(category_child,category_parent,relation_level)VALUES('$category_id','$parent','$new_level')",$conn);

		 if ($parent=='top'){
            $category_level = $level;
         }

      }

   //}else if(!empty($category_id)){
      mysql_query("UPDATE tbl_tags SET category_level = '$category_level' WHERE category_id = '$category_id'",$conn);

	  $_SESSION['alert'] = "success";
	  $_SESSION['msg']   = "Changes have been successfully saved.";

   }

   ?>

   <?php

}else if($_POST['btn_child_tagging'] == "Delete"){
   // DEFINED VARIABLE
   $category_id   = $_POST['cat_id'];

   // CALL FUNCTION
   $conn = connDB();
   $check_delete        = check_delete($category_id);
   $category_check_name = check_delete_get_category_name($category_id);
   $validate_delete     = getTotal($category_id);

   if($validate_delete['total_product'] > 0){
      $_SESSION['alert'] = "error";
	  $_SESSION['msg']   = "Can't delete because it contains one or more items.";
   }else{

      $get_order = mysql_query("SELECT * from tbl_tags WHERE category_id = '$category_id'",$conn);

      if (mysql_num_rows($get_order)!=null){
         $get_order_array = mysql_fetch_array($get_order);
	     $category_order  = $get_order_array["category_order"];
      }

      mysql_query("UPDATE tbl_tags SET category_order = category_order-1 WHERE category_order > '$category_order'",$conn);

      //$category_parent_redirect = $_GET["parent_category"];
      mysql_query("DELETE FROM tbl_tags WHERE category_id = '$category_id'",$conn);

      $category_relation = mysql_query("SELECT * from tbl_tags_relation WHERE category_parent = '$category_id'",$conn);

      if (mysql_num_rows($category_relation)!=null){

	     for ($counter=1;$counter<=mysql_num_rows($category_relation);$counter++){
	        $category_relation_array = mysql_fetch_array($category_relation);
		    $category_child = $category_relation_array["category_child"];

		    mysql_query("DELETE FROM tbl_tags_relation WHERE category_parent = '$category_child'",$conn);
		    mysql_query("DELETE FROM tbl_tags WHERE category_id = '$category_child'",$conn);
         }
      }

      mysql_query("DELETE FROM tbl_tags_relation WHERE category_child = '$category_id' OR category_parent = '$category_id'",$conn);

   }//END CHECK

   $_SESSION['alert'] = "success";
   $_SESSION['msg']   = "Item(s) has been successfully deleted.";

}else if($_POST['btn_child_tagging'] == "GO"){

   if($_POST['category-action'] == "delete" || $_POST['category-option'] == "yes"){

	  foreach($_POST['category_id'] as $category_id){
		 // CALL FUNCTION
		 $check_delete        = check_delete($category_id);
		 $category_check_name = check_delete_get_category_name($category_id);
		 $validate_delete     = getTotal($category_id);

		 if($validate_delete['total_product'] > 0){
	        $_SESSION['alert'] = "error";
			$_SESSION['msg']   = "Can't delete because it contains one or more items.";
		 }else{
            mysql_query("DELETE FROM tbl_tags WHERE category_id = '$category_id'",$conn);

			$_SESSION['alert'] = "success";
			$_SESSION['msg']   = "Item(s) has been successfully deleted.";
		 }

	  }

   }

}

// SHOW CATEGORY
function listCategory($level,$parent,$current_category){
   $conn = connDB();

   $get_data = mysql_query("SELECT * from tbl_tags AS cat INNER JOIN tbl_tag_relation AS cat_rel ON cat.category_id = cat_rel.category_child
	                        WHERE cat.category_level = '$level' AND cat_rel.category_parent = '$parent' ORDER BY category_order",$conn);

   if (mysql_num_rows($get_data)!=null && mysql_num_rows($get_data)!=0){

	  for ($counter=1;$counter<=mysql_num_rows($get_data);$counter++){
	     $get_data_array = mysql_fetch_array($get_data);
		 $new_level = $level*1+1;
		 $new_parent = $get_data_array["category_id"];
		 echo '<option class="option_level_'.$level.'" data-level="'.$level.'" id="option_level_'.$level.'"';
		 if ($current_category==$new_parent."'"){
			echo "selected=selected";
		 }

		 echo ' value="'.$new_parent.'">';

		 for ($i=0;$i<$level;$i++){
			echo '-- ';
		 }

		 echo $get_data_array["category_name"].'</option>';
		 listCategory($new_level,$new_parent,$current_category);
      }
   }
}

// SHOW LISTING
function showCategory($level,$parent,$current_category, $one, $two, $three, $four,$tot_query, $row){
   $conn = connDB();

   $get_data = mysql_query("SELECT
                            cat.category_id, cat.category_name, cat.category_level, cat.category_order, cat.category_active_status, cat.category_visibility_status,
							rel.relation_id, rel.category_child, rel.category_parent, rel.relation_level,
							COUNT( prod.id ) AS total_product, prod.product_name

							FROM tbl_tags AS cat LEFT JOIN tbl_product AS prod ON cat.category_id = prod.product_category
							                          INNER JOIN tbl_tags_relation AS rel ON cat.category_id = rel.category_child
							WHERE $one AND cat.category_level = '$level' AND rel.category_parent = '$parent'
							GROUP BY category_id
							ORDER BY $two
							LIMIT  $three, $four
						   ",$conn);

   if (mysql_num_rows($get_data)!=null && mysql_num_rows($get_data)!=0){
	  for ($counter=1;$counter<=mysql_num_rows($get_data);$counter++){

	     $get_data_array = mysql_fetch_array($get_data);
		 $new_level      = $level*1+1;
		 $new_parent     = $get_data_array["category_id"];

		 $cat_name       = $get_data_array['category_name'];
		 $cat_active     = $get_data_array['category_active_status'];
		 $cat_visibility = $get_data_array['category_visibility_status'];

		 echo "
";
		 echo "<input type=\"checkbox\" name=\"category_id[]\" value=\"".$new_parent."\" id=\"check_".$row."\" onmouseover=\"downCheck()\" onmouseout=\"upCheck()\" onclick=\"selectRowCheck('".$row."')\">	";
		 echo "";
		 for ($i=0;$i<$level;$i++){
			echo '-- ';
		 }
		 echo ucwords(strtolower($cat_name))."	";
		 echo "".$get_data_array['total_product']."	";
		 echo "".$cat_active."	";
		 echo "".$cat_visibility."	";
		 echo "
";

		 $new_row        = ($row * 1) + 1;

		 showCategory($new_level,$new_parent,$current_category,$one,$two,$three,$four, $tot_query, $new_row);
      }
   }
}

if(isset($_POST['btn_child_tagging'])){

   $category_id = $_POST['category_id'];

   if($_POST['category-action'] == "delete"){
      foreach($category_id as $category_id){
	     delete_category($category_id);
	  }

   }else if($_POST['category-action'] == "order"){

      $hidden_id = $_POST['hidden_category_id'];

	  foreach($hidden_id as $key=>$category_id){
	     update_order($key, $category_id);
	  }

	  $_SESSION['alert'] = 'success';
	  $_SESSION['msg']   = 'Changes has been successfully saved.';

   }

}
?>


text:
<?php
/**
 * This code has been auto-generated by the JMSDiExtraBundle.
 *
 * Manual changes to it will be lost.
 */
return function($container) {
    $instance = new \Acme\HelloBundle\Controller\HelloController();
    return $instance;
};


text:
<md-menu md-position-mode="target-right target">
  <md-button ng-click="$ctrl.openMenu($mdOpenMenu, $event)" class="md-icon-button">
    <md-icon md-font-library="material-icons">subject</md-icon>
    <md-tooltip>日志</md-tooltip>
  </md-button>
  <md-menu-content class="kd-replicationcontroller-card-logs-menu" width="6">
    <md-menu-item class="kd-menu-logs-md-menu-item">

日志

    </md-menu-item>
    <md-menu-item class="kd-menu-logs-md-menu-item" layout>

任务

        一直在运行

    </md-menu-item>
    <md-menu-item ng-repeat="pod in ::$ctrl.replicationControllerPodsList"
        class="kd-menu-logs-md-menu-item" layout>

        {{::pod.name}}

            {{::(pod.startTime | date:'d/M/yy HH:mm':'UTC')}} UTC

            没有运行

          open_in_new

        -

    </md-menu-item>
  </md-menu-content>
</md-menu>


text:
// scalastyle:off println
package org.apache.spark.examples.mllib

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
// $example on$
import org.apache.spark.mllib.linalg.Matrix
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.linalg.distributed.RowMatrix
// $example off$

object PCAOnRowMatrixExample {

  def main(args: Array[String]): Unit = {

    val conf = new SparkConf().setAppName("PCAOnRowMatrixExample")
    val sc = new SparkContext(conf)

    // $example on$
    val data = Array(
      Vectors.sparse(5, Seq((1, 1.0), (3, 7.0))),
      Vectors.dense(2.0, 0.0, 3.0, 4.0, 5.0),
      Vectors.dense(4.0, 0.0, 0.0, 6.0, 7.0))

    val rows = sc.parallelize(data)

    val mat: RowMatrix = new RowMatrix(rows)

    // Compute the top 4 principal components.
    // Principal components are stored in a local dense matrix.
    val pc: Matrix = mat.computePrincipalComponents(4)

    // Project the rows to the linear space spanned by the top 4 principal components.
    val projected: RowMatrix = mat.multiply(pc)
    // $example off$
    val collect = projected.rows.collect()
    println("Projected Row Matrix of principal component:")
    collect.foreach { vector => println(vector) }

    sc.stop()
  }
}
// scalastyle:on println


text:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MyBlog.Models
{
    public class ArticleViewModel
    {
        public int Id { get; set; }

        [Required]
        [StringLength(50)]
        public string Title { get; set; }

        [Required]
        public string Content { get; set; }

        public string AuthorId { get; set; }
    }
}


text:
#ifndef PlatformLocale_h
#define PlatformLocale_h

#include "platform/DateComponents.h"
#include "platform/Language.h"
#include "public/platform/WebLocalizedString.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/text/WTFString.h"

namespace blink {

class PLATFORM_EXPORT Locale {
    WTF_MAKE_NONCOPYABLE(Locale);
public:
    static PassOwnPtr<Locale> create(const String& localeIdentifier);
    static Locale& defaultLocale();

    String queryString(WebLocalizedString::Name);
    String queryString(WebLocalizedString::Name, const String& parameter);
    String queryString(WebLocalizedString::Name, const String& parameter1, const String& parameter2);
    String validationMessageTooLongText(unsigned valueLength, int maxLength);
    String validationMessageTooShortText(unsigned valueLength, int minLength);

    // Converts the specified number string to another number string localized
    // for this Locale locale. The input string must conform to HTML
    // floating-point numbers, and is not empty.
    String convertToLocalizedNumber(const String&);

    // Converts the specified localized number string to a number string in the
    // HTML floating-point number format. The input string is provided by a end
    // user, and might not be a number string. It's ok that the function returns
    // a string which is not conforms to the HTML floating-point number format,
    // callers of this function are responsible to check the format of the
    // resultant string.
    String convertFromLocalizedNumber(const String&);

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    // Returns localized decimal separator, e.g. "." for English, "," for French.
    String localizedDecimalSeparator();
#endif

    // Returns date format in Unicode TR35 LDML[1] containing day of month,
    // month, and year, e.g. "dd/mm/yyyy"
    // [1] LDML http://unicode.org/reports/tr35/#Date_Format_Patterns
    virtual String dateFormat() = 0;

    // Returns a year-month format in Unicode TR35 LDML.
    virtual String monthFormat() = 0;

    // Returns a year-month format using short month lanel in Unicode TR35 LDML.
    virtual String shortMonthFormat() = 0;

    // Returns time format in Unicode TR35 LDML[1] containing hour, minute, and
    // second with optional period(AM/PM), e.g. "h:mm:ss a"
    // [1] LDML http://unicode.org/reports/tr35/#Date_Format_Patterns
    virtual String timeFormat() = 0;

    // Returns time format in Unicode TR35 LDML containing hour, and minute
    // with optional period(AM/PM), e.g. "h:mm a"
    // Note: Some platforms return same value as timeFormat().
    virtual String shortTimeFormat() = 0;

    // Returns a date-time format in Unicode TR35 LDML. It should have a seconds
    // field.
    virtual String dateTimeFormatWithSeconds() = 0;

    // Returns a date-time format in Unicode TR35 LDML. It should have no seconds
    // field.
    virtual String dateTimeFormatWithoutSeconds() = 0;

    // weekFormatInLDML() returns week and year format in LDML, Unicode
    // technical standard 35, Locale Data Markup Language, e.g. "'Week' ww, yyyy"
    String weekFormatInLDML();

    // Returns a vector of string of which size is 12. The first item is a
    // localized string of Jan and the last item is a localized string of
    // Dec. These strings should be short.
    virtual const Vector<String>& shortMonthLabels() = 0;

    // Returns a vector of string of which size is 12. The first item is a
    // stand-alone localized string of January and the last item is a
    // stand-alone localized string of December. These strings should not be
    // abbreviations.
    virtual const Vector<String>& standAloneMonthLabels() = 0;

    // Stand-alone month version of shortMonthLabels.
    virtual const Vector<String>& shortStandAloneMonthLabels() = 0;

    // Returns localized period field(AM/PM) strings.
    virtual const Vector<String>& timeAMPMLabels() = 0;

    // Returns a vector of string of which size is 12. The first item is a
    // localized string of January, and the last item is a localized string of
    // December. These strings should not be abbreviations.
    virtual const Vector<String>& monthLabels() = 0;

    // Returns a vector of string of which size is 7. The first item is a
    // localized short string of Monday, and the last item is a localized
    // short string of Saturday. These strings should be short.
    virtual const Vector<String>& weekDayShortLabels() = 0;

    // The first day of a week. 0 is Sunday, and 6 is Saturday.
    virtual unsigned firstDayOfWeek() = 0;

    // Returns true if people use right-to-left writing in the locale for this
    // object.
    virtual bool isRTL() = 0;

    enum FormatType { FormatTypeUnspecified, FormatTypeShort, FormatTypeMedium };

    // Serializes the specified date into a formatted date string to
    // display to the user. If an implementation doesn't support
    // localized dates the function should return an empty string.
    // FormatType can be used to specify if you want the short format.
    String formatDateTime(const DateComponents&, FormatType = FormatTypeUnspecified);

    virtual ~Locale();

protected:
    enum {
        // 0-9 for digits.
        DecimalSeparatorIndex = 10,
        GroupSeparatorIndex = 11,
        DecimalSymbolsSize
    };

    Locale() : m_hasLocaleData(false) { }
    virtual void initializeLocaleData() = 0;
    void setLocaleData(const Vector<String, DecimalSymbolsSize>&, const String& positivePrefix, const String& positiveSuffix, const String& negativePrefix, const String& negativeSuffix);

private:
    bool detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex);
    unsigned matchedDecimalSymbolIndex(const String& input, unsigned& position);

    String m_decimalSymbols[DecimalSymbolsSize];
    String m_positivePrefix;
    String m_positiveSuffix;
    String m_negativePrefix;
    String m_negativeSuffix;
    bool m_hasLocaleData;
};

} // namespace blink
#endif