puppet 5.5.10-x86-mingw32 → 5.5.12-x86-mingw32

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +30 -0
  3. data/Gemfile.lock +13 -13
  4. data/lib/puppet.rb +4 -4
  5. data/lib/puppet/application.rb +1 -1
  6. data/lib/puppet/application/filebucket.rb +6 -1
  7. data/lib/puppet/configurer.rb +4 -7
  8. data/lib/puppet/confine/boolean.rb +45 -0
  9. data/lib/puppet/confine/false.rb +7 -1
  10. data/lib/puppet/confine/true.rb +7 -1
  11. data/lib/puppet/defaults.rb +0 -18
  12. data/lib/puppet/functions/call.rb +2 -1
  13. data/lib/puppet/network/http/connection.rb +15 -5
  14. data/lib/puppet/pops/issues.rb +4 -0
  15. data/lib/puppet/pops/model/factory.rb +38 -4
  16. data/lib/puppet/pops/parser/egrammar.ra +2 -2
  17. data/lib/puppet/pops/parser/eparser.rb +628 -627
  18. data/lib/puppet/pops/parser/heredoc_support.rb +17 -7
  19. data/lib/puppet/pops/parser/lexer2.rb +6 -1
  20. data/lib/puppet/pops/parser/locator.rb +106 -86
  21. data/lib/puppet/pops/parser/parser_support.rb +11 -2
  22. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  23. data/lib/puppet/provider/file/windows.rb +49 -1
  24. data/lib/puppet/provider/group/windows_adsi.rb +4 -1
  25. data/lib/puppet/provider/mount/parsed.rb +3 -0
  26. data/lib/puppet/provider/package/windows.rb +5 -1
  27. data/lib/puppet/provider/service/systemd.rb +1 -1
  28. data/lib/puppet/provider/service/upstart.rb +8 -6
  29. data/lib/puppet/settings.rb +10 -5
  30. data/lib/puppet/transaction.rb +8 -6
  31. data/lib/puppet/transaction/resource_harness.rb +1 -0
  32. data/lib/puppet/type/exec.rb +27 -5
  33. data/lib/puppet/type/file/mode.rb +6 -1
  34. data/lib/puppet/type/filebucket.rb +12 -8
  35. data/lib/puppet/util/command_line.rb +5 -1
  36. data/lib/puppet/util/log.rb +7 -2
  37. data/lib/puppet/util/windows/security.rb +29 -8
  38. data/lib/puppet/version.rb +1 -1
  39. data/locales/puppet.pot +196 -151
  40. data/man/man5/puppet.conf.5 +2 -2
  41. data/man/man8/puppet-agent.8 +1 -1
  42. data/man/man8/puppet-apply.8 +1 -1
  43. data/man/man8/puppet-ca.8 +1 -1
  44. data/man/man8/puppet-catalog.8 +1 -1
  45. data/man/man8/puppet-cert.8 +1 -1
  46. data/man/man8/puppet-certificate.8 +1 -1
  47. data/man/man8/puppet-certificate_request.8 +1 -1
  48. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  49. data/man/man8/puppet-config.8 +1 -1
  50. data/man/man8/puppet-describe.8 +1 -1
  51. data/man/man8/puppet-device.8 +1 -1
  52. data/man/man8/puppet-doc.8 +1 -1
  53. data/man/man8/puppet-epp.8 +1 -1
  54. data/man/man8/puppet-facts.8 +1 -1
  55. data/man/man8/puppet-filebucket.8 +6 -2
  56. data/man/man8/puppet-generate.8 +1 -1
  57. data/man/man8/puppet-help.8 +1 -1
  58. data/man/man8/puppet-key.8 +1 -1
  59. data/man/man8/puppet-lookup.8 +1 -1
  60. data/man/man8/puppet-man.8 +1 -1
  61. data/man/man8/puppet-master.8 +1 -1
  62. data/man/man8/puppet-module.8 +1 -1
  63. data/man/man8/puppet-node.8 +1 -1
  64. data/man/man8/puppet-parser.8 +1 -1
  65. data/man/man8/puppet-plugin.8 +1 -1
  66. data/man/man8/puppet-report.8 +1 -1
  67. data/man/man8/puppet-resource.8 +1 -1
  68. data/man/man8/puppet-script.8 +1 -1
  69. data/man/man8/puppet-status.8 +1 -1
  70. data/man/man8/puppet.8 +2 -2
  71. data/spec/fixtures/unit/provider/mount/parsed/freebsd.fstab +1 -0
  72. data/spec/fixtures/unit/provider/mount/parsed/freebsd.mount +1 -0
  73. data/spec/fixtures/unit/provider/mount/parsed/linux.fstab +1 -0
  74. data/spec/fixtures/unit/provider/mount/parsed/linux.mount +1 -0
  75. data/spec/fixtures/unit/provider/mount/parsed/netbsd.fstab +1 -0
  76. data/spec/fixtures/unit/provider/mount/parsed/netbsd.mount +1 -0
  77. data/spec/fixtures/unit/provider/mount/parsed/openbsd.fstab +1 -0
  78. data/spec/fixtures/unit/provider/mount/parsed/openbsd.mount +1 -0
  79. data/spec/integration/provider/file/windows_spec.rb +162 -0
  80. data/spec/integration/type/file_spec.rb +0 -19
  81. data/spec/unit/application_spec.rb +8 -1
  82. data/spec/unit/configurer_spec.rb +2 -4
  83. data/spec/unit/confine/false_spec.rb +27 -0
  84. data/spec/unit/confine/true_spec.rb +27 -0
  85. data/spec/unit/defaults_spec.rb +0 -14
  86. data/spec/unit/network/http/connection_spec.rb +1 -1
  87. data/spec/unit/pops/loaders/loaders_spec.rb +5 -0
  88. data/spec/unit/pops/parser/locator_spec.rb +45 -0
  89. data/spec/unit/pops/parser/parse_heredoc_spec.rb +111 -15
  90. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +9 -0
  91. data/spec/unit/provider/group/windows_adsi_spec.rb +7 -1
  92. data/spec/unit/provider/mount/parsed_spec.rb +8 -1
  93. data/spec/unit/provider/package/windows_spec.rb +12 -1
  94. data/spec/unit/provider/service/systemd_spec.rb +6 -4
  95. data/spec/unit/settings_spec.rb +36 -0
  96. data/spec/unit/transaction/resource_harness_spec.rb +26 -0
  97. data/spec/unit/transaction_spec.rb +29 -0
  98. data/spec/unit/type/exec_spec.rb +47 -0
  99. data/spec/unit/type/filebucket_spec.rb +8 -6
  100. data/spec/unit/util/command_line_spec.rb +23 -2
  101. data/spec/unit/util/log_spec.rb +15 -0
  102. data/spec/unit/util/storage_spec.rb +19 -19
  103. metadata +6 -3
  104. data/MAINTAINERS +0 -47
@@ -1525,15 +1525,6 @@ describe Puppet::Type.type(:file), :uses_checksums => true do
1525
1525
  catalog.apply
1526
1526
  end
1527
1527
 
1528
- it "should not allow the user to explicitly set the mode to 4 ,and correct to 7" do
1529
- system_aces = get_aces_for_path_by_sid(path, @sids[:system])
1530
- expect(system_aces).not_to be_empty
1531
-
1532
- system_aces.each do |ace|
1533
- expect(ace.mask).to eq(Puppet::Util::Windows::File::FILE_ALL_ACCESS)
1534
- end
1535
- end
1536
-
1537
1528
  it "prepends SYSTEM ace when changing group from system to power users" do
1538
1529
  @file[:group] = @sids[:power_users]
1539
1530
  catalog.apply
@@ -1612,16 +1603,6 @@ describe Puppet::Type.type(:file), :uses_checksums => true do
1612
1603
  catalog.apply
1613
1604
  end
1614
1605
 
1615
- it "should not allow the user to explicitly set the mode to 4, and correct to 7" do
1616
- system_aces = get_aces_for_path_by_sid(dir, @sids[:system])
1617
- expect(system_aces).not_to be_empty
1618
-
1619
- system_aces.each do |ace|
1620
- # unlike files, Puppet sets execute bit on directories that are readable
1621
- expect(ace.mask).to eq(Puppet::Util::Windows::File::FILE_ALL_ACCESS)
1622
- end
1623
- end
1624
-
1625
1606
  it "prepends SYSTEM ace when changing group from system to power users" do
1626
1607
  @directory[:group] = @sids[:power_users]
1627
1608
  catalog.apply
@@ -640,10 +640,17 @@ describe Puppet::Application do
640
640
  it "should log an exception that is raised" do
641
641
  our_exception = Puppet::DevError.new("test exception")
642
642
  Puppet::Util::Log.expects(:newdestination).with(test_arg).raises(our_exception)
643
- Puppet.expects(:log_exception).with(our_exception)
643
+ Puppet.expects(:log_and_raise).with(our_exception, anything)
644
644
  @app.handle_logdest_arg(test_arg)
645
645
  end
646
646
 
647
+ it "should exit when an exception is raised" do
648
+ our_exception = Puppet::DevError.new("test exception")
649
+ Puppet::Util::Log.expects(:newdestination).with(test_arg).raises(our_exception)
650
+ Puppet.expects(:log_and_raise).with(our_exception, anything).raises(our_exception)
651
+ expect { @app.handle_logdest_arg(test_arg) }.to raise_error(Puppet::DevError)
652
+ end
653
+
647
654
  it "should set the new log destination" do
648
655
  Puppet::Util::Log.expects(:newdestination).with(test_arg)
649
656
  @app.handle_logdest_arg(test_arg)
@@ -1027,17 +1027,15 @@ describe Puppet::Configurer do
1027
1027
  @agent.run
1028
1028
  end
1029
1029
 
1030
- it "should fallback to an empty server when failover fails" do
1030
+ it "should error when no servers in 'server_list' are reachable" do
1031
1031
  Puppet.settings[:server_list] = ["myserver:123"]
1032
1032
  pool = Puppet::Network::HTTP::Pool.new(Puppet[:http_keepalive_timeout])
1033
1033
  Puppet::Network::HTTP::Pool.expects(:new).returns(pool)
1034
1034
  Puppet.expects(:override).with({:http_pool => pool}).yields
1035
1035
  Puppet.expects(:override).with({:server => "myserver", :serverport => '123'}).yields
1036
- Puppet.expects(:override).with({:server => nil, :serverport => nil}).yields
1037
1036
  error = Net::HTTPError.new(400, 'dummy server communication error')
1038
1037
  Puppet::Node.indirection.expects(:find).raises(error)
1039
- @agent.expects(:run_internal).returns(nil)
1040
- @agent.run
1038
+ expect{ @agent.run }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list/)
1041
1039
  end
1042
1040
 
1043
1041
  it "should not make multiple node requets when the server is found" do
@@ -12,6 +12,33 @@ describe Puppet::Confine::False do
12
12
  expect { Puppet::Confine.new }.to raise_error(ArgumentError)
13
13
  end
14
14
 
15
+ describe "when passing in a lambda as a value for lazy evaluation" do
16
+ it "should accept it" do
17
+ confine = Puppet::Confine::False.new(lambda { false })
18
+ expect(confine.values).to eql([false])
19
+ end
20
+
21
+ describe "when enforcing cache-positive behavior" do
22
+ def cached_value_of(confine)
23
+ confine.instance_variable_get(:@cached_value)
24
+ end
25
+
26
+ it "should cache a false value" do
27
+ confine = Puppet::Confine::False.new(lambda { false })
28
+ confine.values
29
+
30
+ expect(cached_value_of(confine)).to eql([false])
31
+ end
32
+
33
+ it "should not cache a true value" do
34
+ confine = Puppet::Confine::False.new(lambda { true })
35
+ confine.values
36
+
37
+ expect(cached_value_of(confine)).to be_nil
38
+ end
39
+ end
40
+ end
41
+
15
42
  describe "when testing values" do
16
43
  before { @confine = Puppet::Confine::False.new("foo") }
17
44
 
@@ -12,6 +12,33 @@ describe Puppet::Confine::True do
12
12
  expect { Puppet::Confine::True.new }.to raise_error(ArgumentError)
13
13
  end
14
14
 
15
+ describe "when passing in a lambda as a value for lazy evaluation" do
16
+ it "should accept it" do
17
+ confine = Puppet::Confine::True.new(lambda { true })
18
+ expect(confine.values).to eql([true])
19
+ end
20
+
21
+ describe "when enforcing cache-positive behavior" do
22
+ def cached_value_of(confine)
23
+ confine.instance_variable_get(:@cached_value)
24
+ end
25
+
26
+ it "should cache a true value" do
27
+ confine = Puppet::Confine::True.new(lambda { true })
28
+ confine.values
29
+
30
+ expect(cached_value_of(confine)).to eql([true])
31
+ end
32
+
33
+ it "should not cache a false value" do
34
+ confine = Puppet::Confine::True.new(lambda { false })
35
+ confine.values
36
+
37
+ expect(cached_value_of(confine)).to be_nil
38
+ end
39
+ end
40
+ end
41
+
15
42
  describe "when testing values" do
16
43
  before do
17
44
  @confine = Puppet::Confine::True.new("foo")
@@ -110,20 +110,6 @@ describe "Defaults" do
110
110
  end
111
111
  end
112
112
 
113
- describe 'server vs server_list' do
114
- it 'should warn when both settings are set in code' do
115
- Puppet.expects(:deprecation_warning).with('Attempted to set both server and server_list. Server setting will not be used.', :SERVER_DUPLICATION)
116
- Puppet.settings[:server] = 'test_server'
117
- Puppet.settings[:server_list] = ['one', 'two']
118
- end
119
-
120
- it 'should warn when both settings are set by command line' do
121
- Puppet.expects(:deprecation_warning).with('Attempted to set both server and server_list. Server setting will not be used.', :SERVER_DUPLICATION)
122
- Puppet.settings.handlearg("--server_list", "one,two")
123
- Puppet.settings.handlearg("--server", "test_server")
124
- end
125
- end
126
-
127
113
  describe 'manage_internal_file_permissions' do
128
114
  describe 'on windows', :if => Puppet::Util::Platform.windows? do
129
115
  it 'should default to false' do
@@ -121,7 +121,7 @@ describe Puppet::Network::HTTP::Connection do
121
121
 
122
122
  expect do
123
123
  connection.get('request')
124
- end.to raise_error(Puppet::Error, "certificate verify failed: [shady looking signature]")
124
+ end.to raise_error(Puppet::Error, /certificate verify failed: \[shady looking signature\]/)
125
125
  end
126
126
 
127
127
  it "should provide a helpful error message when hostname was not match with server certificate", :unless => Puppet.features.microsoft_windows? do
@@ -409,6 +409,11 @@ describe 'loaders' do
409
409
  expect(function.call(scope, 'passed in scope')).to eql("usee::callee_ws() got 'passed in scope'")
410
410
  end
411
411
 
412
+ it 'calls can be made to a non core function via the call() function' do
413
+ call_function = loader.load_typed(typed_name(:function, 'call')).value
414
+ expect(call_function.call(scope, 'user::puppetcaller4')).to eql("usee::callee() got 'first' - usee::callee() got 'second'")
415
+ end
416
+
412
417
  end
413
418
 
414
419
  context 'loading' do
@@ -41,4 +41,49 @@ describe Puppet::Pops::Parser::Locator do
41
41
  expect(model.body.locator.line_for_offset(2)).to eq(:third_value)
42
42
  end
43
43
 
44
+ it 'A heredoc without margin and interpolated expression location has offset and length relative the source' do
45
+ parser = Puppet::Pops::Parser::Parser.new()
46
+ src = <<-CODE
47
+ # line one
48
+ # line two
49
+ @("END"/L)
50
+ Line four\\
51
+ Line five ${1 +
52
+ 1}
53
+ END
54
+ CODE
55
+
56
+ model = parser.parse_string(src).model
57
+ interpolated_expr = model.body.text_expr.segments[1].expr
58
+ expect(interpolated_expr.left_expr.offset).to eq(84)
59
+ expect(interpolated_expr.left_expr.length).to eq(1)
60
+ expect(interpolated_expr.right_expr.offset).to eq(96)
61
+ expect(interpolated_expr.right_expr.length).to eq(1)
62
+ expect(interpolated_expr.offset).to eq(86) # the + sign
63
+ expect(interpolated_expr.length).to eq(1) # the + sign
64
+ expect(interpolated_expr.locator.extract_tree_text(interpolated_expr)).to eq("1 +\n 1")
65
+ end
66
+
67
+ it 'A heredoc with margin and interpolated expression location has offset and length relative the source' do
68
+ parser = Puppet::Pops::Parser::Parser.new()
69
+ src = <<-CODE
70
+ # line one
71
+ # line two
72
+ @("END"/L)
73
+ Line four\\
74
+ Line five ${1 +
75
+ 1}
76
+ |- END
77
+ CODE
78
+
79
+ model = parser.parse_string(src).model
80
+ interpolated_expr = model.body.text_expr.segments[1].expr
81
+ expect(interpolated_expr.left_expr.offset).to eq(84)
82
+ expect(interpolated_expr.left_expr.length).to eq(1)
83
+ expect(interpolated_expr.right_expr.offset).to eq(96)
84
+ expect(interpolated_expr.right_expr.length).to eq(1)
85
+ expect(interpolated_expr.offset).to eq(86) # the + sign
86
+ expect(interpolated_expr.length).to eq(1) # the + sign
87
+ expect(interpolated_expr.locator.extract_tree_text(interpolated_expr)).to eq("1 +\n 1")
88
+ end
44
89
  end
@@ -10,7 +10,7 @@ describe "egrammar parsing heredoc" do
10
10
  it "parses plain heredoc" do
11
11
  expect(dump(parse("@(END)\nThis is\nheredoc text\nEND\n"))).to eq([
12
12
  "(@()",
13
- " (sublocated 'This is\nheredoc text\n')",
13
+ " 'This is\nheredoc text\n'",
14
14
  ")"
15
15
  ].join("\n"))
16
16
  end
@@ -25,7 +25,7 @@ describe "egrammar parsing heredoc" do
25
25
  ].join("\n")
26
26
  expect(dump(parse(src))).to eq([
27
27
  "(@()",
28
- " (sublocated 'This is\nheredoc text\n')",
28
+ " 'This is\nheredoc text\n'",
29
29
  ")"
30
30
  ].join("\n"))
31
31
  end
@@ -40,7 +40,7 @@ describe "egrammar parsing heredoc" do
40
40
  ].join("\n")
41
41
  expect(dump(parse(src))).to eq([
42
42
  "(@()",
43
- " (sublocated 'This is\nheredoc text')",
43
+ " 'This is\nheredoc text'",
44
44
  ")"
45
45
  ].join("\n"))
46
46
  end
@@ -53,7 +53,7 @@ describe "egrammar parsing heredoc" do
53
53
  CODE
54
54
  expect(dump(parse(src))).to eq([
55
55
  "(@(syntax)",
56
- " (sublocated 'Tex\tt\\n')",
56
+ " 'Tex\tt\\n'",
57
57
  ")"
58
58
  ].join("\n"))
59
59
  end
@@ -66,7 +66,7 @@ describe "egrammar parsing heredoc" do
66
66
  CODE
67
67
  expect(dump(parse(src))).to eq([
68
68
  "(@()",
69
- " (sublocated (cat 'Hello ' (str $name)))",
69
+ " (cat 'Hello ' (str $name))",
70
70
  ")"
71
71
  ].join("\n"))
72
72
  end
@@ -79,7 +79,7 @@ describe "egrammar parsing heredoc" do
79
79
  CODE
80
80
  expect(dump(parse(src))).to eq([
81
81
  "(@()",
82
- " (sublocated (cat 'Hello \\' (str $name)))",
82
+ " (cat 'Hello \\' (str $name))",
83
83
  ")"
84
84
  ].join("\n"))
85
85
  end
@@ -92,7 +92,7 @@ describe "egrammar parsing heredoc" do
92
92
  CODE
93
93
  expect(dump(parse(src))).to eq([
94
94
  "(@()",
95
- " (sublocated (cat 'Hello \\' (str $name)))",
95
+ " (cat 'Hello \\' (str $name))",
96
96
  ")"
97
97
  ].join("\n"))
98
98
  end
@@ -107,7 +107,7 @@ describe "egrammar parsing heredoc" do
107
107
  parse(src)
108
108
  expect(dump(parse(src))).to eq([
109
109
  "(@()",
110
- " (sublocated 'First Line Second Line')",
110
+ " 'First Line Second Line'",
111
111
  ")"
112
112
  ].join("\n"))
113
113
  end
@@ -122,7 +122,7 @@ describe "egrammar parsing heredoc" do
122
122
  parse(src)
123
123
  expect(dump(parse(src))).to eq([
124
124
  "(@()",
125
- " (sublocated ' First Line Second Line')",
125
+ " ' First Line Second Line'",
126
126
  ")"
127
127
  ].join("\n"))
128
128
  end
@@ -135,12 +135,12 @@ describe "egrammar parsing heredoc" do
135
135
  CODE
136
136
  expect(dump(parse(src))).to eq([
137
137
  "(@()",
138
- " (sublocated (cat 'Hello ' (str $name) '$%a'))",
138
+ " (cat 'Hello ' (str $name) '$%a')",
139
139
  ")"
140
140
  ].join("\n"))
141
141
  end
142
142
 
143
- it "parses interpolated [] expression by looking at the correct preceding char for space" do
143
+ it "parses interpolated [] expression by looking at the correct preceding char for space when there is no heredoc margin" do
144
144
  # NOTE: Important not to use the left margin feature here
145
145
  src = <<-CODE
146
146
  $xxxxxxx = @("END")
@@ -150,12 +150,108 @@ END
150
150
  CODE
151
151
  expect(dump(parse(src))).to eq([
152
152
  "(= $xxxxxxx (@()",
153
- " (sublocated (cat (str (slice (slice $facts 'os') 'family')) '",
153
+ " (cat (str (slice (slice $facts 'os') 'family')) '",
154
154
  "XXXXXXX XXX",
155
- "'))",
155
+ "')",
156
156
  "))"].join("\n"))
157
157
  end
158
158
 
159
+ it "parses interpolated [] expression by looking at the correct preceding char for space when there is a heredoc margin" do
160
+ # NOTE: Important not to use the left margin feature here - the problem in PUP 9303 is triggered by lines and text before
161
+ # an interpolation containing [].
162
+ src = <<-CODE
163
+ # comment
164
+ # comment
165
+ $xxxxxxx = @("END")
166
+ 1
167
+ 2
168
+ 3
169
+ 4
170
+ 5
171
+ YYYYY${facts['fqdn']}
172
+ XXXXXXX XXX
173
+ | END
174
+ CODE
175
+ expect(dump(parse(src))).to eq([
176
+ "(= $xxxxxxx (@()",
177
+ " (cat '1", "2", "3", "4", "5",
178
+ "YYYYY' (str (slice $facts 'fqdn')) '",
179
+ "XXXXXXX XXX",
180
+ "')",
181
+ "))"].join("\n"))
182
+ end
183
+
184
+ it "correctly reports an error location in a nested heredoc with margin" do
185
+ # NOTE: Important not to use the left margin feature here - the problem in PUP 9303 is triggered by lines and text before
186
+ # an interpolation containing [].
187
+ src = <<-CODE
188
+ # comment
189
+ # comment
190
+ $xxxxxxx = @("END")
191
+ 1
192
+ 2
193
+ 3
194
+ 4
195
+ 5
196
+ YYYYY${facts]}
197
+ XXXXXXX XXX
198
+ | END
199
+ CODE
200
+ expect{parse(src)}.to raise_error(/Syntax error at '\]' \(line: 9, column: 15\)/)
201
+ end
202
+
203
+ it "correctly reports an error location in a heredoc with line endings escaped" do
204
+ # DO NOT CHANGE INDENTATION OF THIS HEREDOC
205
+ src = <<-CODE
206
+ # line one
207
+ # line two
208
+ @("END"/L)
209
+ First Line\\
210
+ Second Line ${facts]}
211
+ |- END
212
+ CODE
213
+ expect{parse(src)}.to raise_error(/Syntax error at '\]' \(line: 5, column: 24\)/)
214
+ end
215
+
216
+ it "correctly reports an error location in a heredoc with line endings escaped when there is text in the margin" do
217
+ # DO NOT CHANGE INDENTATION OR SPACING OF THIS HEREDOC
218
+ src = <<-CODE
219
+ # line one
220
+ # line two
221
+ @("END"/L)
222
+ First Line\\
223
+ Second Line
224
+ x Third Line ${facts]}
225
+ |- END
226
+ # line 8
227
+ # line 9
228
+ CODE
229
+ expect{parse(src)}.to raise_error(/Syntax error at '\]' \(line: 6, column: 23\)/)
230
+ end
231
+
232
+ it "correctly reports an error location in a heredoc with line endings escaped when there is text in the margin" do
233
+ # DO NOT CHANGE INDENTATION OR SPACING OF THIS HEREDOC
234
+ src = <<-CODE
235
+ @(END)
236
+ AAA
237
+ BBB
238
+ CCC
239
+ DDD
240
+ EEE
241
+ FFF
242
+ |- END
243
+ CODE
244
+ expect(dump(parse(src))).to eq([
245
+ "(@()",
246
+ " 'AAA", # no left space trimmed
247
+ " BBB",
248
+ " CCC",
249
+ " DDD",
250
+ "EEE", # left space trimmed
251
+ " FFF'", # indented one because it is one in from margin marker
252
+ ")"].join("\n"))
253
+ end
254
+
159
255
  it 'parses multiple heredocs on the same line' do
160
256
  src = <<-CODE
161
257
  notice({ @(foo) => @(bar) })
@@ -168,9 +264,9 @@ CODE
168
264
  expect(dump(parse(src))).to eq([
169
265
  '(block',
170
266
  ' (invoke notice ({} ((@()',
171
- ' (sublocated \' hello\')',
267
+ ' \' hello\'',
172
268
  ' ) (@()',
173
- ' (sublocated \' world\')',
269
+ ' \' world\'',
174
270
  ' ))))',
175
271
  ' (invoke notice \'!\')',
176
272
  ')'