layers.t 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #!./perl
  2. my $PERLIO;
  3. BEGIN {
  4. unshift @INC, 't/CORE/lib';
  5. require 't/CORE/test.pl';
  6. # Makes testing easier.
  7. $ENV{PERLIO} = 'stdio' if exists $ENV{PERLIO} && $ENV{PERLIO} eq '';
  8. skip_all("PERLIO='$ENV{PERLIO}' unknown")
  9. if exists $ENV{PERLIO} && $ENV{PERLIO} !~ /^(stdio|perlio|mmap)$/;
  10. $PERLIO = exists $ENV{PERLIO} ? $ENV{PERLIO} : "(undef)";
  11. }
  12. use Config;
  13. my $DOSISH = $^O =~ /^(?:MSWin32|os2|dos|NetWare)$/ ? 1 : 0;
  14. $DOSISH = 1 if !$DOSISH and $^O =~ /^uwin/;
  15. my $NONSTDIO = exists $ENV{PERLIO} && $ENV{PERLIO} ne 'stdio' ? 1 : 0;
  16. my $FASTSTDIO = $Config{d_faststdio} && $Config{usefaststdio} ? 1 : 0;
  17. my $UTF8_STDIN;
  18. if (${^UNICODE} & 1) {
  19. if (${^UNICODE} & 64) {
  20. # Conditional on the locale
  21. $UTF8_STDIN = ${^UTF8LOCALE};
  22. } else {
  23. # Unconditional
  24. $UTF8_STDIN = 1;
  25. }
  26. } else {
  27. $UTF8_STDIN = 0;
  28. }
  29. my $NTEST = 62 - (($DOSISH || !$FASTSTDIO) ? 7 : 0) - ($DOSISH ? 7 : 0)
  30. + $UTF8_STDIN;
  31. sub PerlIO::F_UTF8 () { 0x00008000 } # from perliol.h
  32. plan tests => $NTEST;
  33. print <<__EOH__;
  34. # PERLIO = $PERLIO
  35. # DOSISH = $DOSISH
  36. # NONSTDIO = $NONSTDIO
  37. # FASTSTDIO = $FASTSTDIO
  38. # UNICODE = ${^UNICODE}
  39. # UTF8LOCALE = ${^UTF8LOCALE}
  40. # UTF8_STDIN = $UTF8_STDIN
  41. __EOH__
  42. {
  43. sub check {
  44. my ($result, $expected, $id) = @_;
  45. # An interesting dance follows where we try to make the following
  46. # IO layer stack setups to compare equal:
  47. #
  48. # PERLIO UNIX-like DOS-like
  49. #
  50. # unset / "" unix perlio / stdio [1] unix crlf
  51. # stdio unix perlio / stdio [1] stdio
  52. # perlio unix perlio unix perlio
  53. # mmap unix mmap unix mmap
  54. #
  55. # [1] "stdio" if Configure found out how to do "fast stdio" (depends
  56. # on the stdio implementation) and in Perl 5.8, otherwise "unix perlio"
  57. #
  58. if ($NONSTDIO) {
  59. # Get rid of "unix".
  60. shift @$result if $result->[0] eq "unix";
  61. # Change expectations.
  62. if ($FASTSTDIO) {
  63. $expected->[0] = $ENV{PERLIO};
  64. } else {
  65. $expected->[0] = $ENV{PERLIO} if $expected->[0] eq "stdio";
  66. }
  67. } elsif (!$FASTSTDIO && !$DOSISH) {
  68. splice(@$result, 0, 2, "stdio")
  69. if @$result >= 2 &&
  70. $result->[0] eq "unix" &&
  71. $result->[1] eq "perlio";
  72. } elsif ($DOSISH) {
  73. splice(@$result, 0, 2, "stdio")
  74. if @$result >= 2 &&
  75. $result->[0] eq "unix" &&
  76. $result->[1] eq "crlf";
  77. }
  78. if ($DOSISH && grep { $_ eq 'crlf' } @$expected) {
  79. # 5 tests potentially skipped because
  80. # DOSISH systems already have a CRLF layer
  81. # which will make new ones not stick.
  82. splice @$expected, 1, 1 if $expected->[1] eq 'crlf';
  83. }
  84. my $n = scalar @$expected;
  85. is(scalar @$result, $n, "$id - layers == $n");
  86. for (my $i = 0; $i < $n; $i++) {
  87. my $j = $expected->[$i];
  88. if (ref $j eq 'CODE') {
  89. ok($j->($result->[$i]), "$id - $i is ok");
  90. } else {
  91. is($result->[$i], $j,
  92. sprintf("$id - $i is %s",
  93. defined $j ? $j : "undef"));
  94. }
  95. }
  96. }
  97. check([ PerlIO::get_layers(STDIN) ],
  98. $UTF8_STDIN ? [ "stdio", "utf8" ] : [ "stdio" ],
  99. "STDIN");
  100. my $afile = tempfile();
  101. open(F, ">:crlf", $afile);
  102. check([ PerlIO::get_layers(F) ],
  103. [ qw(stdio crlf) ],
  104. "open :crlf");
  105. binmode(F, ":crlf");
  106. check([ PerlIO::get_layers(F) ],
  107. [ qw(stdio crlf) ],
  108. "binmode :crlf");
  109. binmode(F, ":encoding(cp1047)");
  110. check([ PerlIO::get_layers(F) ],
  111. [ qw[stdio crlf encoding(cp1047) utf8] ],
  112. ":encoding(cp1047)");
  113. binmode(F, ":crlf");
  114. check([ PerlIO::get_layers(F) ],
  115. [ qw[stdio crlf encoding(cp1047) utf8 crlf utf8] ],
  116. ":encoding(cp1047):crlf");
  117. binmode(F, ":pop:pop");
  118. check([ PerlIO::get_layers(F) ],
  119. [ qw(stdio crlf) ],
  120. ":pop");
  121. binmode(F, ":raw");
  122. check([ PerlIO::get_layers(F) ],
  123. [ "stdio" ],
  124. ":raw");
  125. binmode(F, ":utf8");
  126. check([ PerlIO::get_layers(F) ],
  127. [ qw(stdio utf8) ],
  128. ":utf8");
  129. binmode(F, ":bytes");
  130. check([ PerlIO::get_layers(F) ],
  131. [ "stdio" ],
  132. ":bytes");
  133. binmode(F, ":encoding(utf8)");
  134. check([ PerlIO::get_layers(F) ],
  135. [ qw[stdio encoding(utf8) utf8] ],
  136. ":encoding(utf8)");
  137. binmode(F, ":raw :crlf");
  138. check([ PerlIO::get_layers(F) ],
  139. [ qw(stdio crlf) ],
  140. ":raw:crlf");
  141. binmode(F, ":raw :encoding(latin1)"); # "latin1" will be canonized
  142. # 7 tests potentially skipped.
  143. unless ($DOSISH || !$FASTSTDIO) {
  144. my @results = PerlIO::get_layers(F, details => 1);
  145. # Get rid of the args and the flags.
  146. splice(@results, 1, 2) if $NONSTDIO;
  147. check([ @results ],
  148. [ "stdio", undef, sub { $_[0] > 0 },
  149. "encoding", "iso-8859-1", sub { $_[0] & PerlIO::F_UTF8() } ],
  150. ":raw:encoding(latin1)");
  151. }
  152. binmode(F);
  153. check([ PerlIO::get_layers(F) ],
  154. [ "stdio" ],
  155. "binmode");
  156. # RT78844
  157. {
  158. local $@ = "foo";
  159. binmode(F, ":encoding(utf8)");
  160. is( $@, "foo", '$@ not clobbered by binmode and :encoding');
  161. }
  162. close F;
  163. {
  164. use open(IN => ":crlf", OUT => ":encoding(cp1252)");
  165. open F, '<', $afile;
  166. open G, '>', $afile;
  167. diag ("perlcc issue 203"); # https://code.google.com/p/perl-compiler/issues/detail?id=203
  168. check([ PerlIO::get_layers(F, input => 1) ],
  169. [ qw(stdio crlf) ],
  170. "use open IN");
  171. check([ PerlIO::get_layers(G, output => 1) ],
  172. [ qw[stdio encoding(cp1252) utf8] ],
  173. "use open OUT");
  174. close F;
  175. close G;
  176. }
  177. # Check that PL_sigwarn's reference count is correct, and that
  178. # &PerlIO::Layer::NoWarnings isn't prematurely freed.
  179. fresh_perl_like (<<"EOT", qr/^CODE/);
  180. open(UTF, "<:raw:encoding(utf8)", '$afile') or die \$!;
  181. print ref *PerlIO::Layer::NoWarnings{CODE};
  182. EOT
  183. # TODO: not with 5.14
  184. # [perl #97956] Not calling FETCH all the time on tied variables
  185. my $f;
  186. sub TIESCALAR { bless [] }
  187. sub FETCH { ++$f; $_[0][0] = $_[1] }
  188. sub STORE { $_[0][0] }
  189. tie my $t, "";
  190. SKIP: {
  191. skip("requires 5.16", 3) if $] < 5.016;
  192. $t = *f;
  193. $f = 0; PerlIO::get_layers $t;
  194. is $f, 1, '1 fetch on tied glob';
  195. $t = \*f;
  196. $f = 0; PerlIO::get_layers $t;
  197. is $f, 1, '1 fetch on tied globref';
  198. $t = *f;
  199. $f = 0; PerlIO::get_layers \$t;
  200. is $f, 1, '1 fetch on referenced tied glob';
  201. }
  202. $t = '';
  203. $f = 0; PerlIO::get_layers $t;
  204. is $f, 1, '1 fetch on tied string';
  205. SKIP: {
  206. skip("requires 5.16", 3) if $] < 5.016;
  207. # No distinction between nums and strings
  208. open "12", "<:crlf", "t/test.pl" or die "$0 cannot open t/test.pl: $!";
  209. ok PerlIO::get_layers(12), 'str/num arguments are treated identically';
  210. }
  211. }