Re: [PATCH] Re: [perl #39530] printf: bad formatting of hexadecimal conversion of...
[p5sagit/p5-mst-13.2.git] / t / op / state.t
1 #!./perl -w
2 # tests state variables
3
4 BEGIN {
5     chdir 't' if -d 't';
6     @INC = '../lib';
7     require './test.pl';
8 }
9
10 use strict;
11 use feature "state";
12
13 plan tests => 30;
14
15 ok( ! defined state $uninit, q(state vars are undef by default) );
16
17 # basic functionality
18
19 sub stateful {
20     state $x;
21     state $y = 1;
22     my $z = 2;
23     return ($x++, $y++, $z++);
24 }
25
26 my ($x, $y, $z) = stateful();
27 is( $x, 0, 'uninitialized state var' );
28 is( $y, 1, 'initialized state var' );
29 is( $z, 2, 'lexical' );
30
31 ($x, $y, $z) = stateful();
32 is( $x, 1, 'incremented state var' );
33 is( $y, 2, 'incremented state var' );
34 is( $z, 2, 'reinitialized lexical' );
35
36 ($x, $y, $z) = stateful();
37 is( $x, 2, 'incremented state var' );
38 is( $y, 3, 'incremented state var' );
39 is( $z, 2, 'reinitialized lexical' );
40
41 # in a nested block
42
43 sub nesting {
44     state $foo = 10;
45     my $t;
46     { state $bar = 12; $t = ++$bar }
47     ++$foo;
48     return ($foo, $t);
49 }
50
51 ($x, $y) = nesting();
52 is( $x, 11, 'outer state var' );
53 is( $y, 13, 'inner state var' );
54
55 ($x, $y) = nesting();
56 is( $x, 12, 'outer state var' );
57 is( $y, 14, 'inner state var' );
58
59 # in a closure
60
61 sub generator {
62     my $outer;
63     # we use $outer to generate a closure
64     sub { ++$outer; ++state $x }
65 }
66
67 my $f1 = generator();
68 is( $f1->(), 1, 'generator 1' );
69 is( $f1->(), 2, 'generator 1' );
70 my $f2 = generator();
71 is( $f2->(), 1, 'generator 2' );
72 is( $f1->(), 3, 'generator 1 again' );
73 is( $f2->(), 2, 'generator 2 once more' );
74
75 # with ties
76 {
77     package countfetches;
78     our $fetchcount = 0;
79     sub TIESCALAR {bless {}};
80     sub FETCH { ++$fetchcount; 18 };
81     tie my $y, "countfetches";
82     sub foo { state $x = $y; $x++ }
83     ::is( foo(), 18, "initialisation with tied variable" );
84     ::is( foo(), 19, "increments correctly" );
85     ::is( foo(), 20, "increments correctly, twice" );
86     ::is( $fetchcount, 1, "fetch only called once" );
87 }
88
89 # state variables are shared among closures
90
91 sub gen_cashier {
92     my $amount = shift;
93     state $cash_in_store = 0;
94     return {
95         add => sub { $cash_in_store += $amount },
96         del => sub { $cash_in_store -= $amount },
97         bal => sub { $cash_in_store },
98     };
99 }
100
101 gen_cashier(59)->{add}->();
102 gen_cashier(17)->{del}->();
103 is( gen_cashier()->{bal}->(), 42, '$42 in my drawer' );
104
105 # stateless assignment to a state variable
106
107 sub stateless {
108     (state $reinitme) = 42;
109     ++$reinitme;
110 }
111 is( stateless(), 43, 'stateless function, first time' );
112 is( stateless(), 43, 'stateless function, second time' );
113
114 # array state vars
115
116 sub stateful_array {
117     state @x;
118     push @x, 'x';
119     return $#x;
120 }
121
122 my $xsize = stateful_array();
123 is( $xsize, 0, 'uninitialized state array' );
124
125 $xsize = stateful_array();
126 is( $xsize, 1, 'uninitialized state array after one iteration' );
127
128 # hash state vars
129
130 sub stateful_hash {
131     state %hx;
132     return $hx{foo}++;
133 }
134
135 my $xhval = stateful_hash();
136 is( $xhval, 0, 'uninitialized state hash' );
137
138 $xhval = stateful_hash();
139 is( $xhval, 1, 'uninitialized state hash after one iteration' );