File Coverage

blib/lib/XAO/testcases/FS/fields.pm
Criterion Covered Total %
statement 21 411 5.1
branch 0 12 0.0
condition 0 34 0.0
subroutine 7 53 13.2
pod 0 20 0.0
total 28 530 5.2


line stmt bran cond sub pod time code
1             package XAO::testcases::FS::fields;
2 1     1   736 use strict;
  1         2  
  1         28  
3 1     1   513 use XAO::Utils;
  1         19416  
  1         62  
4 1     1   463 use XAO::Objects;
  1         5312  
  1         46  
5 1     1   7 use Error qw(:try);
  1         2  
  1         5  
6              
7 1     1   136 use base qw(XAO::testcases::FS::base);
  1         3  
  1         490  
8              
9             sub test_utf8_non_bmp {
10 0     0 0   my $self=shift;
11              
12 0           my $odb=$self->get_odb();
13              
14 0           my $global=$odb->fetch('/');
15 0           $self->assert(ref($global), "Failure getting / reference");
16              
17 0           $global->add_placeholder(
18             name => 'text',
19             type => 'text',
20             charset => 'utf8',
21             maxlength => 50,
22             );
23              
24 1     1   677 use utf8;
  1         24  
  1         5  
25              
26             # The non-BMP (Basic Multilingual Plane, 0x0000-0xffff) unicode
27             # characters don't work with MySQL. They result in the string
28             # truncation at the unicode character.
29             #
30 0           my $unicode="Smile - \x{1f600} - After";
31 0           my $result='';
32 0           my $error;
33             try {
34 0     0     $global->put(text => $unicode);
35 0           $result=$global->get('text');
36             }
37             otherwise {
38 0     0     my $etext=''.shift;
39 0           dprint "Expected error: $etext";
40 0           $error=1;
41 0           };
42              
43 0           $self->assert($error,
44             "Expected a failure for supplemental unicode string '$unicode', got '$result'");
45             }
46              
47             sub test_space_stripping {
48 0     0 0   my $self=shift;
49              
50 0           my $odb=$self->get_odb();
51              
52 0           my $global=$odb->fetch('/');
53 0           $self->assert(ref($global), "Failure getting / reference");
54              
55             ##
56             # Spaces at the end of string are chopped off at least by
57             # MySQL. Documented bug.
58             #
59 0           foreach my $text (" aaa .") {
60 0           $global->put(project => $text);
61 0           my $got=$global->get('project');
62 0           $self->assert($got eq $text,
63             "Field update ('$text' != '$got')");
64             }
65             }
66              
67             sub test_8bit_transparency {
68 0     0 0   my $self=shift;
69              
70 0           my $odb=$self->get_odb();
71              
72 0           my $global=$odb->fetch('/');
73 0           $self->assert(ref($global), "Failure getting / reference");
74              
75             # For compatibility no charset means binary transparency, checking for it
76             #
77 0           $global->add_placeholder(
78             name => 'text',
79             type => 'text',
80             maxlength => 3,
81             );
82 0           $global->add_placeholder(
83             name => 'tbin',
84             type => 'text',
85             maxlength => 3,
86             charset => 'binary',
87             );
88 0           $global->add_placeholder(
89             name => 'bin',
90             type => 'blob',
91             maxlength => 3,
92             );
93              
94 1     1   345 use bytes;
  1         3  
  1         5  
95              
96 0           foreach my $code (0..31,128..255) {
97 0           my $char=chr($code).chr($code).chr($code);
98              
99 0           foreach my $fname (qw(text tbin bin)) {
100 0           $global->put($fname => $char);
101 0           my $got=$global->get($fname);
102             ### dprint "char='$char', got='$got'";
103 0           $self->assert($char eq $got,
104             "Bin.transparency failure on code $code, got '$got' for field '$fname' (".ord($got).")");
105             }
106             }
107             }
108              
109             sub test_delete_field {
110 0     0 0   my $self=shift;
111              
112 0           my $odb=$self->get_odb();
113              
114 0           my $global=$odb->fetch('/');
115 0           $self->assert(ref($global), "Failure getting / reference");
116              
117 0           $global->put(project => '123abc');
118 0           $global->delete('project');
119              
120 0           my $got=$global->get('project');
121 0   0       $self->assert(defined($got) && $got eq '',
122             "Field is incorrect after delete");
123              
124             }
125              
126             sub test_fetch {
127 0     0 0   my $self=shift;
128              
129 0           my $odb=$self->get_odb();
130              
131 0           my $cust=$odb->fetch('/Customers/c1');
132 0           $self->assert($cust, 'Hash object fetch failed');
133              
134 0           my $custlist=$odb->fetch('/Customers');
135 0           $self->assert($cust, 'List object fetch failed');
136             }
137              
138             sub test_container_key {
139 0     0 0   my $self=shift;
140              
141 0           my $odb=$self->get_odb();
142              
143 0           my $cust=$odb->fetch('/Customers/c1');
144 0           $self->assert($cust, 'Hash object fetch failed');
145              
146 0           my $ckey=$cust->container_key();
147 0           $self->assert($ckey eq 'c1',
148             "container_key() returned bad value ('$ckey'!='c1')");
149             }
150              
151             sub test_defined {
152 0     0 0   my $self=shift;
153              
154 0           my $odb=$self->get_odb();
155              
156 0           my $cust=$odb->fetch('/Customers/c1');
157 0           $self->assert($cust, 'Hash object fetch failed');
158              
159 0           $cust->put(name => 'aaaa');
160              
161 0           $self->assert($cust->defined('name'),
162             "Method defined('name') returned false instead of true");
163             }
164              
165             sub test_exists {
166 0     0 0   my $self=shift;
167              
168 0           my $odb=$self->get_odb();
169              
170 0           my $cust=$odb->fetch('/Customers/c1');
171 0           $self->assert($cust, 'Hash object fetch failed');
172              
173 0           $self->assert($cust->exists('name'),
174             "Method exists('name') returned false instead of true");
175              
176 0           $self->assert(!$cust->exists('nonexistent'),
177             "Method exists('nonexistent') returned true instead of false");
178              
179 0           $self->assert($cust->exists('unique_id'),
180             "Method exists('unique_id') returned false instead of true");
181             }
182              
183             sub test_keys {
184 0     0 0   my $self=shift;
185              
186 0           my $odb=$self->get_odb();
187              
188 0           my $cust=$odb->fetch('/Customers/c1');
189 0           $self->assert($cust, 'Hash object fetch failed');
190              
191 0           my $keys=join(',',sort $cust->keys());
192 0           $self->assert($keys eq 'customer_id,name',
193             "Keys are wrong for customer ('$keys'!='customer_id,name')");
194             }
195              
196             sub test_is_attached {
197 0     0 0   my $self=shift;
198              
199 0           my $odb=$self->get_odb();
200              
201 0           my $cust=$odb->fetch('/Customers/c1');
202 0           $self->assert($cust, 'Hash object fetch failed');
203              
204 0           $self->assert($cust->is_attached(),
205             "Is_attached() returned false on attached object");
206              
207 0           my $newcust=$odb->fetch('/Customers')->get_new();
208 0           $self->assert(! $newcust->is_attached(),
209             "Is_attached() returned true on detached object");
210             }
211              
212             sub test_values {
213 0     0 0   my $self=shift;
214              
215 0           my $odb=$self->get_odb();
216              
217 0           my $cust=$odb->fetch('/Customers/c1');
218 0           $self->assert($cust, 'Hash object fetch failed');
219              
220 0           $cust->add_placeholder(name => 'xxx',
221             type => 'text',
222             maxlength => 20,
223             );
224              
225 0           $cust->put(name => 'foo');
226 0           $cust->put(xxx => '123');
227              
228 0           my %v;
229 0           @v{$cust->keys()}=$cust->values();
230 0           my $v=join(",",map { $v{$_} } sort keys %v);
  0            
231              
232 0           $self->assert($v eq 'c1,foo,123',
233             "Values() returned wrong list ('$v'!='c1,foo,123')");
234             }
235              
236             sub test_describe {
237 0     0 0   my $self=shift;
238 0           my $odb=$self->get_odb();
239 0           my $cust=$odb->fetch('/Customers/c1');
240              
241 0           $cust->add_placeholder(name => 'xxx',
242             type => 'text',
243             maxlength => 123,
244             );
245              
246 0           my $desc=$cust->describe('xxx');
247 0           $self->assert(ref($desc),
248             "Describe() did not return field description");
249 0           $self->assert($desc->{name} eq 'xxx',
250             "Describe() returned wrong name ($desc->{name}!='xxx')");
251 0           $self->assert($desc->{type} eq 'text',
252             "Describe() returned wrong type ($desc->{type}!='text')");
253 0           $self->assert($desc->{maxlength} eq 123,
254             "Describe() returned wrong maxlength ($desc->{maxlength}!='123')");
255 0           $self->assert($desc->{default} eq '',
256             "Describe() returned wrong default ($desc->{default})");
257             }
258              
259             sub test_integer {
260 0     0 0   my $self=shift;
261 0           my $odb=$self->get_odb();
262 0           my $cust=$odb->fetch('/Customers/c1');
263              
264 0           foreach my $max (100, 100000, 100000000) {
265              
266 0           $cust->add_placeholder(name => 'int',
267             type => 'integer',
268             minvalue => 20,
269             maxvalue => $max);
270              
271 0           my $value=int($max/2);
272 0           $cust->put(int => $value);
273 0           my $got=$cust->get('int');
274 0           $self->assert($got == $value,
275             "Got not what was stored ($got!=$value)");
276              
277 0           my $stored=1;
278             try {
279 0     0     $cust->put(int => $max+1);
280             }
281             otherwise {
282 0     0     $stored=0;
283 0           };
284 0           $self->assert(!$stored,
285             "Allowed to store value bigger then maxvalue (max=$max)");
286 0           $self->assert($cust->get('int') == $value,
287             "Value was corrupted by unsuccessful store (max=$max)");
288              
289 0           $stored=1;
290             try {
291 0     0     $cust->put(int => $max);
292             }
293             otherwise {
294 0     0     $stored=0;
295 0           };
296 0           $self->assert($stored,
297             "Does not allow to store value equal to maxvalue (max=$max)");
298              
299 0           $stored=1;
300             try {
301 0     0     $cust->put(int => 10);
302             }
303             otherwise {
304 0     0     $stored=0;
305 0           };
306 0           $self->assert(!$stored,
307             "Allowed to store value less then minvalue (max=$max)");
308 0           $self->assert($cust->get('int') == $max,
309             "Value was corrupted by unsuccessful store (max=$max)");
310              
311 0           $cust->drop_placeholder('int');
312             }
313             }
314              
315             sub test_decimal {
316 0     0 0   my $self=shift;
317 0           my $odb=$self->get_odb();
318 0           my $cust=$odb->fetch('/Customers/c1');
319              
320 0           $cust->add_placeholder(
321             name => 'decimal',
322             type => 'real',
323             minvalue => -100,
324             scale => 2,
325             index => 1,
326             );
327              
328 0           my @tests=(
329             { value => 0,
330             expect => 0.00,
331             },
332             { value => 0.1,
333             expect => 0.1,
334             },
335             { value => 0.01,
336             expect => 0.01,
337             },
338             { value => 0.001,
339             expect => 0.00,
340             },
341             { value => -99.999,
342             expect => -100.00,
343             },
344             { value => 1234567890.01,
345             expect => 1234567890.01,
346             },
347             );
348              
349 0           foreach my $test (@tests) {
350 0           $cust->put(decimal => $test->{'value'});
351              
352 0           my $got=$cust->get('decimal');
353              
354 0           my $expect=$test->{'expect'};
355              
356 0 0         if(abs($expect)<0.0001) {
357 0 0         $self->assert(($got ? undef : 'bad'),
358             "Expected zero value ($expect) to be a logical false, got '$got'");
359             }
360              
361 0           $self->assert(abs($got - $expect)<0.00001,
362             "For value '$test->{'value'}' expected '$expect', got '$got'");
363             }
364             }
365              
366             sub test_real {
367 0     0 0   my $self=shift;
368 0           my $odb=$self->get_odb();
369 0           my $cust=$odb->fetch('/Customers/c1');
370              
371 0           foreach my $max (100, 1e20) {
372              
373 0           $cust->add_placeholder(name => 'real',
374             type => 'real',
375             minvalue => 20,
376             maxvalue => $max);
377              
378 0           my $value=$max/2;
379 0           $cust->put(real => $value);
380 0           my $got=$cust->get('real');
381 0           $self->assert($got == $value,
382             "Got not what was stored ($got!=$value)");
383              
384 0           my $stored=1;
385             try {
386 0     0     $cust->put(real => $max*1.1);
387             }
388             otherwise {
389 0     0     $stored=0;
390 0           };
391 0           $self->assert(!$stored,
392             "Allowed to store value bigger then maxvalue (max=$max)");
393 0           $self->assert($cust->get('real') == $value,
394             "Value was corrupted by unsuccessful store (max=$max)");
395              
396 0           $stored=1;
397             try {
398 0     0     $cust->put(real => $max);
399             }
400             otherwise {
401 0     0     $stored=0;
402 0           };
403 0           $self->assert($stored,
404             "Does not allow to store value equal to maxvalue (max=$max)");
405              
406 0           $stored=1;
407             try {
408 0     0     $cust->put(real => 10);
409             }
410             otherwise {
411 0     0     $stored=0;
412 0           };
413 0           $self->assert(!$stored,
414             "Allowed to store value less then minvalue (max=$max)");
415 0           $self->assert($cust->get('real') == $max,
416             "Value was corrupted by unsuccessful store (max=$max)");
417              
418 0           $cust->drop_placeholder('real');
419             }
420              
421 0           my $clist=$odb->fetch('/Customers');
422 0           my $nc=$clist->get_new();
423 0           $nc->add_placeholder(name => 'real',
424             type => 'real');
425              
426 0           $nc->put(real => 123.45);
427 0           $clist->put('new' => $nc);
428 0           $nc=$clist->get('new');
429              
430 0           $self->assert(ref($nc),
431             "Can't get stored object with real field");
432 0           my $got=$nc->get('real');
433 0           $self->assert($got == 123.45,
434             "Got wrong real value ($got!=123.45)");
435              
436 0           $nc->put(real => 0.000);
437              
438 0           $got=$nc->get('real');
439              
440 0 0         $self->assert(($got ? undef : 'bad'),
441             "Expected zero value to be a logical false, got '$got'");
442             }
443              
444             sub test_defaults {
445 0     0 0   my $self=shift;
446              
447 0           my $odb=$self->get_odb();
448              
449 0           my $list=$odb->fetch('/Customers');
450              
451 0           my %tests=(
452             t001 => {
453             field => {
454             type => 'text',
455             maxlength => 20,
456             },
457             expect => '',
458             vlist => [
459             '' => '',
460             'aaa' => 'aaa',
461             '0.0' => '0.0',
462             '0000' => '0000',
463             ],
464             },
465             t100 => {
466             field => {
467             type => 'integer',
468             default => 'foo',
469             },
470             expect_error => 1,
471             },
472             t101 => {
473             field => {
474             type => 'integer',
475             },
476             expect => 0,
477             vlist => [
478             0 => 0,
479             1 => 1,
480             -99 => -99,
481             '' => 0,
482             '00' => 0,
483             -0 => 0,
484             -007 => -7,
485             1.4 => 1,
486             1.5 => 1,
487             '1.50' => 1,
488             1.99 => 1,
489             -1.99 => -1,
490             -77.7 => -77,
491             ],
492             },
493             t102 => {
494             field => {
495             type => 'integer',
496             default => 7,
497             },
498             expect => 7,
499             },
500             t103 => {
501             field => {
502             type => 'integer',
503             minvalue => 7,
504             },
505             expect => 7,
506             },
507             t104 => {
508             field => {
509             type => 'integer',
510             maxvalue => 777,
511             },
512             expect => 0,
513             },
514             t105 => {
515             field => {
516             type => 'integer',
517             maxvalue => -777,
518             },
519             expect => -777,
520             },
521             t106 => {
522             field => {
523             type => 'integer',
524             minvalue => -999,
525             maxvalue => -777,
526             },
527             expect => -999,
528             },
529             t107 => {
530             field => {
531             type => 'integer',
532             minvalue => 999,
533             maxvalue => -777,
534             },
535             expect_error => 1,
536             },
537             t108 => {
538             field => {
539             type => 'integer',
540             minvalue => 111,
541             maxvalue => 333,
542             default => 222,
543             },
544             expect => 222,
545             },
546             t109 => {
547             field => {
548             type => 'integer',
549             minvalue => 111,
550             maxvalue => 333,
551             default => 444,
552             },
553             expect_error => 1,
554             },
555             #
556             t200 => {
557             field => {
558             type => 'real',
559             default => 'foo',
560             },
561             expect_error => 1,
562             },
563             t201 => {
564             field => {
565             type => 'real',
566             },
567             expect => 0,
568             vlist => [
569             0 => 0,
570             1 => 1,
571             -99 => -99,
572             '' => 0,
573             '00' => 0,
574             -0 => 0,
575             -007 => -7,
576             1.4 => 1.4,
577             1.5 => 1.5,
578             '1.50' => 1.5,
579             1.99 => 1.99,
580             -1.99 => -1.99,
581             -77.7 => -77.7,
582             ],
583             },
584             t202 => {
585             field => {
586             type => 'real',
587             scale => 2,
588             },
589             expect => 0,
590             vlist => [
591             1 => '1.00',
592             -99 => '-99.00',
593             -007 => '-7.00',
594             1.4 => '1.40',
595             1.5 => '1.50',
596             '1.50' => '1.50',
597             1.99 => '1.99',
598             -1.99 => '-1.99',
599             -77.7 => '-77.70',
600             '.123' => '0.12',
601             '-1.456'=> '-1.46',
602             ],
603             },
604             t203 => {
605             field => {
606             type => 'real',
607             default => 1.234,
608             },
609             expect => 1.234,
610             },
611             t204 => {
612             field => {
613             type => 'real',
614             minvalue => -10,
615             },
616             expect => 0,
617             },
618             t205 => {
619             field => {
620             type => 'real',
621             minvalue => 10,
622             },
623             expect => 10,
624             },
625             );
626              
627 0           foreach my $tname (keys %tests) {
628 0           my $tdata=$tests{$tname};
629              
630 0           my $fdesc=$tdata->{'field'};
631 0   0       $fdesc->{'name'}||=$tname;
632 0           my $name=$fdesc->{'name'};
633              
634 0 0         if($tdata->{'expect_error'}) {
635 0           my $errored;
636             try {
637 0     0     $list->get_new->add_placeholder($fdesc);
638             }
639             otherwise {
640 0     0     dprint "Expected error: ".shift;
641 0           $errored=1;
642 0           };
643 0           $self->assert($errored,
644             "Expected $tname to error, but passed successfully");
645 0           next;
646             }
647             else {
648 0           $list->get_new->add_placeholder($fdesc);
649             }
650              
651             # Unattached object
652             #
653 0           my $expect=$tdata->{'expect'};
654 0           my $nobj=$list->get_new;
655 0           my $got=$nobj->get($name);
656 0   0       $self->assert($got eq $expect,
657             "Expected $name to be $expect, got ".($got//'')." for $tname (unattached-1, initial)");
658              
659             # Storing as is, without modification or values
660             #
661 0           my $id=$list->put($nobj);
662              
663 0           $got=$nobj->get($name);
664 0   0       $self->assert($got eq $expect,
665             "Expected $name to be $expect, got ".($got//'')." for $tname (unattached-2, initial)");
666              
667 0           $got=$list->get($id)->get($name);
668 0   0       $self->assert($got eq $expect,
669             "Expected $name to be $expect, got ".($got//'')." for $tname (stored, initial)");
670              
671 0           $list->delete($id);
672              
673             # Storing values, validating them as received.
674             #
675 0   0       my $vlist=$tdata->{'vlist'} || [];
676 0           for(my $i=0; $i
677 0           my $v=$vlist->[$i];
678 0           $expect=$vlist->[$i+1];
679              
680 0           $nobj=$list->get_new;
681 0           $nobj->put($name => $v);
682              
683 0           $got=$nobj->get($name);
684 0   0       $self->assert($got eq $expect,
685             "Expected $name to be '$expect', got '".($got//'')."' after putting '$v' for $tname (unattached-1, vlist)");
686              
687 0           $id=$list->put($nobj);
688              
689 0           $got=$nobj->get($name);
690 0   0       $self->assert($got eq $expect,
691             "Expected $name to be '$expect', got '".($got//'')."' after putting '$v' for $tname (unattached-2, vlist)");
692              
693 0           $got=$list->get($id)->get($name);
694 0   0       $self->assert($got eq $expect,
695             "Expected $name to be '$expect', got '".($got//'')."' after putting '$v' for $tname (stored-1, vlist)");
696              
697 0           $list->delete($id);
698 0           $id=$list->put($list->get_new);
699 0           $list->get($id)->put($name => $v);
700              
701 0           $got=$list->get($id)->get($name);
702 0   0       $self->assert($got eq $expect,
703             "Expected $name to be '$expect', got '".($got//'')."' after putting '$v' for $tname (stored-2, vlist)");
704             }
705              
706 0           $list->get_new->drop_placeholder($name);
707             }
708             }
709              
710             sub test_unique {
711 0     0 0   my $self=shift;
712 0           my $odb=$self->get_odb();
713              
714 0           my $list=$odb->fetch('/Customers');
715 0           $list->destroy();
716              
717 0           foreach my $type (qw(text blob integer real)) {
718              
719 0           my $c=$list->get_new();
720              
721 0 0 0       $c->add_placeholder(
722             name => 'uf',
723             type => $type,
724             unique => 1,
725             maxlength => ($type eq 'text' || $type eq 'blob') ? 100 : undef,
726             );
727              
728 0           $c->put(uf => 1);
729              
730 0           $list->put(u1 => $c);
731 0           my $c1=$list->get('u1');
732 0           $self->assert(ref($c1),
733             "Can't get stored object");
734 0           $self->assert($c1->get('uf') == 1,
735             "Wrong value in the unique field of the first object (1)");
736 0           my $mistake;
737              
738             # MySQL is noisy about mistakes that we expect. So we hide DBD
739             # messages.
740             #
741 0           $self->stderr_stop();
742             try {
743 0     0     $list->put(u2 => $c);
744 0           $mistake=1;
745             } otherwise {
746 0     0     $mistake=0;
747 0           };
748 0           $self->stderr_restore();
749 0           $self->assert(! $mistake,
750             "Succeded in putting the same object twice, 'unique' does not work");
751              
752 0           $c->put(uf => 2);
753 0           $list->put(u2 => $c);
754 0           my $c2=$list->get('u2');
755 0           $self->assert(ref($c2),
756             "Can't get stored object");
757 0           $self->assert($c2->get('uf') == 2,
758             "Wrong value in the unique field of the first object (2)");
759              
760 0           $c2->put(uf => 3);
761 0           $self->assert($c2->get('uf') == 3,
762             "Wrong value in the unique field of the first object (3)");
763              
764 0           $self->stderr_stop();
765             try {
766 0     0     $c1->put(uf => 3);
767 0           $mistake=1;
768             } otherwise {
769 0     0     $mistake=0;
770 0           };
771 0           $self->stderr_restore();
772 0           $self->assert(! $mistake,
773             "Succeded in storing two equal values into unique field");
774 0           $self->assert($c1->get('uf') == 1,
775             "Unique field produced error and still stored second value");
776              
777 0           $c->drop_placeholder('uf');
778 0           $list->destroy();
779             }
780             }
781              
782             # Checking how 'unique' works for second level objects. The trick with
783             # them is that the field should be unique in the space of an enclosing
784             # container, but two containers can have identical properties.
785             #
786             sub test_unique_2 {
787 0     0 0   my $self=shift;
788 0           my $odb=$self->get_odb();
789              
790 0           my $list=$odb->fetch('/Customers');
791 0           my $c1=$list->get('c1');
792 0           my $c2=$list->get('c2');
793              
794 0           foreach my $type (qw(text blob integer real)) {
795 0           $c1->add_placeholder(
796             name => 'Orders',
797             type => 'list',
798             class => 'Data::Order',
799             key => 'order_id',
800             );
801              
802 0           my $order=$c1->get('Orders')->get_new;
803              
804 0 0 0       $order->add_placeholder(
805             name => 'foo',
806             type => $type,
807             unique => 1,
808             maxlength => ($type eq 'text' || $type eq 'blob') ? 100 : undef,
809             );
810              
811 0           $order->put(foo => 1);
812              
813 0           my $c1list=$c1->get('Orders');
814 0           my $c2list=$c2->get('Orders');
815              
816 0           my $mistake;
817 0           $self->stderr_stop();
818             try {
819 0     0     $c1list->put(o1 => $order);
820 0           $c2list->put(o1 => $order);
821 0           $mistake=0;
822             }
823             otherwise {
824 0     0     $mistake=1;
825 0           };
826 0           $self->stderr_restore();
827 0           $self->assert(! $mistake,
828             "Can't put the same object into two different parents' lists");
829              
830 0           $self->stderr_stop();
831             try {
832 0     0     $c1list->put(o2 => $order);
833 0           $mistake=1;
834             }
835             otherwise {
836 0     0     $mistake=0;
837 0           };
838 0           $self->stderr_restore();
839 0           $self->assert(! $mistake,
840             "Put the same object twice (type=$type), 'unique' does not work on the second level");
841              
842 0           $order->put(foo => 2);
843 0           $c2list->put(o2 => $order);
844              
845 0           $self->stderr_stop();
846             try {
847 0     0     $c2list->put(o1 => $order);
848 0           $mistake=1;
849             } otherwise {
850 0     0     $mistake=0;
851 0           };
852 0           $self->stderr_restore();
853 0           $self->assert(! $mistake,
854             "Put the same object twice (type=$type), replacement");
855              
856 0           $self->assert(! $c1list->exists('o2'),
857             "Got o2 from the c1list");
858              
859 0           $self->assert($c1list->get('o1')->get('foo') eq '1',
860             "Got wrong value from c1list");
861 0           $self->assert($c2list->get('o1')->get('foo') eq '1',
862             "Got wrong value from c2list/o2");
863 0           $self->assert($c2list->get('o2')->get('foo') eq '2',
864             "Got wrong value from c2list/o2");
865              
866 0           dprint "Dropping placeholder Orders/foo";
867 0           $order->drop_placeholder('foo');
868              
869 0           dprint "Dropping placeholder Orders";
870 0           $c1->drop_placeholder('Orders');
871             }
872             }
873              
874             sub test_get_multi {
875 0     0 0   my $self=shift;
876              
877 0           my $odb=$self->get_odb();
878              
879 0           my $cust=$odb->fetch('/Customers/c1');
880 0           $self->assert($cust, 'Hash object fetch failed');
881              
882 0           $cust->add_placeholder(name => 'xxx',
883             type => 'text',
884             maxlength => 50,
885             );
886              
887 0           $cust->put(name => 'foo', xxx => '123');
888              
889 0           my ($name_1,$xxx_1)=$cust->get(qw(name xxx));
890 0           my ($xxx_2,$name_2)=$cust->get(qw(xxx name));
891              
892 0           $self->assert($name_1 eq 'foo',
893             "test_get_multi: Got wrong name_1");
894 0           $self->assert($xxx_1 eq '123',
895             "test_get_multi: Got wrong xxx_1");
896 0   0       $self->assert($xxx_1 eq $xxx_2 && $name_1 eq $name_2,
897             "test_get_multi: Order of stuff is wrong on second call");
898              
899 0           my $global=$odb->fetch('/');
900 0           my @val=$global->get(sort $global->keys);
901 0           $self->assert(@val == 2,
902             "test_get_multi: Global returned wrong number of values");
903 0   0       $self->assert(ref($val[0]) && $val[0]->objtype eq 'List',
904             "test_get_multi: Global did not return list reference");
905              
906              
907 0           my $nc=$odb->fetch('/Customers')->get_new();
908 0           $nc->put({ name => 'abc', xxx => 'zzz'});
909 0           my ($xxx,$name)=$nc->get(qw(xxx name));
910 0           $self->assert($name eq 'abc',
911             "test_get_multi: Got wrong name");
912 0           $self->assert($xxx eq 'zzz',
913             "test_get_multi: Got wrong xxx");
914             }
915              
916             ##
917             # Checks how translation from undef to default values work. Undefs are
918             # not supported by XAO::FS and therefore are never returned.
919             #
920             sub test_null {
921 0     0 0   my $self=shift;
922              
923 0           my $odb=$self->get_odb();
924              
925 0           my $clist=$odb->fetch('/Customers');
926 0           $self->assert($clist, 'List object fetch failed');
927 0           my $cust=$clist->get('c1');
928 0           $self->assert($cust, 'Hash object fetch failed');
929              
930 0           $cust->add_placeholder(name => 'text',
931             type => 'text',
932             maxlength=> 50,
933             );
934 0           $cust->add_placeholder(name => 'text2',
935             type => 'text',
936             default => 'test',
937             maxlength=> 50,
938             );
939 0           $cust->add_placeholder(name => 'blob',
940             type => 'blob',
941             default => "\x80\x82\x84\x86",
942             maxlength=> 50,
943             );
944 0           $cust->add_placeholder(name => 'integer',
945             type => 'integer',
946             );
947 0           $cust->add_placeholder(name => 'real',
948             type => 'real',
949             );
950 0           $cust->add_placeholder(name => 'int1',
951             type => 'integer',
952             default => 10000,
953             );
954 0           $cust->add_placeholder(name => 'int2',
955             type => 'integer',
956             minvalue => 1000,
957             );
958 0           $cust->add_placeholder(name => 'real2',
959             type => 'real',
960             minvalue => 256,
961             );
962              
963 0           my %matrix=(
964             t1 => {
965             name => 'text',
966             default => '',
967             },
968             t2 => {
969             name => 'integer',
970             default => 0,
971             },
972             t3 => {
973             name => 'int1',
974             default => 10000,
975             },
976             t4 => {
977             name => 'int2',
978             default => 1000,
979             },
980             t5 => {
981             name => 'real',
982             default => 0,
983             },
984             t6 => {
985             name => 'real2',
986             default => 256,
987             },
988             t7 => {
989             name => 'text2',
990             default => 'test',
991             },
992             78 => {
993             name => 'blob',
994             default => "\x80\x82\x84\x86",
995             },
996             );
997              
998 0           foreach my $test (map { $matrix{$_} } sort keys %matrix) {
  0            
999 0           my $name=$test->{name};
1000 0           my $expect=$test->{default};
1001              
1002 0           my $c=$clist->get('c2');
1003              
1004 0           my $desc=$c->describe($name);
1005 0           $self->assert(defined($desc->{default}),
1006             "Default value not set in describe() for $name");
1007 0           $self->assert($desc->{default} eq $expect,
1008             "Default value is wrong for $name (got '$desc->{default}', expected '$expect')");
1009              
1010 0           my $got=$c->get($name);
1011 0           $self->assert(defined($got),
1012             "Got 'undef' for name=$name (initial)");
1013 0           $self->assert($got eq $expect,
1014             "Expect $expect, got $got for name=$name (initial)");
1015              
1016 0           $c->put($name => 12345);
1017              
1018 0           $c=$clist->get('c2');
1019              
1020 0           $c->delete($name);
1021              
1022 0           $got=$c->get($name);
1023 0           $self->assert(defined($got),
1024             "Got 'undef' for name=$name (deleted)");
1025 0           $self->assert($got eq $expect,
1026             "Expect $expect, got $got for name=$name (deleted)");
1027              
1028 0           $c->put($name => undef);
1029              
1030 0           $c=$clist->get('c2');
1031              
1032 0           $got=$c->get($name);
1033 0           $self->assert(defined($got),
1034             "Got 'undef' for name=$name (put undef)");
1035 0           $self->assert($got eq $expect,
1036             "Expect $expect, got $got for name=$name (put undef)");
1037              
1038 0           $c->put($name => $expect);
1039              
1040 0           $c=$clist->get('c2');
1041              
1042 0           $got=$c->get($name);
1043 0           $self->assert(defined($got),
1044             "Got 'undef' for name=$name (put default)");
1045 0           $self->assert($got eq $expect,
1046             "Expect $expect, got $got for name=$name (put default)");
1047              
1048             ##
1049             # Now the same on detached object
1050             #
1051 0           $c=$clist->get_new;
1052              
1053 0           $got=$c->get($name);
1054 0           $self->assert(defined($got),
1055             "Got 'undef' for name=$name (initial, detached)");
1056 0           $self->assert($got eq $expect,
1057             "Expect $expect, got $got for name=$name (initial, detached)");
1058              
1059 0           $c->put($name => 12345);
1060 0           $c->delete($name);
1061              
1062 0           $got=$c->get($name);
1063 0           $self->assert(defined($got),
1064             "Got 'undef' for name=$name (deleted, detached)");
1065 0           $self->assert($got eq $expect,
1066             "Expect $expect, got $got for name=$name (deleted, detached)");
1067              
1068 0           $c->put($name => undef);
1069              
1070 0           $got=$c->get($name);
1071 0           $self->assert(defined($got),
1072             "Got 'undef' for name=$name (put undef, detached)");
1073 0           $self->assert($got eq $expect,
1074             "Expect $expect, got $got for name=$name (put undef, detached)");
1075              
1076 0           $c->put($name => $expect);
1077              
1078 0           $got=$c->get($name);
1079 0           $self->assert(defined($got),
1080             "Got 'undef' for name=$name (put default, detached)");
1081 0           $self->assert($got eq $expect,
1082             "Expect $expect, got $got for name=$name (put default, detached)");
1083              
1084             }
1085             }
1086              
1087             1;