1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
RSpec::Support.require_rspec_core "formatters/base_formatter"
require 'control_group_data'
require 'ffi_yajl'
class Chef
class Audit
class ChefJsonFormatter < ::RSpec::Core::Formatters::BaseFormatter
::RSpec::Core::Formatters.register self, :example_group_started, :message, :stop, :close, :example_failed
attr_reader :control_group_data
# TODO hopefully the runner can take care of this for us since there won't be an outer-most
# control group
@@outer_example_group_found = false
def initialize(output)
super
end
# Invoked for each `control`, `describe`, `context` block
def example_group_started(notification)
unless @@outer_example_group_found
@control_group_data = ControlGroupData.new(notification.group.description)
@@outer_example_group_found = true
end
end
def example_failed(notification)
e = notification.example.metadata[:execution_result].exception
raise e unless e.kind_of? ::RSpec::Expectations::ExpectationNotMetError
end
def message(notification)
puts "message: #{notification}"
end
def stop(notification)
notification.examples.each do |example|
control_data = build_control_from(example)
e = example.exception
if e
control = control_group_data.example_failure(e.message, control_data)
else
control = control_group_data.example_success(control_data)
end
control.line_number = example.metadata[:line_number]
end
end
def close(notification)
output.write FFI_Yajl::Encoder.encode(control_group_data.to_hash, pretty: true)
output.close if IO === output && output != $stdout
end
private
def build_control_from(example)
described_class = example.metadata[:described_class]
if described_class
resource_type = described_class.class.name.split(':')[-1]
# TODO submit github PR to expose this
resource_name = described_class.instance_variable_get(:@name)
end
describe_groups = []
group = example.metadata[:example_group]
# If the innermost block has a resource instead of a string, don't include it in context
describe_groups.unshift(group[:description]) if described_class.nil?
group = group[:parent_example_group]
while !group.nil?
describe_groups.unshift(group[:description])
group = group[:parent_example_group]
end
# TODO remove this when we're no longer wrapping everything with "mysql audit"
describe_groups.shift
{
:name => example.description,
:desc => example.full_description,
:resource_type => resource_type,
:resource_name => resource_name,
:context => describe_groups
}
end
end
end
end
|