Example #1
0
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);
  }
}
Example #2
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;
}
Example #3
0
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);
}