puppet 5.0.1 → 5.1.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/lib/puppet/agent.rb +1 -0
  3. data/lib/puppet/defaults.rb +1 -1
  4. data/lib/puppet/functions.rb +6 -7
  5. data/lib/puppet/functions/all.rb +100 -0
  6. data/lib/puppet/functions/any.rb +105 -0
  7. data/lib/puppet/functions/defined.rb +3 -3
  8. data/lib/puppet/functions/new.rb +2 -1
  9. data/lib/puppet/functions/reduce.rb +31 -0
  10. data/lib/puppet/functions/tree_each.rb +200 -0
  11. data/lib/puppet/module.rb +30 -0
  12. data/lib/puppet/parser/functions/new.rb +67 -0
  13. data/lib/puppet/parser/functions/reduce.rb +31 -0
  14. data/lib/puppet/parser/relationship.rb +2 -2
  15. data/lib/puppet/parser/resource.rb +39 -10
  16. data/lib/puppet/parser/scope.rb +1 -1
  17. data/lib/puppet/pops/evaluator/access_operator.rb +11 -4
  18. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
  19. data/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -4
  20. data/lib/puppet/pops/evaluator/relationship_operator.rb +1 -1
  21. data/lib/puppet/pops/evaluator/runtime3_converter.rb +3 -3
  22. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -1
  23. data/lib/puppet/pops/loader/module_loaders.rb +1 -1
  24. data/lib/puppet/pops/loader/static_loader.rb +1 -2
  25. data/lib/puppet/pops/loaders.rb +1 -2
  26. data/lib/puppet/pops/lookup/context.rb +1 -1
  27. data/lib/puppet/pops/lookup/lookup_adapter.rb +2 -1
  28. data/lib/puppet/pops/model/ast.rb +440 -436
  29. data/lib/puppet/pops/model/factory.rb +140 -140
  30. data/lib/puppet/pops/pcore.rb +1 -2
  31. data/lib/puppet/pops/resource/param.rb +1 -1
  32. data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
  33. data/lib/puppet/pops/serialization/from_data_converter.rb +0 -12
  34. data/lib/puppet/pops/time/timestamp.rb +29 -17
  35. data/lib/puppet/pops/types/annotatable.rb +2 -2
  36. data/lib/puppet/pops/types/annotation.rb +8 -8
  37. data/lib/puppet/pops/types/class_loader.rb +3 -3
  38. data/lib/puppet/pops/types/implementation_registry.rb +1 -1
  39. data/lib/puppet/pops/types/iterable.rb +2 -2
  40. data/lib/puppet/pops/types/p_binary_type.rb +2 -2
  41. data/lib/puppet/pops/types/p_init_type.rb +238 -0
  42. data/lib/puppet/pops/types/p_meta_type.rb +14 -11
  43. data/lib/puppet/pops/types/p_object_type.rb +15 -15
  44. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +2 -2
  45. data/lib/puppet/pops/types/p_sem_ver_type.rb +2 -2
  46. data/lib/puppet/pops/types/p_sensitive_type.rb +2 -2
  47. data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
  48. data/lib/puppet/pops/types/p_timestamp_type.rb +6 -2
  49. data/lib/puppet/pops/types/p_type_set_type.rb +10 -9
  50. data/lib/puppet/pops/types/ruby_generator.rb +6 -5
  51. data/lib/puppet/pops/types/ruby_method.rb +2 -2
  52. data/lib/puppet/pops/types/string_converter.rb +1 -1
  53. data/lib/puppet/pops/types/tree_iterators.rb +250 -0
  54. data/lib/puppet/pops/types/type_calculator.rb +13 -13
  55. data/lib/puppet/pops/types/type_factory.rb +26 -7
  56. data/lib/puppet/pops/types/type_formatter.rb +9 -4
  57. data/lib/puppet/pops/types/type_parser.rb +8 -3
  58. data/lib/puppet/pops/types/type_set_reference.rb +2 -2
  59. data/lib/puppet/pops/types/types.rb +168 -109
  60. data/lib/puppet/provider/package/gem.rb +10 -9
  61. data/lib/puppet/provider/package/pip.rb +12 -3
  62. data/lib/puppet/provider/package/yum.rb +9 -1
  63. data/lib/puppet/resource/capability_finder.rb +30 -11
  64. data/lib/puppet/type/file.rb +21 -13
  65. data/lib/puppet/util/execution.rb +67 -14
  66. data/lib/puppet/util/suidmanager.rb +1 -0
  67. data/lib/puppet/version.rb +1 -1
  68. data/locales/puppet.pot +130 -66
  69. data/man/man5/puppet.conf.5 +1 -1
  70. data/spec/fixtures/unit/provider/package/yum/yum-check-update-simple.txt +1 -0
  71. data/spec/integration/parser/collection_spec.rb +40 -1
  72. data/spec/shared_contexts/types_setup.rb +41 -2
  73. data/spec/unit/agent_spec.rb +11 -0
  74. data/spec/unit/file_bucket/dipper_spec.rb +13 -4
  75. data/spec/unit/functions/all_spec.rb +97 -0
  76. data/spec/unit/functions/any_spec.rb +109 -0
  77. data/spec/unit/functions/hiera_spec.rb +5 -0
  78. data/spec/unit/functions/new_spec.rb +66 -0
  79. data/spec/unit/functions/tree_each_spec.rb +444 -0
  80. data/spec/unit/module_spec.rb +29 -0
  81. data/spec/unit/pops/serialization/serialization_spec.rb +2 -2
  82. data/spec/unit/pops/serialization/to_from_hr_spec.rb +2 -2
  83. data/spec/unit/pops/types/iterable_spec.rb +9 -9
  84. data/spec/unit/pops/types/p_init_type_spec.rb +285 -0
  85. data/spec/unit/pops/types/p_object_type_spec.rb +8 -8
  86. data/spec/unit/pops/types/p_sensitive_type_spec.rb +4 -0
  87. data/spec/unit/pops/types/p_timespan_type_spec.rb +14 -0
  88. data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -1
  89. data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
  90. data/spec/unit/pops/types/ruby_generator_spec.rb +9 -22
  91. data/spec/unit/pops/types/string_converter_spec.rb +2 -2
  92. data/spec/unit/pops/types/type_acceptor_spec.rb +2 -2
  93. data/spec/unit/pops/types/type_calculator_spec.rb +43 -38
  94. data/spec/unit/pops/types/type_factory_spec.rb +6 -6
  95. data/spec/unit/pops/types/type_formatter_spec.rb +6 -6
  96. data/spec/unit/pops/types/types_spec.rb +16 -4
  97. data/spec/unit/provider/package/gem_spec.rb +6 -6
  98. data/spec/unit/provider/package/pip_spec.rb +44 -23
  99. data/spec/unit/provider/package/puppet_gem_spec.rb +1 -1
  100. data/spec/unit/provider/package/yum_spec.rb +8 -0
  101. data/spec/unit/resource/capability_finder_spec.rb +4 -5
  102. data/spec/unit/type/file_spec.rb +19 -14
  103. data/spec/unit/util/execution_spec.rb +216 -82
  104. data/tasks/generate_ast_model.rake +10 -2
  105. metadata +15 -2
@@ -121,7 +121,7 @@ These are the modules that will be used by \fIall\fR environments\. Note that th
121
121
  The address a listening server should bind to\.
122
122
  .
123
123
  .IP "\(bu" 4
124
- \fIDefault\fR: 0\.0\.0\.0
124
+ \fIDefault\fR: *
125
125
  .
126
126
  .IP "" 0
127
127
  .
@@ -9,4 +9,5 @@ curl.i686 7.32.0-10.fc20 updates
9
9
  curl.x86_64 7.32.0-10.fc20 updates
10
10
  gawk.i686 4.1.0-3.fc20 updates
11
11
  dhclient.i686 12:4.1.1-38.P1.fc20 updates
12
+ java-1.8.0-openjdk.x86_64 1:1.8.0.131-2.b11.el7_3 updates
12
13
  selinux-policy.noarch 3.12.1-163.fc20 updates-testing
@@ -312,7 +312,46 @@ describe 'collectors' do
312
312
  MANIFEST
313
313
  end
314
314
 
315
+ context 'when overriding an already evaluated resource' do
316
+ let(:logs) { [] }
317
+ let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
318
+ let(:manifest) { <<-MANIFEST }
319
+ define foo($message) {
320
+ notify { "testing": message => $message }
321
+ }
322
+ foo { test: message => 'given' }
323
+ define delayed {
324
+ Foo <| |> { message => 'overridden' }
325
+ }
326
+ delayed {'do it now': }
327
+ MANIFEST
328
+
329
+ around(:each) do |example|
330
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
331
+ example.run
332
+ end
333
+ end
334
+
335
+ it 'and --strict=off, it silently skips the override' do
336
+ Puppet[:strict] = :off
337
+ expect_the_message_to_be(['given'], manifest)
338
+ expect(warnings).to be_empty
339
+ end
340
+
341
+ it 'and --strict=warning, it warns about the attempt to override and skips it' do
342
+ Puppet[:strict] = :warning
343
+ expect_the_message_to_be(['given'], manifest)
344
+ expect(warnings).to include(
345
+ /Attempt to override an already evaluated resource, defined at line 4, with new values at line 6/)
346
+ end
347
+
348
+ it 'and --strict=error, it fails compilation' do
349
+ Puppet[:strict] = :error
350
+ expect { compile_to_catalog(manifest) }.to raise_error(
351
+ /Attempt to override an already evaluated resource, defined at line 4, with new values at line 6/)
352
+ expect(warnings).to be_empty
353
+ end
354
+ end
315
355
  end
316
356
  end
317
-
318
357
  end
@@ -19,7 +19,7 @@ shared_context 'types_setup' do
19
19
  Puppet::Pops::Types::PIterableType,
20
20
  Puppet::Pops::Types::PIteratorType,
21
21
  Puppet::Pops::Types::PRuntimeType,
22
- Puppet::Pops::Types::PHostClassType,
22
+ Puppet::Pops::Types::PClassType,
23
23
  Puppet::Pops::Types::PResourceType,
24
24
  Puppet::Pops::Types::PPatternType,
25
25
  Puppet::Pops::Types::PEnumType,
@@ -27,7 +27,7 @@ shared_context 'types_setup' do
27
27
  Puppet::Pops::Types::PStructType,
28
28
  Puppet::Pops::Types::PTupleType,
29
29
  Puppet::Pops::Types::PCallableType,
30
- Puppet::Pops::Types::PType,
30
+ Puppet::Pops::Types::PTypeType,
31
31
  Puppet::Pops::Types::POptionalType,
32
32
  Puppet::Pops::Types::PDefaultType,
33
33
  Puppet::Pops::Types::PTypeReferenceType,
@@ -38,12 +38,51 @@ shared_context 'types_setup' do
38
38
  Puppet::Pops::Types::PTimestampType,
39
39
  Puppet::Pops::Types::PSensitiveType,
40
40
  Puppet::Pops::Types::PBinaryType,
41
+ Puppet::Pops::Types::PInitType
41
42
  ]
42
43
  end
43
44
  def all_types
44
45
  self.class.all_types
45
46
  end
46
47
 
48
+ def self.abstract_types
49
+ [ Puppet::Pops::Types::PAnyType,
50
+ Puppet::Pops::Types::PCallableType,
51
+ Puppet::Pops::Types::PEnumType,
52
+ Puppet::Pops::Types::PClassType,
53
+ Puppet::Pops::Types::PDefaultType,
54
+ Puppet::Pops::Types::PCollectionType,
55
+ Puppet::Pops::Types::PInitType,
56
+ Puppet::Pops::Types::PIterableType,
57
+ Puppet::Pops::Types::PIteratorType,
58
+ Puppet::Pops::Types::PNotUndefType,
59
+ Puppet::Pops::Types::PResourceType,
60
+ Puppet::Pops::Types::PRuntimeType,
61
+ Puppet::Pops::Types::POptionalType,
62
+ Puppet::Pops::Types::PPatternType,
63
+ Puppet::Pops::Types::PScalarType,
64
+ Puppet::Pops::Types::PScalarDataType,
65
+ Puppet::Pops::Types::PVariantType,
66
+ Puppet::Pops::Types::PUndefType,
67
+ Puppet::Pops::Types::PTypeReferenceType,
68
+ Puppet::Pops::Types::PTypeAliasType,
69
+ ]
70
+ end
71
+ def abstract_types
72
+ self.class.abstract_types
73
+ end
74
+
75
+ # Internal types. Not meaningful in pp
76
+ def self.internal_types
77
+ [ Puppet::Pops::Types::PTypeReferenceType,
78
+ Puppet::Pops::Types::PTypeAliasType,
79
+ ]
80
+ end
81
+ def internal_types
82
+ self.class.internal_types
83
+ end
84
+
85
+
47
86
  def self.scalar_data_types
48
87
  # PVariantType is also scalar data, if its types are all ScalarData
49
88
  [
@@ -217,6 +217,17 @@ describe Puppet::Agent do
217
217
  @agent.run
218
218
  end
219
219
 
220
+ it 'should exit with 1 if an exception is raised' do
221
+ client = AgentTestClient.new
222
+ AgentTestClient.expects(:new).returns client
223
+
224
+ client.expects(:run).raises(StandardError)
225
+
226
+ Kernel.expects(:fork).yields
227
+ @agent.expects(:exit).with(1)
228
+ @agent.run
229
+ end
230
+
220
231
  it "should re-raise exit happening in the child" do
221
232
  Process.stubs(:waitpid2).returns [123, (stub 'process::status', :exitstatus => -1)]
222
233
  expect { @agent.run }.to raise_error(SystemExit)
@@ -91,15 +91,24 @@ describe Puppet::FileBucket::Dipper, :uses_checksums => true do
91
91
  end
92
92
 
93
93
  it "should properly diff files on the filebucket" do
94
- file1 = make_tmp_file("OriginalContent")
95
- file2 = make_tmp_file("ModifiedContent")
94
+ file1 = make_tmp_file("OriginalContent\n")
95
+ file2 = make_tmp_file("ModifiedContent\n")
96
96
  @dipper = Puppet::FileBucket::Dipper.new(:Path => tmpdir("bucket"))
97
97
  checksum1 = @dipper.backup(file1)
98
98
  checksum2 = @dipper.backup(file2)
99
99
 
100
100
  # Diff without the context
101
- diff12 = `diff -uN #{file1} #{file2} | sed '1,2d'`
102
- diff21 = `diff -uN #{file2} #{file1} | sed '1,2d'`
101
+ # Lines we need to see match 'Content' instead of trimming diff output filter out
102
+ # surrounding noise...or hard code the check values
103
+ if Facter.value(:osfamily) == 'Solaris' &&
104
+ Puppet::Util::Package.versioncmp(Facter.value(:operatingsystemrelease), '11.0') >= 0
105
+ # Use gdiff on Solaris
106
+ diff12 = Puppet::Util::Execution.execute("gdiff -uN #{file1} #{file2}| grep Content")
107
+ diff21 = Puppet::Util::Execution.execute("gdiff -uN #{file2} #{file1}| grep Content")
108
+ else
109
+ diff12 = Puppet::Util::Execution.execute("diff -uN #{file1} #{file2}| grep Content")
110
+ diff21 = Puppet::Util::Execution.execute("diff -uN #{file2} #{file1}| grep Content")
111
+ end
103
112
 
104
113
  expect(@dipper.diff(checksum1, checksum2, nil, nil)).to include(diff12)
105
114
  expect(@dipper.diff(checksum1, nil, nil, file2)).to include(diff12)
@@ -0,0 +1,97 @@
1
+ require 'puppet'
2
+ require 'spec_helper'
3
+ require 'puppet_spec/compiler'
4
+
5
+ require 'shared_behaviours/iterative_functions'
6
+
7
+ describe 'the all method' do
8
+ include PuppetSpec::Compiler
9
+
10
+ context "should be callable as" do
11
+ it 'all on an array' do
12
+ catalog = compile_to_catalog(<<-MANIFEST)
13
+ $a = [1,2,3]
14
+ $n = $a.all |$v| { $v > 0 }
15
+ file { "$n": ensure => present }
16
+ MANIFEST
17
+
18
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
19
+ end
20
+
21
+ it 'all on an array with index' do
22
+ catalog = compile_to_catalog(<<-MANIFEST)
23
+ $a = [0,2,4]
24
+ $n = $a.all |$i, $v| { $v == $i * 2 }
25
+ file { "$n": ensure => present }
26
+ MANIFEST
27
+
28
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
29
+ end
30
+
31
+ it 'all on a hash selecting entries' do
32
+ catalog = compile_to_catalog(<<-MANIFEST)
33
+ $a = {0=>0,1=>2,2=>4}
34
+ $n = $a.all |$e| { $e[1] == $e[0]*2 }
35
+ file { "$n": ensure => present }
36
+ MANIFEST
37
+
38
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
39
+ end
40
+
41
+ it 'all on a hash selecting key and value' do
42
+ catalog = compile_to_catalog(<<-MANIFEST)
43
+ $a = {0=>0,1=>2,2=>4}
44
+ $n = $a.all |$k,$v| { $v == $k*2 }
45
+ file { "$n": ensure => present }
46
+ MANIFEST
47
+
48
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
49
+ end
50
+ end
51
+
52
+ context "produces a boolean" do
53
+ it 'true when boolean true is found' do
54
+ catalog = compile_to_catalog(<<-MANIFEST)
55
+ $a = [6,6,6]
56
+ $n = $a.all |$v| { true }
57
+ file { "$n": ensure => present }
58
+ MANIFEST
59
+
60
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
61
+ end
62
+
63
+ it 'true when truthy is found' do
64
+ catalog = compile_to_catalog(<<-MANIFEST)
65
+ $a = [6,6,6]
66
+ $n = $a.all |$v| { 42 }
67
+ file { "$n": ensure => present }
68
+ MANIFEST
69
+
70
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
71
+ end
72
+
73
+ it 'false when truthy is not found (all undef)' do
74
+ catalog = compile_to_catalog(<<-MANIFEST)
75
+ $a = [6,6,6]
76
+ $n = $a.all |$v| { undef }
77
+ file { "$n": ensure => present }
78
+ MANIFEST
79
+
80
+ expect(catalog.resource(:file, "false")['ensure']).to eq('present')
81
+ end
82
+
83
+ it 'false when truthy is not found (all false)' do
84
+ catalog = compile_to_catalog(<<-MANIFEST)
85
+ $a = [6,6,6]
86
+ $n = $a.all |$v| { false }
87
+ file { "$n": ensure => present }
88
+ MANIFEST
89
+
90
+ expect(catalog.resource(:file, "false")['ensure']).to eq('present')
91
+ end
92
+
93
+ end
94
+ it_should_behave_like 'all iterative functions argument checks', 'any'
95
+ it_should_behave_like 'all iterative functions hash handling', 'any'
96
+
97
+ end
@@ -0,0 +1,109 @@
1
+ require 'puppet'
2
+ require 'spec_helper'
3
+ require 'puppet_spec/compiler'
4
+
5
+ require 'shared_behaviours/iterative_functions'
6
+
7
+ describe 'the any method' do
8
+ include PuppetSpec::Compiler
9
+
10
+ context "should be callable as" do
11
+ it 'any on an array' do
12
+ catalog = compile_to_catalog(<<-MANIFEST)
13
+ $a = [1,2,3]
14
+ $n = $a.any |$v| { $v == 2 }
15
+ file { "$n": ensure => present }
16
+ MANIFEST
17
+
18
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
19
+ end
20
+
21
+ it 'any on an array with index' do
22
+ catalog = compile_to_catalog(<<-MANIFEST)
23
+ $a = [6,6,6]
24
+ $n = $a.any |$i, $v| { $i == 2 }
25
+ file { "$n": ensure => present }
26
+ MANIFEST
27
+
28
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
29
+ end
30
+
31
+ it 'any on a hash selecting entries' do
32
+ catalog = compile_to_catalog(<<-MANIFEST)
33
+ $a = {'a'=>'ah','b'=>'be','c'=>'ce'}
34
+ $n = $a.any |$e| { $e[1] == 'be' }
35
+ file { "$n": ensure => present }
36
+ MANIFEST
37
+
38
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
39
+ end
40
+
41
+ it 'any on a hash selecting key and value' do
42
+ catalog = compile_to_catalog(<<-MANIFEST)
43
+ $a = {'a'=>'ah','b'=>'be','c'=>'ce'}
44
+ $n = $a.any |$k, $v| { $v == 'be' }
45
+ file { "$n": ensure => present }
46
+ MANIFEST
47
+
48
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
49
+ end
50
+ end
51
+
52
+ context 'stops iteration when result is known' do
53
+ it 'true when boolean true is found' do
54
+ catalog = compile_to_catalog(<<-MANIFEST)
55
+ $a = [1,2,3]
56
+ $n = $a.any |$v| { if $v == 1 { true } else { fail("unwanted") } }
57
+ file { "$n": ensure => present }
58
+ MANIFEST
59
+
60
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
61
+ end
62
+ end
63
+
64
+ context "produces a boolean" do
65
+ it 'true when boolean true is found' do
66
+ catalog = compile_to_catalog(<<-MANIFEST)
67
+ $a = [6,6,6]
68
+ $n = $a.any |$v| { true }
69
+ file { "$n": ensure => present }
70
+ MANIFEST
71
+
72
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
73
+ end
74
+
75
+ it 'true when truthy is found' do
76
+ catalog = compile_to_catalog(<<-MANIFEST)
77
+ $a = [6,6,6]
78
+ $n = $a.any |$v| { 42 }
79
+ file { "$n": ensure => present }
80
+ MANIFEST
81
+
82
+ expect(catalog.resource(:file, "true")['ensure']).to eq('present')
83
+ end
84
+
85
+ it 'false when truthy is not found (all undef)' do
86
+ catalog = compile_to_catalog(<<-MANIFEST)
87
+ $a = [6,6,6]
88
+ $n = $a.any |$v| { undef }
89
+ file { "$n": ensure => present }
90
+ MANIFEST
91
+
92
+ expect(catalog.resource(:file, "false")['ensure']).to eq('present')
93
+ end
94
+
95
+ it 'false when truthy is not found (all false)' do
96
+ catalog = compile_to_catalog(<<-MANIFEST)
97
+ $a = [6,6,6]
98
+ $n = $a.any |$v| { false }
99
+ file { "$n": ensure => present }
100
+ MANIFEST
101
+
102
+ expect(catalog.resource(:file, "false")['ensure']).to eq('present')
103
+ end
104
+
105
+ end
106
+ it_should_behave_like 'all iterative functions argument checks', 'any'
107
+ it_should_behave_like 'all iterative functions hash handling', 'any'
108
+
109
+ end
@@ -293,6 +293,11 @@ describe 'when calling' do
293
293
  expect(func('mod::c')).to eql('mod::c (from module)')
294
294
  end
295
295
  end
296
+
297
+ it 'should not be disabled by data_binding_terminus setting' do
298
+ Puppet[:data_binding_terminus] = 'none'
299
+ expect(func('a')).to eql('first a')
300
+ end
296
301
  end
297
302
 
298
303
  context 'hiera_array' do
@@ -39,6 +39,26 @@ describe 'the new function' do
39
39
  )}.to raise_error(Puppet::Error, /expects an Integer\[1, 5\] value, got Integer\[42, 42\]/)
40
40
  end
41
41
 
42
+ it 'accepts and returns a second parameter that is an instance of the first, even when the type has no backing new_function' do
43
+ expect(eval_and_collect_notices(<<-MANIFEST)).to eql(%w(true true true true true true))
44
+ notice(undef == Undef(undef))
45
+
46
+ notice(default == Default(default))
47
+
48
+ notice(Any == Type(Any))
49
+
50
+ $b = Binary('YmluYXI=')
51
+ notice($b == Binary($b))
52
+
53
+ $t = Timestamp('2012-03-04T09:10:11.001')
54
+ notice($t == Timestamp($t))
55
+
56
+ type MyObject = Object[{attributes => {'type' => String}}]
57
+ $o = MyObject('Remote')
58
+ notice($o == MyObject($o))
59
+ MANIFEST
60
+ end
61
+
42
62
  context 'when invoked on NotUndef' do
43
63
  it 'produces an instance of the NotUndef nested type' do
44
64
  expect(compile_to_catalog(<<-MANIFEST
@@ -640,6 +660,42 @@ describe 'the new function' do
640
660
  )}.to raise_error(Puppet::Error, error_match)
641
661
  end
642
662
  end
663
+
664
+ context 'when using the optional "tree" format' do
665
+ it 'can convert a tree in flat form to a hash' do
666
+ expect(compile_to_catalog(<<-"MANIFEST"
667
+ $x = Hash.new([[[0], a],[[1,0], b],[[1,1], c],[[2,0], d]], tree)
668
+ notify { test: message => $x }
669
+ MANIFEST
670
+ )).to have_resource('Notify[test]').with_parameter(:message, { 0 => 'a', 1 => { 0 => 'b', 1=> 'c'}, 2 => {0 => 'd'} })
671
+ end
672
+
673
+ it 'preserves array in flattened tree but overwrites entries if they are present' do
674
+ expect(compile_to_catalog(<<-"MANIFEST"
675
+ $x = Hash.new([[[0], a],[[1,0], b],[[1,1], c],[[2], [overwritten, kept]], [[2,0], d]], tree)
676
+ notify { test: message => $x }
677
+ MANIFEST
678
+ )).to have_resource('Notify[test]').with_parameter(:message, { 0 => 'a', 1 => { 0 => 'b', 1=> 'c'}, 2 => ['d', 'kept'] })
679
+ end
680
+
681
+ it 'preserves hash in flattened tree but overwrites entries if they are present' do
682
+ expect(compile_to_catalog(<<-"MANIFEST"
683
+ $x = Hash.new([[[0], a],[[1,0], b],[[1,1], c],[[2], {0 => 0, kept => 1}], [[2,0], d]], tree)
684
+ notify { test: message => $x }
685
+ MANIFEST
686
+ )).to have_resource('Notify[test]').with_parameter(:message, { 0 => 'a', 1 => { 0 => 'b', 1=> 'c'}, 2 => {0=>'d', 'kept'=>1} })
687
+ end
688
+ end
689
+
690
+ context 'when using the optional "tree_hash" format' do
691
+ it 'turns array in flattened tree into hash' do
692
+ expect(compile_to_catalog(<<-"MANIFEST"
693
+ $x = Hash.new([[[0], a],[[1,0], b],[[1,1], c],[[2], [overwritten, kept]], [[2,0], d]], hash_tree)
694
+ notify { test: message => $x }
695
+ MANIFEST
696
+ )).to have_resource('Notify[test]').with_parameter(:message, { 0=>'a', 1=>{ 0=>'b', 1=>'c'}, 2=>{0=>'d', 1=>'kept'}})
697
+ end
698
+ end
643
699
  end
644
700
 
645
701
  context 'when invoked on Struct' do
@@ -691,4 +747,14 @@ describe 'the new function' do
691
747
  )).to have_resource('Notify[Boolean, true]')
692
748
  end
693
749
  end
750
+
751
+ context 'when invoked on a Type' do
752
+ it 'creates a Type from its string representation' do
753
+ expect(compile_to_catalog(<<-MANIFEST
754
+ $x = Type.new('Integer[3,10]')
755
+ notify { "${type($x)}": }
756
+ MANIFEST
757
+ )).to have_resource('Notify[Type[Integer[3, 10]]]')
758
+ end
759
+ end
694
760
  end