puppet 4.7.1-universal-darwin → 4.8.0-universal-darwin

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 (276) hide show
  1. data/Gemfile +0 -3
  2. data/MAINTAINERS +76 -0
  3. data/README.md +0 -6
  4. data/Rakefile +2 -2
  5. data/lib/puppet/agent.rb +3 -3
  6. data/lib/puppet/application/apply.rb +1 -1
  7. data/lib/puppet/configurer.rb +2 -2
  8. data/lib/puppet/data_providers.rb +1 -0
  9. data/lib/puppet/data_providers/data_adapter.rb +1 -0
  10. data/lib/puppet/data_providers/data_function_support.rb +1 -0
  11. data/lib/puppet/data_providers/function_env_data_provider.rb +1 -0
  12. data/lib/puppet/data_providers/function_module_data_provider.rb +1 -0
  13. data/lib/puppet/data_providers/hiera_config.rb +1 -0
  14. data/lib/puppet/data_providers/hiera_env_data_provider.rb +1 -0
  15. data/lib/puppet/data_providers/hiera_interpolate.rb +1 -0
  16. data/lib/puppet/data_providers/hiera_module_data_provider.rb +1 -0
  17. data/lib/puppet/data_providers/hiera_support.rb +1 -2
  18. data/lib/puppet/data_providers/json_data_provider_factory.rb +2 -0
  19. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +2 -0
  20. data/lib/puppet/defaults.rb +20 -1
  21. data/lib/puppet/environments.rb +5 -2
  22. data/lib/puppet/face/catalog.rb +1 -1
  23. data/lib/puppet/face/epp.rb +57 -11
  24. data/lib/puppet/face/module/install.rb +6 -6
  25. data/lib/puppet/functions.rb +23 -24
  26. data/lib/puppet/functions/alert.rb +14 -0
  27. data/lib/puppet/functions/binary_file.rb +25 -0
  28. data/lib/puppet/functions/break.rb +22 -0
  29. data/lib/puppet/functions/contain.rb +33 -0
  30. data/lib/puppet/functions/crit.rb +14 -0
  31. data/lib/puppet/functions/debug.rb +14 -0
  32. data/lib/puppet/functions/emerg.rb +14 -0
  33. data/lib/puppet/functions/epp.rb +1 -1
  34. data/lib/puppet/functions/err.rb +14 -0
  35. data/lib/puppet/functions/find_file.rb +31 -0
  36. data/lib/puppet/functions/include.rb +21 -0
  37. data/lib/puppet/functions/info.rb +14 -0
  38. data/lib/puppet/functions/new.rb +1 -1
  39. data/lib/puppet/functions/next.rb +23 -0
  40. data/lib/puppet/functions/notice.rb +14 -0
  41. data/lib/puppet/functions/regsubst.rb +12 -16
  42. data/lib/puppet/functions/require.rb +37 -0
  43. data/lib/puppet/functions/return.rb +22 -0
  44. data/lib/puppet/functions/strftime.rb +35 -0
  45. data/lib/puppet/functions/warning.rb +14 -0
  46. data/lib/puppet/generate/models/type/type.rb +4 -0
  47. data/lib/puppet/generate/templates/type/pcore.erb +2 -1
  48. data/lib/puppet/indirector/face.rb +6 -1
  49. data/lib/puppet/network/http/error.rb +2 -2
  50. data/lib/puppet/network/http/handler.rb +2 -2
  51. data/lib/puppet/node/environment.rb +11 -0
  52. data/lib/puppet/parser/ast.rb +5 -0
  53. data/lib/puppet/parser/ast/pops_bridge.rb +17 -4
  54. data/lib/puppet/parser/compiler.rb +29 -1
  55. data/lib/puppet/parser/functions.rb +6 -0
  56. data/lib/puppet/parser/functions/assert_type.rb +1 -1
  57. data/lib/puppet/parser/functions/binary_file.rb +24 -0
  58. data/lib/puppet/parser/functions/break.rb +39 -0
  59. data/lib/puppet/parser/functions/contain.rb +7 -15
  60. data/lib/puppet/parser/functions/defined.rb +2 -2
  61. data/lib/puppet/parser/functions/dig.rb +1 -1
  62. data/lib/puppet/parser/functions/each.rb +1 -1
  63. data/lib/puppet/parser/functions/epp.rb +2 -2
  64. data/lib/puppet/parser/functions/filter.rb +1 -1
  65. data/lib/puppet/parser/functions/find_file.rb +28 -0
  66. data/lib/puppet/parser/functions/hiera.rb +4 -4
  67. data/lib/puppet/parser/functions/hiera_array.rb +1 -1
  68. data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
  69. data/lib/puppet/parser/functions/hiera_include.rb +1 -1
  70. data/lib/puppet/parser/functions/include.rb +4 -8
  71. data/lib/puppet/parser/functions/inline_epp.rb +1 -1
  72. data/lib/puppet/parser/functions/lest.rb +1 -1
  73. data/lib/puppet/parser/functions/lookup.rb +4 -2
  74. data/lib/puppet/parser/functions/map.rb +1 -1
  75. data/lib/puppet/parser/functions/match.rb +1 -1
  76. data/lib/puppet/parser/functions/new.rb +414 -18
  77. data/lib/puppet/parser/functions/next.rb +38 -0
  78. data/lib/puppet/parser/functions/reduce.rb +1 -1
  79. data/lib/puppet/parser/functions/regsubst.rb +4 -2
  80. data/lib/puppet/parser/functions/require.rb +4 -27
  81. data/lib/puppet/parser/functions/return.rb +71 -0
  82. data/lib/puppet/parser/functions/reverse_each.rb +1 -1
  83. data/lib/puppet/parser/functions/scanf.rb +13 -8
  84. data/lib/puppet/parser/functions/slice.rb +1 -1
  85. data/lib/puppet/parser/functions/split.rb +1 -1
  86. data/lib/puppet/parser/functions/step.rb +1 -1
  87. data/lib/puppet/parser/functions/strftime.rb +185 -0
  88. data/lib/puppet/parser/functions/then.rb +1 -1
  89. data/lib/puppet/parser/functions/type.rb +1 -1
  90. data/lib/puppet/parser/functions/with.rb +3 -3
  91. data/lib/puppet/parser/resource.rb +8 -5
  92. data/lib/puppet/parser/scope.rb +1 -1
  93. data/lib/puppet/plugins/configuration.rb +8 -0
  94. data/lib/puppet/plugins/data_providers.rb +1 -0
  95. data/lib/puppet/plugins/data_providers/data_provider.rb +7 -28
  96. data/lib/puppet/plugins/data_providers/registry.rb +1 -0
  97. data/lib/puppet/pops.rb +4 -0
  98. data/lib/puppet/pops/evaluator/access_operator.rb +36 -5
  99. data/lib/puppet/pops/evaluator/closure.rb +81 -12
  100. data/lib/puppet/pops/evaluator/compare_operator.rb +24 -1
  101. data/lib/puppet/pops/evaluator/evaluator_impl.rb +29 -5
  102. data/lib/puppet/pops/evaluator/json_strict_literal_evaluator.rb +1 -1
  103. data/lib/puppet/pops/evaluator/runtime3_converter.rb +53 -62
  104. data/lib/puppet/pops/evaluator/runtime3_support.rb +15 -6
  105. data/lib/puppet/pops/functions/dispatch.rb +9 -2
  106. data/lib/puppet/pops/functions/dispatcher.rb +3 -1
  107. data/lib/puppet/pops/functions/function.rb +19 -2
  108. data/lib/puppet/pops/issues.rb +9 -0
  109. data/lib/puppet/pops/label_provider.rb +2 -2
  110. data/lib/puppet/pops/loader/loader.rb +17 -0
  111. data/lib/puppet/pops/loader/static_loader.rb +0 -41
  112. data/lib/puppet/pops/lookup.rb +12 -0
  113. data/lib/puppet/pops/lookup/context.rb +86 -0
  114. data/lib/puppet/pops/lookup/explainer.rb +46 -6
  115. data/lib/puppet/pops/lookup/invocation.rb +19 -0
  116. data/lib/puppet/pops/lookup/sub_lookup.rb +1 -1
  117. data/lib/puppet/pops/model/factory.rb +20 -8
  118. data/lib/puppet/pops/model/model_label_provider.rb +3 -0
  119. data/lib/puppet/pops/model/model_meta.rb +2 -0
  120. data/lib/puppet/pops/model/model_tree_dumper.rb +14 -0
  121. data/lib/puppet/pops/parser/egrammar.ra +11 -6
  122. data/lib/puppet/pops/parser/eparser.rb +1112 -1086
  123. data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
  124. data/lib/puppet/pops/pcore.rb +1 -0
  125. data/lib/puppet/pops/puppet_stack.rb +3 -3
  126. data/lib/puppet/pops/resource/param.rb +5 -1
  127. data/lib/puppet/pops/resource/resource_type_impl.rb +8 -4
  128. data/lib/puppet/pops/resource/resource_type_set.pcore +1 -0
  129. data/lib/puppet/pops/serialization/abstract_reader.rb +19 -2
  130. data/lib/puppet/pops/serialization/abstract_writer.rb +16 -3
  131. data/lib/puppet/pops/serialization/deserializer.rb +5 -1
  132. data/lib/puppet/pops/serialization/extension.rb +2 -0
  133. data/lib/puppet/pops/serialization/json.rb +76 -26
  134. data/lib/puppet/pops/serialization/serializer.rb +5 -1
  135. data/lib/puppet/pops/serialization/time_factory.rb +2 -1
  136. data/lib/puppet/pops/time/timespan.rb +718 -0
  137. data/lib/puppet/pops/time/timestamp.rb +148 -0
  138. data/lib/puppet/pops/types/p_binary_type.rb +220 -0
  139. data/lib/puppet/pops/types/p_object_type.rb +12 -6
  140. data/lib/puppet/pops/types/p_sensitive_type.rb +5 -1
  141. data/lib/puppet/pops/types/p_timespan_type.rb +141 -0
  142. data/lib/puppet/pops/types/p_timestamp_type.rb +69 -0
  143. data/lib/puppet/pops/types/string_converter.rb +62 -0
  144. data/lib/puppet/pops/types/type_asserter.rb +1 -1
  145. data/lib/puppet/pops/types/type_calculator.rb +17 -3
  146. data/lib/puppet/pops/types/type_factory.rb +35 -1
  147. data/lib/puppet/pops/types/type_formatter.rb +64 -11
  148. data/lib/puppet/pops/types/type_mismatch_describer.rb +110 -61
  149. data/lib/puppet/pops/types/type_parser.rb +18 -4
  150. data/lib/puppet/pops/types/types.rb +98 -63
  151. data/lib/puppet/pops/validation.rb +9 -1
  152. data/lib/puppet/pops/validation/checker4_0.rb +7 -0
  153. data/lib/puppet/property.rb +1 -1
  154. data/lib/puppet/provider.rb +3 -6
  155. data/lib/puppet/provider/mcx/mcxcontent.rb +1 -1
  156. data/lib/puppet/provider/mount/parsed.rb +18 -4
  157. data/lib/puppet/provider/nameservice/directoryservice.rb +15 -7
  158. data/lib/puppet/provider/package/gem.rb +6 -1
  159. data/lib/puppet/provider/package/pip.rb +0 -1
  160. data/lib/puppet/provider/package/pkg.rb +5 -1
  161. data/lib/puppet/provider/package/pkgng.rb +1 -1
  162. data/lib/puppet/provider/package/yum.rb +10 -0
  163. data/lib/puppet/provider/service/launchd.rb +1 -0
  164. data/lib/puppet/provider/user/directoryservice.rb +6 -6
  165. data/lib/puppet/provider/yumrepo/inifile.rb +1 -1
  166. data/lib/puppet/provider/zpool/zpool.rb +1 -1
  167. data/lib/puppet/resource.rb +54 -12
  168. data/lib/puppet/resource/capability_finder.rb +15 -9
  169. data/lib/puppet/resource/catalog.rb +25 -6
  170. data/lib/puppet/resource/type.rb +3 -1
  171. data/lib/puppet/settings.rb +1 -1
  172. data/lib/puppet/settings/environment_conf.rb +12 -4
  173. data/lib/puppet/syntax_checkers/base64.rb +41 -0
  174. data/lib/puppet/syntax_checkers/json.rb +0 -2
  175. data/lib/puppet/transaction.rb +6 -0
  176. data/lib/puppet/transaction/additional_resource_generator.rb +5 -0
  177. data/lib/puppet/transaction/report.rb +7 -2
  178. data/lib/puppet/type.rb +2 -1
  179. data/lib/puppet/type/file/checksum.rb +1 -0
  180. data/lib/puppet/type/file/content.rb +4 -4
  181. data/lib/puppet/type/mount.rb +44 -0
  182. data/lib/puppet/type/ssh_authorized_key.rb +1 -1
  183. data/lib/puppet/type/tidy.rb +3 -0
  184. data/lib/puppet/type/user.rb +12 -6
  185. data/lib/puppet/util/log.rb +25 -0
  186. data/lib/puppet/util/plist.rb +8 -3
  187. data/lib/puppet/version.rb +1 -1
  188. data/lib/puppet_x.rb +7 -1
  189. data/spec/integration/application/apply_spec.rb +118 -0
  190. data/spec/integration/parser/compiler_spec.rb +28 -0
  191. data/spec/integration/parser/pcore_resource_spec.rb +40 -3
  192. data/spec/integration/provider/mount_spec.rb +2 -1
  193. data/spec/integration/util/windows/principal_spec.rb +2 -2
  194. data/spec/integration/util/windows/registry_spec.rb +4 -4
  195. data/spec/lib/puppet_spec/compiler.rb +5 -1
  196. data/spec/lib/puppet_spec/unindent.rb +5 -0
  197. data/spec/shared_contexts/types_setup.rb +6 -0
  198. data/spec/shared_examples/rhel_package_provider.rb +16 -0
  199. data/spec/spec_helper.rb +1 -0
  200. data/spec/unit/agent_spec.rb +11 -0
  201. data/spec/unit/application/lookup_spec.rb +94 -3
  202. data/spec/unit/capability_spec.rb +22 -0
  203. data/spec/unit/configurer_spec.rb +8 -0
  204. data/spec/unit/face/epp_face_spec.rb +22 -3
  205. data/spec/unit/functions/assert_type_spec.rb +3 -3
  206. data/spec/unit/functions/binary_file_spec.rb +46 -0
  207. data/spec/unit/functions/break_spec.rb +89 -0
  208. data/spec/unit/{parser/functions → functions}/contain_spec.rb +68 -3
  209. data/spec/unit/functions/find_file_spec.rb +69 -0
  210. data/spec/unit/functions/include_spec.rb +175 -0
  211. data/spec/unit/functions/logging_spec.rb +54 -0
  212. data/spec/unit/functions/lookup_spec.rb +3 -3
  213. data/spec/unit/functions/new_spec.rb +105 -5
  214. data/spec/unit/functions/next_spec.rb +93 -0
  215. data/spec/unit/functions/require_spec.rb +83 -0
  216. data/spec/unit/functions/return_spec.rb +105 -0
  217. data/spec/unit/{parser/functions → functions}/shared.rb +14 -11
  218. data/spec/unit/functions/strftime_spec.rb +152 -0
  219. data/spec/unit/functions4_spec.rb +22 -0
  220. data/spec/unit/indirector/face_spec.rb +10 -2
  221. data/spec/unit/network/http/error_spec.rb +1 -2
  222. data/spec/unit/network/http/handler_spec.rb +6 -5
  223. data/spec/unit/parser/functions/hiera_array_spec.rb +1 -1
  224. data/spec/unit/parser/functions/hiera_hash_spec.rb +1 -1
  225. data/spec/unit/parser/functions/hiera_include_spec.rb +1 -1
  226. data/spec/unit/parser/functions/hiera_spec.rb +1 -1
  227. data/spec/unit/parser/functions/lookup_spec.rb +1 -1
  228. data/spec/unit/parser/functions/regsubst_spec.rb +1 -1
  229. data/spec/unit/parser/functions/split_spec.rb +1 -1
  230. data/spec/unit/pops/evaluator/access_ops_spec.rb +81 -1
  231. data/spec/unit/pops/evaluator/arithmetic_ops_spec.rb +170 -0
  232. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +29 -4
  233. data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +112 -4
  234. data/spec/unit/pops/loaders/dependency_loader_spec.rb +12 -0
  235. data/spec/unit/pops/loaders/static_loader_spec.rb +0 -26
  236. data/spec/unit/pops/lookup/context_spec.rb +149 -0
  237. data/spec/unit/pops/parser/parse_functions_spec.rb +19 -0
  238. data/spec/unit/pops/parser/parse_lambda_spec.rb +19 -0
  239. data/spec/unit/pops/puppet_stack_spec.rb +1 -1
  240. data/spec/unit/pops/resource/resource_type_impl_spec.rb +74 -0
  241. data/spec/unit/pops/serialization/packer_spec.rb +34 -14
  242. data/spec/unit/pops/serialization/serialization_spec.rb +67 -5
  243. data/spec/unit/pops/time/timespan_spec.rb +121 -0
  244. data/spec/unit/pops/types/p_binary_type_spec.rb +243 -0
  245. data/spec/unit/pops/types/p_object_type_spec.rb +7 -7
  246. data/spec/unit/pops/types/p_sensitive_type_spec.rb +1 -1
  247. data/spec/unit/pops/types/p_timespan_type_spec.rb +273 -0
  248. data/spec/unit/pops/types/p_timestamp_type_spec.rb +311 -0
  249. data/spec/unit/pops/types/p_type_set_type_spec.rb +13 -13
  250. data/spec/unit/pops/types/ruby_generator_spec.rb +12 -12
  251. data/spec/unit/pops/types/string_converter_spec.rb +89 -0
  252. data/spec/unit/pops/types/type_asserter_spec.rb +3 -3
  253. data/spec/unit/pops/types/type_calculator_spec.rb +113 -5
  254. data/spec/unit/pops/types/type_formatter_spec.rb +40 -0
  255. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +49 -38
  256. data/spec/unit/pops/types/type_parser_spec.rb +87 -4
  257. data/spec/unit/pops/types/types_spec.rb +1 -1
  258. data/spec/unit/pops/validator/validator_spec.rb +23 -0
  259. data/spec/unit/provider/mount/parsed_spec.rb +47 -29
  260. data/spec/unit/provider/package/pkg_spec.rb +109 -99
  261. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +1 -0
  262. data/spec/unit/provider/user/aix_spec.rb +1 -1
  263. data/spec/unit/provider/user/directoryservice_spec.rb +101 -30
  264. data/spec/unit/resource/capability_finder_spec.rb +29 -7
  265. data/spec/unit/resource/catalog_spec.rb +127 -0
  266. data/spec/unit/ssl/certificate_request_spec.rb +1 -1
  267. data/spec/unit/transaction/additional_resource_generator_spec.rb +30 -0
  268. data/spec/unit/transaction/persistence_spec.rb +1 -6
  269. data/spec/unit/transaction/report_spec.rb +23 -0
  270. data/spec/unit/transaction_spec.rb +38 -0
  271. data/spec/unit/type/mount_spec.rb +5 -0
  272. data/spec/unit/util/plist_spec.rb +14 -2
  273. metadata +71 -12
  274. data/spec/integration/parser/functions/require_spec.rb +0 -43
  275. data/spec/unit/parser/functions/include_spec.rb +0 -55
  276. data/spec/unit/parser/functions/require_spec.rb +0 -68
@@ -1,5 +1,6 @@
1
1
  #! /usr/bin/env ruby
2
2
  require 'spec_helper'
3
+ require 'puppet_spec/compiler'
3
4
 
4
5
  require 'puppet/pops'
5
6
  require 'puppet/pops/evaluator/evaluator_impl'
@@ -73,5 +74,174 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
73
74
  expect(evaluate(literal('012.3') + literal('010'))).to eq(20.3)
74
75
  end
75
76
  end
77
+
78
+ context 'on timespans' do
79
+ include PuppetSpec::Compiler
80
+
81
+ it 'Timespan + Timespan = Timespan' do
82
+ code = 'notice(assert_type(Timespan, Timespan({days => 3}) + Timespan({hours => 12})))'
83
+ expect(eval_and_collect_notices(code)).to eql(['3-12:00:00.0'])
84
+ end
85
+
86
+ it 'Timespan - Timespan = Timespan' do
87
+ code = 'notice(assert_type(Timespan, Timespan({days => 3}) - Timespan({hours => 12})))'
88
+ expect(eval_and_collect_notices(code)).to eql(['2-12:00:00.0'])
89
+ end
90
+
91
+ it 'Timespan + -Timespan = Timespan' do
92
+ code = 'notice(assert_type(Timespan, Timespan({days => 3}) + -Timespan({hours => 12})))'
93
+ expect(eval_and_collect_notices(code)).to eql(['2-12:00:00.0'])
94
+ end
95
+
96
+ it 'Timespan - -Timespan = Timespan' do
97
+ code = 'notice(assert_type(Timespan, Timespan({days => 3}) - -Timespan({hours => 12})))'
98
+ expect(eval_and_collect_notices(code)).to eql(['3-12:00:00.0'])
99
+ end
100
+
101
+ it 'Timespan / Timespan = Float' do
102
+ code = "notice(assert_type(Float, Timespan({days => 3}) / Timespan('0-12:00:00')))"
103
+ expect(eval_and_collect_notices(code)).to eql(['6.0'])
104
+ end
105
+
106
+ it 'Timespan * Timespan is an error' do
107
+ code = 'notice(Timespan({days => 3}) * Timespan({hours => 12}))'
108
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /A Timestamp cannot be multiplied by a Timespan/)
109
+ end
110
+
111
+ it 'Timespan + Numeric = Timespan (numeric treated as seconds)' do
112
+ code = 'notice(assert_type(Timespan, Timespan({days => 3}) + 7300.0))'
113
+ expect(eval_and_collect_notices(code)).to eql(['3-02:01:40.0'])
114
+ end
115
+
116
+ it 'Timespan - Numeric = Timespan (numeric treated as seconds)' do
117
+ code = "notice(assert_type(Timespan, Timespan({days => 3}) - 7300.123))"
118
+ expect(eval_and_collect_notices(code)).to eql(['2-21:58:19.877'])
119
+ end
120
+
121
+ it 'Timespan * Numeric = Timespan (numeric treated as seconds)' do
122
+ code = "notice(strftime(assert_type(Timespan, Timespan({days => 3}) * 2), '%D'))"
123
+ expect(eval_and_collect_notices(code)).to eql(['6'])
124
+ end
125
+
126
+ it 'Numeric + Timespan = Timespan (numeric treated as seconds)' do
127
+ code = 'notice(assert_type(Timespan, 7300.0 + Timespan({days => 3})))'
128
+ expect(eval_and_collect_notices(code)).to eql(['3-02:01:40.0'])
129
+ end
130
+
131
+ it 'Numeric - Timespan = Timespan (numeric treated as seconds)' do
132
+ code = "notice(strftime(assert_type(Timespan, 300000 - Timespan({days => 3})), '%H:%M'))"
133
+ expect(eval_and_collect_notices(code)).to eql(['11:20'])
134
+ end
135
+
136
+ it 'Numeric * Timespan = Timespan (numeric treated as seconds)' do
137
+ code = "notice(strftime(assert_type(Timespan, 2 * Timespan({days => 3})), '%D'))"
138
+ expect(eval_and_collect_notices(code)).to eql(['6'])
139
+ end
140
+
141
+ it 'Timespan + Timestamp = Timestamp' do
142
+ code = "notice(assert_type(Timestamp, Timespan({days => 3}) + Timestamp('2016-08-27T16:44:49.999 UTC')))"
143
+ expect(eval_and_collect_notices(code)).to eql(['2016-08-30T16:44:49.999 UTC'])
144
+ end
145
+
146
+ it 'Timespan - Timestamp is an error' do
147
+ code = 'notice(Timespan({days => 3}) - Timestamp())'
148
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /A Timestamp cannot be subtracted from a Timespan/)
149
+ end
150
+
151
+ it 'Timespan * Timestamp is an error' do
152
+ code = 'notice(Timespan({days => 3}) * Timestamp())'
153
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /A Timestamp cannot be multiplied by a Timestamp/)
154
+ end
155
+
156
+ it 'Timespan / Timestamp is an error' do
157
+ code = 'notice(Timespan({days => 3}) / Timestamp())'
158
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /A Timespan cannot be divided by a Timestamp/)
159
+ end
160
+ end
161
+
162
+
163
+ context 'on timestamps' do
164
+ include PuppetSpec::Compiler
165
+
166
+ it 'Timestamp + Timestamp is an error' do
167
+ code = 'notice(Timestamp() + Timestamp())'
168
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /A Timestamp cannot be added to a Timestamp/)
169
+ end
170
+
171
+ it 'Timestamp + Timespan = Timestamp' do
172
+ code = "notice(assert_type(Timestamp, Timestamp('2016-10-10') + Timespan('0-12:00:00')))"
173
+ expect(eval_and_collect_notices(code)).to eql(['2016-10-10T12:00:00.000 UTC'])
174
+ end
175
+
176
+ it 'Timestamp + Numeric = Timestamp' do
177
+ code = "notice(assert_type(Timestamp, Timestamp('2016-10-10T12:00:00.000') + 3600.123))"
178
+ expect(eval_and_collect_notices(code)).to eql(['2016-10-10T13:00:00.123 UTC'])
179
+ end
180
+
181
+ it 'Numeric + Timestamp = Timestamp' do
182
+ code = "notice(assert_type(Timestamp, 3600.123 + Timestamp('2016-10-10T12:00:00.000')))"
183
+ expect(eval_and_collect_notices(code)).to eql(['2016-10-10T13:00:00.123 UTC'])
184
+ end
185
+
186
+ it 'Timestamp - Timestamp = Timespan' do
187
+ code = "notice(assert_type(Timespan, Timestamp('2016-10-10') - Timestamp('2015-10-10')))"
188
+ expect(eval_and_collect_notices(code)).to eql(['366-00:00:00.0'])
189
+ end
190
+
191
+ it 'Timestamp - Timespan = Timestamp' do
192
+ code = "notice(assert_type(Timestamp, Timestamp('2016-10-10') - Timespan('0-12:00:00')))"
193
+ expect(eval_and_collect_notices(code)).to eql(['2016-10-09T12:00:00.000 UTC'])
194
+ end
195
+
196
+ it 'Timestamp - Numeric = Timestamp' do
197
+ code = "notice(assert_type(Timestamp, Timestamp('2016-10-10') - 3600.123))"
198
+ expect(eval_and_collect_notices(code)).to eql(['2016-10-09T22:59:59.877 UTC'])
199
+ end
200
+
201
+ it 'Numeric - Timestamp = Timestamp' do
202
+ code = "notice(assert_type(Timestamp, 123 - Timestamp('2016-10-10')))"
203
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '-' is not applicable.*when right side is a Timestamp/)
204
+ end
205
+
206
+ it 'Timestamp / Timestamp is an error' do
207
+ code = "notice(Timestamp('2016-10-10') / Timestamp())"
208
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\/' is not applicable to a Timestamp/)
209
+ end
210
+
211
+ it 'Timestamp / Timespan is an error' do
212
+ code = "notice(Timestamp('2016-10-10') / Timespan('0-12:00:00'))"
213
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\/' is not applicable to a Timestamp/)
214
+ end
215
+
216
+ it 'Timestamp / Numeric is an error' do
217
+ code = "notice(Timestamp('2016-10-10') / 3600.123)"
218
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\/' is not applicable to a Timestamp/)
219
+ end
220
+
221
+ it 'Numeric / Timestamp is an error' do
222
+ code = "notice(3600.123 / Timestamp('2016-10-10'))"
223
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\/' is not applicable.*when right side is a Timestamp/)
224
+ end
225
+
226
+ it 'Timestamp * Timestamp is an error' do
227
+ code = "notice(Timestamp('2016-10-10') * Timestamp())"
228
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\*' is not applicable to a Timestamp/)
229
+ end
230
+
231
+ it 'Timestamp * Timespan is an error' do
232
+ code = "notice(Timestamp('2016-10-10') * Timespan('0-12:00:00'))"
233
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\*' is not applicable to a Timestamp/)
234
+ end
235
+
236
+ it 'Timestamp * Numeric is an error' do
237
+ code = "notice(Timestamp('2016-10-10') * 3600.123)"
238
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\*' is not applicable to a Timestamp/)
239
+ end
240
+
241
+ it 'Numeric * Timestamp is an error' do
242
+ code = "notice(3600.123 * Timestamp('2016-10-10'))"
243
+ expect { eval_and_collect_notices(code) }.to raise_error(Puppet::Error, /Operator '\*' is not applicable.*when right side is a Timestamp/)
244
+ end
245
+ end
76
246
  end
77
247
  end
@@ -746,8 +746,9 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
746
746
  "Array[Integer,1,2,3]" => 'Array-Type[] accepts 1 to 3 arguments. Got 4',
747
747
  "Array[Integer,String]" => "A Type's size constraint arguments must be a single Integer type, or 1-2 integers (or default). Got a String-Type",
748
748
  "Hash[Integer,String, 1,2,3]" => 'Hash-Type[] accepts 2 to 4 arguments. Got 5',
749
- "'abc'[x]" => "The value 'x' cannot be converted to Numeric",
750
- "'abc'[1.0]" => "A String[] cannot use Float where Integer is expected",
749
+ "'abc'[x]" => "A substring operation does not accept a String as a character index. Expected an Integer",
750
+ "'abc'[1.0]" => "A substring operation does not accept a Float as a character index. Expected an Integer",
751
+ "'abc'[1, x]" => "A substring operation does not accept a String as a character index. Expected an Integer",
751
752
  "'abc'[1,2,3]" => "String supports [] with one or two arguments. Got 3",
752
753
  "NotUndef[0]" => 'NotUndef-Type[] argument must be a Type or a String. Got Fixnum',
753
754
  "NotUndef[a,b]" => 'NotUndef-Type[] accepts 0 to 1 arguments. Got 2',
@@ -1040,6 +1041,12 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1040
1041
  expect{parser.evaluate_string(scope, "assert_no_undef({1 => undef})")}.to_not raise_error()
1041
1042
  end
1042
1043
 
1044
+ it 'a lambda return value is checked using the return type' do
1045
+ expect(parser.evaluate_string(scope, "[1,2].map |Integer $x| >> Integer { $x }")).to eql([1,2])
1046
+ expect { parser.evaluate_string(scope, "[1,2].map |Integer $x| >> String { $x }") }.to raise_error(
1047
+ /value returned from lambda has wrong type, expects a String value, got Integer/)
1048
+ end
1049
+
1043
1050
  context 'using the 3x function api' do
1044
1051
  it 'can call a 3x function' do
1045
1052
  Puppet::Parser::Functions.newfunction("bazinga", :type => :rvalue) { |args| args[0] }
@@ -1274,7 +1281,7 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1274
1281
  expect(parser.evaluate_string(scope, src)).to eq("Tex\tt\\n")
1275
1282
  end
1276
1283
 
1277
- it "parses syntax checked specification" do
1284
+ it "parses json syntax checked specification" do
1278
1285
  src = <<-CODE
1279
1286
  @(END:json)
1280
1287
  ["foo", "bar"]
@@ -1283,7 +1290,16 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1283
1290
  expect(parser.evaluate_string(scope, src)).to eq('["foo", "bar"]')
1284
1291
  end
1285
1292
 
1286
- it "parses syntax checked specification with error and reports it" do
1293
+ it "parses base64 syntax checked specification" do
1294
+ src = <<-CODE
1295
+ @(END:base64)
1296
+ dGhlIHF1aWNrIHJlZCBmb3g=
1297
+ |- END
1298
+ CODE
1299
+ expect(parser.evaluate_string(scope, src)).to eq('dGhlIHF1aWNrIHJlZCBmb3g=')
1300
+ end
1301
+
1302
+ it "parses json syntax checked specification with error and reports it" do
1287
1303
  src = <<-CODE
1288
1304
  @(END:json)
1289
1305
  ['foo', "bar"]
@@ -1292,6 +1308,15 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1292
1308
  expect { parser.evaluate_string(scope, src)}.to raise_error(/Cannot parse invalid JSON string/)
1293
1309
  end
1294
1310
 
1311
+ it "parses base syntax checked specification with error and reports it" do
1312
+ src = <<-CODE
1313
+ @(END:base64)
1314
+ dGhlIHF1aWNrIHJlZCBmb3g
1315
+ |- END
1316
+ CODE
1317
+ expect { parser.evaluate_string(scope, src)}.to raise_error(/Cannot parse invalid Base64 string/)
1318
+ end
1319
+
1295
1320
  it "parses interpolated heredoc expression" do
1296
1321
  src = <<-CODE
1297
1322
  $pname = 'Fjodor'
@@ -5,21 +5,129 @@ require 'puppet/pops'
5
5
  require 'puppet/pops/types/type_factory'
6
6
 
7
7
  describe 'when converting to 3.x' do
8
+ let(:converter) { Puppet::Pops::Evaluator::Runtime3Converter.instance }
9
+
8
10
  it "converts a resource type starting with Class without confusing it with exact match on 'class'" do
9
11
  t = Puppet::Pops::Types::TypeFactory.resource('classroom', 'kermit')
10
- converted = Puppet::Pops::Evaluator::Runtime3Converter.instance.catalog_type_to_split_type_title(t)
12
+ converted = converter.catalog_type_to_split_type_title(t)
11
13
  expect(converted).to eql(['classroom', 'kermit'])
12
14
  end
13
15
 
14
16
  it "converts a resource type of exactly 'Class'" do
15
17
  t = Puppet::Pops::Types::TypeFactory.resource('class', 'kermit')
16
- converted = Puppet::Pops::Evaluator::Runtime3Converter.instance.catalog_type_to_split_type_title(t)
18
+ converted = converter.catalog_type_to_split_type_title(t)
17
19
  expect(converted).to eql(['class', 'kermit'])
18
20
  end
19
21
 
20
22
  it "errors on attempts to convert an 'Iterator'" do
21
23
  expect {
22
- Puppet::Pops::Evaluator::Runtime3Converter.convert(Puppet::Pops::Types::Iterable.on((1..3)), {}, nil)
24
+ converter.convert(Puppet::Pops::Types::Iterable.on((1..3)), {}, nil)
23
25
  }.to raise_error(Puppet::Error, /Use of an Iterator is not supported here/)
24
26
  end
25
- end
27
+
28
+ it 'does not convert a SemVer instance to string' do
29
+ v = Semantic::Version.parse('1.0.0')
30
+ expect(converter.convert(v, {}, nil)).to equal(v)
31
+ end
32
+
33
+ it 'converts the symbol :undef to the undef value' do
34
+ v = Semantic::Version.parse('1.0.0')
35
+ expect(converter.convert(:undef, {}, 'undef value')).to eql('undef value')
36
+ end
37
+
38
+ it 'converts the nil to the undef value' do
39
+ v = Semantic::Version.parse('1.0.0')
40
+ expect(converter.convert(nil, {}, 'undef value')).to eql('undef value')
41
+ end
42
+
43
+ it 'does not convert a symbol nested in an array' do
44
+ v = Semantic::Version.parse('1.0.0')
45
+ expect(converter.convert({'foo' => :undef}, {}, 'undef value')).to eql({'foo' => :undef})
46
+ end
47
+
48
+ it 'converts nil to :undef when nested in an array' do
49
+ v = Semantic::Version.parse('1.0.0')
50
+ expect(converter.convert({'foo' => nil}, {}, 'undef value')).to eql({'foo' => :undef})
51
+ end
52
+
53
+ it 'does not convert a Regex instance to string' do
54
+ v = /^[A-Z]$/
55
+ expect(converter.convert(v, {}, nil)).to equal(v)
56
+ end
57
+
58
+ it 'does not convert a Version instance to string' do
59
+ v = Semantic::Version.parse('1.0.0')
60
+ expect(converter.convert(v, {}, nil)).to equal(v)
61
+ end
62
+
63
+ it 'does not convert a VersionRange instance to string' do
64
+ v = Semantic::VersionRange.parse('>=1.0.0')
65
+ expect(converter.convert(v, {}, nil)).to equal(v)
66
+ end
67
+
68
+ it 'does not convert a Timespan instance to string' do
69
+ v = Puppet::Pops::Time::Timespan.new(1234)
70
+ expect(converter.convert(v, {}, nil)).to equal(v)
71
+ end
72
+
73
+ it 'does not convert a Timestamp instance to string' do
74
+ v = Puppet::Pops::Time::Timestamp.now
75
+ expect(converter.convert(v, {}, nil)).to equal(v)
76
+ end
77
+
78
+ it 'does not convert a Sensitive instance to string' do
79
+ v = Puppet::Pops::Types::PSensitiveType::Sensitive.new("don't reveal this")
80
+ expect(converter.convert(v, {}, nil)).to equal(v)
81
+ end
82
+
83
+ it 'does not convert a Binary instance to string' do
84
+ v = Puppet::Pops::Types::PBinaryType::Binary.from_base64('w5ZzdGVuIG1lZCByw7ZzdGVuCg==')
85
+ expect(converter.convert(v, {}, nil)).to equal(v)
86
+ end
87
+
88
+ context 'the Runtime3FunctionArgumentConverter' do
89
+ let(:converter) { Puppet::Pops::Evaluator::Runtime3FunctionArgumentConverter.instance }
90
+
91
+ it 'converts a Regex instance to string' do
92
+ c = converter.convert(/^[A-Z]$/, {}, nil)
93
+ expect(c).to be_a(String)
94
+ expect(c).to eql('/^[A-Z]$/')
95
+ end
96
+
97
+ it 'converts a Version instance to string' do
98
+ c = converter.convert(Semantic::Version.parse('1.0.0'), {}, nil)
99
+ expect(c).to be_a(String)
100
+ expect(c).to eql('1.0.0')
101
+ end
102
+
103
+ it 'converts a VersionRange instance to string' do
104
+ c = converter.convert(Semantic::VersionRange.parse('>=1.0.0'), {}, nil)
105
+ expect(c).to be_a(String)
106
+ expect(c).to eql('>=1.0.0')
107
+ end
108
+
109
+ it 'converts a Timespan instance to string' do
110
+ c = converter.convert(Puppet::Pops::Time::Timespan.new(1234), {}, nil)
111
+ expect(c).to be_a(String)
112
+ expect(c).to eql('0-00:00:00.1234')
113
+ end
114
+
115
+ it 'converts a Timestamp instance to string' do
116
+ c = converter.convert(Puppet::Pops::Time::Timestamp.parse('2016-09-15T12:24:47.193 UTC'), {}, nil)
117
+ expect(c).to be_a(String)
118
+ expect(c).to eql('2016-09-15T12:24:47.193 UTC')
119
+ end
120
+
121
+ it 'converts a Binary instance to string' do
122
+ b64 = 'w5ZzdGVuIG1lZCByw7ZzdGVuCg=='
123
+ c = converter.convert(Puppet::Pops::Types::PBinaryType::Binary.from_base64(b64), {}, nil)
124
+ expect(c).to be_a(String)
125
+ expect(c).to eql(b64)
126
+ end
127
+
128
+ it 'does not convert a Sensitive instance to string' do
129
+ v = Puppet::Pops::Types::PSensitiveType::Sensitive.new("don't reveal this")
130
+ expect(converter.convert(v, {}, nil)).to equal(v)
131
+ end
132
+ end
133
+ end
@@ -10,6 +10,18 @@ describe 'dependency loader' do
10
10
  let(:loaders) { Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [])) }
11
11
 
12
12
  describe 'FileBased module loader' do
13
+ it 'prints a pretty name for itself when inspected' do
14
+ module_dir = dir_containing('testmodule', {
15
+ 'lib' => { 'puppet' => { 'functions' => { 'testmodule' => {
16
+ 'foo.rb' => 'Puppet::Functions.create_function("foo") { def foo; end; }'
17
+ }}}}})
18
+
19
+ loader = loader_for('testmodule', module_dir)
20
+
21
+ expect(loader.inspect).to eq("(DependencyLoader 'test-dep' [(ModuleLoader::FileBased 'testmodule' 'testmodule')])")
22
+ expect(loader.to_s).to eq("(DependencyLoader 'test-dep' [(ModuleLoader::FileBased 'testmodule' 'testmodule')])")
23
+ end
24
+
13
25
  it 'load something in global name space raises an error' do
14
26
  module_dir = dir_containing('testmodule', {
15
27
  'lib' => { 'puppet' => { 'functions' => { 'testmodule' => {
@@ -20,32 +20,6 @@ describe 'the static loader' do
20
20
  expect(loader.find(a_typed_name)).to be(nil)
21
21
  end
22
22
 
23
- context 'provides access to logging functions' do
24
- let(:loader) { loader = Puppet::Pops::Loader::StaticLoader.new() }
25
- # Ensure all logging functions produce output
26
- before(:each) { Puppet::Util::Log.level = :debug }
27
-
28
- Puppet::Util::Log.levels.each do |level|
29
- it "defines the function #{level.to_s}" do
30
- expect(loader.load(:function, level).class.name).to eql(level.to_s)
31
- end
32
-
33
- it 'and #{level.to_s} can be called' do
34
- expect(loader.load(:function, level).call({}, 'yay').to_s).to eql('yay')
35
- end
36
-
37
- it "uses the evaluator to format output" do
38
- expect(loader.load(:function, level).call({}, ['yay', 'surprise']).to_s).to eql('[yay, surprise]')
39
- end
40
-
41
- it 'outputs name of source (scope) by passing it to the Log utility' do
42
- the_scope = {}
43
- Puppet::Util::Log.any_instance.expects(:source=).with(the_scope)
44
- loader.load(:function, level).call(the_scope, 'x')
45
- end
46
- end
47
- end
48
-
49
23
  context 'provides access to resource types built into puppet' do
50
24
  let(:loader) { loader = Puppet::Pops::Loader::StaticLoader.new() }
51
25
 
@@ -0,0 +1,149 @@
1
+ #! /usr/bin/env ruby
2
+ require 'spec_helper'
3
+ require 'puppet_spec/compiler'
4
+
5
+ module Puppet::Pops
6
+ module Lookup
7
+ describe 'Puppet::Pops::Lookup::Context' do
8
+
9
+ context 'an instance' do
10
+ include PuppetSpec::Compiler
11
+ it 'can be created' do
12
+ code = "notice(type(Puppet::LookupContext.new('e', 'm')))"
13
+ expect(eval_and_collect_notices(code)[0]).to match(/Object\[\{name => 'Puppet::LookupContext'/)
14
+ end
15
+
16
+ it 'returns its environment_name' do
17
+ code = "notice(Puppet::LookupContext.new('e', 'm').environment_name)"
18
+ expect(eval_and_collect_notices(code)[0]).to eql('e')
19
+ end
20
+
21
+ it 'returns its module_name' do
22
+ code = "notice(Puppet::LookupContext.new('e', 'm').module_name)"
23
+ expect(eval_and_collect_notices(code)[0]).to eql('m')
24
+ end
25
+
26
+ it 'can use an undef module_name' do
27
+ code = "notice(type(Puppet::LookupContext.new('e', undef).module_name))"
28
+ expect(eval_and_collect_notices(code)[0]).to eql('Undef')
29
+ end
30
+
31
+ it 'can store and retrieve a value using the cache' do
32
+ code = <<-PUPPET.unindent
33
+ $ctx = Puppet::LookupContext.new('e', 'm')
34
+ $ctx.cache('ze_key', 'ze_value')
35
+ notice($ctx.cached_value('ze_key'))
36
+ PUPPET
37
+ expect(eval_and_collect_notices(code)[0]).to eql('ze_value')
38
+ end
39
+
40
+ it 'can store and retrieve a hash using the cache' do
41
+ code = <<-PUPPET.unindent
42
+ $ctx = Puppet::LookupContext.new('e', 'm')
43
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
44
+ $ctx.cached_entries |$key, $value| { notice($key); notice($value) }
45
+ PUPPET
46
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 first v2 second))
47
+ end
48
+
49
+ it 'can use the cache to merge hashes' do
50
+ code = <<-PUPPET.unindent
51
+ $ctx = Puppet::LookupContext.new('e', 'm')
52
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
53
+ $ctx.cache_all({ 'v3' => 'third', 'v4' => 'fourth' })
54
+ $ctx.cached_entries |$key, $value| { notice($key); notice($value) }
55
+ PUPPET
56
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 first v2 second v3 third v4 fourth))
57
+ end
58
+
59
+ it 'can use the cache to merge hashes and individual entries' do
60
+ code = <<-PUPPET.unindent
61
+ $ctx = Puppet::LookupContext.new('e', 'm')
62
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
63
+ $ctx.cache('v3', 'third')
64
+ $ctx.cached_entries |$key, $value| { notice($key); notice($value) }
65
+ PUPPET
66
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 first v2 second v3 third))
67
+ end
68
+
69
+ it 'can iterate the cache using one argument block' do
70
+ code = <<-PUPPET.unindent
71
+ $ctx = Puppet::LookupContext.new('e', 'm')
72
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
73
+ $ctx.cached_entries |$entry| { notice($entry[0]); notice($entry[1]) }
74
+ PUPPET
75
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 first v2 second))
76
+ end
77
+
78
+ it 'can replace individual cached entries' do
79
+ code = <<-PUPPET.unindent
80
+ $ctx = Puppet::LookupContext.new('e', 'm')
81
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
82
+ $ctx.cache('v2', 'changed')
83
+ $ctx.cached_entries |$key, $value| { notice($key); notice($value) }
84
+ PUPPET
85
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 first v2 changed))
86
+ end
87
+
88
+ it 'can replace multiple cached entries' do
89
+ code = <<-PUPPET.unindent
90
+ $ctx = Puppet::LookupContext.new('e', 'm')
91
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second', 'v3' => 'third' })
92
+ $ctx.cache_all({ 'v1' => 'one', 'v3' => 'three' })
93
+ $ctx.cached_entries |$key, $value| { notice($key); notice($value) }
94
+ PUPPET
95
+ expect(eval_and_collect_notices(code)).to eql(%w(v1 one v2 second v3 three))
96
+ end
97
+
98
+ it 'cached_entries returns an Iterable when called without a block' do
99
+ code = <<-PUPPET.unindent
100
+ $ctx = Puppet::LookupContext.new('e', 'm')
101
+ $ctx.cache_all({ 'v1' => 'first', 'v2' => 'second' })
102
+ $iter = $ctx.cached_entries
103
+ notice(type($iter, generalized))
104
+ $iter.each |$entry| { notice($entry[0]); notice($entry[1]) }
105
+ PUPPET
106
+ expect(eval_and_collect_notices(code)).to eql(['Iterator[Tuple[String, String, 2, 2]]', 'v1', 'first', 'v2', 'second'])
107
+ end
108
+
109
+ it 'will throw :no_such_key when not_found is called' do
110
+ code = <<-PUPPET.unindent
111
+ $ctx = Puppet::LookupContext.new('e', 'm')
112
+ $ctx.not_found
113
+ PUPPET
114
+ expect { eval_and_collect_notices(code) }.to throw_symbol(:no_such_key)
115
+ end
116
+
117
+ context 'when used in an Invocation' do
118
+ let(:invocation) { Invocation.new({}) }
119
+ let(:invocation_with_explain) { Invocation.new({}, {}, {}, true) }
120
+
121
+ it 'will not call explain unless explanations are active' do
122
+ Invocation.expects(:current).returns(invocation)
123
+ code = <<-PUPPET.unindent
124
+ $ctx = Puppet::LookupContext.new('e', 'm')
125
+ $ctx.explain || { notice('stop calling'); 'bad' }
126
+ PUPPET
127
+ expect(eval_and_collect_notices(code)).to be_empty
128
+ end
129
+
130
+ it 'will call explain when explanations are active' do
131
+ Invocation.expects(:current).returns(invocation_with_explain)
132
+ invocation_with_explain.with(:global, 'test') do
133
+ code = <<-PUPPET.unindent
134
+ $ctx = Puppet::LookupContext.new('e', 'm')
135
+ $ctx.explain || { notice('called'); 'good' }
136
+ PUPPET
137
+ expect(eval_and_collect_notices(code)).to eql(['called'])
138
+ end
139
+ expect(invocation_with_explain.explainer.to_s).to eql(<<-TEXT.unindent)
140
+ Data Binding "test"
141
+ good
142
+ TEXT
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+