puppet-debugger 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +30 -13
- data/.rubocop.yml +3 -1
- data/.rubocop_todo.yml +11 -2
- data/.ruby-version +1 -1
- data/CHANGELOG.md +9 -0
- data/DEVELOPMENT.md +6 -1
- data/Gemfile +14 -12
- data/Plugin_development.md +304 -0
- data/README.md +4 -7
- data/Rakefile +6 -5
- data/bin/pdb +1 -0
- data/lib/awesome_print/ext/awesome_puppet.rb +1 -0
- data/lib/plugins/puppet-debugger/input_responders/benchmark.rb +40 -0
- data/lib/plugins/puppet-debugger/input_responders/classes.rb +15 -0
- data/lib/plugins/puppet-debugger/input_responders/classification.rb +14 -0
- data/lib/plugins/puppet-debugger/input_responders/commands.rb +95 -0
- data/lib/plugins/puppet-debugger/input_responders/datatypes.rb +17 -0
- data/lib/plugins/puppet-debugger/input_responders/environment.rb +14 -0
- data/lib/plugins/puppet-debugger/input_responders/exit.rb +14 -0
- data/lib/plugins/puppet-debugger/input_responders/facterdb_filter.rb +16 -0
- data/lib/plugins/puppet-debugger/input_responders/facts.rb +15 -0
- data/lib/plugins/puppet-debugger/input_responders/functions.rb +15 -0
- data/lib/plugins/puppet-debugger/input_responders/help.rb +14 -0
- data/lib/plugins/puppet-debugger/input_responders/krt.rb +14 -0
- data/lib/{puppet-debugger/support → plugins/puppet-debugger/input_responders}/play.rb +37 -26
- data/lib/plugins/puppet-debugger/input_responders/reset.rb +21 -0
- data/lib/plugins/puppet-debugger/input_responders/resources.rb +22 -0
- data/lib/plugins/puppet-debugger/input_responders/set.rb +55 -0
- data/lib/plugins/puppet-debugger/input_responders/types.rb +35 -0
- data/lib/plugins/puppet-debugger/input_responders/vars.rb +18 -0
- data/lib/plugins/puppet-debugger/input_responders/whereami.rb +29 -0
- data/lib/puppet-debugger.rb +12 -1
- data/lib/puppet-debugger/cli.rb +38 -22
- data/lib/puppet-debugger/code/code_file.rb +16 -15
- data/lib/puppet-debugger/code/code_range.rb +1 -0
- data/lib/puppet-debugger/code/loc.rb +1 -0
- data/lib/puppet-debugger/debugger_code.rb +1 -0
- data/lib/puppet-debugger/hooks.rb +174 -0
- data/lib/puppet-debugger/input_responder_plugin.rb +45 -0
- data/lib/puppet-debugger/plugin_test_helper.rb +44 -0
- data/lib/puppet-debugger/support.rb +13 -9
- data/lib/puppet-debugger/support/compiler.rb +1 -0
- data/lib/puppet-debugger/support/environment.rb +2 -0
- data/lib/puppet-debugger/support/errors.rb +9 -0
- data/lib/puppet-debugger/support/facts.rb +2 -1
- data/lib/puppet-debugger/support/functions.rb +3 -1
- data/lib/puppet-debugger/support/loader.rb +2 -0
- data/lib/puppet-debugger/support/node.rb +1 -0
- data/lib/puppet-debugger/support/scope.rb +1 -0
- data/lib/puppet/application/debugger.rb +1 -0
- data/lib/version.rb +2 -1
- data/puppet-debugger.gemspec +20 -15
- data/run_container_test.sh +1 -1
- data/spec/environment_spec.rb +2 -1
- data/spec/facts_spec.rb +1 -0
- data/spec/hooks_spec.rb +341 -0
- data/spec/input_responder_plugin_spec.rb +45 -0
- data/spec/input_responders/help_spec.rb +17 -0
- data/spec/input_responders/krt_spec.rb +12 -0
- data/spec/input_responders/play_spec.rb +160 -0
- data/spec/pdb_spec.rb +1 -0
- data/spec/puppet/application/debugger_spec.rb +1 -2
- data/spec/puppet_debugger_spec.rb +49 -88
- data/spec/remote_node_spec.rb +3 -2
- data/spec/spec_helper.rb +7 -0
- data/spec/support_spec.rb +5 -116
- data/test_matrix.rb +2 -0
- metadata +65 -12
- data/Gemfile.lock +0 -95
- data/lib/puppet-debugger/support/input_responders.rb +0 -191
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'puppet-debugger/support/errors'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module PuppetDebugger
|
6
|
+
class InputResponderPlugin
|
7
|
+
include Singleton
|
8
|
+
extend Forwardable
|
9
|
+
attr_accessor :debugger
|
10
|
+
def_delegators :debugger, :scope, :node, :environment,
|
11
|
+
:add_hook, :handle_input, :delete_hook, :function_map
|
12
|
+
def_delegators :scope, :compiler, :catalog
|
13
|
+
def_delegators :node, :facts
|
14
|
+
|
15
|
+
def self.command_words
|
16
|
+
self::COMMAND_WORDS
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.summary
|
20
|
+
self::SUMMARY
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.command_group
|
24
|
+
self::COMMAND_GROUP
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.details
|
28
|
+
{ words: command_words, summary: summary, group: command_group }
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param args [Array[String]] - an array of arguments to pass to the plugin command
|
32
|
+
# @param debugger PuppetDebugger::Cli - an instance of the PuppetDebugger::Cli object
|
33
|
+
# @return the output of the plugin command
|
34
|
+
def self.execute(args = [], debugger)
|
35
|
+
instance.debugger = debugger
|
36
|
+
instance.run(args)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param args [Array[String]] - an array of arguments to pass to the plugin command
|
40
|
+
# @return the output of the plugin command
|
41
|
+
def run(args = [])
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# https://relishapp.com/rspec/rspec-core/v/3-6/docs/example-groups/shared-examples
|
2
|
+
RSpec.shared_examples "plugin_tests" do |parameter|
|
3
|
+
let(:plugin) do
|
4
|
+
instance = PuppetDebugger::InputResponders::Commands.plugin_from_command(subject.to_s).instance
|
5
|
+
instance.debugger = debugger
|
6
|
+
instance
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:output) do
|
10
|
+
StringIO.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:debugger) do
|
14
|
+
PuppetDebugger::Cli.new({ out_buffer: output }.merge(options))
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:options) do
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
|
21
|
+
it "commands contant is an array" do
|
22
|
+
expect(plugin.class::COMMAND_WORDS).to be_a(Array)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "commands must contain at least one word" do
|
26
|
+
expect(plugin.class::COMMAND_WORDS.count).to be > 0
|
27
|
+
end
|
28
|
+
|
29
|
+
it "summary must be a string" do
|
30
|
+
expect(plugin.class::SUMMARY).to be_a(String)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'implements run' do
|
34
|
+
expect{plugin.run([])}.not_to raise_error(NotImplementedError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'be looked up via any command words' do
|
38
|
+
plugin.class::COMMAND_WORDS.each do |word|
|
39
|
+
actual = PuppetDebugger::InputResponders::Commands.plugin_from_command(word.to_s).instance.class
|
40
|
+
expect(actual).to eq(plugin.class)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'puppet/pops'
|
3
4
|
require 'facterdb'
|
4
5
|
require 'tempfile'
|
@@ -17,8 +18,6 @@ module PuppetDebugger
|
|
17
18
|
include PuppetDebugger::Support::Functions
|
18
19
|
include PuppetDebugger::Support::Node
|
19
20
|
include PuppetDebugger::Support::Loader
|
20
|
-
include PuppetDebugger::Support::InputResponders
|
21
|
-
include PuppetDebugger::Support::Play
|
22
21
|
|
23
22
|
# parses the error type into a more useful error message defined in errors.rb
|
24
23
|
# returns new error object or the original if error cannot be parsed
|
@@ -45,6 +44,10 @@ module PuppetDebugger
|
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
47
|
+
def static_responder_list
|
48
|
+
PuppetDebugger::InputResponders::Commands.command_list
|
49
|
+
end
|
50
|
+
|
48
51
|
# this is the lib directory of this gem
|
49
52
|
# in order to load any puppet functions from this gem we need to add the lib path
|
50
53
|
# of this gem
|
@@ -61,10 +64,6 @@ module PuppetDebugger
|
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
64
|
-
def keyword_expression
|
65
|
-
@keyword_expression ||= Regexp.new(/^exit|^:set|^play|^classification|^facts|^vars|^functions|^whereami|^classes|^resources|^krt|^environment|^reset|^help/)
|
66
|
-
end
|
67
|
-
|
68
67
|
def known_resource_types
|
69
68
|
res = {
|
70
69
|
hostclasses: scope.environment.known_resource_types.hostclasses.keys,
|
@@ -136,20 +135,25 @@ module PuppetDebugger
|
|
136
135
|
# because the repl is not a module we leave the modname blank
|
137
136
|
scope.environment.known_resource_types.import_ast(ast, '')
|
138
137
|
|
139
|
-
|
138
|
+
exec_hook :before_eval, '', self, self
|
139
|
+
if bench
|
140
140
|
result = nil
|
141
141
|
time = Benchmark.realtime do
|
142
142
|
result = parser.evaluate_string(scope, input, File.expand_path(file))
|
143
143
|
end
|
144
|
-
[result, "Time elapsed #{(time*1000).round(2)} ms"]
|
144
|
+
out = [result, "Time elapsed #{(time * 1000).round(2)} ms"]
|
145
145
|
else
|
146
|
-
parser.evaluate_string(scope, input, File.expand_path(file))
|
146
|
+
out = parser.evaluate_string(scope, input, File.expand_path(file))
|
147
147
|
end
|
148
|
+
exec_hook :after_eval, out, self, self
|
149
|
+
out
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
151
153
|
def puppet_lib_dir
|
152
154
|
# returns something like "/Library/Ruby/Gems/2.0.0/gems/puppet-4.2.2/lib/puppet.rb"
|
155
|
+
# "/Users/adam/.rbenv/versions/2.2.6/lib/ruby/gems/2.2.0/gems/puppet-4.9.4/lib"
|
156
|
+
|
153
157
|
# this is only useful when returning a namespace with the functions
|
154
158
|
@puppet_lib_dir ||= File.dirname(Puppet.method(:[]).source_location.first)
|
155
159
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module PuppetDebugger
|
3
4
|
module Support
|
4
5
|
module Environment
|
@@ -7,6 +8,7 @@ module PuppetDebugger
|
|
7
8
|
def puppet_environment
|
8
9
|
@puppet_environment ||= create_environment
|
9
10
|
end
|
11
|
+
alias :environment :puppet_environment
|
10
12
|
|
11
13
|
# returns an array of module directories, generally this is the only place
|
12
14
|
# to look for puppet code by default. This is read from the puppet configuration
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module PuppetDebugger
|
3
4
|
module Exception
|
4
5
|
class Error < StandardError
|
@@ -8,9 +9,17 @@ module PuppetDebugger
|
|
8
9
|
end
|
9
10
|
end
|
10
11
|
|
12
|
+
|
13
|
+
|
11
14
|
class FatalError < Error
|
12
15
|
end
|
13
16
|
|
17
|
+
class InvalidCommand < Error
|
18
|
+
def message
|
19
|
+
data[:message]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
14
23
|
class ConnectError < Error
|
15
24
|
def message
|
16
25
|
out = <<-EOF
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module PuppetDebugger
|
3
4
|
module Support
|
4
5
|
module Facts
|
@@ -46,7 +47,7 @@ module PuppetDebugger
|
|
46
47
|
node_facts = FacterDB.get_facts(dynamic_facterdb_filter).first
|
47
48
|
if node_facts.nil?
|
48
49
|
message = <<-EOS
|
49
|
-
Using filter: #{
|
50
|
+
Using filter: #{dynamic_facterdb_filter}
|
50
51
|
Bad FacterDB filter, please change the filter so it returns a result set.
|
51
52
|
See https://github.com/camptocamp/facterdb/#with-a-string-filter
|
52
53
|
EOS
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module PuppetDebugger
|
3
4
|
module Support
|
4
5
|
module Functions
|
@@ -43,7 +44,8 @@ module PuppetDebugger
|
|
43
44
|
obj = {}
|
44
45
|
name = File.basename(file, '.rb')
|
45
46
|
obj[:name] = name
|
46
|
-
|
47
|
+
# return the last matched in cases where rbenv might be involved
|
48
|
+
obj[:parent] = file.scan(mod_finder).flatten.last
|
47
49
|
@functions["#{obj[:parent]}::#{name}"] = obj
|
48
50
|
end
|
49
51
|
end
|
data/lib/version.rb
CHANGED
data/puppet-debugger.gemspec
CHANGED
@@ -1,37 +1,42 @@
|
|
1
1
|
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require './lib/version'
|
3
5
|
require 'date'
|
4
6
|
|
5
7
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
8
|
+
s.name = 'puppet-debugger'
|
7
9
|
s.version = PuppetDebugger::VERSION
|
8
10
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|resources|local_test_results|pec)/}) }
|
9
|
-
s.bindir =
|
10
|
-
s.executables = [
|
11
|
+
s.bindir = 'bin'
|
12
|
+
s.executables = ['pdb']
|
11
13
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
12
14
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
13
15
|
if s.respond_to?(:metadata)
|
14
16
|
s.metadata['allowed_push_host'] = 'https://rubygems.org'
|
15
17
|
else
|
16
|
-
raise
|
18
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
17
19
|
end
|
18
|
-
s.required_rubygems_version = Gem::Requirement.new(
|
19
|
-
s.require_paths = [
|
20
|
-
s.authors = [
|
20
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
21
|
+
s.require_paths = ['lib']
|
22
|
+
s.authors = ['Corey Osman']
|
21
23
|
s.date = DateTime.now.strftime('%Y-%m-%d')
|
22
|
-
s.description =
|
23
|
-
s.email =
|
24
|
+
s.description = 'A interactive command line tool for evaluating and debugging the puppet language'
|
25
|
+
s.email = 'corey@nwops.io'
|
24
26
|
s.extra_rdoc_files = [
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
'CHANGELOG.md',
|
28
|
+
'LICENSE.txt',
|
29
|
+
'README.md'
|
28
30
|
]
|
29
31
|
s.homepage = "http://github.com/nwops/puppet-debugger"
|
30
32
|
s.licenses = ["MIT"]
|
31
33
|
s.rubygems_version = "2.4.5.1"
|
32
34
|
s.summary = "A repl based debugger for the puppet language"
|
35
|
+
s.add_runtime_dependency(%q<pluginator>, ["~> 1.4.1"])
|
33
36
|
s.add_runtime_dependency(%q<puppet>, [">= 3.8"])
|
34
|
-
s.add_runtime_dependency(%q<facterdb>, ["
|
35
|
-
s.add_runtime_dependency(%q<awesome_print>, ["~> 1.
|
37
|
+
s.add_runtime_dependency(%q<facterdb>, ["~> 0.3.1"])
|
38
|
+
s.add_runtime_dependency(%q<awesome_print>, ["~> 1.7"])
|
36
39
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
37
|
-
|
40
|
+
s.add_development_dependency(%q<rspec>, ["~> 3.6"])
|
41
|
+
|
42
|
+
end
|
data/run_container_test.sh
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
export PATH=$PATH:/usr/local/bundle
|
3
3
|
gem install bundler > /dev/null
|
4
4
|
gem update --system > /dev/null
|
5
|
-
bundle
|
5
|
+
bundle update
|
6
6
|
bundle exec puppet module install puppetlabs-stdlib
|
7
7
|
echo "Running tests, output to ${OUT_DIR}/results.txt"
|
8
8
|
bundle exec rspec --out "${OUT_DIR}/results.txt" --format documentation
|
data/spec/environment_spec.rb
CHANGED
data/spec/facts_spec.rb
CHANGED
data/spec/hooks_spec.rb
ADDED
@@ -0,0 +1,341 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe PuppetDebugger::Hooks do
|
4
|
+
before do
|
5
|
+
@hooks = PuppetDebugger::Hooks.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:output) do
|
9
|
+
StringIO.new
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:debugger) do
|
13
|
+
PuppetDebugger::Cli.new(out_buffer: output)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "adding a new hook" do
|
17
|
+
it 'should not execute hook while adding it' do
|
18
|
+
run = false
|
19
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
20
|
+
expect(run).to eq false
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should not allow adding of a hook with a duplicate name' do
|
24
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
25
|
+
|
26
|
+
expect { @hooks.add_hook(:test_hook, :my_name) {} }.to raise_error ArgumentError
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should create a new hook with a block' do
|
30
|
+
@hooks.add_hook(:test_hook, :my_name) { }
|
31
|
+
expect(@hooks.hook_count(:test_hook)).to eq 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should create a new hook with a callable' do
|
35
|
+
@hooks.add_hook(:test_hook, :my_name, proc { })
|
36
|
+
expect(@hooks.hook_count(:test_hook)).to eq 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should use block if given both block and callable' do
|
40
|
+
run = false
|
41
|
+
foo = false
|
42
|
+
@hooks.add_hook(:test_hook, :my_name, proc { foo = true }) { run = true }
|
43
|
+
expect(@hooks.hook_count(:test_hook)).to eq 1
|
44
|
+
@hooks.exec_hook(:test_hook)
|
45
|
+
expect(run).to eq true
|
46
|
+
expect(foo).to eq false
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should raise if not given a block or any other object' do
|
50
|
+
expect { @hooks.add_hook(:test_hook, :my_name) }.to raise_error ArgumentError
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should create multiple hooks for an event' do
|
54
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
55
|
+
@hooks.add_hook(:test_hook, :my_name2) {}
|
56
|
+
expect(@hooks.hook_count(:test_hook)).to eq 2
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return a count of 0 for an empty hook' do
|
60
|
+
expect(@hooks.hook_count(:test_hook)).to eq 0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "PuppetDebugger::Hooks#merge" do
|
65
|
+
describe "merge!" do
|
66
|
+
it 'should merge in the PuppetDebugger::Hooks' do
|
67
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
68
|
+
h2 = PuppetDebugger::Hooks.new
|
69
|
+
|
70
|
+
h2.merge!(h1)
|
71
|
+
expect(h2.get_hook(:test_hook, :testing)).to eq h1.get_hook(:test_hook, :testing)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should not share merged elements with original' do
|
75
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
76
|
+
h2 = PuppetDebugger::Hooks.new
|
77
|
+
|
78
|
+
h2.merge!(h1)
|
79
|
+
h2.add_hook(:test_hook, :testing2) {}
|
80
|
+
expect(h2.get_hook(:test_hook, :testing2)).not_to eq h1.get_hook(:test_hook, :testing2)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should NOT overwrite hooks belonging to shared event in receiver' do
|
84
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
85
|
+
callable = proc {}
|
86
|
+
h2 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing2, callable)
|
87
|
+
|
88
|
+
h2.merge!(h1)
|
89
|
+
expect(h2.get_hook(:test_hook, :testing2)).to eq callable
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should overwrite identical hook in receiver' do
|
93
|
+
callable1 = proc { :one }
|
94
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing, callable1)
|
95
|
+
callable2 = proc { :two }
|
96
|
+
h2 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing, callable2)
|
97
|
+
|
98
|
+
h2.merge!(h1)
|
99
|
+
expect(h2.get_hook(:test_hook, :testing)).to eq callable1
|
100
|
+
expect(h2.hook_count(:test_hook)).to eq 1
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should preserve hook order' do
|
104
|
+
name = ""
|
105
|
+
h1 = PuppetDebugger::Hooks.new
|
106
|
+
h1.add_hook(:test_hook, :testing3) { name << "h" }
|
107
|
+
h1.add_hook(:test_hook, :testing4) { name << "n" }
|
108
|
+
|
109
|
+
h2 = PuppetDebugger::Hooks.new
|
110
|
+
h2.add_hook(:test_hook, :testing1) { name << "j" }
|
111
|
+
h2.add_hook(:test_hook, :testing2) { name << "o" }
|
112
|
+
|
113
|
+
h2.merge!(h1)
|
114
|
+
h2.exec_hook(:test_hook)
|
115
|
+
|
116
|
+
expect(name).to eq "john"
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "merge" do
|
120
|
+
it 'should return a fresh, independent instance' do
|
121
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
122
|
+
h2 = PuppetDebugger::Hooks.new
|
123
|
+
|
124
|
+
h3 = h2.merge(h1)
|
125
|
+
expect(h3).not_to eq h1
|
126
|
+
expect(h3).not_to eq h2
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should contain hooks from original instance' do
|
130
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
131
|
+
h2 = PuppetDebugger::Hooks.new.add_hook(:test_hook2, :testing) {}
|
132
|
+
|
133
|
+
h3 = h2.merge(h1)
|
134
|
+
expect(h3.get_hook(:test_hook, :testing)).to eq h1.get_hook(:test_hook, :testing)
|
135
|
+
expect(h3.get_hook(:test_hook2, :testing)).to eq h2.get_hook(:test_hook2, :testing)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should not affect original instances when new hooks are added' do
|
139
|
+
h1 = PuppetDebugger::Hooks.new.add_hook(:test_hook, :testing) {}
|
140
|
+
h2 = PuppetDebugger::Hooks.new.add_hook(:test_hook2, :testing) {}
|
141
|
+
|
142
|
+
h3 = h2.merge(h1)
|
143
|
+
h3.add_hook(:test_hook3, :testing) {}
|
144
|
+
|
145
|
+
expect(h1.get_hook(:test_hook3, :testing)).to eq nil
|
146
|
+
expect(h2.get_hook(:test_hook3, :testing)).to eq nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "dupping a PuppetDebugger::Hooks instance" do
|
154
|
+
it 'should share hooks with original' do
|
155
|
+
@hooks.add_hook(:test_hook, :testing) do
|
156
|
+
:none_such
|
157
|
+
end
|
158
|
+
|
159
|
+
hooks_dup = @hooks.dup
|
160
|
+
expect(hooks_dup.get_hook(:test_hook, :testing)).to eq @hooks.get_hook(:test_hook, :testing)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'adding a new event to dupped instance should not affect original' do
|
164
|
+
@hooks.add_hook(:test_hook, :testing) { :none_such }
|
165
|
+
hooks_dup = @hooks.dup
|
166
|
+
|
167
|
+
hooks_dup.add_hook(:other_test_hook, :testing) { :okay_man }
|
168
|
+
|
169
|
+
expect(hooks_dup.get_hook(:other_test_hook, :testing)).not_to eq @hooks.get_hook(:other_test_hook, :testing)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'adding a new hook to dupped instance should not affect original' do
|
173
|
+
@hooks.add_hook(:test_hook, :testing) { :none_such }
|
174
|
+
hooks_dup = @hooks.dup
|
175
|
+
|
176
|
+
hooks_dup.add_hook(:test_hook, :testing2) { :okay_man }
|
177
|
+
|
178
|
+
expect(hooks_dup.get_hook(:test_hook, :testing2)).not_to eq @hooks.get_hook(:test_hook, :testing2)
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "getting hooks" do
|
184
|
+
describe "get_hook" do
|
185
|
+
it 'should return the correct requested hook' do
|
186
|
+
run = false
|
187
|
+
fun = false
|
188
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
189
|
+
@hooks.add_hook(:test_hook, :my_name2) { fun = true }
|
190
|
+
@hooks.get_hook(:test_hook, :my_name).call
|
191
|
+
expect(run).to eq true
|
192
|
+
expect(fun).to eq false
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should return nil if hook does not exist' do
|
196
|
+
expect(@hooks.get_hook(:test_hook, :my_name)).to eq nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "get_hooks" do
|
201
|
+
it 'should return a hash of hook names/hook functions for an event' do
|
202
|
+
hook1 = proc { 1 }
|
203
|
+
hook2 = proc { 2 }
|
204
|
+
@hooks.add_hook(:test_hook, :my_name1, hook1)
|
205
|
+
@hooks.add_hook(:test_hook, :my_name2, hook2)
|
206
|
+
hash = @hooks.get_hooks(:test_hook)
|
207
|
+
expect(hash.size).to eq 2
|
208
|
+
expect(hash[:my_name1]).to eq hook1
|
209
|
+
expect(hash[:my_name2]).to eq hook2
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should return an empty hash if no hooks defined' do
|
213
|
+
expect(@hooks.get_hooks(:test_hook)).to eq({})
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "clearing all hooks for an event" do
|
219
|
+
it 'should clear all hooks' do
|
220
|
+
@hooks.add_hook(:test_hook, :my_name) { }
|
221
|
+
@hooks.add_hook(:test_hook, :my_name2) { }
|
222
|
+
@hooks.add_hook(:test_hook, :my_name3) { }
|
223
|
+
@hooks.clear_event_hooks(:test_hook)
|
224
|
+
expect(@hooks.hook_count(:test_hook)).to eq 0
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "deleting a hook" do
|
229
|
+
it 'should successfully delete a hook' do
|
230
|
+
@hooks.add_hook(:test_hook, :my_name) {}
|
231
|
+
@hooks.delete_hook(:test_hook, :my_name)
|
232
|
+
expect(@hooks.hook_count(:test_hook)).to eq 0
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should return the deleted hook' do
|
236
|
+
run = false
|
237
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
238
|
+
@hooks.delete_hook(:test_hook, :my_name).call
|
239
|
+
expect(run).to eq true
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should return nil if hook does not exist' do
|
243
|
+
expect(@hooks.delete_hook(:test_hook, :my_name)).to eq nil
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "executing a hook" do
|
248
|
+
it 'should execute block hook' do
|
249
|
+
run = false
|
250
|
+
@hooks.add_hook(:test_hook, :my_name) { run = true }
|
251
|
+
@hooks.exec_hook(:test_hook)
|
252
|
+
expect(run).to eq true
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should execute proc hook' do
|
256
|
+
run = false
|
257
|
+
@hooks.add_hook(:test_hook, :my_name, proc { run = true })
|
258
|
+
@hooks.exec_hook(:test_hook)
|
259
|
+
expect(run).to eq true
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should execute a general callable hook' do
|
263
|
+
callable = Object.new.tap do |obj|
|
264
|
+
obj.instance_variable_set(:@test_var, nil)
|
265
|
+
class << obj
|
266
|
+
attr_accessor :test_var
|
267
|
+
def call() @test_var = true; end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
@hooks.add_hook(:test_hook, :my_name, callable)
|
272
|
+
@hooks.exec_hook(:test_hook)
|
273
|
+
expect(callable.test_var).to eq true
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'should execute all hooks for an event if more than one is defined' do
|
277
|
+
x = nil
|
278
|
+
y = nil
|
279
|
+
@hooks.add_hook(:test_hook, :my_name1) { y = true }
|
280
|
+
@hooks.add_hook(:test_hook, :my_name2) { x = true }
|
281
|
+
@hooks.exec_hook(:test_hook)
|
282
|
+
expect(x).to eq true
|
283
|
+
expect(y).to eq true
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'should execute hooks in order' do
|
287
|
+
array = []
|
288
|
+
@hooks.add_hook(:test_hook, :my_name1) { array << 1 }
|
289
|
+
@hooks.add_hook(:test_hook, :my_name2) { array << 2 }
|
290
|
+
@hooks.add_hook(:test_hook, :my_name3) { array << 3 }
|
291
|
+
@hooks.exec_hook(:test_hook)
|
292
|
+
expect(array).to eq [1, 2, 3]
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'return value of exec_hook should be that of last executed hook' do
|
296
|
+
@hooks.add_hook(:test_hook, :my_name1) { 1 }
|
297
|
+
@hooks.add_hook(:test_hook, :my_name2) { 2 }
|
298
|
+
@hooks.add_hook(:test_hook, :my_name3) { 3 }
|
299
|
+
expect(@hooks.exec_hook(:test_hook)).to eq 3
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'should add exceptions to the errors array' do
|
303
|
+
@hooks.add_hook(:test_hook, :foo1) { raise 'one' }
|
304
|
+
@hooks.add_hook(:test_hook, :foo2) { raise 'two' }
|
305
|
+
@hooks.add_hook(:test_hook, :foo3) { raise 'three' }
|
306
|
+
@hooks.exec_hook(:test_hook)
|
307
|
+
expect(@hooks.errors.map(&:message)).to eq ['one', 'two', 'three']
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should return the last exception raised as the return value' do
|
311
|
+
@hooks.add_hook(:test_hook, :foo1) { raise 'one' }
|
312
|
+
@hooks.add_hook(:test_hook, :foo2) { raise 'two' }
|
313
|
+
@hooks.add_hook(:test_hook, :foo3) { raise 'three' }
|
314
|
+
expect(@hooks.exec_hook(:test_hook)).to eq @hooks.errors.last
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "anonymous hooks" do
|
319
|
+
it 'should allow adding of hook without a name' do
|
320
|
+
@hooks.add_hook(:test_hook, nil) {}
|
321
|
+
expect(@hooks.hook_count(:test_hook)).to eq 1
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'should only allow one anonymous hook to exist' do
|
325
|
+
@hooks.add_hook(:test_hook, nil) { }
|
326
|
+
@hooks.add_hook(:test_hook, nil) { }
|
327
|
+
expect(@hooks.hook_count(:test_hook)).to eq 1
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'should execute most recently added anonymous hook' do
|
331
|
+
x = nil
|
332
|
+
y = nil
|
333
|
+
@hooks.add_hook(:test_hook, nil) { y = 1 }
|
334
|
+
@hooks.add_hook(:test_hook, nil) { x = 2 }
|
335
|
+
@hooks.exec_hook(:test_hook)
|
336
|
+
expect(y).to eq nil
|
337
|
+
expect(x).to eq 2
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
end
|