fit 1.1
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/README.txt +203 -0
- data/Rakefile +111 -0
- data/bin/FitServer.rb +6 -0
- data/bin/fit +10 -0
- data/bin/fit.cgi +36 -0
- data/doc/examples/AllCombinations.html +55 -0
- data/doc/examples/AllFiles.html +60 -0
- data/doc/examples/AllPairs/function/cosine.html +57 -0
- data/doc/examples/AllPairs/function/sine.html +57 -0
- data/doc/examples/AllPairs/magnitude/180+30.html +45 -0
- data/doc/examples/AllPairs/magnitude/30.html +33 -0
- data/doc/examples/AllPairs/magnitude/360+30.html +45 -0
- data/doc/examples/AllPairs/magnitude/90-30.html +45 -0
- data/doc/examples/AllPairs/sign/change-sign.html +27 -0
- data/doc/examples/AllPairs/sign/multiply.html +31 -0
- data/doc/examples/AllPairs/sign/no-change.html +23 -0
- data/doc/examples/AllPairs.html +51 -0
- data/doc/examples/BinaryChop.html +89 -0
- data/doc/examples/CalculatorExample.html +108 -0
- data/doc/examples/ColumnIndex.html +43 -0
- data/doc/examples/ExampleTests.html +43 -0
- data/doc/examples/FitAcceptanceTests.html +53 -0
- data/doc/examples/GeoCoordinate.html +87 -0
- data/doc/examples/MusicExample.html +143 -0
- data/doc/examples/MusicExampleWithErrors.html +128 -0
- data/doc/examples/NetworkExample.html +47 -0
- data/doc/examples/WebPageExample.html +92 -0
- data/doc/examples/arithmetic.html +211 -0
- data/doc/examples/files/hp35bk.jpg +0 -0
- data/doc/examples/logo.gif +0 -0
- data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.FixtureParameters.html +81 -0
- data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulFixtureNames.html +87 -0
- data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulMemberNames.html +73 -0
- data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.ImportFixture.html +61 -0
- data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.WaysToSpecifyaFixtureNamespace.html +81 -0
- data/doc/spec/annotation.html +3833 -0
- data/doc/spec/extensions.html +302 -0
- data/doc/spec/fixtures.html +5181 -0
- data/doc/spec/index.html +947 -0
- data/doc/spec/parse.html +3094 -0
- data/lib/eg/all_combinations.rb +44 -0
- data/lib/eg/all_files.rb +94 -0
- data/lib/eg/all_pairs.rb +172 -0
- data/lib/eg/arithmetic_column_fixture.rb +35 -0
- data/lib/eg/arithmetic_fixture.rb +29 -0
- data/lib/eg/binary_chop.rb +100 -0
- data/lib/eg/calculator.rb +69 -0
- data/lib/eg/column_index.rb +85 -0
- data/lib/eg/division.rb +13 -0
- data/lib/eg/echo_args_fixture.rb +9 -0
- data/lib/eg/example_tests.rb +84 -0
- data/lib/eg/music/Music.txt +38 -0
- data/lib/eg/music/browser.rb +60 -0
- data/lib/eg/music/display.rb +24 -0
- data/lib/eg/music/music.rb +67 -0
- data/lib/eg/music/music_library.rb +70 -0
- data/lib/eg/music/music_player.rb +77 -0
- data/lib/eg/music/realtime.rb +39 -0
- data/lib/eg/music/simulator.rb +81 -0
- data/lib/eg/nested/bob.rb +12 -0
- data/lib/eg/nested/bob_the_builder_fixture.rb +11 -0
- data/lib/eg/net/simulator.rb +69 -0
- data/lib/eg/page.rb +91 -0
- data/lib/eg/sqrt.rb +19 -0
- data/lib/fat/annotation_fixture.rb +83 -0
- data/lib/fat/color.rb +45 -0
- data/lib/fat/divide.rb +13 -0
- data/lib/fat/document_parse_fixture.rb +67 -0
- data/lib/fat/equals.rb +59 -0
- data/lib/fat/fixture_name_fixture.rb +67 -0
- data/lib/fat/html_to_text_fixture.rb +20 -0
- data/lib/fat/money.rb +18 -0
- data/lib/fat/output_fixture.rb +32 -0
- data/lib/fat/parse_fixture.rb +92 -0
- data/lib/fat/reference_fixture.rb +31 -0
- data/lib/fat/standard_annotation_fixture.rb +58 -0
- data/lib/fat/string_writer.rb +12 -0
- data/lib/fat/table.rb +23 -0
- data/lib/fat/table_parse_fixture.rb +33 -0
- data/lib/fat/text_to_html_fixture.rb +21 -0
- data/lib/fit/action_fixture.rb +65 -0
- data/lib/fit/column_fixture.rb +104 -0
- data/lib/fit/file_runner.rb +80 -0
- data/lib/fit/fit_protocol.rb +62 -0
- data/lib/fit/fit_server.rb +173 -0
- data/lib/fit/fixture.rb +309 -0
- data/lib/fit/fixture_loader.rb +75 -0
- data/lib/fit/import_fixture.rb +9 -0
- data/lib/fit/parse.rb +206 -0
- data/lib/fit/primitive_fixture.rb +52 -0
- data/lib/fit/row_fixture.rb +188 -0
- data/lib/fit/scientific_double.rb +70 -0
- data/lib/fit/summary.rb +46 -0
- data/lib/fit/timed_action_fixture.rb +35 -0
- data/lib/fit/type_adapter.rb +95 -0
- data/lib/fit/wiki_runner.rb +15 -0
- data/lib/fittask.rb +184 -0
- data/test/all_tests.rb +13 -0
- data/test/file_runner_test.rb +52 -0
- data/test/fit_server_test.rb +214 -0
- data/test/fixture_loader_test.rb +71 -0
- data/test/fixture_test.rb +41 -0
- data/test/fixtures/fail_fixture.rb +9 -0
- data/test/fixtures/pass_fixture.rb +9 -0
- data/test/framework_test.rb +51 -0
- data/test/parse_test.rb +101 -0
- data/test/row_fixture_test.rb +44 -0
- data/test/scientific_double_test.rb +35 -0
- data/test/type_adapter_test.rb +120 -0
- metadata +165 -0
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
require 'fat/string_writer'
|
|
6
|
+
|
|
7
|
+
module Fat
|
|
8
|
+
|
|
9
|
+
class StandardAnnotationFixture < Fit::ColumnFixture
|
|
10
|
+
|
|
11
|
+
attr_accessor :original_html, :annotation, :text
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
super
|
|
15
|
+
@original_html = 'Text'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def output
|
|
19
|
+
parse = Fit::Parse.new @original_html, ['td']
|
|
20
|
+
testbed = Fit::Fixture.new
|
|
21
|
+
case @annotation
|
|
22
|
+
when 'right' then testbed.right(parse)
|
|
23
|
+
when 'wrong' then testbed.wrong(parse, @text)
|
|
24
|
+
when 'error' then testbed.error(parse, @text)
|
|
25
|
+
when 'info' then testbed.info(parse, @text)
|
|
26
|
+
when 'ignore' then testbed.ignore(parse)
|
|
27
|
+
else return "unknown type: #@type"
|
|
28
|
+
end
|
|
29
|
+
generate_output parse
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def do_cell cell, column
|
|
33
|
+
begin
|
|
34
|
+
if column == 4
|
|
35
|
+
cell.body = rendered_output
|
|
36
|
+
else
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
rescue Exception => e
|
|
40
|
+
exception cell, e
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def rendered_output
|
|
45
|
+
'<table border="1"><tr>' + output + '</tr></table>'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Code smell note: copied from Fat::ParseFixture
|
|
49
|
+
def generate_output parse
|
|
50
|
+
result = StringWriter.new
|
|
51
|
+
parse.print result
|
|
52
|
+
result.to_s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private :generate_output
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
|
|
2
|
+
# Released under the terms of the GNU General Public License version 2 or later.
|
|
3
|
+
|
|
4
|
+
module Fat
|
|
5
|
+
|
|
6
|
+
class StringWriter
|
|
7
|
+
def initialize; @s = ''; end
|
|
8
|
+
def print s; @s += s.to_s; end
|
|
9
|
+
def to_s; @s; end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
data/lib/fat/table.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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/fixture'
|
|
5
|
+
require 'fit/parse'
|
|
6
|
+
|
|
7
|
+
module Fat
|
|
8
|
+
|
|
9
|
+
class Table < Fit::Fixture
|
|
10
|
+
@@table = nil
|
|
11
|
+
def Table.table; @@table; end
|
|
12
|
+
def Table.table= table; @@table = table; end
|
|
13
|
+
def do_rows rows
|
|
14
|
+
@@table = Fit::ParseHolder.create('table', nil, Table.copy(rows), nil)
|
|
15
|
+
# evaluate the rest of the table like a runner
|
|
16
|
+
Fit::Fixture.new.do_tables @@table
|
|
17
|
+
end
|
|
18
|
+
def Table.copy tree
|
|
19
|
+
tree.nil? ? nil : Fit::ParseHolder.create(tree.tag, tree.body, Table.copy(tree.parts), Table.copy(tree.more))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -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
|
+
module Fat
|
|
7
|
+
|
|
8
|
+
class TableParseFixture < Fit::ColumnFixture
|
|
9
|
+
attr_accessor :html, :row, :column
|
|
10
|
+
def cell_body
|
|
11
|
+
cell.body
|
|
12
|
+
end
|
|
13
|
+
def cell_tag
|
|
14
|
+
cell.tag
|
|
15
|
+
end
|
|
16
|
+
def row_tag
|
|
17
|
+
row.tag
|
|
18
|
+
end
|
|
19
|
+
def table_tag
|
|
20
|
+
table.tag
|
|
21
|
+
end
|
|
22
|
+
def cell
|
|
23
|
+
row.at 0, @column - 1
|
|
24
|
+
end
|
|
25
|
+
def row
|
|
26
|
+
table.at 0, @row - 1
|
|
27
|
+
end
|
|
28
|
+
def table
|
|
29
|
+
Fit::Parse.new(@html)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
require 'fit/fixture'
|
|
6
|
+
|
|
7
|
+
module Fat
|
|
8
|
+
|
|
9
|
+
class TextToHtmlFixture < Fit::ColumnFixture
|
|
10
|
+
attr_accessor :text
|
|
11
|
+
def html
|
|
12
|
+
@text = unescape_ascii @text
|
|
13
|
+
Fit::Fixture.escape @text
|
|
14
|
+
end
|
|
15
|
+
def unescape_ascii text
|
|
16
|
+
text.gsub(/\\n/, "\n").gsub(/\\r/, "\r")
|
|
17
|
+
end
|
|
18
|
+
private :unescape_ascii
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
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/fixture'
|
|
5
|
+
require 'fit/type_adapter'
|
|
6
|
+
|
|
7
|
+
module Fit
|
|
8
|
+
|
|
9
|
+
class ActionFixture < Fixture
|
|
10
|
+
|
|
11
|
+
attr_reader :cells
|
|
12
|
+
protected :cells
|
|
13
|
+
@@actor = nil
|
|
14
|
+
|
|
15
|
+
def ActionFixture.actor; @@actor; end
|
|
16
|
+
def ActionFixture.actor= value
|
|
17
|
+
@@actor = value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def do_cells cells
|
|
21
|
+
@cells = cells
|
|
22
|
+
begin
|
|
23
|
+
send(cells.text)
|
|
24
|
+
rescue Exception => e
|
|
25
|
+
exception cells, e
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def start
|
|
30
|
+
klass = find_class @cells.more.text # using reflection
|
|
31
|
+
@@actor = klass.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# ActionFixture.enter could be called with regular methods
|
|
35
|
+
# featuring a single argument, or on setters methods of the
|
|
36
|
+
# form 'name=' when an assignment on an attr is tried.
|
|
37
|
+
def enter
|
|
38
|
+
method_name = Fixture.camel @cells.more.text
|
|
39
|
+
parameter = @cells.more.more.text
|
|
40
|
+
adapter = TypeAdapter.for(@@actor, method_name, false)
|
|
41
|
+
adapter.type = @@actor.class.metadata[method_name]
|
|
42
|
+
argument = adapter.parse(parameter)
|
|
43
|
+
m = @@actor.method method_name
|
|
44
|
+
if m.arity == 1
|
|
45
|
+
@@actor.send(method_name, argument)
|
|
46
|
+
else
|
|
47
|
+
adapter.set argument
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def press
|
|
52
|
+
method_name = Fixture.camel @cells.more.text
|
|
53
|
+
@@actor.send method_name
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def check
|
|
57
|
+
method_name = Fixture.camel @cells.more.text
|
|
58
|
+
adapter = TypeAdapter.for(@@actor, method_name, false)
|
|
59
|
+
adapter.type = @@actor.class.metadata[method_name]
|
|
60
|
+
super(@cells.more.more, adapter)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
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/fixture'
|
|
5
|
+
require 'fit/type_adapter'
|
|
6
|
+
|
|
7
|
+
module Fit
|
|
8
|
+
|
|
9
|
+
class ColumnFixture < Fixture
|
|
10
|
+
|
|
11
|
+
attr_accessor :column_bindings, :has_executed
|
|
12
|
+
protected :column_bindings, :column_bindings=, :has_executed, :has_executed=
|
|
13
|
+
|
|
14
|
+
# Traversal
|
|
15
|
+
|
|
16
|
+
def do_rows rows
|
|
17
|
+
bind rows.parts
|
|
18
|
+
super(rows.more)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def do_row row
|
|
22
|
+
@has_executed = false
|
|
23
|
+
begin
|
|
24
|
+
reset
|
|
25
|
+
super
|
|
26
|
+
execute if not @has_executed
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
exception row.leaf, e
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def do_cell cell, column_index
|
|
33
|
+
adapter = @column_bindings[column_index]
|
|
34
|
+
begin
|
|
35
|
+
text = cell.text
|
|
36
|
+
if text.empty?
|
|
37
|
+
check cell, adapter
|
|
38
|
+
elsif adapter.nil?
|
|
39
|
+
ignore cell
|
|
40
|
+
elsif adapter.is_output?
|
|
41
|
+
check cell, adapter
|
|
42
|
+
else
|
|
43
|
+
adapter.set(adapter.parse(text))
|
|
44
|
+
end
|
|
45
|
+
rescue Exception => e
|
|
46
|
+
exception cell, e
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def check cell, adapter
|
|
51
|
+
unless @has_executed
|
|
52
|
+
begin
|
|
53
|
+
execute
|
|
54
|
+
rescue Exception => e
|
|
55
|
+
exception cell, e
|
|
56
|
+
end
|
|
57
|
+
@has_executed = true
|
|
58
|
+
end
|
|
59
|
+
super
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def reset
|
|
63
|
+
# about to process first cell of row
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def execute
|
|
67
|
+
# about to process first method call of row
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Utility
|
|
71
|
+
|
|
72
|
+
protected
|
|
73
|
+
|
|
74
|
+
def bind heads
|
|
75
|
+
@column_bindings = []
|
|
76
|
+
until heads.nil?
|
|
77
|
+
name = heads.text
|
|
78
|
+
begin
|
|
79
|
+
if name.empty?
|
|
80
|
+
@column_bindings << nil
|
|
81
|
+
else
|
|
82
|
+
suffix = ''
|
|
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
|
|
89
|
+
adapter = TypeAdapter.for(self, name)
|
|
90
|
+
adapter.type = get_target_class.metadata[name]
|
|
91
|
+
@column_bindings << adapter
|
|
92
|
+
end
|
|
93
|
+
rescue Exception => e
|
|
94
|
+
exception heads, e
|
|
95
|
+
end
|
|
96
|
+
heads = heads.more
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def get_target_class; self.class; end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
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/fixture'
|
|
5
|
+
require 'fit/parse'
|
|
6
|
+
|
|
7
|
+
require 'fileutils' # for report generation
|
|
8
|
+
|
|
9
|
+
module Fit
|
|
10
|
+
|
|
11
|
+
class FileRunner
|
|
12
|
+
attr_accessor :input, :tables, :fixture, :output
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@fixture = Fixture.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run args
|
|
19
|
+
process_args args
|
|
20
|
+
process
|
|
21
|
+
$stderr.puts @fixture.totals
|
|
22
|
+
exit @fixture.total_errors
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def process_args args
|
|
26
|
+
error "Usage: #{File.basename($0)} input_file output_file" unless args.size == 2
|
|
27
|
+
|
|
28
|
+
input_name = File.expand_path args[0]
|
|
29
|
+
input_file = File.open input_name
|
|
30
|
+
output_name = File.expand_path args[1]
|
|
31
|
+
FileUtils.mkpath File.dirname(output_name)
|
|
32
|
+
@output = File.open output_name, 'w'
|
|
33
|
+
@fixture.summary['input file'] = input_name
|
|
34
|
+
@fixture.summary['input update'] = input_file.mtime.to_s
|
|
35
|
+
@fixture.summary['output file'] = output_name
|
|
36
|
+
@input = input_file.read
|
|
37
|
+
input_file.close
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def process
|
|
41
|
+
begin
|
|
42
|
+
unless @input.index('<wiki>').nil?
|
|
43
|
+
@tables = Parse.new @input, ['wiki', 'table', 'tr', 'td']
|
|
44
|
+
@fixture.do_tables @tables.parts
|
|
45
|
+
else
|
|
46
|
+
@tables = Parse.new @input, ['table', 'tr', 'td']
|
|
47
|
+
@fixture.do_tables @tables
|
|
48
|
+
end
|
|
49
|
+
rescue Exception => e
|
|
50
|
+
exception e
|
|
51
|
+
end
|
|
52
|
+
@tables.print @output
|
|
53
|
+
@output.close
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def exception e
|
|
57
|
+
@tables = ParseHolder.create 'body', 'Unable to parse input. Input ignored.', nil, nil
|
|
58
|
+
@fixture.exception @tables, e
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def error msg
|
|
62
|
+
$stderr.puts msg
|
|
63
|
+
exit -1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
protected :exception, :error
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The main loop of the program
|
|
73
|
+
# if __FILE__ == $0
|
|
74
|
+
# begin
|
|
75
|
+
# Fit::FileRunner.new.run ARGV
|
|
76
|
+
# rescue Exception => e
|
|
77
|
+
# $stderr.puts e.message
|
|
78
|
+
# exit -1
|
|
79
|
+
# end
|
|
80
|
+
# end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'fit/fixture'
|
|
2
|
+
|
|
3
|
+
module Fit
|
|
4
|
+
|
|
5
|
+
class FitProtocol
|
|
6
|
+
|
|
7
|
+
def FitProtocol.read_size(input)
|
|
8
|
+
str_value = read(10, input)
|
|
9
|
+
return str_value.to_i
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def FitProtocol.read(bytes, input)
|
|
13
|
+
value = input.read(bytes)
|
|
14
|
+
return value
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def FitProtocol.read_document(input)
|
|
18
|
+
byte_count = read_size(input)
|
|
19
|
+
return read(byte_count, input)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def FitProtocol.read_counts(input)
|
|
23
|
+
counts = Counts.new
|
|
24
|
+
counts.right = FitProtocol.read_size(input)
|
|
25
|
+
counts.wrong = FitProtocol.read_size(input)
|
|
26
|
+
counts.ignores = FitProtocol.read_size(input)
|
|
27
|
+
counts.exceptions = FitProtocol.read_size(input)
|
|
28
|
+
return counts
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def FitProtocol.write_size(size, output)
|
|
32
|
+
formatted_size = FitProtocol.format_number(size)
|
|
33
|
+
output.write(formatted_size)
|
|
34
|
+
output.flush
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def FitProtocol.write_document(document, output)
|
|
38
|
+
FitProtocol.write_size(document.size, output)
|
|
39
|
+
output.write(document)
|
|
40
|
+
output.flush
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def FitProtocol.write_counts(counts, output)
|
|
44
|
+
FitProtocol.write_size(0, output)
|
|
45
|
+
FitProtocol.write_size(counts.right, output)
|
|
46
|
+
FitProtocol.write_size(counts.wrong, output)
|
|
47
|
+
FitProtocol.write_size(counts.ignores, output)
|
|
48
|
+
FitProtocol.write_size(counts.exceptions, output)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def FitProtocol.format_number(size)
|
|
52
|
+
number_of_zeros = 10 - size.to_s.size
|
|
53
|
+
formatted_value = ""
|
|
54
|
+
number_of_zeros.times do
|
|
55
|
+
formatted_value << '0'
|
|
56
|
+
end
|
|
57
|
+
formatted_value << size.to_s
|
|
58
|
+
return formatted_value
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Written by Object Mentor, Inc. 2005
|
|
2
|
+
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
|
|
3
|
+
# Released under the terms of the GNU General Public License version 2 or later.
|
|
4
|
+
|
|
5
|
+
require 'fit/fixture'
|
|
6
|
+
require 'fit/parse'
|
|
7
|
+
require 'fit/fit_protocol'
|
|
8
|
+
require 'socket'
|
|
9
|
+
|
|
10
|
+
module Fit
|
|
11
|
+
|
|
12
|
+
class FitServer
|
|
13
|
+
|
|
14
|
+
attr_accessor :host, :port, :test_ticket, :verbose
|
|
15
|
+
attr_reader :reason_for_bad_connection, :counts
|
|
16
|
+
|
|
17
|
+
def run(args)
|
|
18
|
+
if args(args)
|
|
19
|
+
connected = establish_connection
|
|
20
|
+
if not connected
|
|
21
|
+
puts "Could not connect. " + @reason_for_bad_connection
|
|
22
|
+
return -1
|
|
23
|
+
else
|
|
24
|
+
process
|
|
25
|
+
close_connection
|
|
26
|
+
finish
|
|
27
|
+
return exit_code
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
usage
|
|
31
|
+
return -1
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def args(arg_list)
|
|
36
|
+
begin
|
|
37
|
+
arg_count = arg_list.size
|
|
38
|
+
if arg_count == 4 and arg_list.shift == '-v'
|
|
39
|
+
@verbose = true
|
|
40
|
+
elsif arg_count != 3
|
|
41
|
+
return false
|
|
42
|
+
end
|
|
43
|
+
@host = arg_list.shift
|
|
44
|
+
@port = arg_list.shift.to_i
|
|
45
|
+
return false if @port.zero?;
|
|
46
|
+
@test_ticket = arg_list.shift
|
|
47
|
+
return true
|
|
48
|
+
rescue => exception
|
|
49
|
+
return false
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def usage
|
|
54
|
+
puts "Usage: ruby FitServer.rb [options] <host> <port> <test_ticket>"
|
|
55
|
+
puts " -v: verbose"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def build_request
|
|
59
|
+
return "GET /?responder=socketCatcher&ticket=" + @test_ticket + " HTTP/1.1\r\n\r\n"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def close_connection
|
|
63
|
+
@socket.close
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def establish_connection
|
|
67
|
+
say "Connecting to " + @host.to_s + ":" + @port.to_s
|
|
68
|
+
@socket = TCPSocket.new(@host, @port)
|
|
69
|
+
@socket.print(build_request)
|
|
70
|
+
@socket.flush
|
|
71
|
+
status = FitProtocol.read_size(@socket)
|
|
72
|
+
unless status.zero?
|
|
73
|
+
@reason_for_bad_connection = FitProtocol.read(status, @socket)
|
|
74
|
+
say "\t> failed to connect: " + @reason_for_bad_connection
|
|
75
|
+
return false
|
|
76
|
+
else
|
|
77
|
+
say "\t> connected"
|
|
78
|
+
return true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def process
|
|
83
|
+
@fixture_listener = TablePrintingFixtureListener.new(@socket)
|
|
84
|
+
@counts = Counts.new
|
|
85
|
+
document_size = 0
|
|
86
|
+
begin
|
|
87
|
+
while ((document_size = FitProtocol.read_size(@socket)) != 0)
|
|
88
|
+
begin
|
|
89
|
+
say "Processing document with " + document_size.to_s + " bytes"
|
|
90
|
+
document = FitProtocol.read(document_size, @socket)
|
|
91
|
+
tables = Parse.new(document, ['table', 'tr', 'td'])
|
|
92
|
+
new_fixture
|
|
93
|
+
@fixture.do_tables(tables)
|
|
94
|
+
say "\t> " + @fixture.counts.to_s
|
|
95
|
+
@counts.tally(@fixture.counts)
|
|
96
|
+
rescue Fit::ParseException => e
|
|
97
|
+
exception(e)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
rescue => e
|
|
101
|
+
exception(e)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def new_fixture
|
|
106
|
+
@fixture = Fixture.new
|
|
107
|
+
@fixture.listener = @fixture_listener
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def good_connection?
|
|
111
|
+
return reason_for_bad_connection.nil?
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def finish
|
|
115
|
+
say "Final counts: " + @counts.to_s
|
|
116
|
+
say "Exiting with code " + exit_code().to_s
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def exit_code()
|
|
120
|
+
return @counts.wrong + @counts.exceptions
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def say(message)
|
|
124
|
+
puts message if @verbose
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def exception(e)
|
|
128
|
+
say "Exception occured!"
|
|
129
|
+
say "\t> " + e.to_s
|
|
130
|
+
parse = ParseHolder.create("span", "Exception occurred: ", nil, nil)
|
|
131
|
+
if @fixture.nil?
|
|
132
|
+
new_fixture
|
|
133
|
+
end
|
|
134
|
+
@fixture.exception(parse, e)
|
|
135
|
+
@counts.exceptions = @counts.exceptions + 1
|
|
136
|
+
@fixture_listener.table_finished(parse)
|
|
137
|
+
@fixture_listener.tables_finished(@fixture.counts)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
class PrintString
|
|
143
|
+
def initialize; @buffer = ''; end
|
|
144
|
+
def print text; @buffer += text; end
|
|
145
|
+
def to_s; @buffer; end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class TablePrintingFixtureListener
|
|
149
|
+
def initialize(socket)
|
|
150
|
+
@socket = socket
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def table_finished(tableParse)
|
|
154
|
+
buffer = PrintString.new
|
|
155
|
+
print_table(tableParse, buffer)
|
|
156
|
+
FitProtocol.write_document(buffer.to_s, @socket)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def print_table(table, output)
|
|
160
|
+
more = table.more
|
|
161
|
+
table.more = nil
|
|
162
|
+
if table.trailer.nil?
|
|
163
|
+
table.trailer = ""
|
|
164
|
+
end
|
|
165
|
+
table.print(output)
|
|
166
|
+
table.more = more
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def tables_finished(counts)
|
|
170
|
+
FitProtocol.write_counts(counts, @socket)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|