puppet 3.7.5 → 3.8.1

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +5 -5
  3. data/lib/hiera/puppet_function.rb +15 -4
  4. data/lib/puppet.rb +5 -2
  5. data/lib/puppet/application/agent.rb +5 -0
  6. data/lib/puppet/application/apply.rb +5 -0
  7. data/lib/puppet/application/device.rb +8 -3
  8. data/lib/puppet/application/master.rb +5 -0
  9. data/lib/puppet/defaults.rb +8 -0
  10. data/lib/puppet/error.rb +27 -1
  11. data/lib/puppet/file_system.rb +13 -0
  12. data/lib/puppet/file_system/file19windows.rb +8 -0
  13. data/lib/puppet/file_system/file_impl.rb +4 -0
  14. data/lib/puppet/file_system/memory_impl.rb +4 -0
  15. data/lib/puppet/functions.rb +25 -3
  16. data/lib/puppet/functions/defined.rb +130 -0
  17. data/lib/puppet/functions/hiera_include.rb +1 -1
  18. data/lib/puppet/node/environment.rb +4 -0
  19. data/lib/puppet/parser/compiler.rb +5 -2
  20. data/lib/puppet/parser/functions/defined.rb +26 -1
  21. data/lib/puppet/parser/functions/file.rb +3 -1
  22. data/lib/puppet/parser/templatewrapper.rb +2 -1
  23. data/lib/puppet/pops.rb +5 -0
  24. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  25. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  26. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  27. data/lib/puppet/pops/evaluator/evaluator_impl.rb +43 -28
  28. data/lib/puppet/pops/evaluator/runtime3_support.rb +9 -5
  29. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  30. data/lib/puppet/pops/issue_reporter.rb +42 -16
  31. data/lib/puppet/pops/issues.rb +96 -0
  32. data/lib/puppet/pops/loader/module_loaders.rb +3 -1
  33. data/lib/puppet/pops/loaders.rb +6 -4
  34. data/lib/puppet/pops/migration/migration_checker.rb +45 -0
  35. data/lib/puppet/pops/model/factory.rb +1 -1
  36. data/lib/puppet/pops/model/model_meta.rb +1 -1
  37. data/lib/puppet/pops/parser/egrammar.ra +1 -1
  38. data/lib/puppet/pops/parser/eparser.rb +1 -1
  39. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  40. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  41. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  42. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  43. data/lib/puppet/pops/parser/lexer2.rb +8 -8
  44. data/lib/puppet/pops/parser/lexer_support.rb +46 -20
  45. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  46. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  47. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  48. data/lib/puppet/pops/types/type_factory.rb +67 -14
  49. data/lib/puppet/pops/types/type_parser.rb +22 -13
  50. data/lib/puppet/pops/types/types.rb +21 -3
  51. data/lib/puppet/pops/types/types_meta.rb +13 -2
  52. data/lib/puppet/pops/validation.rb +25 -2
  53. data/lib/puppet/pops/validation/checker4_0.rb +25 -5
  54. data/lib/puppet/provider/group/windows_adsi.rb +18 -6
  55. data/lib/puppet/provider/mount/parsed.rb +145 -2
  56. data/lib/puppet/provider/package/pip.rb +4 -5
  57. data/lib/puppet/provider/package/zypper.rb +17 -7
  58. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +35 -10
  59. data/lib/puppet/provider/service/init.rb +7 -0
  60. data/lib/puppet/provider/user/windows_adsi.rb +8 -1
  61. data/lib/puppet/provider/zpool/zpool.rb +7 -2
  62. data/lib/puppet/resource.rb +1 -1
  63. data/lib/puppet/type/group.rb +1 -1
  64. data/lib/puppet/type/mount.rb +14 -3
  65. data/lib/puppet/type/scheduled_task.rb +21 -6
  66. data/lib/puppet/util/log.rb +50 -8
  67. data/lib/puppet/util/log/destinations.rb +23 -2
  68. data/lib/puppet/util/logging.rb +37 -1
  69. data/lib/puppet/util/windows/adsi.rb +36 -11
  70. data/lib/puppet/version.rb +1 -1
  71. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  72. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  73. data/spec/integration/parser/collector_spec.rb +7 -0
  74. data/spec/integration/parser/future_compiler_spec.rb +9 -0
  75. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  76. data/spec/unit/file_system_spec.rb +38 -0
  77. data/spec/unit/functions/defined_spec.rb +291 -0
  78. data/spec/unit/functions/hiera_spec.rb +8 -6
  79. data/spec/unit/functions4_spec.rb +97 -2
  80. data/spec/unit/parser/functions/file_spec.rb +8 -2
  81. data/spec/unit/parser/functions/template_spec.rb +1 -1
  82. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  83. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  84. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +61 -8
  85. data/spec/unit/pops/issues_spec.rb +16 -16
  86. data/spec/unit/pops/loaders/module_loaders_spec.rb +5 -0
  87. data/spec/unit/pops/migration_spec.rb +180 -0
  88. data/spec/unit/pops/parser/lexer2_spec.rb +152 -1
  89. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  90. data/spec/unit/pops/transformer/transform_calls_spec.rb +1 -1
  91. data/spec/unit/pops/types/type_calculator_spec.rb +204 -11
  92. data/spec/unit/pops/validation_spec.rb +66 -0
  93. data/spec/unit/provider/group/windows_adsi_spec.rb +65 -1
  94. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  95. data/spec/unit/provider/package/pip_spec.rb +19 -7
  96. data/spec/unit/provider/package/zypper_spec.rb +25 -14
  97. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  98. data/spec/unit/provider/service/base_spec.rb +42 -31
  99. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  100. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  101. data/spec/unit/provider/service/init_spec.rb +18 -0
  102. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  103. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  104. data/spec/unit/provider/user/windows_adsi_spec.rb +21 -0
  105. data/spec/unit/provider/zpool/zpool_spec.rb +47 -10
  106. data/spec/unit/util/log_spec.rb +113 -0
  107. data/spec/unit/util/windows/adsi_spec.rb +106 -26
  108. metadata +10 -2
@@ -15,7 +15,7 @@ describe "the 'file' function" do
15
15
 
16
16
  def with_file_content(content)
17
17
  path = tmpfile('file-function')
18
- file = File.new(path, 'w')
18
+ file = File.new(path, 'wb')
19
19
  file.sync = true
20
20
  file.print content
21
21
  yield path
@@ -23,7 +23,13 @@ describe "the 'file' function" do
23
23
 
24
24
  it "should read a file" do
25
25
  with_file_content('file content') do |name|
26
- scope.function_file([name]).should == "file content"
26
+ expect(scope.function_file([name])).to eq("file content")
27
+ end
28
+ end
29
+
30
+ it "should read a file keeping line endings intact" do
31
+ with_file_content("file content\r\n") do |name|
32
+ expect(scope.function_file([name])).to eq("file content\r\n")
27
33
  end
28
34
  end
29
35
 
@@ -82,7 +82,7 @@ describe "the template function" do
82
82
  end
83
83
 
84
84
  def eval_template(content)
85
- File.stubs(:read).with("template").returns(content)
85
+ Puppet::FileSystem.stubs(:read_preserve_line_endings).with("template").returns(content)
86
86
  Puppet::Parser::Files.stubs(:find_template).returns("template")
87
87
  scope.function_template(['template'])
88
88
  end
@@ -111,7 +111,7 @@ describe Puppet::Parser::TemplateWrapper do
111
111
  Puppet::Parser::Files.stubs(:find_template).
112
112
  with(name, anything()).
113
113
  returns(full_name)
114
- File.stubs(:read).with(full_name).returns(contents)
114
+ Puppet::FileSystem.stubs(:read_preserve_line_endings).with(full_name).returns(contents)
115
115
 
116
116
  full_name
117
117
  end
@@ -400,6 +400,25 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl/AccessOperator' do
400
400
  expect {evaluate(expr)}.to raise_error(/Resource not found: File\['x'\]/)
401
401
  end
402
402
 
403
+ # NotUndef Type
404
+ #
405
+ it 'produces a NotUndef instance' do
406
+ type_expr = fqr('NotUndef')
407
+ expect(evaluate(type_expr)).to eql(Puppet::Pops::Types::TypeFactory.not_undef())
408
+ end
409
+
410
+ it 'produces a NotUndef instance with contained type' do
411
+ type_expr = fqr('NotUndef')[fqr('Integer')]
412
+ tf = Puppet::Pops::Types::TypeFactory
413
+ expect(evaluate(type_expr)).to eql(tf.not_undef(tf.integer))
414
+ end
415
+
416
+ it 'produces a NotUndef instance with String type when given a literal String' do
417
+ type_expr = fqr('NotUndef')[literal('hey')]
418
+ tf = Puppet::Pops::Types::TypeFactory
419
+ expect(evaluate(type_expr)).to eql(tf.not_undef(tf.string('hey')))
420
+ end
421
+
403
422
  # Type Type
404
423
  #
405
424
  it 'creates a Type instance when applied to a Type' do
@@ -78,6 +78,9 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
78
78
  "[1,2,3] != [1,2,3]" => false,
79
79
  "[1,2,3][2]" => 3,
80
80
  "[1,2,3] + [4,5]" => [1,2,3,4,5],
81
+ "[1,2,3, *[4,5]]" => [1,2,3,4,5],
82
+ "[1,2,3, (*[4,5])]" => [1,2,3,4,5],
83
+ "[1,2,3, ((*[4,5]))]" => [1,2,3,4,5],
81
84
  "[1,2,3] + [[4,5]]" => [1,2,3,[4,5]],
82
85
  "[1,2,3] + 4" => [1,2,3,4],
83
86
  "[1,2,3] << [4,5]" => [1,2,3,[4,5]],
@@ -235,6 +238,8 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
235
238
  "$x = Pattern['a.*'] a =~ $x" => true,
236
239
  "1 =~ Integer" => true,
237
240
  "1 !~ Integer" => false,
241
+ "undef =~ NotUndef" => false,
242
+ "undef !~ NotUndef" => true,
238
243
  "[1,2,3] =~ Array[Integer[1,10]]" => true,
239
244
  }.each do |source, result|
240
245
  it "should parse and evaluate the expression '#{source}' to #{result}" do
@@ -316,7 +321,7 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
316
321
  end
317
322
 
318
323
  {
319
- 'Any' => ['Data', 'Scalar', 'Numeric', 'Integer', 'Float', 'Boolean', 'String', 'Pattern', 'Collection',
324
+ 'Any' => ['NotUndef', 'Data', 'Scalar', 'Numeric', 'Integer', 'Float', 'Boolean', 'String', 'Pattern', 'Collection',
320
325
  'Array', 'Hash', 'CatalogEntry', 'Resource', 'Class', 'Undef', 'File', 'NotYetKnownResourceType'],
321
326
 
322
327
  # Note, Data > Collection is false (so not included)
@@ -473,6 +478,7 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
473
478
  "unless false {5}" => 5,
474
479
  "unless true {5}" => nil,
475
480
  "unless true {2} else {5}" => 5,
481
+ "unless true {} else {5}" => 5,
476
482
  "$a = if true {5} $a" => 5,
477
483
  "$a = if false {5} $a" => nil,
478
484
  "$a = if false {2} else {5} $a" => 5,
@@ -510,12 +516,31 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
510
516
  "case ringo {
511
517
  *[paul, john, ringo, george] : { 'beatle' } }" => 'beatle',
512
518
 
519
+ "case ringo {
520
+ (*[paul, john, ringo, george]) : { 'beatle' } }" => 'beatle',
521
+
513
522
  "case undef {
514
523
  undef : { 'yes' } }" => 'yes',
515
524
 
516
525
  "case undef {
517
526
  *undef : { 'no' }
518
527
  default :{ 'yes' }}" => 'yes',
528
+
529
+ "case [green, 2, whatever] {
530
+ [/ee/, Integer[0,10], default] : { 'yes' }
531
+ default :{ 'no' }}" => 'yes',
532
+
533
+ "case [green, 2, whatever] {
534
+ default :{ 'no' }
535
+ [/ee/, Integer[0,10], default] : { 'yes' }}" => 'yes',
536
+
537
+ "case {a=>1, b=>2, whatever=>3, extra => ignored} {
538
+ { a => Integer[0,5],
539
+ b => Integer[0,5],
540
+ whatever => default
541
+ } : { 'yes' }
542
+ default : { 'no' }}" => 'yes',
543
+
519
544
  }.each do |source, result|
520
545
  it "should parse and evaluate the expression '#{source}' to #{result}" do
521
546
  parser.evaluate_string(scope, source, __FILE__).should == result
@@ -532,8 +557,22 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
532
557
  "'banana' ? { /.*(ana).*/ => $1 }" => 'ana',
533
558
  "[2] ? { Array[String] => yes, Array => yes}" => 'yes',
534
559
  "ringo ? *[paul, john, ringo, george] => 'beatle'" => 'beatle',
560
+ "ringo ? (*[paul, john, ringo, george]) => 'beatle'"=> 'beatle',
535
561
  "undef ? undef => 'yes'" => 'yes',
536
562
  "undef ? {*undef => 'no', default => 'yes'}" => 'yes',
563
+
564
+ "[green, 2, whatever] ? {
565
+ [/ee/, Integer[0,10], default
566
+ ] => 'yes',
567
+ default => 'no'}" => 'yes',
568
+
569
+ "{a=>1, b=>2, whatever=>3, extra => ignored} ?
570
+ {{ a => Integer[0,5],
571
+ b => Integer[0,5],
572
+ whatever => default
573
+ } => 'yes',
574
+ default => 'no' }" => 'yes',
575
+
537
576
  }.each do |source, result|
538
577
  it "should parse and evaluate the expression '#{source}' to #{result}" do
539
578
  parser.evaluate_string(scope, source, __FILE__).should == result
@@ -700,6 +739,8 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
700
739
  "'abc'[x]" => "The value 'x' cannot be converted to Numeric",
701
740
  "'abc'[1.0]" => "A String[] cannot use Float where Integer is expected",
702
741
  "'abc'[1,2,3]" => "String supports [] with one or two arguments. Got 3",
742
+ "NotUndef[0]" => 'NotUndef-Type[] argument must be a Type or a String. Got Fixnum',
743
+ "NotUndef[a,b]" => 'NotUndef-Type[] accepts 0 to 1 arguments. Got 2',
703
744
  "Resource[0]" => 'First argument to Resource[] must be a resource type or a String. Got Integer',
704
745
  "Resource[a, 0]" => 'Error creating type specialization of a Resource-Type, Cannot use Integer where a resource title String is expected',
705
746
  "File[0]" => 'Error creating type specialization of a File-Type, Cannot use Integer where a resource title String is expected',
@@ -899,6 +940,8 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
899
940
  'sprintf( "x%iy", $a )' => "x10y",
900
941
  # unfolds
901
942
  'sprintf( *["x%iy", $a] )' => "x10y",
943
+ '( *["x%iy", $a] ).sprintf' => "x10y",
944
+ '((*["x%iy", $a])).sprintf' => "x10y",
902
945
  '"x%iy".sprintf( $a )' => "x10y",
903
946
  '$b.reduce |$memo,$x| { $memo + $x }' => 6,
904
947
  'reduce($b) |$memo,$x| { $memo + $x }' => 6,
@@ -1099,7 +1142,7 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1099
1142
  end
1100
1143
 
1101
1144
  it "a lex error should be raised for '$foo::::bar'" do
1102
- expect { parser.evaluate_string(scope, "$foo::::bar") }.to raise_error(Puppet::LexError, /Illegal fully qualified name at line 1:7/)
1145
+ expect { parser.evaluate_string(scope, "$foo::::bar") }.to raise_error(Puppet::ParseErrorWithIssue, /Illegal fully qualified name at line 1:7/)
1103
1146
  end
1104
1147
 
1105
1148
  { '$a = $0' => nil,
@@ -1238,6 +1281,16 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1238
1281
  parser.evaluate_string(scope, src).should == "Hello Fjodor"
1239
1282
  end
1240
1283
 
1284
+ it "parses interpolated heredoc expression with escapes" do
1285
+ src = <<-CODE
1286
+ $name = 'Fjodor'
1287
+ @("END")
1288
+ Hello\\ \\$name
1289
+ |- END
1290
+ CODE
1291
+ parser.evaluate_string(scope, src).should == "Hello\\ \\Fjodor"
1292
+ end
1293
+
1241
1294
  end
1242
1295
  context "Handles Deprecations and Discontinuations" do
1243
1296
  it 'of import statements' do
@@ -1266,14 +1319,14 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1266
1319
  end
1267
1320
 
1268
1321
  it 'for non r-value producing define' do
1269
- Puppet.expects(:err).with("Invalid use of expression. A 'define' expression does not produce a value at line 1:6")
1270
- Puppet.expects(:err).with("Classes, definitions, and nodes may only appear at toplevel or inside other classes at line 1:6")
1322
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => "Invalid use of expression. A 'define' expression does not produce a value", :line => 1, :pos => 6))
1323
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => 'Classes, definitions, and nodes may only appear at toplevel or inside other classes', :line => 1, :pos => 6))
1271
1324
  expect { parser.parse_string("$a = define foo { }", nil) }.to raise_error(/2 errors/)
1272
1325
  end
1273
1326
 
1274
1327
  it 'for non r-value producing class' do
1275
- Puppet.expects(:err).with("Invalid use of expression. A Host Class Definition does not produce a value at line 1:6")
1276
- Puppet.expects(:err).with("Classes, definitions, and nodes may only appear at toplevel or inside other classes at line 1:6")
1328
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => 'Invalid use of expression. A Host Class Definition does not produce a value', :line => 1, :pos => 6))
1329
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => 'Classes, definitions, and nodes may only appear at toplevel or inside other classes', :line => 1, :pos => 6))
1277
1330
  expect { parser.parse_string("$a = class foo { }", nil) }.to raise_error(/2 errors/)
1278
1331
  end
1279
1332
 
@@ -1287,8 +1340,8 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
1287
1340
  end
1288
1341
 
1289
1342
  it 'for multiple errors with a summary exception' do
1290
- Puppet.expects(:err).with("Invalid use of expression. A Node Definition does not produce a value at line 1:6")
1291
- Puppet.expects(:err).with("Classes, definitions, and nodes may only appear at toplevel or inside other classes at line 1:6")
1343
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => 'Invalid use of expression. A Node Definition does not produce a value', :line => 1, :pos => 6))
1344
+ Puppet::Util::Log.expects(:create).with(has_entries(:level => :err, :message => 'Classes, definitions, and nodes may only appear at toplevel or inside other classes', :line => 1, :pos => 6))
1292
1345
  expect { parser.parse_string("$a = node x { }",nil) }.to raise_error(/2 errors/)
1293
1346
  end
1294
1347
 
@@ -62,19 +62,19 @@ describe "Puppet::Pops::IssueReporter" do
62
62
  end
63
63
 
64
64
  it "emits warnings if told to emit them" do
65
- Puppet.expects(:warning).twice.with(regexp_matches(/warning1|deprecation1/))
65
+ Puppet::Log.expects(:create).twice.with(has_entries(:level => :warning, :message => regexp_matches(/warning1|deprecation1/)))
66
66
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
67
67
  end
68
68
 
69
69
  it "does not emit warnings if not told to emit them" do
70
- Puppet.expects(:warning).never
70
+ Puppet::Log.expects(:create).never
71
71
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, {})
72
72
  end
73
73
 
74
74
  it "emits no warnings if :max_warnings is 0" do
75
75
  acceptor.accept( warning(2) )
76
76
  Puppet[:max_warnings] = 0
77
- Puppet.expects(:warning).once.with(regexp_matches(/deprecation1/))
77
+ Puppet::Log.expects(:create).once.with(has_entries(:level => :warning, :message => regexp_matches(/deprecation1/)))
78
78
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
79
79
  end
80
80
 
@@ -82,20 +82,20 @@ describe "Puppet::Pops::IssueReporter" do
82
82
  acceptor.accept( warning(2) )
83
83
  acceptor.accept( warning(3) )
84
84
  Puppet[:max_warnings] = 1
85
- Puppet.expects(:warning).twice.with(regexp_matches(/warning1|deprecation1/))
85
+ Puppet::Log.expects(:create).twice.with(has_entries(:level => :warning, :message => regexp_matches(/warning1|deprecation1/)))
86
86
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
87
87
  end
88
88
 
89
89
  it "does not emit more deprecations warnings than the max deprecation warnings" do
90
90
  acceptor.accept( deprecation(2) )
91
91
  Puppet[:max_deprecations] = 0
92
- Puppet.expects(:warning).once.with(regexp_matches(/warning1/))
92
+ Puppet::Log.expects(:create).once.with(has_entries(:level => :warning, :message => regexp_matches(/warning1/)))
93
93
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
94
94
  end
95
95
 
96
96
  it "does not emit deprecation warnings, but does emit regular warnings if disable_warnings includes deprecations" do
97
97
  Puppet[:disable_warnings] = 'deprecations'
98
- Puppet.expects(:warning).once.with(regexp_matches(/warning1/))
98
+ Puppet::Log.expects(:create).once.with(has_entries(:level => :warning, :message => regexp_matches(/warning1/)))
99
99
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
100
100
  end
101
101
  end
@@ -103,7 +103,7 @@ describe "Puppet::Pops::IssueReporter" do
103
103
  context "given errors" do
104
104
  it "logs nothing, but raises the given :message if :emit_errors is repressing error logging" do
105
105
  acceptor.accept( error(1) )
106
- Puppet.expects(:err).never
106
+ Puppet::Log.expects(:create).never
107
107
  expect do
108
108
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_errors => false, :message => 'special'})
109
109
  end.to raise_error(Puppet::ParseError, 'special')
@@ -111,7 +111,7 @@ describe "Puppet::Pops::IssueReporter" do
111
111
 
112
112
  it "prefixes :message if a single error is raised" do
113
113
  acceptor.accept( error(1) )
114
- Puppet.expects(:err).never
114
+ Puppet::Log.expects(:create).never
115
115
  expect do
116
116
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :message => 'special'})
117
117
  end.to raise_error(Puppet::ParseError, /special error1/)
@@ -119,7 +119,7 @@ describe "Puppet::Pops::IssueReporter" do
119
119
 
120
120
  it "logs nothing and raises immediately if there is only one error" do
121
121
  acceptor.accept( error(1) )
122
- Puppet.expects(:err).never
122
+ Puppet::Log.expects(:create).never
123
123
  expect do
124
124
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { })
125
125
  end.to raise_error(Puppet::ParseError, /error1/)
@@ -129,7 +129,7 @@ describe "Puppet::Pops::IssueReporter" do
129
129
  acceptor.accept( error(1) )
130
130
  acceptor.accept( error(2) )
131
131
  Puppet[:max_errors] = 0
132
- Puppet.expects(:err).never
132
+ Puppet::Log.expects(:create).never
133
133
  expect do
134
134
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { })
135
135
  end.to raise_error(Puppet::ParseError, /error1/)
@@ -138,7 +138,7 @@ describe "Puppet::Pops::IssueReporter" do
138
138
  it "logs the :message if there is more than one allowed error" do
139
139
  acceptor.accept( error(1) )
140
140
  acceptor.accept( error(2) )
141
- Puppet.expects(:err).times(3).with(regexp_matches(/error1|error2|special/))
141
+ Puppet::Log.expects(:create).times(3).with(has_entries(:level => :err, :message => regexp_matches(/error1|error2|special/)))
142
142
  expect do
143
143
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :message => 'special'})
144
144
  end.to raise_error(Puppet::ParseError, /Giving up/)
@@ -149,7 +149,7 @@ describe "Puppet::Pops::IssueReporter" do
149
149
  acceptor.accept( error(2) )
150
150
  acceptor.accept( error(3) )
151
151
  Puppet[:max_errors] = 2
152
- Puppet.expects(:err).times(2).with(regexp_matches(/error1|error2/))
152
+ Puppet::Log.expects(:create).times(2).with(has_entries(:level => :err, :message => regexp_matches(/error1|error2/)))
153
153
  expect do
154
154
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { })
155
155
  end.to raise_error(Puppet::ParseError, /3 errors.*Giving up/)
@@ -160,7 +160,7 @@ describe "Puppet::Pops::IssueReporter" do
160
160
  acceptor.accept( error(2) )
161
161
  acceptor.accept( error(3) )
162
162
  Puppet[:max_errors] = 4
163
- Puppet.expects(:err).times(3).with(regexp_matches(/error[123]/))
163
+ Puppet::Log.expects(:create).times(3).with(has_entries(:level => :err, :message => regexp_matches(/error[123]/)))
164
164
  expect do
165
165
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { })
166
166
  end.to raise_error(Puppet::ParseError, /3 errors.*Giving up/)
@@ -170,7 +170,7 @@ describe "Puppet::Pops::IssueReporter" do
170
170
  acceptor.accept( error(1) )
171
171
  acceptor.accept( error(2) )
172
172
  Puppet[:disable_warnings] = 'deprecations'
173
- Puppet.expects(:err).times(2).with(regexp_matches(/error1|error2/))
173
+ Puppet::Log.expects(:create).times(2).with(has_entries(:level => :err, :message => regexp_matches(/error1|error2/)))
174
174
  expect do
175
175
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { })
176
176
  end.to raise_error(Puppet::ParseError, /Giving up/)
@@ -186,8 +186,8 @@ describe "Puppet::Pops::IssueReporter" do
186
186
  acceptor.accept( error(3) )
187
187
  acceptor.accept( deprecation(1) )
188
188
  Puppet[:max_errors] = 2
189
- Puppet.expects(:warning).twice.with(regexp_matches(/warning1|deprecation1/))
190
- Puppet.expects(:err).times(2).with(regexp_matches(/error[123]/))
189
+ Puppet::Log.expects(:create).twice.with(has_entries(:level => :warning, :message => regexp_matches(/warning1|deprecation1/)))
190
+ Puppet::Log.expects(:create).twice.with(has_entries(:level => :err, :message => regexp_matches(/error[123]/)))
191
191
  expect do
192
192
  Puppet::Pops::IssueReporter.assert_and_report(acceptor, { :emit_warnings => true })
193
193
  end.to raise_error(Puppet::ParseError, /3 errors.*2 warnings.*Giving up/)
@@ -57,6 +57,11 @@ describe 'FileBased module loader' do
57
57
  expect(function.is_a?(Puppet::Functions::Function)).to eq(true)
58
58
  end
59
59
 
60
+ it 'system loader has itself as private loader' do
61
+ module_loader = Puppet::Pops::Loader::ModuleLoaders.system_loader_from(static_loader, loaders)
62
+ expect(module_loader.private_loader).to be(module_loader)
63
+ end
64
+
60
65
  it 'makes parent loader win over entries in child' do
61
66
  module_dir = dir_containing('testmodule', {
62
67
  'lib' => { 'puppet' => { 'functions' => { 'testmodule' => {
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet/pops'
4
+ require 'puppet/pops/evaluator/evaluator_impl'
5
+ require 'puppet/loaders'
6
+ require 'puppet_spec/pops'
7
+ require 'puppet_spec/scope'
8
+ require 'puppet/parser/e4_parser_adapter'
9
+
10
+ describe 'Puppet::Pops::MigrationMigrationChecker' do
11
+ include PuppetSpec::Pops
12
+ include PuppetSpec::Scope
13
+ before(:each) do
14
+ Puppet[:strict_variables] = true
15
+
16
+ # These must be set since the 3x logic switches some behaviors on these even if the tests explicitly
17
+ # use the 4x parser and evaluator.
18
+ #
19
+ Puppet[:parser] = 'future'
20
+
21
+ # Puppetx cannot be loaded until the correct parser has been set (injector is turned off otherwise)
22
+ require 'puppetx'
23
+
24
+ # Tests needs a known configuration of node/scope/compiler since it parses and evaluates
25
+ # snippets as the compiler will evaluate them, butwithout the overhead of compiling a complete
26
+ # catalog for each tested expression.
27
+ #
28
+ @parser = Puppet::Pops::Parser::EvaluatingParser.new
29
+ @node = Puppet::Node.new('node.example.com')
30
+ @node.environment = Puppet::Node::Environment.create(:testing, [])
31
+ @compiler = Puppet::Parser::Compiler.new(@node)
32
+ @scope = Puppet::Parser::Scope.new(@compiler)
33
+ @scope.source = Puppet::Resource::Type.new(:node, 'node.example.com')
34
+ @scope.parent = @compiler.topscope
35
+ end
36
+
37
+ let(:scope) { @scope }
38
+
39
+ describe "when there is no MigrationChecker in the PuppetContext" do
40
+ it "a null implementation of the MigrationChecker gets created (once per impl that needs one)" do
41
+ migration_checker = Puppet::Pops::Migration::MigrationChecker.new()
42
+ Puppet::Pops::Migration::MigrationChecker.expects(:new).at_least_once.returns(migration_checker)
43
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "1", __FILE__).should == 1
44
+ Puppet::Pops::Migration::MigrationChecker.unstub(:new)
45
+ end
46
+ end
47
+
48
+ describe "when there is a MigrationChecker in the Puppet Context" do
49
+ it "does not create any MigrationChecker instances when parsing and evaluating" do
50
+ migration_checker = mock()
51
+ Puppet::Pops::Migration::MigrationChecker.expects(:new).never
52
+ Puppet.override({:migration_checker => migration_checker}, "test-context") do
53
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "true", __FILE__)
54
+ end
55
+ Puppet::Pops::Migration::MigrationChecker.unstub(:new)
56
+ end
57
+ end
58
+
59
+ describe "when validating parsed code" do
60
+ it "is called for each integer" do
61
+ migration_checker = mock()
62
+ migration_checker.expects(:report_ambiguous_integer).times(3)
63
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
64
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "$a = [1,2,3]", __FILE__)
65
+ end
66
+ end
67
+
68
+ it "is called for each float" do
69
+ migration_checker = mock()
70
+ migration_checker.expects(:report_ambiguous_float).times(3)
71
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
72
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "$a = [1.0,2.0,3.1415]", __FILE__)
73
+ end
74
+ end
75
+
76
+ it "last expressions in blocks are checked" do
77
+ migration_checker = mock()
78
+ migration_checker.expects(:report_array_last_in_block).twice # the program itself is a block too
79
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
80
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "$b = {} if true { $a = $b [false] }", __FILE__)
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ describe "when evaluating code" do
87
+ it "is called for boolean coercion of String" do
88
+ migration_checker = mock()
89
+ migration_checker.expects(:report_empty_string_true).times(2)
90
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
91
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "$a = ('a' and '')", __FILE__)
92
+ end
93
+ end
94
+
95
+ context "with a case expression" do
96
+ it "the test expression is checked for UC_bareword" do
97
+ migration_checker = mock()
98
+ migration_checker.expects(:report_uc_bareword_type).once
99
+ migration_checker.expects(:report_option_type_mismatch).once
100
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
101
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "case Foo { 'Foo': {}}", __FILE__)
102
+ end
103
+ end
104
+
105
+ it "all case options are checked for UC_bareword" do
106
+ migration_checker = mock()
107
+ migration_checker.expects(:report_uc_bareword_type).times(4)
108
+ migration_checker.expects(:report_option_type_mismatch).times(4)
109
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
110
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope,
111
+ "case true { Foo, Bar: {} Fee, 'not': {}}", __FILE__)
112
+ end
113
+ end
114
+ end
115
+
116
+ context "with a selector expression" do
117
+ it "the test expression is checked for UC_bareword" do
118
+ migration_checker = mock()
119
+ migration_checker.expects(:report_uc_bareword_type).once
120
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
121
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "Foo ? { default => false}", __FILE__)
122
+ end
123
+ end
124
+
125
+ it "all options are checked for UC_bareword" do
126
+ migration_checker = mock()
127
+ migration_checker.expects(:report_uc_bareword_type).times(3)
128
+ migration_checker.expects(:report_option_type_mismatch).times(3)
129
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
130
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope,
131
+ "true ? { Foo => false, Bar => false, 'not' => false, default => true}", __FILE__)
132
+ end
133
+ end
134
+ end
135
+
136
+ context "with a comparison of" do
137
+ ['==', '!=', ].each do |operator|
138
+ it "'a' #{operator} 'b'" do
139
+ migration_checker = mock()
140
+ migration_checker.expects(:report_uc_bareword_type).twice
141
+ migration_checker.expects(:report_equality_type_mismatch).once
142
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
143
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "'a' #{operator} 'b'", __FILE__)
144
+ end
145
+ end
146
+ end
147
+
148
+ ['<', '>', '<=', '>='].each do |operator|
149
+ it "'a' #{operator} 'b'" do
150
+ migration_checker = mock()
151
+ migration_checker.expects(:report_uc_bareword_type).twice
152
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
153
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "'a' #{operator} 'b'", __FILE__)
154
+ end
155
+ end
156
+ end
157
+
158
+ ['=~', '!~'].each do |operator|
159
+ it "'a' #{operator} /.*/" do
160
+ migration_checker = mock()
161
+ migration_checker.expects(:report_uc_bareword_type).once
162
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
163
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "'a' #{operator} /.*/", __FILE__)
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ context "with an in operator" do
170
+ it "'a' in [true,false]" do
171
+ migration_checker = mock()
172
+ migration_checker.expects(:report_uc_bareword_type).once
173
+ migration_checker.expects(:report_in_expression).once
174
+ Puppet.override({:migration_checker => migration_checker}, "migration-context") do
175
+ Puppet::Pops::Parser::EvaluatingParser.new.evaluate_string(scope, "'a' in [true, false]", __FILE__)
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end