Beispiel #1
0
static void test_add_sub(void) {
    int i;
    int j;
    int k;
    /* Basic addition and subtraction. */
    for (i = -100; i <= 100; i++) {
        for (j = -100; j <= 100; j++) {
            for (k = 1; k <= 10000000; k *= 10) {
                int sum = i + j;
                int diff = i - j;
                gpr_timespec it = gpr_time_from_micros(i * k, GPR_TIMESPAN);
                gpr_timespec jt = gpr_time_from_micros(j * k, GPR_TIMESPAN);
                gpr_timespec sumt = gpr_time_add(it, jt);
                gpr_timespec difft = gpr_time_sub(it, jt);
                if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) !=
                        0) {
                    fprintf(stderr, "i %d  j %d  sum %d    sumt ", i, j, sum);
                    ts_to_s(sumt, &to_fp, stderr);
                    fprintf(stderr, "\n");
                    GPR_ASSERT(0);
                }
                if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) !=
                        0) {
                    fprintf(stderr, "i %d  j %d  diff %d    diff ", i, j, diff);
                    ts_to_s(sumt, &to_fp, stderr);
                    fprintf(stderr, "\n");
                    GPR_ASSERT(0);
                }
            }
        }
    }
}
Beispiel #2
0
static void test_values(void) {
    int i;

    gpr_timespec x = gpr_time_0(GPR_CLOCK_REALTIME);
    GPR_ASSERT(x.tv_sec == 0 && x.tv_nsec == 0);

    x = gpr_inf_future(GPR_CLOCK_REALTIME);
    fprintf(stderr, "far future ");
    i_to_s(x.tv_sec, 16, 16, &to_fp, stderr);
    fprintf(stderr, "\n");
    GPR_ASSERT(x.tv_sec == INT64_MAX);
    fprintf(stderr, "far future ");
    ts_to_s(x, &to_fp, stderr);
    fprintf(stderr, "\n");

    x = gpr_inf_past(GPR_CLOCK_REALTIME);
    fprintf(stderr, "far past   ");
    i_to_s(x.tv_sec, 16, 16, &to_fp, stderr);
    fprintf(stderr, "\n");
    GPR_ASSERT(x.tv_sec == INT64_MIN);
    fprintf(stderr, "far past   ");
    ts_to_s(x, &to_fp, stderr);
    fprintf(stderr, "\n");

    for (i = 1; i != 1000 * 1000 * 1000; i *= 10) {
        x = gpr_time_from_micros(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec == i / GPR_US_PER_SEC &&
                   x.tv_nsec == (i % GPR_US_PER_SEC) * GPR_NS_PER_US);
        x = gpr_time_from_nanos(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec == i / GPR_NS_PER_SEC &&
                   x.tv_nsec == (i % GPR_NS_PER_SEC));
        x = gpr_time_from_millis(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec == i / GPR_MS_PER_SEC &&
                   x.tv_nsec == (i % GPR_MS_PER_SEC) * GPR_NS_PER_MS);
    }

    /* Test possible overflow in conversion of -ve values. */
    x = gpr_time_from_micros(-(LONG_MAX - 999997), GPR_TIMESPAN);
    GPR_ASSERT(x.tv_sec < 0);
    GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);

    x = gpr_time_from_nanos(-(LONG_MAX - 999999997), GPR_TIMESPAN);
    GPR_ASSERT(x.tv_sec < 0);
    GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);

    x = gpr_time_from_millis(-(LONG_MAX - 997), GPR_TIMESPAN);
    GPR_ASSERT(x.tv_sec < 0);
    GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);

    /* Test general -ve values. */
    for (i = -1; i > -1000 * 1000 * 1000; i *= 7) {
        x = gpr_time_from_micros(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec * GPR_US_PER_SEC + x.tv_nsec / GPR_NS_PER_US == i);
        x = gpr_time_from_nanos(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec * GPR_NS_PER_SEC + x.tv_nsec == i);
        x = gpr_time_from_millis(i, GPR_TIMESPAN);
        GPR_ASSERT(x.tv_sec * GPR_MS_PER_SEC + x.tv_nsec / GPR_NS_PER_MS == i);
    }
}
Beispiel #3
0
void test_encoding(void) {
    LOG_TEST();
    assert_encodes_as(gpr_time_from_micros(-1), "1n");
    assert_encodes_as(gpr_time_from_seconds(-10), "1n");
    assert_encodes_as(gpr_time_from_nanos(10), "10n");
    assert_encodes_as(gpr_time_from_nanos(999999999), "1S");
    assert_encodes_as(gpr_time_from_micros(1), "1u");
    assert_encodes_as(gpr_time_from_micros(10), "10u");
    assert_encodes_as(gpr_time_from_micros(100), "100u");
    assert_encodes_as(gpr_time_from_micros(890), "890u");
    assert_encodes_as(gpr_time_from_micros(900), "900u");
    assert_encodes_as(gpr_time_from_micros(901), "901u");
    assert_encodes_as(gpr_time_from_millis(1), "1m");
    assert_encodes_as(gpr_time_from_millis(2), "2m");
    assert_encodes_as(gpr_time_from_micros(10001), "10100u");
    assert_encodes_as(gpr_time_from_micros(999999), "1S");
    assert_encodes_as(gpr_time_from_millis(1000), "1S");
    assert_encodes_as(gpr_time_from_millis(2000), "2S");
    assert_encodes_as(gpr_time_from_millis(2500), "2500m");
    assert_encodes_as(gpr_time_from_millis(59900), "59900m");
    assert_encodes_as(gpr_time_from_seconds(50), "50S");
    assert_encodes_as(gpr_time_from_seconds(59), "59S");
    assert_encodes_as(gpr_time_from_seconds(60), "1M");
    assert_encodes_as(gpr_time_from_seconds(80), "80S");
    assert_encodes_as(gpr_time_from_seconds(90), "90S");
    assert_encodes_as(gpr_time_from_minutes(2), "2M");
    assert_encodes_as(gpr_time_from_minutes(20), "20M");
    assert_encodes_as(gpr_time_from_hours(1), "1H");
    assert_encodes_as(gpr_time_from_hours(10), "10H");
    assert_encodes_as(gpr_time_from_seconds(1000000000), "1000000000S");
}
void test_encoding(void) {
  LOG_TEST("test_encoding");
  assert_encodes_as(gpr_time_from_micros(-1, GPR_TIMESPAN), "1n");
  assert_encodes_as(gpr_time_from_seconds(-10, GPR_TIMESPAN), "1n");
  assert_encodes_as(gpr_time_from_nanos(10, GPR_TIMESPAN), "10n");
  assert_encodes_as(gpr_time_from_nanos(999999999, GPR_TIMESPAN), "1S");
  assert_encodes_as(gpr_time_from_micros(1, GPR_TIMESPAN), "1u");
  assert_encodes_as(gpr_time_from_micros(10, GPR_TIMESPAN), "10u");
  assert_encodes_as(gpr_time_from_micros(100, GPR_TIMESPAN), "100u");
  assert_encodes_as(gpr_time_from_micros(890, GPR_TIMESPAN), "890u");
  assert_encodes_as(gpr_time_from_micros(900, GPR_TIMESPAN), "900u");
  assert_encodes_as(gpr_time_from_micros(901, GPR_TIMESPAN), "901u");
  assert_encodes_as(gpr_time_from_millis(1, GPR_TIMESPAN), "1m");
  assert_encodes_as(gpr_time_from_millis(2, GPR_TIMESPAN), "2m");
  assert_encodes_as(gpr_time_from_micros(10001, GPR_TIMESPAN), "10100u");
  assert_encodes_as(gpr_time_from_micros(999999, GPR_TIMESPAN), "1S");
  assert_encodes_as(gpr_time_from_millis(1000, GPR_TIMESPAN), "1S");
  assert_encodes_as(gpr_time_from_millis(2000, GPR_TIMESPAN), "2S");
  assert_encodes_as(gpr_time_from_millis(2500, GPR_TIMESPAN), "2500m");
  assert_encodes_as(gpr_time_from_millis(59900, GPR_TIMESPAN), "59900m");
  assert_encodes_as(gpr_time_from_seconds(50, GPR_TIMESPAN), "50S");
  assert_encodes_as(gpr_time_from_seconds(59, GPR_TIMESPAN), "59S");
  assert_encodes_as(gpr_time_from_seconds(60, GPR_TIMESPAN), "1M");
  assert_encodes_as(gpr_time_from_seconds(80, GPR_TIMESPAN), "80S");
  assert_encodes_as(gpr_time_from_seconds(90, GPR_TIMESPAN), "90S");
  assert_encodes_as(gpr_time_from_minutes(2, GPR_TIMESPAN), "2M");
  assert_encodes_as(gpr_time_from_minutes(20, GPR_TIMESPAN), "20M");
  assert_encodes_as(gpr_time_from_hours(1, GPR_TIMESPAN), "1H");
  assert_encodes_as(gpr_time_from_hours(10, GPR_TIMESPAN), "10H");
  assert_encodes_as(gpr_time_from_seconds(1000000000, GPR_TIMESPAN),
                    "1000000000S");
}
Beispiel #5
0
static void test_overflow(void) {
    /* overflow */
    gpr_timespec x = gpr_time_from_micros(1, GPR_TIMESPAN);
    do {
        x = gpr_time_add(x, x);
    } while (gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) < 0);
    GPR_ASSERT(gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) == 0);
    x = gpr_time_from_micros(-1, GPR_TIMESPAN);
    do {
        x = gpr_time_add(x, x);
    } while (gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) > 0);
    GPR_ASSERT(gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) == 0);
}
Beispiel #6
0
static void test_sticky_infinities(void) {
    int i;
    int j;
    int k;
    gpr_timespec infinity[2];
    gpr_timespec addend[3];
    infinity[0] = gpr_inf_future(GPR_TIMESPAN);
    infinity[1] = gpr_inf_past(GPR_TIMESPAN);
    addend[0] = gpr_inf_future(GPR_TIMESPAN);
    addend[1] = gpr_inf_past(GPR_TIMESPAN);
    addend[2] = gpr_time_0(GPR_TIMESPAN);

    /* Infinities are sticky */
    for (i = 0; i != sizeof(infinity) / sizeof(infinity[0]); i++) {
        for (j = 0; j != sizeof(addend) / sizeof(addend[0]); j++) {
            gpr_timespec x = gpr_time_add(infinity[i], addend[j]);
            GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
            x = gpr_time_sub(infinity[i], addend[j]);
            GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
        }
        for (k = -200; k <= 200; k++) {
            gpr_timespec y = gpr_time_from_micros(k * 100000, GPR_TIMESPAN);
            gpr_timespec x = gpr_time_add(infinity[i], y);
            GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
            x = gpr_time_sub(infinity[i], y);
            GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
        }
    }
}
/* Shuts down and drains the completion queue if necessary.
 *
 * This is done when the ruby completion queue object is about to be GCed.
 */
static void grpc_rb_completion_queue_shutdown_drain(grpc_completion_queue *cq) {
  next_call_stack next_call;
  grpc_completion_type type;
  int drained = 0;
  MEMZERO(&next_call, next_call_stack, 1);

  grpc_completion_queue_shutdown(cq);
  next_call.cq = cq;
  next_call.event.type = GRPC_QUEUE_TIMEOUT;
  /* TODO: the timeout should be a module level constant that defaults
   * to gpr_inf_future(GPR_CLOCK_REALTIME).
   *
   * - at the moment this does not work, it stalls.  Using a small timeout like
   *   this one works, and leads to fast test run times; a longer timeout was
   *   causing unnecessary delays in the test runs.
   *
   * - investigate further, this is probably another example of C-level cleanup
   * not working consistently in all cases.
   */
  next_call.timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                   gpr_time_from_micros(5e3, GPR_TIMESPAN));
  do {
    rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
                               (void *)&next_call, NULL, NULL);
    type = next_call.event.type;
    if (type == GRPC_QUEUE_TIMEOUT) break;
    if (type != GRPC_QUEUE_SHUTDOWN) {
      ++drained;
      rb_warning("completion queue shutdown: %d undrained events", drained);
    }
  } while (type != GRPC_QUEUE_SHUTDOWN);
}
Beispiel #8
0
// Reads and verifies the specified number of records. Reader can also be
// stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec'
// between read iterations.
static void reader_thread(void* arg) {
  reader_thread_args* args = (reader_thread_args*)arg;
  if (VERBOSE) {
    printf("   Reader starting\n");
  }
  gpr_timespec interval = gpr_time_from_micros(
      args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN);
  gpr_mu_lock(args->mu);
  int records_read = 0;
  int num_iterations = 0;
  int counter = 0;
  while (!args->stop_flag && records_read < args->total_records) {
    gpr_cv_wait(&args->stop, args->mu, interval);
    if (!args->stop_flag) {
      records_read += perform_read_iteration(args->record_size);
      GPR_ASSERT(records_read <= args->total_records);
      if (VERBOSE && (counter++ == 100000)) {
        printf("   Reader: %d out of %d read\n", records_read,
               args->total_records);
        counter = 0;
      }
      ++num_iterations;
    }
  }
  // Done
  args->running = 0;
  gpr_cv_signal(args->done);
  if (VERBOSE) {
    printf("   Reader: records: %d, iterations: %d\n", records_read,
           num_iterations);
  }
  gpr_mu_unlock(args->mu);
}
Beispiel #9
0
/* Test several threads running (*body)(struct test *m) for increasing settings
   of m->iterations, until about timeout_s to 2*timeout_s seconds have elapsed.
   If extra!=NULL, run (*extra)(m) in an additional thread.  */
static void test(const char *name, void (*body)(void *m),
                 void (*extra)(void *m), int timeout_s) {
  gpr_int64 iterations = 1024;
  struct test *m;
  gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
  gpr_timespec time_taken;
  gpr_timespec deadline = gpr_time_add(
      start, gpr_time_from_micros(timeout_s * 1000000, GPR_TIMESPAN));
  fprintf(stderr, "%s:", name);
  while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
    iterations <<= 1;
    fprintf(stderr, " %ld", (long)iterations);
    m = test_new(10, iterations);
    if (extra != NULL) {
      gpr_thd_id id;
      GPR_ASSERT(gpr_thd_new(&id, extra, m, NULL));
      m->done++; /* one more thread to wait for */
    }
    test_create_threads(m, body);
    test_wait(m);
    if (m->counter != m->threads * m->iterations) {
      fprintf(stderr, "counter %ld  threads %d  iterations %ld\n",
              (long)m->counter, m->threads, (long)m->iterations);
      GPR_ASSERT(0);
    }
    test_destroy(m);
  }
  time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start);
  fprintf(stderr, " done %ld.%09d s\n", (long)time_taken.tv_sec,
          (int)time_taken.tv_nsec);
}
Beispiel #10
0
/* Reads and verifies the specified number of records. Reader can also be
   stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec'
   between read iterations. */
static void reader_thread(void* arg) {
  gpr_int32 records_read = 0;
  reader_thread_args* args = (reader_thread_args*)arg;
  gpr_int32 num_iterations = 0;
  gpr_timespec interval;
  int counter = 0;
  printf("   Reader starting\n");
  interval = gpr_time_from_micros(args->read_iteration_interval_in_msec * 1000);
  gpr_mu_lock(args->mu);
  while (!args->stop_flag && records_read < args->total_records) {
    gpr_cv_wait(&args->stop, args->mu, interval);
    if (!args->stop_flag) {
      records_read += perform_read_iteration(args->record_size);
      GPR_ASSERT(records_read <= args->total_records);
      if (counter++ == 100000) {
        printf("   Reader: %d out of %d read\n", records_read,
               args->total_records);
        counter = 0;
      }
      ++num_iterations;
    }
  }
  /* Done */
  args->running = 0;
  gpr_cv_broadcast(args->done);
  printf("   Reader: records: %d, iterations: %d\n", records_read,
         num_iterations);
  gpr_mu_unlock(args->mu);
}
Beispiel #11
0
void grpc_client_setup_create_and_attach(
    grpc_channel_stack *newly_minted_channel, const grpc_channel_args *args,
    grpc_mdctx *mdctx,
    void (*initiate)(void *user_data, grpc_client_setup_request *request),
    void (*done)(void *user_data), void *user_data) {
  grpc_client_setup *s = gpr_malloc(sizeof(grpc_client_setup));

  s->base.vtable = &setup_vtable;
  gpr_mu_init(&s->mu);
  gpr_cv_init(&s->cv);
  s->refs = 1;
  s->mdctx = mdctx;
  s->initiate = initiate;
  s->done = done;
  s->user_data = user_data;
  s->active_request = NULL;
  s->args = grpc_channel_args_copy(args);
  s->current_backoff_interval = gpr_time_from_micros(1000000);
  s->in_alarm = 0;
  s->in_cb = 0;
  s->cancelled = 0;
  grpc_pollset_set_init(&s->interested_parties);

  grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base);
}
Beispiel #12
0
gpr_timespec tunnel_get_shutdown_timeout(grpc_tunnel* tunnel) {
  int timeout_ms = grpc_channel_arg_get_int_value(
      tunnel->tunnel_args, GRPC_ARG_TUNNEL_SHUTDOWN_TIMEOUT_MS,
      TUNNEL_DEFAULT_SHUTDOWN_TIMEOUT_MS);
  return gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                      gpr_time_from_micros((int64_t)(1e3 * (timeout_ms)),
                                           GPR_TIMESPAN));
}
Beispiel #13
0
void bad_ssl_run(grpc_server *server) {
  int shutdown_started = 0;
  int shutdown_finished = 0;
  grpc_event ev;
  grpc_call_error error;
  grpc_call *s = NULL;
  grpc_call_details call_details;
  grpc_metadata_array request_metadata_recv;
  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);

  grpc_call_details_init(&call_details);
  grpc_metadata_array_init(&request_metadata_recv);

  grpc_server_register_completion_queue(server, cq, NULL);
  grpc_server_start(server);

  error = grpc_server_request_call(server, &s, &call_details,
                                   &request_metadata_recv, cq, cq, (void *)1);
  GPR_ASSERT(GRPC_CALL_OK == error);

  signal(SIGINT, sigint_handler);
  while (!shutdown_finished) {
    if (got_sigint && !shutdown_started) {
      gpr_log(GPR_INFO, "Shutting down due to SIGINT");
      grpc_server_shutdown_and_notify(server, cq, NULL);
      GPR_ASSERT(grpc_completion_queue_pluck(
                     cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
                     .type == GRPC_OP_COMPLETE);
      grpc_completion_queue_shutdown(cq);
      shutdown_started = 1;
    }
    ev = grpc_completion_queue_next(
        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                         gpr_time_from_micros(1000000, GPR_TIMESPAN)),
        NULL);
    switch (ev.type) {
      case GRPC_OP_COMPLETE:
        GPR_ASSERT(ev.tag == (void *)1);
        GPR_ASSERT(ev.success == 0);
        break;
      case GRPC_QUEUE_SHUTDOWN:
        GPR_ASSERT(shutdown_started);
        shutdown_finished = 1;
        break;
      case GRPC_QUEUE_TIMEOUT:
        break;
    }
  }

  GPR_ASSERT(s == NULL);
  grpc_call_details_destroy(&call_details);
  grpc_metadata_array_destroy(&request_metadata_recv);
}
Beispiel #14
0
void gpr_cancellable_cancel(gpr_cancellable *c) {
  if (!gpr_cancellable_is_cancelled(c)) {
    int failures;
    int backoff = 1;
    do {
      struct gpr_cancellable_list_ *l;
      struct gpr_cancellable_list_ *nl;
      gpr_mu *omu = 0; /* one-element cache of a processed gpr_mu */
      gpr_cv *ocv = 0; /* one-element cache of a processd gpr_cv */
      gpr_mu_lock(&c->mu);
      gpr_atm_rel_store(&c->cancelled, 1);
      failures = 0;
      for (l = c->waiters.next; l != &c->waiters; l = nl) {
        nl = l->next;
        if (omu != l->mu) {
          omu = l->mu;
          if (gpr_mu_trylock(l->mu)) {
            gpr_mu_unlock(l->mu);
            l->next->prev = l->prev; /* remove *l from list */
            l->prev->next = l->next;
            /* allow unconditional dequeue in gpr_cv_cancellable_wait() */
            l->next = l;
            l->prev = l;
            ocv = 0; /* force broadcast */
          } else {
            failures++;
          }
        }
        if (ocv != l->cv) {
          ocv = l->cv;
          gpr_cv_broadcast(l->cv);
        }
      }
      gpr_mu_unlock(&c->mu);
      if (failures != 0) {
        if (backoff < 10) {
          volatile int i;
          for (i = 0; i != (1 << backoff); i++) {
          }
          backoff++;
        } else {
          gpr_event ev;
          gpr_event_init(&ev);
          gpr_event_wait(
              &ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                gpr_time_from_micros(1000, GPR_TIMESPAN)));
        }
      }
    } while (failures != 0);
  }
}
Beispiel #15
0
/* Wait a millisecond and increment counter on each iteration, using an event
   for timing; then mark thread as done. */
static void inc_with_1ms_delay_event(void *v /*=m*/) {
  struct test *m = v;
  gpr_int64 i;
  for (i = 0; i != m->iterations; i++) {
    gpr_timespec deadline;
    deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                            gpr_time_from_micros(1000, GPR_TIMESPAN));
    GPR_ASSERT(gpr_event_wait(&m->event, deadline) == NULL);
    gpr_mu_lock(&m->mu);
    m->counter++;
    gpr_mu_unlock(&m->mu);
  }
  mark_thread_done(m);
}
Beispiel #16
0
/* Wait a millisecond and increment counter on each iteration;
   then mark thread as done. */
static void inc_with_1ms_delay(void *v /*=m*/) {
  struct test *m = v;
  gpr_int64 i;
  for (i = 0; i != m->iterations; i++) {
    gpr_timespec deadline;
    gpr_mu_lock(&m->mu);
    deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                            gpr_time_from_micros(1000, GPR_TIMESPAN));
    while (!gpr_cv_wait(&m->cv, &m->mu, deadline)) {
    }
    m->counter++;
    gpr_mu_unlock(&m->mu);
  }
  mark_thread_done(m);
}
Beispiel #17
0
int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
        gpr_timespec now) {
    gpr_timespec timeout;
    static const int64_t max_spin_polling_us = 10;
    if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
        return -1;
    }
    if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros(
            max_spin_polling_us,
            GPR_TIMESPAN))) <= 0) {
        return 0;
    }
    timeout = gpr_time_sub(deadline, now);
    return gpr_time_to_millis(gpr_time_add(
                                  timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
}
Beispiel #18
0
/* Consume elements from m->q until m->threads*m->iterations are seen,
   wait an extra second to confirm that no more elements are arriving,
   then mark thread as done. */
static void consumer(void *v /*=m*/) {
  struct test *m = v;
  gpr_int64 n = m->iterations * m->threads;
  gpr_int64 i;
  int value;
  for (i = 0; i != n; i++) {
    queue_remove(&m->q, &value, gpr_inf_future(GPR_CLOCK_REALTIME));
  }
  gpr_mu_lock(&m->mu);
  m->counter = n;
  gpr_mu_unlock(&m->mu);
  GPR_ASSERT(
      !queue_remove(&m->q, &value,
                    gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_micros(1000000, GPR_TIMESPAN))));
  mark_thread_done(m);
}
Beispiel #19
0
/**
 * Constructs a new instance of the Timeval class
 * @param long $usec The number of microseconds in the interval
 */
PHP_METHOD(Timeval, __construct) {
  wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
  zend_long microseconds;

  /* "l" == 1 long */
#ifndef FAST_ZPP
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &microseconds) == FAILURE) {
    zend_throw_exception(spl_ce_InvalidArgumentException,
                         "Timeval expects a long", 1);
    return;
  }
#else
  ZEND_PARSE_PARAMETERS_START(1, 1)
    Z_PARAM_LONG(microseconds)
  ZEND_PARSE_PARAMETERS_END();
#endif

  gpr_timespec time = gpr_time_from_micros(microseconds, GPR_TIMESPAN);
  memcpy(&timeval->wrapped, &time, sizeof(gpr_timespec));
}
Beispiel #20
0
static void test(void) {
  int i;
  gpr_thd_id thd;
  struct test t;
  int n = 1;
  gpr_timespec interval;

  gpr_mu_init(&t.mu);
  gpr_cv_init(&t.cv);
  gpr_event_init(&t.ev);
  gpr_event_init(&t.done);
  gpr_cancellable_init(&t.cancel);

  /* A gpr_cancellable starts not cancelled. */
  GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel));

  /* Test timeout on event wait for uncancelled gpr_cancellable */
  interval = gpr_now(GPR_CLOCK_REALTIME);
  gpr_event_cancellable_wait(
      &t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                          gpr_time_from_micros(1000000, GPR_TIMESPAN)),
      &t.cancel);
  interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
  GPR_ASSERT(
      gpr_time_cmp(interval, gpr_time_from_micros(500000, GPR_TIMESPAN)) >= 0);
  GPR_ASSERT(
      gpr_time_cmp(gpr_time_from_micros(2000000, GPR_TIMESPAN), interval) >= 0);

  /* Test timeout on cv wait for uncancelled gpr_cancellable */
  gpr_mu_lock(&t.mu);
  interval = gpr_now(GPR_CLOCK_REALTIME);
  while (!gpr_cv_cancellable_wait(
      &t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_micros(1000000, GPR_TIMESPAN)),
      &t.cancel)) {
  }
  interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
  GPR_ASSERT(
      gpr_time_cmp(interval, gpr_time_from_micros(500000, GPR_TIMESPAN)) >= 0);
  GPR_ASSERT(
      gpr_time_cmp(gpr_time_from_micros(2000000, GPR_TIMESPAN), interval) >= 0);
  gpr_mu_unlock(&t.mu);

  /* Create some threads.  They all wait until cancelled; the last to finish
     sets t.done.  */
  t.n = n;
  for (i = 0; i != n; i++) {
    GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL));
  }
  /* Check that t.cancel still is not cancelled. */
  GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel));

  /* Wait a second, and check that no threads have finished waiting. */
  gpr_mu_lock(&t.mu);
  gpr_cv_wait(&t.cv, &t.mu,
              gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                           gpr_time_from_micros(1000000, GPR_TIMESPAN)));
  GPR_ASSERT(t.n == n);
  gpr_mu_unlock(&t.mu);

  /* Check that t.cancel still is not cancelled, but when
     cancelled it retports that it is cacncelled. */
  GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel));
  gpr_cancellable_cancel(&t.cancel);
  GPR_ASSERT(gpr_cancellable_is_cancelled(&t.cancel));

  /* Wait for threads to finish. */
  gpr_event_wait(&t.done, gpr_inf_future(GPR_CLOCK_REALTIME));
  GPR_ASSERT(t.n == 0);

  /* Test timeout on cv wait for cancelled gpr_cancellable */
  gpr_mu_lock(&t.mu);
  interval = gpr_now(GPR_CLOCK_REALTIME);
  while (!gpr_cv_cancellable_wait(
      &t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_micros(1000000, GPR_TIMESPAN)),
      &t.cancel)) {
  }
  interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
  GPR_ASSERT(
      gpr_time_cmp(gpr_time_from_micros(100000, GPR_TIMESPAN), interval) >= 0);
  gpr_mu_unlock(&t.mu);

  /* Test timeout on event wait for cancelled gpr_cancellable */
  interval = gpr_now(GPR_CLOCK_REALTIME);
  gpr_event_cancellable_wait(
      &t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                          gpr_time_from_micros(1000000, GPR_TIMESPAN)),
      &t.cancel);
  interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval);
  GPR_ASSERT(
      gpr_time_cmp(gpr_time_from_micros(100000, GPR_TIMESPAN), interval) >= 0);

  gpr_mu_destroy(&t.mu);
  gpr_cv_destroy(&t.cv);
  gpr_cancellable_destroy(&t.cancel);
}
Beispiel #21
0
gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
  return gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC),
      gpr_time_from_micros(grpc_test_slowdown_factor() * (int64_t)1e3 * time_ms,
                           GPR_TIMESPAN));
}
Beispiel #22
0
int main(int argc, char **argv) {
  grpc_memory_counters_init();
  grpc_slice slice = grpc_slice_from_copied_string("x");
  char *fake_argv[1];

  char *target = "localhost:443";
  gpr_cmdline *cl;
  grpc_event event;

  grpc_init();

  GPR_ASSERT(argc >= 1);
  fake_argv[0] = argv[0];
  grpc_test_init(1, fake_argv);

  int warmup_iterations = 100;
  int benchmark_iterations = 1000;

  cl = gpr_cmdline_create("memory profiling client");
  gpr_cmdline_add_string(cl, "target", "Target host:port", &target);
  gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations);
  gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations",
                      &benchmark_iterations);
  gpr_cmdline_parse(cl, argc, argv);
  gpr_cmdline_destroy(cl);

  for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) {
    calls[k].details = grpc_empty_slice();
  }

  cq = grpc_completion_queue_create(NULL);

  struct grpc_memory_counters client_channel_start =
      grpc_memory_counters_snapshot();
  channel = grpc_insecure_channel_create(target, NULL, NULL);

  int call_idx = 0;

  struct grpc_memory_counters before_server_create = send_snapshot_request(
      0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation"));
  struct grpc_memory_counters after_server_create = send_snapshot_request(
      0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation"));

  // warmup period
  for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) {
    init_ping_pong_request(call_idx + 1);
  }

  struct grpc_memory_counters server_benchmark_calls_start =
      send_snapshot_request(
          0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));

  struct grpc_memory_counters client_benchmark_calls_start =
      grpc_memory_counters_snapshot();

  // benchmark period
  for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) {
    init_ping_pong_request(call_idx + 1);
  }

  struct grpc_memory_counters client_calls_inflight =
      grpc_memory_counters_snapshot();

  struct grpc_memory_counters server_calls_inflight = send_snapshot_request(
      0, grpc_slice_from_static_string("Reflector/DestroyCalls"));

  do {
    event = grpc_completion_queue_next(
        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                         gpr_time_from_micros(10000, GPR_TIMESPAN)),
        NULL);
  } while (event.type != GRPC_QUEUE_TIMEOUT);

  // second step - recv status and destroy call
  for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations;
       ++call_idx) {
    finish_ping_pong_request(call_idx + 1);
  }

  struct grpc_memory_counters server_calls_end = send_snapshot_request(
      0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));

  struct grpc_memory_counters client_channel_end =
      grpc_memory_counters_snapshot();

  grpc_channel_destroy(channel);
  grpc_completion_queue_shutdown(cq);

  do {
    event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
                                       NULL);
  } while (event.type != GRPC_QUEUE_SHUTDOWN);
  grpc_slice_unref(slice);

  grpc_completion_queue_destroy(cq);
  grpc_shutdown();

  gpr_log(GPR_INFO, "---------client stats--------");
  gpr_log(GPR_INFO, "client call memory usage: %f bytes per call",
          (double)(client_calls_inflight.total_size_relative -
                   client_benchmark_calls_start.total_size_relative) /
              benchmark_iterations);
  gpr_log(GPR_INFO, "client channel memory usage %zi bytes",
          client_channel_end.total_size_relative -
              client_channel_start.total_size_relative);

  gpr_log(GPR_INFO, "---------server stats--------");
  gpr_log(GPR_INFO, "server create: %zi bytes",
          after_server_create.total_size_relative -
              before_server_create.total_size_relative);
  gpr_log(GPR_INFO, "server call memory usage: %f bytes per call",
          (double)(server_calls_inflight.total_size_relative -
                   server_benchmark_calls_start.total_size_relative) /
              benchmark_iterations);
  gpr_log(GPR_INFO, "server channel memory usage %zi bytes",
          server_calls_end.total_size_relative -
              after_server_create.total_size_relative);

  grpc_memory_counters_destroy();
  return 0;
}
Beispiel #23
0
int main(int argc, char **argv) {
  grpc_event ev;
  call_state *s;
  char *addr_buf = NULL;
  gpr_cmdline *cl;
  int shutdown_started = 0;
  int shutdown_finished = 0;

  int secure = 0;
  char *addr = NULL;

  char *fake_argv[1];

  GPR_ASSERT(argc >= 1);
  fake_argv[0] = argv[0];
  grpc_test_init(1, fake_argv);

  grpc_init();
  srand(clock());

  cl = gpr_cmdline_create("fling server");
  gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr);
  gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure);
  gpr_cmdline_parse(cl, argc, argv);
  gpr_cmdline_destroy(cl);

  if (addr == NULL) {
    gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die());
    addr = addr_buf;
  }
  gpr_log(GPR_INFO, "creating server on: %s", addr);

  cq = grpc_completion_queue_create();
  if (secure) {
    grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                    test_server1_cert};
    grpc_server_credentials *ssl_creds =
        grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0);
    server = grpc_server_create(NULL);
    GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
    grpc_server_credentials_release(ssl_creds);
  } else {
    server = grpc_server_create(NULL);
    GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr));
  }
  grpc_server_register_completion_queue(server, cq);
  grpc_server_start(server);

  gpr_free(addr_buf);
  addr = addr_buf = NULL;

  grpc_call_details_init(&call_details);

  request_call();

  grpc_profiler_start("server.prof");
  signal(SIGINT, sigint_handler);
  while (!shutdown_finished) {
    if (got_sigint && !shutdown_started) {
      gpr_log(GPR_INFO, "Shutting down due to SIGINT");
      grpc_server_shutdown_and_notify(server, cq, tag(1000));
      GPR_ASSERT(grpc_completion_queue_pluck(
                     cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))
                     .type == GRPC_OP_COMPLETE);
      grpc_completion_queue_shutdown(cq);
      shutdown_started = 1;
    }
    ev = grpc_completion_queue_next(
        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                         gpr_time_from_micros(1000000, GPR_TIMESPAN)));
    s = ev.tag;
    switch (ev.type) {
      case GRPC_OP_COMPLETE:
        switch ((gpr_intptr)s) {
          case FLING_SERVER_NEW_REQUEST:
            if (call != NULL) {
              if (0 ==
                  strcmp(call_details.method, "/Reflector/reflectStream")) {
                /* Received streaming call. Send metadata here. */
                start_read_op(FLING_SERVER_READ_FOR_STREAMING);
                send_initial_metadata();
              } else {
                /* Received unary call. Can do all ops in one batch. */
                start_read_op(FLING_SERVER_READ_FOR_UNARY);
              }
            } else {
              GPR_ASSERT(shutdown_started);
            }
            /*	    request_call();
             */
            break;
          case FLING_SERVER_READ_FOR_STREAMING:
            if (payload_buffer != NULL) {
              /* Received payload from client. */
              start_write_op();
            } else {
              /* Received end of stream from client. */
              start_send_status();
            }
            break;
          case FLING_SERVER_WRITE_FOR_STREAMING:
            /* Write completed at server  */
            grpc_byte_buffer_destroy(payload_buffer);
            payload_buffer = NULL;
            start_read_op(FLING_SERVER_READ_FOR_STREAMING);
            break;
          case FLING_SERVER_SEND_INIT_METADATA_FOR_STREAMING:
            /* Metadata send completed at server */
            break;
          case FLING_SERVER_SEND_STATUS_FOR_STREAMING:
            /* Send status and close completed at server */
            grpc_call_destroy(call);
            if (!shutdown_started) request_call();
            break;
          case FLING_SERVER_READ_FOR_UNARY:
            /* Finished payload read for unary. Start all reamaining
             *  unary ops in a batch.
             */
            handle_unary_method();
            break;
          case FLING_SERVER_BATCH_OPS_FOR_UNARY:
            /* Finished unary call. */
            grpc_byte_buffer_destroy(payload_buffer);
            payload_buffer = NULL;
            grpc_call_destroy(call);
            if (!shutdown_started) request_call();
            break;
        }
        break;
      case GRPC_QUEUE_SHUTDOWN:
        GPR_ASSERT(shutdown_started);
        shutdown_finished = 1;
        break;
      case GRPC_QUEUE_TIMEOUT:
        break;
    }
  }
  grpc_profiler_stop();
  grpc_call_details_destroy(&call_details);

  grpc_server_destroy(server);
  grpc_completion_queue_destroy(cq);
  grpc_shutdown();
  return 0;
}
Beispiel #24
0
static void test_similar(void) {
    GPR_ASSERT(1 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN),
                                     gpr_inf_future(GPR_TIMESPAN),
                                     gpr_time_0(GPR_TIMESPAN)));
    GPR_ASSERT(1 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN),
                                     gpr_inf_past(GPR_TIMESPAN),
                                     gpr_time_0(GPR_TIMESPAN)));
    GPR_ASSERT(0 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN),
                                     gpr_inf_future(GPR_TIMESPAN),
                                     gpr_time_0(GPR_TIMESPAN)));
    GPR_ASSERT(0 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN),
                                     gpr_inf_past(GPR_TIMESPAN),
                                     gpr_time_0(GPR_TIMESPAN)));
    GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_0(GPR_TIMESPAN)));
    GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_from_micros(15, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN)));
    GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(15, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN)));
    GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_from_micros(25, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN)));
    GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(25, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN),
                                     gpr_time_from_micros(10, GPR_TIMESPAN)));
}
Beispiel #25
0
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  grpc_test_only_set_metadata_hash_seed(0);
  if (squelch) gpr_set_log_function(dont_log);
  input_stream inp = {data, data + size};
  grpc_resolve_address = my_resolve_address;
  grpc_tcp_client_connect_impl = my_tcp_client_connect;
  gpr_now_impl = now_impl;
  grpc_init();

  GPR_ASSERT(g_channel == NULL);
  GPR_ASSERT(g_server == NULL);

  bool server_shutdown = false;
  int pending_server_shutdowns = 0;
  int pending_channel_watches = 0;
  int pending_pings = 0;

  g_active_call = new_call(NULL, ROOT);

  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);

  while (!is_eof(&inp) || g_channel != NULL || g_server != NULL ||
         pending_channel_watches > 0 || pending_pings > 0 ||
         g_active_call->type != ROOT || g_active_call->next != g_active_call) {
    if (is_eof(&inp)) {
      if (g_channel != NULL) {
        grpc_channel_destroy(g_channel);
        g_channel = NULL;
      }
      if (g_server != NULL) {
        if (!server_shutdown) {
          grpc_server_shutdown_and_notify(
              g_server, cq, create_validator(assert_success_and_decrement,
                                             &pending_server_shutdowns));
          server_shutdown = true;
          pending_server_shutdowns++;
        } else if (pending_server_shutdowns == 0) {
          grpc_server_destroy(g_server);
          g_server = NULL;
        }
      }
      call_state *s = g_active_call;
      do {
        if (s->type != PENDING_SERVER && s->call != NULL) {
          s = destroy_call(s);
        } else {
          s = s->next;
        }
      } while (s != g_active_call);

      g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN));
    }

    switch (next_byte(&inp)) {
      // terminate on bad bytes
      default:
        end(&inp);
        break;
      // tickle completion queue
      case 0: {
        grpc_event ev = grpc_completion_queue_next(
            cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
        switch (ev.type) {
          case GRPC_OP_COMPLETE: {
            validator *v = ev.tag;
            v->validate(v->arg, ev.success);
            gpr_free(v);
            break;
          }
          case GRPC_QUEUE_TIMEOUT:
            break;
          case GRPC_QUEUE_SHUTDOWN:
            abort();
            break;
        }
        break;
      }
      // increment global time
      case 1: {
        g_now = gpr_time_add(
            g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
        break;
      }
      // create an insecure channel
      case 2: {
        if (g_channel == NULL) {
          char *target = read_string(&inp);
          char *target_uri;
          gpr_asprintf(&target_uri, "dns:%s", target);
          grpc_channel_args *args = read_args(&inp);
          g_channel = grpc_insecure_channel_create(target_uri, args, NULL);
          GPR_ASSERT(g_channel != NULL);
          grpc_channel_args_destroy(args);
          gpr_free(target_uri);
          gpr_free(target);
        } else {
          end(&inp);
        }
        break;
      }
      // destroy a channel
      case 3: {
        if (g_channel != NULL) {
          grpc_channel_destroy(g_channel);
          g_channel = NULL;
        } else {
          end(&inp);
        }
        break;
      }
      // bring up a server
      case 4: {
        if (g_server == NULL) {
          grpc_channel_args *args = read_args(&inp);
          g_server = grpc_server_create(args, NULL);
          GPR_ASSERT(g_server != NULL);
          grpc_channel_args_destroy(args);
          grpc_server_register_completion_queue(g_server, cq, NULL);
          grpc_server_start(g_server);
          server_shutdown = false;
          GPR_ASSERT(pending_server_shutdowns == 0);
        } else {
          end(&inp);
        }
      }
      // begin server shutdown
      case 5: {
        if (g_server != NULL) {
          grpc_server_shutdown_and_notify(
              g_server, cq, create_validator(assert_success_and_decrement,
                                             &pending_server_shutdowns));
          pending_server_shutdowns++;
          server_shutdown = true;
        } else {
          end(&inp);
        }
        break;
      }
      // cancel all calls if shutdown
      case 6: {
        if (g_server != NULL && server_shutdown) {
          grpc_server_cancel_all_calls(g_server);
        } else {
          end(&inp);
        }
        break;
      }
      // destroy server
      case 7: {
        if (g_server != NULL && server_shutdown &&
            pending_server_shutdowns == 0) {
          grpc_server_destroy(g_server);
          g_server = NULL;
        } else {
          end(&inp);
        }
        break;
      }
      // check connectivity
      case 8: {
        if (g_channel != NULL) {
          uint8_t try_to_connect = next_byte(&inp);
          if (try_to_connect == 0 || try_to_connect == 1) {
            grpc_channel_check_connectivity_state(g_channel, try_to_connect);
          } else {
            end(&inp);
          }
        } else {
          end(&inp);
        }
        break;
      }
      // watch connectivity
      case 9: {
        if (g_channel != NULL) {
          grpc_connectivity_state st =
              grpc_channel_check_connectivity_state(g_channel, 0);
          if (st != GRPC_CHANNEL_FATAL_FAILURE) {
            gpr_timespec deadline = gpr_time_add(
                gpr_now(GPR_CLOCK_REALTIME),
                gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
            grpc_channel_watch_connectivity_state(
                g_channel, st, deadline, cq,
                create_validator(validate_connectivity_watch,
                                 make_connectivity_watch(
                                     deadline, &pending_channel_watches)));
            pending_channel_watches++;
          }
        } else {
          end(&inp);
        }
        break;
      }
      // create a call
      case 10: {
        bool ok = true;
        if (g_channel == NULL) ok = false;
        grpc_call *parent_call = NULL;
        if (g_active_call->type != ROOT) {
          if (g_active_call->call == NULL || g_active_call->type == CLIENT) {
            end(&inp);
            break;
          }
          parent_call = g_active_call->call;
        }
        uint32_t propagation_mask = read_uint32(&inp);
        char *method = read_string(&inp);
        char *host = read_string(&inp);
        gpr_timespec deadline =
            gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                         gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));

        if (ok) {
          call_state *cs = new_call(g_active_call, CLIENT);
          cs->call =
              grpc_channel_create_call(g_channel, parent_call, propagation_mask,
                                       cq, method, host, deadline, NULL);
        } else {
          end(&inp);
        }
        gpr_free(method);
        gpr_free(host);
        break;
      }
      // switch the 'current' call
      case 11: {
        g_active_call = g_active_call->next;
        break;
      }
      // queue some ops on a call
      case 12: {
        if (g_active_call->type == PENDING_SERVER ||
            g_active_call->type == ROOT || g_active_call->call == NULL) {
          end(&inp);
          break;
        }
        size_t num_ops = next_byte(&inp);
        if (num_ops > 6) {
          end(&inp);
          break;
        }
        grpc_op *ops = gpr_malloc(sizeof(grpc_op) * num_ops);
        bool ok = true;
        size_t i;
        grpc_op *op;
        for (i = 0; i < num_ops; i++) {
          op = &ops[i];
          switch (next_byte(&inp)) {
            default:
              /* invalid value */
              op->op = (grpc_op_type)-1;
              ok = false;
              break;
            case GRPC_OP_SEND_INITIAL_METADATA:
              op->op = GRPC_OP_SEND_INITIAL_METADATA;
              read_metadata(&inp, &op->data.send_initial_metadata.count,
                            &op->data.send_initial_metadata.metadata,
                            g_active_call);
              break;
            case GRPC_OP_SEND_MESSAGE:
              op->op = GRPC_OP_SEND_MESSAGE;
              op->data.send_message = read_message(&inp);
              break;
            case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
              op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
              break;
            case GRPC_OP_SEND_STATUS_FROM_SERVER:
              op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
              read_metadata(
                  &inp,
                  &op->data.send_status_from_server.trailing_metadata_count,
                  &op->data.send_status_from_server.trailing_metadata,
                  g_active_call);
              op->data.send_status_from_server.status = next_byte(&inp);
              op->data.send_status_from_server.status_details =
                  read_string(&inp);
              break;
            case GRPC_OP_RECV_INITIAL_METADATA:
              op->op = GRPC_OP_RECV_INITIAL_METADATA;
              op->data.recv_initial_metadata =
                  &g_active_call->recv_initial_metadata;
              break;
            case GRPC_OP_RECV_MESSAGE:
              op->op = GRPC_OP_RECV_MESSAGE;
              op->data.recv_message = &g_active_call->recv_message;
              break;
            case GRPC_OP_RECV_STATUS_ON_CLIENT:
              op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
              op->data.recv_status_on_client.status = &g_active_call->status;
              op->data.recv_status_on_client.trailing_metadata =
                  &g_active_call->recv_trailing_metadata;
              op->data.recv_status_on_client.status_details =
                  &g_active_call->recv_status_details;
              op->data.recv_status_on_client.status_details_capacity =
                  &g_active_call->recv_status_details_capacity;
              break;
            case GRPC_OP_RECV_CLOSE_ON_SERVER:
              op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
              op->data.recv_close_on_server.cancelled =
                  &g_active_call->cancelled;
              break;
          }
          op->reserved = NULL;
          op->flags = read_uint32(&inp);
        }
        if (ok) {
          validator *v = create_validator(finished_batch, g_active_call);
          g_active_call->pending_ops++;
          grpc_call_error error =
              grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL);
          if (error != GRPC_CALL_OK) {
            v->validate(v->arg, false);
            gpr_free(v);
          }
        } else {
          end(&inp);
        }
        for (i = 0; i < num_ops; i++) {
          op = &ops[i];
          switch (op->op) {
            case GRPC_OP_SEND_INITIAL_METADATA:
              break;
            case GRPC_OP_SEND_MESSAGE:
              grpc_byte_buffer_destroy(op->data.send_message);
              break;
            case GRPC_OP_SEND_STATUS_FROM_SERVER:
              gpr_free((void *)op->data.send_status_from_server.status_details);
              break;
            case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
            case GRPC_OP_RECV_INITIAL_METADATA:
            case GRPC_OP_RECV_MESSAGE:
            case GRPC_OP_RECV_STATUS_ON_CLIENT:
            case GRPC_OP_RECV_CLOSE_ON_SERVER:
              break;
          }
        }
        gpr_free(ops);

        break;
      }
      // cancel current call
      case 13: {
        if (g_active_call->type != ROOT && g_active_call->call != NULL) {
          grpc_call_cancel(g_active_call->call, NULL);
        } else {
          end(&inp);
        }
        break;
      }
      // get a calls peer
      case 14: {
        if (g_active_call->type != ROOT && g_active_call->call != NULL) {
          free_non_null(grpc_call_get_peer(g_active_call->call));
        } else {
          end(&inp);
        }
        break;
      }
      // get a channels target
      case 15: {
        if (g_channel != NULL) {
          free_non_null(grpc_channel_get_target(g_channel));
        } else {
          end(&inp);
        }
        break;
      }
      // send a ping on a channel
      case 16: {
        if (g_channel != NULL) {
          pending_pings++;
          grpc_channel_ping(g_channel, cq,
                            create_validator(decrement, &pending_pings), NULL);
        } else {
          end(&inp);
        }
        break;
      }
      // enable a tracer
      case 17: {
        char *tracer = read_string(&inp);
        grpc_tracer_set_enabled(tracer, 1);
        gpr_free(tracer);
        break;
      }
      // disable a tracer
      case 18: {
        char *tracer = read_string(&inp);
        grpc_tracer_set_enabled(tracer, 0);
        gpr_free(tracer);
        break;
      }
      // request a server call
      case 19: {
        if (g_server == NULL) {
          end(&inp);
          break;
        }
        call_state *cs = new_call(g_active_call, PENDING_SERVER);
        cs->pending_ops++;
        validator *v = create_validator(finished_request_call, cs);
        grpc_call_error error =
            grpc_server_request_call(g_server, &cs->call, &cs->call_details,
                                     &cs->recv_initial_metadata, cq, cq, v);
        if (error != GRPC_CALL_OK) {
          v->validate(v->arg, false);
          gpr_free(v);
        }
        break;
      }
      // destroy a call
      case 20: {
        if (g_active_call->type != ROOT &&
            g_active_call->type != PENDING_SERVER &&
            g_active_call->call != NULL) {
          destroy_call(g_active_call);
        } else {
          end(&inp);
        }
        break;
      }
    }
  }

  GPR_ASSERT(g_channel == NULL);
  GPR_ASSERT(g_server == NULL);
  GPR_ASSERT(g_active_call->type == ROOT);
  GPR_ASSERT(g_active_call->next == g_active_call);
  gpr_free(g_active_call);

  grpc_completion_queue_shutdown(cq);
  GPR_ASSERT(
      grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL)
          .type == GRPC_QUEUE_SHUTDOWN);
  grpc_completion_queue_destroy(cq);

  grpc_shutdown();
  return 0;
}