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,904 @@
1
+ require 'spec_helper'
2
+ require 'puppet/pops'
3
+
4
+ describe 'The string converter' do
5
+ let(:converter) { Puppet::Pops::Types::StringConverter.singleton }
6
+ let(:factory) { Puppet::Pops::Types::TypeFactory }
7
+ let(:format) { Puppet::Pops::Types::StringConverter::Format }
8
+
9
+ describe 'helper Format' do
10
+ it 'parses a single character like "%d" as a format' do
11
+ fmt = format.new("%d")
12
+ expect(fmt.format()).to be(:d)
13
+ expect(fmt.alt()).to be(false)
14
+ expect(fmt.left()).to be(false)
15
+ expect(fmt.width()).to be_nil
16
+ expect(fmt.prec()).to be_nil
17
+ expect(fmt.plus()).to eq(:ignore)
18
+ end
19
+
20
+ it 'alternative form can be given with "%#d"' do
21
+ fmt = format.new("%#d")
22
+ expect(fmt.format()).to be(:d)
23
+ expect(fmt.alt()).to be(true)
24
+ end
25
+
26
+ it 'left adjust can be given with "%-d"' do
27
+ fmt = format.new("%-d")
28
+ expect(fmt.format()).to be(:d)
29
+ expect(fmt.left()).to be(true)
30
+ end
31
+
32
+ it 'plus sign can be used to indicate how positive numbers are displayed' do
33
+ fmt = format.new("%+d")
34
+ expect(fmt.format()).to be(:d)
35
+ expect(fmt.plus()).to eq(:plus)
36
+ end
37
+
38
+ it 'a space can be used to output " " instead of "+" for positive numbers' do
39
+ fmt = format.new("% d")
40
+ expect(fmt.format()).to be(:d)
41
+ expect(fmt.plus()).to eq(:space)
42
+ end
43
+
44
+ it 'padding with zero can be specified with a "0" flag' do
45
+ fmt = format.new("%0d")
46
+ expect(fmt.format()).to be(:d)
47
+ expect(fmt.zero_pad()).to be(true)
48
+ end
49
+
50
+ it 'width can be specified as an integer >= 1' do
51
+ fmt = format.new("%1d")
52
+ expect(fmt.format()).to be(:d)
53
+ expect(fmt.width()).to be(1)
54
+ fmt = format.new("%10d")
55
+ expect(fmt.width()).to be(10)
56
+ end
57
+
58
+ it 'precision can be specified as an integer >= 0' do
59
+ fmt = format.new("%.0d")
60
+ expect(fmt.format()).to be(:d)
61
+ expect(fmt.prec()).to be(0)
62
+ fmt = format.new("%.10d")
63
+ expect(fmt.prec()).to be(10)
64
+ end
65
+
66
+ it 'width and precision can both be specified' do
67
+ fmt = format.new("%2.3d")
68
+ expect(fmt.format()).to be(:d)
69
+ expect(fmt.width()).to be(2)
70
+ expect(fmt.prec()).to be(3)
71
+ end
72
+
73
+ [
74
+ '[', '{', '(', '<', '|',
75
+ ].each do | delim |
76
+ it "a container delimiter pair can be set with '#{delim}'" do
77
+ fmt = format.new("%#{delim}d")
78
+ expect(fmt.format()).to be(:d)
79
+ expect(fmt.delimiters()).to eql(delim)
80
+ end
81
+ end
82
+
83
+ it "Is an error to specify different delimiters at the same time" do
84
+ expect do
85
+ fmt = format.new("%[{d")
86
+ end.to raise_error(/Only one of the delimiters/)
87
+ end
88
+
89
+ it "Is an error to specify the same flag more than once" do
90
+ expect do
91
+ fmt = format.new("%[[d")
92
+ end.to raise_error(/The same flag can only be used once/)
93
+ end
94
+ end
95
+
96
+ context 'when converting to string' do
97
+ {
98
+ 42 => "42",
99
+ 3.14 => "3.140000",
100
+ "hello world" => "hello world",
101
+ "hello\tworld" => "hello\tworld",
102
+ }.each do |from, to|
103
+ it "the string value of #{from} is '#{to}'" do
104
+ expect(converter.convert(from, :default)).to eq(to)
105
+ end
106
+ end
107
+
108
+ it 'float point value decimal digits can be specified' do
109
+ string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => '%.2f'}
110
+ expect(converter.convert(3.14, string_formats)).to eq('3.14')
111
+ end
112
+
113
+ it 'when specifying format for one type, other formats are not affected' do
114
+ string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => '%.2f'}
115
+ expect(converter.convert('3.1415', string_formats)).to eq('3.1415')
116
+ end
117
+
118
+ it 'The %p format for string produces quoted string' do
119
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%p'}
120
+ expect(converter.convert("hello\tworld", string_formats)).to eq('"hello\\tworld"')
121
+ end
122
+
123
+ {
124
+ '%s' => 'hello::world',
125
+ '%p' => '"hello::world"',
126
+ '%c' => 'Hello::world',
127
+ '%#c' => '"Hello::world"',
128
+ '%u' => 'HELLO::WORLD',
129
+ '%#u' => '"HELLO::WORLD"',
130
+ }.each do |fmt, result |
131
+ it "the format #{fmt} produces #{result}" do
132
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => fmt}
133
+ expect(converter.convert('hello::world', string_formats)).to eq(result)
134
+ end
135
+ end
136
+
137
+ {
138
+ '%c' => 'Hello::world',
139
+ '%#c' => '"Hello::world"',
140
+ '%d' => 'hello::world',
141
+ '%#d' => '"hello::world"',
142
+ }.each do |fmt, result |
143
+ it "the format #{fmt} produces #{result}" do
144
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => fmt}
145
+ expect(converter.convert('HELLO::WORLD', string_formats)).to eq(result)
146
+ end
147
+ end
148
+
149
+ {
150
+ ' a b ' => 'a b',
151
+ 'a b ' => 'a b',
152
+ ' a b' => 'a b',
153
+ }.each do |input, result |
154
+ it "the input #{input} is trimmed to #{result} by using format '%t'" do
155
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%t'}
156
+ expect(converter.convert(input, string_formats)).to eq(result)
157
+ end
158
+ end
159
+
160
+ {
161
+ ' a b ' => '"a b"',
162
+ 'a b ' => '"a b"',
163
+ ' a b' => '"a b"',
164
+ }.each do |input, result |
165
+ it "the input #{input} is trimmed to #{result} by using format '%#t'" do
166
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%#t'}
167
+ expect(converter.convert(input, string_formats)).to eq(result)
168
+ end
169
+ end
170
+
171
+ it 'errors when format is not recognized' do
172
+ expect do
173
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => "%k"}
174
+ converter.convert('wat', string_formats)
175
+ end.to raise_error(/Illegal format 'k' specified for value of String type - expected one of the characters 'cCudspt'/)
176
+ end
177
+
178
+ it 'Width pads a string left with spaces to given width' do
179
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%6s'}
180
+ expect(converter.convert("abcd", string_formats)).to eq(' abcd')
181
+ end
182
+
183
+ it 'Width pads a string right with spaces to given width and - flag' do
184
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%-6s'}
185
+ expect(converter.convert("abcd", string_formats)).to eq('abcd ')
186
+ end
187
+
188
+ it 'Precision truncates the string if precision < length' do
189
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => '%-6.2s'}
190
+ expect(converter.convert("abcd", string_formats)).to eq('ab ')
191
+ end
192
+
193
+ {
194
+ '%4.2s' => ' he',
195
+ '%4.2p' => ' "h',
196
+ '%4.2c' => ' He',
197
+ '%#4.2c' => ' "H',
198
+ '%4.2u' => ' HE',
199
+ '%#4.2u' => ' "H',
200
+ '%4.2c' => ' He',
201
+ '%#4.2c' => ' "H',
202
+ '%4.2d' => ' he',
203
+ '%#4.2d' => ' "h',
204
+ }.each do |fmt, result |
205
+ it "width and precision can be combined with #{fmt}" do
206
+ string_formats = { Puppet::Pops::Types::PStringType::DEFAULT => fmt}
207
+ expect(converter.convert('hello::world', string_formats)).to eq(result)
208
+ end
209
+ end
210
+
211
+ end
212
+
213
+ context 'when converting integer' do
214
+ it 'the default string representation is decimal' do
215
+ expect(converter.convert(42, :default)).to eq('42')
216
+ end
217
+
218
+ {
219
+ '%s' => '18',
220
+ '%4.1s' => ' 1',
221
+ '%p' => '18',
222
+ '%4.2p' => ' 18',
223
+ '%4.1p' => ' 1',
224
+ '%#s' => '"18"',
225
+ '%#6.4s' => ' "18"',
226
+ '%#p' => '18',
227
+ '%#6.4p' => ' 18',
228
+ '%d' => '18',
229
+ '%4.1d' => ' 18',
230
+ '%4.3d' => ' 018',
231
+ '%x' => '12',
232
+ '%4.3x' => ' 012',
233
+ '%#x' => '0x12',
234
+ '%#6.4x' => '0x0012',
235
+ '%X' => '12',
236
+ '%4.3X' => ' 012',
237
+ '%#X' => '0X12',
238
+ '%#6.4X' => '0X0012',
239
+ '%o' => '22',
240
+ '%4.2o' => ' 22',
241
+ '%#o' => '022',
242
+ '%#6.4o' => ' 0022',
243
+ '%b' => '10010',
244
+ '%7.6b' => ' 010010',
245
+ '%#b' => '0b10010',
246
+ '%#9.6b' => ' 0b010010',
247
+ '%#B' => '0B10010',
248
+ '%#9.6B' => ' 0B010010',
249
+ # Integer to float then a float format - fully tested for float
250
+ '%e' => '1.800000e+01',
251
+ '%E' => '1.800000E+01',
252
+ '%f' => '18.000000',
253
+ '%g' => '18',
254
+ '%a' => '0x1.2p+4',
255
+ '%A' => '0X1.2P+4',
256
+ '%.1f' => '18.0',
257
+ }.each do |fmt, result |
258
+ it "the format #{fmt} produces #{result}" do
259
+ string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => fmt}
260
+ expect(converter.convert(18, string_formats)).to eq(result)
261
+ end
262
+ end
263
+
264
+ it 'produces a unicode char string by using format %c' do
265
+ string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => '%c'}
266
+ expect(converter.convert(0x1F603, string_formats)).to eq("\u{1F603}")
267
+ end
268
+
269
+ it 'produces a quoted unicode char string by using format %#c' do
270
+ string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => '%#c'}
271
+ expect(converter.convert(0x1F603, string_formats)).to eq("\"\u{1F603}\"")
272
+ end
273
+
274
+ it 'errors when format is not recognized' do
275
+ expect do
276
+ string_formats = { Puppet::Pops::Types::PIntegerType::DEFAULT => "%k"}
277
+ converter.convert(18, string_formats)
278
+ end.to raise_error(/Illegal format 'k' specified for value of Integer type - expected one of the characters 'dxXobBeEfgGaAspc'/)
279
+ end
280
+ end
281
+
282
+ context 'when converting float' do
283
+ it 'the default string representation is decimal' do
284
+ expect(converter.convert(42.0, :default)).to eq('42.000000')
285
+ end
286
+
287
+ {
288
+ '%s' => '18.0',
289
+ '%#s' => '"18.0"',
290
+ '%5s' => ' 18.0',
291
+ '%#8s' => ' "18.0"',
292
+ '%05.1s' => ' 1',
293
+ '%p' => '18.0',
294
+ '%7.2p' => ' 18',
295
+
296
+ '%e' => '1.800000e+01',
297
+ '%+e' => '+1.800000e+01',
298
+ '% e' => ' 1.800000e+01',
299
+ '%.2e' => '1.80e+01',
300
+ '%10.2e' => ' 1.80e+01',
301
+ '%-10.2e' => '1.80e+01 ',
302
+ '%010.2e' => '001.80e+01',
303
+
304
+ '%E' => '1.800000E+01',
305
+ '%+E' => '+1.800000E+01',
306
+ '% E' => ' 1.800000E+01',
307
+ '%.2E' => '1.80E+01',
308
+ '%10.2E' => ' 1.80E+01',
309
+ '%-10.2E' => '1.80E+01 ',
310
+ '%010.2E' => '001.80E+01',
311
+
312
+ '%f' => '18.000000',
313
+ '%+f' => '+18.000000',
314
+ '% f' => ' 18.000000',
315
+ '%.2f' => '18.00',
316
+ '%10.2f' => ' 18.00',
317
+ '%-10.2f' => '18.00 ',
318
+ '%010.2f' => '0000018.00',
319
+
320
+ '%g' => '18',
321
+ '%5g' => ' 18',
322
+ '%05g' => '00018',
323
+ '%-5g' => '18 ',
324
+ '%5.4g' => ' 18', # precision has no effect
325
+
326
+ '%a' => '0x1.2p+4',
327
+ '%.4a' => '0x1.2000p+4',
328
+ '%10a' => ' 0x1.2p+4',
329
+ '%010a' => '0x001.2p+4',
330
+ '%-10a' => '0x1.2p+4 ',
331
+ '%A' => '0X1.2P+4',
332
+ '%.4A' => '0X1.2000P+4',
333
+ '%10A' => ' 0X1.2P+4',
334
+ '%-10A' => '0X1.2P+4 ',
335
+ '%010A' => '0X001.2P+4',
336
+
337
+ # integer formats fully tested for integer
338
+ '%d' => '18',
339
+ '%x' => '12',
340
+ '%X' => '12',
341
+ '%o' => '22',
342
+ '%b' => '10010',
343
+ '%#B' => '0B10010',
344
+ }.each do |fmt, result |
345
+ it "the format #{fmt} produces #{result}" do
346
+ string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => fmt}
347
+ expect(converter.convert(18.0, string_formats)).to eq(result)
348
+ end
349
+ end
350
+
351
+ it 'errors when format is not recognized' do
352
+ expect do
353
+ string_formats = { Puppet::Pops::Types::PFloatType::DEFAULT => "%k"}
354
+ converter.convert(18.0, string_formats)
355
+ end.to raise_error(/Illegal format 'k' specified for value of Float type - expected one of the characters 'dxXobBeEfgGaAsp'/)
356
+ end
357
+ end
358
+
359
+ context 'when converting undef' do
360
+ it 'the default string representation is empty string' do
361
+ expect(converter.convert(nil, :default)).to eq('')
362
+ end
363
+
364
+ { "%u" => "undef",
365
+ "%#u" => "undefined",
366
+ "%s" => "",
367
+ "%#s" => '""',
368
+ "%p" => 'undef',
369
+ "%#p" => '"undef"',
370
+ "%n" => 'nil',
371
+ "%#n" => 'null',
372
+ "%v" => 'n/a',
373
+ "%V" => 'N/A',
374
+ "%d" => 'NaN',
375
+ "%x" => 'NaN',
376
+ "%o" => 'NaN',
377
+ "%b" => 'NaN',
378
+ "%B" => 'NaN',
379
+ "%e" => 'NaN',
380
+ "%E" => 'NaN',
381
+ "%f" => 'NaN',
382
+ "%g" => 'NaN',
383
+ "%G" => 'NaN',
384
+ "%a" => 'NaN',
385
+ "%A" => 'NaN',
386
+ }.each do |fmt, result |
387
+ it "the format #{fmt} produces #{result}" do
388
+ string_formats = { Puppet::Pops::Types::PUndefType::DEFAULT => fmt}
389
+ expect(converter.convert(nil, string_formats)).to eq(result)
390
+ end
391
+ end
392
+
393
+ { "%7u" => " undef",
394
+ "%-7u" => "undef ",
395
+ "%#10u" => " undefined",
396
+ "%#-10u" => "undefined ",
397
+ "%7.2u" => " un",
398
+ "%4s" => " ",
399
+ "%#4s" => ' ""',
400
+ "%7p" => ' undef',
401
+ "%7.1p" => ' u',
402
+ "%#8p" => ' "undef"',
403
+ "%5n" => ' nil',
404
+ "%.1n" => 'n',
405
+ "%-5n" => 'nil ',
406
+ "%#5n" => ' null',
407
+ "%#-5n" => 'null ',
408
+ "%5v" => ' n/a',
409
+ "%5.2v" => ' n/',
410
+ "%-5v" => 'n/a ',
411
+ "%5V" => ' N/A',
412
+ "%5.1V" => ' N',
413
+ "%-5V" => 'N/A ',
414
+ "%5d" => ' NaN',
415
+ "%5.2d" => ' Na',
416
+ "%-5d" => 'NaN ',
417
+ "%5x" => ' NaN',
418
+ "%5.2x" => ' Na',
419
+ "%-5x" => 'NaN ',
420
+ "%5o" => ' NaN',
421
+ "%5.2o" => ' Na',
422
+ "%-5o" => 'NaN ',
423
+ "%5b" => ' NaN',
424
+ "%5.2b" => ' Na',
425
+ "%-5b" => 'NaN ',
426
+ "%5B" => ' NaN',
427
+ "%5.2B" => ' Na',
428
+ "%-5B" => 'NaN ',
429
+ "%5e" => ' NaN',
430
+ "%5.2e" => ' Na',
431
+ "%-5e" => 'NaN ',
432
+ "%5E" => ' NaN',
433
+ "%5.2E" => ' Na',
434
+ "%-5E" => 'NaN ',
435
+ "%5f" => ' NaN',
436
+ "%5.2f" => ' Na',
437
+ "%-5f" => 'NaN ',
438
+ "%5g" => ' NaN',
439
+ "%5.2g" => ' Na',
440
+ "%-5g" => 'NaN ',
441
+ "%5G" => ' NaN',
442
+ "%5.2G" => ' Na',
443
+ "%-5G" => 'NaN ',
444
+ "%5a" => ' NaN',
445
+ "%5.2a" => ' Na',
446
+ "%-5a" => 'NaN ',
447
+ "%5A" => ' NaN',
448
+ "%5.2A" => ' Na',
449
+ "%-5A" => 'NaN ',
450
+ }.each do |fmt, result |
451
+ it "the format #{fmt} produces #{result}" do
452
+ string_formats = { Puppet::Pops::Types::PUndefType::DEFAULT => fmt}
453
+ expect(converter.convert(nil, string_formats)).to eq(result)
454
+ end
455
+ end
456
+
457
+ it 'errors when format is not recognized' do
458
+ expect do
459
+ string_formats = { Puppet::Pops::Types::PUndefType::DEFAULT => "%k"}
460
+ converter.convert(nil, string_formats)
461
+ end.to raise_error(/Illegal format 'k' specified for value of Undef type - expected one of the characters 'nudxXobBeEfgGaAvVsp'/)
462
+ end
463
+ end
464
+
465
+ context 'when converting default' do
466
+ it 'the default string representation is unquoted "default"' do
467
+ expect(converter.convert(:default, :default)).to eq('default')
468
+ end
469
+
470
+ { "%d" => 'default',
471
+ "%D" => 'Default',
472
+ "%#d" => '"default"',
473
+ "%#D" => '"Default"',
474
+ "%s" => 'default',
475
+ "%p" => 'default',
476
+ }.each do |fmt, result |
477
+ it "the format #{fmt} produces #{result}" do
478
+ string_formats = { Puppet::Pops::Types::PDefaultType::DEFAULT => fmt}
479
+ expect(converter.convert(:default, string_formats)).to eq(result)
480
+ end
481
+ end
482
+
483
+ it 'errors when format is not recognized' do
484
+ expect do
485
+ string_formats = { Puppet::Pops::Types::PDefaultType::DEFAULT => "%k"}
486
+ converter.convert(:default, string_formats)
487
+ end.to raise_error(/Illegal format 'k' specified for value of Default type - expected one of the characters 'dDsp'/)
488
+ end
489
+ end
490
+
491
+ context 'when converting boolean true' do
492
+ it 'the default string representation is unquoted "true"' do
493
+ expect(converter.convert(true, :default)).to eq('true')
494
+ end
495
+
496
+ { "%t" => 'true',
497
+ "%#t" => 't',
498
+ "%T" => 'True',
499
+ "%#T" => 'T',
500
+ "%s" => 'true',
501
+ "%p" => 'true',
502
+ "%d" => '1',
503
+ "%x" => '1',
504
+ "%#x" => '0x1',
505
+ "%o" => '1',
506
+ "%#o" => '01',
507
+ "%b" => '1',
508
+ "%#b" => '0b1',
509
+ "%#B" => '0B1',
510
+ "%e" => '1.000000e+00',
511
+ "%f" => '1.000000',
512
+ "%g" => '1',
513
+ "%a" => '0x1p+0',
514
+ "%A" => '0X1P+0',
515
+ "%.1f" => '1.0',
516
+ "%y" => 'yes',
517
+ "%Y" => 'Yes',
518
+ "%#y" => 'y',
519
+ "%#Y" => 'Y',
520
+ }.each do |fmt, result |
521
+ it "the format #{fmt} produces #{result}" do
522
+ string_formats = { Puppet::Pops::Types::PBooleanType::DEFAULT => fmt}
523
+ expect(converter.convert(true, string_formats)).to eq(result)
524
+ end
525
+ end
526
+
527
+ it 'errors when format is not recognized' do
528
+ expect do
529
+ string_formats = { Puppet::Pops::Types::PBooleanType::DEFAULT => "%k"}
530
+ converter.convert(true, string_formats)
531
+ end.to raise_error(/Illegal format 'k' specified for value of Boolean type - expected one of the characters 'tTyYdxXobBeEfgGaAsp'/)
532
+ end
533
+
534
+ end
535
+
536
+ context 'when converting boolean false' do
537
+ it 'the default string representation is unquoted "false"' do
538
+ expect(converter.convert(false, :default)).to eq('false')
539
+ end
540
+
541
+ { "%t" => 'false',
542
+ "%#t" => 'f',
543
+ "%T" => 'False',
544
+ "%#T" => 'F',
545
+ "%s" => 'false',
546
+ "%p" => 'false',
547
+ "%d" => '0',
548
+ "%x" => '0',
549
+ "%#x" => '0',
550
+ "%o" => '0',
551
+ "%#o" => '0',
552
+ "%b" => '0',
553
+ "%#b" => '0',
554
+ "%#B" => '0',
555
+ "%e" => '0.000000e+00',
556
+ "%E" => '0.000000E+00',
557
+ "%f" => '0.000000',
558
+ "%g" => '0',
559
+ "%a" => '0x0p+0',
560
+ "%A" => '0X0P+0',
561
+ "%.1f" => '0.0',
562
+ "%y" => 'no',
563
+ "%Y" => 'No',
564
+ "%#y" => 'n',
565
+ "%#Y" => 'N',
566
+ }.each do |fmt, result |
567
+ it "the format #{fmt} produces #{result}" do
568
+ string_formats = { Puppet::Pops::Types::PBooleanType::DEFAULT => fmt}
569
+ expect(converter.convert(false, string_formats)).to eq(result)
570
+ end
571
+ end
572
+
573
+ it 'errors when format is not recognized' do
574
+ expect do
575
+ string_formats = { Puppet::Pops::Types::PBooleanType::DEFAULT => "%k"}
576
+ converter.convert(false, string_formats)
577
+ end.to raise_error(/Illegal format 'k' specified for value of Boolean type - expected one of the characters 'tTyYdxXobBeEfgGaAsp'/)
578
+ end
579
+ end
580
+
581
+ context 'when converting array' do
582
+ it 'the default string representation is using [] delimiters, joins with ',' and uses %p for values' do
583
+ expect(converter.convert(["hello", "world"], :default)).to eq('["hello", "world"]')
584
+ end
585
+
586
+ { "%s" => '[1, "hello"]',
587
+ "%p" => '[1, "hello"]',
588
+ "%a" => '[1, "hello"]',
589
+ "%<a" => '<1, "hello">',
590
+ "%[a" => '[1, "hello"]',
591
+ "%(a" => '(1, "hello")',
592
+ "%{a" => '{1, "hello"}',
593
+ "% a" => '1, "hello"',
594
+
595
+ {'format' => '%(a',
596
+ 'separator' => ''
597
+ } => '(1 "hello")',
598
+
599
+ {'format' => '%|a',
600
+ 'separator' => ''
601
+ } => '|1 "hello"|',
602
+
603
+ {'format' => '%(a',
604
+ 'separator' => '',
605
+ 'string_formats' => {Puppet::Pops::Types::PIntegerType::DEFAULT => '%#x'}
606
+ } => '(0x1 "hello")',
607
+ }.each do |fmt, result |
608
+ it "the format #{fmt} produces #{result}" do
609
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => fmt}
610
+ expect(converter.convert([1, "hello"], string_formats)).to eq(result)
611
+ end
612
+ end
613
+
614
+ it "multiple rules selects most specific" do
615
+ short_array_t = factory.array_of(factory.integer, factory.range(1,2))
616
+ long_array_t = factory.array_of(factory.integer, factory.range(3,100))
617
+ string_formats = {
618
+ short_array_t => "%(a",
619
+ long_array_t => "%[a",
620
+ }
621
+ expect(converter.convert([1, 2], string_formats)).to eq('(1, 2)')
622
+ expect(converter.convert([1, 2, 3], string_formats)).to eq('[1, 2, 3]')
623
+ end
624
+
625
+ it 'indents elements in alternate mode' do
626
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#a', 'separator' =>"," } }
627
+ # formatting matters here
628
+ result = [
629
+ "[1, 2, 9, 9,",
630
+ " [3, 4],",
631
+ " [5,",
632
+ " [6, 7]],",
633
+ " 8, 9]"
634
+ ].join("\n")
635
+
636
+ formatted = converter.convert([1, 2, 9, 9, [3, 4], [5, [6, 7]], 8, 9], string_formats)
637
+ expect(formatted).to eq(result)
638
+ end
639
+
640
+ it 'treats hashes as nested arrays wrt indentation' do
641
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#a', 'separator' =>"," } }
642
+ # formatting matters here
643
+ result = [
644
+ "[1, 2, 9, 9,",
645
+ " {3 => 4, 5 => 6},",
646
+ " [5,",
647
+ " [6, 7]],",
648
+ " 8, 9]"
649
+ ].join("\n")
650
+
651
+ formatted = converter.convert([1, 2, 9, 9, {3 => 4, 5 => 6}, [5, [6, 7]], 8, 9], string_formats)
652
+ expect(formatted).to eq(result)
653
+ end
654
+
655
+ it 'indents and breaks when a sequence > given width, in alternate mode' do
656
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#3a', 'separator' =>"," } }
657
+ # formatting matters here
658
+ result = [
659
+ "[ 1,",
660
+ " 2,",
661
+ " 90,", # this sequence has length 4 (1,2,90) which is > 3
662
+ " [3, 4],",
663
+ " [5,",
664
+ " [6, 7]],",
665
+ " 8,",
666
+ " 9]",
667
+ ].join("\n")
668
+
669
+ formatted = converter.convert([1, 2, 90, [3, 4], [5, [6, 7]], 8, 9], string_formats)
670
+ expect(formatted).to eq(result)
671
+ end
672
+
673
+ it 'indents and breaks when a sequence (placed last) > given width, in alternate mode' do
674
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#3a', 'separator' =>"," } }
675
+ # formatting matters here
676
+ result = [
677
+ "[ 1,",
678
+ " 2,",
679
+ " 9,", # this sequence has length 3 (1,2,9) which does not cause breaking on each
680
+ " [3, 4],",
681
+ " [5,",
682
+ " [6, 7]],",
683
+ " 8,",
684
+ " 900]", # this sequence has length 4 (8, 900) which causes breaking on each
685
+ ].join("\n")
686
+
687
+ formatted = converter.convert([1, 2, 9, [3, 4], [5, [6, 7]], 8, 900], string_formats)
688
+ expect(formatted).to eq(result)
689
+ end
690
+
691
+ it 'indents and breaks nested sequences when one is placed first' do
692
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#a', 'separator' =>"," } }
693
+ # formatting matters here
694
+ result = [
695
+ "[",
696
+ " [",
697
+ " [1, 2,",
698
+ " [3, 4]]],",
699
+ " [5,",
700
+ " [6, 7]],",
701
+ " 8, 900]",
702
+ ].join("\n")
703
+
704
+ formatted = converter.convert([[[1, 2, [3, 4]]], [5, [6, 7]], 8, 900], string_formats)
705
+ expect(formatted).to eq(result)
706
+ end
707
+
708
+ it 'errors when format is not recognized' do
709
+ expect do
710
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => "%k"}
711
+ converter.convert([1,2], string_formats)
712
+ end.to raise_error(/Illegal format 'k' specified for value of Array type - expected one of the characters 'asp'/)
713
+ end
714
+ end
715
+
716
+ context 'when converting hash' do
717
+ it 'the default string representation is using {} delimiters, joins with '=>' and uses %p for values' do
718
+ expect(converter.convert({"hello" => "world"}, :default)).to eq('{"hello" => "world"}')
719
+ end
720
+
721
+ { "%s" => '{1 => "world"}',
722
+ "%p" => '{1 => "world"}',
723
+ "%h" => '{1 => "world"}',
724
+ "%a" => '[[1, "world"]]',
725
+ "%<h" => '<1 => "world">',
726
+ "%[h" => '[1 => "world"]',
727
+ "%(h" => '(1 => "world")',
728
+ "%{h" => '{1 => "world"}',
729
+ "% h" => '1 => "world"',
730
+
731
+ {'format' => '%(h',
732
+ 'separator2' => ' '
733
+ } => '(1 "world")',
734
+
735
+ {'format' => '%(h',
736
+ 'separator2' => ' ',
737
+ 'string_formats' => {Puppet::Pops::Types::PIntegerType::DEFAULT => '%#x'}
738
+ } => '(0x1 "world")',
739
+ }.each do |fmt, result |
740
+ it "the format #{fmt} produces #{result}" do
741
+ string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => fmt}
742
+ expect(converter.convert({1 => "world"}, string_formats)).to eq(result)
743
+ end
744
+ end
745
+
746
+ { "%s" => '{1 => "hello", 2 => "world"}',
747
+
748
+ {'format' => '%(h',
749
+ 'separator2' => ' '
750
+ } => '(1 "hello", 2 "world")',
751
+
752
+ {'format' => '%(h',
753
+ 'separator' => ' >>',
754
+ 'separator2' => ' <=> ',
755
+ 'string_formats' => {Puppet::Pops::Types::PIntegerType::DEFAULT => '%#x'}
756
+ } => '(0x1 <=> "hello" >> 0x2 <=> "world")',
757
+ }.each do |fmt, result |
758
+ it "the format #{fmt} produces #{result}" do
759
+ string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => fmt}
760
+ expect(converter.convert({1 => "hello", 2 => "world"}, string_formats)).to eq(result)
761
+ end
762
+ end
763
+
764
+ it 'indents elements in alternative mode #' do
765
+ string_formats = {
766
+ Puppet::Pops::Types::PHashType::DEFAULT => {
767
+ 'format' => '%#h',
768
+ }
769
+ }
770
+ # formatting matters here
771
+ result = [
772
+ "{",
773
+ " 1 => \"hello\",",
774
+ " 2 => {",
775
+ " 3 => \"world\"",
776
+ " }",
777
+ "}"
778
+ ].join("\n")
779
+
780
+ expect(converter.convert({1 => "hello", 2 => {3=> "world"}}, string_formats)).to eq(result)
781
+ end
782
+
783
+ context "containing an array" do
784
+ it 'the hash and array renders without breaks and indentation by default' do
785
+ result = '{1 => [1, 2, 3]}'
786
+ formatted = converter.convert({ 1 => [1, 2, 3] }, :default)
787
+ expect(formatted).to eq(result)
788
+ end
789
+
790
+ it 'the array renders with breaks if so specified' do
791
+ string_formats = { Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#1a', 'separator' =>"," } }
792
+ result = [
793
+ "{1 => [ 1,",
794
+ " 2,",
795
+ " 3]}"
796
+ ].join("\n")
797
+ formatted = converter.convert({ 1 => [1, 2, 3] }, string_formats)
798
+ expect(formatted).to eq(result)
799
+ end
800
+
801
+ it 'both hash and array renders with breaks and indentation if so specified for both' do
802
+ string_formats = {
803
+ Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%#1a', 'separator' =>"," },
804
+ Puppet::Pops::Types::PHashType::DEFAULT => { 'format' => '%#h', 'separator' =>"," }
805
+ }
806
+ result = [
807
+ "{",
808
+ " 1 => [ 1,",
809
+ " 2,",
810
+ " 3]",
811
+ "}"
812
+ ].join("\n")
813
+ formatted = converter.convert({ 1 => [1, 2, 3] }, string_formats)
814
+ expect(formatted).to eq(result)
815
+ end
816
+
817
+ it 'hash, but not array is rendered with breaks and indentation if so specified only for the hash' do
818
+ string_formats = {
819
+ Puppet::Pops::Types::PArrayType::DEFAULT => { 'format' => '%a', 'separator' =>"," },
820
+ Puppet::Pops::Types::PHashType::DEFAULT => { 'format' => '%#h', 'separator' =>"," }
821
+ }
822
+ result = [
823
+ "{",
824
+ " 1 => [1, 2, 3]",
825
+ "}"
826
+ ].join("\n")
827
+ formatted = converter.convert({ 1 => [1, 2, 3] }, string_formats)
828
+ expect(formatted).to eq(result)
829
+ end
830
+ end
831
+
832
+ it 'errors when format is not recognized' do
833
+ expect do
834
+ string_formats = { Puppet::Pops::Types::PHashType::DEFAULT => "%k"}
835
+ converter.convert({1 => 2}, string_formats)
836
+ end.to raise_error(/Illegal format 'k' specified for value of Hash type - expected one of the characters 'hasp'/)
837
+ end
838
+ end
839
+
840
+ context 'when converting regexp' do
841
+ it 'the default string representation is /regexp/' do
842
+ expect(converter.convert(/.*/, :default)).to eq('/.*/')
843
+ end
844
+
845
+ { "%s" => '/.*/',
846
+ "%6s" => ' /.*/',
847
+ "%.2s" => '/.',
848
+ "%-6s" => '/.*/ ',
849
+ "%p" => '/.*/',
850
+ "%6p" => ' /.*/',
851
+ "%-6p" => '/.*/ ',
852
+ "%.2p" => '/.',
853
+ "%#s" => '".*"',
854
+ "%#p" => '/.*/',
855
+ }.each do |fmt, result |
856
+ it "the format #{fmt} produces #{result}" do
857
+ string_formats = { Puppet::Pops::Types::PRegexpType::DEFAULT => fmt}
858
+ expect(converter.convert(/.*/, string_formats)).to eq(result)
859
+ end
860
+ end
861
+
862
+ it 'errors when format is not recognized' do
863
+ expect do
864
+ string_formats = { Puppet::Pops::Types::PRegexpType::DEFAULT => "%k"}
865
+ converter.convert(/.*/, string_formats)
866
+ end.to raise_error(/Illegal format 'k' specified for value of Regexp type - expected one of the characters 'rsp'/)
867
+ end
868
+ end
869
+
870
+ context 'when converting iterator' do
871
+ it 'the iterator is transformed to an array and formatted using array rules' do
872
+ itor = Puppet::Pops::Types::Iterator.new(Puppet::Pops::Types::PIntegerType::DEFAULT, [1,2,3]).reverse_each
873
+ expect(converter.convert(itor, :default)).to eq('[3, 2, 1]')
874
+ end
875
+ end
876
+
877
+ context 'when converting type' do
878
+ it 'the default string representation of a type is its programmatic string form' do
879
+ expect(converter.convert(factory.integer, :default)).to eq('Integer')
880
+ end
881
+
882
+ { "%s" => 'Integer',
883
+ "%p" => 'Integer',
884
+ "%#s" => '"Integer"',
885
+ "%#p" => 'Integer',
886
+ }.each do |fmt, result |
887
+ it "the format #{fmt} produces #{result}" do
888
+ string_formats = { Puppet::Pops::Types::PType::DEFAULT => fmt}
889
+ expect(converter.convert(factory.integer, string_formats)).to eq(result)
890
+ end
891
+ end
892
+
893
+ it 'errors when format is not recognized' do
894
+ expect do
895
+ string_formats = { Puppet::Pops::Types::PType::DEFAULT => "%k"}
896
+ converter.convert(factory.integer, string_formats)
897
+ end.to raise_error(/Illegal format 'k' specified for value of Type type - expected one of the characters 'sp'/)
898
+ end
899
+ end
900
+
901
+ it "allows format to be directly given (instead of as a type=> format hash)" do
902
+ expect(converter.convert('hello', '%5.1s')).to eq(' h')
903
+ end
904
+ end