text: /*
   *
   * Copyright 2015, Google Inc.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are
   * met:
   *
   *     * Redistributions of source code must retain the above copyright
   * notice, this list of conditions and the following disclaimer.
   *     * Redistributions in binary form must reproduce the above
   * copyright notice, this list of conditions and the following disclaimer
   * in the documentation and/or other materials provided with the
   * distribution.
   *     * Neither the name of Google Inc. nor the names of its
   * contributors may be used to endorse or promote products derived from
   * this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   */
  
  #include "test/core/end2end/end2end_tests.h"
  
  #include <stdio.h>
  #include <string.h>
  #include <unistd.h>
  
  #include <grpc/byte_buffer.h>
  #include <grpc/support/alloc.h>
  #include <grpc/support/log.h>
  #include <grpc/support/time.h>
  #include <grpc/support/useful.h>
  #include "test/core/end2end/cq_verifier.h"
  
  enum { TIMEOUT = 200000 };
  
  static void *tag(gpr_intptr t) { return (void *)t; }
  
  static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
                                              const char *test_name,
                                              grpc_channel_args *client_args,
                                              grpc_channel_args *server_args) {
    grpc_end2end_test_fixture f;
    gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
    f = config.create_fixture(client_args, server_args);
    config.init_client(&f, client_args);
    config.init_server(&f, server_args);
    return f;
  }
  
  static gpr_timespec n_seconds_time(int n) {
    return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
  }
  
  static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
  
  static void drain_cq(grpc_completion_queue *cq) {
    grpc_event *ev;
    grpc_completion_type type;
    do {
      ev = grpc_completion_queue_next(cq, five_seconds_time());
      GPR_ASSERT(ev);
      type = ev->type;
      grpc_event_finish(ev);
    } while (type != GRPC_QUEUE_SHUTDOWN);
  }
  
  static void shutdown_server(grpc_end2end_test_fixture *f) {
    if (!f->server) return;
    /* don't shutdown, just destroy, to tickle this code edge */
    grpc_server_destroy(f->server);
    f->server = NULL;
  }
  
  static void shutdown_client(grpc_end2end_test_fixture *f) {
    if (!f->client) return;
    grpc_channel_destroy(f->client);
    f->client = NULL;
  }
  
  static void end_test(grpc_end2end_test_fixture *f) {
    shutdown_server(f);
    shutdown_client(f);
  
    grpc_completion_queue_shutdown(f->server_cq);
    drain_cq(f->server_cq);
    grpc_completion_queue_destroy(f->server_cq);
    grpc_completion_queue_shutdown(f->client_cq);
    drain_cq(f->client_cq);
    grpc_completion_queue_destroy(f->client_cq);
  }
  
  static void test_early_server_shutdown_finishes_tags(
      grpc_end2end_test_config config) {
    grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
    cq_verifier *v_server = cq_verifier_create(f.server_cq);
    grpc_call *s = (void *)1;
  
    /* upon shutdown, the server should finish all requested calls indicating
       no new call */
    grpc_server_request_call_old(f.server, tag(1000));
    grpc_server_shutdown(f.server);
    cq_expect_server_rpc_new(v_server, &s, tag(1000), NULL, NULL, gpr_inf_past,
                             NULL);
    cq_verify(v_server);
    GPR_ASSERT(s == NULL);
  
    end_test(&f);
    config.tear_down_data(&f);
    cq_verifier_destroy(v_server);
  }
  
  void grpc_end2end_tests(grpc_end2end_test_config config) {
    test_early_server_shutdown_finishes_tags(config);
  }
  