test_bench-telemetry 2.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/lib/test_bench/telemetry/controls/capture_sink/path.rb +30 -0
  3. data/lib/test_bench/telemetry/controls/capture_sink/record.rb +21 -0
  4. data/lib/test_bench/telemetry/controls/comment.rb +19 -0
  5. data/lib/test_bench/telemetry/controls/detail_level.rb +15 -0
  6. data/lib/test_bench/telemetry/controls/error.rb +36 -0
  7. data/lib/test_bench/telemetry/controls/event.rb +77 -0
  8. data/lib/test_bench/telemetry/controls/events/asserted.rb +32 -0
  9. data/lib/test_bench/telemetry/controls/events/commented.rb +26 -0
  10. data/lib/test_bench/telemetry/controls/events/context_entered.rb +31 -0
  11. data/lib/test_bench/telemetry/controls/events/context_exited.rb +34 -0
  12. data/lib/test_bench/telemetry/controls/events/context_skipped.rb +31 -0
  13. data/lib/test_bench/telemetry/controls/events/detail_decreased.rb +23 -0
  14. data/lib/test_bench/telemetry/controls/events/detail_increased.rb +23 -0
  15. data/lib/test_bench/telemetry/controls/events/error_raised.rb +26 -0
  16. data/lib/test_bench/telemetry/controls/events/file_entered.rb +29 -0
  17. data/lib/test_bench/telemetry/controls/events/file_exited.rb +32 -0
  18. data/lib/test_bench/telemetry/controls/events/fixture_finished.rb +29 -0
  19. data/lib/test_bench/telemetry/controls/events/fixture_started.rb +26 -0
  20. data/lib/test_bench/telemetry/controls/events/run_aborted.rb +29 -0
  21. data/lib/test_bench/telemetry/controls/events/run_finished.rb +32 -0
  22. data/lib/test_bench/telemetry/controls/events/run_started.rb +29 -0
  23. data/lib/test_bench/telemetry/controls/events/test_finished.rb +34 -0
  24. data/lib/test_bench/telemetry/controls/events/test_skipped.rb +31 -0
  25. data/lib/test_bench/telemetry/controls/events/test_started.rb +31 -0
  26. data/lib/test_bench/telemetry/controls/events.rb +27 -0
  27. data/lib/test_bench/telemetry/controls/fixture_name.rb +19 -0
  28. data/lib/test_bench/telemetry/controls/handler.rb +76 -0
  29. data/lib/test_bench/telemetry/controls/line_number.rb +10 -0
  30. data/lib/test_bench/telemetry/controls/path.rb +87 -0
  31. data/lib/test_bench/telemetry/controls/random.rb +7 -0
  32. data/lib/test_bench/telemetry/controls/result.rb +12 -0
  33. data/lib/test_bench/telemetry/controls/sink.rb +11 -0
  34. data/lib/test_bench/telemetry/controls/time.rb +76 -0
  35. data/lib/test_bench/telemetry/controls/title.rb +43 -0
  36. data/lib/test_bench/telemetry/controls.rb +40 -0
  37. data/lib/test_bench/telemetry/event/events.rb +35 -0
  38. data/lib/test_bench/telemetry/event/serialization.rb +143 -0
  39. data/lib/test_bench/telemetry/event/type.rb +27 -0
  40. data/lib/test_bench/telemetry/event.rb +41 -0
  41. data/lib/test_bench/telemetry/sink/capture/path.rb +69 -0
  42. data/lib/test_bench/telemetry/sink/capture/record/generate.rb +49 -0
  43. data/lib/test_bench/telemetry/sink/capture/record.rb +73 -0
  44. data/lib/test_bench/telemetry/sink/capture.rb +55 -0
  45. data/lib/test_bench/telemetry/sink/file.rb +31 -0
  46. data/lib/test_bench/telemetry/sink/handler.rb +90 -0
  47. data/lib/test_bench/telemetry/substitute.rb +65 -0
  48. data/lib/test_bench/telemetry/telemetry.rb +68 -0
  49. data/lib/test_bench/telemetry.rb +19 -0
  50. metadata +118 -0
@@ -0,0 +1,27 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Event
4
+ module Type
5
+ def self.get(class_name)
6
+ *, constant_name = class_name.split('::')
7
+
8
+ constant_name.to_sym
9
+ end
10
+
11
+ def self.method_cased(event_type)
12
+ pascal_cased = event_type.to_s
13
+
14
+ underscore_cased = pascal_cased.gsub(%r{(?:\A|[a-z])[A-Z]+}) do |match_text|
15
+ if ('a'..'z').include?(match_text[0])
16
+ match_text.insert(1, '_')
17
+ end
18
+ match_text.downcase!
19
+ match_text
20
+ end
21
+
22
+ underscore_cased.to_sym
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Event
4
+ def self.define(*attribute_names)
5
+ Struct.new(*attribute_names, :time) do
6
+ include Event
7
+ end
8
+ end
9
+
10
+ def self.included(cls)
11
+ cls.class_exec do
12
+ extend EventType
13
+ end
14
+ end
15
+
16
+ def self.each_event_type(&block)
17
+ Events.constants(false).each(&block)
18
+ end
19
+
20
+ def event_type
21
+ self.class.event_type
22
+ end
23
+
24
+ def dump
25
+ Serialization.dump(self)
26
+ end
27
+
28
+ def self.load(data, event_namespace=nil)
29
+ event_namespace ||= Events
30
+
31
+ Serialization.load(data, event_namespace)
32
+ end
33
+
34
+ module EventType
35
+ def event_type
36
+ @event_type ||= Type.get(name)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,69 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ class Capture
5
+ class Path
6
+ def segments
7
+ @segments ||= []
8
+ end
9
+ attr_writer :segments
10
+
11
+ def match?(*segments, segment)
12
+ if not segment == self.segments.last
13
+ return false
14
+ end
15
+
16
+ segment_iterator = self.segments.to_enum
17
+
18
+ control_segments = [*segments, segment]
19
+
20
+ control_segments.all? do |control_segment|
21
+ begin
22
+ next_segment = segment_iterator.next
23
+ end until next_segment == control_segment
24
+ true
25
+
26
+ rescue StopIteration
27
+ false
28
+ end
29
+ end
30
+
31
+ def push_segment(segment)
32
+ segments << segment
33
+ end
34
+ alias :push :push_segment
35
+ alias :<< :push
36
+
37
+ def pop_segment(compare_segment=nil)
38
+ segments.pop
39
+ end
40
+ alias :pop :pop_segment
41
+
42
+ def copy(receiver)
43
+ path = self.class.new
44
+
45
+ segments.each do |segment|
46
+ path << segment
47
+ end
48
+
49
+ receiver.path = path
50
+ path
51
+ end
52
+
53
+ def copy?(compare_path)
54
+ eql?(compare_path) && !equal?(compare_path)
55
+ end
56
+
57
+ def eql?(compare)
58
+ if compare.is_a?(self.class)
59
+ segments == compare.segments
60
+ else
61
+ false
62
+ end
63
+ end
64
+ alias :== :eql?
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,49 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ class Capture
5
+ class Record
6
+ class Generate
7
+ include Event::Events
8
+
9
+ def path
10
+ @path ||= Path.new
11
+ end
12
+ attr_writer :path
13
+
14
+ def detail_level
15
+ @detail_level ||= 0
16
+ end
17
+ attr_writer :detail_level
18
+
19
+ def call(event)
20
+ case event
21
+ when TestStarted, ContextEntered
22
+ path.push(event.title)
23
+ when TestFinished, ContextExited
24
+ path.pop(event.title)
25
+ when DetailIncreased
26
+ self.detail_level += 1
27
+ when DetailDecreased
28
+ self.detail_level -= 1
29
+ end
30
+
31
+ record = Record.build(event, path, detail_level)
32
+
33
+ case event
34
+ when TestFinished, ContextExited
35
+ title = event.title
36
+ record.path.push(title)
37
+ when Commented
38
+ comment = event.comment
39
+ record.path.push(comment)
40
+ end
41
+
42
+ record
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,73 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ class Capture
5
+ Record = Struct.new(:event, :path, :detail_level) do
6
+ def self.build(event, path, detail_level)
7
+ instance = new
8
+ instance.event = event
9
+ instance.detail_level = detail_level
10
+
11
+ path.copy(instance)
12
+
13
+ instance
14
+ end
15
+
16
+ def match?(*path_segments, detail: nil, detail_level: nil, &block)
17
+ if not path_segments?(*path_segments)
18
+ false
19
+ elsif not detail?(detail)
20
+ false
21
+ elsif not detail_level?(detail_level)
22
+ false
23
+ elsif not block?(&block)
24
+ false
25
+ else
26
+ true
27
+ end
28
+ end
29
+
30
+ def detail_match?(match)
31
+ if match.nil?
32
+ true
33
+ elsif match
34
+ detail_level > 0
35
+ else
36
+ detail_level.zero?
37
+ end
38
+ end
39
+ alias :detail? :detail_match?
40
+
41
+ def detail_level_match?(detail_level)
42
+ if detail_level.nil?
43
+ true
44
+ else
45
+ detail_level == self.detail_level
46
+ end
47
+ end
48
+ alias :detail_level? :detail_level_match?
49
+
50
+ def path_segments_match?(*segments)
51
+ if segments.empty?
52
+ true
53
+ else
54
+ path.match?(*segments)
55
+ end
56
+ end
57
+ alias :path_segments? :path_segments_match?
58
+
59
+ def block_match?(&block)
60
+ if block.nil?
61
+ true
62
+ elsif block.(event.event_type, *event.values)
63
+ true
64
+ else
65
+ false
66
+ end
67
+ end
68
+ alias :block? :block_match?
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,55 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ class Capture
5
+ include Sink
6
+
7
+ MatchError = Class.new(RuntimeError)
8
+
9
+ def raw_records
10
+ @raw_records ||= []
11
+ end
12
+
13
+ def generate_record
14
+ @generate_record ||= Record::Generate.new
15
+ end
16
+ attr_writer :generate_record
17
+
18
+ def call(event)
19
+ record = generate_record.(event)
20
+
21
+ raw_records.push(record)
22
+
23
+ record
24
+ end
25
+
26
+ def one_record?(...)
27
+ record = one_record(...)
28
+
29
+ !record.nil?
30
+ end
31
+
32
+ def one_record(...)
33
+ records = records(...)
34
+
35
+ if records.count > 1
36
+ raise MatchError, "More than one record matches (Matching Records: #{records.count})"
37
+ end
38
+
39
+ records.first
40
+ end
41
+
42
+ def any_record?(...)
43
+ records(...).any?
44
+ end
45
+ alias :record? :any_record?
46
+
47
+ def records(...)
48
+ raw_records.select do |record|
49
+ record.match?(...)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,31 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ class File
5
+ include Sink
6
+
7
+ attr_reader :io
8
+
9
+ def initialize(io)
10
+ @io = io
11
+ end
12
+
13
+ def self.open(path, &block)
14
+ ::File.open(path, 'w') do |io|
15
+ instance = new(io)
16
+
17
+ block.(instance, io)
18
+
19
+ return instance
20
+ end
21
+ end
22
+
23
+ def call(event)
24
+ data = event.dump
25
+
26
+ io.write(data)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,90 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Sink
4
+ module Handler
5
+ def self.included(cls)
6
+ cls.class_exec do
7
+ include Sink
8
+
9
+ extend HandlerMethod
10
+ extend HandleMacro
11
+
12
+ include Event::Events
13
+ end
14
+ end
15
+
16
+ def handle(event)
17
+ handles = handle?(event)
18
+
19
+ if handles
20
+ handler_method = handler_method(event)
21
+
22
+ parameters = method(handler_method).parameters
23
+
24
+ final_parameter_type, _ = parameters.last
25
+ if not final_parameter_type == :rest
26
+ parameter_count = parameters.count
27
+
28
+ arguments = event.values[0...parameter_count]
29
+ else
30
+ arguments = event.values
31
+ end
32
+
33
+ __send__(handler_method, *arguments)
34
+
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+ alias :call :handle
41
+
42
+ def handle?(event_or_event_type)
43
+ handler_method = handler_method(event_or_event_type)
44
+
45
+ not handler_method.nil?
46
+ end
47
+
48
+ def handler_method(event_or_event_type)
49
+ handler_method = self.class.handler_method(event_or_event_type)
50
+
51
+ if respond_to?(handler_method)
52
+ handler_method
53
+ else
54
+ nil
55
+ end
56
+ end
57
+
58
+ module HandleMacro
59
+ def handle_macro(event_class, &block)
60
+ event_type = event_class
61
+
62
+ handler_method = HandlerMethod.get(event_type)
63
+
64
+ define_method(handler_method, &block)
65
+ end
66
+ alias :handle :handle_macro
67
+ end
68
+
69
+ module HandlerMethod
70
+ def handler_method(event_or_event_type)
71
+ HandlerMethod.get(event_or_event_type)
72
+ end
73
+
74
+ def self.get(event_or_event_type)
75
+ if event_or_event_type.is_a?(Symbol)
76
+ event_type = event_or_event_type
77
+ else
78
+ event = event_or_event_type
79
+ event_type = event.event_type
80
+ end
81
+
82
+ event_type_method_cased = Event::Type.method_cased(event_type)
83
+
84
+ :"handle_#{event_type_method_cased}"
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,65 @@
1
+ module TestBench
2
+ class Telemetry
3
+ module Substitute
4
+ def self.build
5
+ Telemetry.build
6
+ end
7
+
8
+ class Telemetry < Telemetry
9
+ def capture_sink
10
+ @capture_sink ||= Sink::Capture.new
11
+ end
12
+
13
+ def self.build
14
+ instance = new
15
+ instance.register(instance.capture_sink)
16
+ instance
17
+ end
18
+
19
+ Event.each_event_type do |event_type|
20
+ event_type_method_cased = Event::Type.method_cased(event_type)
21
+
22
+ module_eval(<<~RUBY, __FILE__, __LINE__)
23
+ def one_#{event_type_method_cased}_record?(*arguments, **keyword_arguments, &block)
24
+ one_record?(*arguments, **keyword_arguments) do |compare_event_type, *event_values|
25
+ if compare_event_type == #{event_type.inspect}
26
+ block.(*event_values)
27
+ end
28
+ end
29
+ end
30
+
31
+ def one_#{event_type_method_cased}_record(*arguments, **keyword_arguments, &block)
32
+ one_record(*arguments, **keyword_arguments) do |compare_event_type, *event_values|
33
+ if compare_event_type == #{event_type.inspect}
34
+ block.(*event_values)
35
+ end
36
+ end
37
+ end
38
+
39
+ def any_#{event_type_method_cased}_record?(*arguments, **keyword_arguments, &block)
40
+ any_record?(*arguments, **keyword_arguments) do |compare_event_type, *event_values|
41
+ if compare_event_type == #{event_type.inspect}
42
+ block.(*event_values)
43
+ end
44
+ end
45
+ end
46
+ alias :#{event_type_method_cased}_record? :any_#{event_type_method_cased}_record?
47
+
48
+ def #{event_type_method_cased}_records(*arguments, **keyword_arguments, &block)
49
+ records(*arguments, **keyword_arguments) do |compare_event_type, *event_values|
50
+ if compare_event_type == #{event_type.inspect}
51
+ block.(*event_values)
52
+ end
53
+ end
54
+ end
55
+ RUBY
56
+ end
57
+
58
+ def one_record?(...) = capture_sink.one_record?(...)
59
+ def one_record(...) = capture_sink.one_record(...)
60
+ def any_record?(...) = capture_sink.any_record?(...)
61
+ def records(...) = capture_sink.records(...)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,68 @@
1
+ module TestBench
2
+ class Telemetry
3
+ include Event::Events
4
+
5
+ RegistrationError = Class.new(RuntimeError)
6
+
7
+ def sinks
8
+ @sinks ||= []
9
+ end
10
+
11
+ def self.build(*sinks)
12
+ instance = new
13
+
14
+ sinks.each do |sink|
15
+ instance.register(sink)
16
+ end
17
+
18
+ instance
19
+ end
20
+
21
+ def self.configure(receiver, *sinks, attr_name: nil)
22
+ attr_name ||= :telemetry
23
+
24
+ instance = build(*sinks)
25
+ receiver.public_send(:"#{attr_name}=", instance)
26
+ end
27
+
28
+ def record(event, now=nil)
29
+ event.time ||= current_time(now)
30
+
31
+ sinks.each do |sink|
32
+ sink.(event)
33
+ end
34
+
35
+ event
36
+ end
37
+
38
+ def register(sink)
39
+ if registered?(sink)
40
+ raise RegistrationError, "Already registered #{sink.inspect}"
41
+ end
42
+
43
+ sinks << sink
44
+ end
45
+
46
+ def registered?(sink)
47
+ sinks.include?(sink)
48
+ end
49
+
50
+ Event.each_event_type do |event_type|
51
+ event_class = Event.const_get(event_type)
52
+
53
+ event_type_method_cased = Event::Type.method_cased(event_type)
54
+
55
+ module_eval(<<~RUBY, __FILE__, __LINE__)
56
+ def record_#{event_type_method_cased}(*values)
57
+ event = #{event_class}.new(*values)
58
+
59
+ record(event)
60
+ end
61
+ RUBY
62
+ end
63
+
64
+ def current_time(now)
65
+ now || ::Time.now
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_bench/random'
2
+
3
+ require 'test_bench/telemetry/event'
4
+ require 'test_bench/telemetry/event/type'
5
+ require 'test_bench/telemetry/event/serialization'
6
+ require 'test_bench/telemetry/event/events'
7
+
8
+ require 'test_bench/telemetry/sink/handler'
9
+
10
+ require 'test_bench/telemetry/sink/capture/path'
11
+ require 'test_bench/telemetry/sink/capture/record'
12
+ require 'test_bench/telemetry/sink/capture/record/generate'
13
+ require 'test_bench/telemetry/sink/capture'
14
+
15
+ require 'test_bench/telemetry/sink/file'
16
+
17
+ require 'test_bench/telemetry/telemetry'
18
+
19
+ require 'test_bench/telemetry/substitute'