int main( int argc , char ** argv) { util_install_signals(); { const char * file = argv[1]; test_fortio_is_instance( file ); test_fortio_safe_cast( file ); test_assert_util_abort("fortio_safe_cast", test_fortio_unsafe_cast, NULL); test_existing_read( file ); test_not_existing_read( ); test_open_close_read( file ); test_wrapper( file ); test_fread_truncated_head(); test_fread_truncated_data(); test_fread_truncated_tail(); test_fread_invalid_tail(); test_fseek(); test_at_eof(); test_write( "/tmp/path/does/not/exist" , false ); { test_work_area_type * work_area = test_work_area_alloc("ecl_fortio.write" ); util_make_path("path"); test_write( "path/file.x" , true ); test_work_area_free( work_area ); } exit(0); } }
int check_output_files(Test *test, int *out_fds, char **out_files) { int i; int res = 0; for (i = 0; i < test->nfiles; i++) { int eof = 0; size_t offset = 0; /* Seek back to the start */ if (-1 == lseek(out_fds[i], 0, SEEK_SET)) { fprintf(stderr, "Couldn't seek on %s : %s\n", out_files[i], strerror(errno)); res = -1; continue; } /* Check the contents */ if (read_data(out_fds[i], test->in_len, &offset, 0, &eof) < 0) { res = -1; continue; } if (eof) { fprintf(stderr, "Got EOF on %s after %ld bytes (expected %ld)\n", out_files[i], (long) offset, (long) test->in_len); res = -1; continue; } if (offset != test->in_len) { fprintf(stderr, "Didn't read expected number of bytes from %s. " "Got %ld expected %ld", out_files[i], (long) offset, (long) test->in_len); res = -1; continue; } } /* Check that we are now at EOF for all the files, i.e. nothing unexpected got tagged on the end */ if (!res) { res = test_at_eof(test->nfiles, out_fds, out_files); } /* Close all the file descriptors */ for (i = 0; i < test->nfiles; i++) { if (0 != close(out_fds[i])) { fprintf(stderr, "Error closing %s : %s\n", out_files[i], strerror(errno)); res = -1; } } return res; }
int run_poll_loop(Test *test, int in_fd, int *fifo_fds, char **fifos) { struct pollfd polls[MAX_READERS + 2]; /* 1 for in_fd, 1 for chld_fds[0] */ int poll_idx[MAX_READERS + 2];/* Which file is in each poll slot */ /* in_fd should be polled */ int in_polled = test->in_type == IN_FILE ? 0 : 1; /* in_fd is a slow pipe */ int in_slow = test->in_type == IN_SLOW_PIPE ? 1 : 0; size_t fifo_offsets[MAX_READERS]; /* Offsets into the outputs */ size_t fifo_totals[MAX_READERS]; /* Target length for each output */ unsigned int seg_num; /* Test segment counter */ size_t sent = 0; /* number of bytes sent to in_fd so far */ ssize_t bytes; int i; for (i = 0; i < test->npipes; i++) fifo_offsets[i] = fifo_totals[i] = 0; for (seg_num = 0; seg_num < test->nsegs; seg_num++) { TestSegment *seg = &test->segs[seg_num]; /* current test segment */ int done = 0; /* Set targets for each output */ for (i = 0; i < test->npipes; i++) { if (fifo_fds[i] >= 0 && seg->bytes[i] > 0) { fifo_totals[i] += seg->bytes[i]; } } while (!done) { int npolls = 0, ready; size_t max_offset = 0; int noutputs = test->nfiles; /* number of live outputs */ /* Add SIGCHLD file descriptor to poll. This is written to by the signal handler. It ensures that poll returns when the child exits. This prevents a potential deadlock when poll waits forever on in_fd as there is nothing reading from it any more. */ poll_idx[npolls] = IDX_CHLDFD; polls[npolls].fd = chld_fds[0]; polls[npolls].events = POLLIN; polls[npolls++].revents = 0; /* Add outputs to poll. Also count them and find out which has read the most, for the slow pipe */ for (i = 0; i < test->npipes; i++) { if (fifo_fds[i] < 0) continue; /* Skip if already closed */ noutputs++; if (max_offset < fifo_offsets[i]) max_offset = fifo_offsets[i]; if (fifo_offsets[i] < fifo_totals[i] /* Poll if something to receive */ || seg->bytes[i] < 0) { /* or about to close */ poll_idx[npolls] = i; polls[npolls].fd = fifo_fds[i]; polls[npolls].events = POLLIN; polls[npolls++].revents = 0; } } /* Add in_fd to poll if necessary */ if (in_polled) { /* Input is a pipe */ if (sent < test->in_len) { /* There is more data to send */ if (!in_slow || max_offset >= sent) { /* Either a fast pipe, or one of the outputs has caught up */ poll_idx[npolls] = IDX_IN_FD; polls[npolls].fd = in_fd; polls[npolls].events = POLLOUT|POLLERR|POLLHUP; polls[npolls++].revents = 0; } } else { /* no more to send, close in_fd */ if (0 != close(in_fd)) { perror("Closing pipe"); return -1; } in_polled = 0; /* don't try to poll in_fd any more */ } } /* Do the poll. Wait forever unless we got a SIGCHLD, in which case we are just draining any remaining data from the output pipes. */ do { ready = poll(polls, npolls, got_chld ? 100 : -1); } while (ready < 0 && EINTR == errno); if (ready == 0 && got_chld) { /* Shouldn't happen */ fprintf(stderr, "Child exited, but timed out waiting for data\n"); return -1; } for (i = 0; i < npolls && ready > 0; i++) { if (0 == polls[i].revents) continue; /* Not ready */ --ready; if (poll_idx[i] == IDX_IN_FD) { /* Can send more data */ /* Work out how much to send. For IN_PIPE, as much as possible. For IN_SLOW_PIPE, a few bytes at a time. */ size_t l = (in_slow ? (sent + test->slow_pipe_rate < test->in_len ? sent + test->slow_pipe_rate : test->in_len) : test->in_len); assert(in_polled && polls[i].fd == in_fd); /* Send some data */ bytes = gen_data("pipe", in_fd, l, &sent, 1, noutputs > 0 ? 0 : 1); if (bytes < 0) { fprintf(stderr, "Error sending data to test process : %s\n", strerror(errno)); return -1; } } else if (poll_idx[i] >= 0) { /* Can read data */ int polled = poll_idx[i]; /* Get the index of the ready output */ assert(fifo_fds[polled] == polls[i].fd); if (seg->bytes[polled] < 0) { /* Decided to close instead */ if (0 != close(fifo_fds[polled])) { perror("Closing pipe"); return -1; } fifo_fds[polled] = -1; /* Mark as closed */ noutputs--; } else { /* Try to read */ int eof = 0; bytes = read_data(fifo_fds[polled], fifo_totals[polled], &fifo_offsets[polled], 1, &eof); if (bytes < 0) return -1; if (eof) { fprintf(stderr, "Got unexpected EOF on fifo %s\n", fifos[polled]); return -1; } } } else { /* Got a SIGCHLD */ assert(poll_idx[i] == IDX_CHLDFD); /* Drain the pipe to prevent an endless poll loop */ drain_signal_pipe(); } } /* Are we there yet? */ done = 1; for (i = 0; i < test->npipes; i++) { if ((fifo_fds[i] >= 0 && fifo_offsets[i] < fifo_totals[i]) || (seg->bytes[i] < 0 && fifo_fds[i] >= 0)) { done = 0; break; } } } /* End of poll loop */ } /* End of seg loop */ if (in_polled) { /* Try to push out any remaining data */ if (sent < test->in_len) { size_t left = test->in_len - sent; fprintf(stderr, "Pushing ...\n"); if (gen_data("pipe", in_fd, test->in_len, &sent, 0, test->nfiles == 0 ? 1 : 0) != left) { fprintf(stderr, "gen_data returned error\n"); return -1; } } /* Ensure in_fd has been closed */ if (0 != close(in_fd)) { perror("Closing pipe"); return -1; } } /* By now, any unclosed pipes should be at EOF, so test for that */ return test_at_eof(test->npipes, fifo_fds, fifos); }