3 use Test::More tests => 274;
4 use Imager::Test qw(is_image);
5 # for SEEK_SET etc, Fcntl doesn't provide these in 5.005_03
9 BEGIN { use_ok(Imager => ':all') };
11 -d "testout" or mkdir "testout";
15 Imager->open_log(log => "testout/t07iolayer.log");
18 # start by testing io buffer
20 my $data="P2\n2 2\n255\n 255 0\n0 255\n";
21 my $IO = Imager::io_new_buffer($data);
22 my $im = Imager::i_readpnm_wiol($IO, -1);
24 ok($im, "read from data io");
26 open(FH, ">testout/t07.ppm") or die $!;
29 my $IO2 = Imager::io_new_fd( $fd );
30 Imager::i_writeppm_wiol($im, $IO2);
34 open(FH, "<testimg/penguin-base.ppm");
38 my $IO3 = Imager::IO->new_buffer($data);
40 $im = Imager::i_readpnm_wiol($IO3, -1);
42 ok($im, "read from buffer, for compare");
45 open(FH, "<testimg/penguin-base.ppm") or die $!;
48 my $IO4 = Imager::IO->new_fd( $fd );
49 my $im2 = Imager::i_readpnm_wiol($IO4, -1);
53 ok($im2, "read from file, for compare");
55 is(i_img_diff($im, $im2), 0, "compare images");
58 my $IO5 = Imager::io_new_bufchain();
59 Imager::i_writeppm_wiol($im, $IO5);
60 my $data2 = Imager::io_slurp($IO5);
63 ok($data2, "check we got data from bufchain");
65 my $IO6 = Imager::io_new_buffer($data2);
66 my $im3 = Imager::i_readpnm_wiol($IO6, -1);
68 is(Imager::i_img_diff($im, $im3), 0, "read from buffer");
73 my ($size, $maxread) = @_;
74 my $out = substr($work, $pos, $maxread);
79 my ($size, $maxread) = @_;
80 my $out = substr($work, $pos, $maxread);
84 my $IO7 = Imager::IO->new_cb(undef, \&io_reader, undef, undef);
85 ok($IO7, "making readcb object");
86 my $im4 = Imager::i_readpnm_wiol($IO7, -1);
87 ok($im4, "read from cb");
88 ok(Imager::i_img_diff($im, $im4) == 0, "read from cb image match");
91 $IO7 = Imager::io_new_cb(undef, \&io_reader2, undef, undef);
92 ok($IO7, "making short readcb object");
93 my $im5 = Imager::i_readpnm_wiol($IO7, -1);
94 ok($im4, "read from cb2");
95 is(Imager::i_img_diff($im, $im5), 0, "read from cb2 image match");
99 substr($work, $pos, $pos+length $what) = $what;
100 $pos += length $what;
110 my $IO8 = Imager::io_new_cb(\&io_writer, undef, undef, \&io_close);
111 ok($IO8, "making writecb object");
114 ok(Imager::i_writeppm_wiol($im, $IO8), "write to cb");
115 # I originally compared this to $data, but that doesn't include the
117 is($work, $data2, "write image match");
118 ok($did_close, "did close");
120 # with a short buffer, no closer
121 my $IO9 = Imager::io_new_cb(\&io_writer, undef, undef, undef, 1);
122 ok($IO9, "making short writecb object");
125 ok(Imager::i_writeppm_wiol($im, $IO9), "write to short cb");
126 is($work, $data2, "short write image match");
129 my $buf_data = "Test data";
130 my $io9 = Imager::io_new_buffer($buf_data);
131 is(ref $io9, "Imager::IO", "check class");
133 is($io9->raw_read($work, 4), 4, "read 4 from buffer object");
134 is($work, "Test", "check data read");
135 is($io9->raw_read($work, 5), 5, "read the rest");
136 is($work, " data", "check data read");
137 is($io9->raw_seek(5, SEEK_SET), 5, "seek");
138 is($io9->raw_read($work, 5), 4, "short read");
139 is($work, "data", "check data read");
140 is($io9->raw_seek(-1, SEEK_CUR), 8, "seek relative");
141 is($io9->raw_seek(-5, SEEK_END), 4, "seek relative to end");
142 is($io9->raw_seek(-10, SEEK_CUR), -1, "seek failure");
146 my $io = Imager::IO->new_bufchain();
147 is(ref $io, "Imager::IO", "check class");
148 is($io->raw_write("testdata"), 8, "check write");
149 is($io->raw_seek(-8, SEEK_CUR), 0, "seek relative");
151 is($io->raw_read($work, 8), 8, "check read");
152 is($work, "testdata", "check data read");
153 is($io->raw_seek(-3, SEEK_END), 5, "seek end relative");
154 is($io->raw_read($work, 5), 3, "short read");
155 is($work, "ata", "check read data");
156 is($io->raw_seek(4, SEEK_SET), 4, "absolute seek to write some");
157 is($io->raw_write("testdata"), 8, "write");
158 is($io->raw_seek(0, SEEK_CUR), 12, "check size");
162 my $data = Imager::io_slurp($io);
163 is($data, "testtestdata", "check we have the right data");
166 { # callback failure checks
167 my $fail_io = Imager::io_new_cb(\&fail_write, \&fail_read, \&fail_seek, undef, 1);
170 my $read_result = $fail_io->raw_read($buffer, 10);
171 is($read_result, undef, "read failure undef in scalar context");
172 my @read_result = $fail_io->raw_read($buffer, 10);
173 is(@read_result, 0, "empty list in list context");
174 $read_result = $fail_io->raw_read2(10);
175 is($read_result, undef, "raw_read2 failure (scalar)");
176 @read_result = $fail_io->raw_read2(10);
177 is(@read_result, 0, "raw_read2 failure (list)");
179 my $write_result = $fail_io->raw_write("test");
180 is($write_result, -1, "failed write");
182 my $seek_result = $fail_io->raw_seek(-1, SEEK_SET);
183 is($seek_result, -1, "failed seek");
186 { # callback success checks
187 my $good_io = Imager::io_new_cb(\&good_write, \&good_read, \&good_seek, undef, 1);
190 my $read_result = $good_io->raw_read($buffer, 10);
191 is($read_result, 8, "read success (scalar)");
192 is($buffer, "testdata", "check data");
193 my @read_result = $good_io->raw_read($buffer, 10);
194 is_deeply(\@read_result, [ 8 ], "read success (list)");
195 is($buffer, "testdata", "check data");
196 $read_result = $good_io->raw_read2(10);
197 is($read_result, "testdata", "read2 success (scalar)");
198 @read_result = $good_io->raw_read2(10);
199 is_deeply(\@read_result, [ "testdata" ], "read2 success (list)");
203 my $eof_io = Imager::io_new_cb(undef, \&eof_read, undef, undef, 1);
205 my $read_result = $eof_io->raw_read($buffer, 10);
206 is($read_result, 0, "read eof (scalar)");
207 is($buffer, '', "check data");
208 my @read_result = $eof_io->raw_read($buffer, 10);
209 is_deeply(\@read_result, [ 0 ], "read eof (list)");
210 is($buffer, '', "check data");
214 my $none_io = Imager::io_new_cb(undef, undef, undef, undef, 0);
215 is($none_io->raw_write("test"), -1, "write with no writecb should fail");
217 is($none_io->raw_read($buffer, 10), undef, "read with no readcb should fail");
218 is($none_io->raw_seek(0, SEEK_SET), -1, "seek with no seekcb should fail");
222 { # make sure we croak when trying to write a string with characters over 0xff
223 # the write callback shouldn't get called
224 skip("no native UTF8 support in this version of perl", 2)
226 my $io = Imager::io_new_cb(\&good_write, undef, undef, 1);
227 my $data = chr(0x100);
228 is(ord $data, 0x100, "make sure we got what we expected");
231 $io->raw_write($data);
233 ok($@, "should have croaked")
237 { # 0.52 left some debug code in a path that wasn't tested, make sure
238 # that path is tested
239 # http://rt.cpan.org/Ticket/Display.html?id=20705
240 my $io = Imager::io_new_cb
243 print "# write $_[0]\n";
247 print "# read $_[0], $_[1]\n";
250 sub { print "# seek\n"; 0 },
251 sub { print "# close\n"; 1 });
253 is($io->raw_read($buffer, 10), 10, "read 10");
254 is($buffer, "xxxxxxxxxx", "read value");
255 ok($io->raw_write("foo"), "write");
256 is($io->raw_close, 0, "close");
260 { # fd_seek write failure
262 or skip("No /dev/full", 3);
263 open my $fh, "> /dev/full"
264 or skip("Can't open /dev/full: $!", 3);
265 my $io = Imager::io_new_fd(fileno($fh));
266 ok($io, "make fd io for /dev/full");
267 Imager::i_clear_error();
268 is($io->raw_write("test"), -1, "fail to write");
269 my $msg = Imager->_error_as_msg;
270 like($msg, qr/^write\(\) failure: /, "check error message");
273 # /dev/full succeeds on seek on Linux
279 { # fd_seek seek failure
280 my $seekfail = "testout/t07seekfail.dat";
281 open my $fh, "> $seekfail"
282 or skip("Can't open $seekfail: $!", 3);
283 my $io = Imager::io_new_fd(fileno($fh));
284 ok($io, "make fd io for $seekfail");
286 Imager::i_clear_error();
287 is($io->raw_seek(-1, SEEK_SET), -1, "shouldn't be able to seek to -1");
288 my $msg = Imager->_error_as_msg;
289 like($msg, qr/^lseek\(\) failure: /, "check error message");
298 { # fd_seek read failure
299 open my $fh, "> testout/t07writeonly.txt"
300 or skip("Can't open testout/t07writeonly.txt: $!", 3);
301 my $io = Imager::io_new_fd(fileno($fh));
302 ok($io, "make fd io for write-only");
304 Imager::i_clear_error();
306 is($io->raw_read($buf, 10), undef,
307 "file open for write shouldn't be readable");
308 my $msg = Imager->_error_as_msg;
309 like($msg, qr/^read\(\) failure: /, "check error message");
317 open my $fh, "> testout/t07readeof.txt"
318 or skip("Can't open testout/t07readeof.txt: $!", 5);
322 open my $fhr, "< testout/t07readeof.txt",
323 or skip("Can't open testout/t07readeof.txt: $!", 5);
324 my $io = Imager::io_new_fd(fileno($fhr));
325 ok($io, "make fd io for read eof");
327 Imager::i_clear_error();
329 is($io->raw_read($buf, 10), 4,
330 "10 byte read on 4 byte file should return 4");
331 my $msg = Imager->_error_as_msg;
332 is($msg, "", "should be no error message")
333 or print STDERR "# read(4) message is: $msg\n";
335 Imager::i_clear_error();
337 is($io->raw_read($buf, 10), 0,
338 "10 byte read at end of 4 byte file should return 0 (eof)");
340 $msg = Imager->_error_as_msg;
341 is($msg, "", "should be no error message")
342 or print STDERR "# read(4), eof message is: $msg\n";
348 my $data="P2\n2 2\n255\n 255 0\n0 255\n";
349 my $io = Imager::io_new_buffer($data);
353 is($c, ord "P", "getc");
354 my $peekc = $io->peekc();
356 is($peekc, ord "2", "peekc");
358 my $peekn = $io->peekn(2);
359 is($peekn, "2\n", "peekn");
362 is($c, ord "2", "getc after peekc/peekn");
364 is($io->seek(0, SEEK_SET), "0", "seek");
365 is($io->getc, ord "P", "check we got back to the start");
368 { # test closecb result is propagated
369 my $success_cb = sub { 1 };
370 my $failure_cb = sub { 0 };
373 my $io = Imager::io_new_cb(undef, $success_cb, undef, $success_cb);
374 is($io->close(), 0, "test successful close");
377 my $io = Imager::io_new_cb(undef, $success_cb, undef, $failure_cb);
378 is($io->close(), -1, "test failed close");
382 { # buffered coverage/function tests
383 # some data to play with
384 my $base = pack "C*", map rand(26) + ord("a"), 0 .. 20_001;
386 { # buffered accessors
387 my $io = Imager::io_new_buffer($base);
388 ok($io->set_buffered(0), "set unbuffered");
389 ok(!$io->is_buffered, "verify unbuffered");
390 ok($io->set_buffered(1), "set buffered");
391 ok($io->is_buffered, "verify buffered");
394 { # initial i_io_read(), buffered
401 my $req_size = $size;
403 if ($pos + $size > length $work) {
404 $size = length($work) - $pos;
407 my $result = substr($work, $pos, $size);
409 $ops .= "R$req_size>$size;";
411 print "# read $req_size>$size\n";
418 substr($work, $pos, length($data), $data);
423 my $io = Imager::io_new_cb(undef, $read, undef, undef);
425 is($io->read($buf, 1000), 1000, "read initial 1000");
426 is($buf, substr($base, 0, 1000), "check data read");
427 is($ops, "R8192>8192;", "check read op happened to buffer size");
430 is($io->read($buf, 1001), 1001, "read another 1001");
431 is($buf, substr($base, 1000, 1001), "check data read");
432 is($ops, "R8192>8192;", "should be no further reads");
435 is($io->read($buf, 40_000), length($base) - 2001,
436 "read the rest in one chunk");
437 is($buf, substr($base, 2001), "check the data read");
438 my $buffer_left = 8192 - 2001;
439 my $after_buffer = length($base) - 8192;
440 is($ops, "R8192>8192;R".(40_000 - $buffer_left).">$after_buffer;R21999>0;",
441 "check we tried to read the remainder");
444 # read after write errors
445 my $io = Imager::io_new_cb($write, $read, undef, undef);
446 is($io->write("test"), 4, "write 4 bytes, io in write mode");
447 is($io->read2(10), undef, "read should fail");
448 is($io->peekn(10), undef, "peekn should fail");
449 is($io->getc(), -1, "getc should fail");
450 is($io->peekc(), -1, "peekc should fail");
455 my $io = Imager::io_new_buffer($base);
456 print "# buffer fill check\n";
457 ok($io, "make memory io");
459 is($io->read($buf, 4096), 4096, "read 4k");
460 is($buf, substr($base, 0, 4096), "check data is correct");
464 is($io->peekn(5120), substr($base, 4096, 5120),
465 "peekn() 5120, which should exceed the buffer, and only read the left overs");
469 my $io = Imager::io_new_buffer($base);
470 is($io->peekn(10), substr($base, 0, 10),
471 "make sure initial peekn() is sane");
472 is($io->read2(10), substr($base, 0, 10),
473 "and that reading 10 gets the expected data");
477 my $io = Imager::io_new_buffer($base);
478 is($io->peekn(10_000), substr($base, 0, 8192),
479 "peekn() larger than buffer should return buffer-size bytes");
482 { # small peekn then large peekn with a small I/O back end
483 # this might happen when reading from a socket
490 my $req_size = $size;
491 # do small reads, to trigger a possible bug
496 if ($pos + $size > length $work) {
497 $size = length($work) - $pos;
500 my $result = substr($work, $pos, $size);
502 $ops .= "R$req_size>$size;";
504 print "# read $req_size>$size\n";
508 my $io = Imager::io_new_cb(undef, $reader, undef, undef);
509 ok($io, "small reader io");
510 is($io->peekn(25), substr($base, 0, 25), "peek 25");
511 is($ops, "R8192>10;R8182>10;R8172>10;",
512 "check we got the raw calls expected");
513 is($io->peekn(65), substr($base, 0, 65), "peek 65");
514 is($ops, "R8192>10;R8182>10;R8172>10;R8162>10;R8152>10;R8142>10;R8132>10;",
515 "check we got the raw calls expected");
517 for my $buffered (1, 0) { # peekn followed by errors
518 my $buffered_desc = $buffered ? "buffered" : "unbuffered";
524 my $req_size = $size;
525 if ($pos + $size > length $base) {
526 $size = length($base) - $pos;
528 # error instead of eof
530 print "# read $req_size>error\n";
533 my $result = substr($base, $pos, $size);
536 print "# read $req_size>$size\n";
540 my $io = Imager::io_new_cb(undef, $reader, undef, undef);
541 ok($io, "make $buffered_desc cb with error after 6 bytes");
542 is($io->peekn(5), "abcde",
543 "peekn until just before error ($buffered_desc)");
544 is($io->peekn(6), "abcdef", "peekn until error ($buffered_desc)");
545 is($io->peekn(7), "abcdef", "peekn past error ($buffered_desc)");
547 "should be no error indicator, since data buffered ($buffered_desc)");
549 "should be no eof indicator, since data buffered ($buffered_desc)");
552 is($io->read2(6), "abcdef", "consume the buffer ($buffered_desc)");
553 is($io->peekn(10), undef,
554 "peekn should get an error indicator ($buffered_desc)");
555 ok($io->error, "should be an error state ($buffered_desc)");
556 ok(!$io->eof, "but not eof ($buffered_desc)");
558 { # peekn on an empty file
559 my $io = Imager::io_new_buffer("");
560 is($io->peekn(10), "", "peekn on empty source");
561 ok($io->eof, "should be in eof state");
562 ok(!$io->error, "but not error");
564 { # peekn on error source
565 my $io = Imager::io_new_cb(undef, sub { return; }, undef, undef);
566 is($io->peekn(10), undef, "peekn on empty source");
567 ok($io->error, "should be in error state");
568 ok(!$io->eof, "but not eof");
570 { # peekn on short source
571 my $io = Imager::io_new_buffer("abcdef");
572 is($io->peekn(4), "abcd", "peekn 4 on 6 byte source");
573 is($io->peekn(10), "abcdef", "followed by peekn 10 on 6 byte source");
574 is($io->peekn(10), "abcdef", "and again, now eof is set");
577 Imager::i_clear_error();
578 my $io = Imager::io_new_buffer("abcdef");
579 is($io->peekn(0), undef, "peekn 0 on 6 byte source");
580 my $msg = Imager->_error_as_msg;
581 is($msg, "peekn size must be positive");
583 { # getc through a whole file (buffered)
584 my $io = Imager::io_new_buffer($base);
586 while ((my $c = $io->getc()) != -1) {
589 is($out, $base, "getc should return the file byte by byte (buffered)");
590 is($io->getc, -1, "another getc after eof should fail too");
591 ok($io->eof, "should be marked eof");
592 ok(!$io->error, "shouldn't be marked in error");
594 { # getc through a whole file (unbuffered)
595 my $io = Imager::io_new_buffer($base);
596 $io->set_buffered(0);
598 while ((my $c = $io->getc()) != -1) {
601 is($out, $base, "getc should return the file byte by byte (unbuffered)");
602 is($io->getc, -1, "another getc after eof should fail too");
603 ok($io->eof, "should be marked eof");
604 ok(!$io->error, "shouldn't be marked in error");
606 { # buffered getc with an error
607 my $io = Imager::io_new_cb(undef, sub { return; }, undef, undef);
608 is($io->getc, -1, "buffered getc error");
609 ok($io->error, "io marked in error");
610 ok(!$io->eof, "but not eof");
612 { # unbuffered getc with an error
613 my $io = Imager::io_new_cb(undef, sub { return; }, undef, undef);
614 $io->set_buffered(0);
615 is($io->getc, -1, "unbuffered getc error");
616 ok($io->error, "io marked in error");
617 ok(!$io->eof, "but not eof");
619 { # initial peekc - buffered
620 my $io = Imager::io_new_buffer($base);
622 is($c, ord($base), "buffered peekc matches");
623 is($io->peekc, $c, "duplicate peekc matchess");
625 { # initial peekc - unbuffered
626 my $io = Imager::io_new_buffer($base);
627 $io->set_buffered(0);
629 is($c, ord($base), "unbuffered peekc matches");
630 is($io->peekc, $c, "duplicate peekc matchess");
632 { # initial peekc eof - buffered
633 my $io = Imager::io_new_cb(undef, sub { "" }, undef, undef);
635 is($c, -1, "buffered eof peekc is -1");
636 is($io->peekc, $c, "duplicate matches");
637 ok($io->eof, "io marked eof");
638 ok(!$io->error, "but not error");
640 { # initial peekc eof - unbuffered
641 my $io = Imager::io_new_cb(undef, sub { "" }, undef, undef);
642 $io->set_buffered(0);
644 is($c, -1, "buffered eof peekc is -1");
645 is($io->peekc, $c, "duplicate matches");
646 ok($io->eof, "io marked eof");
647 ok(!$io->error, "but not error");
649 { # initial peekc error - buffered
650 my $io = Imager::io_new_cb(undef, sub { return; }, undef, undef);
652 is($c, -1, "buffered error peekc is -1");
653 is($io->peekc, $c, "duplicate matches");
654 ok($io->error, "io marked error");
655 ok(!$io->eof, "but not eof");
657 { # initial peekc error - unbuffered
658 my $io = Imager::io_new_cb(undef, sub { return; }, undef, undef);
659 $io->set_buffered(0);
661 is($c, -1, "unbuffered error peekc is -1");
662 is($io->peekc, $c, "duplicate matches");
663 ok($io->error, "io marked error");
664 ok(!$io->eof, "but not eof");
667 my $io = Imager::io_new_bufchain();
668 is($io->putc(ord "A"), ord "A", "initial putc buffered");
669 is($io->close, 0, "close it");
670 is(Imager::io_slurp($io), "A", "check it was written");
672 { # initial putc - unbuffered
673 my $io = Imager::io_new_bufchain();
674 $io->set_buffered(0);
675 is($io->putc(ord "A"), ord "A", "initial putc unbuffered");
676 is($io->close, 0, "close it");
677 is(Imager::io_slurp($io), "A", "check it was written");
679 { # putc unbuffered with error
680 my $io = Imager::io_new_cb(undef, undef, undef, undef);
681 $io->set_buffered(0);
682 is($io->putc(ord "A"), -1, "initial putc unbuffered error");
683 ok($io->error, "io in error");
684 is($io->putc(ord "B"), -1, "still in error");
686 { # writes while in read state
687 my $io = Imager::io_new_cb(sub { 1 }, sub { return "AA" }, undef, undef);
688 is($io->getc, ord "A", "read to setup read buffer");
689 is($io->putc(ord "B"), -1, "putc should fail");
690 is($io->write("test"), -1, "write should fail");
692 { # buffered putc error handling
693 # tests the check for error state in the buffered putc code
694 my $io = Imager::io_new_cb(undef, undef, undef, undef);
696 ok(!$io->flush, "flush should fail");
697 ok($io->error, "should be in error state");
698 is($io->putc(ord "B"), -1, "check for error");
700 { # buffered putc flush error handling
701 # test handling of flush failure and of the error state resulting
703 my $io = Imager::io_new_cb(undef, undef, undef, undef);
705 while (++$i < 100_000 && $io->putc(ord "A") == ord "A") {
706 # until we have to flush and fail doing do
708 is($i, 8193, "should have failed on 8193rd byte");
709 ok($io->error, "should be in error state");
710 is($io->putc(ord "B"), -1, "next putc should fail");
712 { # buffered write flush error handling
713 # test handling of flush failure and of the error state resulting
715 my $io = Imager::io_new_cb(undef, undef, undef, undef);
717 while (++$i < 100_000 && $io->write("A") == 1) {
718 # until we have to flush and fail doing do
720 is($i, 8193, "should have failed on 8193rd byte");
721 ok($io->error, "should be in error state");
722 is($io->write("B"), -1, "next write should fail");
724 { # buffered read error
725 my $io = Imager::io_new_cb(undef, undef, undef, undef);
726 is($io->read2(10), undef, "initial read returning error");
727 ok($io->error, "should be in error state");
729 { # unbuffered read error
730 my $io = Imager::io_new_cb(undef, undef, undef, undef);
731 $io->set_buffered(0);
732 is($io->read2(10), undef, "initial read returning error");
733 ok($io->error, "should be in error state");
735 { # unbuffered write error
737 my $io = Imager::io_new_cb(sub { return $count++; }, undef, undef, undef);
738 $io->set_buffered(0);
739 is($io->write("A"), -1, "unbuffered write failure");
740 ok($io->error, "should be in error state");
741 is($io->write("BC"), -1, "should still fail");
743 { # buffered write + large write
744 my $io = Imager::io_new_bufchain();
745 is($io->write(substr($base, 0, 4096)), 4096,
746 "should be buffered");
747 is($io->write(substr($base, 4096)), length($base) - 4096,
748 "large write, should fill buffer and fall back to direct write");
749 is($io->close, 0, "close it");
750 is(Imager::io_slurp($io), $base, "make sure the data is correct");
752 { # initial large write with failure
753 # tests error handling for the case where we bypass the buffer
754 # when the write is too large to fit
755 my $io = Imager::io_new_cb(undef, undef, undef, undef);
756 ok($io->flush, "flush with nothing buffered should succeed");
757 is($io->write($base), -1, "large write failure");
758 ok($io->error, "should be in error state");
759 is($io->close, -1, "should fail to close");
761 { # write that causes a flush then fills the buffer a bit
762 my $io = Imager::io_new_bufchain();
763 is($io->write(substr($base, 0, 6000)), 6000, "fill the buffer a bit");
764 is($io->write(substr($base, 6000, 4000)), 4000,
765 "cause it to flush and then fill some more");
766 is($io->write(substr($base, 10000)), length($base)-10000,
767 "write out the rest of our test data");
768 is($io->close, 0, "close the stream");
769 is(Imager::io_slurp($io), $base, "make sure the data is right");
771 { # failure on flush on close
772 my $io = Imager::io_new_cb(undef, undef, undef, undef);
773 is($io->putc(ord "A"), ord "A", "something in the buffer");
774 ok(!$io->error, "should be no error yet");
775 is($io->close, -1, "close should failure due to flush error");
778 my $io = Imager::io_new_cb(undef, undef, undef, undef);
779 is($io->seek(0, SEEK_SET), -1, "seek failure");
781 { # read a little and seek
782 my $io = Imager::io_new_buffer($base);
783 is($io->getc, ord $base, "read one");
784 is($io->getc, ord substr($base, 1, 1), "read another");
785 is($io->seek(-1, SEEK_CUR), 1, "seek relative back to origin+1");
786 is($io->getc, ord substr($base, 1, 1), "read another again");
788 { # seek with failing flush
789 my $io = Imager::io_new_cb(undef, undef, undef, undef);
790 is($io->putc(ord "A"), ord "A", "write one");
791 ok(!$io->error, "not in error mode (yet)");
792 is($io->seek(0, SEEK_SET), -1, "seek failure due to flush");
793 ok($io->error, "in error mode");
796 my $data = "test1\ntest2\ntest3";
797 my $io = Imager::io_new_buffer($data);
798 is($io->gets(6), "test1\n", "gets(6)");
799 is($io->gets(5), "test2", "gets(5) (short for the line)");
800 is($io->gets(10), "\n", "gets(10) the rest of the line (the newline)");
801 is($io->gets(), "test3", "gets(default) unterminated line");
804 my $data = "test1\ntest2\ntest3";
805 my $io = Imager::io_new_buffer($data);
806 is($io->gets(6, ord("1")), "test1", "gets(6) (line terminator 1)");
807 is($io->gets(6, ord("2")), "\ntest2", "gets(6) (line terminator 2)");
808 is($io->gets(6, ord("3")), "\ntest3", "gets(6) (line terminator 3)");
809 is($io->getc, -1, "should be eof");
813 { # based on discussion on IRC, user was attempting to write a TIFF
814 # image file with only a write callback, but TIFF requires seek and
815 # read callbacks when writing.
816 # https://rt.cpan.org/Ticket/Display.html?id=76782
817 my $cb = Imager::io_new_cb(undef, undef, undef, undef);
819 Imager::i_clear_error();
821 is($cb->read($data, 10), undef, "default read callback should fail");
822 is(Imager->_error_as_msg(), "read callback called but no readcb supplied",
823 "check error message");
826 Imager::i_clear_error();
827 is($cb->raw_write("abc"), -1, "default write callback should fail");
828 is(Imager->_error_as_msg(), "write callback called but no writecb supplied",
829 "check error message");
832 Imager::i_clear_error();
833 is($cb->seek(0, 0), -1, "default seek callback should fail");
834 is(Imager->_error_as_msg(), "seek callback called but no seekcb supplied",
835 "check error message");
842 or skip "PerlIO::scalar requires perlio", 13;
845 open my $fh, "+<", \$foo;
846 my $io = Imager::IO->_new_perlio($fh);
847 ok($io, "perlio: make a I/O object for a perl scalar fh");
848 is($io->write("test"), 4, "perlio: check we can write");
849 is($io->seek(2, SEEK_SET), 2, "perlio: check we can seek");
850 is($io->write("more"), 4, "perlio: write some more");
851 is($io->seek(0, SEEK_SET), 0, "perlio: seek back to start");
853 is($io->read($data, 10), 6, "perlio: read everything back");
854 is($data, "temore", "perlio: check we read back what we wrote");
855 is($io->close, 0, "perlio: close it");
856 is($foo, "temore", "perlio: check it got to the scalar properly");
858 my $io2 = Imager::IO->new_fh($fh);
859 ok($io2, "new_fh() can make an I/O layer object from a scalar fh");
862 my $im = Imager->new(xsize => 10, ysize => 10);
864 open my $fh2, ">", \$foo;
865 ok($im->write(fh => $fh2, type => "pnm"), "can write image to scalar fh")
866 or print "# ", $im->errstr, "\n";
869 open my $fh3, "<", \$foo;
870 my $im2 = Imager->new(fh => $fh3);
871 ok($im2, "read image from a scalar fh");
872 is_image($im, $im2, "check they match");
876 tie *FOO, "IO::Tied";
877 my $io = Imager::IO->new_fh(\*FOO);
878 ok($io, "tied: make a I/O object for a tied fh");
879 is($io->write("test"), 4, "tied: check we can write");
880 is($io->seek(2, SEEK_SET), 2, "tied: check we can seek");
881 is($io->write("more"), 4, "tied: write some more");
882 is($io->seek(0, SEEK_SET), 0, "tied: seek back to start");
884 is($io->read($data, 10), 6, "tied: read everything back");
885 is($data, "temore", "tied: check we read back what we wrote");
886 is($io->close, 0, "tied: close it");
887 is(tied(*FOO)->[0], "temore", "tied: check it got to the output properly");
892 unless ($ENV{IMAGER_KEEP_FILES}) {
893 unlink "testout/t07.ppm", "testout/t07iolayer.log";
905 my $data = "testdata";
906 length $data <= $max_len or substr($data, $max_len) = '';
908 print "# good_read ($max_len) => $data\n";
926 use base 'Tie::Handle';
930 return bless [ "", 0 ];
934 for my $entry (@_[1 .. $#_]) {
935 substr($_[0][0], $_[0][1], length $entry, $entry);
936 $_[0][1] += length $entry;
943 my ($self, $offset, $whence) = @_;
946 if ($whence == SEEK_SET) {
949 elsif ($whence == SEEK_CUR) {
950 $newpos = $self->[1] + $offset;
952 elsif ($whence == SEEK_END) {
953 $newpos = length($self->[0]) + $newpos;
963 $self->[1] = $newpos;
975 my $offset = @_ > 2 ? $_[2] : 0;
976 if ($self->[1] + $outlen > length $self->[0]) {
977 $outlen = length($self->[0]) - $self->[1];
981 defined $_[0] or $_[0] = "";
982 substr($_[0], $offset, $outlen) = substr($self->[0], $self->[1], $outlen);
983 $self->[1] += $outlen;