rspec-core 2.0.0.beta.9 → 2.0.0.beta.10
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/VERSION +1 -1
- data/features/configuration/custom_settings.feature +86 -0
- data/features/formatters/custom_formatter.feature +1 -1
- data/lib/rspec/core.rb +6 -1
- data/lib/rspec/core/backward_compatibility.rb +3 -5
- data/lib/rspec/core/command_line.rb +52 -0
- data/lib/rspec/core/configuration.rb +106 -118
- data/lib/rspec/core/configuration_options.rb +30 -88
- data/lib/rspec/core/deprecation.rb +3 -4
- data/lib/rspec/core/drb_command_line.rb +29 -0
- data/lib/rspec/core/formatters/base_formatter.rb +3 -8
- data/lib/rspec/core/formatters/base_text_formatter.rb +2 -2
- data/lib/rspec/core/formatters/documentation_formatter.rb +2 -2
- data/lib/rspec/core/kernel_extensions.rb +1 -1
- data/lib/rspec/core/metadata.rb +11 -11
- data/lib/rspec/core/option_parser.rb +84 -0
- data/lib/rspec/core/runner.rb +17 -42
- data/lib/rspec/core/world.rb +2 -2
- data/lib/rspec/monkey.rb +1 -0
- data/lib/rspec/monkey/spork/test_framework/rspec.rb +7 -0
- data/rspec-core.gemspec +18 -59
- data/spec/rspec/core/configuration_options_spec.rb +91 -7
- data/spec/rspec/core/configuration_spec.rb +52 -18
- data/spec/rspec/core/deprecations_spec.rb +4 -2
- data/spec/rspec/core/drb_command_line_spec.rb +151 -0
- data/spec/rspec/core/formatters/base_formatter_spec.rb +2 -1
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +1 -2
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +1 -2
- data/spec/rspec/core/formatters/progress_formatter_spec.rb +1 -2
- data/spec/rspec/core/resources/a_spec.rb +1 -1
- data/spec/rspec/core/runner_spec.rb +38 -27
- data/spec/rspec/core/shared_example_group_spec.rb +1 -1
- data/spec/spec_helper.rb +56 -41
- metadata +17 -58
- data/example_specs/failing/README.txt +0 -7
- data/example_specs/failing/diffing_spec.rb +0 -38
- data/example_specs/failing/failing_implicit_docstrings_example.rb +0 -19
- data/example_specs/failing/failure_in_after.rb +0 -10
- data/example_specs/failing/failure_in_before.rb +0 -10
- data/example_specs/failing/mocking_example.rb +0 -40
- data/example_specs/failing/mocking_with_flexmock.rb +0 -26
- data/example_specs/failing/mocking_with_mocha.rb +0 -25
- data/example_specs/failing/mocking_with_rr.rb +0 -27
- data/example_specs/failing/partial_mock_example.rb +0 -20
- data/example_specs/failing/pending_example.rb +0 -9
- data/example_specs/failing/predicate_example.rb +0 -34
- data/example_specs/failing/raising_example.rb +0 -47
- data/example_specs/failing/spec_helper.rb +0 -1
- data/example_specs/failing/syntax_error_example.rb +0 -7
- data/example_specs/failing/team_spec.rb +0 -43
- data/example_specs/failing/timeout_behaviour.rb +0 -7
- data/example_specs/passing/custom_formatter.rb +0 -12
- data/example_specs/passing/custom_matchers.rb +0 -54
- data/example_specs/passing/dynamic_spec.rb +0 -9
- data/example_specs/passing/file_accessor.rb +0 -19
- data/example_specs/passing/file_accessor_spec.rb +0 -38
- data/example_specs/passing/filtered_formatter.rb +0 -18
- data/example_specs/passing/filtered_formatter_example.rb +0 -31
- data/example_specs/passing/greeter_spec.rb +0 -31
- data/example_specs/passing/helper_method_example.rb +0 -14
- data/example_specs/passing/implicit_docstrings_example.rb +0 -18
- data/example_specs/passing/io_processor.rb +0 -8
- data/example_specs/passing/io_processor_spec.rb +0 -21
- data/example_specs/passing/mocking_example.rb +0 -27
- data/example_specs/passing/multi_threaded_example_group_runner.rb +0 -26
- data/example_specs/passing/nested_classes_example.rb +0 -36
- data/example_specs/passing/options_example.rb +0 -31
- data/example_specs/passing/options_formatter.rb +0 -20
- data/example_specs/passing/partial_mock_example.rb +0 -29
- data/example_specs/passing/pending_example.rb +0 -20
- data/example_specs/passing/predicate_example.rb +0 -27
- data/example_specs/passing/shared_example_group_example.rb +0 -81
- data/example_specs/passing/shared_stack_examples.rb +0 -36
- data/example_specs/passing/spec_helper.rb +0 -1
- data/example_specs/passing/stack.rb +0 -36
- data/example_specs/passing/stack_spec.rb +0 -64
- data/example_specs/passing/stack_spec_with_nested_example_groups.rb +0 -67
- data/example_specs/passing/stubbing_example.rb +0 -69
- data/example_specs/passing/subject_example.rb +0 -45
- data/example_specs/passing/yielding_example.rb +0 -33
- data/example_specs/ruby1.9.compatibility/access_to_constants_spec.rb +0 -85
- data/example_specs/spec_helper.rb +0 -10
- data/features/configuration/custom_options.feature +0 -71
@@ -8,113 +8,56 @@ module RSpec
|
|
8
8
|
LOCAL_OPTIONS_FILE = ".rspec"
|
9
9
|
GLOBAL_OPTIONS_FILE = File.join(File.expand_path("~"), ".rspec")
|
10
10
|
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :options
|
12
12
|
|
13
13
|
def initialize(args)
|
14
14
|
@args = args
|
15
|
-
@options =
|
15
|
+
@options = parse_options
|
16
16
|
end
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
config.send("#{key}=", value)
|
17
|
+
|
18
|
+
def configure(config)
|
19
|
+
options.each do |key, value|
|
20
|
+
config.send("#{key}=", value) rescue nil
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def drb_argv
|
25
|
+
argv = []
|
26
|
+
argv << "--color" if options[:color_enabled]
|
27
|
+
argv << "--profile" if options[:profile_examples]
|
28
|
+
argv << "--backtrace" if options[:full_backtrace]
|
29
|
+
argv << "--formatter" << options[:formatter] if options[:formatter]
|
30
|
+
argv << "--line_number" << options[:line_number] if options[:line_number]
|
31
|
+
argv << "--options_file" << options[:options_file] if options[:options_file]
|
32
|
+
argv << "--example" << options[:full_description].source if options[:full_description]
|
33
|
+
argv + options[:files_or_directories_to_run]
|
28
34
|
end
|
29
35
|
|
30
36
|
private
|
31
37
|
|
32
|
-
def
|
38
|
+
def parse_options
|
39
|
+
command_line_options = parse_command_line_options
|
40
|
+
local_options = parse_local_options(command_line_options)
|
41
|
+
global_options = parse_global_options
|
42
|
+
|
33
43
|
[global_options, local_options, command_line_options].inject do |merged, options|
|
34
44
|
merged.merge(options)
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
38
|
-
def
|
39
|
-
|
48
|
+
def parse_command_line_options
|
49
|
+
options = Parser.parse!(@args)
|
50
|
+
options[:files_or_directories_to_run] = @args
|
51
|
+
options
|
40
52
|
end
|
41
53
|
|
42
|
-
|
43
|
-
|
44
|
-
new.parse!(args)
|
45
|
-
end
|
46
|
-
|
47
|
-
class << self
|
48
|
-
alias_method :parse, :parse!
|
49
|
-
end
|
50
|
-
|
51
|
-
def parse!(args)
|
52
|
-
options = {}
|
53
|
-
parser(options).parse!(args)
|
54
|
-
options
|
55
|
-
end
|
56
|
-
|
57
|
-
alias_method :parse, :parse!
|
58
|
-
|
59
|
-
def parser(options)
|
60
|
-
OptionParser.new do |parser|
|
61
|
-
parser.banner = "Usage: rspec [options] [files or directories]"
|
62
|
-
|
63
|
-
parser.on('-b', '--backtrace', 'Enable full backtrace') do |o|
|
64
|
-
options[:full_backtrace] = true
|
65
|
-
end
|
66
|
-
|
67
|
-
parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output') do |o|
|
68
|
-
options[:color_enabled] = o
|
69
|
-
end
|
70
|
-
|
71
|
-
parser.on('-d', '--debug', 'Enable debugging') do |o|
|
72
|
-
options[:debug] = true
|
73
|
-
end
|
74
|
-
|
75
|
-
parser.on('-e', '--example PATTERN', "Run examples whose full descriptions match this pattern",
|
76
|
-
"(PATTERN is compiled into a Ruby regular expression)") do |o|
|
77
|
-
options[:full_description] = /#{o}/
|
78
|
-
end
|
79
|
-
|
80
|
-
parser.on('-f', '--formatter FORMATTER', 'Choose a formatter',
|
81
|
-
' [p]rogress (default - dots)',
|
82
|
-
' [d]ocumentation (group and example names)') do |o|
|
83
|
-
options[:formatter] = o
|
84
|
-
end
|
85
|
-
|
86
|
-
parser.on_tail('-h', '--help', "You're looking at it.") do
|
87
|
-
puts parser
|
88
|
-
exit
|
89
|
-
end
|
90
|
-
|
91
|
-
parser.on('-I DIRECTORY', 'specify $LOAD_PATH directory (may be used more than once)') do |dir|
|
92
|
-
options[:libs] ||= []
|
93
|
-
options[:libs] << dir
|
94
|
-
end
|
95
|
-
|
96
|
-
parser.on('-l', '--line_number LINE', 'Specify the line number of a single example to run') do |o|
|
97
|
-
options[:line_number] = o
|
98
|
-
end
|
99
|
-
|
100
|
-
parser.on('-o', '--options PATH', 'Read configuration options from a file path. (Defaults to spec/spec.parser)') do |o|
|
101
|
-
options[:options_file] = o || local_options_file
|
102
|
-
end
|
103
|
-
|
104
|
-
parser.on('-p', '--profile', 'Enable profiling of examples with output of the top 10 slowest examples') do |o|
|
105
|
-
options[:profile_examples] = o
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
54
|
+
def parse_local_options(options)
|
55
|
+
parse_options_file(local_options_file(options))
|
109
56
|
end
|
110
57
|
|
111
|
-
def
|
58
|
+
def parse_global_options
|
112
59
|
parse_options_file(GLOBAL_OPTIONS_FILE)
|
113
60
|
end
|
114
|
-
|
115
|
-
def local_options
|
116
|
-
parse_options_file(local_options_file)
|
117
|
-
end
|
118
61
|
|
119
62
|
def parse_options_file(path)
|
120
63
|
Parser.parse(args_from_options_file(path))
|
@@ -125,13 +68,12 @@ module RSpec
|
|
125
68
|
File.readlines(path).map {|l| l.split}.flatten
|
126
69
|
end
|
127
70
|
|
128
|
-
def local_options_file
|
129
|
-
return
|
71
|
+
def local_options_file(options)
|
72
|
+
return options[:options_file] if options[:options_file]
|
130
73
|
return LOCAL_OPTIONS_FILE if File.exist?(LOCAL_OPTIONS_FILE)
|
131
74
|
RSpec.deprecate("spec/spec.opts", ".rspec or ~/.rspec", "2.0.0") if File.exist?("spec/spec.opts")
|
132
75
|
"spec/spec.opts"
|
133
76
|
end
|
134
|
-
|
135
77
|
end
|
136
78
|
end
|
137
79
|
end
|
@@ -21,13 +21,12 @@ ADDITIONAL
|
|
21
21
|
end
|
22
22
|
|
23
23
|
message << "*****************************************************************"
|
24
|
-
|
24
|
+
warn_deprecation(message)
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
27
|
+
def warn_deprecation(message)
|
28
|
+
send :warn, message
|
29
29
|
end
|
30
|
-
|
31
30
|
end
|
32
31
|
|
33
32
|
class HashWithDeprecationNotice < Hash
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
class DRbCommandLine
|
4
|
+
def initialize(argv)
|
5
|
+
@options = RSpec::Core::ConfigurationOptions.new(argv)
|
6
|
+
end
|
7
|
+
|
8
|
+
def drb_port
|
9
|
+
@options.options[:drb_port] || ENV['RSPEC_DRB'] || 8989
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(err, out)
|
13
|
+
begin
|
14
|
+
begin
|
15
|
+
DRb.start_service("druby://localhost:0")
|
16
|
+
rescue SocketError, Errno::EADDRNOTAVAIL
|
17
|
+
DRb.start_service("druby://:0")
|
18
|
+
end
|
19
|
+
spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}")
|
20
|
+
spec_server.run(@options.drb_argv, err, out)
|
21
|
+
true
|
22
|
+
rescue DRb::DRbConnError
|
23
|
+
err.puts "No DRb server is running. Running in local process instead ..."
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,18 +5,15 @@ module RSpec
|
|
5
5
|
class BaseFormatter
|
6
6
|
include Helpers
|
7
7
|
attr_accessor :example_group
|
8
|
-
attr_reader :example_count, :duration, :examples
|
8
|
+
attr_reader :example_count, :duration, :examples, :output
|
9
9
|
|
10
|
-
def initialize
|
10
|
+
def initialize(output)
|
11
|
+
@output = output
|
11
12
|
@example_count = 0
|
12
13
|
@examples = []
|
13
14
|
@example_group = nil
|
14
15
|
end
|
15
16
|
|
16
|
-
def output
|
17
|
-
configuration.output
|
18
|
-
end
|
19
|
-
|
20
17
|
def pending_examples
|
21
18
|
@pending_examples ||= ::RSpec.world.find(examples, :execution_result => { :status => 'pending' })
|
22
19
|
end
|
@@ -28,8 +25,6 @@ module RSpec
|
|
28
25
|
def report(count)
|
29
26
|
sync_output do
|
30
27
|
start(count)
|
31
|
-
# TODO - spec that we still dump even when there's
|
32
|
-
# an exception
|
33
28
|
begin
|
34
29
|
yield self
|
35
30
|
ensure
|
@@ -60,8 +60,8 @@ module RSpec
|
|
60
60
|
sorted_examples = examples.sort_by { |example| example.execution_result[:run_time] }.reverse.first(10)
|
61
61
|
output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
|
62
62
|
sorted_examples.each do |example|
|
63
|
-
output.puts " (#{format_seconds(
|
64
|
-
output.puts grey(" # #{format_caller(example.metadata[:
|
63
|
+
output.puts " (#{format_seconds(example.execution_result[:run_time])} seconds) #{example}"
|
64
|
+
output.puts grey(" # #{format_caller(example.metadata[:location])}")
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Kernel
|
2
2
|
def debugger(*args)
|
3
|
-
|
3
|
+
RSpec.configuration.error_stream.puts "debugger statement ignored, use -d or --debug option to enable debugging\n#{caller(0)[1]}"
|
4
4
|
end
|
5
5
|
end
|
data/lib/rspec/core/metadata.rb
CHANGED
@@ -82,8 +82,8 @@ EOM
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def all_apply?(filters)
|
85
|
-
filters.all? do |
|
86
|
-
apply_condition(
|
85
|
+
filters.all? do |key, value|
|
86
|
+
apply_condition(key, value)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -96,23 +96,23 @@ EOM
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
def apply_condition(
|
99
|
+
def apply_condition(key, value, metadata=nil)
|
100
100
|
metadata ||= self
|
101
|
-
case
|
101
|
+
case value
|
102
102
|
when Hash
|
103
|
-
|
103
|
+
value.all? { |k, v| apply_condition(k, v, metadata[key]) }
|
104
104
|
when Regexp
|
105
|
-
metadata[
|
105
|
+
metadata[key] =~ value
|
106
106
|
when Proc
|
107
|
-
|
107
|
+
value.call(metadata[key]) rescue false
|
108
108
|
when Fixnum
|
109
|
-
if
|
110
|
-
relevant_line_numbers(metadata).include?(world.preceding_declaration_line(
|
109
|
+
if key == :line_number
|
110
|
+
relevant_line_numbers(metadata).include?(world.preceding_declaration_line(value))
|
111
111
|
else
|
112
|
-
metadata[
|
112
|
+
metadata[key] == value
|
113
113
|
end
|
114
114
|
else
|
115
|
-
metadata[
|
115
|
+
metadata[key] == value
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RSpec::Core
|
2
|
+
class Parser
|
3
|
+
def self.parse!(args)
|
4
|
+
new.parse!(args)
|
5
|
+
end
|
6
|
+
|
7
|
+
class << self
|
8
|
+
alias_method :parse, :parse!
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse!(args)
|
12
|
+
options = {}
|
13
|
+
parser(options).parse!(args)
|
14
|
+
options
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :parse, :parse!
|
18
|
+
|
19
|
+
def parser(options)
|
20
|
+
OptionParser.new do |parser|
|
21
|
+
parser.banner = "Usage: rspec [options] [files or directories]"
|
22
|
+
|
23
|
+
parser.on('-b', '--backtrace', 'Enable full backtrace') do |o|
|
24
|
+
options[:full_backtrace] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output') do |o|
|
28
|
+
options[:color_enabled] = o
|
29
|
+
end
|
30
|
+
|
31
|
+
parser.on('-d', '--debug', 'Enable debugging') do |o|
|
32
|
+
options[:debug] = true
|
33
|
+
end
|
34
|
+
|
35
|
+
parser.on('-e', '--example PATTERN', "Run examples whose full descriptions match this pattern",
|
36
|
+
"(PATTERN is compiled into a Ruby regular expression)") do |o|
|
37
|
+
options[:full_description] = /#{o}/
|
38
|
+
end
|
39
|
+
|
40
|
+
parser.on('-f', '--formatter FORMATTER', 'Choose a formatter',
|
41
|
+
' [p]rogress (default - dots)',
|
42
|
+
' [d]ocumentation (group and example names)') do |o|
|
43
|
+
options[:formatter] = o
|
44
|
+
end
|
45
|
+
|
46
|
+
parser.on_tail('-h', '--help', "You're looking at it.") do
|
47
|
+
puts parser
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
parser.on('-I DIRECTORY', 'specify $LOAD_PATH directory (may be used more than once)') do |dir|
|
52
|
+
options[:libs] ||= []
|
53
|
+
options[:libs] << dir
|
54
|
+
end
|
55
|
+
|
56
|
+
parser.on('-l', '--line_number LINE', 'Specify the line number of a single example to run') do |o|
|
57
|
+
options[:line_number] = o
|
58
|
+
end
|
59
|
+
|
60
|
+
parser.on('-o', '--options PATH', 'Read configuration options from a file path. (Defaults to spec/spec.parser)') do |o|
|
61
|
+
options[:options_file] = o || local_options_file
|
62
|
+
end
|
63
|
+
|
64
|
+
parser.on('-p', '--profile', 'Enable profiling of examples with output of the top 10 slowest examples') do |o|
|
65
|
+
options[:profile_examples] = o
|
66
|
+
end
|
67
|
+
|
68
|
+
parser.on('-v', '--version', 'Show version') do
|
69
|
+
puts RSpec::Core::Version::STRING
|
70
|
+
exit
|
71
|
+
end
|
72
|
+
|
73
|
+
parser.on('-X', '--drb', 'Run examples via DRb') do |o|
|
74
|
+
options[:drb] = true
|
75
|
+
end
|
76
|
+
|
77
|
+
parser.on('--drb-port [PORT]', 'Port to connect to on the DRb server') do |o|
|
78
|
+
options[:drb_port] = o.to_i
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/rspec/core/runner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'drb/drb'
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Core
|
3
5
|
class Runner
|
@@ -7,60 +9,33 @@ module RSpec
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def self.autorun
|
10
|
-
return if installed_at_exit?
|
12
|
+
return if installed_at_exit? || running_in_drb?
|
11
13
|
@installed_at_exit = true
|
12
|
-
at_exit {
|
13
|
-
end
|
14
|
-
|
15
|
-
def configuration
|
16
|
-
RSpec.configuration
|
14
|
+
at_exit { run(ARGV, $stderr, $stdout) ? exit(0) : exit(1) }
|
17
15
|
end
|
18
16
|
|
19
|
-
def
|
20
|
-
|
17
|
+
def self.running_in_drb?
|
18
|
+
(DRb.current_server rescue false) &&
|
19
|
+
!!((DRb.current_server.uri) =~ /druby\:\/\/127.0.0.1\:/)
|
21
20
|
end
|
22
21
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
configure(args)
|
29
|
-
RSpec.world.announce_inclusion_filter
|
30
|
-
|
31
|
-
reporter.report(example_count) do |reporter|
|
32
|
-
example_groups.run_examples(reporter)
|
22
|
+
def self.run(args, err, out)
|
23
|
+
if args.any? {|a| %w[--drb -X].include? a}
|
24
|
+
run_over_drb(args, err, out) || run_in_process(args, err, out)
|
25
|
+
else
|
26
|
+
run_in_process(args, err, out)
|
33
27
|
end
|
34
|
-
|
35
|
-
example_groups.success?
|
36
28
|
end
|
37
|
-
|
38
|
-
private
|
39
29
|
|
40
|
-
def
|
41
|
-
|
42
|
-
configuration.require_files_to_run
|
43
|
-
configuration.configure_mock_framework
|
30
|
+
def self.run_over_drb(args, err, out)
|
31
|
+
DRbCommandLine.new(args).run(err, out)
|
44
32
|
end
|
45
33
|
|
46
|
-
def
|
47
|
-
|
34
|
+
def self.run_in_process(args, err, out)
|
35
|
+
CommandLine.new(args).run(err, out)
|
48
36
|
end
|
49
37
|
|
50
|
-
def example_groups
|
51
|
-
RSpec.world.example_groups.extend(ExampleGroups)
|
52
|
-
end
|
53
|
-
|
54
|
-
module ExampleGroups
|
55
|
-
def run_examples(reporter)
|
56
|
-
@success = self.inject(true) {|success, group| success &= group.run(reporter)}
|
57
|
-
end
|
58
|
-
|
59
|
-
def success?
|
60
|
-
@success ||= false
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
38
|
end
|
39
|
+
|
65
40
|
end
|
66
41
|
end
|