215
227
calculator.infer(nil).class.should == Puppet::Pops::Types::PNilType
218
it ':undef translates to PNilType' do
219
calculator.infer(:undef).class.should == Puppet::Pops::Types::PNilType
230
it ':undef translates to PRuntimeType' do
231
calculator.infer(:undef).class.should == Puppet::Pops::Types::PRuntimeType
222
it 'an instance of class Foo translates to PRubyType[Foo]' do
234
it 'an instance of class Foo translates to PRuntimeType[ruby, Foo]' do
226
238
t = calculator.infer(Foo.new)
227
t.class.should == Puppet::Pops::Types::PRubyType
228
t.ruby_class.should == 'Foo'
239
t.class.should == Puppet::Pops::Types::PRuntimeType
240
t.runtime.should == :ruby
241
t.runtime_type_name.should == 'Foo'
231
244
context 'array' do
328
341
calculator.infer({:first => 1, :second => 2}).class.should == Puppet::Pops::Types::PHashType
331
it 'with symbolic keys translates to PHashType[PRubyType[Symbol],value]' do
344
it 'with symbolic keys translates to PHashType[PRuntimeType[ruby, Symbol], value]' do
332
345
k = calculator.infer({:first => 1, :second => 2}).key_type
333
k.class.should == Puppet::Pops::Types::PRubyType
334
k.ruby_class.should == 'Symbol'
346
k.class.should == Puppet::Pops::Types::PRuntimeType
347
k.runtime.should == :ruby
348
k.runtime_type_name.should == 'Symbol'
337
it 'with string keys translates to PHashType[PStringType,value]' do
351
it 'with string keys translates to PHashType[PStringType, value]' do
338
352
calculator.infer({'first' => 1, 'second' => 2}).key_type.class.should == Puppet::Pops::Types::PStringType
341
it 'with fixnum values translates to PHashType[key,PIntegerType]' do
355
it 'with fixnum values translates to PHashType[key, PIntegerType]' do
342
356
calculator.infer({:first => 1, :second => 2}).element_type.class.should == Puppet::Pops::Types::PIntegerType
491
505
context 'computes assignability' do
492
506
include_context "types_setup"
494
context "for Object, such that" do
495
it 'all types are assignable to Object' do
496
t = Puppet::Pops::Types::PObjectType.new()
497
all_types.each { |t2| t2.new.should be_assignable_to(t) }
500
it 'Object is not assignable to anything but Object' do
501
tested_types = all_types() - [Puppet::Pops::Types::PObjectType]
502
t = Puppet::Pops::Types::PObjectType.new()
508
context 'for Unit, such that' do
509
it 'all types are assignable to Unit' do
510
t = Puppet::Pops::Types::PUnitType.new()
511
all_types.each { |t2| t2.new.should be_assignable_to(t) }
514
it 'Unit is assignable to all other types' do
515
t = Puppet::Pops::Types::PUnitType.new()
516
all_types.each { |t2| t.should be_assignable_to(t2.new) }
519
it 'Unit is assignable to Unit' do
520
t = Puppet::Pops::Types::PUnitType.new()
521
t2 = Puppet::Pops::Types::PUnitType.new()
522
t.should be_assignable_to(t2)
526
context "for Any, such that" do
527
it 'all types are assignable to Any' do
528
t = Puppet::Pops::Types::PAnyType.new()
529
all_types.each { |t2| t2.new.should be_assignable_to(t) }
532
it 'Any is not assignable to anything but Any' do
533
tested_types = all_types() - [Puppet::Pops::Types::PAnyType]
534
t = Puppet::Pops::Types::PAnyType.new()
503
535
tested_types.each { |t2| t.should_not be_assignable_to(t2.new) }
793
825
calculator.assignable?(pattern, enum).should == true
828
it 'pattern should accept a variant where all variants are acceptable' do
829
pattern = pattern_t(/^\w+$/)
830
calculator.assignable?(pattern, variant_t(string_t('a'), string_t('b'))).should == true
833
it 'pattern representing all patterns should accept any pattern' do
834
calculator.assignable?(pattern_t(), pattern_t('a')).should == true
835
calculator.assignable?(pattern_t(), pattern_t()).should == true
838
it 'pattern representing all patterns should accept any enum' do
839
calculator.assignable?(pattern_t(), enum_t('a')).should == true
840
calculator.assignable?(pattern_t(), enum_t()).should == true
843
it 'pattern representing all patterns should accept any string' do
844
calculator.assignable?(pattern_t(), string_t('a')).should == true
845
calculator.assignable?(pattern_t(), string_t()).should == true
850
context 'when dealing with enums' do
851
it 'should accept a string with matching content' do
852
calculator.assignable?(enum_t('a', 'b'), string_t('a')).should == true
853
calculator.assignable?(enum_t('a', 'b'), string_t('b')).should == true
854
calculator.assignable?(enum_t('a', 'b'), string_t('c')).should == false
857
it 'should accept an enum with matching enum' do
858
calculator.assignable?(enum_t('a', 'b'), enum_t('a', 'b')).should == true
859
calculator.assignable?(enum_t('a', 'b'), enum_t('a')).should == true
860
calculator.assignable?(enum_t('a', 'b'), enum_t('c')).should == false
863
it 'non parameterized enum accepts any other enum but not the reverse' do
864
calculator.assignable?(enum_t(), enum_t('a')).should == true
865
calculator.assignable?(enum_t('a'), enum_t()).should == false
868
it 'enum should accept a variant where all variants are acceptable' do
869
enum = enum_t('a', 'b')
870
calculator.assignable?(enum, variant_t(string_t('a'), string_t('b'))).should == true
874
context 'when dealing with string and enum combinations' do
875
it 'should accept assigning any enum to unrestricted string' do
876
calculator.assignable?(string_t(), enum_t('blue')).should == true
877
calculator.assignable?(string_t(), enum_t('blue', 'red')).should == true
880
it 'should not accept assigning longer enum value to size restricted string' do
881
calculator.assignable?(constrained_t(string_t(),2,2), enum_t('a','blue')).should == false
884
it 'should accept assigning any string to empty enum' do
885
calculator.assignable?(enum_t(), string_t()).should == true
888
it 'should accept assigning empty enum to any string' do
889
calculator.assignable?(string_t(), enum_t()).should == true
892
it 'should not accept assigning empty enum to size constrained string' do
893
calculator.assignable?(constrained_t(string_t(),2,2), enum_t()).should == false
897
context 'when dealing with string/pattern/enum combinations' do
898
it 'any string is equal to any enum is equal to any pattern' do
899
calculator.assignable?(string_t(), enum_t()).should == true
900
calculator.assignable?(string_t(), pattern_t()).should == true
901
calculator.assignable?(enum_t(), string_t()).should == true
902
calculator.assignable?(enum_t(), pattern_t()).should == true
903
calculator.assignable?(pattern_t(), string_t()).should == true
904
calculator.assignable?(pattern_t(), enum_t()).should == true
798
908
context 'when dealing with tuples' do
909
it 'matches empty tuples' do
913
calculator.assignable?(tuple1, tuple2).should == true
914
calculator.assignable?(tuple2, tuple1).should == true
917
it 'accepts an empty tuple as assignable to a tuple with a min size of 0' do
918
tuple1 = tuple_t(Object)
919
factory.constrain_size(tuple1, 0, :default)
922
calculator.assignable?(tuple1, tuple2).should == true
923
calculator.assignable?(tuple2, tuple1).should == false
799
926
it 'should accept matching tuples' do
800
927
tuple1 = tuple_t(1,2)
801
928
tuple2 = tuple_t(Integer,Integer)
960
1098
context 'when testing if x is instance of type t' do
961
1099
include_context "types_setup"
963
it 'should consider undef to be instance of Object and NilType' do
1101
it 'should consider undef to be instance of Any, NilType, and optional' do
964
1102
calculator.instance?(Puppet::Pops::Types::PNilType.new(), nil).should == true
965
calculator.instance?(Puppet::Pops::Types::PObjectType.new(), nil).should == true
968
it 'should not consider undef to be an instance of any other type than Object and NilType and Data' do
969
types_to_test = all_types - [
970
Puppet::Pops::Types::PObjectType,
1103
calculator.instance?(Puppet::Pops::Types::PAnyType.new(), nil).should == true
1104
calculator.instance?(Puppet::Pops::Types::POptionalType.new(), nil).should == true
1107
it 'all types should be (ruby) instance of PAnyType' do
1108
all_types.each do |t|
1109
t.new.is_a?(Puppet::Pops::Types::PAnyType).should == true
1113
it "should consider :undef to be instance of Runtime['ruby', 'Symbol]" do
1114
calculator.instance?(Puppet::Pops::Types::PRuntimeType.new(:runtime => :ruby, :runtime_type_name => 'Symbol'), :undef).should == true
1117
it "should consider :undef to be instance of an Optional type" do
1118
calculator.instance?(Puppet::Pops::Types::POptionalType.new(), :undef).should == true
1121
it 'should not consider undef to be an instance of any other type than Any, NilType and Data' do
1122
types_to_test = all_types - [
1123
Puppet::Pops::Types::PAnyType,
971
1124
Puppet::Pops::Types::PNilType,
972
Puppet::Pops::Types::PDataType]
1125
Puppet::Pops::Types::PDataType,
1126
Puppet::Pops::Types::POptionalType,
974
1129
types_to_test.each {|t| calculator.instance?(t.new, nil).should == false }
975
1130
types_to_test.each {|t| calculator.instance?(t.new, :undef).should == false }
1133
it 'should consider default to be instance of Default and Any' do
1134
calculator.instance?(Puppet::Pops::Types::PDefaultType.new(), :default).should == true
1135
calculator.instance?(Puppet::Pops::Types::PAnyType.new(), :default).should == true
1138
it 'should not consider "default" to be an instance of anything but Default, and Any' do
1139
types_to_test = all_types - [
1140
Puppet::Pops::Types::PAnyType,
1141
Puppet::Pops::Types::PDefaultType,
1144
types_to_test.each {|t| calculator.instance?(t.new, :default).should == false }
978
1147
it 'should consider fixnum instanceof PIntegerType' do
979
1148
calculator.instance?(Puppet::Pops::Types::PIntegerType.new(), 1).should == true
1093
1262
it 'a hash with nil/undef data should be considered instance of Data' do
1094
1263
calculator.instance?(data_t, {'a' => nil}).should == true
1095
calculator.instance?(data_t, {'a' => :undef}).should == true
1098
it 'a hash with nil/undef key should not considered instance of Data' do
1266
it 'a hash with nil/default key should not considered instance of Data' do
1099
1267
calculator.instance?(data_t, {nil => 10}).should == false
1100
calculator.instance?(data_t, {:undef => 10}).should == false
1268
calculator.instance?(data_t, {:default => 10}).should == false
1103
it 'an array with undef entries should be considered instance of Data' do
1104
calculator.instance?(data_t, [:undef]).should == true
1271
it 'an array with nil entries should be considered instance of Data' do
1105
1272
calculator.instance?(data_t, [nil]).should == true
1108
it 'an array with undef / data entries should be considered instance of Data' do
1109
calculator.instance?(data_t, [1, :undef, 'a']).should == true
1275
it 'an array with nil + data entries should be considered instance of Data' do
1110
1276
calculator.instance?(data_t, [1, nil, 'a']).should == true
1119
1285
the_block = factory.LAMBDA(params,factory.literal(42))
1120
1286
the_closure = Puppet::Pops::Evaluator::Closure.new(:fake_evaluator, the_block, :fake_scope)
1121
1287
expect(calculator.instance?(all_callables_t, the_closure)).to be_true
1122
# TODO: lambdas are currently unttypes, anything can be given if arg count is correct
1123
expect(calculator.instance?(callable_t(optional_object_t), the_closure)).to be_true
1124
# Arg count is wrong
1125
expect(calculator.instance?(callable_t(optional_object_t, optional_object_t), the_closure)).to be_false
1288
expect(calculator.instance?(callable_t(object_t), the_closure)).to be_true
1289
expect(calculator.instance?(callable_t(object_t, object_t), the_closure)).to be_false
1128
1292
it 'a Function instance should be considered a Callable' do
1397
1561
expect(calculator.string(callable_t(String, Integer))).to eql("Callable[String, Integer]")
1400
it "should yield 'Callable[t,min.max]' for callable with size constraint (infinite max)" do
1564
it "should yield 'Callable[t,min,max]' for callable with size constraint (infinite max)" do
1401
1565
expect(calculator.string(callable_t(String, 0))).to eql("Callable[String, 0, default]")
1404
it "should yield 'Callable[t,min.max]' for callable with size constraint (capped max)" do
1568
it "should yield 'Callable[t,min,max]' for callable with size constraint (capped max)" do
1405
1569
expect(calculator.string(callable_t(String, 0, 3))).to eql("Callable[String, 0, 3]")
1572
it "should yield 'Callable[min,max]' callable with size > 0" do
1573
expect(calculator.string(callable_t(0, 0))).to eql("Callable[0, 0]")
1574
expect(calculator.string(callable_t(0, 1))).to eql("Callable[0, 1]")
1575
expect(calculator.string(callable_t(0, :default))).to eql("Callable[0, default]")
1408
1578
it "should yield 'Callable[Callable]' for callable with block" do
1409
1579
expect(calculator.string(callable_t(all_callables_t))).to eql("Callable[0, 0, Callable]")
1410
1580
expect(calculator.string(callable_t(string_t, all_callables_t))).to eql("Callable[String, Callable]")
1411
1581
expect(calculator.string(callable_t(string_t, 1,1, all_callables_t))).to eql("Callable[String, 1, 1, Callable]")
1584
it "should yield Unit for a Unit type" do
1585
expect(calculator.string(unit_t)).to eql('Unit')
1416
1589
context 'when processing meta type' do
1764
context 'when determening callability' do
1765
context 'and given is exact' do
1766
it 'with callable' do
1767
required = callable_t(string_t)
1768
given = callable_t(string_t)
1769
calculator.callable?(required, given).should == true
1772
it 'with args tuple' do
1773
required = callable_t(string_t)
1774
given = tuple_t(string_t)
1775
calculator.callable?(required, given).should == true
1778
it 'with args tuple having a block' do
1779
required = callable_t(string_t, callable_t(string_t))
1780
given = tuple_t(string_t, callable_t(string_t))
1781
calculator.callable?(required, given).should == true
1784
it 'with args array' do
1785
required = callable_t(string_t)
1786
given = array_t(string_t)
1787
factory.constrain_size(given, 1, 1)
1788
calculator.callable?(required, given).should == true
1792
context 'and given is more generic' do
1793
it 'with callable' do
1794
required = callable_t(string_t)
1795
given = callable_t(object_t)
1796
calculator.callable?(required, given).should == true
1799
it 'with args tuple' do
1800
required = callable_t(string_t)
1801
given = tuple_t(object_t)
1802
calculator.callable?(required, given).should == false
1805
it 'with args tuple having a block' do
1806
required = callable_t(string_t, callable_t(string_t))
1807
given = tuple_t(string_t, callable_t(object_t))
1808
calculator.callable?(required, given).should == true
1811
it 'with args tuple having a block with captures rest' do
1812
required = callable_t(string_t, callable_t(string_t))
1813
given = tuple_t(string_t, callable_t(object_t, 0, :default))
1814
calculator.callable?(required, given).should == true
1818
context 'and given is more specific' do
1819
it 'with callable' do
1820
required = callable_t(object_t)
1821
given = callable_t(string_t)
1822
calculator.callable?(required, given).should == false
1825
it 'with args tuple' do
1826
required = callable_t(object_t)
1827
given = tuple_t(string_t)
1828
calculator.callable?(required, given).should == true
1831
it 'with args tuple having a block' do
1832
required = callable_t(string_t, callable_t(object_t))
1833
given = tuple_t(string_t, callable_t(string_t))
1834
calculator.callable?(required, given).should == false
1837
it 'with args tuple having a block with captures rest' do
1838
required = callable_t(string_t, callable_t(object_t))
1839
given = tuple_t(string_t, callable_t(string_t, 0, :default))
1840
calculator.callable?(required, given).should == false
1587
1845
matcher :be_assignable_to do |type|
1588
1846
calc = Puppet::Pops::Types::TypeCalculator.new