| /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as | |
| * applicable. | |
| * | |
| * Licensed 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(&readp, &writep, p); | |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); | |
| ABTS_PTR_NOTNULL(tc, readp); | |
| ABTS_PTR_NOTNULL(tc, writep); | |
| rv = apr_file_pipe_timeout_get(readp, &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(&readp, &writep, 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_INT_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_INT_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_INT_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 *)malloc(bytes_per_iteration); | |
| 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_error_check_set(procattr, 1); | |
| ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); | |
| args[0] = "readchild" EXTENSION; | |
| args[1] = NULL; | |
| rv = apr_proc_create(&proc, "./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); | |
| } | |
| 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); | |
| return suite; | |
| } | |