1
package tests::ConfigValuesTest;
5
use base qw/Test::Unit::TestSuite/;
7
use Lire::Config::TypeSpec;
8
use Lire::Config::Value;
12
return "Configuration Values Tests";
16
return qw/tests::ConfigScalarTest tests::ConfigListTest
17
tests::ConfigDictionaryTest /;
20
package tests::ConfigValueTest;
22
use base qw/Lire::Test::TestCase/;
25
my $self = shift->SUPER::new( @_ );
27
$self->{'config_spec'} = new Lire::Config::ConfigSpec();
28
$self->{'list_spec'} = new Lire::Config::ListSpec( 'name' => "list" );
29
$self->{'config_spec'}->add( $self->{'list_spec'} );
30
$self->{'int_spec'} = new Lire::Config::IntegerSpec( 'name' => "int" );
31
$self->{'config_spec'}->add( $self->{'int_spec'} );
32
$self->{'string_spec'} = new Lire::Config::StringSpec( 'name' => "string" );
33
$self->{'config_spec'}->add( $self->{'string_spec'} );
34
$self->{'list_spec'}->add( $self->{'int_spec'} );
35
$self->{'select_spec'} = new Lire::Config::SelectSpec( 'name' => "select" );
36
$self->{'config_spec'}->add( $self->{'select_spec'} );
37
$self->{'list_spec'}->add( $self->{'select_spec'} );
38
$self->{'select_spec'}->add( new Lire::Config::OptionSpec( 'name' => "option_1" ));
39
$self->{'select_spec'}->add( new Lire::Config::OptionSpec( 'name' => "option_2" ));
47
my $value = $self->type()->new( 'spec' => $self->spec() );
48
$self->assert_isa( $self->type(), $value );
49
$self->assert_str_equals( $self->spec()->name(), $value->name() );
51
my $proto = $value->new();
52
$self->assert_isa( $self->type(), $proto );
53
$self->assert_str_not_equals( $proto, $value );
54
$self->assert_deep_equals( $proto, $value );
56
$self->assert_dies( qr/missing 'spec' parameter/,
57
sub { $self->type()->new() } );
59
$self->assert_dies( qr/'spec' parameter.*should be a.*instance/,
60
sub { $self->type()->new( 'spec' => $self ) } );
64
sub test_as_shell_var {
67
my $value = $self->type()->new( 'spec' => $self->spec() );
68
my $name = $value->name();
69
$self->assert_matches( qr/$name=.*not supported/, $value->as_shell_var() );
75
my $value = $self->type()->new( 'spec' => $self->spec() );
76
my $clone = $value->clone();
78
$self->assert_str_not_equals( $value, $clone );
79
$self->assert_deep_equals( $value, $clone );
80
$self->assert_str_equals( $value->{'spec'}, $clone->{'spec'} );
86
my $value = $self->type()->new( 'spec' => $self->spec() );
87
$self->assert( $value->is_equals( $value ), 'is_equals( $self )' );
88
$self->assert( $value->is_equals( $value->clone() ),
89
'is_equals( clone )' );
91
# Changing the spec, should returns false.
92
my $other_value = $value->clone();
93
$other_value->{'spec'} = {};
94
$self->assert( ! $value->is_equals( $other_value ),
95
'! is_equals( other_spec )' );
101
my $default = $self->spec()->instance();
102
$self->assert( ! $default->is_default(), "!is_default()" );
103
$self->spec()->default( $default );
105
my $value = $self->type()->new( 'spec' => $self->spec() );
106
$self->assert( $value->is_default(), "is_default() != 1" );
109
sub check_save_xml_default {
110
my ( $self, $value ) = @_;
112
my $name = $self->spec()->name();
113
my $fh = new IO::Scalar();
114
my $buf = $fh->sref();
115
$value->save_xml( $fh );
116
my $pos = index( $$buf, "<param name=\"$name\"" );
117
$self->assert( $pos >= 0, $$buf || 'Nothing written' );
119
$self->spec()->default( $value );
120
my $default = $self->spec()->instance();
122
$default->save_xml( $fh );
123
$self->assert_str_equals( '', $$buf );
125
$self->spec()->default( undef );
128
sub check_save_xml_obsolete {
129
my ( $self, $value ) = @_;
131
my $name = $self->spec()->name();
132
my $fh = new IO::Scalar();
133
my $buf = $fh->sref();
134
$self->spec()->obsolete( 1 );
135
$value->save_xml( $fh );
136
$self->assert_str_equals( '', $$buf );
138
$self->spec()->obsolete( 0 );
139
$value->save_xml( $fh, 0, 'lrcml:' );
140
my $pos = index( $$buf, "<lrcml:param name=\"$name\"" );
141
$self->assert( $pos >= 0, $$buf || 'Nothing written' );
147
my $value = $self->spec()->instance();
148
$self->check_save_xml_default( $value->clone() );
149
$self->check_save_xml_obsolete( $value->clone() );
152
package tests::ConfigScalarTest;
154
use base qw/tests::ConfigValueTest/;
157
return "Lire::Config::Scalar";
161
return $_[0]{'int_spec'};
167
$self->SUPER::test_new;
169
my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'},
173
$self->assert_equals( 10, $value->as_value() );
174
$self->assert_deep_equals( $value, $value->new() );
176
my $other = $value->new( 'value' => 11 );
177
$self->assert_num_equals( 11, $other->{'value'} );
184
my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} );
186
$self->assert_equals( 10, $value->as_value() );
188
$value = new Lire::Config::Scalar( 'spec' => $self->{'select_spec'} );
189
$value->set( "OPTION_1" );
190
$self->assert_equals( "OPTION_1", $value->get() );
191
$self->assert_equals( "option_1", $value->as_value() );
194
local $SIG{'__WARN__'} = sub { $warning .= join "", @_ };
195
$value = new Lire::Config::Scalar( 'spec' => $self->{'select_spec'} );
196
$value->{'value'} = "no_such_option";
197
my @array_context = $value->as_value();
198
$self->assert_matches( qr/invalid value for parameter 'select':/,
200
$self->assert_deep_equals( [], \@array_context );
202
# Second as_value() shouldn't emit another warning
204
$self->assert_null( scalar $value->as_value(),
205
"should return undef in scalar context" );
206
$self->assert_equals( '', $warning );
209
sub test_as_shell_var {
212
my $int = $self->type->new( 'spec' => $self->{'int_spec'}, value => 10 );
213
$self->assert_equals( "int='10'", $int->as_shell_var() );
215
my $undefined_int = $self->type->new( 'spec' => $self->{'int_spec'} );
216
$self->assert_equals( "", $undefined_int->as_shell_var() );
218
my $s = q{> Long string with shell `metacharacters`, 'quote', "double"};
219
my $quoted = q{> Long string with shell `metacharacters`, '\''quote'\'', "double"};
220
my $string = $self->type->new( 'spec' => $self->{'string_spec'}, value => $s );
221
$self->assert_equals( "string='$quoted'", $string->as_shell_var() );
223
local $SIG{'__WARN__'} = sub { $self->annotate( join "", @_ ) };
224
my $bad_option = $self->type->new( 'spec' => $self->{'select_spec'},
225
'value' => "bad_option" );
226
$self->assert_equals( '', $bad_option->as_shell_var() );
232
my $value = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} );
235
$self->assert_equals( 10, $value->get() );
238
my $oldwarn = $SIG{'__WARN__'};
239
$SIG{'__WARN__'} = sub { $warning = join(' ', @_); };
241
$SIG{'__WARN__'} = $oldwarn;
242
$self->assert_null($warning, "set() with invalid value should NOT warn");
248
$self->SUPER::test_is_equals();
250
my $string = new Lire::Config::Scalar( 'spec' => $self->{'string_spec'} );
251
my $other_string = $string->clone();
252
$string->{'value'} = 'A value';
253
my $int = new Lire::Config::Scalar( 'spec' => $self->{'int_spec'} );
254
my $other_int = $int->clone();
255
$int->{'value'} = 10;
257
$self->assert( ! $string->is_equals( $other_string ),
258
"! is_equals( undef )" );
259
$other_int->{'value'} = 11;
260
$self->assert( ! $int->is_equals( $other_int ), "! is_equals( 11 )" );
261
$other_int->{'value'} = "10.0000";
262
$self->assert( $int->is_equals( $other_int ), "is_equals( 10.00 )" );
266
package tests::ConfigListTest;
268
use base qw/tests::ConfigValueTest/;
271
return "Lire::Config::List";
275
return $_[0]{'list_spec'};
281
$self->SUPER::test_new();
283
my $list = $self->{'list_spec'}->instance();
284
$list->append( $self->{'select_spec'}->instance() );
285
$self->assert_deep_equals( $list, $list->new() );
291
local $SIG{'__WARN__'} = sub { $self->annotate( join "", @_ ) };
292
my $list = $self->{'list_spec'}->instance();
293
$self->assert_deep_equals( [], $list->as_value() );
294
$list->append( $self->{'int_spec'}->instance( 'value' => 10 ) );
295
$list->append( $self->{'select_spec'}->instance( 'value' => "option_1" ) );
296
$list->append( $self->{'select_spec'}->instance( 'value' => "no_such_option" ) );
297
$self->assert_deep_equals( [ 10, "option_1" ],
305
my $list = $self->{'list_spec'}->instance();
306
$self->assert( $list->is_valid(), 'is_valid()' );
308
$list->append( $self->{'int_spec'}->instance( 'value' => 'abc' ) );
309
$self->assert( !$list->is_valid(), '!is_valid()' );
310
$list->get( 0 )->set( '10' );
311
$self->assert( $list->is_valid(), 'is_valid()' );
312
$list->append( $self->{'select_spec'}->instance( 'value' => "bad_option"));
313
$self->assert( !$list->is_valid(), '!is_valid()' );
314
$list->get( 1 )->spec()->required( 0 );
315
$self->assert( $list->is_valid(), 'is_valid()' );
322
my $list = $self->{'list_spec'}->instance();
323
$self->assert_dies( qr/index out of bounds/,
324
sub { $list->get( 0 ) } );
326
my $int = $self->{'int_spec'}->instance( 'value' => 10 );
327
$list->append( $int );
328
$self->assert_equals( $int, $list->get( 0 ) );
329
$self->assert_equals( $int, $list->get( -1 ) );
331
$self->assert_dies( qr/'idx' parameter should be an integer/,
332
sub { $list->get( "string" ) } );
338
my $list = $self->{'list_spec'}->instance();
339
$self->assert_dies( qr/missing 'idx' parameter/,
340
sub { $list->set() });
341
my $int = $self->{'int_spec'}->instance( 'value' => 10 );
342
$self->assert_dies( qr/index out of bounds: 0/,
343
sub { $list->set( 0, $int ) } );
344
$list->append( $int );
345
$self->assert_dies( qr/missing 'value' parameter/,
346
sub { $list->set( 0, undef ) } );
348
$int = $self->{'int_spec'}->instance( 'value' => 5 );
349
$list->set( 0, $int );
350
$self->assert_str_equals( $int, $list->{'elements'}[0] );
356
my $list = $self->{'list_spec'}->instance();
357
$self->assert_equals( 0, scalar $list->elements() );
359
my $select = $self->{'select_spec'}->instance();
360
my $int = $self->{'int_spec'}->instance( 'value' => 10 );
361
$list->append( $select );
362
$self->assert_equals( 1, scalar $list->elements() );
363
$list->append( $int );
364
$self->assert_deep_equals( [ $select, $int ], [$list->elements()] );
366
$self->assert_dies( qr/missing 'value' parameter/,
367
sub { $list->append() });
368
$self->assert_dies( qr/cannot contains config parameters/,
369
sub { $list->append( $self->{'config_spec'}->instance() )});
371
my $bad_select = new Lire::Config::SelectSpec( 'name' => $self->{'select_spec'}->name );
372
$self->assert_dies( qr/is not a valid instance for component/,
373
sub { $list->append( $bad_select->instance() ) } );
378
my $list = $self->{'list_spec'}->instance();
380
$self->assert_dies( qr/not an integer: wawa/,
381
sub { $list->check_idx( 'wawa' ) } );
382
$self->assert_dies( qr/index out of bounds: 0/,
383
sub { $list->check_idx( 0 ) } );
384
$self->assert_dies( qr/index out of bounds: -1/,
385
sub { $list->check_idx( -1 ) } );
387
$list->{'elements'} = [ undef, undef, undef ];
388
foreach my $idx ( qw/ 0 1 2 -1 -2 -3/ ) {
389
eval { $list->check_idx( $idx ) };
390
$self->fail( "$@" ) if $@;
394
sub test_append_idx {
397
my $list = $self->{'list_spec'}->instance();
398
my $int = $self->{'int_spec'}->instance( 'value' => 10 );
399
$list->{'elements'} = [ undef, undef ];
400
$list->append( $int, 0 );
401
$self->assert_deep_equals( [ undef, $int, undef ], $list->{'elements'} );
402
$list->append( $int, -1 );
403
$self->assert_deep_equals( [ undef, $int, undef, $int ],
404
$list->{'elements'} );
410
my $list = $self->{'list_spec'}->instance();
411
$list->{'elements'} = [ 0, 1, 2, 3, 4 ];
412
$list->move( 0, -1 );
413
$self->assert_deep_equals( [ 1, 2, 3, 4, 0 ], $list->{'elements'} );
415
$self->assert_deep_equals( [ 2, 1, 3, 4, 0 ], $list->{'elements'} );
416
$list->move( 2, -2 );
417
$self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} );
419
$self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} );
420
$list->move( 0, -5 );
421
$self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} );
422
$list->move( -5, -5 );
423
$self->assert_deep_equals( [ 2, 1, 4, 3, 0 ], $list->{'elements'} );
424
$list->move( -5, -4 );
425
$self->assert_deep_equals( [ 1, 2, 4, 3, 0 ], $list->{'elements'} );
431
my $list = $self->{'list_spec'}->instance();
432
$list->{'elements'} = [ 0, 1, 2, 3, 4 ];
435
$self->assert_deep_equals( [], $list->{'elements'} );
441
$self->SUPER::test_is_equals();
443
my $list = $self->{'list_spec'}->instance();
444
my $other = $list->clone();
445
my $int = $self->{'int_spec'}->instance( 'value' => 10 );
446
$list->append( $int );
447
$self->assert( ! $list->is_equals( $other ),
448
'! is_equals( count )' );
449
$other->append( $self->{'int_spec'}->instance( 'value' => 11 ) );
450
$self->assert( ! $list->is_equals( $other ),
451
'! is_equals( different )' );
452
$other->set( 0, $int->clone() );
453
$self->assert( $list->is_equals( $other ), 'is_equals()' );
456
package tests::ConfigDictionaryTest;
458
use base qw/tests::ConfigValueTest/;
461
return "Lire::Config::Dictionary";
465
return $_[0]{'config_spec'};
471
$self->SUPER::test_new();
473
my $dict = $self->{'config_spec'}->instance();
474
$dict->set( $self->{'int_spec'}->instance() );
475
$self->assert_deep_equals( $dict, $dict->new() );
481
local $SIG{'__WARN__'} = sub { $self->annotate( join "", $@ ) };
482
my $dict = $self->{'config_spec'}->instance();
483
$self->assert_deep_equals( { 'select' => undef,
491
$dict->set( $self->{'select_spec'}->instance( 'value' => "option_1" ) );
492
$dict->set( $self->{'int_spec'}->instance( 'value' => "10" ) );
493
$self->assert_deep_equals( {
494
'select' => "option_1",
506
my $dict = $self->{'config_spec'}->instance();
508
$self->assert( !$dict->is_set( "int" ), "is_set() returned true" );
510
$self->assert( $dict->is_set( "int" ), "is_set() returned false" );
512
$self->assert_dies( qr/missing 'name' parameter/,
513
sub { $dict->is_set() } );
516
$self->assert_dies( qr/no parameter no_such_param defined/,
517
sub { $dict->is_set( "no_such_param") } );
523
my $dict = $self->{'config_spec'}->instance();
524
my $int = $dict->get( "int" );
525
$self->assert_not_null( $int, "get() should create the instance" );
526
$self->assert_equals( "int", $int->name() );
527
$self->assert_str_equals( '', $int->get() );
529
$self->assert_equals( $int, $dict->get( "int" ) );
531
$self->assert_dies( qr/missing 'name' parameter/,
532
sub { $dict->get() } );
534
$self->assert_dies( qr/no parameter bad_param defined in/,
535
sub { $dict->get( "bad_param" ) } );
541
my $dict = $self->{'config_spec'}->instance();
543
$self->assert_dies( qr/missing 'value' parameter/,
544
sub { $dict->set() } );
546
$self->assert_dies( qr/\'value\' parameter should be a \'Lire::Config::Value\' instance, not/,
547
sub{ $dict->set( $self->{'config_spec'} ) } );
549
my $int = $self->{'int_spec'}->instance();
551
$self->assert_equals( $int, $dict->get( 'int' ) );
553
my $select = new Lire::Config::SelectSpec( 'name' => 'int' )->instance();
555
$self->assert_dies( qr/is not a valid instance for parameter/,
556
sub { $dict->set( $select ) } );
562
$self->SUPER::test_is_equals();
564
my $dict = $self->{'config_spec'}->instance();
565
my $other = $dict->clone();
566
$dict->set( $self->{'string_spec'}->instance( 'value' => 'A value' ) );
567
$self->assert( ! $dict->is_equals( $other ), "!is_equals()" );
569
$other->set( $self->{'string_spec'}->instance( 'value' => 'A value' ) );
570
$self->assert( $dict->is_equals( $other ), "is_equals()" );
576
my $cfg = $self->{'config_spec'}->instance();
577
$self->assert( !$cfg->is_valid(), '!is_valid()' );
579
$cfg->get( 'int' )->set( 10 );
580
$cfg->get( 'select' )->spec()->required( 0 );
581
$cfg->get( 'string' )->spec()->required( 0 );
582
$self->assert( $cfg->is_valid(), 'is_valid()' );