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.

Files changed (218) hide show
  1. data/CONTRIBUTING.md +5 -5
  2. data/Gemfile +2 -2
  3. data/LICENSE +2 -2
  4. data/README.md +5 -0
  5. data/ext/project_data.yaml +2 -0
  6. data/lib/hiera_puppet.rb +6 -14
  7. data/lib/puppet/application/agent.rb +2 -3
  8. data/lib/puppet/data_providers/hiera_config.rb +2 -4
  9. data/lib/puppet/data_providers/hiera_interpolate.rb +12 -154
  10. data/lib/puppet/data_providers/json_data_provider_factory.rb +0 -7
  11. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -8
  12. data/lib/puppet/defaults.rb +70 -7
  13. data/lib/puppet/functions.rb +69 -0
  14. data/lib/puppet/functions/dig.rb +39 -0
  15. data/lib/puppet/functions/lest.rb +53 -0
  16. data/lib/puppet/functions/lookup.rb +40 -27
  17. data/lib/puppet/functions/new.rb +502 -0
  18. data/lib/puppet/functions/regsubst.rb +11 -10
  19. data/lib/puppet/functions/then.rb +74 -0
  20. data/lib/puppet/functions/type.rb +4 -4
  21. data/lib/puppet/functions/with.rb +1 -1
  22. data/lib/puppet/indirector/catalog/compiler.rb +2 -0
  23. data/lib/puppet/indirector/resource_type/parser.rb +5 -0
  24. data/lib/puppet/indirector/rest.rb +5 -1
  25. data/lib/puppet/loaders.rb +2 -0
  26. data/lib/puppet/metatype/manager.rb +19 -2
  27. data/lib/puppet/module_tool/applications/application.rb +1 -1
  28. data/lib/puppet/module_tool/skeleton/templates/generator/Gemfile +6 -2
  29. data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +19 -4
  30. data/lib/puppet/module_tool/skeleton/templates/generator/{tests → examples}/init.pp.erb +1 -1
  31. data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +0 -1
  32. data/lib/puppet/network/http/api/master/v3/environment.rb +6 -2
  33. data/lib/puppet/parser/ast/pops_bridge.rb +20 -3
  34. data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +24 -2
  35. data/lib/puppet/parser/e4_parser_adapter.rb +13 -12
  36. data/lib/puppet/parser/environment_compiler.rb +2 -2
  37. data/lib/puppet/parser/resource.rb +14 -5
  38. data/lib/puppet/parser/scope.rb +18 -15
  39. data/lib/puppet/plugins/data_providers/data_provider.rb +19 -8
  40. data/lib/puppet/pops.rb +6 -0
  41. data/lib/puppet/pops/adapters.rb +5 -1
  42. data/lib/puppet/pops/evaluator/access_operator.rb +52 -14
  43. data/lib/puppet/pops/evaluator/compare_operator.rb +34 -4
  44. data/lib/puppet/pops/evaluator/evaluator_impl.rb +75 -22
  45. data/lib/puppet/pops/evaluator/literal_evaluator.rb +7 -6
  46. data/lib/puppet/pops/evaluator/runtime3_converter.rb +13 -1
  47. data/lib/puppet/pops/evaluator/runtime3_support.rb +14 -4
  48. data/lib/puppet/pops/functions/dispatcher.rb +1 -1
  49. data/lib/puppet/pops/issues.rb +18 -2
  50. data/lib/puppet/pops/loader/base_loader.rb +48 -7
  51. data/lib/puppet/pops/loader/dependency_loader.rb +27 -2
  52. data/lib/puppet/pops/loader/loader.rb +12 -0
  53. data/lib/puppet/pops/loader/predefined_loader.rb +29 -0
  54. data/lib/puppet/pops/loader/runtime3_type_loader.rb +57 -0
  55. data/lib/puppet/pops/loader/static_loader.rb +92 -5
  56. data/lib/puppet/pops/loader/type_definition_instantiator.rb +25 -3
  57. data/lib/puppet/pops/loaders.rb +84 -14
  58. data/lib/puppet/pops/lookup/explainer.rb +38 -1
  59. data/lib/puppet/pops/lookup/interpolation.rb +115 -0
  60. data/lib/puppet/pops/lookup/sub_lookup.rb +86 -0
  61. data/lib/puppet/pops/model/ast_transformer.rb +8 -1
  62. data/lib/puppet/pops/model/factory.rb +31 -8
  63. data/lib/puppet/pops/model/model.rb +8 -0
  64. data/lib/puppet/pops/model/model_label_provider.rb +1 -0
  65. data/lib/puppet/pops/model/model_meta.rb +7 -1
  66. data/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
  67. data/lib/puppet/pops/parser/egrammar.ra +24 -7
  68. data/lib/puppet/pops/parser/eparser.rb +863 -798
  69. data/lib/puppet/pops/parser/evaluating_parser.rb +4 -0
  70. data/lib/puppet/pops/parser/locator.rb +8 -4
  71. data/lib/puppet/pops/pcore.rb +30 -0
  72. data/lib/puppet/pops/types/class_loader.rb +2 -4
  73. data/lib/puppet/pops/types/implementation_registry.rb +146 -0
  74. data/lib/puppet/pops/types/iterable.rb +4 -4
  75. data/lib/puppet/pops/types/p_object_type.rb +846 -0
  76. data/lib/puppet/pops/types/p_runtime_type.rb +102 -0
  77. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +164 -0
  78. data/lib/puppet/pops/types/p_sem_ver_type.rb +113 -0
  79. data/lib/puppet/pops/types/puppet_object.rb +21 -0
  80. data/lib/puppet/pops/types/ruby_generator.rb +258 -0
  81. data/lib/puppet/pops/types/string_converter.rb +922 -0
  82. data/lib/puppet/pops/types/type_calculator.rb +29 -5
  83. data/lib/puppet/pops/types/type_conversion_error.rb +15 -0
  84. data/lib/puppet/pops/types/type_factory.rb +49 -16
  85. data/lib/puppet/pops/types/type_formatter.rb +335 -112
  86. data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -29
  87. data/lib/puppet/pops/types/type_parser.rb +205 -197
  88. data/lib/puppet/pops/types/types.rb +481 -103
  89. data/lib/puppet/pops/validation.rb +1 -1
  90. data/lib/puppet/pops/validation/checker4_0.rb +66 -4
  91. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  92. data/lib/puppet/pops/visitor.rb +3 -1
  93. data/lib/puppet/property.rb +1 -1
  94. data/lib/puppet/provider/augeas/augeas.rb +1 -1
  95. data/lib/puppet/provider/package/pip.rb +64 -20
  96. data/lib/puppet/provider/package/rpm.rb +112 -0
  97. data/lib/puppet/provider/package/yum.rb +7 -68
  98. data/lib/puppet/provider/service/daemontools.rb +3 -3
  99. data/lib/puppet/provider/service/init.rb +4 -2
  100. data/lib/puppet/provider/service/runit.rb +3 -3
  101. data/lib/puppet/provider/service/smf.rb +6 -3
  102. data/lib/puppet/provider/service/systemd.rb +59 -73
  103. data/lib/puppet/reference/providers.rb +1 -2
  104. data/lib/puppet/resource.rb +54 -37
  105. data/lib/puppet/resource/catalog.rb +31 -29
  106. data/lib/puppet/resource/type_collection.rb +23 -8
  107. data/lib/puppet/settings.rb +4 -2
  108. data/lib/puppet/settings/base_setting.rb +9 -3
  109. data/lib/puppet/settings/symbolic_enum_setting.rb +17 -0
  110. data/lib/puppet/test/test_helper.rb +0 -1
  111. data/lib/puppet/type.rb +9 -3
  112. data/lib/puppet/type/exec.rb +17 -17
  113. data/lib/puppet/type/file.rb +12 -0
  114. data/lib/puppet/type/file/content.rb +6 -6
  115. data/lib/puppet/type/file/ensure.rb +4 -4
  116. data/lib/puppet/type/file/source.rb +4 -4
  117. data/lib/puppet/type/file/target.rb +2 -2
  118. data/lib/puppet/type/mount.rb +18 -1
  119. data/lib/puppet/type/package.rb +3 -3
  120. data/lib/puppet/type/schedule.rb +4 -4
  121. data/lib/puppet/type/service.rb +15 -0
  122. data/lib/puppet/type/sshkey.rb +5 -3
  123. data/lib/puppet/type/tidy.rb +3 -3
  124. data/lib/puppet/type/zone.rb +5 -5
  125. data/lib/puppet/util/feature.rb +1 -1
  126. data/lib/puppet/util/monkey_patches.rb +8 -0
  127. data/lib/puppet/util/network_device/cisco/device.rb +16 -6
  128. data/lib/puppet/util/network_device/cisco/interface.rb +5 -6
  129. data/lib/puppet/util/plist.rb +3 -3
  130. data/lib/puppet/version.rb +1 -1
  131. data/spec/fixtures/unit/application/environments/production/data/common.yaml +13 -0
  132. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +2 -1
  133. data/spec/fixtures/unit/data_providers/environments/production/modules/abc/manifests/init.pp +2 -1
  134. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/data/empty_key.json +1 -0
  135. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/hiera.yaml +5 -0
  136. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/manifests/init.pp +2 -0
  137. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_json/metadata.json +9 -0
  138. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/data/empty_key.yaml +1 -0
  139. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/hiera.yaml +5 -0
  140. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/manifests/init.pp +2 -0
  141. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_key_yaml/metadata.json +9 -0
  142. data/spec/fixtures/unit/functions/lookup/environments/production/modules/empty_yaml/data/empty.yaml +1 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/type/usee_type.rb +5 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +6 -0
  145. data/spec/fixtures/unit/provider/service/smf/svcs.out +4 -3
  146. data/spec/integration/module_tool/tar/mini_spec.rb +27 -27
  147. data/spec/integration/parser/catalog_spec.rb +14 -2
  148. data/spec/integration/parser/compiler_spec.rb +94 -3
  149. data/spec/integration/parser/resource_expressions_spec.rb +1 -1
  150. data/spec/integration/resource/type_collection_spec.rb +8 -0
  151. data/spec/lib/puppet_spec/compiler.rb +11 -4
  152. data/spec/shared_contexts/types_setup.rb +4 -0
  153. data/spec/unit/application/lookup_spec.rb +91 -9
  154. data/spec/unit/appmgmt_spec.rb +44 -35
  155. data/spec/unit/capability_spec.rb +33 -53
  156. data/spec/unit/data_providers/function_data_provider_spec.rb +19 -1
  157. data/spec/unit/data_providers/hiera_data_provider_spec.rb +1 -1
  158. data/spec/unit/defaults_spec.rb +18 -0
  159. data/spec/unit/functions/assert_type_spec.rb +1 -1
  160. data/spec/unit/functions/dig_spec.rb +58 -0
  161. data/spec/unit/functions/lest_spec.rb +34 -0
  162. data/spec/unit/functions/lookup_spec.rb +108 -2
  163. data/spec/unit/functions/new_spec.rb +543 -0
  164. data/spec/unit/functions/regsubst_spec.rb +8 -0
  165. data/spec/unit/functions/then_spec.rb +40 -0
  166. data/spec/unit/functions4_spec.rb +78 -10
  167. data/spec/unit/hiera_puppet_spec.rb +49 -8
  168. data/spec/unit/indirector/resource_type/parser_spec.rb +5 -0
  169. data/spec/unit/indirector/rest_spec.rb +12 -0
  170. data/spec/unit/network/http/api/master/v3/environment_spec.rb +60 -0
  171. data/spec/unit/node/environment_spec.rb +10 -0
  172. data/spec/unit/parser/compiler_spec.rb +20 -1
  173. data/spec/unit/parser/functions/create_resources_spec.rb +2 -2
  174. data/spec/unit/parser/functions/shared.rb +1 -1
  175. data/spec/unit/parser/resource_spec.rb +8 -1
  176. data/spec/unit/parser/scope_spec.rb +45 -0
  177. data/spec/unit/pops/evaluator/access_ops_spec.rb +14 -0
  178. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +13 -5
  179. data/spec/unit/pops/loaders/static_loader_spec.rb +92 -1
  180. data/spec/unit/{data_providers/hiera_interpolation_spec.rb → pops/lookup/interpolation_spec.rb} +7 -5
  181. data/spec/unit/pops/parser/lexer2_spec.rb +2 -9
  182. data/spec/unit/pops/parser/parse_application_spec.rb +3 -8
  183. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +19 -0
  184. data/spec/unit/pops/parser/parse_capabilities_spec.rb +3 -10
  185. data/spec/unit/pops/parser/parse_site_spec.rb +19 -10
  186. data/spec/unit/pops/parser/parser_rspec_helper.rb +0 -4
  187. data/spec/unit/pops/types/enumeration_spec.rb +13 -12
  188. data/spec/unit/pops/types/iterable_spec.rb +2 -2
  189. data/spec/unit/pops/types/p_object_type_spec.rb +1060 -0
  190. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +285 -0
  191. data/spec/unit/pops/types/recursion_guard_spec.rb +19 -17
  192. data/spec/unit/pops/types/ruby_generator_spec.rb +261 -0
  193. data/spec/unit/pops/types/string_converter_spec.rb +904 -0
  194. data/spec/unit/pops/types/type_calculator_spec.rb +430 -406
  195. data/spec/unit/pops/types/type_factory_spec.rb +119 -104
  196. data/spec/unit/pops/types/type_formatter_spec.rb +73 -6
  197. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +2 -2
  198. data/spec/unit/pops/types/type_parser_spec.rb +54 -15
  199. data/spec/unit/pops/types/types_spec.rb +113 -8
  200. data/spec/unit/pops/validator/validator_spec.rb +84 -10
  201. data/spec/unit/provider/package/pip3_spec.rb +9 -270
  202. data/spec/unit/provider/package/pip_spec.rb +85 -30
  203. data/spec/unit/provider/package/rpm_spec.rb +160 -3
  204. data/spec/unit/provider/package/yum_spec.rb +23 -134
  205. data/spec/unit/provider/service/smf_spec.rb +14 -2
  206. data/spec/unit/provider/service/systemd_spec.rb +33 -41
  207. data/spec/unit/resource/capability_finder_spec.rb +10 -2
  208. data/spec/unit/settings/file_setting_spec.rb +6 -0
  209. data/spec/unit/transaction/additional_resource_generator_spec.rb +80 -65
  210. data/spec/unit/type/mount_spec.rb +51 -10
  211. data/spec/unit/type/service_spec.rb +16 -0
  212. data/spec/unit/type_spec.rb +14 -0
  213. data/spec/unit/util/feature_spec.rb +1 -1
  214. data/spec/unit/util/monkey_patches_spec.rb +60 -0
  215. data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
  216. metadata +63 -11
  217. data/lib/puppet/pops/types/types_meta.rb +0 -0
  218. 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
- describe 'the Puppet::Pops::Types::RecursionGuard' do
5
- let(:guard) { Puppet::Pops::Types::RecursionGuard.new }
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
10
- expect(guard.add_this(x)).to eq(Puppet::Pops::Types::RecursionGuard::SELF_RECURSION_IN_THIS)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
16
- expect(guard.add_that(x)).to eq(Puppet::Pops::Types::RecursionGuard::SELF_RECURSION_IN_THAT)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
22
- expect(guard.add_that(x)).to eq(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
29
- expect(guard.add_that(y)).to eq(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
30
- expect(guard.add_this(x)).to eq(Puppet::Pops::Types::RecursionGuard::SELF_RECURSION_IN_THIS)
31
- expect(guard.add_that(y)).to eq(Puppet::Pops::Types::RecursionGuard::SELF_RECURSION_IN_BOTH)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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(Puppet::Pops::Types::RecursionGuard::NO_SELF_RECURSION)
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