static void
test_case(const char * tapname, const char * request, unsigned count)
{
    SXE  * client;
    tap_ev event;

    tap_test_case_name(tapname);

    SXEA1((client = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
            "Failed to allocate client SXE");
    SXEA1(sxe_connect(client, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK, "Failed to connect to HTTPD");

#ifdef _WIN32
    usleep(10000);    /* Copied from test-errors.c and which is a TODO item */
#endif

    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &event), "client_connect", "Got a client connected event");
    is(tap_ev_arg(event, "this"), client, "It's the client");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect", "Got a server connected event");

    test_sxe_send(client, request, strlen(request), client_sent, "client_sent", q_client, TEST_WAIT, &event);

    if (count == 2) {
        is_eq(test_tap_ev_queue_identifier_wait(q_httpd , TEST_WAIT, &event), "h_header", "HTTPD: header event (a)"         );
        is_strncmp(tap_ev_arg(event, "key"  ), "Good"   , SXE_LITERAL_LENGTH( "Good"   ), "HTTPD: header was 'Good'"        );
        is_strncmp(tap_ev_arg(event, "value"), "Header" , SXE_LITERAL_LENGTH( "Header" ), "HTTPD: header value was 'Header'");

        is_eq(test_tap_ev_queue_identifier_wait(q_httpd , TEST_WAIT, &event), "h_header", "HTTPD: header event (b)"         );
        is_strncmp(tap_ev_arg(event, "key"  ), "Another", SXE_LITERAL_LENGTH( "Another"), "HTTPD: header was 'Another'"     );
        is_strncmp(tap_ev_arg(event, "value"), "Foo"    , SXE_LITERAL_LENGTH( "Foo"    ), "HTTPD: header value was 'Foo'"   );
    }

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_respond", "HTTPD: respond event");

    sxe_close(client);
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_close", "HTTPD: close event");
}
Ejemplo n.º 2
0
int
main(void)
{

#if !TEST_DIRWATCH
/* TODO: Implement sxe_dirwatch() on Windows */
/* TODO: Implement sxe_dirwatch() on Apple */
/* TODO: Implement sxe_dirwatch() on FreeBSD */
#else

    char tempdir1[] = "tmp-XXXXXX";
    char tempdir2[] = "tmp-XXXXXX";
    char tempdir3[] = "tmp-XXXXXX";
    SXE_DIRWATCH dirwatch1;
    SXE_DIRWATCH dirwatch2;
    SXE_DIRWATCH dirwatch3;
    char fname[PATH_MAX];
    tap_ev ev;

    plan_tests(28);

    sxe_register(1, 0);
    sxe_init();

    /* We need to make a new temporary directory, because *everything* appears
     * to change willy-nilly during the build. The current directory has a
     * file that always changes. The /tmp directory always seems to have
     * spurious changes in it. */
    SXEA1(mkdtemp(tempdir1), "Failed to create tempdir: %s", strerror(errno));
    SXEA1(mkdtemp(tempdir2), "Failed to create tempdir: %s", strerror(errno));
    SXEA1(mkdtemp(tempdir3), "Failed to create tempdir: %s", strerror(errno));

    sxe_dirwatch_init();
    sxe_dirwatch_init(); /* for coverage */
    sxe_dirwatch_add(&dirwatch1, tempdir1, SXE_DIRWATCH_CREATED|SXE_DIRWATCH_MODIFIED|SXE_DIRWATCH_DELETED, test_dirwatch_event, (void *)1);
    sxe_dirwatch_add(&dirwatch2, tempdir2, SXE_DIRWATCH_MODIFIED, test_dirwatch_event, (void *)2);
    sxe_dirwatch_add(&dirwatch3, tempdir3, SXE_DIRWATCH_DELETED, test_dirwatch_event, (void *)3);
    sxe_dirwatch_start();

    /* tempdir1: create, modify, delete */
    {
        char rname[PATH_MAX];
        int fd;

        snprintf(rname, sizeof rname, "%s/renamed", tempdir1);
        snprintf(fname, sizeof fname, "%s/created", tempdir1);

        fd = open(fname, O_CREAT|O_RDWR, S_IRWXU);
        write(fd, "Hello", 5);
        rename(fname, rname);
        unlink(rname);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), "created",                                 "Got filename %s", fname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_CREATED,                        "Got flags=SXE_DIRWATCH_CREATED");
        is(tap_ev_arg(ev, "user_data"), 1,                                         "Got user_data=1 (%s)", tempdir1);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), "created",                                 "Got filename %s", fname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_MODIFIED,                       "Got flags=SXE_DIRWATCH_MODIFIED");
        is(tap_ev_arg(ev, "user_data"), 1,                                         "Got user_data=1 (%s)", tempdir1);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), "created",                                 "Got filename %s", fname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_DELETED,                        "Got flags=SXE_DIRWATCH_DELETED");
        is(tap_ev_arg(ev, "user_data"), 1,                                         "Got user_data=1 (%s)", tempdir1);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), "renamed",                                 "Got filename %s", rname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_CREATED,                        "Got flags=SXE_DIRWATCH_CREATED");
        is(tap_ev_arg(ev, "user_data"), 1,                                         "Got user_data=1 (%s)", tempdir1);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), "renamed",                                 "Got filename %s", rname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_DELETED,                        "Got flags=SXE_DIRWATCH_DELETED");
        is(tap_ev_arg(ev, "user_data"), 1,                                         "Got user_data=1 (%s)", tempdir1);
    }

    /* tempdir2: modified */
    {
        const char *rel;
        int fd;

        snprintf(fname, sizeof fname, "%s/file.XXXXXX", tempdir2);
        SXEA1((rel = strchr(fname, '/')), "Didn't find '/' in %s", fname);
        rel++;

        fd = mkstemp(fname);
        write(fd, "Hello", 5);
        unlink(fname);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), rel,                                       "Got filename %s", fname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_MODIFIED,                       "Got flags=SXE_DIRWATCH_MODIFIED");
        is(tap_ev_arg(ev, "user_data"), 2,                                         "Got user_data=2 (%s)", tempdir2);
    }

    /* tempdir3: deleted */
    {
        const char *rel;
        int fd;

        snprintf(fname, sizeof fname, "%s/file.XXXXXX", tempdir3);
        SXEA1((rel = strchr(fname, '/')), "Didn't find '/' in %s", fname);
        rel++;

        fd = mkstemp(fname);
        unlink(fname);

        is_eq(test_tap_ev_identifier_wait(TEST_WAIT, &ev), "test_dirwatch_event",  "Got a dirwatch event");
        is_eq(tap_ev_arg(ev, "chfile"), rel,                                       "Got filename %s", fname);
        is(tap_ev_arg(ev, "chflags"), SXE_DIRWATCH_DELETED,                        "Got flags=SXE_DIRWATCH_DELETED");
        is(tap_ev_arg(ev, "user_data"), 3,                                         "Got user_data=3 (%s)", tempdir3);
    }

    rmdir(tempdir1);
    rmdir(tempdir2);
    rmdir(tempdir3);

    sxe_dirwatch_stop();

#endif
    return exit_status();
}
Ejemplo n.º 3
0
int
main(void)
{
    SXE_HTTPD    httpd;
    SXE        * client;
    SXE        * client2;
    SXE        * server;
    SXE        * server2;
    tap_ev       event;

    plan_tests(14);

    test_sxe_register_and_init(1000);

    sxe_httpd_construct(&httpd, 2, 10, 512, 0);
    SXE_HTTPD_SET_HANDLER(&httpd, connect, h_connect);
    SXE_HTTPD_SET_HANDLER(&httpd, request, h_request);
    SXE_HTTPD_SET_HANDLER(&httpd, close,   h_close);
    ok((listener = test_httpd_listen(&httpd, "0.0.0.0", 0)) != NULL,                              "HTTPD listening");

    /* Starts two connections, then make a new connection, the oldest will be reaped by the server */
    tap_test_case_name("reap connections");

    /* 1st connection */
    SXEA1((client = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
           "Failed to allocate client SXE");
    SXEA1(sxe_connect(client, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK,          "Failed to connect to HTTPD");
    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &event), "client_connect", "Got 1st client connected event");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect",     "Got 1st server connect event");
    server = SXE_CAST(SXE *, tap_ev_arg(event, "this"));

    /* 1st client: send a complete request line */
    TEST_SXE_SEND_LITERAL(client, "GET /good HTTP/1.1\r\n", client_sent, q_client, TEST_WAIT, &event);

    /* Waiting for 1st client request state "stable" on "STATE_HEADER" to make
     * sure there is no more state updates on this request object, then the following
     * usleep will guarantee the 1st connection is older than the 2nd one.
     */
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_request",     "Got 1st server request event");
    is(tap_ev_arg(event, "this"), server,                                                        "It's the 1st server");
    usleep(300000);

    /* 2nd connection, reaping happens, the 1st one got reaped */
    SXEA1((client2 = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
           "Failed to allocate client SXE");
    SXEA1(sxe_connect(client2, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK,         "Failed to connect to HTTPD");

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect",     "Got 2nd server connect event");
    server2 = SXE_CAST(SXE *, tap_ev_arg(event, "this"));
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_close",       "Got a server close event");
    is(tap_ev_arg(event, "this"), server,                                                        "It's the 1st server");

    /* Pull these two arguments off in any order */
    test_process_all_libev_events();
    ok((event = tap_ev_queue_shift_next(q_client, "client_connect")) != NULL, "Got 2nd client connected event");
    ok((event = tap_ev_queue_shift_next(q_client, "client_close")) != NULL, "Got a client close event");
    is(tap_ev_arg(event, "this"), client,                                                        "It's the 1st client");

    is(tap_ev_queue_length(q_httpd),                                         0,                "No server events lurking");
    is(tap_ev_queue_length(q_client),                                         0,                "No client events lurking");

    sxe_close(listener);
    return exit_status();
}
Ejemplo n.º 4
0
int
main(int argc, char *argv[]) {
    tap_ev           ev;
    struct object   self;
    struct object * this = &self;
    char            expected[1024];
    pid_t           pid = getpid();

    plan_tests(28);

    MOCK_SET_HOOK(openlog, t_openlog);
    MOCK_SET_HOOK(syslog,  t_syslog);
    q_syslog = tap_ev_queue_new();

    sxe_log_use_syslog("my-program", LOG_NDELAY|LOG_PID, LOG_USER);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "openlog",             "sxe_log_use_syslog() calls openlog()");
    is_eq(tap_ev_arg(ev, "ident"), "my-program",        "sxe_log_use_syslog() calls openlog() with correct 'ident' parameter");
    is(tap_ev_arg(ev, "option"), LOG_NDELAY|LOG_PID,    "sxe_log_use_syslog() calls openlog() with correct 'option' parameter");
    is(tap_ev_arg(ev, "facility"), LOG_USER,            "sxe_log_use_syslog() calls openlog() with correct 'facility' parameter");

    SXEL10("SXEL10");
    snprintf(expected, sizeof expected, "T=%d ------ 1 - SXEL10\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL10() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_ERR,             "SXEL10() maps to LOG_ERR syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL10() is logged correctly");

    SXEL21("SXEL21(%s)", "arg1");
    snprintf(expected, sizeof expected, "T=%d ------ 2 - SXEL21(arg1)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL21() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_WARNING,         "SXEL21() maps to LOG_WARNING syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL21() is logged correctly");

    SXEL32("SXEL32(%s,%d)", "arg1", 22);
    snprintf(expected, sizeof expected, "T=%d ------ 3 - SXEL32(arg1,22)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL32() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_NOTICE,          "SXEL32() maps to LOG_NOTICE syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL32() is logged correctly");

    SXEL43("SXEL43(%s,%d,%u)", "arg1", 22, 44);
    snprintf(expected, sizeof expected, "T=%d ------ 4 - SXEL43(arg1,22,44)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL43() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_INFO,            "SXEL43() maps to LOG_INFO syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL43() is logged correctly");

    SXEL54("SXEL54(%s,%d,%u,%x)", "arg1", 22, 44, 64);
    snprintf(expected, sizeof expected, "T=%d ------ 5 - SXEL54(arg1,22,44,40)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL54() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_DEBUG,           "SXEL54() maps to LOG_DEBUG syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL54() is logged correctly");

    SXEL65("SXEL65(%s,%d,%u,%x,%.2f)", "arg1", 22, 44, 64, 3.1415926);
    snprintf(expected, sizeof expected, "T=%d ------ 6 - SXEL65(arg1,22,44,40,3.14)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL65() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_DEBUG,           "SXEL65() maps to LOG_DEBUG syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL65() is logged correctly");

    this->id = 99;
    SXEL10I("SXEL10I");
    snprintf(expected, sizeof expected, "T=%d     99 1 - SXEL10I\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL10I() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_ERR,             "SXEL10I() maps to LOG_ERR syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL10I() is logged correctly");

    this->id = 98;
    SXEL65I("SXEL65I(%s,%d,%u,%x,%.2f)", "arg1", 22, 44, 64, 3.1415926);
    snprintf(expected, sizeof expected, "T=%d     98 6 - SXEL65I(arg1,22,44,40,3.14)\n", pid);
    ev = tap_ev_queue_shift(q_syslog);
    is_eq(tap_ev_identifier(ev), "syslog",              "SXEL65I() calls syslog()");
    is(tap_ev_arg(ev, "priority"), LOG_DEBUG,           "SXEL65I() maps to LOG_DEBUG syslog level");
    is_eq(tap_ev_arg(ev, "logline"), expected,          "SXEL65I() is logged correctly");

    sxe_log_hook_buffer_prefix(NULL); /* For coverage */
    (void)argc;
    (void)argv;

    return exit_status();
}
Ejemplo n.º 5
0
int
main(void)
{
    SXE_HTTPD                httpd;
    SXE_HTTPD_REQUEST      * request;
    tap_ev                   ev;
    SXE                    * listener;
    SXE                    * c;
    SXE                    * c2;
    char                     buffer[1024];

    tap_plan(24, TAP_FLAG_ON_FAILURE_EXIT, NULL);
    test_sxe_register_and_init(12);

    sxe_httpd_construct(&httpd, 3, 10, 512, 0);

    SXE_HTTPD_SET_HANDLER(&httpd, connect, h_connect);
    SXE_HTTPD_SET_HANDLER(&httpd, request, h_request);
    SXE_HTTPD_SET_HANDLER(&httpd, header,  h_header);
    SXE_HTTPD_SET_HANDLER(&httpd, eoh,     h_eoh);
    SXE_HTTPD_SET_HANDLER(&httpd, body,    h_body);
    SXE_HTTPD_SET_HANDLER(&httpd, respond, h_respond);
    SXE_HTTPD_SET_HANDLER(&httpd, close,   h_close);

    listener = test_httpd_listen(&httpd, "0.0.0.0", 0);

    c = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, NULL);
    sxe_connect(c, "127.0.0.1", SXE_LOCAL_PORT(listener));

    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_connect",      "1st Client connected to HTTPD");
    TEST_SXE_SEND_LITERAL(c, "POST /this/is/a/URL HTTP/1.1\r\nContent-Length: 10\r\n\r\n12345678\r\n", client_sent, q_client, TEST_WAIT, &ev);

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_connect",            "HTTPD: connected");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_request",            "HTTPD: new request");

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_header",             "HTTPD: header event");
    is_strncmp(tap_ev_arg(ev, "key"), "Content-Length", SXE_LITERAL_LENGTH("Content-Length"), "HTTPD: header was 'Connect'");
    is_strncmp(tap_ev_arg(ev, "value"), "10", SXE_LITERAL_LENGTH("10"),                       "HTTPD: header value was 'whatever'");

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_eoh",                "HTTPD: eoh (end of headers) event");

    test_ev_queue_wait_read(q_httpd, TEST_WAIT, &ev, NULL, "h_body", buffer, 10, "HTTPD body handler");
    is_strncmp(buffer, "12345678\r\n", SXE_LITERAL_LENGTH("12345678\r\n"),                    "HTTPD: read correct body");

    /* httpd is still in "req_response" state */
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_respond",            "HTTPD: respond event");

    /* Extra data from client, e.g., "content-length" is wrong and shorter than real packet */
    TEST_SXE_SEND_LITERAL(c, "AB", client_sent, q_client, TEST_WAIT, &ev);

    /* Send another valid request again, the connection is in "sink" mode now, data will get ignored */
    TEST_SXE_SEND_LITERAL(c, "POST /this/is/a/URL HTTP/1.1\r\nContent-Length: 10\r\n\r\n12345678\r\n", client_sent, q_client, TEST_WAIT, &ev);
    test_process_all_libev_events();

    /* In sink mode, no more httpd events */
    is(tap_ev_queue_length(q_httpd), 0, "No lurking httpd events");

    /* New client connection should not be affected */
    c2 = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close);
    sxe_connect(c2, "127.0.0.1", SXE_LOCAL_PORT(listener));

    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_connect",      "2nd Client connected to HTTPD");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_connect",            "HTTPD: connected");

    TEST_SXE_SEND_LITERAL(c2, "GET /simple HTTP/1.1\r\n\r\n", client_sent, q_client, TEST_WAIT, &ev);

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_request",            "HTTPD: new request");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_eoh",                "HTTPD: eoh (end of headers) event");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_respond",            "HTTPD: respond event");
    request = (SXE_HTTPD_REQUEST *)(long)tap_ev_arg(ev, "request");
    sxe_httpd_response_simple(request, h_sent, NULL, 200, "OK", NULL, "Connection", "close", NULL);
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_sent",               "HTTPD: finished responding");
    sxe_close(request->sxe);

#define TEST_200_CLOSE_RESPONSE "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
    test_ev_queue_wait_read(q_client, TEST_WAIT, &ev, c2, "client_read", buffer, SXE_LITERAL_LENGTH(TEST_200_CLOSE_RESPONSE), "client");
    is_strncmp(buffer, TEST_200_CLOSE_RESPONSE, SXE_LITERAL_LENGTH(TEST_200_CLOSE_RESPONSE),  "GET response is a 200 OK with close");
    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_close",        "Got a client close event");

    return exit_status();
}