| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 <stdlib.h> |
| |
| #include "testutil.h" |
| #include "apr_file_io.h" |
| #include "apr_errno.h" |
| #include "apr_general.h" |
| #include "apr_lib.h" |
| #include "apr_thread_proc.h" |
| #include "apr_strings.h" |
| |
| static apr_file_t *readp = NULL; |
| static apr_file_t *writep = NULL; |
| |
| static void create_pipe(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| |
| rv = apr_file_pipe_create(&readp, &writep, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_PTR_NOTNULL(tc, readp); |
| ABTS_PTR_NOTNULL(tc, writep); |
| } |
| |
| static void close_pipe(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| apr_size_t nbytes = 256; |
| char buf[256]; |
| |
| rv = apr_file_close(readp); |
| rv = apr_file_close(writep); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_file_read(readp, buf, &nbytes); |
| ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv)); |
| } |
| |
| static void set_timeout(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| apr_interval_time_t timeout; |
| |
| rv = apr_file_pipe_create_pools(&readp, &writep, APR_WRITE_BLOCK, p, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_PTR_NOTNULL(tc, readp); |
| ABTS_PTR_NOTNULL(tc, writep); |
| |
| rv = apr_file_pipe_timeout_get(writep, &timeout); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_ASSERT(tc, "Timeout mismatch, expected -1", timeout == -1); |
| |
| rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_file_pipe_timeout_get(readp, &timeout); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_ASSERT(tc, "Timeout mismatch, expected 1 second", |
| timeout == apr_time_from_sec(1)); |
| } |
| |
| static void read_write(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| char *buf; |
| apr_size_t nbytes; |
| |
| nbytes = strlen("this is a test"); |
| buf = (char *)apr_palloc(p, nbytes + 1); |
| |
| rv = apr_file_pipe_create_pools(&readp, &writep, APR_WRITE_BLOCK, p, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_PTR_NOTNULL(tc, readp); |
| ABTS_PTR_NOTNULL(tc, writep); |
| |
| rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| if (!rv) { |
| rv = apr_file_read(readp, buf, &nbytes); |
| ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); |
| ABTS_SIZE_EQUAL(tc, 0, nbytes); |
| } |
| } |
| |
| static void read_write_notimeout(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| char *buf = "this is a test"; |
| char *input; |
| apr_size_t nbytes; |
| |
| nbytes = strlen("this is a test"); |
| |
| rv = apr_file_pipe_create(&readp, &writep, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_PTR_NOTNULL(tc, readp); |
| ABTS_PTR_NOTNULL(tc, writep); |
| |
| rv = apr_file_write(writep, buf, &nbytes); |
| ABTS_SIZE_EQUAL(tc, strlen("this is a test"), nbytes); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| nbytes = 256; |
| input = apr_pcalloc(p, nbytes + 1); |
| rv = apr_file_read(readp, input, &nbytes); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| ABTS_SIZE_EQUAL(tc, strlen("this is a test"), nbytes); |
| ABTS_STR_EQUAL(tc, "this is a test", input); |
| } |
| |
| static void test_pipe_writefull(abts_case *tc, void *data) |
| { |
| int iterations = 1000; |
| int i; |
| int bytes_per_iteration = 8000; |
| char *buf = (char *)calloc(bytes_per_iteration, 1); |
| char responsebuf[128]; |
| apr_size_t nbytes; |
| int bytes_processed; |
| apr_proc_t proc = {0}; |
| apr_procattr_t *procattr; |
| const char *args[2]; |
| apr_status_t rv; |
| apr_exit_why_e why; |
| |
| rv = apr_procattr_create(&procattr, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, |
| APR_CHILD_BLOCK); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV); |
| APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv); |
| |
| rv = apr_procattr_error_check_set(procattr, 1); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| args[0] = "readchild" EXTENSION; |
| args[1] = NULL; |
| rv = apr_proc_create(&proc, TESTBINPATH "readchild" EXTENSION, args, NULL, procattr, p); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_file_pipe_timeout_set(proc.in, apr_time_from_sec(10)); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| rv = apr_file_pipe_timeout_set(proc.out, apr_time_from_sec(10)); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| i = iterations; |
| do { |
| rv = apr_file_write_full(proc.in, buf, bytes_per_iteration, NULL); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| } while (--i); |
| |
| free(buf); |
| |
| rv = apr_file_close(proc.in); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| |
| nbytes = sizeof(responsebuf); |
| rv = apr_file_read(proc.out, responsebuf, &nbytes); |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); |
| bytes_processed = (int)apr_strtoi64(responsebuf, NULL, 10); |
| ABTS_INT_EQUAL(tc, iterations * bytes_per_iteration, bytes_processed); |
| |
| ABTS_ASSERT(tc, "wait for child process", |
| apr_proc_wait(&proc, NULL, &why, APR_WAIT) == APR_CHILD_DONE); |
| |
| ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT); |
| } |
| |
| static void wait_pipe(abts_case *tc, void *data) |
| { |
| apr_status_t rv; |
| apr_interval_time_t delay = 200000; |
| apr_time_t start_time; |
| apr_time_t end_time; |
| apr_size_t nbytes; |
| |
| rv = apr_file_pipe_create(&readp, &writep, p); |
| APR_ASSERT_SUCCESS(tc, "Couldn't create pipe", rv); |
| |
| rv = apr_file_pipe_timeout_set(readp, delay); |
| APR_ASSERT_SUCCESS(tc, "Couldn't set pipe timeout", rv); |
| |
| start_time = apr_time_now(); |
| rv = apr_file_pipe_wait(readp, APR_WAIT_READ); |
| ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); |
| |
| end_time = apr_time_now(); |
| ABTS_ASSERT(tc, "apr_file_pipe_wait() waited for the time out", end_time - start_time >= delay); |
| |
| nbytes = 4; |
| rv = apr_file_write(writep, "data", &nbytes); |
| APR_ASSERT_SUCCESS(tc, "Couldn't write to pipe", rv); |
| |
| rv = apr_file_pipe_wait(readp, APR_WAIT_READ); |
| APR_ASSERT_SUCCESS(tc, "Wait for pipe failed", rv); |
| } |
| |
| abts_suite *testpipe(abts_suite *suite) |
| { |
| suite = ADD_SUITE(suite) |
| |
| abts_run_test(suite, create_pipe, NULL); |
| abts_run_test(suite, close_pipe, NULL); |
| abts_run_test(suite, set_timeout, NULL); |
| abts_run_test(suite, close_pipe, NULL); |
| abts_run_test(suite, read_write, NULL); |
| abts_run_test(suite, close_pipe, NULL); |
| abts_run_test(suite, read_write_notimeout, NULL); |
| abts_run_test(suite, test_pipe_writefull, NULL); |
| abts_run_test(suite, close_pipe, NULL); |
| abts_run_test(suite, wait_pipe, NULL); |
| |
| return suite; |
| } |
| |