fit 1.1 → 1.2
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/CHANGELOG +27 -0
- data/{README.txt → README.rdoc} +28 -9
- data/Rakefile +44 -4
- data/bin/fit +29 -3
- data/doc/book/TestChatServer.html +207 -0
- data/doc/book/TestDiscount.html +178 -0
- data/doc/book/TestDiscountGroup.html +223 -0
- data/doc/book/TestDiscountMoney.html +179 -0
- data/doc/book/TestLateHours.html +245 -0
- data/doc/bugs/ColumnFixtureFollowedByActionFixture.html +316 -0
- data/doc/examples/MusicExampleWithErrors.html +1 -1
- data/doc/spec/annotation.html +3634 -3833
- data/doc/spec/index.html +1043 -947
- data/doc/spec/parse-windows-1252.html +3806 -0
- data/doc/spec/parse.html +3806 -3094
- data/doc/spec/ui.html +1537 -0
- data/lib/eg/all_files.rb +1 -1
- data/lib/eg/book/calculate_discount.rb +25 -0
- data/lib/eg/book/calculate_discount_money.rb +60 -0
- data/lib/eg/book/chat_server_actions.rb +85 -0
- data/lib/eg/book/discount_group_ordered_list.rb +59 -0
- data/lib/eg/book/rent/calculate_late_hours.rb +35 -0
- data/lib/eg/column_index.rb +4 -3
- data/lib/eg/music/display.rb +4 -2
- data/lib/eg/music/music.rb +4 -2
- data/lib/fat/command_line_fixture.rb +33 -0
- data/lib/fat/html_to_text_fixture.rb +3 -3
- data/lib/fit/column_fixture.rb +11 -7
- data/lib/fit/file_runner.rb +65 -10
- data/lib/fit/fixture.rb +10 -4
- data/lib/fit/fixture_loader.rb +29 -19
- data/lib/fit/parse.rb +46 -12
- data/lib/fit/type_adapter.rb +8 -3
- data/lib/fit/version.rb +26 -0
- data/lib/fitlibrary/comment_fixture.rb +12 -0
- data/lib/fitlibrary/spec/specify_fixture.rb +154 -0
- data/lib/fitlibrary/specify/column_fixture_under_test.rb +17 -0
- data/lib/fitlibrary/specify/column_fixture_under_test_with_args.rb +17 -0
- data/lib/fittask.rb +43 -47
- data/test/all_tests.rb +2 -1
- data/test/column_fixture_test.rb +26 -0
- data/test/file_runner_test.rb +2 -7
- data/test/fixture_loader_test.rb +16 -3
- data/test/parse_test.rb +18 -3
- data/test/type_adapter_test.rb +58 -44
- metadata +180 -156
data/lib/eg/all_files.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'fit/column_fixture'
|
2
|
+
|
3
|
+
module Eg
|
4
|
+
module Book
|
5
|
+
|
6
|
+
class CalculateDiscount < Fit::ColumnFixture
|
7
|
+
attr_writer :amount
|
8
|
+
def initialize
|
9
|
+
@application = Discount.new
|
10
|
+
end
|
11
|
+
def discount
|
12
|
+
@application.get_discount @amount
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Discount
|
17
|
+
# A 5 percent discount is provided whenever the
|
18
|
+
# total purchase is greater than $1,000
|
19
|
+
def get_discount amount
|
20
|
+
(amount >= 1000) ? (amount / 100.0) * 5 : 0.0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fit/column_fixture'
|
2
|
+
|
3
|
+
module Eg
|
4
|
+
module Book
|
5
|
+
|
6
|
+
class MoneyDiscount
|
7
|
+
# A 5 percent discount is provided whenever the
|
8
|
+
# total purchase is greater than $1,000
|
9
|
+
def get_discount amount
|
10
|
+
(amount >= Money.new(1000)) ? (amount * 0.05) : Money.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Money
|
15
|
+
attr_reader :cents
|
16
|
+
def initialize amount = 0
|
17
|
+
@cents = (amount * 100 + 0.5).to_i
|
18
|
+
end
|
19
|
+
def >= money
|
20
|
+
@cents >= money.cents
|
21
|
+
end
|
22
|
+
def * times
|
23
|
+
Money.new(@cents / 100.0 * times)
|
24
|
+
end
|
25
|
+
def == money
|
26
|
+
money.class == Money and @cents == money.cents
|
27
|
+
end
|
28
|
+
def Money.parse string
|
29
|
+
raise Exception.new('Invalid money value') unless string =~ /^\$/
|
30
|
+
dot = string.index '.'
|
31
|
+
raise Exception.new('Invalid money value') if dot.nil? or dot != string.size - 3
|
32
|
+
money = string[1..-1].to_f
|
33
|
+
Money.new money
|
34
|
+
end
|
35
|
+
def to_s
|
36
|
+
cent_string = "#{@cents % 100}"
|
37
|
+
cent_string += '0' if cent_string.size == 1
|
38
|
+
"$#{cents / 100}.#{cent_string}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Fixture
|
43
|
+
|
44
|
+
class CalculateDiscountMoney < Fit::ColumnFixture
|
45
|
+
attr_writer :amount
|
46
|
+
def initialize
|
47
|
+
@application = MoneyDiscount.new
|
48
|
+
end
|
49
|
+
def discount
|
50
|
+
@application.get_discount @amount
|
51
|
+
end
|
52
|
+
@@metadata = { 'amount' => Money, 'discount()' => Money }
|
53
|
+
def parse string, klass
|
54
|
+
return Money.parse(string) if klass == Money
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fit/fixture'
|
2
|
+
|
3
|
+
module Eg
|
4
|
+
module Book
|
5
|
+
|
6
|
+
class ChatServerActions < Fit::Fixture
|
7
|
+
def initialize
|
8
|
+
@chat = ChatRoom.new
|
9
|
+
end
|
10
|
+
def user user_name
|
11
|
+
@user_name = user_name
|
12
|
+
end
|
13
|
+
def connect
|
14
|
+
@chat.connect_user @user_name
|
15
|
+
end
|
16
|
+
def room room_name
|
17
|
+
@room_name = room_name
|
18
|
+
end
|
19
|
+
def new_room
|
20
|
+
@chat.user_creates_room @user_name, @room_name
|
21
|
+
end
|
22
|
+
def enter_room
|
23
|
+
@chat.user_enters_room @user_name, @room_name
|
24
|
+
end
|
25
|
+
def occupant_count
|
26
|
+
@chat.occupants @room_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ChatRoom
|
31
|
+
def initialize
|
32
|
+
@users = {}
|
33
|
+
@rooms = {}
|
34
|
+
end
|
35
|
+
def connect_user user_name
|
36
|
+
return false unless @users[user_name].nil?
|
37
|
+
@users[user_name] = User.new user_name
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
def user_creates_room user_name, room_name
|
41
|
+
user = @users[user_name]
|
42
|
+
raise Exception.new("Unknown user name: #{user_name}") unless user
|
43
|
+
raise Exception.new("Duplicate room name: #{room_name}") if @rooms.include? room_name
|
44
|
+
@rooms[room_name] = Room.new room_name, user, self
|
45
|
+
end
|
46
|
+
def user_enters_room user_name, room_name
|
47
|
+
user = @users[user_name]
|
48
|
+
room = @rooms[room_name]
|
49
|
+
return false if user.nil? or room.nil?
|
50
|
+
room.add user
|
51
|
+
return true
|
52
|
+
end
|
53
|
+
def occupants room_name
|
54
|
+
room = @rooms[room_name]
|
55
|
+
raise Exception.new("Unknown room: #{room_name}") unless room
|
56
|
+
room.occupant_count
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class User
|
61
|
+
attr_accessor :name
|
62
|
+
def initialize name
|
63
|
+
@name = name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
require 'set'
|
68
|
+
|
69
|
+
class Room
|
70
|
+
def initialize room_name, owner, chat
|
71
|
+
@name = room_name
|
72
|
+
@owner = owner
|
73
|
+
@chat = chat
|
74
|
+
@users = Set.new
|
75
|
+
end
|
76
|
+
def add user
|
77
|
+
@users.add user
|
78
|
+
end
|
79
|
+
def occupant_count
|
80
|
+
@users.size
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'fit/row_fixture'
|
2
|
+
|
3
|
+
module Eg
|
4
|
+
module Book
|
5
|
+
|
6
|
+
class DiscountGroupOrderedList < Fit::RowFixture
|
7
|
+
def query
|
8
|
+
groups = DiscountGroup.get_elements
|
9
|
+
ordered_groups = []
|
10
|
+
groups.each_with_index { |e, i|
|
11
|
+
group = OrderedDiscountGroup.new(i + 1, e.future_value,
|
12
|
+
e.max_owing, e.min_purchase, e.discount_percent)
|
13
|
+
ordered_groups << group
|
14
|
+
}
|
15
|
+
ordered_groups
|
16
|
+
end
|
17
|
+
def get_target_class
|
18
|
+
OrderedDiscountGroup
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# System under test
|
23
|
+
|
24
|
+
class OrderedDiscountGroup
|
25
|
+
attr_reader :order, :future_value
|
26
|
+
attr_reader :max_owing, :min_purchase, :discount_percent
|
27
|
+
def initialize order, future_value, max_owing, min_purchase, discount_percent
|
28
|
+
@order = order
|
29
|
+
@future_value = future_value
|
30
|
+
@max_owing = max_owing
|
31
|
+
@min_purchase = min_purchase
|
32
|
+
@discount_percent = discount_percent
|
33
|
+
end
|
34
|
+
@@metadata = { 'order' => Fixnum, 'future_value' => String,
|
35
|
+
'max_owing' => Float, 'min_purchase' => Float, 'discount_percent' => Float }
|
36
|
+
def OrderedDiscountGroup.metadata; @@metadata; end
|
37
|
+
end
|
38
|
+
|
39
|
+
class DiscountGroup
|
40
|
+
attr_reader :future_value
|
41
|
+
attr_reader :max_owing, :min_purchase, :discount_percent
|
42
|
+
def initialize future_value, max_owing, min_purchase, discount_percent
|
43
|
+
@future_value = future_value
|
44
|
+
@max_owing = max_owing
|
45
|
+
@min_purchase = min_purchase
|
46
|
+
@discount_percent = discount_percent
|
47
|
+
end
|
48
|
+
def DiscountGroup.get_elements
|
49
|
+
[ DiscountGroup.new('low', 0, 0, 0),
|
50
|
+
DiscountGroup.new('low', 0, 2000, 3),
|
51
|
+
DiscountGroup.new('medium', 500, 600, 3),
|
52
|
+
DiscountGroup.new('medium', 0, 500, 5),
|
53
|
+
DiscountGroup.new('high', 2000, 2000, 10)
|
54
|
+
]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fit/column_fixture'
|
2
|
+
|
3
|
+
module Eg
|
4
|
+
module Book
|
5
|
+
|
6
|
+
module Rent
|
7
|
+
class CalculateLateHours < Fit::ColumnFixture
|
8
|
+
attr_writer :hours_late, :grace, :high_demand
|
9
|
+
attr_writer :count_grace
|
10
|
+
def count_grace= string
|
11
|
+
@count_grace = { 'yes' => true, 'no' => false }[string]
|
12
|
+
end
|
13
|
+
def extra_hours
|
14
|
+
late_returns = LateReturns.new @count_grace
|
15
|
+
late_returns.extra_hours @hours_late, @grace, @high_demand
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# System under test
|
21
|
+
|
22
|
+
class LateReturns
|
23
|
+
def initialize count_grace
|
24
|
+
@count_grace = count_grace
|
25
|
+
end
|
26
|
+
def extra_hours hours_late, grace, high_demand
|
27
|
+
return 0 if hours_late < 1
|
28
|
+
hours = @count_grace ? hours_late : (hours_late - grace)
|
29
|
+
return 0 if hours.zero?
|
30
|
+
high_demand + hours
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/eg/column_index.rb
CHANGED
@@ -31,8 +31,9 @@ module Eg
|
|
31
31
|
# ...then find the columns in these classes
|
32
32
|
columns = []
|
33
33
|
names.each do |name|
|
34
|
-
obj =
|
35
|
-
|
34
|
+
obj = @@loader.find_class(name).new
|
35
|
+
# Ruby 1.9 returns method names as symbols
|
36
|
+
attributes = (obj.methods - Object.new.methods).collect {|a| a.to_s}
|
36
37
|
setters = attributes.dup.delete_if {|a| a[-1..-1] != "="}
|
37
38
|
attributes -= setters
|
38
39
|
setters.each do |s|
|
@@ -58,7 +59,7 @@ module Eg
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def parse_class name
|
61
|
-
|
62
|
+
@@loader.find_class(name)
|
62
63
|
end
|
63
64
|
|
64
65
|
# Helper class
|
data/lib/eg/music/display.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'fit/row_fixture'
|
5
5
|
|
6
|
-
require '
|
6
|
+
require 'date'
|
7
7
|
|
8
8
|
module Eg
|
9
9
|
module Music
|
@@ -13,7 +13,9 @@ module Eg
|
|
13
13
|
def query; MusicLibrary.display_contents; end
|
14
14
|
def parse string, klass
|
15
15
|
if klass == Time
|
16
|
-
|
16
|
+
d = Date._parse string
|
17
|
+
d_array = [d[:year], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:zone], d[:wday]]
|
18
|
+
Time.gm(*d_array.compact)
|
17
19
|
else
|
18
20
|
super
|
19
21
|
end
|
data/lib/eg/music/music.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
|
2
2
|
# Released under the terms of the GNU General Public License version 2 or later.
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'date'
|
5
5
|
|
6
6
|
module Eg
|
7
7
|
module Music
|
@@ -48,7 +48,9 @@ module Eg
|
|
48
48
|
m.track_number = data[6].to_i
|
49
49
|
m.track_count = data[7].to_i
|
50
50
|
m.year = data[8].to_i
|
51
|
-
|
51
|
+
d = Date._parse data[9]
|
52
|
+
d_array = [d[:year], d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:zone], d[:wday]]
|
53
|
+
m.date = Time.gm(*d_array.compact)
|
52
54
|
m
|
53
55
|
end
|
54
56
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
|
2
|
+
# Released under the terms of the GNU General Public License version 2 or later.
|
3
|
+
|
4
|
+
require 'fit/column_fixture'
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
module Fat
|
9
|
+
|
10
|
+
# This is really testing OptionParser rather than some
|
11
|
+
# new RubyFIT code, but it's nice to have anyway just
|
12
|
+
# in case the Ruby standard library behaviour should
|
13
|
+
# change between subsequent versions.
|
14
|
+
class CommandLineFixture < Fit::ColumnFixture
|
15
|
+
attr_accessor :command_line
|
16
|
+
attr_reader :encoding
|
17
|
+
def initialize
|
18
|
+
@options = OptionParser.new
|
19
|
+
@options.on('--encoding=ENC') { |enc| @encoding = enc }
|
20
|
+
end
|
21
|
+
def input_file
|
22
|
+
args()[0]
|
23
|
+
end
|
24
|
+
def output_file
|
25
|
+
args()[1]
|
26
|
+
end
|
27
|
+
def args
|
28
|
+
@encoding = 'Implementation-specific'
|
29
|
+
@options.parse(command_line.split)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -9,12 +9,12 @@ module Fat
|
|
9
9
|
@@metadata = {'html' => String}
|
10
10
|
attr_writer :html
|
11
11
|
def text
|
12
|
-
html = @html.gsub(/\\u00a0/,
|
12
|
+
html = @html.gsub(/\\u00a0/, [0x00a0].pack('U'))
|
13
13
|
escape_ascii(Fit::Parse.html_to_text(html))
|
14
14
|
end
|
15
15
|
def escape_ascii text
|
16
|
-
text.gsub(
|
16
|
+
text.gsub([0x0a].pack('U'), "\\n").gsub([0x0d].pack('U'), "\\r").gsub([0xa0].pack('U'), " ")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
end
|
20
|
+
end
|
data/lib/fit/column_fixture.rb
CHANGED
@@ -79,13 +79,7 @@ module Fit
|
|
79
79
|
if name.empty?
|
80
80
|
@column_bindings << nil
|
81
81
|
else
|
82
|
-
|
83
|
-
if name =~ /\(\)$/
|
84
|
-
suffix = '()'
|
85
|
-
name = name[0...-2]
|
86
|
-
end
|
87
|
-
name = name.split(/([a-zA-Z][^A-Z]+)/).delete_if {|e| e.empty?}.collect {|e| e.downcase}.join('_')
|
88
|
-
name += suffix
|
82
|
+
name = camel name
|
89
83
|
adapter = TypeAdapter.for(self, name)
|
90
84
|
adapter.type = get_target_class.metadata[name]
|
91
85
|
@column_bindings << adapter
|
@@ -97,6 +91,16 @@ module Fit
|
|
97
91
|
end
|
98
92
|
end
|
99
93
|
|
94
|
+
def camel name
|
95
|
+
suffix = ''
|
96
|
+
if name =~ /\(\)$/
|
97
|
+
suffix = '()'
|
98
|
+
name = name[0...-2]
|
99
|
+
end
|
100
|
+
name = name.split(/([a-zA-Z][^A-Z]+)/).delete_if {|e| e.empty?}.collect {|e| e.strip.downcase}.join('_')
|
101
|
+
name += suffix
|
102
|
+
end
|
103
|
+
|
100
104
|
def get_target_class; self.class; end
|
101
105
|
|
102
106
|
end
|
data/lib/fit/file_runner.rb
CHANGED
@@ -5,17 +5,23 @@ require 'fit/fixture'
|
|
5
5
|
require 'fit/parse'
|
6
6
|
|
7
7
|
require 'fileutils' # for report generation
|
8
|
+
require 'iconv' # for I/O encoding
|
9
|
+
require 'stringio' # to help fix any possibly invalid byte sequence
|
8
10
|
|
9
11
|
module Fit
|
10
12
|
|
11
13
|
class FileRunner
|
12
14
|
attr_accessor :input, :tables, :fixture, :output
|
13
15
|
|
16
|
+
DEFAULT_ENCODING = 'UTF-8'
|
17
|
+
|
14
18
|
def initialize
|
15
19
|
@fixture = Fixture.new
|
20
|
+
@encoding = DEFAULT_ENCODING
|
16
21
|
end
|
17
22
|
|
18
|
-
def run args
|
23
|
+
def run args, opts=nil
|
24
|
+
@encoding = opts[:encoding].upcase unless opts.nil?
|
19
25
|
process_args args
|
20
26
|
process
|
21
27
|
$stderr.puts @fixture.totals
|
@@ -23,20 +29,58 @@ module Fit
|
|
23
29
|
end
|
24
30
|
|
25
31
|
def process_args args
|
26
|
-
error "
|
27
|
-
|
32
|
+
error "no input file" if args[0].nil?
|
28
33
|
input_name = File.expand_path args[0]
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
begin
|
35
|
+
if input_name.respond_to? :encoding
|
36
|
+
input_file = File.open input_name, "r:#@encoding"
|
37
|
+
else
|
38
|
+
input_file = File.open input_name
|
39
|
+
end
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
error "#{input_name}: file not found"
|
42
|
+
end
|
43
|
+
output_name = check_output_file args[1]
|
44
|
+
create_output_file output_name
|
33
45
|
@fixture.summary['input file'] = input_name
|
34
46
|
@fixture.summary['input update'] = input_file.mtime.to_s
|
35
47
|
@fixture.summary['output file'] = output_name
|
36
|
-
|
48
|
+
unless input_name.respond_to? :encoding
|
49
|
+
read_file_with_encoding input_file
|
50
|
+
else
|
51
|
+
read_file input_file
|
52
|
+
end
|
37
53
|
input_file.close
|
38
54
|
end
|
39
55
|
|
56
|
+
def check_output_file arg
|
57
|
+
error "no output file" if arg.nil?
|
58
|
+
output_name = File.expand_path arg
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_output_file output_name
|
62
|
+
FileUtils.mkpath File.dirname(output_name)
|
63
|
+
if output_name.respond_to? :encoding
|
64
|
+
@output = File.open output_name, "w:#@encoding"
|
65
|
+
else
|
66
|
+
@output = File.open output_name, 'w'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def read_file_with_encoding input_file
|
71
|
+
if @encoding == DEFAULT_ENCODING
|
72
|
+
@input = input_file.read
|
73
|
+
else
|
74
|
+
conv = Iconv.new DEFAULT_ENCODING, @encoding
|
75
|
+
@input = conv.iconv(input_file.read)
|
76
|
+
@input << conv.iconv(nil)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_file input_file
|
81
|
+
@input = (@encoding == DEFAULT_ENCODING) ? input_file.read : input_file.read.encode(DEFAULT_ENCODING)
|
82
|
+
end
|
83
|
+
|
40
84
|
def process
|
41
85
|
begin
|
42
86
|
unless @input.index('<wiki>').nil?
|
@@ -49,7 +93,18 @@ module Fit
|
|
49
93
|
rescue Exception => e
|
50
94
|
exception e
|
51
95
|
end
|
52
|
-
@
|
96
|
+
if @encoding == DEFAULT_ENCODING
|
97
|
+
@tables.print @output
|
98
|
+
else
|
99
|
+
buffer = StringIO.new
|
100
|
+
conv = Iconv.new "#{DEFAULT_ENCODING}//IGNORE", DEFAULT_ENCODING
|
101
|
+
@tables.print buffer, conv
|
102
|
+
buffer.print conv.iconv(nil)
|
103
|
+
conv = Iconv.new "#@encoding//IGNORE", DEFAULT_ENCODING
|
104
|
+
@output.print conv.iconv(buffer.string)
|
105
|
+
@output << conv.iconv(nil)
|
106
|
+
buffer.close
|
107
|
+
end
|
53
108
|
@output.close
|
54
109
|
end
|
55
110
|
|
@@ -59,7 +114,7 @@ module Fit
|
|
59
114
|
end
|
60
115
|
|
61
116
|
def error msg
|
62
|
-
$stderr.puts msg
|
117
|
+
$stderr.puts "#{File.basename($0)}: #{msg}"
|
63
118
|
exit -1
|
64
119
|
end
|
65
120
|
|