static void
test_cntev_orconn_state_proxy(void *arg)
{
  orconn_event_msg_t conn;

  (void)arg;
  MOCK(queue_control_event_string, mock_queue_control_event_string);
  control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  setup_orconn_state(&conn, 1, 1, PROXY_CONNECT);
  send_ocirc_chan(1, 1, true);

  send_orconn_state(&conn, OR_CONN_STATE_CONNECTING);
  assert_bootmsg("3 TAG=conn_proxy");
  send_orconn_state(&conn, OR_CONN_STATE_PROXY_HANDSHAKING);
  assert_bootmsg("4 TAG=conn_done_proxy");
  send_orconn_state(&conn, OR_CONN_STATE_TLS_HANDSHAKING);
  assert_bootmsg("10 TAG=conn_done");
  send_orconn_state(&conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
  assert_bootmsg("14 TAG=handshake");
  send_orconn_state(&conn, OR_CONN_STATE_OPEN);
  assert_bootmsg("15 TAG=handshake_done");

  send_ocirc_chan(2, 2, false);
  conn.u.state.gid = 2;
  conn.u.state.chan = 2;
  send_orconn_state(&conn, OR_CONN_STATE_CONNECTING);
  assert_bootmsg("78 TAG=ap_conn_proxy");
  send_orconn_state(&conn, OR_CONN_STATE_PROXY_HANDSHAKING);
  assert_bootmsg("79 TAG=ap_conn_done_proxy");

 done:
  tor_free(saved_event_str);
  UNMOCK(queue_control_event_string);
}
static void
test_cntev_orconn_state(void *arg)
{
  orconn_event_msg_t conn;

  (void)arg;
  MOCK(queue_control_event_string, mock_queue_control_event_string);
  control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  setup_orconn_state(&conn, 1, 1, PROXY_NONE);

  send_orconn_state(&conn, OR_CONN_STATE_CONNECTING);
  send_ocirc_chan(1, 1, true);
  assert_bootmsg("5 TAG=conn");
  send_orconn_state(&conn, OR_CONN_STATE_TLS_HANDSHAKING);
  assert_bootmsg("10 TAG=conn_done");
  send_orconn_state(&conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
  assert_bootmsg("14 TAG=handshake");
  send_orconn_state(&conn, OR_CONN_STATE_OPEN);
  assert_bootmsg("15 TAG=handshake_done");

  conn.u.state.gid = 2;
  conn.u.state.chan = 2;
  send_orconn_state(&conn, OR_CONN_STATE_CONNECTING);
  /* It doesn't know it's an origin circuit yet */
  assert_bootmsg("15 TAG=handshake_done");
  send_ocirc_chan(2, 2, false);
  assert_bootmsg("80 TAG=ap_conn");
  send_orconn_state(&conn, OR_CONN_STATE_TLS_HANDSHAKING);
  assert_bootmsg("85 TAG=ap_conn_done");
  send_orconn_state(&conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
  assert_bootmsg("89 TAG=ap_handshake");
  send_orconn_state(&conn, OR_CONN_STATE_OPEN);
  assert_bootmsg("90 TAG=ap_handshake_done");

 done:
  tor_free(saved_event_str);
  UNMOCK(queue_control_event_string);
}
/* Test deferral of directory bootstrap messages (conn_or) */
static void
test_cntev_dirboot_defer_orconn(void *arg)
{
  (void)arg;

  MOCK(queue_control_event_string, mock_queue_control_event_string);
  control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
  assert_bootmsg("0 TAG=starting");
  /* This event should get deferred */
  control_event_boot_dir(BOOTSTRAP_STATUS_ENOUGH_DIRINFO, 0);
  assert_bootmsg("0 TAG=starting");
  control_event_bootstrap(BOOTSTRAP_STATUS_CONN, 0);
  assert_bootmsg("5 TAG=conn");
  control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
  assert_bootmsg("14 TAG=handshake");
  /* The deferred event should appear */
  control_event_boot_first_orconn();
  assert_bootmsg("75 TAG=enough_dirinfo");
 done:
  tor_free(saved_event_str);
  UNMOCK(queue_control_event_string);
}
/* Test deferral of directory bootstrap messages (requesting_descriptors) */
static void
test_cntev_dirboot_defer_desc(void *arg)
{
  (void)arg;

  MOCK(queue_control_event_string, mock_queue_control_event_string);
  control_testing_set_global_event_mask(EVENT_MASK_(EVENT_STATUS_CLIENT));
  control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
  assert_bootmsg("0 TAG=starting");
  /* This event should get deferred */
  control_event_boot_dir(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
  assert_bootmsg("0 TAG=starting");
  control_event_bootstrap(BOOTSTRAP_STATUS_CONN, 0);
  assert_bootmsg("5 TAG=conn");
  control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
  assert_bootmsg("14 TAG=handshake");
  /* The deferred event should appear */
  control_event_boot_first_orconn();
  assert_bootmsg("45 TAG=requesting_descriptors");
 done:
  tor_free(saved_event_str);
  UNMOCK(queue_control_event_string);
}
static void
test_cntev_event_mask(void *arg)
{
  unsigned int test_event, selected_event;
  (void)arg;

  /* Check that nothing is interesting when no events are set */
  control_testing_set_global_event_mask(EVENT_MASK_NONE_);

  /* Check that nothing is interesting between EVENT_MIN_ and EVENT_MAX_ */
  for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++)
    tt_assert(!control_event_is_interesting(test_event));

  /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
   * This will break if control_event_is_interesting() checks its arguments */
  for (test_event = 0; test_event < EVENT_MIN_; test_event++)
    tt_assert(!control_event_is_interesting(test_event));
  for (test_event = EVENT_MAX_ + 1;
       test_event < EVENT_CAPACITY_;
       test_event++)
    tt_assert(!control_event_is_interesting(test_event));

  /* Check that all valid events are interesting when all events are set */
  control_testing_set_global_event_mask(EVENT_MASK_ALL_);

  /* Check that everything is interesting between EVENT_MIN_ and EVENT_MAX_ */
  for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++)
    tt_assert(control_event_is_interesting(test_event));

  /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
   * This will break if control_event_is_interesting() checks its arguments */
  for (test_event = 0; test_event < EVENT_MIN_; test_event++)
    tt_assert(!control_event_is_interesting(test_event));
  for (test_event = EVENT_MAX_ + 1;
       test_event < EVENT_CAPACITY_;
       test_event++)
    tt_assert(!control_event_is_interesting(test_event));

  /* Check that only that event is interesting when a single event is set */
  for (selected_event = EVENT_MIN_;
       selected_event <= EVENT_MAX_;
       selected_event++) {
    control_testing_set_global_event_mask(EVENT_MASK_(selected_event));

    /* Check that only this event is interesting
     * between EVENT_MIN_ and EVENT_MAX_ */
    for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) {
      if (test_event == selected_event) {
        tt_assert(control_event_is_interesting(test_event));
      } else {
        tt_assert(!control_event_is_interesting(test_event));
      }
    }

    /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
     * This will break if control_event_is_interesting checks its arguments */
    for (test_event = 0; test_event < EVENT_MIN_; test_event++)
      tt_assert(!control_event_is_interesting(test_event));
    for (test_event = EVENT_MAX_ + 1;
         test_event < EVENT_CAPACITY_;
         test_event++)
      tt_assert(!control_event_is_interesting(test_event));
  }

  /* Check that only that event is not-interesting
   * when a single event is un-set */
  for (selected_event = EVENT_MIN_;
       selected_event <= EVENT_MAX_;
       selected_event++) {
    control_testing_set_global_event_mask(
                                          EVENT_MASK_ALL_
                                          & ~(EVENT_MASK_(selected_event))
                                          );

    /* Check that only this event is not-interesting
     * between EVENT_MIN_ and EVENT_MAX_ */
    for (test_event = EVENT_MIN_; test_event <= EVENT_MAX_; test_event++) {
      if (test_event == selected_event) {
        tt_assert(!control_event_is_interesting(test_event));
      } else {
        tt_assert(control_event_is_interesting(test_event));
      }
    }

    /* Check that nothing is interesting outside EVENT_MIN_ to EVENT_MAX_
     * This will break if control_event_is_interesting checks its arguments */
    for (test_event = 0; test_event < EVENT_MIN_; test_event++)
      tt_assert(!control_event_is_interesting(test_event));
    for (test_event = EVENT_MAX_ + 1;
         test_event < EVENT_CAPACITY_;
         test_event++)
      tt_assert(!control_event_is_interesting(test_event));
  }

 done:
  ;
}