tracing-matchers 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []