test-kitchen 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +5 -0
  3. data/.travis.yml +8 -3
  4. data/CHANGELOG.md +66 -0
  5. data/Guardfile +3 -1
  6. data/README.md +3 -1
  7. data/Rakefile +1 -16
  8. data/features/kitchen_command.feature +1 -0
  9. data/features/kitchen_driver_create_command.feature +1 -0
  10. data/features/kitchen_driver_discover_command.feature +1 -0
  11. data/features/kitchen_help_command.feature +16 -0
  12. data/features/kitchen_init_command.feature +2 -0
  13. data/features/kitchen_list_command.feature +42 -0
  14. data/features/support/env.rb +25 -0
  15. data/lib/kitchen.rb +0 -1
  16. data/lib/kitchen/busser.rb +2 -2
  17. data/lib/kitchen/cli.rb +80 -233
  18. data/lib/kitchen/command.rb +117 -0
  19. data/lib/kitchen/command/action.rb +44 -0
  20. data/lib/kitchen/command/console.rb +51 -0
  21. data/lib/kitchen/command/diagnose.rb +51 -0
  22. data/lib/kitchen/command/driver_discover.rb +72 -0
  23. data/lib/kitchen/command/list.rb +86 -0
  24. data/lib/kitchen/command/login.rb +42 -0
  25. data/lib/kitchen/command/sink.rb +53 -0
  26. data/lib/kitchen/command/test.rb +50 -0
  27. data/lib/kitchen/driver/ssh_base.rb +2 -1
  28. data/lib/kitchen/loader/yaml.rb +67 -29
  29. data/lib/kitchen/provisioner/base.rb +67 -4
  30. data/lib/kitchen/provisioner/chef_base.rb +50 -65
  31. data/lib/kitchen/provisioner/chef_solo.rb +3 -2
  32. data/lib/kitchen/provisioner/chef_zero.rb +11 -9
  33. data/lib/kitchen/provisioner/shell.rb +88 -0
  34. data/lib/kitchen/state_file.rb +7 -2
  35. data/lib/kitchen/util.rb +1 -1
  36. data/lib/kitchen/version.rb +1 -1
  37. data/spec/kitchen/loader/yaml_spec.rb +327 -13
  38. data/spec/spec_helper.rb +2 -7
  39. data/support/chef-client-zero.rb +1 -0
  40. data/templates/driver/README.md.erb +1 -1
  41. data/test-kitchen.gemspec +2 -2
  42. metadata +59 -46
@@ -30,7 +30,8 @@ module Kitchen
30
30
  default_config :solo_rb, {}
31
31
 
32
32
  def create_sandbox
33
- create_chef_sandbox { prepare_solo_rb }
33
+ super
34
+ prepare_solo_rb
34
35
  end
35
36
 
36
37
  def run_command
@@ -48,7 +49,7 @@ module Kitchen
48
49
  def prepare_solo_rb
49
50
  data = default_config_rb.merge(config[:solo_rb])
50
51
 
51
- File.open(File.join(tmpdir, "solo.rb"), "wb") do |file|
52
+ File.open(File.join(sandbox_path, "solo.rb"), "wb") do |file|
52
53
  file.write(format_config_file(data))
53
54
  end
54
55
  end
@@ -29,13 +29,13 @@ module Kitchen
29
29
 
30
30
  default_config :client_rb, {}
31
31
  default_config :ruby_bindir, "/opt/chef/embedded/bin"
32
+ default_config :json_attributes, true
32
33
 
33
34
  def create_sandbox
34
- create_chef_sandbox do
35
- prepare_chef_client_zero_rb
36
- prepare_validation_pem
37
- prepare_client_rb
38
- end
35
+ super
36
+ prepare_chef_client_zero_rb
37
+ prepare_validation_pem
38
+ prepare_client_rb
39
39
  end
40
40
 
41
41
  def prepare_command
@@ -62,9 +62,11 @@ module Kitchen
62
62
  def run_command
63
63
  args = [
64
64
  "--config #{config[:root_path]}/client.rb",
65
- "--json-attributes #{config[:root_path]}/dna.json",
66
65
  "--log_level #{config[:log_level]}"
67
66
  ]
67
+ if config[:json_attributes]
68
+ args << "--json-attributes #{config[:root_path]}/dna.json"
69
+ end
68
70
 
69
71
  if local_mode_supported?
70
72
  ["#{sudo('chef-client')} -z"].concat(args).join(" ")
@@ -84,19 +86,19 @@ module Kitchen
84
86
 
85
87
  source = File.join(File.dirname(__FILE__),
86
88
  %w{.. .. .. support chef-client-zero.rb})
87
- FileUtils.cp(source, File.join(tmpdir, "chef-client-zero.rb"))
89
+ FileUtils.cp(source, File.join(sandbox_path, "chef-client-zero.rb"))
88
90
  end
89
91
 
90
92
  def prepare_validation_pem
91
93
  source = File.join(File.dirname(__FILE__),
92
94
  %w{.. .. .. support dummy-validation.pem})
93
- FileUtils.cp(source, File.join(tmpdir, "validation.pem"))
95
+ FileUtils.cp(source, File.join(sandbox_path, "validation.pem"))
94
96
  end
95
97
 
96
98
  def prepare_client_rb
97
99
  data = default_config_rb.merge(config[:client_rb])
98
100
 
99
- File.open(File.join(tmpdir, "client.rb"), "wb") do |file|
101
+ File.open(File.join(sandbox_path, "client.rb"), "wb") do |file|
100
102
  file.write(format_config_file(data))
101
103
  end
102
104
  end
@@ -0,0 +1,88 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Chris Lundquist (<chris.lundquist@github.com>)
4
+ #
5
+ # Copyright (C) 2013, Chris Lundquist
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'kitchen/provisioner/base'
20
+
21
+ module Kitchen
22
+
23
+ module Provisioner
24
+
25
+ # Basic shell provisioner.
26
+ #
27
+ # @author Chris Lundquist (<chris.ludnquist@github.com>)
28
+ class Shell < Base
29
+
30
+ default_config :script do |provisioner|
31
+ provisioner.calculate_path("bootstrap.sh", :script)
32
+ end
33
+ expand_path_for :script
34
+
35
+ default_config :data_path do |provisioner|
36
+ provisioner.calculate_path("data")
37
+ end
38
+ expand_path_for :data_path
39
+
40
+ def create_sandbox
41
+ super
42
+ prepare_data
43
+ prepare_script
44
+ end
45
+
46
+ def init_command
47
+ data = File.join(config[:root_path], "data")
48
+ "#{sudo('rm')} -rf #{data} ; mkdir -p #{config[:root_path]}"
49
+ end
50
+
51
+ def run_command
52
+ sudo(File.join(config[:root_path], File.basename(config[:script])))
53
+ end
54
+
55
+ protected
56
+
57
+ def prepare_data
58
+ return unless config[:data_path]
59
+
60
+ info("Preparing data")
61
+ debug("Using data from #{config[:data_path]}")
62
+
63
+ tmpdata_dir = File.join(sandbox_path, "data")
64
+ FileUtils.mkdir_p(tmpdata_dir)
65
+ FileUtils.cp_r(Dir.glob("#{config[:data_path]}/*"), tmpdata_dir)
66
+ end
67
+
68
+ def prepare_script
69
+ info("Preparing script")
70
+
71
+ if config[:script]
72
+ debug("Using script from #{config[:script]}")
73
+ FileUtils.cp_r(config[:script], sandbox_path)
74
+ else
75
+ config[:script] = File.join(sandbox_path, "bootstrap.sh")
76
+ info("#{File.basename(config[:script])} not found " +
77
+ "so Kitchen will run a stubbed script. Is this intended?")
78
+ File.open(config[:script], "wb") do |file|
79
+ file.write(%{#!/bin/sh\necho "NO BOOTSTRAP SCRIPT PRESENT"\n})
80
+ end
81
+ end
82
+
83
+ FileUtils.chmod(0755,
84
+ File.join(sandbox_path, File.basename(config[:script])))
85
+ end
86
+ end
87
+ end
88
+ end
@@ -16,7 +16,12 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'safe_yaml'
19
+ if RUBY_VERSION <= "1.9.3"
20
+ # ensure that Psych and not Syck is used for Ruby 1.9.2
21
+ require 'yaml'
22
+ YAML::ENGINE.yamler = 'psych'
23
+ end
24
+ require 'safe_yaml/load'
20
25
 
21
26
  module Kitchen
22
27
 
@@ -86,7 +91,7 @@ module Kitchen
86
91
  end
87
92
 
88
93
  def deserialize_string(string)
89
- ::YAML.safe_load(string)
94
+ SafeYAML.load(string)
90
95
  rescue SyntaxError, Psych::SyntaxError => ex
91
96
  raise StateFileLoadError, "Error parsing #{file_name} (#{ex.message})"
92
97
  end
data/lib/kitchen/util.rb CHANGED
@@ -184,7 +184,7 @@ module Kitchen
184
184
 
185
185
  # do_download URL FILENAME
186
186
  do_download() {
187
- PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
187
+ PATH=/opt/local/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
188
188
  export PATH
189
189
 
190
190
  echo "downloading $1"
@@ -18,5 +18,5 @@
18
18
 
19
19
  module Kitchen
20
20
 
21
- VERSION = "1.1.1"
21
+ VERSION = "1.2.0"
22
22
  end
@@ -28,7 +28,9 @@ end
28
28
 
29
29
  describe Kitchen::Loader::YAML do
30
30
 
31
- let(:loader) { Kitchen::Loader::YAML.new("/tmp/.kitchen.yml") }
31
+ let(:loader) do
32
+ Kitchen::Loader::YAML.new(:project_config => "/tmp/.kitchen.yml")
33
+ end
32
34
 
33
35
  before do
34
36
  FakeFS.activate!
@@ -42,17 +44,64 @@ describe Kitchen::Loader::YAML do
42
44
 
43
45
  describe ".initialize" do
44
46
 
45
- it "sets config_file based on Dir.pwd by default" do
47
+ it "sets project_config based on Dir.pwd by default" do
48
+ stub_file(File.join(Dir.pwd, '.kitchen.yml'), Hash.new)
46
49
  loader = Kitchen::Loader::YAML.new
47
50
 
48
- loader.config_file.must_equal File.expand_path(
49
- File.join(Dir.pwd, '.kitchen.yml'))
51
+ loader.diagnose[:project_config][:filename].
52
+ must_equal File.expand_path(File.join(Dir.pwd, '.kitchen.yml'))
50
53
  end
51
54
 
52
- it "sets config_file from parameter, if given" do
53
- loader = Kitchen::Loader::YAML.new('/tmp/crazyfunkytown.file')
55
+ it "sets project_config from parameter, if given" do
56
+ stub_file('/tmp/crazyfunkytown.file', Hash.new)
57
+ loader = Kitchen::Loader::YAML.new(
58
+ :project_config => '/tmp/crazyfunkytown.file')
54
59
 
55
- loader.config_file.must_equal '/tmp/crazyfunkytown.file'
60
+ loader.diagnose[:project_config][:filename].
61
+ must_match %r{/tmp/crazyfunkytown.file$}
62
+ end
63
+
64
+ it "sets local_config based on Dir.pwd by default" do
65
+ stub_file(File.join(Dir.pwd, '.kitchen.local.yml'), Hash.new)
66
+ loader = Kitchen::Loader::YAML.new
67
+
68
+ loader.diagnose[:local_config][:filename].
69
+ must_equal File.expand_path(File.join(Dir.pwd, '.kitchen.local.yml'))
70
+ end
71
+
72
+ it "sets local_config based on location of project_config by default" do
73
+ stub_file('/tmp/.kitchen.local.yml', Hash.new)
74
+ loader = Kitchen::Loader::YAML.new(
75
+ :project_config => '/tmp/.kitchen.yml')
76
+
77
+ loader.diagnose[:local_config][:filename].
78
+ must_match %r{/tmp/.kitchen.local.yml$}
79
+ end
80
+
81
+ it "sets local_config from parameter, if given" do
82
+ stub_file('/tmp/crazyfunkytown.file', Hash.new)
83
+ loader = Kitchen::Loader::YAML.new(
84
+ :local_config => '/tmp/crazyfunkytown.file')
85
+
86
+ loader.diagnose[:local_config][:filename].
87
+ must_match %r{/tmp/crazyfunkytown.file$}
88
+ end
89
+
90
+ it "sets global_config based on ENV['HOME'] by default" do
91
+ stub_file(File.join(ENV['HOME'], '.kitchen/config.yml'), Hash.new)
92
+ loader = Kitchen::Loader::YAML.new
93
+
94
+ loader.diagnose[:global_config][:filename].must_equal File.expand_path(
95
+ File.join(ENV['HOME'], '.kitchen/config.yml'))
96
+ end
97
+
98
+ it "sets global_config from parameter, if given" do
99
+ stub_file('/tmp/crazyfunkytown.file', Hash.new)
100
+ loader = Kitchen::Loader::YAML.new(
101
+ :global_config => '/tmp/crazyfunkytown.file')
102
+
103
+ loader.diagnose[:global_config][:filename].
104
+ must_match %r{/tmp/crazyfunkytown.file$}
56
105
  end
57
106
  end
58
107
 
@@ -326,14 +375,25 @@ describe Kitchen::Loader::YAML do
326
375
  FileUtils.mkdir_p "/tmp"
327
376
  File.open("/tmp/.kitchen.yml", "wb") { |f| f.write '&*%^*' }
328
377
 
329
- proc { loader.read }.must_raise Kitchen::UserError
378
+ err = proc { loader.read }.must_raise Kitchen::UserError
379
+ err.message.must_match Regexp.new(
380
+ "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
330
381
  end
331
382
 
332
383
  it "raises a UserError if kitchen.yml cannot be parsed" do
333
384
  FileUtils.mkdir_p "/tmp"
334
385
  File.open("/tmp/.kitchen.yml", "wb") { |f| f.write 'uhoh' }
335
386
 
336
- proc { loader.read }.must_raise Kitchen::UserError
387
+ err = proc { loader.read }.must_raise Kitchen::UserError
388
+ err.message.must_match Regexp.new(
389
+ "Error parsing ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
390
+ end
391
+
392
+ it "handles a kitchen.yml if it is a commented out YAML document" do
393
+ FileUtils.mkdir_p "/tmp"
394
+ File.open("/tmp/.kitchen.yml", "wb") { |f| f.write '#---\n' }
395
+
396
+ loader.read.must_equal(Hash.new)
337
397
  end
338
398
 
339
399
  it "raises a UserError if kitchen.local.yml cannot be parsed" do
@@ -356,6 +416,20 @@ describe Kitchen::Loader::YAML do
356
416
  loader.read.must_equal({ :name => "ahhchoo" })
357
417
  end
358
418
 
419
+ it "raises a UserError if there is an ERB processing error" do
420
+ FileUtils.mkdir_p "/tmp"
421
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
422
+ f.write <<-'YAML'.gsub(/^ {10}/, '')
423
+ ---
424
+ <%= poop %>: yep
425
+ YAML
426
+ end
427
+
428
+ err = proc { loader.read }.must_raise Kitchen::UserError
429
+ err.message.must_match Regexp.new(
430
+ "Error parsing ERB content in ([a-zA-Z]:)?\/tmp\/\.kitchen\.yml")
431
+ end
432
+
359
433
  it "evaluates kitchen.local.yml through erb before loading by default" do
360
434
  FileUtils.mkdir_p "/tmp"
361
435
  File.open("/tmp/.kitchen.local.yml", "wb") do |f|
@@ -377,7 +451,7 @@ describe Kitchen::Loader::YAML do
377
451
 
378
452
  it "skips evaluating kitchen.yml through erb if disabled" do
379
453
  loader = Kitchen::Loader::YAML.new(
380
- '/tmp/.kitchen.yml', :process_erb => false)
454
+ :project_config => '/tmp/.kitchen.yml', :process_erb => false)
381
455
  FileUtils.mkdir_p "/tmp"
382
456
  File.open("/tmp/.kitchen.yml", "wb") do |f|
383
457
  f.write <<-'YAML'.gsub(/^ {10}/, '')
@@ -391,7 +465,7 @@ describe Kitchen::Loader::YAML do
391
465
 
392
466
  it "skips evaluating kitchen.local.yml through erb if disabled" do
393
467
  loader = Kitchen::Loader::YAML.new(
394
- '/tmp/.kitchen.yml', :process_erb => false)
468
+ :project_config => '/tmp/.kitchen.yml', :process_erb => false)
395
469
  FileUtils.mkdir_p "/tmp"
396
470
  File.open("/tmp/.kitchen.local.yml", "wb") do |f|
397
471
  f.write <<-'YAML'.gsub(/^ {10}/, '')
@@ -406,7 +480,7 @@ describe Kitchen::Loader::YAML do
406
480
 
407
481
  it "skips kitchen.local.yml if disabled" do
408
482
  loader = Kitchen::Loader::YAML.new(
409
- '/tmp/.kitchen.yml', :process_local => false)
483
+ :project_config => '/tmp/.kitchen.yml', :process_local => false)
410
484
  stub_yaml!(".kitchen.yml", {
411
485
  'a' => 'b'
412
486
  })
@@ -419,7 +493,7 @@ describe Kitchen::Loader::YAML do
419
493
 
420
494
  it "skips the global config if disabled" do
421
495
  loader = Kitchen::Loader::YAML.new(
422
- '/tmp/.kitchen.yml', :process_global => false)
496
+ :project_config => '/tmp/.kitchen.yml', :process_global => false)
423
497
  stub_yaml!(".kitchen.yml", {
424
498
  'a' => 'b'
425
499
  })
@@ -431,6 +505,246 @@ describe Kitchen::Loader::YAML do
431
505
  end
432
506
  end
433
507
 
508
+ describe "#diagnose" do
509
+
510
+ it "returns a Hash" do
511
+ stub_yaml!(Hash.new)
512
+
513
+ loader.diagnose.must_be_kind_of(Hash)
514
+ end
515
+
516
+ it "contains erb processing information when true" do
517
+ stub_yaml!(Hash.new)
518
+
519
+ loader.diagnose[:process_erb].must_equal true
520
+ end
521
+
522
+ it "contains erb processing information when false" do
523
+ stub_yaml!(Hash.new)
524
+ loader = Kitchen::Loader::YAML.new(
525
+ :project_config => '/tmp/.kitchen.yml', :process_erb => false)
526
+
527
+ loader.diagnose[:process_erb].must_equal false
528
+ end
529
+
530
+ it "contains local processing information when true" do
531
+ stub_yaml!(Hash.new)
532
+
533
+ loader.diagnose[:process_local].must_equal true
534
+ end
535
+
536
+ it "contains local processing information when false" do
537
+ stub_yaml!(Hash.new)
538
+ loader = Kitchen::Loader::YAML.new(
539
+ :project_config => '/tmp/.kitchen.yml', :process_local => false)
540
+
541
+ loader.diagnose[:process_local].must_equal false
542
+ end
543
+
544
+ it "contains global processing information when true" do
545
+ stub_yaml!(Hash.new)
546
+
547
+ loader.diagnose[:process_global].must_equal true
548
+ end
549
+
550
+ it "contains global processing information when false" do
551
+ stub_yaml!(Hash.new)
552
+ loader = Kitchen::Loader::YAML.new(
553
+ :project_config => '/tmp/.kitchen.yml', :process_global => false)
554
+
555
+ loader.diagnose[:process_global].must_equal false
556
+ end
557
+
558
+ describe "for yaml files" do
559
+
560
+ before do
561
+ stub_yaml!(".kitchen.yml", {
562
+ "from_project" => "project",
563
+ "common" => { "p" => "pretty" }
564
+ })
565
+ stub_yaml!(".kitchen.local.yml", {
566
+ "from_local" => "local",
567
+ "common" => { "l" => "looky" }
568
+ })
569
+ stub_global!({
570
+ "from_global" => "global",
571
+ "common" => { "g" => "goody" }
572
+ })
573
+ end
574
+
575
+ it "global config contains a filename" do
576
+ loader.diagnose[:global_config][:filename].
577
+ must_equal File.join(ENV["HOME"], ".kitchen/config.yml")
578
+ end
579
+
580
+ it "global config contains raw data" do
581
+ loader.diagnose[:global_config][:raw_data].must_equal({
582
+ "from_global" => "global",
583
+ "common" => { "g" => "goody" }
584
+ })
585
+ end
586
+
587
+ it "project config contains a filename" do
588
+ loader.diagnose[:project_config][:filename].
589
+ must_match %r{/tmp/.kitchen.yml$}
590
+ end
591
+
592
+ it "project config contains raw data" do
593
+ loader.diagnose[:project_config][:raw_data].must_equal({
594
+ "from_project" => "project",
595
+ "common" => { "p" => "pretty" }
596
+ })
597
+ end
598
+
599
+ it "local config contains a filename" do
600
+ loader.diagnose[:local_config][:filename].
601
+ must_match %r{/tmp/.kitchen.local.yml$}
602
+ end
603
+
604
+ it "local config contains raw data" do
605
+ loader.diagnose[:local_config][:raw_data].must_equal({
606
+ "from_local" => "local",
607
+ "common" => { "l" => "looky" }
608
+ })
609
+ end
610
+
611
+ it "combined config contains a nil filename" do
612
+ loader.diagnose[:combined_config][:filename].
613
+ must_equal nil
614
+ end
615
+
616
+ it "combined config contains raw data" do
617
+ loader.diagnose[:combined_config][:raw_data].must_equal({
618
+ "from_global" => "global",
619
+ "from_project" => "project",
620
+ "from_local" => "local",
621
+ "common" => {
622
+ "g" => "goody",
623
+ "p" => "pretty",
624
+ "l" => "looky"
625
+ }
626
+ })
627
+ end
628
+
629
+ describe "for global on error" do
630
+
631
+ before do
632
+ FileUtils.mkdir_p(File.join(ENV["HOME"], ".kitchen"))
633
+ File.open(File.join(ENV["HOME"], ".kitchen/config.yml"), "wb") do |f|
634
+ f.write '&*%^*'
635
+ end
636
+ end
637
+
638
+ it "uses an error hash with the raw file contents" do
639
+ loader.diagnose[:global_config][:raw_data][:error][:raw_file].
640
+ must_equal "&*%^*"
641
+ end
642
+
643
+ it "uses an error hash with the exception" do
644
+ loader.diagnose[:global_config][:raw_data][:error][:exception].
645
+ must_match %r{Kitchen::UserError}
646
+ end
647
+
648
+ it "uses an error hash with the exception message" do
649
+ loader.diagnose[:global_config][:raw_data][:error][:message].
650
+ must_match %r{Error parsing}
651
+ end
652
+
653
+ it "uses an error hash with the exception backtrace" do
654
+ loader.diagnose[:global_config][:raw_data][:error][:backtrace].
655
+ must_be_kind_of Array
656
+ end
657
+ end
658
+
659
+ describe "for project on error" do
660
+
661
+ before do
662
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
663
+ f.write '&*%^*'
664
+ end
665
+ end
666
+
667
+ it "uses an error hash with the raw file contents" do
668
+ loader.diagnose[:project_config][:raw_data][:error][:raw_file].
669
+ must_equal "&*%^*"
670
+ end
671
+
672
+ it "uses an error hash with the exception" do
673
+ loader.diagnose[:project_config][:raw_data][:error][:exception].
674
+ must_match %r{Kitchen::UserError}
675
+ end
676
+
677
+ it "uses an error hash with the exception message" do
678
+ loader.diagnose[:project_config][:raw_data][:error][:message].
679
+ must_match %r{Error parsing}
680
+ end
681
+
682
+ it "uses an error hash with the exception backtrace" do
683
+ loader.diagnose[:project_config][:raw_data][:error][:backtrace].
684
+ must_be_kind_of Array
685
+ end
686
+ end
687
+
688
+ describe "for local on error" do
689
+
690
+ before do
691
+ File.open("/tmp/.kitchen.local.yml", "wb") do |f|
692
+ f.write '&*%^*'
693
+ end
694
+ end
695
+
696
+ it "uses an error hash with the raw file contents" do
697
+ loader.diagnose[:local_config][:raw_data][:error][:raw_file].
698
+ must_equal "&*%^*"
699
+ end
700
+
701
+ it "uses an error hash with the exception" do
702
+ loader.diagnose[:local_config][:raw_data][:error][:exception].
703
+ must_match %r{Kitchen::UserError}
704
+ end
705
+
706
+ it "uses an error hash with the exception message" do
707
+ loader.diagnose[:local_config][:raw_data][:error][:message].
708
+ must_match %r{Error parsing}
709
+ end
710
+
711
+ it "uses an error hash with the exception backtrace" do
712
+ loader.diagnose[:local_config][:raw_data][:error][:backtrace].
713
+ must_be_kind_of Array
714
+ end
715
+ end
716
+
717
+ describe "for combined on error" do
718
+
719
+ before do
720
+ File.open("/tmp/.kitchen.yml", "wb") do |f|
721
+ f.write '&*%^*'
722
+ end
723
+ end
724
+
725
+ it "uses an error hash with nil raw file contents" do
726
+ loader.diagnose[:combined_config][:raw_data][:error][:raw_file].
727
+ must_equal nil
728
+ end
729
+
730
+ it "uses an error hash with the exception" do
731
+ loader.diagnose[:combined_config][:raw_data][:error][:exception].
732
+ must_match %r{Kitchen::UserError}
733
+ end
734
+
735
+ it "uses an error hash with the exception message" do
736
+ loader.diagnose[:combined_config][:raw_data][:error][:message].
737
+ must_match %r{Error parsing}
738
+ end
739
+
740
+ it "uses an error hash with the exception backtrace" do
741
+ loader.diagnose[:combined_config][:raw_data][:error][:backtrace].
742
+ must_be_kind_of Array
743
+ end
744
+ end
745
+ end
746
+ end
747
+
434
748
  private
435
749
 
436
750
  def stub_file(path, hash)