puppet 4.4.2 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CONTRIBUTING.md +5 -5
- data/Gemfile +2 -2
- data/LICENSE +2 -2
- data/README.md +5 -0
- data/ext/project_data.yaml +2 -0
- data/lib/hiera_puppet.rb +6 -14
- data/lib/puppet/application/agent.rb +2 -3
- data/lib/puppet/data_providers/hiera_config.rb +2 -4
- data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
- data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
- data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
- data/lib/puppet/defaults.rb +70 -7
- data/lib/puppet/functions.rb +69 -0
- data/lib/puppet/functions/dig.rb +39 -0
- data/lib/puppet/functions/lest.rb +53 -0
- data/lib/puppet/functions/lookup.rb +40 -27
- data/lib/puppet/functions/new.rb +502 -0
- data/lib/puppet/functions/regsubst.rb +11 -10
- data/lib/puppet/functions/then.rb +74 -0
- data/lib/puppet/functions/type.rb +4 -4
- data/lib/puppet/functions/with.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +2 -0
- data/lib/puppet/indirector/resource_type/parser.rb +5 -0
- data/lib/puppet/indirector/rest.rb +5 -1
- data/lib/puppet/loaders.rb +2 -0
- data/lib/puppet/metatype/manager.rb +19 -2
- data/lib/puppet/module_tool/applications/application.rb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
- data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
- data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
- data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
- data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
- data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
- data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
- data/lib/puppet/parser/environment_compiler.rb +2 -2
- data/lib/puppet/parser/resource.rb +14 -5
- data/lib/puppet/parser/scope.rb +18 -15
- data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
- data/lib/puppet/pops.rb +6 -0
- data/lib/puppet/pops/adapters.rb +5 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
- data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
- data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
- data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
- data/lib/puppet/pops/functions/dispatcher.rb +1 -1
- data/lib/puppet/pops/issues.rb +18 -2
- data/lib/puppet/pops/loader/base_loader.rb +48 -7
- data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
- data/lib/puppet/pops/loader/loader.rb +12 -0
- data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
- data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
- data/lib/puppet/pops/loader/static_loader.rb +92 -5
- data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
- data/lib/puppet/pops/loaders.rb +84 -14
- data/lib/puppet/pops/lookup/explainer.rb +38 -1
- data/lib/puppet/pops/lookup/interpolation.rb +115 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
- data/lib/puppet/pops/model/ast_transformer.rb +8 -1
- data/lib/puppet/pops/model/factory.rb +31 -8
- data/lib/puppet/pops/model/model.rb +8 -0
- data/lib/puppet/pops/model/model_label_provider.rb +1 -0
- data/lib/puppet/pops/model/model_meta.rb +7 -1
- data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
- data/lib/puppet/pops/parser/egrammar.ra +24 -7
- data/lib/puppet/pops/parser/eparser.rb +863 -798
- data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
- data/lib/puppet/pops/parser/locator.rb +8 -4
- data/lib/puppet/pops/pcore.rb +30 -0
- data/lib/puppet/pops/types/class_loader.rb +2 -4
- data/lib/puppet/pops/types/implementation_registry.rb +146 -0
- data/lib/puppet/pops/types/iterable.rb +4 -4
- data/lib/puppet/pops/types/p_object_type.rb +846 -0
- data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
- data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
- data/lib/puppet/pops/types/puppet_object.rb +21 -0
- data/lib/puppet/pops/types/ruby_generator.rb +258 -0
- data/lib/puppet/pops/types/string_converter.rb +922 -0
- data/lib/puppet/pops/types/type_calculator.rb +29 -5
- data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
- data/lib/puppet/pops/types/type_factory.rb +49 -16
- data/lib/puppet/pops/types/type_formatter.rb +335 -112
- data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
- data/lib/puppet/pops/types/type_parser.rb +205 -197
- data/lib/puppet/pops/types/types.rb +481 -103
- data/lib/puppet/pops/validation.rb +1 -1
- data/lib/puppet/pops/validation/checker4_0.rb +66 -4
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/pops/visitor.rb +3 -1
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +64 -20
- data/lib/puppet/provider/package/rpm.rb +112 -0
- data/lib/puppet/provider/package/yum.rb +7 -68
- data/lib/puppet/provider/service/daemontools.rb +3 -3
- data/lib/puppet/provider/service/init.rb +4 -2
- data/lib/puppet/provider/service/runit.rb +3 -3
- data/lib/puppet/provider/service/smf.rb +6 -3
- data/lib/puppet/provider/service/systemd.rb +59 -73
- data/lib/puppet/reference/providers.rb +1 -2
- data/lib/puppet/resource.rb +54 -37
- data/lib/puppet/resource/catalog.rb +31 -29
- data/lib/puppet/resource/type_collection.rb +23 -8
- data/lib/puppet/settings.rb +4 -2
- data/lib/puppet/settings/base_setting.rb +9 -3
- data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
- data/lib/puppet/test/test_helper.rb +0 -1
- data/lib/puppet/type.rb +9 -3
- data/lib/puppet/type/exec.rb +17 -17
- data/lib/puppet/type/file.rb +12 -0
- data/lib/puppet/type/file/content.rb +6 -6
- data/lib/puppet/type/file/ensure.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/mount.rb +18 -1
- data/lib/puppet/type/package.rb +3 -3
- data/lib/puppet/type/schedule.rb +4 -4
- data/lib/puppet/type/service.rb +15 -0
- data/lib/puppet/type/sshkey.rb +5 -3
- data/lib/puppet/type/tidy.rb +3 -3
- data/lib/puppet/type/zone.rb +5 -5
- data/lib/puppet/util/feature.rb +1 -1
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/network_device/cisco/device.rb +16 -6
- data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
- data/lib/puppet/util/plist.rb +3 -3
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
- data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
- data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
- data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
- data/spec/integration/parser/catalog_spec.rb +14 -2
- data/spec/integration/parser/compiler_spec.rb +94 -3
- data/spec/integration/parser/resource_expressions_spec.rb +1 -1
- data/spec/integration/resource/type_collection_spec.rb +8 -0
- data/spec/lib/puppet_spec/compiler.rb +11 -4
- data/spec/shared_contexts/types_setup.rb +4 -0
- data/spec/unit/application/lookup_spec.rb +91 -9
- data/spec/unit/appmgmt_spec.rb +44 -35
- data/spec/unit/capability_spec.rb +33 -53
- data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
- data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
- data/spec/unit/defaults_spec.rb +18 -0
- data/spec/unit/functions/assert_type_spec.rb +1 -1
- data/spec/unit/functions/dig_spec.rb +58 -0
- data/spec/unit/functions/lest_spec.rb +34 -0
- data/spec/unit/functions/lookup_spec.rb +108 -2
- data/spec/unit/functions/new_spec.rb +543 -0
- data/spec/unit/functions/regsubst_spec.rb +8 -0
- data/spec/unit/functions/then_spec.rb +40 -0
- data/spec/unit/functions4_spec.rb +78 -10
- data/spec/unit/hiera_puppet_spec.rb +49 -8
- data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
- data/spec/unit/indirector/rest_spec.rb +12 -0
- data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
- data/spec/unit/node/environment_spec.rb +10 -0
- data/spec/unit/parser/compiler_spec.rb +20 -1
- data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
- data/spec/unit/parser/functions/shared.rb +1 -1
- data/spec/unit/parser/resource_spec.rb +8 -1
- data/spec/unit/parser/scope_spec.rb +45 -0
- data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
- data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
- data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
- data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
- data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
- data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
- data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
- data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
- data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
- data/spec/unit/pops/types/enumeration_spec.rb +13 -12
- data/spec/unit/pops/types/iterable_spec.rb +2 -2
- data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
- data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
- data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
- data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
- data/spec/unit/pops/types/string_converter_spec.rb +904 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
- data/spec/unit/pops/types/type_factory_spec.rb +119 -104
- data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
- data/spec/unit/pops/types/type_parser_spec.rb +54 -15
- data/spec/unit/pops/types/types_spec.rb +113 -8
- data/spec/unit/pops/validator/validator_spec.rb +84 -10
- data/spec/unit/provider/package/pip3_spec.rb +9 -270
- data/spec/unit/provider/package/pip_spec.rb +85 -30
- data/spec/unit/provider/package/rpm_spec.rb +160 -3
- data/spec/unit/provider/package/yum_spec.rb +23 -134
- data/spec/unit/provider/service/smf_spec.rb +14 -2
- data/spec/unit/provider/service/systemd_spec.rb +33 -41
- data/spec/unit/resource/capability_finder_spec.rb +10 -2
- data/spec/unit/settings/file_setting_spec.rb +6 -0
- data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
- data/spec/unit/type/mount_spec.rb +51 -10
- data/spec/unit/type/service_spec.rb +16 -0
- data/spec/unit/type_spec.rb +14 -0
- data/spec/unit/util/feature_spec.rb +1 -1
- data/spec/unit/util/monkey_patches_spec.rb +60 -0
- data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
- metadata +63 -11
- data/lib/puppet/pops/types/types_meta.rb +0 -0
- data/spec/integration/provider/package_spec.rb +0 -35
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet/pops'
|
3
|
+
require 'puppet_spec/compiler'
|
4
|
+
|
5
|
+
module Puppet::Pops
|
6
|
+
module Types
|
7
|
+
describe 'Semantic Versions' do
|
8
|
+
include PuppetSpec::Compiler
|
9
|
+
|
10
|
+
context 'the SemVer type' do
|
11
|
+
it 'is normalized in a Variant' do
|
12
|
+
t = TypeFactory.variant(TypeFactory.sem_ver('>=1.0.0 <2.0.0'), TypeFactory.sem_ver('>=1.5.0 <4.0.0')).normalize
|
13
|
+
expect(t).to be_a(PSemVerType)
|
14
|
+
expect(t).to eql(TypeFactory.sem_ver('>=1.0.0 <4.0.0'))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when used in Puppet expressions' do
|
19
|
+
|
20
|
+
context 'the SemVer type' do
|
21
|
+
it 'can have multiple range arguments' do
|
22
|
+
code = <<-CODE
|
23
|
+
$t = SemVer[SemVerRange('>=1.0.0 <2.0.0'), SemVerRange('>=3.0.0 <4.0.0')]
|
24
|
+
notice(SemVer('1.2.3') =~ $t)
|
25
|
+
notice(SemVer('2.3.4') =~ $t)
|
26
|
+
notice(SemVer('3.4.5') =~ $t)
|
27
|
+
CODE
|
28
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false', 'true'])
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'can have multiple range arguments in string form' do
|
32
|
+
code = <<-CODE
|
33
|
+
$t = SemVer['>=1.0.0 <2.0.0', '>=3.0.0 <4.0.0']
|
34
|
+
notice(SemVer('1.2.3') =~ $t)
|
35
|
+
notice(SemVer('2.3.4') =~ $t)
|
36
|
+
notice(SemVer('3.4.5') =~ $t)
|
37
|
+
CODE
|
38
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false', 'true'])
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'range arguments are normalized' do
|
42
|
+
code = <<-CODE
|
43
|
+
notice(SemVer['>=1.0.0 <2.0.0', '>=1.5.0 <4.0.0'] == SemVer['>=1.0.0 <4.0.0'])
|
44
|
+
CODE
|
45
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'is assignable to a type containing ranges with a merged range that is assignable but individual ranges are not' do
|
49
|
+
code = <<-CODE
|
50
|
+
$x = SemVer['>=1.0.0 <2.0.0', '>=1.5.0 <3.0.0']
|
51
|
+
$y = SemVer['>=1.2.0 <2.8.0']
|
52
|
+
notice($y < $x)
|
53
|
+
CODE
|
54
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'the SemVerRange type' do
|
59
|
+
it 'a range is an instance of the type' do
|
60
|
+
code = <<-CODE
|
61
|
+
notice(SemVerRange('3.0.0 - 4.0.0') =~ SemVerRange)
|
62
|
+
CODE
|
63
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'a SemVer instance' do
|
68
|
+
it 'can be created from a String' do
|
69
|
+
code = <<-CODE
|
70
|
+
$x = SemVer('1.2.3')
|
71
|
+
notice(assert_type(SemVer, $x))
|
72
|
+
CODE
|
73
|
+
expect(eval_and_collect_notices(code)).to eql(['1.2.3'])
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'can be compared to another instance for equality' do
|
77
|
+
code = <<-CODE
|
78
|
+
$x = SemVer('1.2.3')
|
79
|
+
$y = SemVer('1.2.3')
|
80
|
+
notice($x == $y)
|
81
|
+
notice($x != $y)
|
82
|
+
CODE
|
83
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false'])
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'can be compared to another instance for magnitude' do
|
87
|
+
code = <<-CODE
|
88
|
+
$x = SemVer('1.1.1')
|
89
|
+
$y = SemVer('1.2.3')
|
90
|
+
notice($x < $y)
|
91
|
+
notice($x <= $y)
|
92
|
+
notice($x > $y)
|
93
|
+
notice($x >= $y)
|
94
|
+
CODE
|
95
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'true', 'false', 'false'])
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'can be matched against a version range' do
|
99
|
+
code = <<-CODE
|
100
|
+
$v = SemVer('1.1.1')
|
101
|
+
notice($v =~ SemVerRange('>1.0.0'))
|
102
|
+
notice($v =~ SemVerRange('>1.1.1'))
|
103
|
+
notice($v =~ SemVerRange('>=1.1.1'))
|
104
|
+
CODE
|
105
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false', 'true'])
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'can be matched against a SemVerRange in case expression' do
|
109
|
+
code = <<-CODE
|
110
|
+
case SemVer('1.1.1') {
|
111
|
+
SemVerRange('>1.1.1'): {
|
112
|
+
notice('high')
|
113
|
+
}
|
114
|
+
SemVerRange('>1.0.0'): {
|
115
|
+
notice('mid')
|
116
|
+
}
|
117
|
+
default: {
|
118
|
+
notice('low')
|
119
|
+
}
|
120
|
+
}
|
121
|
+
CODE
|
122
|
+
expect(eval_and_collect_notices(code)).to eql(['mid'])
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'can be matched against a SemVer in case expression' do
|
126
|
+
code = <<-CODE
|
127
|
+
case SemVer('1.1.1') {
|
128
|
+
SemVer('1.1.0'): {
|
129
|
+
notice('high')
|
130
|
+
}
|
131
|
+
SemVer('1.1.1'): {
|
132
|
+
notice('mid')
|
133
|
+
}
|
134
|
+
default: {
|
135
|
+
notice('low')
|
136
|
+
}
|
137
|
+
}
|
138
|
+
CODE
|
139
|
+
expect(eval_and_collect_notices(code)).to eql(['mid'])
|
140
|
+
end
|
141
|
+
|
142
|
+
it "can be matched against a versions in 'in' expression" do
|
143
|
+
code = <<-CODE
|
144
|
+
notice(SemVer('1.1.1') in [SemVer('1.0.0'), SemVer('1.1.1'), SemVer('2.3.4')])
|
145
|
+
CODE
|
146
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
147
|
+
end
|
148
|
+
|
149
|
+
it "can be matched against a VersionRange using an 'in' expression" do
|
150
|
+
code = <<-CODE
|
151
|
+
notice(SemVer('1.1.1') in SemVerRange('>1.0.0'))
|
152
|
+
CODE
|
153
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
154
|
+
end
|
155
|
+
|
156
|
+
it "can be matched against multiple VersionRanges using an 'in' expression" do
|
157
|
+
code = <<-CODE
|
158
|
+
notice(SemVer('1.1.1') in [SemVerRange('>=1.0.0 <1.0.2'), SemVerRange('>=1.1.0 <1.1.2')])
|
159
|
+
CODE
|
160
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'a String representing a SemVer' do
|
165
|
+
it 'can be matched against a version range' do
|
166
|
+
code = <<-CODE
|
167
|
+
$v = '1.1.1'
|
168
|
+
notice($v =~ SemVerRange('>1.0.0'))
|
169
|
+
notice($v =~ SemVerRange('>1.1.1'))
|
170
|
+
notice($v =~ SemVerRange('>=1.1.1'))
|
171
|
+
CODE
|
172
|
+
expect(eval_and_collect_notices(code)).to eql(['true', 'false', 'true'])
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'can be matched against a SemVerRange in case expression' do
|
176
|
+
code = <<-CODE
|
177
|
+
case '1.1.1' {
|
178
|
+
SemVerRange('>1.1.1'): {
|
179
|
+
notice('high')
|
180
|
+
}
|
181
|
+
SemVerRange('>1.0.0'): {
|
182
|
+
notice('mid')
|
183
|
+
}
|
184
|
+
default: {
|
185
|
+
notice('low')
|
186
|
+
}
|
187
|
+
}
|
188
|
+
CODE
|
189
|
+
expect(eval_and_collect_notices(code)).to eql(['mid'])
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'can be matched against a SemVer in case expression' do
|
193
|
+
code = <<-CODE
|
194
|
+
case '1.1.1' {
|
195
|
+
SemVer('1.1.0'): {
|
196
|
+
notice('high')
|
197
|
+
}
|
198
|
+
SemVer('1.1.1'): {
|
199
|
+
notice('mid')
|
200
|
+
}
|
201
|
+
default: {
|
202
|
+
notice('low')
|
203
|
+
}
|
204
|
+
}
|
205
|
+
CODE
|
206
|
+
expect(eval_and_collect_notices(code)).to eql(['mid'])
|
207
|
+
end
|
208
|
+
|
209
|
+
it "can be matched against a VersionRange using an 'in' expression" do
|
210
|
+
code = <<-CODE
|
211
|
+
notice('1.1.1' in SemVerRange('>1.0.0'))
|
212
|
+
CODE
|
213
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
214
|
+
end
|
215
|
+
|
216
|
+
it "can be matched against multiple VersionRanges using an 'in' expression" do
|
217
|
+
code = <<-CODE
|
218
|
+
notice('1.1.1' in [SemVerRange('>=1.0.0 <1.0.2'), SemVerRange('>=1.1.0 <1.1.2')])
|
219
|
+
CODE
|
220
|
+
expect(eval_and_collect_notices(code)).to eql(['true'])
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'matching SemVer' do
|
225
|
+
suitability = {
|
226
|
+
[ '1.2.3', '1.2.2' ] => false,
|
227
|
+
[ '>=1.2.3', '1.2.2' ] => false,
|
228
|
+
[ '<=1.2.3', '1.2.2' ] => true,
|
229
|
+
[ '1.2.3 - 1.2.4', '1.2.2' ] => false,
|
230
|
+
[ '~1.2.3', '1.2.2' ] => false,
|
231
|
+
[ '~1.2', '1.2.2' ] => true,
|
232
|
+
[ '~1', '1.2.2' ] => true,
|
233
|
+
[ '1.2.x', '1.2.2' ] => true,
|
234
|
+
[ '1.x', '1.2.2' ] => true,
|
235
|
+
|
236
|
+
[ '1.2.3', '1.2.3-alpha' ] => true,
|
237
|
+
[ '>=1.2.3', '1.2.3-alpha' ] => true,
|
238
|
+
[ '<=1.2.3', '1.2.3-alpha' ] => true,
|
239
|
+
[ '>1.2.3', '1.2.3-alpha' ] => false,
|
240
|
+
[ '<1.2.3', '1.2.3-alpha' ] => false,
|
241
|
+
[ '1.2.3 - 1.2.4', '1.2.3-alpha' ] => true,
|
242
|
+
[ '1.2.3 - 1.2.4', '1.2.4-alpha' ] => true,
|
243
|
+
[ '1.2.3 - 1.2.4', '1.2.5-alpha' ] => false,
|
244
|
+
[ '~1.2.3', '1.2.3-alpha' ] => true,
|
245
|
+
[ '~1.2.3', '1.3.0-alpha' ] => false,
|
246
|
+
[ '~1.2', '1.2.3-alpha' ] => true,
|
247
|
+
[ '~1.2', '2.0.0-alpha' ] => false,
|
248
|
+
[ '~1', '1.2.3-alpha' ] => true,
|
249
|
+
[ '~1', '2.0.0-alpha' ] => false,
|
250
|
+
[ '1.2.x', '1.2.3-alpha' ] => true,
|
251
|
+
[ '1.2.x', '1.3.0-alpha' ] => false,
|
252
|
+
[ '1.x', '1.2.3-alpha' ] => true,
|
253
|
+
[ '1.x', '2.0.0-alpha' ] => false,
|
254
|
+
|
255
|
+
[ '1.2.3', '1.2.3' ] => true,
|
256
|
+
[ '>=1.2.3', '1.2.3' ] => true,
|
257
|
+
[ '<=1.2.3', '1.2.3' ] => true,
|
258
|
+
[ '1.2.3 - 1.2.4', '1.2.3' ] => true,
|
259
|
+
[ '~1.2.3', '1.2.3' ] => true,
|
260
|
+
[ '~1.2', '1.2.3' ] => true,
|
261
|
+
[ '~1', '1.2.3' ] => true,
|
262
|
+
[ '1.2.x', '1.2.3' ] => true,
|
263
|
+
[ '1.x', '1.2.3' ] => true,
|
264
|
+
|
265
|
+
[ '1.2.3', '1.2.4' ] => false,
|
266
|
+
[ '>=1.2.3', '1.2.4' ] => true,
|
267
|
+
[ '<=1.2.3', '1.2.4' ] => false,
|
268
|
+
[ '1.2.3 - 1.2.4', '1.2.4' ] => true,
|
269
|
+
# [ '~1.2.3', '1.2.4' ] => true, Awaits fix for PUP-6242
|
270
|
+
[ '~1.2', '1.2.4' ] => true,
|
271
|
+
[ '~1', '1.2.4' ] => true,
|
272
|
+
[ '1.2.x', '1.2.4' ] => true,
|
273
|
+
[ '1.x', '1.2.4' ] => true,
|
274
|
+
}
|
275
|
+
suitability.each do |arguments, expected|
|
276
|
+
it "'#{arguments[1]}' against SemVerRange '#{arguments[0]}', yields #{expected}" do
|
277
|
+
code = "notice(SemVer('#{arguments[1]}') =~ SemVerRange('#{arguments[0]}'))"
|
278
|
+
expect(eval_and_collect_notices(code)).to eql([expected.to_s])
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -1,34 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'puppet/pops/types/recursion_guard'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Puppet::Pops::Types
|
5
|
+
describe 'the RecursionGuard' do
|
6
|
+
let(:guard) { RecursionGuard.new }
|
6
7
|
|
7
8
|
it "should detect recursion in 'this' context" do
|
8
9
|
x = Object.new
|
9
|
-
expect(guard.add_this(x)).to eq(
|
10
|
-
expect(guard.add_this(x)).to eq(
|
10
|
+
expect(guard.add_this(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
11
|
+
expect(guard.add_this(x)).to eq(RecursionGuard::SELF_RECURSION_IN_THIS)
|
11
12
|
end
|
12
13
|
|
13
14
|
it "should detect recursion in 'that' context" do
|
14
15
|
x = Object.new
|
15
|
-
expect(guard.add_that(x)).to eq(
|
16
|
-
expect(guard.add_that(x)).to eq(
|
16
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
17
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::SELF_RECURSION_IN_THAT)
|
17
18
|
end
|
18
19
|
|
19
20
|
it "should keep 'this' and 'that' context separate" do
|
20
21
|
x = Object.new
|
21
|
-
expect(guard.add_this(x)).to eq(
|
22
|
-
expect(guard.add_that(x)).to eq(
|
22
|
+
expect(guard.add_this(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
23
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
23
24
|
end
|
24
25
|
|
25
26
|
it "should detect when there's a recursion in both 'this' and 'that' context" do
|
26
27
|
x = Object.new
|
27
28
|
y = Object.new
|
28
|
-
expect(guard.add_this(x)).to eq(
|
29
|
-
expect(guard.add_that(y)).to eq(
|
30
|
-
expect(guard.add_this(x)).to eq(
|
31
|
-
expect(guard.add_that(y)).to eq(
|
29
|
+
expect(guard.add_this(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
30
|
+
expect(guard.add_that(y)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
31
|
+
expect(guard.add_this(x)).to eq(RecursionGuard::SELF_RECURSION_IN_THIS)
|
32
|
+
expect(guard.add_that(y)).to eq(RecursionGuard::SELF_RECURSION_IN_BOTH)
|
32
33
|
end
|
33
34
|
|
34
35
|
it "should report that 'this' is recursive after a recursion has been detected" do
|
@@ -62,30 +63,31 @@ describe 'the Puppet::Pops::Types::RecursionGuard' do
|
|
62
63
|
it "should not call 'hash' on an added instance" do
|
63
64
|
x = mock
|
64
65
|
x.expects(:hash).never
|
65
|
-
expect(guard.add_that(x)).to eq(
|
66
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
66
67
|
end
|
67
68
|
|
68
69
|
it "should not call '==' on an added instance" do
|
69
70
|
x = mock
|
70
71
|
x.expects(:==).never
|
71
|
-
expect(guard.add_that(x)).to eq(
|
72
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
72
73
|
end
|
73
74
|
|
74
75
|
it "should not call 'eq?' on an added instance" do
|
75
76
|
x = mock
|
76
77
|
x.expects(:eq?).never
|
77
|
-
expect(guard.add_that(x)).to eq(
|
78
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
78
79
|
end
|
79
80
|
|
80
81
|
it "should not call 'eql?' on an added instance" do
|
81
82
|
x = mock
|
82
83
|
x.expects(:eql?).never
|
83
|
-
expect(guard.add_that(x)).to eq(
|
84
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
84
85
|
end
|
85
86
|
|
86
87
|
it "should not call 'equal?' on an added instance" do
|
87
88
|
x = mock
|
88
89
|
x.expects(:equal?).never
|
89
|
-
expect(guard.add_that(x)).to eq(
|
90
|
+
expect(guard.add_that(x)).to eq(RecursionGuard::NO_SELF_RECURSION)
|
90
91
|
end
|
91
92
|
end
|
93
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet/pops'
|
3
|
+
require 'puppet_spec/compiler'
|
4
|
+
require 'puppet/pops/types/ruby_generator'
|
5
|
+
|
6
|
+
def root_binding
|
7
|
+
return binding
|
8
|
+
end
|
9
|
+
|
10
|
+
module Puppet::Pops
|
11
|
+
module Types
|
12
|
+
describe 'Puppet Ruby Generator' do
|
13
|
+
include PuppetSpec::Compiler
|
14
|
+
|
15
|
+
def source
|
16
|
+
<<-CODE
|
17
|
+
type MyModule::FirstGenerated = Object[{
|
18
|
+
attributes => {
|
19
|
+
name => String,
|
20
|
+
age => { type => Integer, value => 30 },
|
21
|
+
what => { type => String, value => 'what is this', kind => constant }
|
22
|
+
}
|
23
|
+
}]
|
24
|
+
type MyModule::SecondGenerated = Object[{
|
25
|
+
parent => MyModule::FirstGenerated,
|
26
|
+
attributes => {
|
27
|
+
address => String,
|
28
|
+
zipcode => String,
|
29
|
+
email => String,
|
30
|
+
another => { type => Optional[MyModule::FirstGenerated], value => undef },
|
31
|
+
number => Integer
|
32
|
+
}
|
33
|
+
}]
|
34
|
+
CODE
|
35
|
+
end
|
36
|
+
|
37
|
+
let!(:parser) { TypeParser.new }
|
38
|
+
let(:generator) { RubyGenerator.new }
|
39
|
+
|
40
|
+
context 'when generating anonymous classes' do
|
41
|
+
|
42
|
+
scope = nil
|
43
|
+
|
44
|
+
let(:first_type) { parser.parse('MyModule::FirstGenerated', scope) }
|
45
|
+
let(:second_type) { parser.parse('MyModule::SecondGenerated', scope) }
|
46
|
+
let(:first) { generator.create_class(first_type) }
|
47
|
+
let(:second) { generator.create_class(second_type) }
|
48
|
+
|
49
|
+
before(:each) do
|
50
|
+
eval_and_collect_notices(source) do |topscope, catalog|
|
51
|
+
scope = topscope
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
after(:each) { typeset = nil }
|
56
|
+
|
57
|
+
context 'the generated class' do
|
58
|
+
it 'inherits the PuppetObject module' do
|
59
|
+
expect(first < PuppetObject).to be_truthy
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'is the superclass of a generated subclass' do
|
63
|
+
expect(second < first).to be_truthy
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'the #create class method' do
|
68
|
+
it 'has an arity that reflects optional arguments' do
|
69
|
+
expect(first.method(:create).arity).to eql(-2)
|
70
|
+
expect(second.method(:create).arity).to eql(-6)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'creates an instance of the class' do
|
74
|
+
inst = first.create('Bob Builder', 52)
|
75
|
+
expect(inst).to be_a(first)
|
76
|
+
expect(inst.name).to eq('Bob Builder')
|
77
|
+
expect(inst.age).to eq(52)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'will perform type assertion of the arguments' do
|
81
|
+
expect { first.create('Bob Builder', '52') }.to(
|
82
|
+
raise_error(TypeAssertionError,
|
83
|
+
'MyModule::FirstGenerated[age] had wrong type, expected an Integer value, got String')
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'will not accept nil as given value for an optional parameter that does not accept nil' do
|
88
|
+
expect { first.create('Bob Builder', nil) }.to(
|
89
|
+
raise_error(TypeAssertionError,
|
90
|
+
'MyModule::FirstGenerated[age] had wrong type, expected an Integer value, got Undef')
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'reorders parameters to but the optional parameters last' do
|
95
|
+
inst = second.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
|
96
|
+
expect(inst.name).to eq('Bob Builder')
|
97
|
+
expect(inst.address).to eq('42 Cool Street')
|
98
|
+
expect(inst.zipcode).to eq('12345')
|
99
|
+
expect(inst.email).to eq('bob@example.com')
|
100
|
+
expect(inst.number).to eq(23)
|
101
|
+
expect(inst.what).to eql('what is this')
|
102
|
+
expect(inst.age).to eql(30)
|
103
|
+
expect(inst.another).to be_nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'the #from_hash class method' do
|
108
|
+
it 'has an arity of one' do
|
109
|
+
expect(first.method(:from_hash).arity).to eql(1)
|
110
|
+
expect(second.method(:from_hash).arity).to eql(1)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'creates an instance of the class' do
|
114
|
+
inst = first.from_hash('name' => 'Bob Builder', 'age' => 52)
|
115
|
+
expect(inst).to be_a(first)
|
116
|
+
expect(inst.name).to eq('Bob Builder')
|
117
|
+
expect(inst.age).to eq(52)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'accepts an initializer where optional keys are missing' do
|
121
|
+
inst = first.from_hash('name' => 'Bob Builder')
|
122
|
+
expect(inst).to be_a(first)
|
123
|
+
expect(inst.name).to eq('Bob Builder')
|
124
|
+
expect(inst.age).to eq(30)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'does not accept an initializer where optional values are nil and type does not accept nil' do
|
128
|
+
expect { first.from_hash('name' => 'Bob Builder', 'age' => nil) }.to(
|
129
|
+
raise_error(TypeAssertionError,
|
130
|
+
"MyModule::FirstGenerated initializer had wrong type, entry 'age' expected an Integer value, got Undef")
|
131
|
+
)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'creates an instance' do
|
136
|
+
it 'that the TypeCalculator infers to the Object type' do
|
137
|
+
expect(TypeCalculator.infer(first.from_hash('name' => 'Bob Builder'))).to eq(first_type)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'when generating static code' do
|
143
|
+
module_def = nil
|
144
|
+
|
145
|
+
before(:each) do
|
146
|
+
# Ideally, this would be in a before(:all) but that is impossible since lots of Puppet
|
147
|
+
# environment specific settings are configured by the spec_helper in before(:each)
|
148
|
+
if module_def.nil?
|
149
|
+
first_type = nil
|
150
|
+
second_type = nil
|
151
|
+
eval_and_collect_notices(source) do |scope, catalog|
|
152
|
+
first_type = parser.parse('MyModule::FirstGenerated', scope)
|
153
|
+
second_type = parser.parse('MyModule::SecondGenerated', scope)
|
154
|
+
|
155
|
+
loader = Loaders.find_loader(nil)
|
156
|
+
Loaders.implementation_registry.register_type_mapping(
|
157
|
+
PRuntimeType.new(:ruby, [/^PuppetSpec::RubyGenerator::(\w+)$/, 'MyModule::\1']),
|
158
|
+
[/^MyModule::(\w+)$/, 'PuppetSpec::RubyGenerator::\1'], loader)
|
159
|
+
|
160
|
+
module_def = generator.module_definition([first_type, second_type], 'Generated stuff')
|
161
|
+
end
|
162
|
+
Loaders.clear
|
163
|
+
Puppet[:code] = nil
|
164
|
+
|
165
|
+
# Create the actual classes in the PuppetSpec::RubyGenerator module
|
166
|
+
Puppet.override(:loaders => Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, []))) do
|
167
|
+
eval(module_def, root_binding)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
after(:all) do
|
173
|
+
# Don't want generated module to leak outside this test
|
174
|
+
PuppetSpec.send(:remove_const, :RubyGenerator)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'the #_ptype class method returns a resolved Type' do
|
178
|
+
first_type = PuppetSpec::RubyGenerator::FirstGenerated._ptype
|
179
|
+
expect(first_type).to be_a(PObjectType)
|
180
|
+
second_type = PuppetSpec::RubyGenerator::SecondGenerated._ptype
|
181
|
+
expect(second_type).to be_a(PObjectType)
|
182
|
+
expect(second_type.parent).to eql(first_type)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'the #_plocation class method returns a file URI' do
|
186
|
+
loc = PuppetSpec::RubyGenerator::SecondGenerated._plocation
|
187
|
+
expect(loc).to be_a(URI)
|
188
|
+
expect(loc.to_s).to match(/^file:\/.*ruby_generator_spec.rb\?line=\d+$/)
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'the #create class method' do
|
192
|
+
it 'has an arity that reflects optional arguments' do
|
193
|
+
expect(PuppetSpec::RubyGenerator::FirstGenerated.method(:create).arity).to eql(-2)
|
194
|
+
expect(PuppetSpec::RubyGenerator::SecondGenerated.method(:create).arity).to eql(-6)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'creates an instance of the class' do
|
198
|
+
inst = PuppetSpec::RubyGenerator::FirstGenerated.create('Bob Builder', 52)
|
199
|
+
expect(inst).to be_a(PuppetSpec::RubyGenerator::FirstGenerated)
|
200
|
+
expect(inst.name).to eq('Bob Builder')
|
201
|
+
expect(inst.age).to eq(52)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'will perform type assertion of the arguments' do
|
205
|
+
expect { PuppetSpec::RubyGenerator::FirstGenerated.create('Bob Builder', '52') }.to(
|
206
|
+
raise_error(TypeAssertionError,
|
207
|
+
'MyModule::FirstGenerated[age] had wrong type, expected an Integer value, got String')
|
208
|
+
)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'will not accept nil as given value for an optional parameter that does not accept nil' do
|
212
|
+
expect { PuppetSpec::RubyGenerator::FirstGenerated.create('Bob Builder', nil) }.to(
|
213
|
+
raise_error(TypeAssertionError,
|
214
|
+
'MyModule::FirstGenerated[age] had wrong type, expected an Integer value, got Undef')
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'reorders parameters to but the optional parameters last' do
|
219
|
+
inst = PuppetSpec::RubyGenerator::SecondGenerated.create('Bob Builder', '42 Cool Street', '12345', 'bob@example.com', 23)
|
220
|
+
expect(inst.name).to eq('Bob Builder')
|
221
|
+
expect(inst.address).to eq('42 Cool Street')
|
222
|
+
expect(inst.zipcode).to eq('12345')
|
223
|
+
expect(inst.email).to eq('bob@example.com')
|
224
|
+
expect(inst.number).to eq(23)
|
225
|
+
expect(inst.what).to eql('what is this')
|
226
|
+
expect(inst.age).to eql(30)
|
227
|
+
expect(inst.another).to be_nil
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'the #from_hash class method' do
|
232
|
+
it 'has an arity of one' do
|
233
|
+
expect(PuppetSpec::RubyGenerator::FirstGenerated.method(:from_hash).arity).to eql(1)
|
234
|
+
expect(PuppetSpec::RubyGenerator::SecondGenerated.method(:from_hash).arity).to eql(1)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'creates an instance of the class' do
|
238
|
+
inst = PuppetSpec::RubyGenerator::FirstGenerated.from_hash('name' => 'Bob Builder', 'age' => 52)
|
239
|
+
expect(inst).to be_a(PuppetSpec::RubyGenerator::FirstGenerated)
|
240
|
+
expect(inst.name).to eq('Bob Builder')
|
241
|
+
expect(inst.age).to eq(52)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'accepts an initializer where optional keys are missing' do
|
245
|
+
inst = PuppetSpec::RubyGenerator::FirstGenerated.from_hash('name' => 'Bob Builder')
|
246
|
+
expect(inst).to be_a(PuppetSpec::RubyGenerator::FirstGenerated)
|
247
|
+
expect(inst.name).to eq('Bob Builder')
|
248
|
+
expect(inst.age).to eq(30)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'does not accept an initializer where optional values are nil and type does not accept nil' do
|
252
|
+
expect { PuppetSpec::RubyGenerator::FirstGenerated.from_hash('name' => 'Bob Builder', 'age' => nil) }.to(
|
253
|
+
raise_error(TypeAssertionError,
|
254
|
+
"MyModule::FirstGenerated initializer had wrong type, entry 'age' expected an Integer value, got Undef")
|
255
|
+
)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|