cucumber-core 1.5.0 → 2.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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +48 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +39 -0
- data/.travis.yml +2 -3
- data/HISTORY.md +12 -1
- data/README.md +37 -43
- data/cucumber-core.gemspec +2 -0
- data/lib/cucumber/core.rb +5 -2
- data/lib/cucumber/core/ast.rb +1 -0
- data/lib/cucumber/core/ast/background.rb +1 -0
- data/lib/cucumber/core/ast/comment.rb +1 -0
- data/lib/cucumber/core/ast/data_table.rb +1 -0
- data/lib/cucumber/core/ast/describes_itself.rb +1 -0
- data/lib/cucumber/core/ast/doc_string.rb +1 -0
- data/lib/cucumber/core/ast/empty_background.rb +1 -0
- data/lib/cucumber/core/ast/empty_multiline_argument.rb +1 -0
- data/lib/cucumber/core/ast/examples_table.rb +1 -0
- data/lib/cucumber/core/ast/feature.rb +1 -0
- data/lib/cucumber/core/ast/location.rb +1 -0
- data/lib/cucumber/core/ast/names.rb +1 -0
- data/lib/cucumber/core/ast/outline_step.rb +1 -0
- data/lib/cucumber/core/ast/scenario.rb +1 -0
- data/lib/cucumber/core/ast/scenario_outline.rb +1 -0
- data/lib/cucumber/core/ast/step.rb +1 -0
- data/lib/cucumber/core/ast/tag.rb +1 -0
- data/lib/cucumber/core/compiler.rb +1 -0
- data/lib/cucumber/core/event.rb +63 -0
- data/lib/cucumber/core/event_bus.rb +64 -0
- data/lib/cucumber/core/events.rb +69 -0
- data/lib/cucumber/core/filter.rb +1 -0
- data/lib/cucumber/core/gherkin/ast_builder.rb +14 -5
- data/lib/cucumber/core/gherkin/document.rb +6 -4
- data/lib/cucumber/core/gherkin/parser.rb +6 -4
- data/lib/cucumber/core/gherkin/tag_expression.rb +1 -0
- data/lib/cucumber/core/gherkin/writer.rb +1 -0
- data/lib/cucumber/core/gherkin/writer/helpers.rb +1 -0
- data/lib/cucumber/core/platform.rb +1 -0
- data/lib/cucumber/core/report/summary.rb +30 -6
- data/lib/cucumber/core/test/action.rb +1 -0
- data/lib/cucumber/core/test/around_hook.rb +1 -0
- data/lib/cucumber/core/test/case.rb +13 -0
- data/lib/cucumber/core/test/filters.rb +1 -0
- data/lib/cucumber/core/test/filters/locations_filter.rb +1 -0
- data/lib/cucumber/core/test/filters/name_filter.rb +1 -0
- data/lib/cucumber/core/test/filters/tag_filter.rb +1 -0
- data/lib/cucumber/core/test/result.rb +5 -0
- data/lib/cucumber/core/test/runner.rb +10 -10
- data/lib/cucumber/core/test/step.rb +1 -0
- data/lib/cucumber/core/test/timer.rb +1 -0
- data/lib/cucumber/core/version.rb +2 -1
- data/spec/capture_warnings.rb +3 -2
- data/spec/coverage.rb +1 -0
- data/spec/cucumber/core/ast/background_spec.rb +1 -0
- data/spec/cucumber/core/ast/data_table_spec.rb +1 -0
- data/spec/cucumber/core/ast/doc_string_spec.rb +2 -1
- data/spec/cucumber/core/ast/empty_multiline_argument_spec.rb +1 -0
- data/spec/cucumber/core/ast/examples_table_spec.rb +1 -0
- data/spec/cucumber/core/ast/location_spec.rb +1 -0
- data/spec/cucumber/core/ast/outline_step_spec.rb +1 -0
- data/spec/cucumber/core/ast/step_spec.rb +1 -0
- data/spec/cucumber/core/compiler_spec.rb +1 -0
- data/spec/cucumber/core/event_bus_spec.rb +151 -0
- data/spec/cucumber/core/event_spec.rb +40 -0
- data/spec/cucumber/core/filter_spec.rb +1 -0
- data/spec/cucumber/core/gherkin/parser_spec.rb +24 -0
- data/spec/cucumber/core/gherkin/writer_spec.rb +1 -0
- data/spec/cucumber/core/report/summary_spec.rb +127 -0
- data/spec/cucumber/core/test/action_spec.rb +1 -0
- data/spec/cucumber/core/test/case_spec.rb +26 -2
- data/spec/cucumber/core/test/duration_matcher.rb +2 -1
- data/spec/cucumber/core/test/filters/locations_filter_spec.rb +2 -0
- data/spec/cucumber/core/test/result_spec.rb +5 -0
- data/spec/cucumber/core/test/runner_spec.rb +44 -50
- data/spec/cucumber/core/test/step_spec.rb +1 -0
- data/spec/cucumber/core/test/timer_spec.rb +1 -0
- data/spec/cucumber/core_spec.rb +68 -8
- data/spec/readme_spec.rb +1 -0
- data/spec/report_api_spy.rb +1 -0
- metadata +42 -3
data/spec/capture_warnings.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
# With thanks to @myronmarston
|
|
2
3
|
# https://github.com/vcr/vcr/blob/master/spec/capture_warnings.rb
|
|
3
4
|
|
|
@@ -22,7 +23,7 @@ module CaptureWarnings
|
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
if project_warnings.any?
|
|
25
|
-
puts "#{ project_warnings.count } cucumber-core warnings detected"
|
|
26
|
+
puts "#{ project_warnings.count } cucumber-core warnings detected"
|
|
26
27
|
print_warnings('cucumber-core', project_warnings)
|
|
27
28
|
fail "Please remove all cucumber-core warnings."
|
|
28
29
|
end
|
|
@@ -34,7 +35,7 @@ module CaptureWarnings
|
|
|
34
35
|
old_stderr = STDERR.clone
|
|
35
36
|
pipe_r, pipe_w = IO.pipe
|
|
36
37
|
pipe_r.sync = true
|
|
37
|
-
error =
|
|
38
|
+
error = String.new
|
|
38
39
|
reader = Thread.new do
|
|
39
40
|
begin
|
|
40
41
|
loop do
|
data/spec/coverage.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'cucumber/core/ast/location'
|
|
2
3
|
require 'cucumber/core/ast/doc_string'
|
|
3
4
|
require 'unindent'
|
|
@@ -68,7 +69,7 @@ module Cucumber
|
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
context 'quacking like a String' do
|
|
71
|
-
let(:content) { 'content' }
|
|
72
|
+
let(:content) { String.new('content') }
|
|
72
73
|
let(:content_type) { 'text/plain' }
|
|
73
74
|
|
|
74
75
|
it 'delegates #encoding to the content string' do
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
require "cucumber/core/event_bus"
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
module Events
|
|
6
|
+
|
|
7
|
+
class TestEvent < Core::Event.new(:some_attribute)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
AnotherTestEvent = Core::Event.new
|
|
11
|
+
|
|
12
|
+
UnregisteredEvent = Core::Event.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe EventBus do
|
|
16
|
+
let(:event_bus) { EventBus.new(registry) }
|
|
17
|
+
let(:registry) { { test_event: Events::TestEvent, another_test_event: Events::AnotherTestEvent } }
|
|
18
|
+
|
|
19
|
+
context "broadcasting events" do
|
|
20
|
+
|
|
21
|
+
it "can broadcast by calling a method named after the event ID" do
|
|
22
|
+
called = false
|
|
23
|
+
event_bus.on(:test_event) {called = true }
|
|
24
|
+
event_bus.test_event
|
|
25
|
+
expect(called).to be true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "can broadcast by calling the `broadcast` method with an instance of the event type" do
|
|
29
|
+
called = false
|
|
30
|
+
event_bus.on(:test_event) {called = true }
|
|
31
|
+
event_bus.broadcast(Events::TestEvent.new(:some_attribute))
|
|
32
|
+
expect(called).to be true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "calls a subscriber for an event, passing details of the event" do
|
|
36
|
+
received_payload = nil
|
|
37
|
+
event_bus.on :test_event do |event|
|
|
38
|
+
received_payload = event
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
event_bus.test_event :some_attribute
|
|
42
|
+
|
|
43
|
+
expect(received_payload.some_attribute).to eq(:some_attribute)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "does not call subscribers for other events" do
|
|
47
|
+
handler_called = false
|
|
48
|
+
event_bus.on :test_event do
|
|
49
|
+
handler_called = true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
event_bus.another_test_event
|
|
53
|
+
|
|
54
|
+
expect(handler_called).to eq(false)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "broadcasts to multiple subscribers" do
|
|
58
|
+
received_events = []
|
|
59
|
+
event_bus.on :test_event do
|
|
60
|
+
received_events << :event
|
|
61
|
+
end
|
|
62
|
+
event_bus.on :test_event do
|
|
63
|
+
received_events << :event
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
event_bus.test_event(:some_attribute)
|
|
67
|
+
|
|
68
|
+
expect(received_events.length).to eq 2
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "raises an error when given an event to broadcast that it doesn't recognise" do
|
|
72
|
+
expect { event_bus.some_unknown_event }.to raise_error(NameError)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "#broadcast method" do
|
|
76
|
+
it "must be passed an instance of a registered event type" do
|
|
77
|
+
expect {
|
|
78
|
+
event_bus.broadcast Events::UnregisteredEvent
|
|
79
|
+
}.to raise_error(ArgumentError)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "subscribing to events" do
|
|
86
|
+
it "allows subscription by symbol (Event ID)" do
|
|
87
|
+
received_payload = nil
|
|
88
|
+
event_bus.on(:test_event) do |event|
|
|
89
|
+
received_payload = event
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
event_bus.test_event :some_attribute
|
|
93
|
+
|
|
94
|
+
expect(received_payload.some_attribute).to eq(:some_attribute)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "raises an error if you use an unknown Event ID" do
|
|
98
|
+
expect {
|
|
99
|
+
event_bus.on(:some_unknown_event) { :whatever }
|
|
100
|
+
}.to raise_error(ArgumentError)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "allows handlers that are objects with a `call` method" do
|
|
104
|
+
class MyHandler
|
|
105
|
+
attr_reader :received_payload
|
|
106
|
+
|
|
107
|
+
def call(event)
|
|
108
|
+
@received_payload = event
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
handler = MyHandler.new
|
|
113
|
+
event_bus.on(:test_event, handler)
|
|
114
|
+
|
|
115
|
+
event_bus.test_event :some_attribute
|
|
116
|
+
|
|
117
|
+
expect(handler.received_payload.some_attribute).to eq :some_attribute
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "allows handlers that are procs" do
|
|
121
|
+
class MyProccyHandler
|
|
122
|
+
attr_reader :received_payload
|
|
123
|
+
|
|
124
|
+
def initialize(event_bus)
|
|
125
|
+
event_bus.on :test_event, &method(:on_test_event)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def on_test_event(event)
|
|
129
|
+
@received_payload = event
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
handler = MyProccyHandler.new(event_bus)
|
|
134
|
+
|
|
135
|
+
event_bus.test_event :some_attribute
|
|
136
|
+
expect(handler.received_payload.some_attribute).to eq :some_attribute
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "will let you inspect the registry" do
|
|
142
|
+
expect(event_bus.event_types[:test_event]).to eq Events::TestEvent
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "won't let you modify the registry" do
|
|
146
|
+
expect { event_bus.event_types[:foo] = :bar }.to raise_error(RuntimeError)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'cucumber/core/event'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Core
|
|
5
|
+
describe Event do
|
|
6
|
+
|
|
7
|
+
describe ".new" do
|
|
8
|
+
it "generates new types of events" do
|
|
9
|
+
my_event_type = Event.new
|
|
10
|
+
my_event = my_event_type.new
|
|
11
|
+
expect(my_event).to be_kind_of(Core::Event)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "generates events with attributes" do
|
|
15
|
+
my_event_type = Event.new(:foo, :bar)
|
|
16
|
+
my_event = my_event_type.new(1,2)
|
|
17
|
+
expect(my_event.attributes).to eq [1, 2]
|
|
18
|
+
expect(my_event.foo).to eq 1
|
|
19
|
+
expect(my_event.bar).to eq 2
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "a generated event" do
|
|
24
|
+
class MyEventType < Event.new(:foo, :bar)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "can be converted to a hash" do
|
|
28
|
+
my_event = MyEventType.new(1,2)
|
|
29
|
+
expect(my_event.to_h).to eq foo: 1, bar: 2
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "has an event_id" do
|
|
33
|
+
expect(MyEventType.event_id).to eq :my_event_type
|
|
34
|
+
expect(MyEventType.new(1,2).event_id).to eq :my_event_type
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'cucumber/core/gherkin/parser'
|
|
3
4
|
require 'cucumber/core/gherkin/writer'
|
|
4
5
|
|
|
@@ -223,6 +224,29 @@ module Cucumber
|
|
|
223
224
|
|
|
224
225
|
end
|
|
225
226
|
|
|
227
|
+
context "a Scenario Outline with an empty examples table" do
|
|
228
|
+
source do
|
|
229
|
+
feature do
|
|
230
|
+
scenario_outline 'outline name' do
|
|
231
|
+
step 'passing <arg>'
|
|
232
|
+
|
|
233
|
+
examples do
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it "creates an examples table node but no example table rows" do
|
|
240
|
+
allow( visitor ).to receive(:feature).and_yield(visitor)
|
|
241
|
+
allow( visitor ).to receive(:scenario_outline).and_yield(visitor)
|
|
242
|
+
allow( visitor ).to receive(:outline_step)
|
|
243
|
+
expect( visitor ).to receive(:examples_table).and_yield(visitor)
|
|
244
|
+
expect( visitor ).to receive(:examples_table_row).exactly(0).times
|
|
245
|
+
feature.describe_to(visitor)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
end
|
|
249
|
+
|
|
226
250
|
context "a Scenario Outline with no Examples" do
|
|
227
251
|
source do
|
|
228
252
|
feature(language: 'not-a-language')
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require 'cucumber/core/event_bus'
|
|
3
|
+
require 'cucumber/core/events'
|
|
4
|
+
require 'cucumber/core/report/summary'
|
|
5
|
+
require 'cucumber/core/test/result'
|
|
6
|
+
|
|
7
|
+
module Cucumber::Core::Report
|
|
8
|
+
describe Summary do
|
|
9
|
+
let(:event_bus) { ::Cucumber::Core::EventBus.new(registry) }
|
|
10
|
+
let(:registry) { ::Cucumber::Core::Events.registry }
|
|
11
|
+
let(:passed_result) { ::Cucumber::Core::Test::Result::Passed.new(duration) }
|
|
12
|
+
let(:failed_result) { ::Cucumber::Core::Test::Result::Failed.new(duration, exception) }
|
|
13
|
+
let(:pending_result) { ::Cucumber::Core::Test::Result::Pending.new(duration) }
|
|
14
|
+
let(:skipped_result) { ::Cucumber::Core::Test::Result::Skipped.new(duration) }
|
|
15
|
+
let(:undefined_result) { ::Cucumber::Core::Test::Result::Undefined.new(duration) }
|
|
16
|
+
let(:duration) { double }
|
|
17
|
+
let(:exception) { double }
|
|
18
|
+
|
|
19
|
+
before(:each) { @summary = Summary.new(event_bus) }
|
|
20
|
+
|
|
21
|
+
context "test case summary" do
|
|
22
|
+
let(:test_case) { double }
|
|
23
|
+
|
|
24
|
+
it "counts passed test cases" do
|
|
25
|
+
event_bus.send(:test_case_finished, test_case, passed_result)
|
|
26
|
+
|
|
27
|
+
expect( @summary.test_cases.total(:passed) ).to eq(1)
|
|
28
|
+
expect( @summary.test_cases.total ).to eq(1)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "counts failed test cases" do
|
|
32
|
+
event_bus.send(:test_case_finished, test_case, failed_result)
|
|
33
|
+
|
|
34
|
+
expect( @summary.test_cases.total(:failed) ).to eq(1)
|
|
35
|
+
expect( @summary.test_cases.total ).to eq(1)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "counts pending test cases" do
|
|
39
|
+
event_bus.send(:test_case_finished, test_case, pending_result)
|
|
40
|
+
|
|
41
|
+
expect( @summary.test_cases.total(:pending) ).to eq(1)
|
|
42
|
+
expect( @summary.test_cases.total ).to eq(1)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "counts skipped test cases" do
|
|
46
|
+
event_bus.send(:test_case_finished, test_case, skipped_result)
|
|
47
|
+
|
|
48
|
+
expect( @summary.test_cases.total(:skipped) ).to eq(1)
|
|
49
|
+
expect( @summary.test_cases.total ).to eq(1)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "counts undefined test cases" do
|
|
53
|
+
event_bus.send(:test_case_finished, test_case, undefined_result)
|
|
54
|
+
|
|
55
|
+
expect( @summary.test_cases.total(:undefined) ).to eq(1)
|
|
56
|
+
expect( @summary.test_cases.total ).to eq(1)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "test step summary" do
|
|
61
|
+
context "with test steps from gherkin steps" do
|
|
62
|
+
let(:test_step) { double }
|
|
63
|
+
|
|
64
|
+
before(:each) do
|
|
65
|
+
step = double
|
|
66
|
+
expect( step ).to receive(:describe_to) do |visitor|
|
|
67
|
+
visitor.step
|
|
68
|
+
end
|
|
69
|
+
expect( test_step ).to receive(:source).and_return([step])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "counts passed test steps" do
|
|
73
|
+
event_bus.send(:test_step_finished, test_step, passed_result)
|
|
74
|
+
|
|
75
|
+
expect( @summary.test_steps.total(:passed) ).to eq(1)
|
|
76
|
+
expect( @summary.test_steps.total ).to eq(1)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "counts failed test cases" do
|
|
80
|
+
event_bus.send(:test_step_finished, test_step, failed_result)
|
|
81
|
+
|
|
82
|
+
expect( @summary.test_steps.total(:failed) ).to eq(1)
|
|
83
|
+
expect( @summary.test_steps.total ).to eq(1)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "counts pending test cases" do
|
|
87
|
+
event_bus.send(:test_step_finished, test_step, pending_result)
|
|
88
|
+
|
|
89
|
+
expect( @summary.test_steps.total(:pending) ).to eq(1)
|
|
90
|
+
expect( @summary.test_steps.total ).to eq(1)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "counts skipped test cases" do
|
|
94
|
+
event_bus.send(:test_step_finished, test_step, skipped_result)
|
|
95
|
+
|
|
96
|
+
expect( @summary.test_steps.total(:skipped) ).to eq(1)
|
|
97
|
+
expect( @summary.test_steps.total ).to eq(1)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "counts undefined test cases" do
|
|
101
|
+
event_bus.send(:test_step_finished, test_step, undefined_result)
|
|
102
|
+
|
|
103
|
+
expect( @summary.test_steps.total(:undefined) ).to eq(1)
|
|
104
|
+
expect( @summary.test_steps.total ).to eq(1)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "with test steps not from gherkin steps" do
|
|
109
|
+
let(:test_step) { double }
|
|
110
|
+
|
|
111
|
+
before(:each) do
|
|
112
|
+
step = double
|
|
113
|
+
expect( step ).to receive(:describe_to) do |visitor|
|
|
114
|
+
visitor.not_step
|
|
115
|
+
end
|
|
116
|
+
expect( test_step ).to receive(:source).and_return([step])
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "ignores test steps not defined by gherkin steps" do
|
|
120
|
+
event_bus.send(:test_step_finished, test_step, passed_result)
|
|
121
|
+
|
|
122
|
+
expect( @summary.test_steps.total ).to eq(0)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|