infinity_test 0.1.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.
- data/.gitignore +10 -0
- data/.infinity_test +8 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +11 -0
- data/Rakefile +49 -0
- data/Readme.markdown +92 -0
- data/Tasks +5 -0
- data/VERSION.yml +5 -0
- data/bin/infinity_test +7 -0
- data/buzz_images/buzz_lightyear.jpg +0 -0
- data/buzz_images/buzz_lightyear_continencia.gif +0 -0
- data/buzz_images/to_infinity_and_beyond.png +0 -0
- data/features/infinity_test.feature +36 -0
- data/features/support/env.rb +1 -0
- data/images/faces/failure.png +0 -0
- data/images/faces/pending.png +0 -0
- data/images/faces/sucess.png +0 -0
- data/images/hands/failure.png +0 -0
- data/images/hands/pending.png +0 -0
- data/images/hands/sucess.png +0 -0
- data/images/mario_bros/failure.jpg +0 -0
- data/images/mario_bros/pending.jpg +0 -0
- data/images/mario_bros/sucess.jpg +0 -0
- data/images/rails/failure.png +0 -0
- data/images/rails/pending.png +0 -0
- data/images/rails/sucess.png +0 -0
- data/images/rubies/failure.png +0 -0
- data/images/rubies/pending.png +0 -0
- data/images/rubies/sucess.png +0 -0
- data/images/simpson/failure.gif +0 -0
- data/images/simpson/pending.jpg +0 -0
- data/images/simpson/sucess.jpg +0 -0
- data/images/street_fighter/failure.gif +0 -0
- data/images/street_fighter/pending.gif +0 -0
- data/images/street_fighter/sucess.jpg +0 -0
- data/images/toy_story/failure.gif +0 -0
- data/images/toy_story/pending.png +0 -0
- data/images/toy_story/sucess.png +0 -0
- data/infinity_test.gemspec +168 -0
- data/lib/infinity_test.rb +31 -0
- data/lib/infinity_test/application.rb +168 -0
- data/lib/infinity_test/binary_path.rb +21 -0
- data/lib/infinity_test/command.rb +57 -0
- data/lib/infinity_test/configuration.rb +157 -0
- data/lib/infinity_test/continuous_testing.rb +62 -0
- data/lib/infinity_test/dependencies.rb +45 -0
- data/lib/infinity_test/notifications/growl.rb +15 -0
- data/lib/infinity_test/notifications/lib_notify.rb +11 -0
- data/lib/infinity_test/options.rb +52 -0
- data/lib/infinity_test/rspec.rb +87 -0
- data/lib/infinity_test/runner.rb +30 -0
- data/lib/infinity_test/test_unit.rb +74 -0
- data/lib/infinity_test/test_unit_loader.rb +5 -0
- data/spec/factories/buzz/lib/buzz.rb +0 -0
- data/spec/factories/buzz/spec/buzz_spec.rb +0 -0
- data/spec/factories/company/lib/company.rb +0 -0
- data/spec/factories/company/test/company_test.rb +0 -0
- data/spec/factories/images/failure.png +0 -0
- data/spec/factories/images/pending.png +0 -0
- data/spec/factories/images/sucess.png +0 -0
- data/spec/factories/infinity_test +5 -0
- data/spec/factories/infinity_test_example +7 -0
- data/spec/factories/slinky/spec/slinky/slinky_spec.rb +0 -0
- data/spec/factories/travel/lib/travel.rb +0 -0
- data/spec/factories/travel/test/partner_test.rb +0 -0
- data/spec/factories/travel/test/travel_test.rb +0 -0
- data/spec/factories/wood/lib/wood.rb +0 -0
- data/spec/factories/wood/spec/wood_spec.rb +0 -0
- data/spec/infinity_test/application_spec.rb +149 -0
- data/spec/infinity_test/command_spec.rb +47 -0
- data/spec/infinity_test/configuration_spec.rb +196 -0
- data/spec/infinity_test/continuous_testing_spec.rb +7 -0
- data/spec/infinity_test/notifications/growl_spec.rb +9 -0
- data/spec/infinity_test/notifications/lib_notify_spec.rb +9 -0
- data/spec/infinity_test/options_spec.rb +69 -0
- data/spec/infinity_test/rspec_spec.rb +189 -0
- data/spec/infinity_test/runner_spec.rb +34 -0
- data/spec/infinity_test/test_unit_spec.rb +182 -0
- data/spec/infinity_test_spec.rb +29 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +67 -0
- metadata +226 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
RVM_LIBRARY_DIRECTORY = File.expand_path("~/.rvm/lib")
|
3
|
+
|
4
|
+
#
|
5
|
+
# Try to require the rvm in home folder
|
6
|
+
# If not suceed raise a LoadError
|
7
|
+
# Try to see if the user has the RVM 1.0 or higher for the RVM Ruby API
|
8
|
+
# If not raise a NameError
|
9
|
+
#
|
10
|
+
def require_home_rvm
|
11
|
+
$LOAD_PATH.unshift(RVM_LIBRARY_DIRECTORY) unless $LOAD_PATH.include?(RVM_LIBRARY_DIRECTORY)
|
12
|
+
require 'rvm'
|
13
|
+
RVM::Environment
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: Make require with System Wide Install too
|
17
|
+
#
|
18
|
+
begin
|
19
|
+
require_home_rvm
|
20
|
+
rescue LoadError, NameError
|
21
|
+
puts
|
22
|
+
puts "It appears that you have not installed the RVM in #{RVM_LIBRARY_DIRECTORY} or RVM is very old.\n"
|
23
|
+
puts "The RVM is installed?"
|
24
|
+
puts "If not, please see http://rvm.beginrescueend.com/rvm/install/"
|
25
|
+
puts "If so, try to run:"
|
26
|
+
puts "\t rvm update --head"
|
27
|
+
puts "If the error continues, please create an issue in http://github.com/tomas-stefano/infinity_test"
|
28
|
+
puts 'Thanks :)'
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
def require_without_rubygems(options)
|
33
|
+
gem_name = options[:gem]
|
34
|
+
begin
|
35
|
+
require gem_name
|
36
|
+
rescue LoadError
|
37
|
+
require 'rubygems'
|
38
|
+
require gem_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require_without_rubygems :gem => 'watchr'
|
43
|
+
|
44
|
+
require 'ostruct'
|
45
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module InfinityTest
|
2
|
+
module Notifications
|
3
|
+
class Growl
|
4
|
+
|
5
|
+
# Notification via Growl
|
6
|
+
#
|
7
|
+
# Growl.new.notify(:ruby_version => "Ruby 1.9.2", :message => "0 examples, 0 failures", :image => 'image.png')
|
8
|
+
#
|
9
|
+
def notify(options)
|
10
|
+
system "growlnotify -n infinity_test -m '#{options[:message]}' -t 'Ruby #{options[:title]}' --image #{options[:image]} -n infinity_test"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module InfinityTest
|
4
|
+
class Options < Hash
|
5
|
+
|
6
|
+
def initialize(arguments)
|
7
|
+
super()
|
8
|
+
@options = OptionParser.new do |options|
|
9
|
+
parse_rspec(options)
|
10
|
+
parse_test_unit(options)
|
11
|
+
parse_rubies(options)
|
12
|
+
parse_verbose(options)
|
13
|
+
options.banner = [ "Usage: infinity_test [options]", "Starts a continuous test server."].join("\n")
|
14
|
+
options.on_tail("--help", "You're looking at it.") do
|
15
|
+
print options.help
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
end
|
19
|
+
@options.parse!(arguments.clone)
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_rspec(options)
|
23
|
+
options.on('--rspec', 'Rspec Framework') do
|
24
|
+
self[:test_framework] = :rspec
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_test_unit(options)
|
29
|
+
options.on('--test-unit', 'Test Unit') do
|
30
|
+
self[:test_framework] = :test_unit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_rubies(options)
|
35
|
+
options.on('--rubies=rubies', 'Specify the Ruby Versions for Testing with several Rubies') do |versions|
|
36
|
+
self[:rubies] = versions
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_verbose(options)
|
41
|
+
options.on('--verbose', 'The Infinity Test dont print the commands. To print the command set this options!') do
|
42
|
+
self[:verbose] = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def rspec?
|
47
|
+
return true if self[:test_framework].equal?(:rspec)
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module InfinityTest
|
2
|
+
class Rspec
|
3
|
+
include BinaryPath
|
4
|
+
attr_accessor :rubies, :test_directory_pattern, :message, :test_pattern,
|
5
|
+
:failure, :sucess, :pending
|
6
|
+
|
7
|
+
#
|
8
|
+
# rspec = InfinityTest::Rspec.new(:rubies => '1.9.1,1.9.2')
|
9
|
+
# rspec.rubies # => '1.9.1,1.9.2'
|
10
|
+
#
|
11
|
+
def initialize(options={})
|
12
|
+
@rubies = options[:rubies] || []
|
13
|
+
@test_directory_pattern = "^spec/*/(.*)_spec.rb"
|
14
|
+
@test_pattern = options[:test_pattern] || 'spec/**/*_spec.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
def construct_commands(file=nil)
|
18
|
+
@rubies << RVM::Environment.current.environment_name if @rubies.empty?
|
19
|
+
construct_rubies_commands(file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def all_files
|
23
|
+
Dir[@test_pattern]
|
24
|
+
end
|
25
|
+
|
26
|
+
def spec_files
|
27
|
+
all_files.collect { |file| file }.join(' ')
|
28
|
+
end
|
29
|
+
|
30
|
+
def construct_rubies_commands(file=nil)
|
31
|
+
results = Hash.new
|
32
|
+
RVM.environments(@rubies) do |environment|
|
33
|
+
ruby_version = environment.environment_name
|
34
|
+
rspec_binary = search_rspec_two(environment)
|
35
|
+
rspec_binary = search_rspec_one(environment) unless File.exist?(rspec_binary)
|
36
|
+
unless have_binary?(rspec_binary)
|
37
|
+
print_message('rspec', ruby_version)
|
38
|
+
else
|
39
|
+
results[ruby_version] = "rvm #{ruby_version} ruby #{rspec_binary} #{decide_files(file)}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
results
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO: I'm not satisfied yet
|
46
|
+
#
|
47
|
+
def decide_files(file)
|
48
|
+
return file if file
|
49
|
+
spec_files
|
50
|
+
end
|
51
|
+
|
52
|
+
def search_rspec_two(environment)
|
53
|
+
search_binary('rspec', :environment => environment)
|
54
|
+
end
|
55
|
+
|
56
|
+
def search_rspec_one(environment)
|
57
|
+
search_binary('spec', :environment => environment)
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_results(results)
|
61
|
+
shell_result = results.split("\n").last
|
62
|
+
if shell_result =~ /example/
|
63
|
+
@example = shell_result[/(\d+) example/, 1].to_i
|
64
|
+
@failure = shell_result[/(\d+) failure/, 1].to_i
|
65
|
+
@pending = shell_result[/(\d+) pending/, 1].to_i
|
66
|
+
@message = "#{@example} examples, #{@failure} failures, #{@pending} pending"
|
67
|
+
else
|
68
|
+
@example, @pending, @failure = 0, 0, 1
|
69
|
+
@message = "An exception occurred"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def sucess?
|
74
|
+
return false if failure? or pending?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def failure?
|
79
|
+
@failure > 0
|
80
|
+
end
|
81
|
+
|
82
|
+
def pending?
|
83
|
+
@pending > 0 and not failure?
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module InfinityTest
|
2
|
+
class Runner
|
3
|
+
attr_reader :commands, :options, :application
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
@commands = []
|
8
|
+
@application = InfinityTest.application
|
9
|
+
end
|
10
|
+
|
11
|
+
def run!
|
12
|
+
load_configuration_file_or_read_the_options!
|
13
|
+
start_continuous_testing!
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_configuration_file_or_read_the_options!
|
17
|
+
@application.load_configuration_file
|
18
|
+
@application.config.use(
|
19
|
+
:rubies => (options[:rubies] || @application.rubies),
|
20
|
+
:test_framework => (options[:test_framework] || @application.config.test_framework),
|
21
|
+
:verbose => options[:verbose] || @application.config.verbose
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_continuous_testing!
|
26
|
+
InfinityTest::ContinuousTesting.new(:application => @application).start!
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module InfinityTest
|
2
|
+
class TestUnit
|
3
|
+
attr_reader :rubies, :message, :test_directory_pattern, :tests,
|
4
|
+
:assertions, :failures, :errors
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@rubies = options[:rubies] || []
|
8
|
+
@test_directory_pattern = "^test/*/(.*)_test.rb"
|
9
|
+
@test_pattern = 'test/**/*_test.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
def construct_commands(file=nil)
|
13
|
+
@rubies << RVM::Environment.current.environment_name if @rubies.empty?
|
14
|
+
construct_rubies_commands(file)
|
15
|
+
end
|
16
|
+
|
17
|
+
def construct_rubies_commands(file=nil)
|
18
|
+
results = Hash.new
|
19
|
+
RVM.environments(@rubies) do |environment|
|
20
|
+
ruby_version = environment.environment_name
|
21
|
+
results[ruby_version] = "rvm #{ruby_version} ruby -I'lib:test' #{decide_files(file)}"
|
22
|
+
end
|
23
|
+
results
|
24
|
+
end
|
25
|
+
|
26
|
+
def decide_files(file)
|
27
|
+
return file if file
|
28
|
+
test_files
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_files
|
32
|
+
collect_test_files.unshift(test_loader).join(' ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def collect_test_files
|
36
|
+
all_files.collect { |file| file }
|
37
|
+
end
|
38
|
+
|
39
|
+
def all_files
|
40
|
+
Dir[@test_pattern]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_loader
|
44
|
+
$LOAD_PATH.each do |path|
|
45
|
+
file_path = File.join(path, "infinity_test/test_unit_loader.rb")
|
46
|
+
return file_path if File.exist?(file_path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_results(results)
|
51
|
+
shell_result = results.split("\n")
|
52
|
+
shell_result = shell_result.select { |line| line =~ /(\d+) tests/}.first
|
53
|
+
if shell_result
|
54
|
+
@tests = shell_result[/(\d+) tests/, 1].to_i
|
55
|
+
@assertions = shell_result[/(\d+) assertions/, 1].to_i
|
56
|
+
@failures = shell_result[/(\d+) failures/, 1].to_i
|
57
|
+
@errors = shell_result[/(\d+) errors/, 1].to_i
|
58
|
+
@message = shell_result
|
59
|
+
else
|
60
|
+
@tests, @assertions, @failures, @errors = 0, 0, 1, 1
|
61
|
+
@message = "An exception ocurred"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def failure?
|
66
|
+
@failures > 0 or @errors > 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def pending?
|
70
|
+
false # Don't have pending in Test::Unit right?? #doubt
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module InfinityTest
|
4
|
+
describe Application do
|
5
|
+
let(:application) { Application.new }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@application = Application.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return test_unit pattern for test unit" do
|
12
|
+
@application.library_directory_pattern.should eql "^lib/*/(.*)\.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return the rubies in the config" do
|
16
|
+
application_with(:rubies => ['1.8.7']).rubies.should == '1.8.7'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return the rubies in the config" do
|
20
|
+
application_with(:rubies => ['1.9.2']).rubies.should == '1.9.2'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return the before callback" do
|
24
|
+
app = application_with(:test_framework => :rspec)
|
25
|
+
proc = Proc.new { 'To Infinity and beyond!' }
|
26
|
+
app.config.before_run(&proc)
|
27
|
+
app.before_callback.should equal proc
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return the block when set after callback" do
|
31
|
+
app = application_with(:test_framework => :rspec)
|
32
|
+
proc = Proc.new { 'To Infinity and beyond!' }
|
33
|
+
app.config.after_run(&proc)
|
34
|
+
app.after_callback.should equal proc
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#image_to_show' do
|
38
|
+
|
39
|
+
before do
|
40
|
+
@application_with_rspec = application_with(:test_framework => :rspec)
|
41
|
+
@application_with_test_unit = application_with(:test_framework => :test_unit)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return sucess when pass all the tests" do
|
45
|
+
test_should_not_fail!(@application_with_rspec)
|
46
|
+
test_should_not_pending!(@application_with_rspec)
|
47
|
+
@application_with_rspec.image_to_show.should match /sucess/
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return failure when not pass all the tests" do
|
51
|
+
test_should_fail!(@application_with_rspec)
|
52
|
+
@application_with_rspec.image_to_show.should match /failure/
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return pending when have pending tests" do
|
56
|
+
test_should_not_fail!(@application_with_rspec)
|
57
|
+
test_should_pending!(@application_with_rspec)
|
58
|
+
@application_with_rspec.image_to_show.should match /pending/
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_should_not_fail!(object)
|
62
|
+
object.test_framework.should_receive(:failure?).and_return(false)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_fail!(object)
|
66
|
+
object.test_framework.should_receive(:failure?).and_return(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_should_pending!(object)
|
70
|
+
object.test_framework.should_receive(:pending?).and_return(true)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_should_not_pending!(object)
|
74
|
+
object.test_framework.should_receive(:pending?).and_return(false)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#notification_framework' do
|
80
|
+
|
81
|
+
it "should return the Growl notification framework if has :growl" do
|
82
|
+
application.config.notifications :growl
|
83
|
+
application.notification_framework.should be_instance_of InfinityTest::Notifications::Growl
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return the Lib Notify if has :lib_notify" do
|
87
|
+
application.config.notifications :lib_notify
|
88
|
+
application.notification_framework.should be_instance_of InfinityTest::Notifications::LibNotify
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should cache notification" do
|
92
|
+
application.config.notifications :lib_notify
|
93
|
+
notification = application.notification_framework
|
94
|
+
application.notification_framework.should equal notification
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#test_framework' do
|
100
|
+
|
101
|
+
before do
|
102
|
+
@application = Application.new
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return the instance of Rspec when test framework is Rspec" do
|
106
|
+
@application.config.use :test_framework => :rspec
|
107
|
+
@application.test_framework.should be_instance_of(InfinityTest::Rspec)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return the instance of Rspec when test framework is Rspec" do
|
111
|
+
@application.config.use :test_framework => :test_unit
|
112
|
+
@application.test_framework.should be_instance_of(InfinityTest::TestUnit)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should pass all the rubies for the test_framework TestUnit" do
|
116
|
+
@application.config.use :test_framework => :test_unit, :rubies => ['1.9.1', '1.9.2']
|
117
|
+
TestUnit.should_receive(:new).with(:rubies => '1.9.1,1.9.2')
|
118
|
+
@application.test_framework
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should pass all the rubies for the test_framework Rspec" do
|
122
|
+
@application.config.use :test_framework => :rspec, :rubies => ['1.9.1', '1.9.2']
|
123
|
+
Rspec.should_receive(:new).with(:rubies => '1.9.1,1.9.2')
|
124
|
+
@application.test_framework
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should cache the test framework instance" do
|
128
|
+
@application.config.use :test_framework => :rspec
|
129
|
+
test_framework = @application.test_framework
|
130
|
+
@application.test_framework.should equal test_framework
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#verbose?' do
|
136
|
+
|
137
|
+
it "should return to false when not set verbose" do
|
138
|
+
@application.verbose?.should equal false
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should return true when set verbose to true" do
|
142
|
+
@application.config.verbose = true
|
143
|
+
@application.verbose?.should be_true
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|