tracing-matchers 1.0.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.
@@ -0,0 +1,99 @@
1
+ module Tracing
2
+ module Matchers
3
+ module Span
4
+ # @private
5
+ class BeChildOf
6
+ def initialize(parent)
7
+ @expected = parent
8
+ end
9
+
10
+ # @return [Boolean]
11
+ def matches?(span)
12
+ @tracer = span.tracer
13
+ @subject = span
14
+ # actual is either Span, or SpanContext
15
+ @actual = parent_of(@subject)
16
+
17
+ case
18
+ when any? then !!@actual
19
+ when @actual.nil? && @expected then false
20
+ else
21
+ expected_span_id == actual_span_id
22
+ end
23
+ end
24
+
25
+ # @return [String]
26
+ def description
27
+ any? ? "have a parent" : "have #{expected_message} as the parent"
28
+ end
29
+
30
+ # @return [String]
31
+ def failure_message
32
+ any? ? "expected a parent" : "expected #{expected_message} as the parent, got #{actual_message}"
33
+ end
34
+ alias :failure_message_for_should :failure_message
35
+
36
+ # @return [String]
37
+ def failure_message_when_negated
38
+ any? ? "did not expect the parent" : "did not expect #{expected_message} parent, got #{actual_message}"
39
+ end
40
+ alias :failure_message_for_should_not :failure_message_when_negated
41
+
42
+ private
43
+
44
+ def any?
45
+ @expected == :any
46
+ end
47
+
48
+ def parent_of(subject)
49
+ return nil unless subject.context.parent_span_id
50
+
51
+ parent_span = @tracer
52
+ .spans
53
+ .find { |span| span.context.span_id == subject.context.parent_span_id }
54
+
55
+ parent_span || subject.context
56
+ end
57
+
58
+ def actual_span_id
59
+ case
60
+ when @actual.respond_to?(:context) then @actual.context.span_id
61
+ when @actual.respond_to?(:parent_span_id) then @actual.parent_span_id
62
+ else @actual
63
+ end
64
+ end
65
+
66
+ def expected_span_id
67
+ case
68
+ when @expected.respond_to?(:context) then @expected.context.span_id
69
+ when @expected.respond_to?(:span_id) then @expected.span_id
70
+ when @expected.is_a?(String) then @tracer.spans.find { |span| span.operation_name == @expected }&.context&.span_id
71
+ else @expected
72
+ end
73
+ end
74
+
75
+ def expected_spans(tracer)
76
+ tracer.spans.select { |span| span.operation_name == @expected }
77
+ end
78
+
79
+ def expected_message
80
+ case
81
+ when @expected.respond_to?(:context) then "the span with operation name \"#{@expected.operation_name}\""
82
+ when @expected.respond_to?(:span_id) then "the span context with id \"#{@expected.span_id}\""
83
+ when @expected.is_a?(String) then "a span with operation name \"#{@expected}\""
84
+ else nil
85
+ end
86
+ end
87
+
88
+ def actual_message
89
+ case
90
+ when @actual.respond_to?(:operation_name) then "a span with operation name \"#{@actual.operation_name}\""
91
+ when @actual.respond_to?(:parent_span_id) then "a span context with id \"#{@actual.parent_span_id}\""
92
+ when @actual.nil? then "nothing"
93
+ else @actual
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,50 @@
1
+ module Tracing
2
+ module Matchers
3
+ module Span
4
+ # @private
5
+ class HaveBaggage
6
+ def initialize(*args)
7
+ @expected = args.last.is_a?(Hash) ? args.delete_at(-1) : Hash.new
8
+ args.each_slice(2) { |k, v| @expected[k] = v }
9
+ end
10
+
11
+ # @return [Boolean]
12
+ def matches?(span)
13
+ @subject = span
14
+ @actual = span.context.baggage
15
+
16
+ if any?
17
+ @actual.any?
18
+ else
19
+ @expected.all? { |k, v| @actual.key?(k) && v == @actual[k] }
20
+ end
21
+ end
22
+
23
+ # @return [String]
24
+ def description
25
+ desc = "have baggage"
26
+ desc << " #{@expected}" unless any?
27
+ desc
28
+ end
29
+
30
+ # @return [String]
31
+ def failure_message
32
+ any? ? "expected any baggage" : "expected #{@expected} baggage, got #{@actual}"
33
+ end
34
+ alias :failure_message_for_should :failure_message
35
+
36
+ # @return [String]
37
+ def failure_message_when_negated
38
+ any? ? "did not expect any baggage" : "did not expect #{@expected} baggage, got #{@actual}"
39
+ end
40
+ alias :failure_message_for_should_not :failure_message_when_negated
41
+
42
+ private
43
+
44
+ def any?
45
+ @expected.empty?
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,51 @@
1
+ module Tracing
2
+ module Matchers
3
+ module Span
4
+ # @private
5
+ class HaveLog
6
+ def initialize(**fields)
7
+ @expected = fields
8
+ end
9
+
10
+ # @return [Boolean]
11
+ def matches?(span)
12
+ @subject = span
13
+ @actual = span.logs.map { |log| log.fields.dup.tap { |h| h[:event] = log.event } }
14
+
15
+ if any?
16
+ @actual.any?
17
+ else
18
+ @actual.any? do |log|
19
+ @expected.all? { |k, v| log.key?(k) && v == log[k] }
20
+ end
21
+ end
22
+ end
23
+
24
+ # @return [String]
25
+ def description
26
+ desc = "have log entry"
27
+ desc << " #{@expected}" unless any?
28
+ desc
29
+ end
30
+
31
+ # @return [String]
32
+ def failure_message
33
+ any? ? "expected any log entry" : "expected #{@expected} log entry, got #{@actual}"
34
+ end
35
+ alias :failure_message_for_should :failure_message
36
+
37
+ # @return [String]
38
+ def failure_message_when_negated
39
+ any? ? "did not expect any log entry" : "did not expect #{@expected} log entry, got #{@actual}"
40
+ end
41
+ alias :failure_message_for_should_not :failure_message_when_negated
42
+
43
+ private
44
+
45
+ def any?
46
+ @expected.empty?
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ module Tracing
2
+ module Matchers
3
+ module Span
4
+ # @private
5
+ class HaveTag
6
+ def initialize(*args)
7
+ @expected = args.last.is_a?(Hash) ? args.delete_at(-1) : Hash.new
8
+ args.each_slice(2) { |k, v| @expected[k] = v }
9
+ end
10
+
11
+ # @return [Boolean]
12
+ def matches?(span)
13
+ @subject = span
14
+ @actual = span.tags
15
+
16
+ if any?
17
+ @actual.any?
18
+ else
19
+ @expected.all? { |k, v| @actual.key?(k) && v == @actual[k] }
20
+ end
21
+ end
22
+
23
+ # @return [String]
24
+ def description
25
+ desc = "have tags"
26
+ desc << " #{@expected}" unless any?
27
+ desc
28
+ end
29
+
30
+ # @return [String]
31
+ def failure_message
32
+ any? ? "expected any tag" : "expected #{@expected} tags, got #{@actual}"
33
+ end
34
+ alias :failure_message_for_should :failure_message
35
+
36
+ # @return [String]
37
+ def failure_message_when_negated
38
+ any? ? "did not expect any tag" : "did not expect #{@expected} tags, got #{@actual}"
39
+ end
40
+ alias :failure_message_for_should_not :failure_message_when_negated
41
+
42
+ private
43
+
44
+ def any?
45
+ @expected.empty?
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,72 @@
1
+ require "tracing/matchers/span/have_tag"
2
+ require "tracing/matchers/span/have_log"
3
+ require "tracing/matchers/span/have_baggage"
4
+ require "tracing/matchers/span/be_child_of"
5
+
6
+ module Tracing
7
+ module Matchers
8
+ # The `have_tag` matcher tests that the span includes tags.
9
+ # @example
10
+ #
11
+ # # Passes if span have any tag
12
+ # expect(span).to have_tag
13
+ #
14
+ # # Passes if span includes a tag with "tag" key, and "value" value
15
+ # expect(span).to have_tag("key", "value")
16
+ # expect(span).to have_tag("key" => "value")
17
+ #
18
+ # @return [HaveTag]
19
+ def have_tag(*args)
20
+ Tracing::Matchers::Span::HaveTag.new(*args)
21
+ end
22
+ alias :have_tags :have_tag
23
+
24
+ # The `have_log` matcher tests that the span includes a tag.
25
+ # @example
26
+ #
27
+ # # Passes if span have any log
28
+ # expect(span).to have_log
29
+ #
30
+ # # Passes if span includes a log entry with event: "error"
31
+ # expect(span).to have_log(event: "error")
32
+ #
33
+ # @return [HaveTag]
34
+ def have_log(**fields)
35
+ Tracing::Matchers::Span::HaveLog.new(**fields)
36
+ end
37
+ alias :have_logs :have_log
38
+
39
+ # The `have_baggage` matcher tests that the span/span context includes baggage.
40
+ # @example
41
+ #
42
+ # # Passes if span have any baggage item
43
+ # expect(span).to have_baggage
44
+ #
45
+ # # Passes if span includes a baggage item with "tag" key, and "value" value
46
+ # expect(span).to have_baggage("key", "value")
47
+ # expect(span).to have_baggage("key" => "value")
48
+ #
49
+ # @return [HaveBaggage]
50
+ def have_baggage(*args)
51
+ Tracing::Matchers::Span::HaveBaggage.new(*args)
52
+ end
53
+ alias :have_baggage_item :have_baggage
54
+
55
+ # The `be_child_of` matcher tests that the span/span context is a child of some other span/span context.
56
+ # @example
57
+ #
58
+ # # Passes if span is a child of any span
59
+ # expect(span).to have_parent
60
+ #
61
+ # # Passes if span is a child of a specific span context
62
+ # expect(span).to be_child_of("parent operation")
63
+ # expect(span).to be_child_of(parent_span)
64
+ # expect(span).to be_child_of(parent_span_context)
65
+ #
66
+ # @return [HaveBaggage]
67
+ def be_child_of(parent = :any)
68
+ Tracing::Matchers::Span::BeChildOf.new(parent)
69
+ end
70
+ alias :have_parent :be_child_of
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ module Tracing
2
+ module Matchers
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "tracing/matchers/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tracing-matchers"
8
+ spec.version = Tracing::Matchers::VERSION
9
+ spec.authors = ["iaintshine"]
10
+ spec.email = ["bodziomista@gmail.com"]
11
+
12
+ spec.summary = %q{RSpec matchers for testing mocked OpenTracing instrumentations}
13
+ spec.description = %q{}
14
+ spec.homepage = "https://github.com/iaintshine/ruby-tracing-matchers"
15
+ spec.license = "Apache-2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "test-tracer", "~> 1.1"
25
+ spec.add_dependency "rspec", ">= 2.0"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.15"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tracing-matchers
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - iaintshine
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: test-tracer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.15'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.15'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ description: ''
70
+ email:
71
+ - bodziomista@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".ruby-version"
79
+ - ".travis.yml"
80
+ - CODE_OF_CONDUCT.md
81
+ - Gemfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - bin/console
86
+ - bin/setup
87
+ - lib/tracing/matchers.rb
88
+ - lib/tracing/matchers/have_span.rb
89
+ - lib/tracing/matchers/have_spans.rb
90
+ - lib/tracing/matchers/have_traces.rb
91
+ - lib/tracing/matchers/span/be_child_of.rb
92
+ - lib/tracing/matchers/span/have_baggage.rb
93
+ - lib/tracing/matchers/span/have_log.rb
94
+ - lib/tracing/matchers/span/have_tag.rb
95
+ - lib/tracing/matchers/span_matchers.rb
96
+ - lib/tracing/matchers/version.rb
97
+ - tracing-matchers.gemspec
98
+ homepage: https://github.com/iaintshine/ruby-tracing-matchers
99
+ licenses:
100
+ - Apache-2.0
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.6.12
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: RSpec matchers for testing mocked OpenTracing instrumentations
122
+ test_files: []