### ----------------------------------------------------
### -- GIO
### -- Licenses: GPL-3.0
### -- Authors: clifton.wood@gmail.com
### -- File: dev-t/08-file.t
### ----------------------------------------------------
### -- Chunk 2 of 2
 my $c  = 'test_load_bytes_async';
      my $l  = $c.chars;
      my $r  = GLib::FileUtils.write($fd, $c, $l);
      is $r, $l,                               'Wrote proper number of bytes to temporary file';
      native-close($fd);

      $bytes-async-data.loop      = GLib::MainLoop.new(False);
      $bytes-async-data.file      = GIO::File.new_for_path($fn);
      $bytes-async-data.file.load_bytes_async( &load-bytes-cb );
      $bytes-async-data.loop.run;

      is $l, $bytes-async-data.bytes.get-size, 'Async bytes read matches expected value';
      my ($d, $) = $bytes-async-data.bytes.get-data;

      is $d, $c,                               'Async data matches expected value';
      .delete && .unref given $bytes-async-data.file;
      $bytes-async-data.unref;
    }
  }
}

sub compare-buffer ($a, $b) {
  unless $a.defined {
    # diag $b.defined.not ?? 'Passed' !! 'A is NULL but not B';
    return $b.defined.not;
  }
  unless $b.defined {
    # diag $a.defined.not ?? 'Passed' !! 'B is NULL but not A';
    return $a.defined.not;
  }

  for ^$a.elems {
    unless $a[$_] = $b[$_] {
      diag "Failed comparison at position $_";
      return False;
    }
  }
  return True;
}

sub test-writev-helper (
  @vectors           = (),
  $use-bytes-written = False,
  $ec                = Buf,
  $el                = 0
) {
  use GLib::Roles::Pointers;

  my $iostream;
  my $file = GIO::File.new_tmp('g_file_writev_XXXXXX', $iostream);
  ok  $file,                          '$file is non-Nil';
  ok  $iostream,                      '$iostream is non-Nil';

  my $ubw = $iostream.get-output-stream.writev-all(@vectors);
  nok $ERROR,                         'No errors detected during .writev-all';
  if $ERROR {
    diag $ERROR.gist;
    diag $ERROR.message;
  }
  ok  $ubw.defined,                   '.writev-all returned defined values';
  is  $ubw,     $el,                  'Bytes actually written matches expected length'
    if $use-bytes-written;

  my $res = $iostream.close;
  nok $ERROR,                         'No errors detected when closing the iostream';
  ok  $res,                           '.close returned True';
  $iostream.unref;

  my ($contents, $length, $) = $file.load_contents($contents, $length, $);
  nok $ERROR,                         'No errors detected when loading contents';
  # cw: Tricky, since $contents CAN be undefined, $length is the only way
  #     to properly determine if the underlying routine returned true.
  ok  $length.defined,                '.load-contents returned defined values';
  is  $length   // 0,   $el,          'Returned length matches expected value';
  ok  compare-buffer($contents, $ec), 'Contents match expected value';

  .delete && .unref with $file;
}

sub test-writev {
  my $buffer = CArray[uint8].new(1, 2, 3, 4, 5,
                                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                                 1, 2, 3);

  my @vectors = (
    GOutputVector.new($buffer,                   5),
    GOutputVector.new($buffer.&subarray(5),     12),
    GOutputVector.new($buffer.&subarray(5 + 12), 3)
  );

  subtest 'WriteV', {
    test-writev-helper(@vectors, True, $buffer, $buffer.elems);
  }
}

sub test-writev-no-bytes-written {
  my $buffer = CArray[uint8].new(1, 2, 3, 4, 5,
                                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                                 1, 2, 3);

  my @vectors = (
    GOutputVector.new($buffer,                   5),
    GOutputVector.new($buffer.&subarray(5),     12),
    GOutputVector.new($buffer.&subarray(5 + 12), 3)
  );

  subtest 'WriteV, no bytes written', {
    test-writev-helper(@vectors, False, $buffer, $buffer.elems);
  }
}

sub test-writev-no-vectors {
  subtest 'WriteV, No vectors', {
    test-writev-helper;
  }
}

sub test-writev-empty-vectors {
  my @vectors = GOutputVector.new xx 3;

  subtest 'WriteV, Empty vectors', {
    test-writev-helper(@vectors, True, Nil, 0);
  }
}

sub test-writev-too-big-vectors {
  subtest 'WriteV, Too Big Vectors', {
    my $iostream;
    my $buffer    = Pointer[uint8].new(1);
    my @vectors   = GOutputVector.new($buffer, G_MAXSIZE / 2) xx 3;
    my $file      = GIO::File.new_tmp('g_file_writev_XXXXXX', $iostream);

    ok  no-error,                                       'No error generating tmpfile name';
    ok  $iostream,                                      'IOStream returned from .new_tmp is defined';

    my $ostream = $iostream.get-output-stream;
    my $ubw     = $ostream.writev-all(@vectors);
    ok  $ERROR,                                         'Error detected during call to .writev-all';
    #is  $ERROR.domain, $G_IO_ERROR,                     'Error is in the G_IO_ERROR domain';
    is  $ERROR.code,   G_IO_ERROR_INVALID_ARGUMENT.Int, 'Error code is G_IO_ERROR_INVALID_ARGUMENT';
    # cw: Not checking bytes_writte == 0, due to the way this API works as opposed to C
    nok $ubw.defined,                               'Call to .writev-all returned no defined values';

    my  ($res, $contents, $length) = ( $iostream.close );
    ok  no-error,                                   'No error detected when closing iostream';
    ok  $res,                                       '.close operation returned True';
    ok  compare-buffer($contents, $length),         'Buffer comparison succeeded';

    .delete && .unref with $file;
  }
}

# cw: -XXX- 20201013
#
# Continue from L#1324 of original -- Efforts marred by the lack of ability
# to use a sub-CArray. Efforts on this file will be paused until this
# is rectified or a workaround can be discovered.

# cw: Not quite in, yet.
# sub test-build-attribute-list-for-copy {
#   my @test-flags = (
#     G_FILE_COPY_NONE,
#     G_FILE_COPY_TARGET_DEFAULT_PERMS,
#     G_FILE_COPY_ALL_METADATA,
#     G_FILE_COPY_ALL_METADATA +| G_FILE_COPY_TARGET_DEFAULT_PERMS,
#   );
#
#   subtest 'Build attribute list for copy', {
#     my $i;
#     my $tmpfile = GIO::File.new_tmp(
#       'tmp-build-attribute-list-for-copyXXXXXX',
#       $i
#     );
#
#     ok  no-error, 'No error encountered when generating tmpfile name';
#     $i.close;
#     nok no-error, 'No error encountered when closing iostream';
#
#     for @test-flags {
#       my $atrs = $tmpfile.build_attribute_list_for_copy($_);
#       ...
#     }
#   }
# }

GLib::Test.init;

test-basic;
test-parent;
test-type;
test-parse-name;

# cw: These tests are not currently being performed due to the lack of
#     ability to create a sub-buffer or sub-array that can be passed to
#     a NativeCall routine.
test-create-delete($_) for 0, 1, 10, 25, 4096;

test-measure;

# cw: MoarVM panic: native callback ran on thread (140662838081088) unknown to MoarVM
#&test-measure-async();

test-load-bytes;
&test-load-bytes-async();

test-writev;
test-writev-no-bytes-written;
test-writev-no-vectors;
test-writev-empty-vectors;
test-writev-too-big-vectors;


