Make sure Win32-like DBICTest checks are not tripped by repeated disconnects
[dbsrgits/DBIx-Class.git] / t / 87ordered.t
1 # vim: filetype=perl
2 use strict;
3 use warnings;
4
5 use Test::More;
6 use lib qw(t/lib);
7 use DBICTest;
8
9 use POSIX ();
10
11 my $schema = DBICTest->init_schema();
12
13 my $employees = $schema->resultset('Employee');
14 $employees->delete();
15
16 foreach (1..5) {
17     $employees->create({ name=>'temp' });
18 }
19 $employees = $employees->search(undef,{order_by=>'position'});
20 ok( check_rs($employees), "intial positions" );
21
22 hammer_rs( $employees );
23
24 DBICTest::Employee->grouping_column('group_id');
25 $employees->delete();
26 foreach my $group_id (1..4) {
27     foreach (1..6) {
28         $employees->create({ name=>'temp', group_id=>$group_id });
29     }
30 }
31 $employees = $employees->search(undef,{order_by=>'group_id,position'});
32
33 foreach my $group_id (1..4) {
34     my $group_employees = $employees->search({group_id=>$group_id});
35     $group_employees->all();
36     ok( check_rs($group_employees), "group intial positions" );
37     hammer_rs( $group_employees );
38 }
39
40 my $group_3 = $employees->search({group_id=>3});
41 my $to_group = 1;
42 my $to_pos = undef;
43 {
44   my @empl = $group_3->all;
45   while (my $employee = shift @empl) {
46     $employee->move_to_group($to_group, $to_pos);
47     $to_pos++;
48     $to_group = $to_group==1 ? 2 : 1;
49   }
50 }
51 foreach my $group_id (1..4) {
52     my $group_employees = $employees->search({group_id=>$group_id});
53     ok( check_rs($group_employees), "group positions after move_to_group" );
54 }
55
56 my $employee = $employees->search({group_id=>4})->first;
57 $employee->position(2);
58 $employee->update;
59 ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 1" );
60 $employee = $employees->search({group_id=>4})->first;
61 $employee->update({position=>3});
62 ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 2" );
63 $employee = $employees->search({group_id=>4})->first;
64 $employee->group_id(1);
65 $employee->update;
66 ok(
67   check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
68   "overloaded update 3"
69 );
70 $employee = $employees->search({group_id=>4})->first;
71 $employee->update({group_id=>2});
72 ok(
73   check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
74   "overloaded update 4"
75 );
76 $employee = $employees->search({group_id=>4})->first;
77 $employee->group_id(1);
78 $employee->position(3);
79 $employee->update;
80 ok(
81   check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
82   "overloaded update 5"
83 );
84 $employee = $employees->search({group_id=>4})->first;
85 $employee->group_id(2);
86 $employee->position(undef);
87 $employee->update;
88 ok(
89   check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
90   "overloaded update 6"
91 );
92 $employee = $employees->search({group_id=>4})->first;
93 $employee->update({group_id=>1,position=>undef});
94 ok(
95   check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
96   "overloaded update 7"
97 );
98
99 $employee->group_id(2);
100 $employee->name('E of the month');
101 $employee->update({ employee_id => 666, position => 2 });
102 is_deeply(
103   { $employee->get_columns },
104   {
105     employee_id => 666,
106     encoded => undef,
107     group_id => 2,
108     group_id_2 => undef,
109     group_id_3 => undef,
110     name => "E of the month",
111     position => 2
112   },
113   'combined update() worked correctly'
114 );
115 is_deeply(
116   { $employee->get_columns },
117   { $employee->get_from_storage->get_columns },
118   'object matches database state',
119 );
120
121 #####
122 # multicol tests begin here
123 #####
124
125 DBICTest::Employee->grouping_column(['group_id_2', 'group_id_3']);
126 $employees->delete();
127 foreach my $group_id_2 (1..4) {
128     foreach my $group_id_3 (1..4) {
129         foreach (1..4) {
130             $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 });
131         }
132     }
133 }
134 $employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]});
135
136 foreach my $group_id_2 (1..3) {
137     foreach my $group_id_3 (1..3) {
138         my $group_employees = $employees->search({group_id_2=>$group_id_2, group_id_3=>$group_id_3});
139         $group_employees->all();
140         ok( check_rs($group_employees), "group intial positions" );
141         hammer_rs( $group_employees );
142     }
143 }
144
145 # move_to_group, specifying group by hash
146 my $group_4 = $employees->search({group_id_2=>4});
147 $to_group = 1;
148 my $to_group_2_base = 7;
149 my $to_group_2 = 1;
150 $to_pos = undef;
151
152 {
153   my @empl = $group_3->all;
154   while (my $employee = shift @empl) {
155     $employee->move_to_group({group_id_2=>$to_group, group_id_3=>$to_group_2}, $to_pos);
156     $to_pos++;
157     $to_group = ($to_group % 3) + 1;
158     $to_group_2_base++;
159     $to_group_2 = (
160       POSIX::ceil( $to_group_2_base / 3.0 ) % 3
161     ) + 1;
162   }
163 }
164 foreach my $group_id_2 (1..4) {
165     foreach my $group_id_3 (1..4) {
166         my $group_employees = $employees->search({group_id_2=>$group_id_2,group_id_3=>$group_id_3});
167         ok( check_rs($group_employees), "group positions after move_to_group" );
168     }
169 }
170
171 $employees->delete();
172 foreach my $group_id_2 (1..4) {
173     foreach my $group_id_3 (1..4) {
174         foreach (1..4) {
175             $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 });
176         }
177     }
178 }
179 $employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]});
180
181 $employee = $employees->search({group_id_2=>4, group_id_3=>1})->first;
182 $employee->group_id_2(1);
183 $employee->update;
184 ok(
185     check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1}))
186     && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>1})),
187     "overloaded multicol update 1"
188 );
189
190 $employee = $employees->search({group_id_2=>4, group_id_3=>1})->first;
191 $employee->update({group_id_2=>2});
192 ok( check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1}))
193     && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>1})),
194    "overloaded multicol update 2"
195 );
196
197 $employee = $employees->search({group_id_2=>3, group_id_3=>1})->first;
198 $employee->group_id_2(1);
199 $employee->group_id_3(3);
200 $employee->update();
201 ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1}))
202     && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>3})),
203     "overloaded multicol update 3"
204 );
205
206 $employee = $employees->search({group_id_2=>3, group_id_3=>1})->first;
207 $employee->update({group_id_2=>2, group_id_3=>3});
208 ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1}))
209     && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>3})),
210     "overloaded multicol update 4"
211 );
212
213 $employee = $employees->search({group_id_2=>3, group_id_3=>2})->first;
214 $employee->update({group_id_2=>2, group_id_3=>4, position=>2});
215 ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>2}))
216     && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>4})),
217     "overloaded multicol update 5"
218 );
219
220 sub hammer_rs {
221     my $rs = shift;
222     my $employee;
223     my $count = $rs->count();
224     my $position_column = $rs->result_class->position_column();
225     my $row;
226
227     foreach my $position (1..$count) {
228
229         ($row) = $rs->search({ $position_column=>$position })->all();
230         $row->move_previous();
231         ok( check_rs($rs), "move_previous( $position )" );
232
233         ($row) = $rs->search({ $position_column=>$position })->all();
234         $row->move_next();
235         ok( check_rs($rs), "move_next( $position )" );
236
237         ($row) = $rs->search({ $position_column=>$position })->all();
238         $row->move_first();
239         ok( check_rs($rs), "move_first( $position )" );
240
241         ($row) = $rs->search({ $position_column=>$position })->all();
242         $row->move_last();
243         ok( check_rs($rs), "move_last( $position )" );
244
245         foreach my $to_position (1..$count) {
246             ($row) = $rs->search({ $position_column=>$position })->all();
247             $row->move_to($to_position);
248             ok( check_rs($rs), "move_to( $position => $to_position )" );
249         }
250
251         $row = $rs->find({ position => $position });
252         if ($position==1) {
253             ok( !$row->previous_sibling(), 'no previous sibling' );
254             ok( !$row->first_sibling(), 'no first sibling' );
255             ok( $row->next_sibling->position > $position, 'next sibling position > than us');
256             is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us');
257             ok( $row->last_sibling->position > $position, 'last sibling position > than us');
258         }
259         else {
260             ok( $row->previous_sibling(), 'previous sibling' );
261             ok( $row->first_sibling(), 'first sibling' );
262             ok( $row->previous_sibling->position < $position, 'prev sibling position < than us');
263             is( $row->previous_sibling->next_sibling->position, $position, 'prev-next sibling is us');
264             ok( $row->first_sibling->position < $position, 'first sibling position < than us');
265         }
266         if ($position==$count) {
267             ok( !$row->next_sibling(), 'no next sibling' );
268             ok( !$row->last_sibling(), 'no last sibling' );
269             ok( $row->previous_sibling->position < $position, 'prev sibling position < than us');
270             is( $row->previous_sibling->next_sibling->position, $position, 'prev-next sibling is us');
271             ok( $row->first_sibling->position < $position, 'first sibling position < than us');
272         }
273         else {
274             ok( $row->next_sibling(), 'next sibling' );
275             ok( $row->last_sibling(), 'last sibling' );
276             ok( $row->next_sibling->position > $row->position, 'next sibling position > than us');
277             is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us');
278             ok( $row->last_sibling->position > $row->position, 'last sibling position > than us');
279         }
280
281     }
282 }
283
284 sub check_rs {
285     my( $rs ) = @_;
286     $rs->reset();
287     my $position_column = $rs->result_class->position_column();
288     my $expected_position = 0;
289     while (my $row = $rs->next()) {
290         $expected_position ++;
291         if ($row->get_column($position_column)!=$expected_position) {
292             return 0;
293         }
294     }
295     return 1;
296 }
297
298 done_testing;