|  | @@ -0,0 +1,356 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Copyright 2020 gRPC authors.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Licensed under the Apache License, Version 2.0 (the "License");
 | 
	
		
			
				|  |  | + * you may not use this file except in compliance with the License.
 | 
	
		
			
				|  |  | + * You may obtain a copy of the License at
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + *     http://www.apache.org/licenses/LICENSE-2.0
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Unless required by applicable law or agreed to in writing, software
 | 
	
		
			
				|  |  | + * distributed under the License is distributed on an "AS IS" BASIS,
 | 
	
		
			
				|  |  | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
	
		
			
				|  |  | + * See the License for the specific language governing permissions and
 | 
	
		
			
				|  |  | + * limitations under the License.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <grpc/impl/codegen/log.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/channel.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/client_context.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/create_channel.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/server.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/server_builder.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/server_context.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/support/client_callback.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/support/message_allocator.h>
 | 
	
		
			
				|  |  | +#include <gtest/gtest.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <algorithm>
 | 
	
		
			
				|  |  | +#include <atomic>
 | 
	
		
			
				|  |  | +#include <condition_variable>
 | 
	
		
			
				|  |  | +#include <functional>
 | 
	
		
			
				|  |  | +#include <memory>
 | 
	
		
			
				|  |  | +#include <mutex>
 | 
	
		
			
				|  |  | +#include <sstream>
 | 
	
		
			
				|  |  | +#include <thread>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "src/core/lib/iomgr/iomgr.h"
 | 
	
		
			
				|  |  | +#include "src/proto/grpc/testing/echo.grpc.pb.h"
 | 
	
		
			
				|  |  | +#include "test/core/util/port.h"
 | 
	
		
			
				|  |  | +#include "test/core/util/test_config.h"
 | 
	
		
			
				|  |  | +#include "test/cpp/end2end/test_service_impl.h"
 | 
	
		
			
				|  |  | +#include "test/cpp/util/test_credentials_provider.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration
 | 
	
		
			
				|  |  | +// should be skipped based on a decision made at SetUp time. In particular, any
 | 
	
		
			
				|  |  | +// callback tests can only be run if the iomgr can run in the background or if
 | 
	
		
			
				|  |  | +// the transport is in-process.
 | 
	
		
			
				|  |  | +#define MAYBE_SKIP_TEST \
 | 
	
		
			
				|  |  | +  do {                  \
 | 
	
		
			
				|  |  | +    if (do_not_test_) { \
 | 
	
		
			
				|  |  | +      return;           \
 | 
	
		
			
				|  |  | +    }                   \
 | 
	
		
			
				|  |  | +  } while (0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace grpc {
 | 
	
		
			
				|  |  | +namespace testing {
 | 
	
		
			
				|  |  | +namespace {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +enum class Protocol { INPROC, TCP };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
 | 
	
		
			
				|  |  | +using experimental::GenericCallbackServerContext;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class TestScenario {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  TestScenario(Protocol protocol, const std::string& creds_type)
 | 
	
		
			
				|  |  | +      : protocol(protocol), credentials_type(creds_type) {}
 | 
	
		
			
				|  |  | +  void Log() const;
 | 
	
		
			
				|  |  | +  Protocol protocol;
 | 
	
		
			
				|  |  | +  const std::string credentials_type;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static std::ostream& operator<<(std::ostream& out,
 | 
	
		
			
				|  |  | +                                const TestScenario& scenario) {
 | 
	
		
			
				|  |  | +  return out << "TestScenario{protocol="
 | 
	
		
			
				|  |  | +             << (scenario.protocol == Protocol::INPROC ? "INPROC" : "TCP")
 | 
	
		
			
				|  |  | +             << "," << scenario.credentials_type << "}";
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void TestScenario::Log() const {
 | 
	
		
			
				|  |  | +  std::ostringstream out;
 | 
	
		
			
				|  |  | +  out << *this;
 | 
	
		
			
				|  |  | +  gpr_log(GPR_INFO, "%s", out.str().c_str());
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class ContextAllocatorEnd2endTestBase
 | 
	
		
			
				|  |  | +    : public ::testing::TestWithParam<TestScenario> {
 | 
	
		
			
				|  |  | + protected:
 | 
	
		
			
				|  |  | +  static void SetUpTestCase() { grpc_init(); }
 | 
	
		
			
				|  |  | +  static void TearDownTestCase() { grpc_shutdown(); }
 | 
	
		
			
				|  |  | +  ContextAllocatorEnd2endTestBase() {}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ~ContextAllocatorEnd2endTestBase() override = default;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void SetUp() override {
 | 
	
		
			
				|  |  | +    GetParam().Log();
 | 
	
		
			
				|  |  | +    if (GetParam().protocol == Protocol::TCP) {
 | 
	
		
			
				|  |  | +      if (!grpc_iomgr_run_in_background()) {
 | 
	
		
			
				|  |  | +        do_not_test_ = true;
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void CreateServer(std::unique_ptr<grpc::ContextAllocator> context_allocator) {
 | 
	
		
			
				|  |  | +    ServerBuilder builder;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    auto server_creds = GetCredentialsProvider()->GetServerCredentials(
 | 
	
		
			
				|  |  | +        GetParam().credentials_type);
 | 
	
		
			
				|  |  | +    if (GetParam().protocol == Protocol::TCP) {
 | 
	
		
			
				|  |  | +      picked_port_ = grpc_pick_unused_port_or_die();
 | 
	
		
			
				|  |  | +      server_address_ << "localhost:" << picked_port_;
 | 
	
		
			
				|  |  | +      builder.AddListeningPort(server_address_.str(), server_creds);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    builder.experimental().SetContextAllocator(std::move(context_allocator));
 | 
	
		
			
				|  |  | +    builder.RegisterService(&callback_service_);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    server_ = builder.BuildAndStart();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void DestroyServer() {
 | 
	
		
			
				|  |  | +    if (server_) {
 | 
	
		
			
				|  |  | +      server_->Shutdown();
 | 
	
		
			
				|  |  | +      server_.reset();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void ResetStub() {
 | 
	
		
			
				|  |  | +    ChannelArguments args;
 | 
	
		
			
				|  |  | +    auto channel_creds = GetCredentialsProvider()->GetChannelCredentials(
 | 
	
		
			
				|  |  | +        GetParam().credentials_type, &args);
 | 
	
		
			
				|  |  | +    switch (GetParam().protocol) {
 | 
	
		
			
				|  |  | +      case Protocol::TCP:
 | 
	
		
			
				|  |  | +        channel_ = ::grpc::CreateCustomChannel(server_address_.str(),
 | 
	
		
			
				|  |  | +                                               channel_creds, args);
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      case Protocol::INPROC:
 | 
	
		
			
				|  |  | +        channel_ = server_->InProcessChannel(args);
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      default:
 | 
	
		
			
				|  |  | +        assert(false);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    stub_ = EchoTestService::NewStub(channel_);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void TearDown() override {
 | 
	
		
			
				|  |  | +    DestroyServer();
 | 
	
		
			
				|  |  | +    if (picked_port_ > 0) {
 | 
	
		
			
				|  |  | +      grpc_recycle_unused_port(picked_port_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  void SendRpcs(int num_rpcs) {
 | 
	
		
			
				|  |  | +    std::string test_string("");
 | 
	
		
			
				|  |  | +    for (int i = 0; i < num_rpcs; i++) {
 | 
	
		
			
				|  |  | +      EchoRequest request;
 | 
	
		
			
				|  |  | +      EchoResponse response;
 | 
	
		
			
				|  |  | +      ClientContext cli_ctx;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      test_string += std::string(1024, 'x');
 | 
	
		
			
				|  |  | +      request.set_message(test_string);
 | 
	
		
			
				|  |  | +      std::string val;
 | 
	
		
			
				|  |  | +      cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      std::mutex mu;
 | 
	
		
			
				|  |  | +      std::condition_variable cv;
 | 
	
		
			
				|  |  | +      bool done = false;
 | 
	
		
			
				|  |  | +      stub_->experimental_async()->Echo(
 | 
	
		
			
				|  |  | +          &cli_ctx, &request, &response,
 | 
	
		
			
				|  |  | +          [&request, &response, &done, &mu, &cv, val](Status s) {
 | 
	
		
			
				|  |  | +            GPR_ASSERT(s.ok());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            EXPECT_EQ(request.message(), response.message());
 | 
	
		
			
				|  |  | +            std::lock_guard<std::mutex> l(mu);
 | 
	
		
			
				|  |  | +            done = true;
 | 
	
		
			
				|  |  | +            cv.notify_one();
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  | +      std::unique_lock<std::mutex> l(mu);
 | 
	
		
			
				|  |  | +      while (!done) {
 | 
	
		
			
				|  |  | +        cv.wait(l);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  bool do_not_test_{false};
 | 
	
		
			
				|  |  | +  int picked_port_{0};
 | 
	
		
			
				|  |  | +  std::shared_ptr<Channel> channel_;
 | 
	
		
			
				|  |  | +  std::unique_ptr<EchoTestService::Stub> stub_;
 | 
	
		
			
				|  |  | +  CallbackTestServiceImpl callback_service_;
 | 
	
		
			
				|  |  | +  std::unique_ptr<Server> server_;
 | 
	
		
			
				|  |  | +  std::ostringstream server_address_;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class DefaultContextAllocatorTest : public ContextAllocatorEnd2endTestBase {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +TEST_P(DefaultContextAllocatorTest, SimpleRpc) {
 | 
	
		
			
				|  |  | +  MAYBE_SKIP_TEST;
 | 
	
		
			
				|  |  | +  const int kRpcCount = 10;
 | 
	
		
			
				|  |  | +  CreateServer(nullptr);
 | 
	
		
			
				|  |  | +  ResetStub();
 | 
	
		
			
				|  |  | +  SendRpcs(kRpcCount);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class NullContextAllocatorTest : public ContextAllocatorEnd2endTestBase {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  class NullAllocator : public grpc::ContextAllocator {
 | 
	
		
			
				|  |  | +   public:
 | 
	
		
			
				|  |  | +    NullAllocator(std::atomic<int>* allocation_count,
 | 
	
		
			
				|  |  | +                  std::atomic<int>* deallocation_count)
 | 
	
		
			
				|  |  | +        : allocation_count_(allocation_count),
 | 
	
		
			
				|  |  | +          deallocation_count_(deallocation_count) {}
 | 
	
		
			
				|  |  | +    grpc::CallbackServerContext* NewCallbackServerContext() override {
 | 
	
		
			
				|  |  | +      allocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      return nullptr;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    GenericCallbackServerContext* NewGenericCallbackServerContext() override {
 | 
	
		
			
				|  |  | +      allocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      return nullptr;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void Release(
 | 
	
		
			
				|  |  | +        grpc::CallbackServerContext* callback_server_context) override {
 | 
	
		
			
				|  |  | +      deallocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void Release(GenericCallbackServerContext* generic_callback_server_context)
 | 
	
		
			
				|  |  | +        override {
 | 
	
		
			
				|  |  | +      deallocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    std::atomic<int>* allocation_count_;
 | 
	
		
			
				|  |  | +    std::atomic<int>* deallocation_count_;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +TEST_P(NullContextAllocatorTest, UnaryRpc) {
 | 
	
		
			
				|  |  | +  MAYBE_SKIP_TEST;
 | 
	
		
			
				|  |  | +  const int kRpcCount = 10;
 | 
	
		
			
				|  |  | +  std::atomic<int> allocation_count{0};
 | 
	
		
			
				|  |  | +  std::atomic<int> deallocation_count{0};
 | 
	
		
			
				|  |  | +  std::unique_ptr<NullAllocator> allocator(
 | 
	
		
			
				|  |  | +      new NullAllocator(&allocation_count, &deallocation_count));
 | 
	
		
			
				|  |  | +  CreateServer(std::move(allocator));
 | 
	
		
			
				|  |  | +  ResetStub();
 | 
	
		
			
				|  |  | +  SendRpcs(kRpcCount);
 | 
	
		
			
				|  |  | +  // messages_deallocaton_count is updated in Release after server side
 | 
	
		
			
				|  |  | +  // OnDone.
 | 
	
		
			
				|  |  | +  DestroyServer();
 | 
	
		
			
				|  |  | +  EXPECT_EQ(kRpcCount, allocation_count);
 | 
	
		
			
				|  |  | +  EXPECT_EQ(kRpcCount, deallocation_count);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class SimpleContextAllocatorTest : public ContextAllocatorEnd2endTestBase {
 | 
	
		
			
				|  |  | + public:
 | 
	
		
			
				|  |  | +  class SimpleAllocator : public grpc::ContextAllocator {
 | 
	
		
			
				|  |  | +   public:
 | 
	
		
			
				|  |  | +    SimpleAllocator(std::atomic<int>* allocation_count,
 | 
	
		
			
				|  |  | +                    std::atomic<int>* deallocation_count)
 | 
	
		
			
				|  |  | +        : allocation_count_(allocation_count),
 | 
	
		
			
				|  |  | +          deallocation_count_(deallocation_count) {}
 | 
	
		
			
				|  |  | +    grpc::CallbackServerContext* NewCallbackServerContext() override {
 | 
	
		
			
				|  |  | +      allocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      return new grpc::CallbackServerContext();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    GenericCallbackServerContext* NewGenericCallbackServerContext() override {
 | 
	
		
			
				|  |  | +      allocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      return new GenericCallbackServerContext();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void Release(
 | 
	
		
			
				|  |  | +        grpc::CallbackServerContext* callback_server_context) override {
 | 
	
		
			
				|  |  | +      deallocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      delete callback_server_context;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void Release(GenericCallbackServerContext* generic_callback_server_context)
 | 
	
		
			
				|  |  | +        override {
 | 
	
		
			
				|  |  | +      deallocation_count_->fetch_add(1, std::memory_order_relaxed);
 | 
	
		
			
				|  |  | +      delete generic_callback_server_context;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    std::atomic<int>* allocation_count_;
 | 
	
		
			
				|  |  | +    std::atomic<int>* deallocation_count_;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +TEST_P(SimpleContextAllocatorTest, UnaryRpc) {
 | 
	
		
			
				|  |  | +  MAYBE_SKIP_TEST;
 | 
	
		
			
				|  |  | +  const int kRpcCount = 10;
 | 
	
		
			
				|  |  | +  std::atomic<int> allocation_count{0};
 | 
	
		
			
				|  |  | +  std::atomic<int> deallocation_count{0};
 | 
	
		
			
				|  |  | +  std::unique_ptr<SimpleAllocator> allocator(
 | 
	
		
			
				|  |  | +      new SimpleAllocator(&allocation_count, &deallocation_count));
 | 
	
		
			
				|  |  | +  CreateServer(std::move(allocator));
 | 
	
		
			
				|  |  | +  ResetStub();
 | 
	
		
			
				|  |  | +  SendRpcs(kRpcCount);
 | 
	
		
			
				|  |  | +  // messages_deallocaton_count is updated in Release after server side
 | 
	
		
			
				|  |  | +  // OnDone.
 | 
	
		
			
				|  |  | +  DestroyServer();
 | 
	
		
			
				|  |  | +  EXPECT_EQ(kRpcCount, allocation_count);
 | 
	
		
			
				|  |  | +  EXPECT_EQ(kRpcCount, deallocation_count);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +std::vector<TestScenario> CreateTestScenarios(bool test_insecure) {
 | 
	
		
			
				|  |  | +  std::vector<TestScenario> scenarios;
 | 
	
		
			
				|  |  | +  std::vector<std::string> credentials_types{
 | 
	
		
			
				|  |  | +      GetCredentialsProvider()->GetSecureCredentialsTypeList()};
 | 
	
		
			
				|  |  | +  auto insec_ok = [] {
 | 
	
		
			
				|  |  | +    // Only allow insecure credentials type when it is registered with the
 | 
	
		
			
				|  |  | +    // provider. User may create providers that do not have insecure.
 | 
	
		
			
				|  |  | +    return GetCredentialsProvider()->GetChannelCredentials(
 | 
	
		
			
				|  |  | +               kInsecureCredentialsType, nullptr) != nullptr;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  if (test_insecure && insec_ok()) {
 | 
	
		
			
				|  |  | +    credentials_types.push_back(kInsecureCredentialsType);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  GPR_ASSERT(!credentials_types.empty());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  Protocol parr[]{Protocol::INPROC, Protocol::TCP};
 | 
	
		
			
				|  |  | +  for (Protocol p : parr) {
 | 
	
		
			
				|  |  | +    for (const auto& cred : credentials_types) {
 | 
	
		
			
				|  |  | +      if (p == Protocol::INPROC &&
 | 
	
		
			
				|  |  | +          (cred != kInsecureCredentialsType || !insec_ok())) {
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      scenarios.emplace_back(p, cred);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return scenarios;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// TODO(ddyihai): adding client streaming/server streaming/bidi streaming
 | 
	
		
			
				|  |  | +// test.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +INSTANTIATE_TEST_SUITE_P(DefaultContextAllocatorTest,
 | 
	
		
			
				|  |  | +                         DefaultContextAllocatorTest,
 | 
	
		
			
				|  |  | +                         ::testing::ValuesIn(CreateTestScenarios(true)));
 | 
	
		
			
				|  |  | +INSTANTIATE_TEST_SUITE_P(NullContextAllocatorTest, NullContextAllocatorTest,
 | 
	
		
			
				|  |  | +                         ::testing::ValuesIn(CreateTestScenarios(true)));
 | 
	
		
			
				|  |  | +INSTANTIATE_TEST_SUITE_P(SimpleContextAllocatorTest, SimpleContextAllocatorTest,
 | 
	
		
			
				|  |  | +                         ::testing::ValuesIn(CreateTestScenarios(true)));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}  // namespace
 | 
	
		
			
				|  |  | +}  // namespace testing
 | 
	
		
			
				|  |  | +}  // namespace grpc
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int main(int argc, char** argv) {
 | 
	
		
			
				|  |  | +  grpc::testing::TestEnvironment env(argc, argv);
 | 
	
		
			
				|  |  | +  ::testing::InitGoogleTest(&argc, argv);
 | 
	
		
			
				|  |  | +  int ret = RUN_ALL_TESTS();
 | 
	
		
			
				|  |  | +  return ret;
 | 
	
		
			
				|  |  | +}
 |