148
322
calculator.infer({:first => 1, :second => 2}).element_type.class.should == Puppet::Pops::Types::PIntegerType
153
context 'when testing if x is assignable to y' do
154
it 'should allow all object types to PObjectType' do
155
t = Puppet::Pops::Types::PObjectType.new()
156
calculator.assignable?(t, t).should() == true
157
calculator.assignable?(t,Puppet::Pops::Types::PNilType.new()).should() == true
158
calculator.assignable?(t,Puppet::Pops::Types::PDataType.new()).should() == true
159
calculator.assignable?(t,Puppet::Pops::Types::PLiteralType.new()).should() == true
160
calculator.assignable?(t,Puppet::Pops::Types::PStringType.new()).should() == true
161
calculator.assignable?(t,Puppet::Pops::Types::PNumericType.new()).should() == true
162
calculator.assignable?(t,Puppet::Pops::Types::PIntegerType.new()).should() == true
163
calculator.assignable?(t,Puppet::Pops::Types::PFloatType.new()).should() == true
164
calculator.assignable?(t,Puppet::Pops::Types::PPatternType.new()).should() == true
165
calculator.assignable?(t,Puppet::Pops::Types::PBooleanType.new()).should() == true
166
calculator.assignable?(t,Puppet::Pops::Types::PCollectionType.new()).should() == true
167
calculator.assignable?(t,Puppet::Pops::Types::PArrayType.new()).should() == true
168
calculator.assignable?(t,Puppet::Pops::Types::PHashType.new()).should() == true
169
calculator.assignable?(t,Puppet::Pops::Types::PRubyType.new()).should() == true
172
it 'should reject PObjectType to less generic types' do
173
t = Puppet::Pops::Types::PObjectType.new()
174
calculator.assignable?(Puppet::Pops::Types::PDataType.new(), t).should() == false
175
calculator.assignable?(Puppet::Pops::Types::PLiteralType.new(), t).should() == false
176
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), t).should() == false
177
calculator.assignable?(Puppet::Pops::Types::PNumericType.new(), t).should() == false
178
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), t).should() == false
179
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), t).should() == false
180
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), t).should() == false
181
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), t).should() == false
182
calculator.assignable?(Puppet::Pops::Types::PCollectionType.new(), t).should() == false
183
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(), t).should() == false
184
calculator.assignable?(Puppet::Pops::Types::PHashType.new(), t).should() == false
185
calculator.assignable?(Puppet::Pops::Types::PRubyType.new(), t).should() == false
188
it 'should allow all data types, array, and hash to PDataType' do
189
t = Puppet::Pops::Types::PDataType.new()
190
calculator.assignable?(t, t).should() == true
191
calculator.assignable?(t,Puppet::Pops::Types::PLiteralType.new()).should() == true
192
calculator.assignable?(t,Puppet::Pops::Types::PStringType.new()).should() == true
193
calculator.assignable?(t,Puppet::Pops::Types::PNumericType.new()).should() == true
194
calculator.assignable?(t,Puppet::Pops::Types::PIntegerType.new()).should() == true
195
calculator.assignable?(t,Puppet::Pops::Types::PFloatType.new()).should() == true
196
calculator.assignable?(t,Puppet::Pops::Types::PPatternType.new()).should() == true
197
calculator.assignable?(t,Puppet::Pops::Types::PBooleanType.new()).should() == true
198
calculator.assignable?(t,Puppet::Pops::Types::PArrayType.new()).should() == true
199
calculator.assignable?(t,Puppet::Pops::Types::PHashType.new()).should() == true
202
it 'should reject PDataType to less generic data types' do
203
t = Puppet::Pops::Types::PDataType.new()
204
calculator.assignable?(Puppet::Pops::Types::PLiteralType.new(), t).should() == false
205
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), t).should() == false
206
calculator.assignable?(Puppet::Pops::Types::PNumericType.new(), t).should() == false
207
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), t).should() == false
208
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), t).should() == false
209
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), t).should() == false
210
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), t).should() == false
213
it 'should reject PDataType to non data types' do
214
t = Puppet::Pops::Types::PDataType.new()
215
calculator.assignable?(Puppet::Pops::Types::PCollectionType.new(),t).should() == false
216
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(),t).should() == false
217
calculator.assignable?(Puppet::Pops::Types::PHashType.new(),t).should() == false
218
calculator.assignable?(Puppet::Pops::Types::PRubyType.new(), t).should() == false
221
it 'should allow all literal types to PLiteralType' do
222
t = Puppet::Pops::Types::PLiteralType.new()
223
calculator.assignable?(t, t).should() == true
224
calculator.assignable?(t,Puppet::Pops::Types::PStringType.new()).should() == true
225
calculator.assignable?(t,Puppet::Pops::Types::PNumericType.new()).should() == true
226
calculator.assignable?(t,Puppet::Pops::Types::PIntegerType.new()).should() == true
227
calculator.assignable?(t,Puppet::Pops::Types::PFloatType.new()).should() == true
228
calculator.assignable?(t,Puppet::Pops::Types::PPatternType.new()).should() == true
229
calculator.assignable?(t,Puppet::Pops::Types::PBooleanType.new()).should() == true
232
it 'should reject PLiteralType to less generic literal types' do
233
t = Puppet::Pops::Types::PLiteralType.new()
234
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), t).should() == false
235
calculator.assignable?(Puppet::Pops::Types::PNumericType.new(), t).should() == false
236
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), t).should() == false
237
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), t).should() == false
238
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), t).should() == false
239
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), t).should() == false
242
it 'should reject PLiteralType to non literal types' do
243
t = Puppet::Pops::Types::PLiteralType.new()
244
calculator.assignable?(Puppet::Pops::Types::PCollectionType.new(), t).should() == false
245
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(), t).should() == false
246
calculator.assignable?(Puppet::Pops::Types::PHashType.new(), t).should() == false
247
calculator.assignable?(Puppet::Pops::Types::PRubyType.new(), t).should() == false
250
it 'should allow all numeric types to PNumericType' do
251
t = Puppet::Pops::Types::PNumericType.new()
252
calculator.assignable?(t, t).should() == true
253
calculator.assignable?(t, Puppet::Pops::Types::PIntegerType.new()).should() == true
254
calculator.assignable?(t, Puppet::Pops::Types::PFloatType.new()).should() == true
257
it 'should reject PNumericType to less generic numeric types' do
258
t = Puppet::Pops::Types::PNumericType.new()
259
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), t).should() == false
260
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), t).should() == false
263
it 'should reject PNumericType to non numeric types' do
264
t = Puppet::Pops::Types::PNumericType.new()
265
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), t).should() == false
266
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), t).should() == false
267
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), t).should() == false
268
calculator.assignable?(Puppet::Pops::Types::PCollectionType.new(), t).should() == false
269
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(), t).should() == false
270
calculator.assignable?(Puppet::Pops::Types::PHashType.new(), t).should() == false
271
calculator.assignable?(Puppet::Pops::Types::PRubyType.new(), t).should() == false
274
it 'should allow all collection types to PCollectionType' do
275
t = Puppet::Pops::Types::PCollectionType.new()
276
calculator.assignable?(t, t).should() == true
277
calculator.assignable?(t, Puppet::Pops::Types::PArrayType.new()).should() == true
278
calculator.assignable?(t, Puppet::Pops::Types::PHashType.new()).should() == true
281
it 'should reject PCollectionType to less generic collection types' do
282
t = Puppet::Pops::Types::PCollectionType.new()
283
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(), t).should() == false
284
calculator.assignable?(Puppet::Pops::Types::PHashType.new(), t).should() == false
287
it 'should reject PCollectionType to non collection types' do
288
t = Puppet::Pops::Types::PCollectionType.new()
289
calculator.assignable?(Puppet::Pops::Types::PDataType.new(), t).should() == false
290
calculator.assignable?(Puppet::Pops::Types::PLiteralType.new(), t).should() == false
291
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), t).should() == false
292
calculator.assignable?(Puppet::Pops::Types::PNumericType.new(), t).should() == false
293
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), t).should() == false
294
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), t).should() == false
295
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), t).should() == false
296
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), t).should() == false
297
calculator.assignable?(Puppet::Pops::Types::PRubyType.new(), t).should() == false
300
it 'should reject PArrayType to non array type collections' do
301
t = Puppet::Pops::Types::PArrayType.new()
302
calculator.assignable?(Puppet::Pops::Types::PHashType.new(), t).should() == false
305
it 'should reject PHashType to non hash type collections' do
306
t = Puppet::Pops::Types::PHashType.new()
307
calculator.assignable?(Puppet::Pops::Types::PArrayType.new(), t).should() == false
310
it 'should recognize mapped ruby types' do
311
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), Integer).should == true
312
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), Fixnum).should == true
313
calculator.assignable?(Puppet::Pops::Types::PIntegerType.new(), Bignum).should == true
314
calculator.assignable?(Puppet::Pops::Types::PFloatType.new(), Float).should == true
315
calculator.assignable?(Puppet::Pops::Types::PNumericType.new(), Numeric).should == true
316
calculator.assignable?(Puppet::Pops::Types::PNilType.new(), NilClass).should == true
317
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), FalseClass).should == true
318
calculator.assignable?(Puppet::Pops::Types::PBooleanType.new(), TrueClass).should == true
319
calculator.assignable?(Puppet::Pops::Types::PStringType.new(), String).should == true
320
calculator.assignable?(Puppet::Pops::Types::PPatternType.new(), Regexp).should == true
321
calculator.assignable?(Puppet::Pops::Types::TypeFactory.array_of_data(), Array).should == true
322
calculator.assignable?(Puppet::Pops::Types::TypeFactory.hash_of_data(), Hash).should == true
328
context 'patterns' do
329
it "constructs a PPatternType" do
330
t = pattern_t('a(b)c')
331
t.class.should == Puppet::Pops::Types::PPatternType
332
t.patterns.size.should == 1
333
t.patterns[0].class.should == Puppet::Pops::Types::PRegexpType
334
t.patterns[0].pattern.should == 'a(b)c'
335
t.patterns[0].regexp.match('abc')[1].should == 'b'
338
it "constructs a PStringType with multiple strings" do
339
t = string_t('a', 'b', 'c', 'abc')
340
t.values.should == ['a', 'b', 'c', 'abc']
344
# Deal with cases not covered by computing common type
345
context 'when computing common type' do
346
it 'computes given resource type commonality' do
347
r1 = Puppet::Pops::Types::PResourceType.new()
348
r1.type_name = 'File'
349
r2 = Puppet::Pops::Types::PResourceType.new()
350
r2.type_name = 'File'
351
calculator.string(calculator.common_type(r1, r2)).should == "File"
353
r2 = Puppet::Pops::Types::PResourceType.new()
354
r2.type_name = 'File'
355
r2.title = '/tmp/foo'
356
calculator.string(calculator.common_type(r1, r2)).should == "File"
358
r1 = Puppet::Pops::Types::PResourceType.new()
359
r1.type_name = 'File'
360
r1.title = '/tmp/foo'
361
calculator.string(calculator.common_type(r1, r2)).should == "File['/tmp/foo']"
363
r1 = Puppet::Pops::Types::PResourceType.new()
364
r1.type_name = 'File'
365
r1.title = '/tmp/bar'
366
calculator.string(calculator.common_type(r1, r2)).should == "File"
368
r2 = Puppet::Pops::Types::PResourceType.new()
369
r2.type_name = 'Package'
371
calculator.string(calculator.common_type(r1, r2)).should == "Resource"
374
it 'computes given hostclass type commonality' do
375
r1 = Puppet::Pops::Types::PHostClassType.new()
376
r1.class_name = 'foo'
377
r2 = Puppet::Pops::Types::PHostClassType.new()
378
r2.class_name = 'foo'
379
calculator.string(calculator.common_type(r1, r2)).should == "Class[foo]"
381
r2 = Puppet::Pops::Types::PHostClassType.new()
382
r2.class_name = 'bar'
383
calculator.string(calculator.common_type(r1, r2)).should == "Class"
385
r2 = Puppet::Pops::Types::PHostClassType.new()
386
calculator.string(calculator.common_type(r1, r2)).should == "Class"
388
r1 = Puppet::Pops::Types::PHostClassType.new()
389
calculator.string(calculator.common_type(r1, r2)).should == "Class"
392
it 'computes pattern commonality' do
393
t1 = pattern_t('abc')
394
t2 = pattern_t('xyz')
395
common_t = calculator.common_type(t1,t2)
396
common_t.class.should == Puppet::Pops::Types::PPatternType
397
common_t.patterns.map { |pr| pr.pattern }.should == ['abc', 'xyz']
398
calculator.string(common_t).should == "Pattern[/abc/, /xyz/]"
401
it 'computes enum commonality to value set sum' do
402
t1 = enum_t('a', 'b', 'c')
403
t2 = enum_t('x', 'y', 'z')
404
common_t = calculator.common_type(t1, t2)
405
common_t.should == enum_t('a', 'b', 'c', 'x', 'y', 'z')
408
it 'computed variant commonality to type union where added types are not sub-types' do
411
v_a = variant_t(a_t1, a_t2)
413
v_b = variant_t(b_t1)
414
common_t = calculator.common_type(v_a, v_b)
415
common_t.class.should == Puppet::Pops::Types::PVariantType
416
Set.new(common_t.types).should == Set.new([a_t1, a_t2, b_t1])
419
it 'computed variant commonality to type union where added types are sub-types' do
422
v_a = variant_t(a_t1, a_t2)
424
v_b = variant_t(b_t1)
425
common_t = calculator.common_type(v_a, v_b)
426
common_t.class.should == Puppet::Pops::Types::PVariantType
427
Set.new(common_t.types).should == Set.new([a_t1, a_t2])
431
context 'computes assignability' do
432
include_context "types_setup"
434
context "for Object, such that" do
435
it 'all types are assignable to Object' do
436
t = Puppet::Pops::Types::PObjectType.new()
437
all_types.each { |t2| t2.new.should be_assignable_to(t) }
440
it 'Object is not assignable to anything but Object' do
441
tested_types = all_types() - [Puppet::Pops::Types::PObjectType]
442
t = Puppet::Pops::Types::PObjectType.new()
443
tested_types.each { |t2| t.should_not be_assignable_to(t2.new) }
447
context "for Data, such that" do
448
it 'all scalars + array and hash are assignable to Data' do
449
t = Puppet::Pops::Types::PDataType.new()
450
data_compatible_types.each { |t2|
451
type_from_class(t2).should be_assignable_to(t)
455
it 'a Variant of scalar, hash, or array is assignable to Data' do
456
t = Puppet::Pops::Types::PDataType.new()
457
data_compatible_types.each { |t2| variant_t(type_from_class(t2)).should be_assignable_to(t) }
460
it 'Data is not assignable to any of its subtypes' do
461
t = Puppet::Pops::Types::PDataType.new()
462
types_to_test = data_compatible_types- [Puppet::Pops::Types::PDataType]
463
types_to_test.each {|t2| t.should_not be_assignable_to(type_from_class(t2)) }
466
it 'Data is not assignable to a Variant of Data subtype' do
467
t = Puppet::Pops::Types::PDataType.new()
468
types_to_test = data_compatible_types- [Puppet::Pops::Types::PDataType]
469
types_to_test.each { |t2| t.should_not be_assignable_to(variant_t(type_from_class(t2))) }
472
it 'Data is not assignable to any disjunct type' do
473
tested_types = all_types - [Puppet::Pops::Types::PObjectType, Puppet::Pops::Types::PDataType] - scalar_types
474
t = Puppet::Pops::Types::PDataType.new()
475
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
479
context "for Scalar, such that" do
480
it "all scalars are assignable to Scalar" do
481
t = Puppet::Pops::Types::PScalarType.new()
482
scalar_types.each {|t2| t2.new.should be_assignable_to(t) }
485
it 'Scalar is not assignable to any of its subtypes' do
486
t = Puppet::Pops::Types::PScalarType.new()
487
types_to_test = scalar_types - [Puppet::Pops::Types::PScalarType]
488
types_to_test.each {|t2| t.should_not be_assignable_to(t2.new) }
491
it 'Scalar is not assignable to any disjunct type' do
492
tested_types = all_types - [Puppet::Pops::Types::PObjectType, Puppet::Pops::Types::PDataType] - scalar_types
493
t = Puppet::Pops::Types::PScalarType.new()
494
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
498
context "for Numeric, such that" do
499
it "all numerics are assignable to Numeric" do
500
t = Puppet::Pops::Types::PNumericType.new()
501
numeric_types.each {|t2| t2.new.should be_assignable_to(t) }
504
it 'Numeric is not assignable to any of its subtypes' do
505
t = Puppet::Pops::Types::PNumericType.new()
506
types_to_test = numeric_types - [Puppet::Pops::Types::PNumericType]
507
types_to_test.each {|t2| t.should_not be_assignable_to(t2.new) }
510
it 'Numeric is not assignable to any disjunct type' do
511
tested_types = all_types - [
512
Puppet::Pops::Types::PObjectType,
513
Puppet::Pops::Types::PDataType,
514
Puppet::Pops::Types::PScalarType,
516
t = Puppet::Pops::Types::PNumericType.new()
517
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
521
context "for Collection, such that" do
522
it "all collections are assignable to Collection" do
523
t = Puppet::Pops::Types::PCollectionType.new()
524
collection_types.each {|t2| t2.new.should be_assignable_to(t) }
527
it 'Collection is not assignable to any of its subtypes' do
528
t = Puppet::Pops::Types::PCollectionType.new()
529
types_to_test = collection_types - [Puppet::Pops::Types::PCollectionType]
530
types_to_test.each {|t2| t.should_not be_assignable_to(t2.new) }
533
it 'Collection is not assignable to any disjunct type' do
534
tested_types = all_types - [Puppet::Pops::Types::PObjectType] - collection_types
535
t = Puppet::Pops::Types::PCollectionType.new()
536
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
540
context "for Array, such that" do
541
it "Array is not assignable to non Array based Collection type" do
542
t = Puppet::Pops::Types::PArrayType.new()
543
tested_types = collection_types - [
544
Puppet::Pops::Types::PCollectionType,
545
Puppet::Pops::Types::PArrayType,
546
Puppet::Pops::Types::PTupleType]
547
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
550
it 'Array is not assignable to any disjunct type' do
551
tested_types = all_types - [
552
Puppet::Pops::Types::PObjectType,
553
Puppet::Pops::Types::PDataType] - collection_types
554
t = Puppet::Pops::Types::PArrayType.new()
555
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
559
context "for Hash, such that" do
560
it "Hash is not assignable to any other Collection type" do
561
t = Puppet::Pops::Types::PHashType.new()
562
tested_types = collection_types - [
563
Puppet::Pops::Types::PCollectionType,
564
Puppet::Pops::Types::PStructType,
565
Puppet::Pops::Types::PHashType]
566
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
569
it 'Hash is not assignable to any disjunct type' do
570
tested_types = all_types - [
571
Puppet::Pops::Types::PObjectType,
572
Puppet::Pops::Types::PDataType] - collection_types
573
t = Puppet::Pops::Types::PHashType.new()
574
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
578
context "for Tuple, such that" do
579
it "Tuple is not assignable to any other non Array based Collection type" do
580
t = Puppet::Pops::Types::PTupleType.new()
581
tested_types = collection_types - [
582
Puppet::Pops::Types::PCollectionType,
583
Puppet::Pops::Types::PTupleType,
584
Puppet::Pops::Types::PArrayType]
585
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
588
it 'Tuple is not assignable to any disjunct type' do
589
tested_types = all_types - [
590
Puppet::Pops::Types::PObjectType,
591
Puppet::Pops::Types::PDataType] - collection_types
592
t = Puppet::Pops::Types::PTupleType.new()
593
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
597
context "for Struct, such that" do
598
it "Struct is not assignable to any other non Hashed based Collection type" do
599
t = Puppet::Pops::Types::PStructType.new()
600
tested_types = collection_types - [
601
Puppet::Pops::Types::PCollectionType,
602
Puppet::Pops::Types::PStructType,
603
Puppet::Pops::Types::PHashType]
604
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
607
it 'Struct is not assignable to any disjunct type' do
608
tested_types = all_types - [
609
Puppet::Pops::Types::PObjectType,
610
Puppet::Pops::Types::PDataType] - collection_types
611
t = Puppet::Pops::Types::PStructType.new()
612
tested_types.each {|t2| t.should_not be_assignable_to(t2.new) }
616
it 'should recognize mapped ruby types' do
617
{ Integer => Puppet::Pops::Types::PIntegerType.new,
618
Fixnum => Puppet::Pops::Types::PIntegerType.new,
619
Bignum => Puppet::Pops::Types::PIntegerType.new,
620
Float => Puppet::Pops::Types::PFloatType.new,
621
Numeric => Puppet::Pops::Types::PNumericType.new,
622
NilClass => Puppet::Pops::Types::PNilType.new,
623
TrueClass => Puppet::Pops::Types::PBooleanType.new,
624
FalseClass => Puppet::Pops::Types::PBooleanType.new,
625
String => Puppet::Pops::Types::PStringType.new,
626
Regexp => Puppet::Pops::Types::PRegexpType.new,
627
Regexp => Puppet::Pops::Types::PRegexpType.new,
628
Array => Puppet::Pops::Types::TypeFactory.array_of_data(),
629
Hash => Puppet::Pops::Types::TypeFactory.hash_of_data()
630
}.each do |ruby_type, puppet_type |
631
ruby_type.should be_assignable_to(puppet_type)
635
context 'when dealing with integer ranges' do
636
it 'should accept an equal range' do
637
calculator.assignable?(range_t(2,5), range_t(2,5)).should == true
640
it 'should accept an equal reverse range' do
641
calculator.assignable?(range_t(2,5), range_t(5,2)).should == true
644
it 'should accept a narrower range' do
645
calculator.assignable?(range_t(2,10), range_t(3,5)).should == true
648
it 'should accept a narrower reverse range' do
649
calculator.assignable?(range_t(2,10), range_t(5,3)).should == true
652
it 'should reject a wider range' do
653
calculator.assignable?(range_t(3,5), range_t(2,10)).should == false
656
it 'should reject a wider reverse range' do
657
calculator.assignable?(range_t(3,5), range_t(10,2)).should == false
660
it 'should reject a partially overlapping range' do
661
calculator.assignable?(range_t(3,5), range_t(2,4)).should == false
662
calculator.assignable?(range_t(3,5), range_t(4,6)).should == false
665
it 'should reject a partially overlapping reverse range' do
666
calculator.assignable?(range_t(3,5), range_t(4,2)).should == false
667
calculator.assignable?(range_t(3,5), range_t(6,4)).should == false
671
context 'when dealing with patterns' do
672
it 'should accept a string matching a pattern' do
673
p_t = pattern_t('abc')
674
p_s = string_t('XabcY')
675
calculator.assignable?(p_t, p_s).should == true
678
it 'should accept a regexp matching a pattern' do
679
p_t = pattern_t(/abc/)
680
p_s = string_t('XabcY')
681
calculator.assignable?(p_t, p_s).should == true
684
it 'should accept a pattern matching a pattern' do
685
p_t = pattern_t(pattern_t('abc'))
686
p_s = string_t('XabcY')
687
calculator.assignable?(p_t, p_s).should == true
690
it 'should accept a regexp matching a pattern' do
691
p_t = pattern_t(regexp_t('abc'))
692
p_s = string_t('XabcY')
693
calculator.assignable?(p_t, p_s).should == true
696
it 'should accept a string matching all patterns' do
697
p_t = pattern_t('abc', 'ab', 'c')
698
p_s = string_t('XabcY')
699
calculator.assignable?(p_t, p_s).should == true
702
it 'should accept multiple strings if they all match any patterns' do
703
p_t = pattern_t('X', 'Y', 'abc')
704
p_s = string_t('Xa', 'aY', 'abc')
705
calculator.assignable?(p_t, p_s).should == true
708
it 'should reject a string not matching any patterns' do
709
p_t = pattern_t('abc', 'ab', 'c')
710
p_s = string_t('XqqqY')
711
calculator.assignable?(p_t, p_s).should == false
714
it 'should reject multiple strings if not all match any patterns' do
715
p_t = pattern_t('abc', 'ab', 'c', 'q')
716
p_s = string_t('X', 'Y', 'Z')
717
calculator.assignable?(p_t, p_s).should == false
720
it 'should accept enum matching patterns as instanceof' do
721
enum = enum_t('XS', 'S', 'M', 'L' 'XL', 'XXL')
722
pattern = pattern_t('S', 'M', 'L')
723
calculator.assignable?(pattern, enum).should == true
728
context 'when dealing with tuples' do
729
it 'should accept matching tuples' do
730
tuple1 = tuple_t(1,2)
731
tuple2 = tuple_t(Integer,Integer)
732
calculator.assignable?(tuple1, tuple2).should == true
733
calculator.assignable?(tuple2, tuple1).should == true
736
it 'should accept matching tuples where one is more general than the other' do
737
tuple1 = tuple_t(1,2)
738
tuple2 = tuple_t(Numeric,Numeric)
739
calculator.assignable?(tuple1, tuple2).should == false
740
calculator.assignable?(tuple2, tuple1).should == true
743
it 'should accept ranged tuples' do
745
factory.constrain_size(tuple1, 5, 5)
746
tuple2 = tuple_t(Integer,Integer, Integer, Integer, Integer)
747
calculator.assignable?(tuple1, tuple2).should == true
748
calculator.assignable?(tuple2, tuple1).should == true
751
it 'should reject ranged tuples when ranges does not match' do
753
factory.constrain_size(tuple1, 4, 5)
754
tuple2 = tuple_t(Integer,Integer, Integer, Integer, Integer)
755
calculator.assignable?(tuple1, tuple2).should == true
756
calculator.assignable?(tuple2, tuple1).should == false
759
it 'should reject ranged tuples when ranges does not match (using infinite upper bound)' do
761
factory.constrain_size(tuple1, 4, :default)
762
tuple2 = tuple_t(Integer,Integer, Integer, Integer, Integer)
763
calculator.assignable?(tuple1, tuple2).should == true
764
calculator.assignable?(tuple2, tuple1).should == false
767
it 'should accept matching tuples with optional entries by repeating last' do
768
tuple1 = tuple_t(1,2)
769
factory.constrain_size(tuple1, 0, :default)
770
tuple2 = tuple_t(Numeric,Numeric)
771
factory.constrain_size(tuple2, 0, :default)
772
calculator.assignable?(tuple1, tuple2).should == false
773
calculator.assignable?(tuple2, tuple1).should == true
776
it 'should accept matching tuples with optional entries' do
777
tuple1 = tuple_t(Integer, Integer, String)
778
factory.constrain_size(tuple1, 1, 3)
779
array2 = factory.constrain_size(array_t(Integer),2,2)
780
calculator.assignable?(tuple1, array2).should == true
781
factory.constrain_size(tuple1, 3, 3)
782
calculator.assignable?(tuple1, array2).should == false
785
it 'should accept matching array' do
786
tuple1 = tuple_t(1,2)
787
array = array_t(Integer)
788
factory.constrain_size(array, 2, 2)
789
calculator.assignable?(tuple1, array).should == true
790
calculator.assignable?(array, tuple1).should == true
794
context 'when dealing with structs' do
795
it 'should accept matching structs' do
796
struct1 = struct_t({'a'=>Integer, 'b'=>Integer})
797
struct2 = struct_t({'a'=>Integer, 'b'=>Integer})
798
calculator.assignable?(struct1, struct2).should == true
799
calculator.assignable?(struct2, struct1).should == true
802
it 'should accept matching structs where one is more general than the other' do
803
struct1 = struct_t({'a'=>Integer, 'b'=>Integer})
804
struct2 = struct_t({'a'=>Numeric, 'b'=>Numeric})
805
calculator.assignable?(struct1, struct2).should == false
806
calculator.assignable?(struct2, struct1).should == true
809
it 'should accept matching hash' do
810
struct1 = struct_t({'a'=>Integer, 'b'=>Integer})
811
non_empty_string = string_t()
812
non_empty_string.size_type = range_t(1, nil)
813
hsh = hash_t(non_empty_string, Integer)
814
factory.constrain_size(hsh, 2, 2)
815
calculator.assignable?(struct1, hsh).should == true
816
calculator.assignable?(hsh, struct1).should == true
325
820
it 'should recognize ruby type inheritance' do
341
836
calculator.assignable?(barType, fooType).should == false
342
837
calculator.assignable?(Bar, fooType).should == false
840
it "should allow host class with same name" do
841
hc1 = Puppet::Pops::Types::TypeFactory.host_class('the_name')
842
hc2 = Puppet::Pops::Types::TypeFactory.host_class('the_name')
843
calculator.assignable?(hc1, hc2).should == true
846
it "should allow host class with name assigned to hostclass without name" do
847
hc1 = Puppet::Pops::Types::TypeFactory.host_class()
848
hc2 = Puppet::Pops::Types::TypeFactory.host_class('the_name')
849
calculator.assignable?(hc1, hc2).should == true
852
it "should reject host classes with different names" do
853
hc1 = Puppet::Pops::Types::TypeFactory.host_class('the_name')
854
hc2 = Puppet::Pops::Types::TypeFactory.host_class('another_name')
855
calculator.assignable?(hc1, hc2).should == false
858
it "should reject host classes without name assigned to host class with name" do
859
hc1 = Puppet::Pops::Types::TypeFactory.host_class('the_name')
860
hc2 = Puppet::Pops::Types::TypeFactory.host_class()
861
calculator.assignable?(hc1, hc2).should == false
864
it "should allow resource with same type_name and title" do
865
r1 = Puppet::Pops::Types::TypeFactory.resource('file', 'foo')
866
r2 = Puppet::Pops::Types::TypeFactory.resource('file', 'foo')
867
calculator.assignable?(r1, r2).should == true
870
it "should allow more specific resource assignment" do
871
r1 = Puppet::Pops::Types::TypeFactory.resource()
872
r2 = Puppet::Pops::Types::TypeFactory.resource('file')
873
calculator.assignable?(r1, r2).should == true
874
r2 = Puppet::Pops::Types::TypeFactory.resource('file', '/tmp/foo')
875
calculator.assignable?(r1, r2).should == true
876
r1 = Puppet::Pops::Types::TypeFactory.resource('file')
877
calculator.assignable?(r1, r2).should == true
880
it "should reject less specific resource assignment" do
881
r1 = Puppet::Pops::Types::TypeFactory.resource('file', '/tmp/foo')
882
r2 = Puppet::Pops::Types::TypeFactory.resource('file')
883
calculator.assignable?(r1, r2).should == false
884
r2 = Puppet::Pops::Types::TypeFactory.resource()
885
calculator.assignable?(r1, r2).should == false
346
890
context 'when testing if x is instance of type t' do
891
include_context "types_setup"
893
it 'should consider undef to be instance of Object and NilType' do
894
calculator.instance?(Puppet::Pops::Types::PNilType.new(), nil).should == true
895
calculator.instance?(Puppet::Pops::Types::PObjectType.new(), nil).should == true
898
it 'should not consider undef to be an instance of any other type than Object and NilType and Data' do
899
types_to_test = all_types - [
900
Puppet::Pops::Types::PObjectType,
901
Puppet::Pops::Types::PNilType,
902
Puppet::Pops::Types::PDataType]
904
types_to_test.each {|t| calculator.instance?(t.new, nil).should == false }
905
types_to_test.each {|t| calculator.instance?(t.new, :undef).should == false }
347
908
it 'should consider fixnum instanceof PIntegerType' do
348
calculator.instance?(Puppet::Pops::Types::PIntegerType.new(), 1)
909
calculator.instance?(Puppet::Pops::Types::PIntegerType.new(), 1).should == true
351
912
it 'should consider fixnum instanceof Fixnum' do
352
calculator.instance?(Fixnum, 1)
913
calculator.instance?(Fixnum, 1).should == true
916
it 'should consider integer in range' do
917
range = range_t(0,10)
918
calculator.instance?(range, 1).should == true
919
calculator.instance?(range, 10).should == true
920
calculator.instance?(range, -1).should == false
921
calculator.instance?(range, 11).should == false
924
it 'should consider string in length range' do
925
range = factory.constrain_size(string_t, 1,3)
926
calculator.instance?(range, 'a').should == true
927
calculator.instance?(range, 'abc').should == true
928
calculator.instance?(range, '').should == false
929
calculator.instance?(range, 'abcd').should == false
932
it 'should consider array in length range' do
933
range = factory.constrain_size(array_t(integer_t), 1,3)
934
calculator.instance?(range, [1]).should == true
935
calculator.instance?(range, [1,2,3]).should == true
936
calculator.instance?(range, []).should == false
937
calculator.instance?(range, [1,2,3,4]).should == false
940
it 'should consider hash in length range' do
941
range = factory.constrain_size(hash_t(integer_t, integer_t), 1,2)
942
calculator.instance?(range, {1=>1}).should == true
943
calculator.instance?(range, {1=>1, 2=>2}).should == true
944
calculator.instance?(range, {}).should == false
945
calculator.instance?(range, {1=>1, 2=>2, 3=>3}).should == false
948
it 'should consider collection in length range for array ' do
949
range = factory.constrain_size(collection_t, 1,3)
950
calculator.instance?(range, [1]).should == true
951
calculator.instance?(range, [1,2,3]).should == true
952
calculator.instance?(range, []).should == false
953
calculator.instance?(range, [1,2,3,4]).should == false
956
it 'should consider collection in length range for hash' do
957
range = factory.constrain_size(collection_t, 1,2)
958
calculator.instance?(range, {1=>1}).should == true
959
calculator.instance?(range, {1=>1, 2=>2}).should == true
960
calculator.instance?(range, {}).should == false
961
calculator.instance?(range, {1=>1, 2=>2, 3=>3}).should == false
964
it 'should consider string matching enum as instanceof' do
965
enum = enum_t('XS', 'S', 'M', 'L', 'XL', '0')
966
calculator.instance?(enum, 'XS').should == true
967
calculator.instance?(enum, 'S').should == true
968
calculator.instance?(enum, 'XXL').should == false
969
calculator.instance?(enum, '').should == false
970
calculator.instance?(enum, '0').should == true
971
calculator.instance?(enum, 0).should == false
974
it 'should consider array[string] as instance of Array[Enum] when strings are instance of Enum' do
975
enum = enum_t('XS', 'S', 'M', 'L', 'XL', '0')
976
array = array_t(enum)
977
calculator.instance?(array, ['XS', 'S', 'XL']).should == true
978
calculator.instance?(array, ['XS', 'S', 'XXL']).should == false
981
it 'should consider array[mixed] as instance of Variant[mixed] when mixed types are listed in Variant' do
982
enum = enum_t('XS', 'S', 'M', 'L', 'XL')
983
sizes = range_t(30, 50)
984
array = array_t(variant_t(enum, sizes))
985
calculator.instance?(array, ['XS', 'S', 30, 50]).should == true
986
calculator.instance?(array, ['XS', 'S', 'XXL']).should == false
987
calculator.instance?(array, ['XS', 'S', 29]).should == false
990
it 'should consider array[seq] as instance of Tuple[seq] when elements of seq are instance of' do
991
tuple = tuple_t(Integer, String, Float)
992
calculator.instance?(tuple, [1, 'a', 3.14]).should == true
993
calculator.instance?(tuple, [1.2, 'a', 3.14]).should == false
994
calculator.instance?(tuple, [1, 1, 3.14]).should == false
995
calculator.instance?(tuple, [1, 'a', 1]).should == false
998
it 'should consider hash[cont] as instance of Struct[cont-t]' do
999
struct = struct_t({'a'=>Integer, 'b'=>String, 'c'=>Float})
1000
calculator.instance?(struct, {'a'=>1, 'b'=>'a', 'c'=>3.14}).should == true
1001
calculator.instance?(struct, {'a'=>1.2, 'b'=>'a', 'c'=>3.14}).should == false
1002
calculator.instance?(struct, {'a'=>1, 'b'=>1, 'c'=>3.14}).should == false
1003
calculator.instance?(struct, {'a'=>1, 'b'=>'a', 'c'=>1}).should == false
1006
context 'and t is Data' do
1007
it 'undef should be considered instance of Data' do
1008
calculator.instance?(data_t, :undef).should == true
1011
it 'other symbols should not be considered instance of Data' do
1012
calculator.instance?(data_t, :love).should == false
1015
it 'an empty array should be considered instance of Data' do
1016
calculator.instance?(data_t, []).should == true
1019
it 'an empty hash should be considered instance of Data' do
1020
calculator.instance?(data_t, {}).should == true
1023
it 'a hash with nil/undef data should be considered instance of Data' do
1024
calculator.instance?(data_t, {'a' => nil}).should == true
1025
calculator.instance?(data_t, {'a' => :undef}).should == true
1028
it 'a hash with nil/undef key should not considered instance of Data' do
1029
calculator.instance?(data_t, {nil => 10}).should == false
1030
calculator.instance?(data_t, {:undef => 10}).should == false
1033
it 'an array with undef entries should be considered instance of Data' do
1034
calculator.instance?(data_t, [:undef]).should == true
1035
calculator.instance?(data_t, [nil]).should == true
1038
it 'an array with undef / data entries should be considered instance of Data' do
1039
calculator.instance?(data_t, [1, :undef, 'a']).should == true
1040
calculator.instance?(data_t, [1, nil, 'a']).should == true
421
1110
calculator.string(Puppet::Pops::Types::PNumericType.new()).should == 'Numeric'
424
it 'should yield \'Integer\' for PIntegerType' do
425
calculator.string(Puppet::Pops::Types::PIntegerType.new()).should == 'Integer'
1113
it 'should yield \'Integer\' and from/to for PIntegerType' do
1114
int_T = Puppet::Pops::Types::PIntegerType
1115
calculator.string(int_T.new()).should == 'Integer'
1119
calculator.string(int).should == 'Integer[1, 1]'
1123
calculator.string(int).should == 'Integer[1, 2]'
1127
calculator.string(int).should == 'Integer[default, 2]'
1131
calculator.string(int).should == 'Integer[2, default]'
428
1134
it 'should yield \'Float\' for PFloatType' do
429
1135
calculator.string(Puppet::Pops::Types::PFloatType.new()).should == 'Float'
432
it 'should yield \'Pattern\' for PPatternType' do
433
calculator.string(Puppet::Pops::Types::PPatternType.new()).should == 'Pattern'
1138
it 'should yield \'Regexp\' for PRegexpType' do
1139
calculator.string(Puppet::Pops::Types::PRegexpType.new()).should == 'Regexp'
1142
it 'should yield \'Regexp[/pat/]\' for parameterized PRegexpType' do
1143
t = Puppet::Pops::Types::PRegexpType.new()
1145
calculator.string(Puppet::Pops::Types::PRegexpType.new()).should == 'Regexp'
436
1148
it 'should yield \'String\' for PStringType' do
437
1149
calculator.string(Puppet::Pops::Types::PStringType.new()).should == 'String'
1152
it 'should yield \'String\' for PStringType with multiple values' do
1153
calculator.string(string_t('a', 'b', 'c')).should == 'String'
1156
it 'should yield \'String\' and from/to for PStringType' do
1157
string_T = Puppet::Pops::Types::PStringType
1158
calculator.string(factory.constrain_size(string_T.new(), 1,1)).should == 'String[1, 1]'
1159
calculator.string(factory.constrain_size(string_T.new(), 1,2)).should == 'String[1, 2]'
1160
calculator.string(factory.constrain_size(string_T.new(), :default, 2)).should == 'String[default, 2]'
1161
calculator.string(factory.constrain_size(string_T.new(), 2, :default)).should == 'String[2, default]'
440
1164
it 'should yield \'Array[Integer]\' for PArrayType[PIntegerType]' do
441
1165
t = Puppet::Pops::Types::PArrayType.new()
442
1166
t.element_type = Puppet::Pops::Types::PIntegerType.new()
443
1167
calculator.string(t).should == 'Array[Integer]'
1170
it 'should yield \'Collection\' and from/to for PCollectionType' do
1171
col = collection_t()
1172
calculator.string(factory.constrain_size(col.copy, 1,1)).should == 'Collection[1, 1]'
1173
calculator.string(factory.constrain_size(col.copy, 1,2)).should == 'Collection[1, 2]'
1174
calculator.string(factory.constrain_size(col.copy, :default, 2)).should == 'Collection[default, 2]'
1175
calculator.string(factory.constrain_size(col.copy, 2, :default)).should == 'Collection[2, default]'
1178
it 'should yield \'Array\' and from/to for PArrayType' do
1179
arr = array_t(string_t)
1180
calculator.string(factory.constrain_size(arr.copy, 1,1)).should == 'Array[String, 1, 1]'
1181
calculator.string(factory.constrain_size(arr.copy, 1,2)).should == 'Array[String, 1, 2]'
1182
calculator.string(factory.constrain_size(arr.copy, :default, 2)).should == 'Array[String, default, 2]'
1183
calculator.string(factory.constrain_size(arr.copy, 2, :default)).should == 'Array[String, 2, default]'
1186
it 'should yield \'Tuple[Integer]\' for PTupleType[PIntegerType]' do
1187
t = Puppet::Pops::Types::PTupleType.new()
1188
t.addTypes(Puppet::Pops::Types::PIntegerType.new())
1189
calculator.string(t).should == 'Tuple[Integer]'
1192
it 'should yield \'Tuple[T, T,..]\' for PTupleType[T, T, ...]' do
1193
t = Puppet::Pops::Types::PTupleType.new()
1194
t.addTypes(Puppet::Pops::Types::PIntegerType.new())
1195
t.addTypes(Puppet::Pops::Types::PIntegerType.new())
1196
t.addTypes(Puppet::Pops::Types::PStringType.new())
1197
calculator.string(t).should == 'Tuple[Integer, Integer, String]'
1200
it 'should yield \'Tuple\' and from/to for PTupleType' do
1201
tuple_t = tuple_t(string_t)
1202
calculator.string(factory.constrain_size(tuple_t.copy, 1,1)).should == 'Tuple[String, 1, 1]'
1203
calculator.string(factory.constrain_size(tuple_t.copy, 1,2)).should == 'Tuple[String, 1, 2]'
1204
calculator.string(factory.constrain_size(tuple_t.copy, :default, 2)).should == 'Tuple[String, default, 2]'
1205
calculator.string(factory.constrain_size(tuple_t.copy, 2, :default)).should == 'Tuple[String, 2, default]'
1208
it 'should yield \'Struct\' and details for PStructType' do
1209
struct_t = struct_t({'a'=>Integer, 'b'=>String})
1210
s = calculator.string(struct_t)
1211
# Ruby 1.8.7 - noone likes you...
1212
(s == "Struct[{'a'=>Integer, 'b'=>String}]" || s == "Struct[{'b'=>String, 'a'=>Integer}]").should == true
1213
struct_t = struct_t({})
1214
calculator.string(struct_t).should == "Struct"
446
1217
it 'should yield \'Hash[String, Integer]\' for PHashType[PStringType, PIntegerType]' do
447
1218
t = Puppet::Pops::Types::PHashType.new()
448
1219
t.key_type = Puppet::Pops::Types::PStringType.new()
449
1220
t.element_type = Puppet::Pops::Types::PIntegerType.new()
450
1221
calculator.string(t).should == 'Hash[String, Integer]'
1224
it 'should yield \'Hash\' and from/to for PHashType' do
1225
hsh = hash_t(string_t, string_t)
1226
calculator.string(factory.constrain_size(hsh.copy, 1,1)).should == 'Hash[String, String, 1, 1]'
1227
calculator.string(factory.constrain_size(hsh.copy, 1,2)).should == 'Hash[String, String, 1, 2]'
1228
calculator.string(factory.constrain_size(hsh.copy, :default, 2)).should == 'Hash[String, String, default, 2]'
1229
calculator.string(factory.constrain_size(hsh.copy, 2, :default)).should == 'Hash[String, String, 2, default]'
1232
it "should yield 'Class' for a PHostClassType" do
1233
t = Puppet::Pops::Types::PHostClassType.new()
1234
calculator.string(t).should == 'Class'
1237
it "should yield 'Class[x]' for a PHostClassType[x]" do
1238
t = Puppet::Pops::Types::PHostClassType.new()
1240
calculator.string(t).should == 'Class[x]'
1243
it "should yield 'Resource' for a PResourceType" do
1244
t = Puppet::Pops::Types::PResourceType.new()
1245
calculator.string(t).should == 'Resource'
1248
it 'should yield \'File\' for a PResourceType[\'File\']' do
1249
t = Puppet::Pops::Types::PResourceType.new()
1250
t.type_name = 'File'
1251
calculator.string(t).should == 'File'
1254
it "should yield 'File['/tmp/foo']' for a PResourceType['File', '/tmp/foo']" do
1255
t = Puppet::Pops::Types::PResourceType.new()
1256
t.type_name = 'File'
1257
t.title = '/tmp/foo'
1258
calculator.string(t).should == "File['/tmp/foo']"
1261
it "should yield 'Enum[s,...]' for a PEnumType[s,...]" do
1262
t = enum_t('a', 'b', 'c')
1263
calculator.string(t).should == "Enum['a', 'b', 'c']"
1266
it "should yield 'Pattern[/pat/,...]' for a PPatternType['pat',...]" do
1268
t2 = pattern_t('a', 'b', 'c')
1269
calculator.string(t).should == "Pattern[/a/]"
1270
calculator.string(t2).should == "Pattern[/a/, /b/, /c/]"
1273
it "should escape special characters in the string for a PPatternType['pat',...]" do
1274
t = pattern_t('a/b')
1275
calculator.string(t).should == "Pattern[/a\\/b/]"
1278
it "should yield 'Variant[t1,t2,...]' for a PVariantType[t1, t2,...]" do
1282
t = variant_t(t1, t2, t3)
1283
calculator.string(t).should == "Variant[String, Integer, Pattern[/a/]]"
454
1287
context 'when processing meta type' do