void test_verybasic()
{
	qio_file_t *f = NULL;
	qio_channel_t *writing = NULL;
	qio_channel_t *reading = NULL;
	err_t err; 
	char buf[4] = {0};
	
	//open the tmp file, create a write channel, write our data, and release the channel
  	err = qio_file_open_tmp(&f, 0, NULL);
        assert(!err);
      	err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
        assert(!err);
      	err = qio_channel_write_amt(true, writing, "\xDE\xAD\xBE\xEF", 4);
        assert(!err);
        qio_channel_release(writing);

	//open a read channel to the tmp file, and read back the data.
    	err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
        assert(!err);
      	err = qio_channel_read_amt(true, reading, buf, 4);
        assert(!err);
        qio_channel_release(reading);

	///check that what we wrote is what we read back
	if(memcmp(buf, "\xDE\xAD\xBE\xEF", 4) != 0){ assert(0);}

	//close the file
	qio_file_release(f);
	f = NULL;

	printf("PASS: test_verybasic\n");
}
void write_65k_test()
{
        const char *out = NULL;
	char *p = NULL;
        err_t err;
        qio_file_t *f = NULL;
        qio_channel_t *reading = NULL;
        qio_channel_t *writing = NULL;
        qio_style_t style = qio_style_default();
	int buflen = 65535;
        ssize_t out_len = 0;

        err = qio_file_open_tmp(&f, 0, NULL);
        assert(!err);

        style.binary = 1;
        style.byteorder = QIO_BIG;
        style.str_style = -2;

        err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, &style);
        assert(!err);

	p = (char *)calloc(1, buflen);
	if(!p){ assert(0); }
	memset(p, 'A', buflen);

        err = qio_channel_write_string(true, style.byteorder, style.str_style, writing, p, buflen);
        assert(!err);
        qio_channel_release(writing);
        assert(!err);

        err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
        assert(!err);

	while(1){
        	err = qio_channel_read_string(true, style.byteorder, style.str_style, reading, &out, &out_len, -1);
		if(out){
			if(memcmp(out, p, buflen)!=0){
				assert(0);
			}
			free((void*) out); out=NULL;
		}
		if(err>0){ break; }
	}

        qio_channel_release(reading);

	printf("PASS: wrote 65k to file, read it back ok.\n");

        qio_file_release(f);
        f = NULL;

	free(p);
}
void do_test_utf8(int wchar, char* utf8)
{
  err_t err;
  qio_file_t *f = NULL;
  qio_channel_t *reading = NULL;
  qio_channel_t *writing = NULL;
  int32_t got_wchar;
  int i;
  int len;

  len = strlen(utf8);
  if( len == 0 && wchar == 0 ) len = 1; // read 1-byte null

  //printf("Testing character %x len %i \n", wchar, len);

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_write_char(true, writing, wchar);
  assert(!err);

  qio_channel_release(writing);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  for( i = 0; i < len; i++ ) {
   got_wchar = qio_channel_read_byte(true, reading);
   //printf("Read byte %x\n", got_wchar);
   assert(got_wchar == (unsigned char) utf8[i]);
  }
  assert( -EEOF == qio_channel_read_byte(true, reading) );

  qio_channel_release(reading);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_read_char(true, reading, &got_wchar);
  assert(!err);

  assert(got_wchar == wchar);

  qio_channel_release(reading);
 
  qio_file_release(f);
  f = NULL;

}
void max_width_test()
{
        const char *out = NULL;
        ssize_t out_len = 0;
        err_t err;
        qio_file_t *f = NULL;
        qio_channel_t *reading = NULL;
        qio_channel_t *writing = NULL;
        qio_style_t style = qio_style_default();

        err = qio_file_open_tmp(&f, 0, NULL);
        assert(!err);

        style.binary = 0;
        style.string_format = 1;
        style.max_width_columns = 5;


        err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, &style);
        assert(!err);

        err = qio_channel_print_string(true, writing, "helloworld", 10);
        assert(!err);
        qio_channel_release(writing);
        assert(!err);

        err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
        assert(!err);
        err = qio_channel_scan_string(true, reading, &out, &out_len, -1);
        assert(!err);
        qio_channel_release(reading);
        assert(!err);

        if(strlen(out) != 5){
                printf("FAIL: min_width expecting 11 chars for '%s'\n", out);
                assert(0);
        }

        free((void*) out);

        qio_file_release(f);
        f = NULL;
}
Esempio n. 5
0
void check_bits(int offset, int padding)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  // bitpats is in pairs of data, num bits
  uint64_t bitpats[] = {1,1, 0,1, 1,1, 1,1, // 1011 -> b
                        0,1, 0,1, 1,1, 0,1, // 0010 -> 2
                        2,2, 3,2,           // 1011 -> b
                        2,2, 0,2,           // 1000 -> 8
                        0xffffffffffffffffull,64, // ffff ffff ffff ffff
                        0,6, 0x3f,6,        // 0000 0011 1111 -> 03f
                        0,1, 0xff,8, 0,1, 0x7f,7, 3,3,// 0111 1111 1011 1111 1011 ->7fbfb
                        0,3, 1,2, 0,3,      // 0000 1000 -> 08
                        1,1, 0x8100ff00ff20ff81ull,64, 0,7, // 1100 0000 1000 0000 0111 1111 1000 0000 0111 1111 1001 0000 0111 1111 1100 0000 1000 0000 -> c0807f807f907fc080
                        1,2
                       };

  uint8_t expect[] = {0xb2, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xf7, 0xfb, 0xfb, 0x08, 0xc0, 0x80, 0x7f, 0x80, 0x7f, 0x90, 0x7f, 0xc0, 0x80, 0x40, 0xff, 0x40, 0xff, 0x40};
  qioerr err;
  int i;


  if( verbose ) printf("\nBIT IO TEST AT OFFSET %i PADDING %i\n\n", offset, padding);

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, 0, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  for( i = 0; i < offset; i++ ) {
    err = qio_channel_write_byte(true, writing, 0xc1);
    assert(!err);
  }

  // Write stuff to the file.
  for( i = 0; i < sizeof(bitpats)/(2*sizeof(uint64_t)); i++ ) {
    if( verbose ) printf("Writing %i bits of %llx\n", (int) bitpats[2*i + 1], (long long int) bitpats[2*i]);
    err = qio_channel_write_bits(true, writing, bitpats[2*i], bitpats[2*i + 1]);
    assert(!err);
  }
  if( verbose ) printf("Writing byte 0xff at the end\n");
  err = qio_channel_write_byte(true, writing, 0xff);
  assert(!err);
  if( verbose ) printf("Writing bits 010 at the end\n");
  err = qio_channel_write_bits(true, writing, 2, 3);
  assert(!err);
  if( verbose ) printf("Writing byte 0xff at the end\n");
  err = qio_channel_write_byte(true, writing, 0xff);
  assert(!err);
  if( verbose ) printf("Writing bits 010 at the end\n");
  err = qio_channel_write_bits(true, writing, 2, 3);
  assert(!err);

  for( i = 0; i < padding; i++ ) {
    err = qio_channel_write_byte(true, writing, 0xc1);
    assert(!err);
  }


  qio_channel_release(writing);

  // Read the data a byte at a time.
  err = qio_channel_create(&reading, f, 0, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  for( i = 0; i < offset; i++ ) {
    uint8_t got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert(got == 0xc1);
  }

  // Read stuff from the file.
  for( i = 0; i < sizeof(expect); i++ ) {
    uint8_t got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    if( verbose ) printf("Reading byte expecting %x got %x\n", (int) expect[i], (int) got);
    assert( got == expect[i] );
  }

  for( i = 0; i < padding; i++ ) {
    uint8_t got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert(got == 0xc1);
  }


  qio_channel_release(reading);

  // Read the data with the binary reader.
  err = qio_channel_create(&reading, f, 0, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  for( i = 0; i < offset; i++ ) {
    uint8_t got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert(got == 0xc1);
  }

  // Read stuff from the file.
  for( i = 0; i < sizeof(bitpats)/(2*sizeof(uint64_t)); i++ ) {
    uint64_t got = 0;
    err = qio_channel_read_bits(true, reading, &got, bitpats[2*i + 1]);
    assert(!err);
    if( verbose ) printf("Reading %i bits expecting %llx got %llx\n", (int) bitpats[2*i + 1], (long long int) bitpats[2*i], (long long int) got);
    assert( got == bitpats[2*i] );
  }

  {
    uint8_t got = 0;
    uint64_t b = 0;

    got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert( got == 0xff );
  
    b = 0;
    err = qio_channel_read_bits(true, reading, &b, 3);
    assert(!err);
    assert( b == 2 );
 
    got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert( got == 0xff );
 
    b = 0;
    err = qio_channel_read_bits(true, reading, &b, 3);
    assert(!err);
    assert( b == 2 );
  }

  for( i = 0; i < padding; i++ ) {
    uint8_t got = 0;
    err = qio_channel_read_amt(true, reading, &got, 1);
    assert(!err);
    assert(got == 0xc1);
  }

  qio_channel_release(reading);

  // Close the file.
  qio_file_release(f);
}
void check_mark(char* writepattern, char* readpattern)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  int64_t offset;
  int32_t got;

  err_t err;
  int i;

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, 0, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 0);

  for( i = 0; writepattern[i]; i++ ) {
    switch (writepattern[i]) {
      case 'M':
        err = qio_channel_mark(true, writing);
        break;
      case 'R':
        err = qio_channel_revert(true, writing);
        break;
      case 'C':
        err = qio_channel_commit(true, writing);
        break;
      case 'A':
        err = qio_channel_advance(true, writing, 1);
        break;
      default:
        err = qio_channel_write_byte(true, writing, writepattern[i]);
    }
    assert(!err);
  }

  qio_channel_release(writing);

  // Read the data a byte at a time.
  err = qio_channel_create(&reading, f, 0, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  for( i = 0; readpattern[i]; i++ ) {
    switch (readpattern[i]) {
      case 'M':
        err = qio_channel_mark(true, reading);
        break;
      case 'R':
        err = qio_channel_revert(true, reading);
        break;
      case 'C':
        err = qio_channel_commit(true, reading);
        break;
      case 'A':
        err = qio_channel_advance(true, reading, 1);
        break;
      default:
        got = qio_channel_read_byte(true, reading);
        if( got >= 0 ) assert(got == readpattern[i]);
        else err = -got;
    }
    assert(!err);
  }

  got = qio_channel_read_byte(true, reading);
  assert( got == - EEOF );

  qio_channel_release(reading);

  // Close the file.
  qio_file_release(f);
}
void check_mark_easy(void)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  int64_t offset;

  err_t err;

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, 0, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 0);

  err = qio_channel_write_byte(true, writing, 'a');
  assert(!err);
  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 1);

  err = qio_channel_mark(true, writing);
  assert(!err);

  err = qio_channel_write_byte(true, writing, 'b');
  assert(!err);
  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 2);

  err = qio_channel_revert(true, writing);
  assert(!err);
  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 1);

  err = qio_channel_mark(true, writing);
  assert(!err);

  err = qio_channel_write_byte(true, writing, 'c');
  assert(!err);
  err = qio_channel_offset(true, writing, &offset);
  assert(!err);
  assert(offset == 2);

  err = qio_channel_commit(true, writing);
  assert(!err);
  assert(offset == 2);

  qio_channel_release(writing);

  // Read the data a byte at a time.
  err = qio_channel_create(&reading, f, 0, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  assert('a' == qio_channel_read_byte(true, reading));
  assert('c' == qio_channel_read_byte(true, reading));
  assert(-EEOF == qio_channel_read_byte(true, reading));

  qio_channel_release(reading);

  // Close the file.
  qio_file_release(f);
}
// unbounded_channels <= 0 means no, > 0 means yes
// -1 means advance.
void check_channel(char threadsafe, qio_chtype_t type, int64_t start, int64_t len, int64_t chunksz, qio_hint_t file_hints, qio_hint_t ch_hints, char unbounded_channels, char reopen)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  int64_t offset;
  int64_t usesz;
  int64_t end = start + len;
  int err;
  unsigned char* chunk;
  unsigned char* got_chunk;
  int64_t k;
  ssize_t amt_written;
  ssize_t amt_read;
  char* chhints;
  char* fhints;
  FILE* writefp = NULL;
  FILE* readfp = NULL;
  int memory;
  int64_t ch_end = end;
  char filename[128];
  int fd = -1;

  strcpy(filename,"/tmp/qio_testXXXXXX");

  if( unbounded_channels > 0 ) ch_end = INT64_MAX;

  ch_hints = (ch_hints & ~ QIO_CHTYPEMASK) | type;

  memory = 0;

  if( (file_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ||
      (ch_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ) {
    memory = 1;
  }
  if( memory ) {
    file_hints = (file_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
    ch_hints = (ch_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
  }
  if( memory && type == QIO_CH_ALWAYS_UNBUFFERED ) return;
  if( memory && reopen ) return;
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_FREADFWRITE ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_FREADFWRITE ) return;
  }
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_MMAP ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_MMAP ) return;
  }

  fhints = qio_hints_to_string(file_hints);
  chhints = qio_hints_to_string(ch_hints);
  printf("check_channel(threadsafe=%i, type=%i, start=%lli, len=%lli, chunksz=%lli, file_hints=%s, ch_hints=%s, unbounded=%i, reopen=%i)\n",
         (int) threadsafe,
         (int) type,
         (long long int) start,
         (long long int) len,
         (long long int) chunksz,
         fhints,
         chhints,
         (int) unbounded_channels,
         (int) reopen );
  free(fhints);
  free(chhints);

  chunk = malloc(chunksz);
  got_chunk = malloc(chunksz);

  assert(chunk);
  assert(got_chunk);

  if( memory ) {
    err = qio_file_open_mem_ext(&f, NULL, QIO_FDFLAG_READABLE|QIO_FDFLAG_WRITEABLE|QIO_FDFLAG_SEEKABLE, file_hints, NULL);
    assert(!err);
  } else {
    // Open a temporary file.
    if( reopen ) {
      fd = mkstemp(filename);
      close(fd);
      err = qio_file_open_access(&f, filename, "w", file_hints, NULL);
      assert(!err);
    } else {
      err = qio_file_open_tmp(&f, file_hints, NULL);
      assert(!err);
    }

    // Rewind the file
    if (f->fp ) {
      int got;
      got = fseek(f->fp, start, SEEK_SET);
      assert( got == 0 );
    } else {
      off_t off;

      err = sys_lseek(f->fd, start, SEEK_SET, &off);
      assert(!err);
    }
  }

  // Create a "write to file" channel.
  err = qio_channel_create(&writing, f, ch_hints, 0, 1, start, ch_end, NULL);
  assert(!err);

  // Write stuff to the file.
  for( offset = start; offset < end; offset += usesz ) {
    usesz = chunksz;
    if( offset + usesz > end ) usesz = end - offset;
    // Fill chunk.
    fill_testdata(offset, usesz, chunk);
    // Write chunk.
    if( writefp ) {
      amt_written = fwrite(chunk, 1, usesz, writefp);
    } else {
      err = qio_channel_write(threadsafe, writing, chunk, usesz, &amt_written);
      assert(!err);
    }
    assert(amt_written == usesz);

  }

  // Attempt to write 1 more byte; we should get EEOF
  // if we've restricted the range of the channel.
  // Write chunk.
  if( unbounded_channels > 0) {
    // do nothing
  } else {
    if( writefp ) {
      int got;
      got = fflush(writefp);
      assert(got == 0);
      amt_written = fwrite(chunk, 1, 1, writefp);
      // fwrite might buffer on its own.
      if( amt_written != 0 ) {
        got = fflush(writefp);
        assert(got == EOF);
      }
      assert(errno == EEOF);
    } else {
      if( unbounded_channels < 0 ) {
        int times = -unbounded_channels;
        for( int z = 0; z < times; z++ ) {
          err = qio_channel_advance(threadsafe, writing, 1);
          assert( !err );
        }
      }

      err = qio_channel_write(threadsafe, writing, chunk, 1, &amt_written);
      assert(amt_written == 0);
      assert( err == EEOF );
    }
  }

  qio_channel_release(writing);

  // Reopen the file if we're doing reopen
  if( reopen ) {
    // Close the file.
    qio_file_release(f);
    err = qio_file_open_access(&f, filename, "r", file_hints, NULL);
    assert(!err);
  }

  // Check that the file is the right length.
  if( !memory ) {
    struct stat stats;
    err = sys_fstat(f->fd, &stats);
    assert(!err);
    assert(stats.st_size == end);
  }

  // That was fun. Now start at the beginning of the file
  // and read the data.
  
  // Rewind the file 
  if( !memory ) {
    off_t off;

    sys_lseek(f->fd, start, SEEK_SET, &off);
    assert(!err);
  }

  // Read the data.
  //err = qio_channel_init_file(&reading, type, f, ch_hints, 1, 0, start, end);
  err = qio_channel_create(&reading, f, ch_hints, 1, 0, start, ch_end, NULL);
  assert(!err);

  // Read stuff from the file.
  for( offset = start; offset < end; offset += usesz ) {
    usesz = chunksz;
    if( offset + usesz > end ) usesz = end - offset;
    // Fill chunk.
    fill_testdata(offset, usesz, chunk);
    memset(got_chunk, 0xff, usesz);
    // Read chunk.
    if( readfp ) {
      amt_read = fread(got_chunk, 1, usesz, readfp);
    } else {
      err = qio_channel_read(threadsafe, reading, got_chunk, usesz, &amt_read);
      assert( err == EEOF || err == 0);
    }
    assert(amt_read == usesz);

    // Compare chunk.
    for( k = 0; k < usesz; k++ ) {
      assert(got_chunk[k] == chunk[k]);
    }
  }

  if( readfp ) {
    amt_read = fread(got_chunk, 1, 1, readfp);
    assert( amt_read == 0 );
    assert( feof(readfp) );
  } else {
    if( unbounded_channels < 0 ) {
      int times = -unbounded_channels;
      for( int z = 0; z < times; z++ ) {
        err = qio_channel_advance(threadsafe, reading, 1);
        assert( !err );
      }

      err = qio_channel_advance(threadsafe, reading, -unbounded_channels);
      assert( !err );
    }

    err = qio_channel_read(threadsafe, reading, got_chunk, 1, &amt_read);
    assert( err == EEOF );
  }

  qio_channel_release(reading);
  //err = qio_channel_destroy(&reading);

  // Close the file.
  qio_file_release(f);

  if( reopen ) {
    unlink(filename);
  }

  free(chunk);
  free(got_chunk);
}
void test_scanmatch()
{
  err_t err;
  qio_file_t *f = NULL;
  qio_channel_t *reading = NULL;
  qio_channel_t *writing = NULL;

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_write_char(true, writing, ' ');
  assert(!err);
  err = qio_channel_write_char(true, writing, 'm');
  assert(!err);
  err = qio_channel_write_char(true, writing, 'a');
  assert(!err);
  err = qio_channel_write_char(true, writing, 't');
  assert(!err);
  err = qio_channel_write_char(true, writing, 'c');
  assert(!err);
  err = qio_channel_write_char(true, writing, 'h');
  assert(!err);


  qio_channel_release(writing);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_scan_literal(true, reading, "test", 4, 1);
  assert(err == EFORMAT);
  err = qio_channel_scan_literal(true, reading, "match", 5, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, "match", 5, 1);
  assert(err == EEOF);

  qio_channel_release(reading);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);
  err = qio_channel_scan_literal(true, reading, " match", 5, 1);
  assert(err == 0);

  qio_channel_release(reading);
 
  qio_file_release(f);
  f = NULL;

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_write_char(true, writing, 'a');
  assert(!err);
  err = qio_channel_write_char(true, writing, ' ');
  assert(!err);
  err = qio_channel_write_char(true, writing, 'b');
  assert(!err);

  qio_channel_release(writing);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_scan_literal(true, reading, "ab", 2, 1);
  assert(err == EFORMAT);
  err = qio_channel_scan_literal(true, reading, "a", 1, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, " ", 1, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, "b", 1, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, "a", 1, 1);
  assert(err == EEOF);

  qio_channel_release(reading);

  err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  err = qio_channel_scan_literal(true, reading, "ab", 2, 1);
  assert(err == EFORMAT);
  err = qio_channel_scan_literal(true, reading, "a ", 2, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, "b", 1, 1);
  assert(err == 0);
  err = qio_channel_scan_literal(true, reading, "a", 1, 1);
  assert(err == EEOF);

  qio_channel_release(reading);


  qio_file_release(f);
  f = NULL;
}
/**
 * Test basic ascii functionality
 */
void basicstring_test()
{ 
 	const char *out = NULL;
        ssize_t out_len = 0;
        err_t err;
	int x,y=0;
        qio_file_t *f = NULL;
        qio_channel_t *reading = NULL;
        qio_channel_t *writing = NULL;

	#define NUM_STR_STYLES 12
        qio_style_t styles[NUM_STR_STYLES];

	string_test_t strings[] = { 	
				    { "", 0 },
				    { "a", 1 },
				    { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 255},
				  }; 
        int NUM_STRINGS = sizeof(strings)/sizeof(string_test_t);

        printf("Testing basic string writing/reading\n");

        err = qio_file_open_tmp(&f, 0, NULL);
	assert(!err);

        for(x=0;x<NUM_STR_STYLES;x++) {
          qio_style_init_default(&styles[x]);
        }
        // Set up the styles
        // 0 is default.
        styles[0].binary = 1;
        styles[0].str_style = -1;

        // binary styles.
        styles[1].binary = 1;
        styles[1].str_style = -1;
        styles[2].binary = 1;
        styles[2].str_style = -2;
        styles[3].binary = 1;
        styles[3].str_style = -4;
        styles[4].binary = 1;
        styles[4].str_style = -8;
        styles[5].binary = 1;
        styles[5].str_style = -10;
        styles[6].binary = 1;
        styles[6].str_style = -0x0100; // zero-terminated.
        styles[7].binary = 1;
        styles[7].str_style = -0x01ff;
        styles[8].binary = 1;
        styles[8].str_style = 0xffff; // updated below for STYLE 8!

        styles[9].string_format = QIO_STRING_FORMAT_BASIC;
        styles[9].string_start = '|';
        styles[9].string_end = '+';
        styles[10].string_format = QIO_STRING_FORMAT_CHPL;
        styles[11].string_format = QIO_STRING_FORMAT_JSON;

	for(x=0;x<NUM_STR_STYLES;x++){
          qio_style_t* style = &styles[x];
		for(y=0;y<NUM_STRINGS;y++){
                  string_test_t* string = &strings[y];

                        // make style 8 always use the string length!
                        if( x == 8 ) style->str_style = string->length;

        		err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, style);
			assert(!err);

                        //printf("Writing string '%s' with style %i\n", string->string, x);

                        if( style->binary ) 
                          err = qio_channel_write_string(true, style->byteorder, style->str_style, writing, string->string, string->length);
                        else
                          err = qio_channel_print_string(true, writing, string->string, string->length);

			assert(!err);
        		qio_channel_release(writing);

			err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, style);
			assert(!err);

                        //printf("Reading string '%s' with style %i\n", string->string, x);
                        if( style->binary ) 
                          err = qio_channel_read_string(true, style->byteorder, style->str_style, reading, &out, &out_len, -1);
                        else
                          err = qio_channel_scan_string(true, reading, &out, &out_len, -1);
			assert(!err);
			qio_channel_release(reading);

                        //printf("Got '%s' expect '%s'\n", out, string->string);

			if(memcmp(out, string->string, string->length) != 0){
				printf("FAIL: style %d, string='%s'\n", x, string->string);
				free((void*) out);
				assert(0);
			}

			//printf("PASS: style %d\n", x);
			if(out){ free((void*) out); out=NULL; }
		}
	}

        qio_file_release(f);
        f = NULL;
       
        printf("PASS: basic string test\n");
#undef NUM_STR_STYLES
#define NUM_STRINGS 1
}
void test_quoted_string_maxlength(void)
{
  qio_style_t style = qio_style_default();
  qio_channel_t *reading;
  qio_channel_t *writing;
  qio_file_t *f = NULL;
  err_t err;
  const char* inputs[8][16] = {
    { "",     // original string
      "\"\"", // maxlen = 1
      "\"\"", // maxlen = 2
      "\"\"", // maxlen = 3
      "\"\"", // maxlen = 4
      "\"\"", // maxlen = 5
      "\"\"", // maxlen = 6
      "\"\"", // maxlen = 7
      "\"\"", // maxlen = 8
      "\"\"", // maxlen = 9
      "\"\"", // maxlen = 10
      "\"\"", // maxlen = 11
      "\"\"", // maxlen = 12
      "\"\"", // maxlen = 13
      "\"\"", // maxlen = 14
      NULL
    },
    { "a",     // original string
      "\"a\"", // maxlen = 1
      "\"a\"", // maxlen = 2
      "\"a\"", // maxlen = 3
      "\"a\"", // maxlen = 4
      "\"a\"", // maxlen = 5
      "\"a\"", // maxlen = 6
      "\"a\"", // maxlen = 7
      "\"a\"", // maxlen = 8
      "\"a\"", // maxlen = 9
      "\"a\"", // maxlen = 10
      "\"a\"", // maxlen = 11
      "\"a\"", // maxlen = 12
      "\"a\"", // maxlen = 13
      "\"a\"", // maxlen = 14
      NULL
    },
    { "ab",     // original string
      "\"ab\"", // maxlen = 1
      "\"ab\"", // maxlen = 2
      "\"ab\"", // maxlen = 3
      "\"ab\"", // maxlen = 4
      "\"ab\"", // maxlen = 5
      "\"ab\"", // maxlen = 6
      "\"ab\"", // maxlen = 7
      "\"ab\"", // maxlen = 8
      "\"ab\"", // maxlen = 9
      "\"ab\"", // maxlen = 10
      "\"ab\"", // maxlen = 11
      "\"ab\"", // maxlen = 12
      "\"ab\"", // maxlen = 13
      "\"ab\"", // maxlen = 14
      NULL
    },
    { "abc",     // original string
      "\"abc\"", // maxlen = 1
      "\"abc\"", // maxlen = 2
      "\"abc\"", // maxlen = 3
      "\"abc\"", // maxlen = 4
      "\"abc\"", // maxlen = 5
      "\"abc\"", // maxlen = 6
      "\"abc\"", // maxlen = 7
      "\"abc\"", // maxlen = 8
      "\"abc\"", // maxlen = 9
      "\"abc\"", // maxlen = 10
      "\"abc\"", // maxlen = 11
      "\"abc\"", // maxlen = 12
      "\"abc\"", // maxlen = 13
      "\"abc\"", // maxlen = 14
      NULL
    },
    { "abcd",     // original string
      "\"\"...", // maxlen = 1
      "\"\"...", // maxlen = 2
      "\"\"...", // maxlen = 3
      "\"\"...", // maxlen = 4
      "\"\"...", // maxlen = 5
      "\"abcd\"", // maxlen = 6
      "\"abcd\"", // maxlen = 7
      "\"abcd\"", // maxlen = 8
      "\"abcd\"", // maxlen = 9
      "\"abcd\"", // maxlen = 10
      "\"abcd\"", // maxlen = 11
      "\"abcd\"", // maxlen = 12
      "\"abcd\"", // maxlen = 13
      "\"abcd\"", // maxlen = 14
      NULL
    },

    { "123456789",     // original string
      "\"\"...",       // maxlen = 1
      "\"\"...",       // maxlen = 2
      "\"\"...",       // maxlen = 3
      "\"\"...",       // maxlen = 4
      "\"\"...",       // maxlen = 5
      "\"1\"...",      // maxlen = 6
      "\"12\"...",     // maxlen = 7
      "\"123\"...",    // maxlen = 8
      "\"1234\"...",   // maxlen = 9
      "\"12345\"...",  // maxlen = 10
      "\"123456789\"", // maxlen = 11
      "\"123456789\"", // maxlen = 12
      "\"123456789\"", // maxlen = 13
      "\"123456789\"", // maxlen = 14
      NULL
    },

    { "\x01X\x01Y", // original string
      "\"\"...",       // maxlen = 1
      "\"\"...",       // maxlen = 2
      "\"\"...",       // maxlen = 3
      "\"\"...",       // maxlen = 4
      "\"\"...",       // maxlen = 5
      "\"\"...",       // maxlen = 6
      "\"\"...",       // maxlen = 7
      "\"\"...",       // maxlen = 8
      "\"\\x01\"...",  // maxlen = 9
      "\"\\x01X\"...", // maxlen = 10
      "\"\\x01X\"...", // maxlen = 11
      "\"\\x01X\\x01Y\"", // maxlen = 12
      "\"\\x01X\\x01Y\"", // maxlen = 13
      "\"\\x01X\\x01Y\"", // maxlen = 14
      NULL
    },
    { NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
    }
  };

  char buf[50] = {0};
  int i,j;

  style.binary=0;
  style.string_start = '"';
  style.string_end = '"';
  
  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  for( i = 0; inputs[i][0]; i++ ) {
    const char* input = inputs[i][0];
    ssize_t input_len = strlen(input);
    for( j = 1; inputs[i][j]; j++ ) {
      const char* expect = inputs[i][j];
      ssize_t expect_len = strlen(expect);
      qio_truncate_info_t ti;
      const char* got = NULL;
      ssize_t truncate_len = (j<input_len)?(j):(input_len);
      style.string_format = QIO_STRING_FORMAT_CHPL;
      style.max_width_columns = j;

      ti.max_columns = style.max_width_columns;
      ti.max_chars = SSIZE_MAX;
      ti.max_bytes = SSIZE_MAX;
      
      // check that qio_quote_string gives correct string when
      // used in a no-quote mode
      if( i != 6 ) {
        // but not for test 6 since the control characters are weird.
        err = qio_quote_string(0, 0, QIO_STRING_FORMAT_WORD, input, input_len, &got, &ti);
        assert(!err);
        assert(ti.ret_columns == truncate_len);
        assert(ti.ret_chars == truncate_len);
        assert(truncate_len == strlen(got));
        assert( 0 == memcmp(got, input, truncate_len) );
        free((void*) got);
      }

      // Now, check that qio_quote_string returns the correct string.
      err = qio_quote_string(style.string_start, style.string_end, style.string_format, input, input_len, &got, &ti);
      assert(!err);

      assert(ti.ret_columns == strlen(inputs[i][1]) || ti.ret_columns <= j);
      assert(ti.ret_bytes == expect_len);
      assert(ti.ret_bytes == strlen(got));
      assert( 0 == strcmp(got, expect) );
      free((void*) got);

      // Now, check that the quoting works correctly when writing.

      err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, &style);
      assert(!err);
      err = qio_channel_print_string(true, writing, input, input_len);	
      assert(!err);
      qio_channel_release(writing);

      err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, &style);
      assert(!err);
      err = qio_channel_read_amt(true, reading, buf, expect_len);
      assert(!err);

      qio_channel_release(reading);

      //printf("Got %s expect %s\n", buf, expect);
      assert( memcmp(buf, expect, expect_len) == 0 );
    }
  }

  qio_file_release(f);

  printf("PASS: quoted max length\n");
}
void string_escape_tests()
{
	qio_style_t style = qio_style_default();
	qio_channel_t *reading;
	qio_channel_t *writing;
	qio_file_t *f = NULL;
	err_t err;
        const char* inputs[2][4] = { {"a \"\\b\x01", // original string
                                      "\"a \\\"\\\\b\x01\"", // simple encoding
                                      "\"a \\\"\\\\b\\x01\"", // chapel encoding
                                      "\"a \\\"\\\\b\\u0001\"", // JSON encoding
                                     },
                                     { NULL, NULL, NULL, NULL }
                                   };
	char buf[50] = {0};
        int i,j;

	style.binary=0;
	style.string_start = '"';
	style.string_end = '"';
	
	err = qio_file_open_tmp(&f, 0, NULL);
        assert(!err);
        
        for( i = 0; inputs[i][0]; i++ ) {
          const char* input = inputs[i][0];
          ssize_t input_len = strlen(input);
          for( j = 1; j < 4; j++ ) {
            const char* expect = inputs[i][j];
            ssize_t expect_len = strlen(expect);
            style.string_format = j;

            err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, &style);
            assert(!err);
            err = qio_channel_print_string(true, writing, input, input_len);	
            assert(!err);
            qio_channel_release(writing);

            err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, &style);
            assert(!err);
            err = qio_channel_read_amt(true, reading, buf, expect_len);
            assert(!err);
     
            qio_channel_release(reading);

            //printf("Got %s expect %s\n", buf, expect);
            assert( memcmp(buf, expect, expect_len) == 0 );

            // Check that we can read it in again.
            err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, &style);
            assert(!err);

            {
              const char* got = NULL;
              ssize_t got_len = 0;
              err = qio_channel_scan_string(true, reading, &got, &got_len, -1);
              assert(!err);

              //printf("Read back %s expect %s\n", got, input);
              assert( got_len == input_len );
              assert( memcmp(got, input, got_len) == 0 );

              free((void*) got);
            }
     
            qio_channel_release(reading);
          }
        }

        qio_file_release(f);

        printf("PASS: simple escape\n");
}
void test_endian(void)
{
  // We write (hex) 00 0102 03040506 0708091011121314
  // as big endian and little endian, and then we check
  // that the data is what we expected.
  
  err_t err;
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  int64_t offset;
  int len = 15;
  uint8_t n0 = 0;
  uint16_t n1 = 0x0102;
  uint32_t n2 = 0x03040506;
  uint64_t n3 = 0x0708091011121314LL;
  const char* expect_le = "\x00\x02\x01\x06\x05\x04\x03"
                          "\x14\x13\x12\x11\x10\x09\x08\x07";
  const char* expect_be = "\x00\x01\x02\x03\x04\x05\x06"
                          "\x07\x08\x09\x10\x11\x12\x13\x14";
  char got[16];
  int i;
  int b_order;
  const char* expect;

  printf("Testing endian functions\n");

  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  for( i = 0; i < 2; i++ ) {
    if( i == 0 ) {
      b_order = QIO_BIG;
      expect = expect_be;
    } else {
      b_order = QIO_LITTLE;
      expect = expect_le;
    }

    // Create a "write to file" channel.
    err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
    assert(!err);

    err = qio_channel_write_uint8(true, writing, n0);
    assert(!err);
    err = qio_channel_write_uint16(true, b_order, writing, n1);
    assert(!err);
    err = qio_channel_write_uint32(true, b_order, writing, n2);
    assert(!err);
    err = qio_channel_write_uint64(true, b_order, writing, n3);
    assert(!err);

    err = qio_channel_offset(true, writing, &offset);
    assert(!err);

    assert( offset == len );

    qio_channel_release(writing);
    writing = NULL;

    // Create a "read from file" channel.
    err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
    assert(!err);

    err = qio_channel_read_amt(true, reading, got, len);
    assert(!err);

    // Check that we read back what we wrote.
    assert( 0 == memcmp(got, expect, len) );

    qio_channel_release(reading);
    reading = NULL;
  }

  // Close the file.
  qio_file_release(f);
  f = NULL;


}
void test_printscan_float(void)
{
  err_t err;
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;

#define NSTYLES 9
  qio_style_t styles[NSTYLES];

  const char* zero[] = { // writing 0
                        "0.0", // default style
                        "0.000", // %f precision 3
                        "0.000e+00", // %e precision 3
                        "+0.00000", // showpoint, showplus
                        "0x0p+0", // hex
                        "0X0.000P+0", // hex, uppercase, showpoint, prec 3
                        "0", // %g, 4 significant digits
                        "0.0000", // %f, showpoint, precision 4
                        "0.0000e+00", // %e, showpoint, precision 4
                       };

  const char* one[] = { // writing 1
                        "1.0", // default style
                        "1.000", // %f precision 3
                        "1.000e+00", // %e precision 3
                        "+1.00000", // showpoint, showplus
                        "0x1p+0", // hex
                        "0X1.000P+0", // hex, uppercase, showpoint, prec 3
                        "1", // %g, 4 significant digits
                        "1.0000", // %f, showpoint, precision 4
                        "1.0000e+00", // %e, showpoint, precision 4
                       };

  const char* plusinf[] = { // writing +infinity
                        "inf", // default style
                        "inf", // %f precision 3
                        "inf", // %e precision 3
                        "+inf", // showpoint, showplus
                        "inf", // hex
                        "INF", // hex, uppercase, showpoint, prec 3
                        "inf", // %g, 4 significant digits
                        "inf", // %f, showpoint, precision 4
                        "inf", // %e, showpoint, precision 4
                       };
  const char* minusinf[] = { // writing +infinity
                        "-inf", // default style
                        "-inf", // %f precision 3
                        "-inf", // %e precision 3
                        "-inf", // showpoint, showplus
                        "-inf", // hex
                        "-INF", // hex, uppercase, showpoint, prec 3
                        "-inf", // %g, 4 significant digits
                        "-inf", // %f, showpoint, precision 4
                        "-inf", // %e, showpoint, precision 4
                       };
  const char* nan[] = { // writing nan
                        "nan", // default style
                        "nan", // %f precision 3
                        "nan", // %e precision 3
                        "+nan", // showpoint, showplus
                        "nan", // hex
                        "NAN", // hex, uppercase, showpoint, prec 3
                        "nan", // %g, 4 significant digits
                        "nan", // %f, showpoint, precision 4
                        "nan", // %e, showpoint, precision 4
                       };
  const char* nnan[] = { // writing nan
                        "nan", // default style
                        "nan", // %f precision 3
                        "nan", // %e precision 3
                        "-nan", // showpoint, showplus
                        "nan", // hex
                        "NAN", // hex, uppercase, showpoint, prec 3
                        "nan", // %g, 4 significant digits
                        "nan", // %f, showpoint, precision 4
                        "nan", // %e, showpoint, precision 4
                       };
  const char* x[] = { // writing 1.125e+300
                        "1.125e+300", // default style
                        "1124999999999999984717009863215819639889402246251651042717325796981054812448928754462634938945285169790751774504176833459124149130131831874871128930639759966162906545922666490056516990646142904182469580674455306426256469801266735686696548991733655898546719119989659797590624855449025294035374384873472.000", // %f precision 3
                        "1.125e+300", // %e precision 3
                        "+1.12500e+300", // showpoint, showplus
                        "0x1.ae0c41900844fp+996", // hex
                        "0X1.AE1P+996", // hex, uppercase, showpoint, prec 3
                        "1.125e+300", // %g, 4 significant digits
                        "1124999999999999984717009863215819639889402246251651042717325796981054812448928754462634938945285169790751774504176833459124149130131831874871128930639759966162906545922666490056516990646142904182469580674455306426256469801266735686696548991733655898546719119989659797590624855449025294035374384873472.0000", // %f, showpoint, precision 4
                        "1.1250e+300", // %e, showpoint, precision 4
                       };
  const char* y[] = { // writing 6.125e-300,
                        "6.125e-300", // default style
                        "0.000", // %f precision 3
                        "6.125e-300", // %e precision 3
                        "+6.12500e-300", // showpoint, showplus
                        "0x1.0685051469a5p-994", // hex
                        "0X1.068P-994", // hex, uppercase, showpoint, prec 3
                        "6.125e-300", // %g, 4 significant digits
                        "0.0000", // %f, showpoint, precision 4
                        "6.1250e-300", // %e, showpoint, precision 4
                       };
  const char* large[] = { // writing 1.7976931348623157e+308
                        "1.79769e+308", // default style
                        "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000", // %f precision 3
                        "1.798e+308", // %e precision 3
                        "+1.79769e+308", // showpoint, showplus
                        "0x1.fffffffffffffp+1023", // hex
                        "0X2.000P+1023", // hex, uppercase, showpoint, prec 3
                        "1.798e+308", // %g, 4 significant digits
                        "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0000", // %f, showpoint, precision 4
                        "1.7977e+308", // %e, showpoint, precision 4
                       };
  const char* small[] = { // writing 2.2250738585072014e-308
                        "2.22507e-308", // default style
                        "0.000", // %f precision 3
                        "2.225e-308", // %e precision 3
                        "+2.22507e-308", // showpoint, showplus
                        "0x1p-1022", // hex
                        "0X1.000P-1022", // hex, uppercase, showpoint, prec 3
                        "2.225e-308", // %g, 4 significant digits
                        "0.0000", // %f, showpoint, precision 4
                        "2.2251e-308", // %e, showpoint, precision 4
                       };
  double mynan = NAN; // 0.0*(1.0/0.0);
  double posnan = copysign(mynan, 1.0);
  double negnan = copysign(mynan, -1.0);
  double nums[] = {0.0, 1.0,
                   1.0/0.0 /*+inf*/, -1.0/0.0 /*-inf*/,
                   posnan,
                   negnan,
                   1.125e+300, 6.125e-300,
                   1.7976931348623157e+308, 2.2250738585072014e-308 };

  const char** expect_arr[] = { zero, one, plusinf, minusinf, nan, nnan,
                                x,y,large,small, NULL };
  char got[500];
  char sep[4] = {0,0,0,0};
  ssize_t amt_read;
  int i,j;

  //printf("Testing text float I/O\n");

  for( i = 0; i < NSTYLES; i++ ) {
    qio_style_init_default(&styles[i]);
    styles[i].showpointzero = 0;
  }
  // Set up the styles
  // 0 is default.
  styles[0].showpointzero = 1;

  // 1 has %f, precision 3
  styles[1].precision = 3;
  styles[1].realfmt = 1;

  // 2 has %e, precision 3
  styles[2].precision = 3;
  styles[2].realfmt = 2;

  // 3 has showpoint, showplus
  styles[3].showpoint = 1;
  styles[3].showplus = 1;

  // 4 has base 16
  styles[4].base = 16;

  // 5 has base 16, uppercase
  styles[5].base = 16;
  styles[5].uppercase = 1;
  styles[5].showpoint = 1;
  styles[5].precision = 3;

  // 6 %g, 4 significant digits
  styles[6].precision = 4;
  styles[6].realfmt = 0;

  // 7 has %f showpoint, precision 4
  styles[7].showpoint = 1;
  styles[7].precision = 4;
  styles[7].realfmt = 1;

  // 7 has %e showpoint, precision 4
  styles[8].showpoint = 1;
  styles[8].precision = 4;
  styles[8].realfmt = 2;


  // Open a temporary file.
  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  for( i = 0; expect_arr[i]; i++ ) {
    for( j = 0; j < NSTYLES; j++ ) {
      const char* expect = expect_arr[i][j];
      double num = nums[i];
      qio_style_t* style = &styles[j];
      double got_num;

      //printf("Expect '%s' testing %e style %i\n", expect, num, j);

      memset(got, 0, sizeof(got));

      // Create a "write to file" channel.
      err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, style);
      assert(!err);

      err = qio_channel_print_float(true, writing, &num, 8);
      assert(!err);

      // write a separator so we can use the same file..
      err = qio_channel_write_amt(true, writing, sep, sizeof(sep));
      assert(!err);

      qio_channel_release(writing);
      writing = NULL;

      // Create a "read from file" channel.
      err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, style);
      assert(!err);

      err = qio_channel_read(true, reading, got, sizeof(got), &amt_read);
      assert(err == EEOF);

      //printf("Got    '%s'\n", got);

      assert( 0 == strcmp(got, expect) );

      qio_channel_release(reading);
      reading = NULL;


      // Try scanning our number.
      // Create a "read from file" channel.
      if( i < 7 ) {
        err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
        assert(!err);

        got_num = 0;
        err = qio_channel_scan_float(true, reading, &got_num, 8);
        assert(!err);

        //printf("Got    '%s'         %e\n", got, got_num);
        //assert( got_num == num );

        qio_channel_release(reading);
        reading = NULL;
      }
    }
  }

  // Close the file.
  qio_file_release(f);
  f = NULL;

  printf("PASS: text float I/O\n");
#undef NSTYLES
}
void test_printscan_int(void)
{
  err_t err;
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;

#define NSTYLES 10
  qio_style_t styles[NSTYLES];

  const char* zero[] = { // writing 0
                        "0", // default style
                        "  0", // min_width = 3, pad = ' '
                        "000", // min_width = 3, pad = 0
                        "0  ", // min_width = 3, pad = ' ', leftjustify
                        "0", // hex
                        "0x0", // hex, showbase
                        "   0", // binary, min_width = 4
                        "0b0", // binary, showbase
                        " 0b0", // binary, showbase, showplus=pad
                        "+0X0" // hex, showbase, showplus=+, uppercase
                       };

  const char* one[] = { // writing 1
                        "1", // default style
                        "  1", // min_width = 3, pad = ' '
                        "001", // min_width = 3, pad = 0
                        "1  ", // min_width = 3, pad = ' ', leftjustify
                        "1", // hex
                        "0x1", // hex, showbase
                        "   1", // binary, min_width = 4
                        "0b1", // binary, showbase
                        " 0b1", // binary, showbase, showplus=pad
                        "+0X1" // hex, showbase, showplus=+, uppercase
                       };
  const char* hundred[] = { // writing 100 = 0x64 = 0b1100100
                        "100", // default style
                        "100", // min_width = 3, pad = ' '
                        "100", // min_width = 3, pad = 0
                        "100", // min_width = 3, pad = ' ', leftjustify
                        "64", // hex
                        "0x64", // hex, showbase
                        "1100100", // binary, min_width = 4
                        "0b1100100", // binary, showbase
                        " 0b1100100", // binary, showbase, showplus=pad
                        "+0X64" // hex, showbase, showplus=+, uppercase
                          };
  const char* big[] = { // writing 2^63-1 = 9223372036854775807 = 0x7FFFFFFFFFFFFFFF = 0b111111111111111111111111111111111111111111111111111111111111111
                        "9223372036854775807", // default style
                        "9223372036854775807", // min_width = 3, pad = ' '
                        "9223372036854775807", // min_width = 3, pad = 0
                        "9223372036854775807", // min_width = 3, pad = ' ', leftjustify
                        "7fffffffffffffff", // hex
                        "0x7fffffffffffffff", // hex, showbase
                        "111111111111111111111111111111111111111111111111111111111111111", // binary, min_width = 4
                        "0b111111111111111111111111111111111111111111111111111111111111111", // binary, showbase
                        " 0b111111111111111111111111111111111111111111111111111111111111111", // binary, showbase, showplus=pad
                        "+0X7FFFFFFFFFFFFFFF" // hex, showbase, showplus=+, uppercase
                          };
  const char* small[] = { // writing -2^63 = -9223372036854775808 = -0x8000000000000000 = -0b1000000000000000000000000000000000000000000000000000000000000000
                        "-9223372036854775808", // default style
                        "-9223372036854775808", // min_width = 3, pad = ' '
                        "-9223372036854775808", // min_width = 3, pad = 0
                        "-9223372036854775808", // min_width = 3, pad = ' ', leftjustify
                        "-8000000000000000", // hex
                        "-0x8000000000000000", // hex, showbase
                        "-1000000000000000000000000000000000000000000000000000000000000000", // binary, min_width = 4
                        "-0b1000000000000000000000000000000000000000000000000000000000000000", // binary, showbase
                        "-0b1000000000000000000000000000000000000000000000000000000000000000", // binary, showbase, showplus=pad
                        "-0X8000000000000000" // hex, showbase, showplus=+, uppercase
                          };

  int64_t nums[] = {0, 1, 100, INT64_MAX, INT64_MIN, 0};
  const char** expect_arr[] = { zero, one, hundred, big, small, NULL};
  char got[500];
  char sep[4] = {0,0,0,0};
  ssize_t amt_read;
  int i,j;

  printf("Testing text integer I/O\n");

  for( i = 0; i < NSTYLES; i++ ) {
    qio_style_init_default(&styles[i]);
  }
  // Set up the styles
  // 0 is default.

  // 1 has minwidth 3, pad ' '
  styles[1].min_width_columns = 3;
  styles[1].pad_char = ' ';

  // 2 has minwidth 3, pad 0
  styles[2].min_width_columns = 3;
  styles[2].pad_char = '0';

  // 3 has minwidth 3, pad ' ', leftjustify
  styles[3].min_width_columns = 3;
  styles[3].pad_char = ' ';
  styles[3].leftjustify = 1;

  // 4 has defaults, hex
  styles[4].base = 16;
  styles[4].prefix_base = 0;

  // 5 has defaults, hex, showbase
  styles[5].base = 16;
  styles[5].prefix_base = 1;

  // 6 has defaults, binary, min_width=4
  styles[6].base = 2;
  styles[6].min_width_columns = 4;
  styles[6].prefix_base = 0;

  // 7 has defaults, binary, showbase
  styles[7].base = 2;
  styles[7].prefix_base = 1;

  // 8 has showbase, showplus = pad, binary
  styles[8].base = 2;
  styles[8].prefix_base = 1;
  styles[8].showplus = 2;

  // 9 has showbase, showplus, hex, uppercase
  styles[9].base = 16;
  styles[9].prefix_base = 1;
  styles[9].showplus = 1;
  styles[9].uppercase = 1;

  // Open a temporary file.
  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  for( i = 0; expect_arr[i]; i++ ) {
    for( j = 0; j < NSTYLES; j++ ) {
      const char* expect = expect_arr[i][j];
      int64_t num = nums[i];
      qio_style_t* style = &styles[j];
      int64_t got_num;

      //printf("Expect '%s' testing 0x%" PRIx64 " style %i\n", expect, num, j);

      memset(got, 0, sizeof(got));

      // Create a "write to file" channel.
      err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, style);
      assert(!err);

      err = qio_channel_print_int(true, writing, &num, 8, true);
      assert(!err);

      // write a separator so we can use the same file..
      err = qio_channel_write_amt(true, writing, sep, sizeof(sep));
      assert(!err);

      qio_channel_release(writing);
      writing = NULL;

      // Create a "read from file" channel.
      err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
      assert(!err);

      err = qio_channel_read(true, reading, got, sizeof(got), &amt_read);
      assert(err == EEOF);

      //printf("Got    '%s' expect '%s'\n", got, expect);
      //
      assert( 0 == strcmp(got, expect) );

      qio_channel_release(reading);
      reading = NULL;


      // Try scanning our number.
      // Create a "read from file" channel.
      err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, style);
      assert(!err);

      got_num = 0;
      err = qio_channel_scan_int(true, reading, &got_num, 8, 1);
      assert(!err);

      //printf("Got    '%s'         0x%" PRIx64 "\n", got, got_num);
      assert( got_num == num );

      qio_channel_release(reading);
      reading = NULL;
    }
  }

  // Close the file.
  qio_file_release(f);
  f = NULL;
#undef NSTYLES
}
Esempio n. 16
0
void check_write_read_pat(int width, int num, int pat, qio_chtype_t type, qio_hint_t file_hints, qio_hint_t ch_hints, char reopen)
{
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  qioerr err;
  int memory;
  char* chhints;
  char* fhints;
  char filename[128];
  int fd = -1;
  uint64_t one = 1;
  uint64_t mask = (one << width) - 1;
  if( width == 64 ) mask = -1;

  strcpy(filename,"/tmp/qio_bits_testXXXXXX");

  ch_hints = (ch_hints & ~ QIO_CHTYPEMASK) | type;
  memory = 0;

  if( (file_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ||
      (ch_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ) {
    memory = 1;
  }
  if( memory ) {
    file_hints = (file_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
    ch_hints = (ch_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY;
  }
  if( memory && type == QIO_CH_ALWAYS_UNBUFFERED ) return;
  if( memory && reopen ) return;
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_FREADFWRITE ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_FREADFWRITE ) return;
  }
  if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_MMAP ) {
    if( (file_hints & QIO_METHODMASK) != QIO_METHOD_MMAP ) return;
  }

  fhints = qio_hints_to_string(file_hints);
  chhints = qio_hints_to_string(ch_hints);
  if( verbose )
    printf("check_write_read_pat(width=%i, num=%i, pat=%i, type=%i, file_hints=%s %i, ch_hints=%s %i, reopen=%i)\n",
         width, num, pat, type,
         fhints, (int) file_hints, chhints, (int) ch_hints,  (int) reopen);

  qio_free(fhints);
  qio_free(chhints);

  if( memory ) {
    err = qio_file_open_mem_ext(&f, NULL, QIO_FDFLAG_READABLE|QIO_FDFLAG_WRITEABLE|QIO_FDFLAG_SEEKABLE, file_hints, NULL);
    assert(!err);
  } else {
    if( reopen ) {
      fd = mkstemp(filename);
      close(fd);
      err = qio_file_open_access(&f, filename, "w", file_hints, NULL);
      assert(!err);

    } else {
      err = qio_file_open_tmp(&f, 0, NULL);
      assert(!err);
    }
  }

  err = qio_channel_create(&writing, f, ch_hints, 0, 1, 0, INT64_MAX, NULL);
  assert(!err);

  for( int i = 0; i < num; i++ ) {
    uint64_t x;
    if( pat == 0 ) {
      if( i & 1 ) x = mask;
      else x = 0;
    } else {
      x = ((uint64_t) i) & mask;
    }
    { // check offset
      int64_t off = qio_channel_offset_unlocked(writing);
      assert( off == (width * i + 7) / 8 );
    }
    err = qio_channel_write_bits(false, writing, x, width);
    assert(!err);
  }
  qio_channel_release(writing);

  // Reopen the file if we're doing reopen
  if( reopen ) {
    // Close the file.
    qio_file_release(f);
    err = qio_file_open_access(&f, filename, "r", file_hints, NULL);
    assert(!err);
  }
  // Rewind the file 
  if( !memory ) {
    off_t off;

    sys_lseek(f->fd, 0, SEEK_SET, &off);
    assert(!err);
  }



  err = qio_channel_create(&reading, f, ch_hints, 1, 0, 0, INT64_MAX, NULL);
  assert(!err);

  for( int i = 0; i < num; i++ ) {
    uint64_t got = 0;
    uint64_t x;
    if( pat == 0 ) {
      if( i & 1 ) x = mask;
      else x = 0;
    } else {
      x = ((uint64_t) i) & mask;
    }
    { // check offset
      int64_t off = qio_channel_offset_unlocked(reading);
      assert( off == (width * i + 7) / 8 );
    }
    //printf("Reading at %lli\n", (long long int) qio_channel_offset_unlocked(reading));
    err = qio_channel_read_bits(false, reading, &got, width);
    assert(!err);
    //printf("Got  %lli\n", (long long int) got);
    if( got != x ) {
      printf("Fails (%i %i %i) at %i got=%llx expect=%llx\n", width, num, pat, i, (unsigned long long int) got, (unsigned long long int) x);
      assert(got == x);
      break;
    }
  }

  qio_channel_release(reading);

  // Close the file.
  qio_file_release(f);

  if( reopen ) {
    unlink(filename);
  }
}
Esempio n. 17
0
int main(int argc, char** argv)
{
  int offset, padding;
  int width, logn, maxlogn;
  qio_chtype_t type;
  qio_hint_t hints[] = {QIO_METHOD_DEFAULT, QIO_METHOD_READWRITE, QIO_METHOD_PREADPWRITE, QIO_METHOD_FREADFWRITE, QIO_METHOD_MEMORY, QIO_METHOD_MMAP, QIO_METHOD_MMAP|QIO_HINT_PARALLEL, QIO_METHOD_PREADPWRITE | QIO_HINT_NOFAST};
  int nhints = sizeof(hints)/sizeof(qio_hint_t);
  int file_hint, ch_hint;

  {
    //for( file_hint = 0; file_hint < nhints; file_hint++ ) {
    //  check_write_read_pat(1, 262144, 0, 0, file_hint, file_hint, 0);
    //}

    //check_write_read_pat(32,4096,0,3,QIO_METHOD_PREADPWRITE,0,1);
    //check_write_read_pat(32,4096,0,3,0,0,1);
    //exit(0);
//check_write_read_pat(width=32, num=4096, pat=0, type=3, file_hints=default_type default, ch_hints=buffered default, reopen=1)

    // Run unit tests.
    for( offset = 0; offset < 63; offset++ ) {
      for( padding = 0; padding < 63; padding++ ) {
        check_bits(offset, padding);
      }
    }

    maxlogn = 19;
    if( valgrind ) maxlogn = 10;

    for( logn = 0; logn < maxlogn; logn+=9 ) {
      for( width = 1; width <= 64; width++ ) {
        for( file_hint = 0; file_hint < nhints; file_hint++ ) {
          ch_hint = file_hint;
          type = 0;
          check_write_read_pat(width,1 << logn,0,type,file_hint,ch_hint,0);
          check_write_read_pat(width,1 << logn,1,type,file_hint,ch_hint,1);
        }
      }
    }
  }

  // Do extra testing that showed a bug at one point...
  if( !valgrind ) {

    int i;
    int n = 256*1024*1024;

    qio_file_t* f;
    qio_channel_t* writing;
    qio_channel_t* reading;
    uint64_t got;
    uint64_t expect;
    qioerr err;
    

    //qbytes_iobuf_size = 256;

    err = qio_file_open_mem(&f, NULL, NULL);
    assert(!err);
    //err = qio_file_open_access(&f, "test.bin", "w+", 0, NULL);
    //assert(!err);

    err = qio_channel_create(&writing, f, 0, 0, 1, 0, INT64_MAX, NULL);
    assert(!err);

    for( i = 0; i < n; i++ ) {
      err = qio_channel_write_bits(false, writing, i & 0x1f, 5);
      //err = qio_channel_write_bits(false, writing, 0x1f, 5);
      assert(!err);
    }

    qio_channel_release(writing);

    if( argc > 2 ) {
      err = qio_channel_create(&reading, f, 0, 1, 0, 0, INT64_MAX, NULL);
      assert(!err);

      for( i = 0; i < n; i++ ) {
        got = 0;
        err = qio_channel_read_bits(false, reading, &got, 5);
        assert(!err);
        expect = i & 0x1f;
        //expect = 0x1f;
        if( got != expect ) {
          printf("Failed at i=%i got %llx expect %llx\n", i, (long long int) got, (long long int) expect);
          assert( got == expect );
        }
      }

      qio_channel_release(reading);
    }

    qio_file_release(f);
  }

  printf("qio_bits_test PASS\n");

  return 0;
}
void test_readwriteint(void)
{
  err_t err;
  qio_file_t* f;
  qio_channel_t* writing;
  qio_channel_t* reading;
  const char* testdata[] = {"\x00\x00\x00\x00\x00\x00\x00\x00",
                            "\xff\xff\xff\xff\xff\xff\xff\xff",
                            "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f",
                            "\x01\x02\x03\x04\x05\x06\x07\x08",
                            "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8",
                            NULL };
  int sizes[] = {1, -1, 2, -2, 4, -4, 8, -8, 0};
  int byteorder[] = {QIO_NATIVE, QIO_BIG, QIO_LITTLE, 0};
  char got[16];
  int i,j,k;

  printf("Testing binary integer I/O\n");

  // Open a temporary file.
  err = qio_file_open_tmp(&f, 0, NULL);
  assert(!err);

  for( i = 0; testdata[i]; i++ ) {
    for( j = 0; sizes[j]; j++ ) {
      for( k = 0; byteorder[k]; k++ ) {
        const char* data = testdata[i];
        int sz = sizes[j];
        int b_order = byteorder[k];
        int len;

        len = sz;
        if( len < 0 ) len = - sz;


        memset(got, 0, sizeof(got));

        // Create a "write to file" channel.
        err = qio_channel_create(&writing, f, QIO_CH_BUFFERED, 0, 1, 0, INT64_MAX, NULL);
        assert(!err);

        err = qio_channel_write_int(true, b_order, writing, data, len, sz < 0);
        assert(!err);

        qio_channel_release(writing);
        writing = NULL;

        // Create a "read from file" channel.
        err = qio_channel_create(&reading, f, QIO_CH_BUFFERED, 1, 0, 0, INT64_MAX, NULL);
        assert(!err);


        err = qio_channel_read_int(true, b_order, reading, got, len, sz < 0);
        assert(!err);

        // Check that we read back what we wrote.
        assert( 0 == memcmp(got, data, len) );

        qio_channel_release(reading);
        reading = NULL;
      }
    }
  }

  // Close the file.
  qio_file_release(f);
  f = NULL;

}