test_bench-isolated 0 → 2.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/lib/test_bench/isolated.rb +1 -0
  3. data/lib/test_bench_isolated/test_bench/cli.rb +298 -0
  4. data/lib/test_bench_isolated/test_bench/controls/file.rb +7 -0
  5. data/lib/test_bench_isolated/test_bench/controls/path.rb +7 -0
  6. data/lib/test_bench_isolated/test_bench/controls/random.rb +9 -0
  7. data/lib/test_bench_isolated/test_bench/controls/result.rb +7 -0
  8. data/lib/test_bench_isolated/test_bench/controls/stdin.rb +29 -0
  9. data/lib/test_bench_isolated/test_bench/controls.rb +11 -0
  10. data/lib/test_bench_isolated/test_bench/fixture/actuate/class.rb +97 -0
  11. data/lib/test_bench_isolated/test_bench/fixture/actuate/object.rb +93 -0
  12. data/lib/test_bench_isolated/test_bench/fixture/controls/exception.rb +9 -0
  13. data/lib/test_bench_isolated/test_bench/fixture/controls/fixture/class.rb +88 -0
  14. data/lib/test_bench_isolated/test_bench/fixture/controls/fixture/object/modules.rb +41 -0
  15. data/lib/test_bench_isolated/test_bench/fixture/controls/fixture/object.rb +33 -0
  16. data/lib/test_bench_isolated/test_bench/fixture/controls/fixture.rb +29 -0
  17. data/lib/test_bench_isolated/test_bench/fixture/controls/output.rb +9 -0
  18. data/lib/test_bench_isolated/test_bench/fixture/controls/random.rb +9 -0
  19. data/lib/test_bench_isolated/test_bench/fixture/controls/result.rb +9 -0
  20. data/lib/test_bench_isolated/test_bench/fixture/controls/title.rb +9 -0
  21. data/lib/test_bench_isolated/test_bench/fixture/controls.rb +13 -0
  22. data/lib/test_bench_isolated/test_bench/fixture/evaluate.rb +31 -0
  23. data/lib/test_bench_isolated/test_bench/fixture/fixture.rb +201 -0
  24. data/lib/test_bench_isolated/test_bench/fixture.rb +8 -0
  25. data/lib/test_bench_isolated/test_bench/output/controls/data.rb +51 -0
  26. data/lib/test_bench_isolated/test_bench/output/controls/device.rb +29 -0
  27. data/lib/test_bench_isolated/test_bench/output/controls/event.rb +9 -0
  28. data/lib/test_bench_isolated/test_bench/output/controls/output.rb +36 -0
  29. data/lib/test_bench_isolated/test_bench/output/controls/random.rb +9 -0
  30. data/lib/test_bench_isolated/test_bench/output/controls/style.rb +33 -0
  31. data/lib/test_bench_isolated/test_bench/output/controls/styling.rb +29 -0
  32. data/lib/test_bench_isolated/test_bench/output/controls/text.rb +19 -0
  33. data/lib/test_bench_isolated/test_bench/output/controls.rb +10 -0
  34. data/lib/test_bench_isolated/test_bench/output/device/null.rb +21 -0
  35. data/lib/test_bench_isolated/test_bench/output/device/substitute.rb +60 -0
  36. data/lib/test_bench_isolated/test_bench/output/digest.rb +115 -0
  37. data/lib/test_bench_isolated/test_bench/output/output.rb +68 -0
  38. data/lib/test_bench_isolated/test_bench/output/writer/buffer.rb +59 -0
  39. data/lib/test_bench_isolated/test_bench/output/writer/defaults.rb +13 -0
  40. data/lib/test_bench_isolated/test_bench/output/writer/style.rb +52 -0
  41. data/lib/test_bench_isolated/test_bench/output/writer/substitute.rb +40 -0
  42. data/lib/test_bench_isolated/test_bench/output/writer.rb +212 -0
  43. data/lib/test_bench_isolated/test_bench/output.rb +14 -0
  44. data/lib/test_bench_isolated/test_bench/random/controls/seed.rb +27 -0
  45. data/lib/test_bench_isolated/test_bench/random/controls.rb +1 -0
  46. data/lib/test_bench_isolated/test_bench/random/random.rb +170 -0
  47. data/lib/test_bench_isolated/test_bench/random.rb +1 -0
  48. data/lib/test_bench_isolated/test_bench/run/controls/directory.rb +72 -0
  49. data/lib/test_bench_isolated/test_bench/run/controls/event_data.rb +9 -0
  50. data/lib/test_bench_isolated/test_bench/run/controls/events/event_data.rb +11 -0
  51. data/lib/test_bench_isolated/test_bench/run/controls/events/file_crashed.rb +111 -0
  52. data/lib/test_bench_isolated/test_bench/run/controls/events/file_finished.rb +58 -0
  53. data/lib/test_bench_isolated/test_bench/run/controls/events/file_started.rb +49 -0
  54. data/lib/test_bench_isolated/test_bench/run/controls/events/finished.rb +58 -0
  55. data/lib/test_bench_isolated/test_bench/run/controls/events/session.rb +11 -0
  56. data/lib/test_bench_isolated/test_bench/run/controls/events/started.rb +49 -0
  57. data/lib/test_bench_isolated/test_bench/run/controls/exception.rb +103 -0
  58. data/lib/test_bench_isolated/test_bench/run/controls/executor.rb +58 -0
  59. data/lib/test_bench_isolated/test_bench/run/controls/file/create.rb +71 -0
  60. data/lib/test_bench_isolated/test_bench/run/controls/file/pattern.rb +35 -0
  61. data/lib/test_bench_isolated/test_bench/run/controls/file.rb +182 -0
  62. data/lib/test_bench_isolated/test_bench/run/controls/path.rb +17 -0
  63. data/lib/test_bench_isolated/test_bench/run/controls/process_id.rb +9 -0
  64. data/lib/test_bench_isolated/test_bench/run/controls/random.rb +9 -0
  65. data/lib/test_bench_isolated/test_bench/run/controls/result.rb +9 -0
  66. data/lib/test_bench_isolated/test_bench/run/controls/time.rb +9 -0
  67. data/lib/test_bench_isolated/test_bench/run/controls.rb +26 -0
  68. data/lib/test_bench_isolated/test_bench/run/events.rb +14 -0
  69. data/lib/test_bench_isolated/test_bench/run/executor/serial.rb +36 -0
  70. data/lib/test_bench_isolated/test_bench/run/executor/substitute.rb +47 -0
  71. data/lib/test_bench_isolated/test_bench/run/executor.rb +46 -0
  72. data/lib/test_bench_isolated/test_bench/run/file.rb +83 -0
  73. data/lib/test_bench_isolated/test_bench/run/get_files/substitute.rb +48 -0
  74. data/lib/test_bench_isolated/test_bench/run/get_files.rb +78 -0
  75. data/lib/test_bench_isolated/test_bench/run/output/file.rb +137 -0
  76. data/lib/test_bench_isolated/test_bench/run/output/summary/error.rb +141 -0
  77. data/lib/test_bench_isolated/test_bench/run/output/summary.rb +184 -0
  78. data/lib/test_bench_isolated/test_bench/run/run.rb +156 -0
  79. data/lib/test_bench_isolated/test_bench/run.rb +18 -0
  80. data/lib/test_bench_isolated/test_bench/session/controls/comment.rb +107 -0
  81. data/lib/test_bench_isolated/test_bench/session/controls/detail.rb +93 -0
  82. data/lib/test_bench_isolated/test_bench/session/controls/event.rb +9 -0
  83. data/lib/test_bench_isolated/test_bench/session/controls/events/commented.rb +112 -0
  84. data/lib/test_bench_isolated/test_bench/session/controls/events/context_finished.rb +72 -0
  85. data/lib/test_bench_isolated/test_bench/session/controls/events/context_skipped.rb +49 -0
  86. data/lib/test_bench_isolated/test_bench/session/controls/events/context_started.rb +66 -0
  87. data/lib/test_bench_isolated/test_bench/session/controls/events/detailed.rb +112 -0
  88. data/lib/test_bench_isolated/test_bench/session/controls/events/event_data.rb +11 -0
  89. data/lib/test_bench_isolated/test_bench/session/controls/events/failed.rb +49 -0
  90. data/lib/test_bench_isolated/test_bench/session/controls/events/fixture_finished.rb +55 -0
  91. data/lib/test_bench_isolated/test_bench/session/controls/events/fixture_started.rb +49 -0
  92. data/lib/test_bench_isolated/test_bench/session/controls/events/test_finished.rb +72 -0
  93. data/lib/test_bench_isolated/test_bench/session/controls/events/test_skipped.rb +49 -0
  94. data/lib/test_bench_isolated/test_bench/session/controls/events/test_started.rb +66 -0
  95. data/lib/test_bench_isolated/test_bench/session/controls/events.rb +35 -0
  96. data/lib/test_bench_isolated/test_bench/session/controls/exception.rb +47 -0
  97. data/lib/test_bench_isolated/test_bench/session/controls/failure.rb +21 -0
  98. data/lib/test_bench_isolated/test_bench/session/controls/fixture.rb +21 -0
  99. data/lib/test_bench_isolated/test_bench/session/controls/output/detail.rb +31 -0
  100. data/lib/test_bench_isolated/test_bench/session/controls/output.rb +57 -0
  101. data/lib/test_bench_isolated/test_bench/session/controls/process_id.rb +9 -0
  102. data/lib/test_bench_isolated/test_bench/session/controls/random.rb +9 -0
  103. data/lib/test_bench_isolated/test_bench/session/controls/result.rb +25 -0
  104. data/lib/test_bench_isolated/test_bench/session/controls/substitute/path.rb +35 -0
  105. data/lib/test_bench_isolated/test_bench/session/controls/time.rb +9 -0
  106. data/lib/test_bench_isolated/test_bench/session/controls/title.rb +41 -0
  107. data/lib/test_bench_isolated/test_bench/session/controls.rb +36 -0
  108. data/lib/test_bench_isolated/test_bench/session/events.rb +27 -0
  109. data/lib/test_bench_isolated/test_bench/session/output/get.rb +29 -0
  110. data/lib/test_bench_isolated/test_bench/session/output/writer/buffer/interactive/viewport.rb +167 -0
  111. data/lib/test_bench_isolated/test_bench/session/output/writer/buffer/interactive.rb +141 -0
  112. data/lib/test_bench_isolated/test_bench/session/output/writer/buffer.rb +29 -0
  113. data/lib/test_bench_isolated/test_bench/session/output/writer/defaults.rb +19 -0
  114. data/lib/test_bench_isolated/test_bench/session/output/writer/substitute.rb +19 -0
  115. data/lib/test_bench_isolated/test_bench/session/output/writer.rb +97 -0
  116. data/lib/test_bench_isolated/test_bench/session/output.rb +377 -0
  117. data/lib/test_bench_isolated/test_bench/session/projection.rb +30 -0
  118. data/lib/test_bench_isolated/test_bench/session/session.rb +220 -0
  119. data/lib/test_bench_isolated/test_bench/session/store.rb +61 -0
  120. data/lib/test_bench_isolated/test_bench/session/substitute/path.rb +65 -0
  121. data/lib/test_bench_isolated/test_bench/session/substitute/sink.rb +114 -0
  122. data/lib/test_bench_isolated/test_bench/session/substitute.rb +120 -0
  123. data/lib/test_bench_isolated/test_bench/session.rb +22 -0
  124. data/lib/test_bench_isolated/test_bench/telemetry/controls/event/event_data.rb +17 -0
  125. data/lib/test_bench_isolated/test_bench/telemetry/controls/event/metadata.rb +72 -0
  126. data/lib/test_bench_isolated/test_bench/telemetry/controls/event.rb +140 -0
  127. data/lib/test_bench_isolated/test_bench/telemetry/controls/event_data.rb +131 -0
  128. data/lib/test_bench_isolated/test_bench/telemetry/controls/file.rb +86 -0
  129. data/lib/test_bench_isolated/test_bench/telemetry/controls/handler.rb +83 -0
  130. data/lib/test_bench_isolated/test_bench/telemetry/controls/process_id.rb +21 -0
  131. data/lib/test_bench_isolated/test_bench/telemetry/controls/projection/receiver.rb +33 -0
  132. data/lib/test_bench_isolated/test_bench/telemetry/controls/projection.rb +86 -0
  133. data/lib/test_bench_isolated/test_bench/telemetry/controls/random.rb +9 -0
  134. data/lib/test_bench_isolated/test_bench/telemetry/controls/sink.rb +35 -0
  135. data/lib/test_bench_isolated/test_bench/telemetry/controls/time.rb +125 -0
  136. data/lib/test_bench_isolated/test_bench/telemetry/controls.rb +17 -0
  137. data/lib/test_bench_isolated/test_bench/telemetry/event.rb +108 -0
  138. data/lib/test_bench_isolated/test_bench/telemetry/event_data/serialization.rb +172 -0
  139. data/lib/test_bench_isolated/test_bench/telemetry/event_data.rb +15 -0
  140. data/lib/test_bench_isolated/test_bench/telemetry/sink/file.rb +33 -0
  141. data/lib/test_bench_isolated/test_bench/telemetry/sink/handler/event_registry.rb +44 -0
  142. data/lib/test_bench_isolated/test_bench/telemetry/sink/handler.rb +128 -0
  143. data/lib/test_bench_isolated/test_bench/telemetry/sink/projection.rb +134 -0
  144. data/lib/test_bench_isolated/test_bench/telemetry/sink.rb +13 -0
  145. data/lib/test_bench_isolated/test_bench/telemetry/substitute/sink.rb +85 -0
  146. data/lib/test_bench_isolated/test_bench/telemetry/substitute.rb +34 -0
  147. data/lib/test_bench_isolated/test_bench/telemetry/telemetry.rb +111 -0
  148. data/lib/test_bench_isolated/test_bench/telemetry.rb +17 -0
  149. data/lib/test_bench_isolated/test_bench/test_bench.rb +56 -0
  150. data/lib/test_bench_isolated/test_bench.rb +5 -0
  151. data/script/bench +5 -0
  152. metadata +157 -7
  153. data/lib/test_bench/bootstrap.rb +0 -328
@@ -0,0 +1,25 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ module Controls
5
+ module Result
6
+ def self.example
7
+ pass
8
+ end
9
+
10
+ def self.pass
11
+ true
12
+ end
13
+
14
+ def self.failure
15
+ false
16
+ end
17
+
18
+ def self.random
19
+ Random.boolean
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ module Controls
5
+ module Substitute
6
+ module Path
7
+ def self.example(segments=nil)
8
+ segments ||= Segment.examples
9
+
10
+ segments = segments.dup
11
+
12
+ path = TestBench::Session::Substitute::Path.new
13
+ path.segments = segments
14
+ path
15
+ end
16
+
17
+ module Segment
18
+ def self.examples
19
+ [example, Context.other_example, Test.example]
20
+ end
21
+
22
+ def self.example
23
+ Context.example
24
+ end
25
+
26
+ Test = Title::Test
27
+
28
+ Context = Title::Context
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ module Controls
5
+ Time = TestBench::Telemetry::Controls::Time
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ module Controls
5
+ module Title
6
+ module Context
7
+ def self.example
8
+ "Some Context"
9
+ end
10
+
11
+ def self.other_example
12
+ "Some Other Context"
13
+ end
14
+
15
+ def self.random
16
+ suffix = Random.string
17
+
18
+ "#{example} #{suffix}"
19
+ end
20
+ end
21
+
22
+ module Test
23
+ def self.example
24
+ "Some test"
25
+ end
26
+
27
+ def self.other_example
28
+ "Some other test"
29
+ end
30
+
31
+ def self.random
32
+ suffix = Random.string
33
+
34
+ "#{example} #{suffix}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_bench_isolated/test_bench/telemetry/controls'
2
+ require 'test_bench_isolated/test_bench/output/controls'
3
+
4
+ require 'test_bench_isolated/test_bench/session/controls/random'
5
+ require 'test_bench_isolated/test_bench/session/controls/time'
6
+ require 'test_bench_isolated/test_bench/session/controls/process_id'
7
+ require 'test_bench_isolated/test_bench/session/controls/result'
8
+ require 'test_bench_isolated/test_bench/session/controls/exception'
9
+
10
+ require 'test_bench_isolated/test_bench/session/controls/failure'
11
+ require 'test_bench_isolated/test_bench/session/controls/title'
12
+ require 'test_bench_isolated/test_bench/session/controls/exception'
13
+ require 'test_bench_isolated/test_bench/session/controls/comment'
14
+ require 'test_bench_isolated/test_bench/session/controls/detail'
15
+ require 'test_bench_isolated/test_bench/session/controls/fixture'
16
+
17
+ require 'test_bench_isolated/test_bench/session/controls/events/event_data'
18
+ require 'test_bench_isolated/test_bench/session/controls/events/failed'
19
+ require 'test_bench_isolated/test_bench/session/controls/events/context_started'
20
+ require 'test_bench_isolated/test_bench/session/controls/events/context_finished'
21
+ require 'test_bench_isolated/test_bench/session/controls/events/context_skipped'
22
+ require 'test_bench_isolated/test_bench/session/controls/events/test_started'
23
+ require 'test_bench_isolated/test_bench/session/controls/events/test_finished'
24
+ require 'test_bench_isolated/test_bench/session/controls/events/test_skipped'
25
+ require 'test_bench_isolated/test_bench/session/controls/events/commented'
26
+ require 'test_bench_isolated/test_bench/session/controls/events/detailed'
27
+ require 'test_bench_isolated/test_bench/session/controls/events/fixture_started'
28
+ require 'test_bench_isolated/test_bench/session/controls/events/fixture_finished'
29
+ require 'test_bench_isolated/test_bench/session/controls/events'
30
+
31
+ require 'test_bench_isolated/test_bench/session/controls/substitute/path'
32
+
33
+ require 'test_bench_isolated/test_bench/session/controls/event'
34
+
35
+ require 'test_bench_isolated/test_bench/session/controls/output'
36
+ require 'test_bench_isolated/test_bench/session/controls/output/detail'
@@ -0,0 +1,27 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ module Events
5
+ def self.each_type(&block)
6
+ constants(false).each(&block)
7
+ end
8
+
9
+ Failed = TestBench::Telemetry::Event.define(:message)
10
+
11
+ ContextStarted = TestBench::Telemetry::Event.define(:title)
12
+ ContextFinished = TestBench::Telemetry::Event.define(:title, :result)
13
+ ContextSkipped = TestBench::Telemetry::Event.define(:title)
14
+
15
+ TestStarted = TestBench::Telemetry::Event.define(:title)
16
+ TestFinished = TestBench::Telemetry::Event.define(:title, :result)
17
+ TestSkipped = TestBench::Telemetry::Event.define(:title)
18
+
19
+ Commented = TestBench::Telemetry::Event.define(:text, :quote, :heading)
20
+ Detailed = TestBench::Telemetry::Event.define(:text, :quote, :heading)
21
+
22
+ FixtureStarted = TestBench::Telemetry::Event.define(:name)
23
+ FixtureFinished = TestBench::Telemetry::Event.define(:name, :result)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ module Get
6
+ def self.call(substitute_session, styling: nil)
7
+ styling = true if styling.nil?
8
+
9
+ session_sink = substitute_session.sink
10
+
11
+ output = Output.new
12
+
13
+ if styling
14
+ output.writer.styling!
15
+ end
16
+
17
+ session_sink.records.each do |record|
18
+ event_data = record.event_data
19
+
20
+ output.receive(event_data)
21
+ end
22
+
23
+ output.writer.written_text
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,167 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer
6
+ module Buffer
7
+ class Interactive
8
+ Viewport = Struct.new(:width, :height, :row, :column, :scroll_rows, :rows_scrolled) do
9
+ def self.build(width, height, row, column, scroll_rows=nil)
10
+ scroll_rows ||= 0
11
+
12
+ rows_scrolled = 0
13
+
14
+ new(width, height, row, column, scroll_rows, rows_scrolled)
15
+ end
16
+
17
+ def self.null
18
+ build(0, 0, 0, 0)
19
+ end
20
+
21
+ def self.get
22
+ width, height, row, column = nil
23
+
24
+ Kernel.require 'io/console'
25
+ STDIN.raw do |stdin|
26
+ height, width = stdin.winsize
27
+
28
+ row, column = stdin.cursor
29
+ end
30
+
31
+ scroll_rows = row
32
+
33
+ build(width, height, row, column, scroll_rows)
34
+ end
35
+
36
+ def write(text)
37
+ bytes_written = 0
38
+
39
+ escape_sequence_pattern = self.class.escape_sequence_pattern
40
+
41
+ until text.empty?
42
+ write_text, escape_sequence, text = text.partition(escape_sequence_pattern)
43
+
44
+ bytes_written += write!(write_text)
45
+ bytes_written += escape_sequence.bytesize
46
+ end
47
+
48
+ bytes_written
49
+ end
50
+
51
+ def write!(text)
52
+ newline = text.end_with?("\n")
53
+
54
+ if newline
55
+ text = text[0...-1]
56
+ end
57
+
58
+ bytes_written = write_text(text)
59
+
60
+ if newline
61
+ bytes_written += write_newline
62
+ end
63
+
64
+ bytes_written
65
+ end
66
+
67
+ def write_text(text)
68
+ if text.start_with?("\e")
69
+ return text.bytesize
70
+ end
71
+
72
+ written_text = text[0...capacity]
73
+
74
+ bytes_written = written_text.bytesize
75
+
76
+ row = self.row
77
+ column = self.column
78
+
79
+ text_rows, text_columns = bytes_written.divmod(width)
80
+
81
+ row += text_rows
82
+
83
+ columns_remaining = width - column
84
+ if columns_remaining > text_columns
85
+ column += text_columns
86
+ else
87
+ row += 1
88
+ column = text_columns - columns_remaining
89
+ end
90
+
91
+ if row >= height
92
+ final_row = height - 1
93
+
94
+ scroll_rows = row - final_row
95
+ self.rows_scrolled += scroll_rows
96
+
97
+ row = final_row
98
+ end
99
+
100
+ self.row = row
101
+ self.column = column
102
+
103
+ bytes_written
104
+ end
105
+
106
+ def write_newline
107
+ if bottom_row?
108
+ if scroll_rows_remaining.zero?
109
+ return 0
110
+ end
111
+
112
+ self.rows_scrolled += 1
113
+ else
114
+ self.row += 1
115
+ end
116
+
117
+ self.column = 0
118
+
119
+ 1
120
+ end
121
+
122
+ def capacity?
123
+ if scroll_rows_remaining > 0
124
+ true
125
+ else
126
+ not bottom_row?
127
+ end
128
+ end
129
+
130
+ def capacity
131
+ capacity = 0
132
+
133
+ rows_remaining = height + scroll_rows_remaining - row - 1
134
+
135
+ if rows_remaining > 0
136
+ capacity += (rows_remaining - 1) * width
137
+
138
+ final_row = width - column
139
+ capacity += final_row
140
+ end
141
+
142
+ capacity
143
+ end
144
+
145
+ def scroll_rows_remaining
146
+ scroll_rows - rows_scrolled
147
+ end
148
+
149
+ def bottom_row?
150
+ row == height - 1
151
+ end
152
+
153
+ def self.escape_sequence_pattern
154
+ initiator = %r{\e\[}
155
+ terminator = %r{[[:alpha:]]}
156
+ sequence = %r{[[:digit:]]+(?:;[[:digit:]]+)*}
157
+
158
+ %r{#{initiator}#{sequence}?#{terminator}}
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,141 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer
6
+ module Buffer
7
+ class Interactive
8
+ attr_accessor :viewport
9
+
10
+ attr_accessor :raw_stderr
11
+
12
+ attr_accessor :stderr_pipe
13
+
14
+ def stderr_buffer
15
+ @stderr_buffer ||= String.new
16
+ end
17
+
18
+ def device
19
+ @device ||= TestBench::Output::Device::Substitute.build
20
+ end
21
+ attr_writer :device
22
+
23
+ attr_accessor :buffering
24
+ def buffering? = !!buffering
25
+
26
+ def self.build(device=nil)
27
+ device ||= Defaults.device
28
+
29
+ instance = new
30
+ instance.device = device
31
+ instance
32
+ end
33
+
34
+ def self.configure(receiver, device: nil, attr_name: nil)
35
+ attr_name ||= :buffer
36
+
37
+ instance = build(device)
38
+ receiver.public_send(:"#{attr_name}=", instance)
39
+ end
40
+
41
+ def receive(text)
42
+ if not cursor_saved?
43
+ save_cursor
44
+ end
45
+
46
+ bytes_written = viewport.write(text)
47
+
48
+ write_text = text.byteslice(0, bytes_written)
49
+ device.write(write_text)
50
+
51
+ if not viewport.capacity?
52
+ if not buffering?
53
+ buffering_message = "Output is buffering"
54
+
55
+ device.write("\e[0G\e[2m#{buffering_message}\e[22m")
56
+
57
+ self.buffering = true
58
+ end
59
+ end
60
+
61
+ update_stderr_buffer
62
+
63
+ bytes_written
64
+ end
65
+
66
+ def flush(*_devices)
67
+ if cursor_saved?
68
+ update_stderr_buffer
69
+ restore_cursor
70
+ end
71
+ end
72
+
73
+ def save_cursor
74
+ self.viewport = Viewport.get
75
+
76
+ self.raw_stderr = STDERR.dup
77
+
78
+ reader, writer = IO.pipe
79
+
80
+ new_stderr = writer
81
+ STDERR.reopen(new_stderr)
82
+
83
+ stderr_buffer.clear
84
+
85
+ self.stderr_pipe = reader
86
+
87
+ device.write("\e[s")
88
+ end
89
+
90
+ def restore_cursor
91
+ stderr_pipe.close
92
+
93
+ device.write("\e[u")
94
+
95
+ rows_scrolled = viewport.rows_scrolled
96
+
97
+ if not rows_scrolled.zero?
98
+ upward_movements = rows_scrolled
99
+ device.write("\e[#{upward_movements}F")
100
+ end
101
+
102
+ stderr_buffer.each_line do |line|
103
+ raw_stderr.write("\e[0K")
104
+ raw_stderr.write(line)
105
+ end
106
+
107
+ STDERR.reopen(raw_stderr)
108
+ self.raw_stderr = nil
109
+
110
+ self.viewport = nil
111
+ end
112
+
113
+ def update_stderr_buffer
114
+ loop do
115
+ stderr_text = stderr_pipe.read_nonblock(4096, exception: false)
116
+
117
+ if stderr_text == :wait_readable
118
+ break
119
+ end
120
+
121
+ viewport.write(stderr_text)
122
+
123
+ if not buffering?
124
+ raw_stderr.write(stderr_text)
125
+ end
126
+
127
+ self.stderr_buffer << stderr_text
128
+ end
129
+ end
130
+
131
+ def viewport?
132
+ !viewport.nil?
133
+ end
134
+ alias :cursor_saved? :viewport?
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,29 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer
6
+ module Buffer
7
+ def self.configure(receiver, device: nil, experimental_output: nil, attr_name: nil)
8
+ device ||= Defaults.device
9
+ experimental_output ||= Defaults.experimental_output
10
+ attr_name ||= :buffer
11
+
12
+ if experimental_output
13
+ interactive = device.tty?
14
+ else
15
+ interactive = false
16
+ end
17
+
18
+ if interactive
19
+ Buffer::Interactive.configure(receiver, device:, attr_name:)
20
+ else
21
+ TestBench::Output::Writer::Buffer.configure(receiver, attr_name:)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer
6
+ module Defaults
7
+ def self.device
8
+ TestBench::Output::Writer::Defaults.device
9
+ end
10
+
11
+ def self.experimental_output
12
+ ENV.fetch('TEST_BENCH_EXPERIMENTAL_OUTPUT', 'off') == 'on'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer
6
+ module Substitute
7
+ def self.build
8
+ Writer.build
9
+ end
10
+
11
+ class Writer < Writer
12
+ include TestBench::Output::Writer::Substitute
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,97 @@
1
+ module TestBenchIsolated
2
+ module TestBench
3
+ class Session
4
+ class Output
5
+ class Writer < TestBench::Output::Writer
6
+ attr_accessor :peer
7
+
8
+ def alternate_device
9
+ @alternate_device ||= TestBench::Output::Device::Substitute.build
10
+ end
11
+ attr_writer :alternate_device
12
+
13
+ def indentation_depth
14
+ @indentation_depth ||= 0
15
+ end
16
+ attr_writer :indentation_depth
17
+
18
+ def configure
19
+ device = self.device
20
+
21
+ self.alternate_device = TestBench::Output::Device::Null.build
22
+
23
+ Buffer.configure(self, device:)
24
+ end
25
+
26
+ def self.follow(previous_writer)
27
+ device = previous_writer
28
+
29
+ alternate_device = previous_writer.peer
30
+ alternate_device ||= TestBench::Output::Device::Null.build
31
+
32
+ previous_digest = previous_writer.digest
33
+ digest = previous_digest.clone
34
+
35
+ writer = new
36
+ writer.sync = false
37
+ writer.device = device
38
+ writer.alternate_device = alternate_device
39
+ writer.styling_policy = previous_writer.styling_policy
40
+ writer.digest = digest
41
+ writer.sequence = previous_writer.sequence
42
+ writer.column_sequence = previous_writer.column_sequence
43
+ writer.indentation_depth = previous_writer.indentation_depth
44
+ writer.digest = previous_writer.digest.clone
45
+ writer
46
+ end
47
+
48
+ def branch
49
+ alternate = self.class.follow(self)
50
+ primary = self.class.follow(self)
51
+
52
+ primary.peer = alternate
53
+
54
+ return primary, alternate
55
+ end
56
+
57
+ def indent
58
+ indentation = ' ' * indentation_depth
59
+
60
+ print(indentation)
61
+ end
62
+
63
+ def flush
64
+ buffer.flush(device, alternate_device)
65
+ end
66
+
67
+ def write!(data)
68
+ device.write(data)
69
+ alternate_device.write(data)
70
+ end
71
+
72
+ def increase_indentation
73
+ self.indentation_depth += 1
74
+ end
75
+ alias :indent! :increase_indentation
76
+
77
+ def decrease_indentation
78
+ self.indentation_depth -= 1
79
+ end
80
+ alias :deindent! :decrease_indentation
81
+
82
+ def follows?(other_writer)
83
+ if sequence < other_writer.sequence
84
+ false
85
+ elsif device == other_writer
86
+ true
87
+ elsif device == other_writer.peer
88
+ true
89
+ else
90
+ false
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end