test-kitchen 0.7.0 → 1.0.0.alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. data/.gitignore +20 -0
  2. data/.travis.yml +11 -0
  3. data/.yardopts +3 -0
  4. data/Gemfile +13 -0
  5. data/Guardfile +11 -0
  6. data/LICENSE +15 -0
  7. data/README.md +131 -0
  8. data/Rakefile +69 -0
  9. data/bin/kitchen +9 -4
  10. data/features/cli.feature +17 -0
  11. data/features/cli_init.feature +156 -0
  12. data/features/support/env.rb +14 -0
  13. data/lib/kitchen/busser.rb +166 -0
  14. data/lib/kitchen/chef_data_uploader.rb +156 -0
  15. data/lib/kitchen/cli.rb +540 -0
  16. data/lib/kitchen/collection.rb +55 -0
  17. data/lib/kitchen/color.rb +46 -0
  18. data/lib/kitchen/config.rb +223 -0
  19. data/lib/kitchen/driver/base.rb +180 -0
  20. data/lib/kitchen/driver/dummy.rb +81 -0
  21. data/lib/kitchen/driver/ssh_base.rb +192 -0
  22. data/lib/kitchen/driver.rb +42 -0
  23. data/lib/kitchen/errors.rb +52 -0
  24. data/lib/kitchen/instance.rb +327 -0
  25. data/lib/kitchen/instance_actor.rb +42 -0
  26. data/lib/kitchen/loader/yaml.rb +105 -0
  27. data/lib/kitchen/logger.rb +145 -0
  28. data/{cookbooks/test-kitchen/libraries/helpers.rb → lib/kitchen/logging.rb} +13 -9
  29. data/lib/kitchen/manager.rb +45 -0
  30. data/lib/kitchen/metadata_chopper.rb +52 -0
  31. data/lib/kitchen/platform.rb +61 -0
  32. data/lib/kitchen/rake_tasks.rb +59 -0
  33. data/lib/kitchen/shell_out.rb +65 -0
  34. data/lib/kitchen/state_file.rb +88 -0
  35. data/lib/kitchen/suite.rb +76 -0
  36. data/lib/kitchen/thor_tasks.rb +62 -0
  37. data/lib/kitchen/util.rb +79 -0
  38. data/{cookbooks/test-kitchen/recipes/erlang.rb → lib/kitchen/version.rb} +9 -6
  39. data/lib/kitchen.rb +98 -0
  40. data/lib/vendor/hash_recursive_merge.rb +74 -0
  41. data/spec/kitchen/collection_spec.rb +80 -0
  42. data/spec/kitchen/color_spec.rb +54 -0
  43. data/spec/kitchen/config_spec.rb +201 -0
  44. data/spec/kitchen/driver/dummy_spec.rb +191 -0
  45. data/spec/kitchen/instance_spec.rb +162 -0
  46. data/spec/kitchen/loader/yaml_spec.rb +243 -0
  47. data/spec/kitchen/platform_spec.rb +48 -0
  48. data/spec/kitchen/state_file_spec.rb +122 -0
  49. data/spec/kitchen/suite_spec.rb +64 -0
  50. data/spec/spec_helper.rb +47 -0
  51. data/templates/plugin/driver.rb.erb +23 -0
  52. data/templates/plugin/license_apachev2.erb +15 -0
  53. data/templates/plugin/license_gplv2.erb +18 -0
  54. data/templates/plugin/license_gplv3.erb +16 -0
  55. data/templates/plugin/license_mit.erb +22 -0
  56. data/templates/plugin/license_reserved.erb +5 -0
  57. data/templates/plugin/version.rb.erb +12 -0
  58. data/test-kitchen.gemspec +44 -0
  59. metadata +290 -82
  60. data/config/Cheffile +0 -47
  61. data/config/Kitchenfile +0 -39
  62. data/config/Vagrantfile +0 -114
  63. data/cookbooks/test-kitchen/attributes/default.rb +0 -25
  64. data/cookbooks/test-kitchen/metadata.rb +0 -27
  65. data/cookbooks/test-kitchen/recipes/chef.rb +0 -19
  66. data/cookbooks/test-kitchen/recipes/compat.rb +0 -39
  67. data/cookbooks/test-kitchen/recipes/default.rb +0 -51
  68. data/cookbooks/test-kitchen/recipes/ruby.rb +0 -29
  69. data/lib/test-kitchen/cli/destroy.rb +0 -36
  70. data/lib/test-kitchen/cli/init.rb +0 -37
  71. data/lib/test-kitchen/cli/platform_list.rb +0 -37
  72. data/lib/test-kitchen/cli/project_info.rb +0 -44
  73. data/lib/test-kitchen/cli/ssh.rb +0 -36
  74. data/lib/test-kitchen/cli/status.rb +0 -36
  75. data/lib/test-kitchen/cli/test.rb +0 -68
  76. data/lib/test-kitchen/cli.rb +0 -282
  77. data/lib/test-kitchen/dsl.rb +0 -63
  78. data/lib/test-kitchen/environment.rb +0 -166
  79. data/lib/test-kitchen/platform.rb +0 -79
  80. data/lib/test-kitchen/project/base.rb +0 -159
  81. data/lib/test-kitchen/project/cookbook.rb +0 -97
  82. data/lib/test-kitchen/project/cookbook_copy.rb +0 -58
  83. data/lib/test-kitchen/project/ruby.rb +0 -37
  84. data/lib/test-kitchen/project/supported_platforms.rb +0 -75
  85. data/lib/test-kitchen/project.rb +0 -23
  86. data/lib/test-kitchen/runner/base.rb +0 -154
  87. data/lib/test-kitchen/runner/openstack/dsl.rb +0 -39
  88. data/lib/test-kitchen/runner/openstack/environment.rb +0 -141
  89. data/lib/test-kitchen/runner/openstack.rb +0 -147
  90. data/lib/test-kitchen/runner/vagrant.rb +0 -95
  91. data/lib/test-kitchen/runner.rb +0 -21
  92. data/lib/test-kitchen/scaffold.rb +0 -88
  93. data/lib/test-kitchen/ui.rb +0 -73
  94. data/lib/test-kitchen/version.rb +0 -21
  95. data/lib/test-kitchen.rb +0 -34
@@ -0,0 +1,76 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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
+ module Kitchen
20
+
21
+ # A Chef run_list and attribute hash that will be used in a convergence
22
+ # integration.
23
+ #
24
+ # @author Fletcher Nichol <fnichol@nichol.ca>
25
+ class Suite
26
+
27
+ # @return [String] logical name of this suite
28
+ attr_reader :name
29
+
30
+ # @return [Array] Array of Chef run_list items
31
+ attr_reader :run_list
32
+
33
+ # @return [Hash] Hash of Chef node attributes
34
+ attr_reader :attributes
35
+
36
+ # @return [Array] Array of names of excluded platforms
37
+ attr_reader :excludes
38
+
39
+ # @return [String] local path to the suite's data bags, or nil if one does
40
+ # not exist
41
+ attr_reader :data_bags_path
42
+
43
+ # @return [String] local path to the suite's roles, or nil if one does
44
+ # not exist
45
+ attr_reader :roles_path
46
+
47
+ # Constructs a new suite.
48
+ #
49
+ # @param [Hash] options configuration for a new suite
50
+ # @option options [String] :name logical name of this suit (**Required**)
51
+ # @option options [String] :run_list Array of Chef run_list items
52
+ # (**Required**)
53
+ # @option options [Hash] :attributes Hash of Chef node attributes
54
+ # @option options [String] :excludes Array of names of excluded platforms
55
+ # @option options [String] :data_bags_path path to data bags
56
+ # @option options [String] :roles_path path to roles
57
+ def initialize(options = {})
58
+ validate_options(options)
59
+
60
+ @name = options[:name]
61
+ @run_list = options[:run_list]
62
+ @attributes = options[:attributes] || Hash.new
63
+ @excludes = options[:excludes] || Array.new
64
+ @data_bags_path = options[:data_bags_path]
65
+ @roles_path = options[:roles_path]
66
+ end
67
+
68
+ private
69
+
70
+ def validate_options(opts)
71
+ [:name, :run_list].each do |k|
72
+ raise ClientError, "Suite#new requires option :#{k}" if opts[k].nil?
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,62 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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 'thor'
20
+
21
+ require 'kitchen'
22
+
23
+ module Kitchen
24
+
25
+ # Kitchen Thor task generator.
26
+ #
27
+ # @author Fletcher Nichol <fnichol@nichol.ca>
28
+ class ThorTasks < Thor
29
+
30
+ namespace :kitchen
31
+
32
+ # Creates Kitchen Thor tasks and allows the callee to configure it.
33
+ #
34
+ # @yield [self] gives itself to the block
35
+ def initialize(*args)
36
+ super
37
+ @config = Kitchen::Config.new
38
+ @config.supervised = false
39
+ Kitchen.logger = Kitchen.default_file_logger
40
+ yield self if block_given?
41
+ define
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :config
47
+
48
+ def define
49
+ config.instances.each do |instance|
50
+ self.class.desc instance.name, "Run #{instance.name} test instance"
51
+ self.class.send(:define_method, instance.name.gsub(/-/, '_')) do
52
+ instance.test(:always)
53
+ end
54
+ end
55
+
56
+ self.class.desc "all", "Run all test instances"
57
+ self.class.send(:define_method, :all) do
58
+ config.instances.each { |i| invoke i.name.gsub(/-/, '_') }
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,79 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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
+ module Kitchen
20
+
21
+ # Stateless utility methods used in different contexts. Essentially a mini
22
+ # PassiveSupport library.
23
+ module Util
24
+
25
+ def self.to_camel_case(str)
26
+ str.split('_').map { |w| w.capitalize }.join
27
+ end
28
+
29
+ def self.to_snake_case(str)
30
+ str.split('::').
31
+ last.
32
+ gsub(/([A-Z+])([A-Z][a-z])/, '\1_\2').
33
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
34
+ downcase
35
+ end
36
+
37
+ def self.to_logger_level(symbol)
38
+ return nil unless [:debug, :info, :warn, :error, :fatal].include?(symbol)
39
+
40
+ Logger.const_get(symbol.to_s.upcase)
41
+ end
42
+
43
+ def self.from_logger_level(const)
44
+ case const
45
+ when Logger::DEBUG then :debug
46
+ when Logger::INFO then :info
47
+ when Logger::WARN then :warn
48
+ when Logger::ERROR then :error
49
+ else :fatal
50
+ end
51
+ end
52
+
53
+ def self.symbolized_hash(obj)
54
+ if obj.is_a?(Hash)
55
+ obj.inject({}) { |h, (k, v)| h[k.to_sym] = symbolized_hash(v) ; h }
56
+ elsif obj.is_a?(Array)
57
+ obj.inject([]) { |a, v| a << symbolized_hash(v) ; a }
58
+ else
59
+ obj
60
+ end
61
+ end
62
+
63
+ def self.stringified_hash(obj)
64
+ if obj.is_a?(Hash)
65
+ obj.inject({}) { |h, (k, v)| h[k.to_s] = symbolized_hash(v) ; h }
66
+ elsif obj.is_a?(Array)
67
+ obj.inject([]) { |a, v| a << symbolized_hash(v) ; a }
68
+ else
69
+ obj
70
+ end
71
+ end
72
+
73
+ def self.duration(total)
74
+ minutes = (total / 60).to_i
75
+ seconds = (total - (minutes * 60))
76
+ "(%dm%.2fs)" % [minutes, seconds]
77
+ end
78
+ end
79
+ end
@@ -1,19 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
1
2
  #
2
- # Author:: Seth Chisamore (<schisamo@opscode.com>)
3
- # Copyright:: Copyright (c) 2012 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
8
9
  # You may obtain a copy of the License at
9
10
  #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
+ # http://www.apache.org/licenses/LICENSE-2.0
11
12
  #
12
13
  # Unless required by applicable law or agreed to in writing, software
13
14
  # distributed under the License is distributed on an "AS IS" BASIS,
14
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
16
  # See the License for the specific language governing permissions and
16
17
  # limitations under the License.
17
- #
18
18
 
19
- # TODO - write this!
19
+ module Kitchen
20
+
21
+ VERSION = "1.0.0.alpha.0"
22
+ end
data/lib/kitchen.rb ADDED
@@ -0,0 +1,98 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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 'celluloid'
20
+ require 'pathname'
21
+ require 'thread'
22
+
23
+ require 'kitchen/errors'
24
+ require 'kitchen/logger'
25
+ require 'kitchen/logging'
26
+ require 'kitchen/shell_out'
27
+ require 'kitchen/util'
28
+
29
+ require 'kitchen/busser'
30
+ require 'kitchen/chef_data_uploader'
31
+ require 'kitchen/color'
32
+ require 'kitchen/collection'
33
+ require 'kitchen/config'
34
+ require 'kitchen/driver'
35
+ require 'kitchen/driver/base'
36
+ require 'kitchen/driver/ssh_base'
37
+ require 'kitchen/instance'
38
+ require 'kitchen/instance_actor'
39
+ require 'kitchen/loader/yaml'
40
+ require 'kitchen/manager'
41
+ require 'kitchen/metadata_chopper'
42
+ require 'kitchen/platform'
43
+ require 'kitchen/state_file'
44
+ require 'kitchen/suite'
45
+ require 'kitchen/version'
46
+
47
+ module Kitchen
48
+
49
+ class << self
50
+
51
+ attr_accessor :logger
52
+ attr_accessor :crashes
53
+ attr_accessor :mutex
54
+
55
+ # Returns the root path of the Kitchen gem source code.
56
+ #
57
+ # @return [Pathname] root path of gem
58
+ def source_root
59
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
60
+ end
61
+
62
+ def crashes?
63
+ ! crashes.empty?
64
+ end
65
+
66
+ def default_logger
67
+ Logger.new(:stdout => STDOUT, :level => env_log)
68
+ end
69
+
70
+ def default_file_logger
71
+ logfile = File.expand_path(File.join(".kitchen", "logs", "kitchen.log"))
72
+ Logger.new(:stdout => STDOUT, :logdev => logfile, :level => env_log)
73
+ end
74
+
75
+ private
76
+
77
+ def env_log
78
+ level = ENV['KITCHEN_LOG'] && ENV['KITCHEN_LOG'].downcase.to_sym
79
+ level = Util.to_logger_level(level) unless level.nil?
80
+ end
81
+ end
82
+
83
+ # Default log level verbosity
84
+ DEFAULT_LOG_LEVEL = :info
85
+ end
86
+
87
+ # Initialize the base logger and use that for Celluloid's logger
88
+ Kitchen.logger = Kitchen.default_logger
89
+ Celluloid.logger = Kitchen.logger
90
+
91
+ # Setup a collection of instance crash exceptions for error reporting
92
+ Kitchen.crashes = []
93
+ Celluloid.exception_handler do |exception|
94
+ Kitchen.logger.debug("An instance crashed because of #{exception.inspect}")
95
+ Kitchen.mutex.synchronize { Kitchen.crashes << exception }
96
+ end
97
+
98
+ Kitchen.mutex = Mutex.new
@@ -0,0 +1,74 @@
1
+ #
2
+ # = Hash Recursive Merge
3
+ #
4
+ # Merges a Ruby Hash recursively, Also known as deep merge.
5
+ # Recursive version of Hash#merge and Hash#merge!.
6
+ #
7
+ # Category:: Ruby
8
+ # Package:: Hash
9
+ # Author:: Simone Carletti <weppos@weppos.net>
10
+ # Copyright:: 2007-2008 The Authors
11
+ # License:: MIT License
12
+ # Link:: http://www.simonecarletti.com/
13
+ # Source:: http://gist.github.com/gists/6391/
14
+ #
15
+ module HashRecursiveMerge
16
+
17
+ #
18
+ # Recursive version of Hash#merge!
19
+ #
20
+ # Adds the contents of +other_hash+ to +hsh+,
21
+ # merging entries in +hsh+ with duplicate keys with those from +other_hash+.
22
+ #
23
+ # Compared with Hash#merge!, this method supports nested hashes.
24
+ # When both +hsh+ and +other_hash+ contains an entry with the same key,
25
+ # it merges and returns the values from both arrays.
26
+ #
27
+ # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
28
+ # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
29
+ # h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
30
+ #
31
+ # Simply using Hash#merge! would return
32
+ #
33
+ # h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
34
+ #
35
+ def rmerge!(other_hash)
36
+ merge!(other_hash) do |key, oldval, newval|
37
+ oldval.class == self.class ? oldval.rmerge!(newval) : newval
38
+ end
39
+ end
40
+
41
+ #
42
+ # Recursive version of Hash#merge
43
+ #
44
+ # Compared with Hash#merge!, this method supports nested hashes.
45
+ # When both +hsh+ and +other_hash+ contains an entry with the same key,
46
+ # it merges and returns the values from both arrays.
47
+ #
48
+ # Compared with Hash#merge, this method provides a different approch
49
+ # for merging nasted hashes.
50
+ # If the value of a given key is an Hash and both +other_hash+ abd +hsh
51
+ # includes the same key, the value is merged instead replaced with
52
+ # +other_hash+ value.
53
+ #
54
+ # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
55
+ # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
56
+ # h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
57
+ #
58
+ # Simply using Hash#merge would return
59
+ #
60
+ # h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
61
+ #
62
+ def rmerge(other_hash)
63
+ r = {}
64
+ merge(other_hash) do |key, oldval, newval|
65
+ r[key] = oldval.class == self.class ? oldval.rmerge(newval) : newval
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+
72
+ class Hash
73
+ include HashRecursiveMerge
74
+ end
@@ -0,0 +1,80 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
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_relative '../spec_helper'
20
+ require 'ostruct'
21
+
22
+ require 'kitchen/collection'
23
+
24
+ describe Kitchen::Collection do
25
+
26
+ let(:collection) do
27
+ Kitchen::Collection.new([
28
+ obj('one'), obj('two', 'a'), obj('two', 'b'), obj('three')
29
+ ])
30
+ end
31
+
32
+ it "transparently wraps an Array" do
33
+ collection.must_be_instance_of Array
34
+ end
35
+
36
+ describe "#get" do
37
+
38
+ it "returns a single object by its name" do
39
+ collection.get('three').must_equal obj('three')
40
+ end
41
+
42
+ it "returns the first occurance of an object by its name" do
43
+ collection.get('two').must_equal obj('two', 'a')
44
+ end
45
+
46
+ it "returns nil if an object cannot be found by its name" do
47
+ collection.get('nope').must_be_nil
48
+ end
49
+ end
50
+
51
+ describe "#get_all" do
52
+
53
+ it "returns a Collection of objects whose name matches the regex" do
54
+ result = collection.get_all(/(one|three)/)
55
+ result.size.must_equal 2
56
+ result[0].must_equal obj('one')
57
+ result[1].must_equal obj('three')
58
+ result.get_all(/one/).size.must_equal 1
59
+ end
60
+
61
+ it "returns an empty Collection if on matches are found" do
62
+ result = collection.get_all(/noppa/)
63
+ result.must_equal []
64
+ result.get("nahuh").must_be_nil
65
+ end
66
+ end
67
+
68
+ describe "#as_name" do
69
+
70
+ it "returns an Array of names as strings" do
71
+ collection.as_names.must_equal %w{one two two three}
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def obj(name, extra = nil)
78
+ OpenStruct.new(:name => name, :extra => extra)
79
+ end
80
+ end
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, Fletcher Nichol
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_relative '../spec_helper'
20
+
21
+ require 'kitchen/color'
22
+
23
+ describe Kitchen::Color do
24
+
25
+ describe ".escape" do
26
+
27
+ it "returns an empty string if name is nil" do
28
+ Kitchen::Color.escape(nil).must_equal ""
29
+ end
30
+
31
+ it "returns an empty string if name is not in the ANSI hash" do
32
+ Kitchen::Color.escape(:puce).must_equal ""
33
+ end
34
+
35
+ it "returns an ansi escape sequence string for cyan" do
36
+ Kitchen::Color.escape(:cyan).must_equal "\e[36m"
37
+ end
38
+
39
+ it "returns an ansi escape sequence string for reset" do
40
+ Kitchen::Color.escape(:reset).must_equal "\e[0m"
41
+ end
42
+ end
43
+
44
+ describe ".colorize" do
45
+
46
+ it "returns an ansi escaped string colored yellow" do
47
+ Kitchen::Color.colorize("hello", :yellow).must_equal "\e[33mhello\e[0m"
48
+ end
49
+
50
+ it "returns an unescaped string if color is not in the ANSI hash" do
51
+ Kitchen::Color.colorize("double", :rainbow).must_equal "double"
52
+ end
53
+ end
54
+ end