linkparser 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/rake/testing.rb ADDED
@@ -0,0 +1,202 @@
1
+ #
2
+ # Rake tasklib for testing tasks
3
+ # $Id: testing.rb 80 2008-12-20 19:50:19Z deveiant $
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+
9
+ unless defined?( COVERAGE_MINIMUM )
10
+ if ENV['COVVERAGE_MINIMUM']
11
+ COVERAGE_MINIMUM = Float( ENV['COVERAGE_MINIMUM'] )
12
+ else
13
+ COVERAGE_MINIMUM = 85.0
14
+ end
15
+ end
16
+ SPEC_FILES = [] unless defined?( SPEC_FILES )
17
+ TEST_FILES = [] unless defined?( TEST_FILES )
18
+
19
+ COMMON_SPEC_OPTS = ['-Du', '-b'] unless defined?( COMMON_SPEC_OPTS )
20
+
21
+ COVERAGE_TARGETDIR = BASEDIR + 'coverage' unless defined?( COVERAGE_TARGETDIR )
22
+ RCOV_EXCLUDES = 'spec,tests,/Library/Ruby,/var/lib,/usr/local/lib' unless
23
+ defined?( RCOV_EXCLUDES )
24
+
25
+
26
+ desc "Run all defined tests"
27
+ task :test do
28
+ unless SPEC_FILES.empty?
29
+ log "Running specs"
30
+ Rake::Task['spec:quiet'].invoke
31
+ end
32
+
33
+ unless TEST_FILES.empty?
34
+ log "Running unit tests"
35
+ Rake::Task[:unittests].invoke
36
+ end
37
+ end
38
+
39
+
40
+ ### RSpec specifications
41
+ begin
42
+ gem 'rspec', '>= 1.1.3'
43
+
44
+ require 'spec'
45
+ require 'spec/rake/spectask'
46
+
47
+ ### Task: spec
48
+ task :spec => 'spec:doc'
49
+
50
+ namespace :spec do
51
+ desc "Run rspec every time there's a change to one of the files"
52
+ task :autotest do
53
+ require 'autotest/rspec'
54
+
55
+ autotester = Autotest::Rspec.new
56
+ autotester.run
57
+ end
58
+
59
+ desc "Generate regular color 'doc' spec output"
60
+ Spec::Rake::SpecTask.new( :doc ) do |task|
61
+ task.spec_files = SPEC_FILES
62
+ task.spec_opts = COMMON_SPEC_OPTS + ['-f', 's', '-c']
63
+ end
64
+
65
+ desc "Generate spec output with profiling"
66
+ Spec::Rake::SpecTask.new( :profile ) do |task|
67
+ task.spec_files = SPEC_FILES
68
+ task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'o']
69
+ end
70
+
71
+ desc "Generate quiet non-colored plain-text output"
72
+ Spec::Rake::SpecTask.new( :quiet ) do |task|
73
+ task.spec_files = SPEC_FILES
74
+ task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'p']
75
+ end
76
+
77
+ desc "Generate HTML output"
78
+ Spec::Rake::SpecTask.new( :html ) do |task|
79
+ task.spec_files = SPEC_FILES
80
+ task.spec_opts = COMMON_SPEC_OPTS + ['-f', 'h']
81
+ end
82
+
83
+ end
84
+ rescue LoadError => err
85
+ task :no_rspec do
86
+ $stderr.puts "Specification tasks not defined: %s" % [ err.message ]
87
+ end
88
+
89
+ task :spec => :no_rspec
90
+ namespace :spec do
91
+ task :autotest => :no_rspec
92
+ task :doc => :no_rspec
93
+ task :profile => :no_rspec
94
+ task :quiet => :no_rspec
95
+ task :html => :no_rspec
96
+ end
97
+ end
98
+
99
+
100
+ ### Test::Unit tests
101
+ begin
102
+ require 'rake/testtask'
103
+
104
+ Rake::TestTask.new( :unittests ) do |task|
105
+ task.libs += [LIBDIR]
106
+ task.test_files = TEST_FILES
107
+ task.verbose = true
108
+ end
109
+
110
+ rescue LoadError => err
111
+ task :no_test do
112
+ $stderr.puts "Test tasks not defined: %s" % [ err.message ]
113
+ end
114
+
115
+ task :unittests => :no_rspec
116
+ end
117
+
118
+
119
+ ### RCov (via RSpec) tasks
120
+ begin
121
+ gem 'rcov'
122
+ gem 'rspec', '>= 1.1.3'
123
+
124
+ require 'spec'
125
+ require 'rcov'
126
+
127
+ ### Task: coverage (via RCov)
128
+ desc "Build test coverage reports"
129
+ unless SPEC_FILES.empty?
130
+ Spec::Rake::SpecTask.new( :coverage ) do |task|
131
+ task.spec_files = SPEC_FILES
132
+ task.libs += [LIBDIR]
133
+ task.spec_opts = ['-f', 'p', '-b']
134
+ task.rcov_opts = RCOV_OPTS
135
+ task.rcov = true
136
+ end
137
+ end
138
+ # unless TEST_FILES.empty?
139
+ # require 'rcov/rcovtask'
140
+
141
+ # Rcov::RcovTask.new do |task|
142
+ # task.libs += [LIBDIR]
143
+ # task.test_files = TEST_FILES
144
+ # task.verbose = true
145
+ # task.rcov_opts = RCOV_OPTS
146
+ # end
147
+ # end
148
+
149
+
150
+ ### Task: rcov
151
+ task :rcov => :coverage
152
+
153
+ ### Other coverage tasks
154
+ namespace :coverage do
155
+ desc "Generate a detailed text coverage report"
156
+ Spec::Rake::SpecTask.new( :text ) do |task|
157
+ task.spec_files = SPEC_FILES
158
+ task.rcov_opts = RCOV_OPTS + ['--text-report']
159
+ task.rcov = true
160
+ end
161
+
162
+ desc "Show differences in coverage from last run"
163
+ Spec::Rake::SpecTask.new( :diff ) do |task|
164
+ task.spec_files = SPEC_FILES
165
+ task.spec_opts = ['-f', 'p', '-b']
166
+ task.rcov_opts = RCOV_OPTS - ['--save'] + ['--text-coverage-diff']
167
+ task.rcov = true
168
+ end
169
+
170
+ ### Task: verify coverage
171
+ desc "Build coverage statistics"
172
+ VerifyTask.new( :verify => :rcov ) do |task|
173
+ task.threshold = COVERAGE_MINIMUM
174
+ end
175
+
176
+ desc "Run RCov in 'spec-only' mode to check coverage from specs"
177
+ Spec::Rake::SpecTask.new( :speconly ) do |task|
178
+ task.spec_files = SPEC_FILES
179
+ task.rcov_opts = ['--exclude', RCOV_EXCLUDES, '--text-report', '--save']
180
+ task.rcov = true
181
+ end
182
+ end
183
+
184
+ CLOBBER.include( COVERAGE_TARGETDIR )
185
+
186
+ rescue LoadError => err
187
+ task :no_rcov do
188
+ $stderr.puts "Coverage tasks not defined: RSpec+RCov tasklib not available: %s" %
189
+ [ err.message ]
190
+ end
191
+
192
+ task :coverage => :no_rcov
193
+ task :clobber_coverage
194
+ task :rcov => :no_rcov
195
+ namespace :coverage do
196
+ task :text => :no_rcov
197
+ task :diff => :no_rcov
198
+ end
199
+ task :verify => :no_rcov
200
+ end
201
+
202
+
@@ -0,0 +1,64 @@
1
+ #####################################################################
2
+ ### S U B V E R S I O N T A S K S A N D H E L P E R S
3
+ #####################################################################
4
+
5
+ require 'rake/tasklib'
6
+
7
+ #
8
+ # Work around the inexplicable behaviour of the original RDoc::VerifyTask, which
9
+ # errors if your coverage isn't *exactly* the threshold.
10
+ #
11
+
12
+ # A task that can verify that the RCov coverage doesn't
13
+ # drop below a certain threshold. It should be run after
14
+ # running Spec::Rake::SpecTask.
15
+ class VerifyTask < Rake::TaskLib
16
+
17
+ COVERAGE_PERCENTAGE_PATTERN =
18
+ %r{<tt class='coverage_code'>(\d+\.\d+)%</tt>}
19
+
20
+ # Name of the task. Defaults to :verify_rcov
21
+ attr_accessor :name
22
+
23
+ # Path to the index.html file generated by RCov, which
24
+ # is the file containing the total coverage.
25
+ # Defaults to 'coverage/index.html'
26
+ attr_accessor :index_html
27
+
28
+ # Whether or not to output details. Defaults to true.
29
+ attr_accessor :verbose
30
+
31
+ # The threshold value (in percent) for coverage. If the
32
+ # actual coverage is not equal to this value, the task will raise an
33
+ # exception.
34
+ attr_accessor :threshold
35
+
36
+ def initialize( name=:verify )
37
+ @name = name
38
+ @index_html = 'coverage/index.html'
39
+ @verbose = true
40
+ yield self if block_given?
41
+ raise "Threshold must be set" if @threshold.nil?
42
+ define
43
+ end
44
+
45
+ def define
46
+ desc "Verify that rcov coverage is at least #{threshold}%"
47
+
48
+ task @name do
49
+ total_coverage = nil
50
+ if match = File.read( index_html ).match( COVERAGE_PERCENTAGE_PATTERN )
51
+ total_coverage = Float( match[1] )
52
+ else
53
+ raise "Couldn't find the coverage percentage in #{index_html}"
54
+ end
55
+
56
+ puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
57
+ if total_coverage < threshold
58
+ raise "Coverage must be at least #{threshold}% but was #{total_coverage}%"
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # vim: set nosta noet ts=4 sw=4:
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # Specification for various bugfixes to the LinkParser binding
4
+ # $Id: bugfixes_spec.rb 48 2008-12-19 18:30:33Z deveiant $
5
+ #
6
+ # See the LICENSE file in the distribution for information about copyright and licensing.
7
+ #
8
+
9
+ BEGIN {
10
+ require 'pathname'
11
+ basedir = Pathname.new( __FILE__ ).dirname.parent
12
+
13
+ libdir = basedir + 'lib'
14
+ extdir = basedir + 'ext'
15
+
16
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
17
+ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s )
18
+ }
19
+
20
+ require 'spec/runner'
21
+ require 'linkparser'
22
+
23
+ # @dict = LinkParser::Dictionary.new( :verbosity => 0 )
24
+ # s = LinkParser::Sentence.new('The cat runs.',@dict)
25
+ # puts s.linkages.first.verb # "cat.n" !?!?!
26
+ describe %{bugfix for #3: The first linkage for "The cat runs."} do
27
+ before( :each ) do
28
+ @dict = LinkParser::Dictionary.new( :verbosity => 0 )
29
+ @sentence = @dict.parse( "The cat runs." )
30
+ @linkage = @sentence.linkages.first
31
+ end
32
+
33
+
34
+ it "thinks cat is the subject" do
35
+ @linkage.subject.should == "cat"
36
+ end
37
+
38
+ it "thinks runs is the verb" do
39
+ @linkage.verb.should == "runs"
40
+ end
41
+ end
42
+
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # Specification for the LinkParser::Dictionary class
4
+ # $Id: dictionary_spec.rb 48 2008-12-19 18:30:33Z deveiant $
5
+ #
6
+ # See the LICENSE file in the distribution for information about copyright and licensing.
7
+ #
8
+
9
+ BEGIN {
10
+ require 'pathname'
11
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent
12
+
13
+ libdir = basedir + 'lib'
14
+ extdir = basedir + 'ext'
15
+
16
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
17
+ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s )
18
+ }
19
+
20
+ require 'spec/runner'
21
+ require 'linkparser'
22
+
23
+
24
+ describe LinkParser::Dictionary do
25
+ it "can be instantiated using all default values" do
26
+ lambda { LinkParser::Dictionary.new }.should_not raise_error()
27
+ end
28
+
29
+ it "can be instantiated with an options hash" do
30
+ LinkParser::Dictionary.new( :verbosity => 2 ).options[:verbosity].should == 2
31
+ end
32
+
33
+ it "raises an error when created with an bad number of arguments" do
34
+ lambda {
35
+ LinkParser::Dictionary.new( "foo", "bar", "baz" )
36
+ }.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it "can be instantiated with a language argument" do
40
+ lambda {LinkParser::Dictionary.new( 'en' )}.should_not raise_error()
41
+ end
42
+
43
+ it "can be instantiated with both a language and an options hash" do
44
+ LinkParser::Dictionary.new('en', :verbosity => 2).options[:verbosity].should == 2
45
+ end
46
+
47
+ it "raises an exception if created with unknown dictionaries" do
48
+ lambda {
49
+ LinkParser::Dictionary.new('foo', 'bar', 'baz', 'bim')
50
+ }.should raise_error( LinkParser::Error )
51
+ end
52
+
53
+ it "raises an exception if created with an unknown language" do
54
+ lambda {
55
+ LinkParser::Dictionary.new('zz')
56
+ }.should raise_error( LinkParser::Error )
57
+ end
58
+
59
+ end
60
+
61
+ describe "An instance of LinkParser::Dictionary" do
62
+
63
+ TEST_SENTENCE = "The dog plays with the ball."
64
+
65
+ before( :each ) do
66
+ @dict = LinkParser::Dictionary.new(
67
+ :verbosity => 0,
68
+ :max_null_count => 18,
69
+ :echo_on => true
70
+ )
71
+ end
72
+
73
+
74
+ it "knows what the total cost of its linkages are" do
75
+ @dict.max_cost.should be_an_instance_of(Fixnum)
76
+ end
77
+
78
+ it "can parse a sentence" do
79
+ @dict.parse( TEST_SENTENCE ).
80
+ should be_an_instance_of( LinkParser::Sentence )
81
+ end
82
+
83
+ it "passes on its options to the sentences it parses" do
84
+ sentence = @dict.parse( TEST_SENTENCE )
85
+ sentence.options.max_null_count.should == 18
86
+ sentence.options.verbosity.should == 0
87
+ sentence.options.echo_on?.should == true
88
+ end
89
+ end
90
+
@@ -0,0 +1,434 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # Specification for the LinkParser::Linkage class
4
+ # $Id: linkage_spec.rb 48 2008-12-19 18:30:33Z deveiant $
5
+ #
6
+ # See the LICENSE file in the distribution for information about copyright and licensing.
7
+ #
8
+
9
+ BEGIN {
10
+ require 'pathname'
11
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent
12
+
13
+ libdir = basedir + 'lib'
14
+ extdir = basedir + 'ext'
15
+
16
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
17
+ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s )
18
+ }
19
+
20
+ require 'spec/runner'
21
+ require 'linkparser'
22
+
23
+
24
+ describe LinkParser::Linkage do
25
+
26
+ before( :all ) do
27
+ @dict = LinkParser::Dictionary.new( :verbosity => 0 )
28
+ end
29
+
30
+ before( :each ) do
31
+ @sentence = @dict.parse( "The flag was wet." )
32
+ @linkage = @sentence.linkages.first
33
+ end
34
+
35
+
36
+ # +-------------Xp-------------+
37
+ # +-----Wd-----+ |
38
+ # | +--Ds-+--Ss-+--Pa-+ |
39
+ # | | | | | |
40
+ # LEFT-WALL the flag.n was.v wet.a .
41
+ it "can build a diagram string for a sentence" do
42
+ @linkage.diagram.should =~ /LEFT-WALL/
43
+ @linkage.diagram.should =~ /the/
44
+ @linkage.diagram.should =~ /flag\.n/
45
+ @linkage.diagram.should =~ /was\.v/
46
+ @linkage.diagram.should =~ /wet\.a/
47
+
48
+ @linkage.diagram.should =~ /-Xp-/
49
+ @linkage.diagram.should =~ /-Wd-/
50
+ @linkage.diagram.should =~ /-Ds-/
51
+ @linkage.diagram.should =~ /-Ss-/
52
+ @linkage.diagram.should =~ /-Pa-/
53
+ end
54
+
55
+
56
+ # LEFT-WALL Xp <---Xp----> Xp .
57
+ # (m) LEFT-WALL Wd <---Wd----> Wd flag.n
58
+ # (m) the D <---Ds----> Ds flag.n
59
+ # (m) flag.n Ss <---Ss----> Ss was.v
60
+ # (m) was.v Pa <---Pa----> Pa wet.a
61
+ # . RW <---RW----> RW RIGHT-WALL
62
+ it "can build a 'links and domains' diagram" do
63
+ @linkage.links_and_domains.should =~ /LEFT-WALL/
64
+ @linkage.links_and_domains.should =~ /the/
65
+ @linkage.links_and_domains.should =~ /flag\.n/
66
+ @linkage.links_and_domains.should =~ /was\.v/
67
+ @linkage.links_and_domains.should =~ /wet\.a/
68
+
69
+ @linkage.links_and_domains.should =~ /-Xp-/
70
+ @linkage.links_and_domains.should =~ /-Wd-/
71
+ @linkage.links_and_domains.should =~ /-Ds-/
72
+ @linkage.links_and_domains.should =~ /-Ss-/
73
+ @linkage.links_and_domains.should =~ /-Pa-/
74
+ end
75
+
76
+
77
+ it "knows how many words are in the sentence" do
78
+ # LEFT-WALL + words + '.' + RIGHT-WALL = 7
79
+ @linkage.num_words.should == 7
80
+ end
81
+
82
+
83
+ it "can return a list of the tokenized words" do
84
+ @linkage.words.should include("LEFT-WALL")
85
+ @linkage.words.should include("the")
86
+ @linkage.words.should include("flag.n")
87
+ @linkage.words.should include("was.v")
88
+ @linkage.words.should include("wet.a")
89
+ @linkage.words.should include(".")
90
+ @linkage.words.should include("RIGHT-WALL")
91
+ end
92
+
93
+
94
+ it "knows how many links are in the sentence" do
95
+ @linkage.num_links.should == 6
96
+ end
97
+
98
+
99
+ it "can return the left word for any of its links" do
100
+ # LEFT-WALL Xp <---Xp----> Xp .
101
+ @linkage.link_lword( 0 ).should == @linkage.words.index('LEFT-WALL')
102
+
103
+ # (m) LEFT-WALL Wd <---Wd----> Wd flag.n
104
+ @linkage.link_lword( 1 ).should == @linkage.words.index('LEFT-WALL')
105
+
106
+ # (m) the D <---Ds----> Ds flag.n
107
+ @linkage.link_lword( 2 ).should == @linkage.words.index('the')
108
+
109
+ # (m) flag.n Ss <---Ss----> Ss was.v
110
+ @linkage.link_lword( 3 ).should == @linkage.words.index('flag.n')
111
+
112
+ # (m) was.v Pa <---Pa----> Pa wet.a
113
+ @linkage.link_lword( 4 ).should == @linkage.words.index('was.v')
114
+
115
+ # . RW <---RW----> RW RIGHT-WALL
116
+ @linkage.link_lword( 5 ).should == @linkage.words.index('.')
117
+
118
+ end
119
+
120
+ it "can return the right word for any of its links" do
121
+ # LEFT-WALL Xp <---Xp----> Xp .
122
+ @linkage.link_rword( 0 ).should == @linkage.words.index('.')
123
+
124
+ # (m) LEFT-WALL Wd <---Wd----> Wd flag.n
125
+ @linkage.link_rword( 1 ).should == @linkage.words.index('flag.n')
126
+
127
+ # (m) the D <---Ds----> Ds flag.n
128
+ @linkage.link_rword( 2 ).should == @linkage.words.index('flag.n')
129
+
130
+ # (m) flag.n Ss <---Ss----> Ss was.v
131
+ @linkage.link_rword( 3 ).should == @linkage.words.index('was.v')
132
+
133
+ # (m) was.v Pa <---Pa----> Pa wet.a
134
+ @linkage.link_rword( 4 ).should == @linkage.words.index('wet.a')
135
+
136
+ # . RW <---RW----> RW RIGHT-WALL
137
+ @linkage.link_rword( 5 ).should == @linkage.words.index('RIGHT-WALL')
138
+
139
+ end
140
+
141
+
142
+ it "can return the length of any of its links" do
143
+ @linkage.link_length( 0 ).should == 5
144
+ @linkage.link_length( 1 ).should == 2
145
+ @linkage.link_length( 2 ).should == 1
146
+ @linkage.link_length( 3 ).should == 1
147
+ @linkage.link_length( 4 ).should == 1
148
+ @linkage.link_length( 5 ).should == 1
149
+
150
+ # Out-of-bounds just returns -1
151
+ @linkage.link_length( 7 ).should == -1
152
+ end
153
+
154
+
155
+ it "can return labels for any of its links" do
156
+ @linkage.link_label( 0 ).should == "Xp"
157
+ @linkage.link_label( 1 ).should == "Wd"
158
+ @linkage.link_label( 2 ).should == "Ds"
159
+ @linkage.link_label( 3 ).should == "Ss"
160
+ @linkage.link_label( 4 ).should == "Pa"
161
+ @linkage.link_label( 5 ).should == "RW"
162
+
163
+ @linkage.link_label( 7 ).should be_nil
164
+ end
165
+
166
+
167
+ it "can return left labels for any of its links" do
168
+ @linkage.link_llabel( 0 ).should == "Xp"
169
+ @linkage.link_llabel( 1 ).should == "Wd"
170
+ @linkage.link_llabel( 2 ).should == "D"
171
+ @linkage.link_llabel( 3 ).should == "Ss"
172
+ @linkage.link_llabel( 4 ).should == "Pa"
173
+ @linkage.link_llabel( 5 ).should == "RW"
174
+
175
+ @linkage.link_llabel( 7 ).should be_nil
176
+ end
177
+
178
+
179
+ it "can return labels for any of its links" do
180
+ @linkage.link_rlabel( 0 ).should == "Xp"
181
+ @linkage.link_rlabel( 1 ).should == "Wd"
182
+ @linkage.link_rlabel( 2 ).should == "Ds"
183
+ @linkage.link_rlabel( 3 ).should == "Ss"
184
+ @linkage.link_rlabel( 4 ).should == "Pa"
185
+ @linkage.link_rlabel( 5 ).should == "RW"
186
+
187
+ @linkage.link_rlabel( 7 ).should be_nil
188
+ end
189
+
190
+
191
+ it "can return the number of domains for any link" do
192
+ @linkage.link_num_domains( 0 ).should == 0
193
+ 1.upto(4) do |i|
194
+ @linkage.link_num_domains( i ).should == 1
195
+ end
196
+ @linkage.link_num_domains( 5 ).should == 0
197
+
198
+ @linkage.link_num_domains( 112 ).should == -1
199
+ end
200
+
201
+
202
+ it "can return the names of the domains of any of its links" do
203
+ @linkage.link_domain_names( 0 ).should be_an_instance_of( Array )
204
+ @linkage.link_domain_names( 0 ).should be_empty
205
+
206
+ 1.upto(4) do |i|
207
+ @linkage.link_domain_names( i ).should be_an_instance_of( Array )
208
+ @linkage.link_domain_names( i ).should == ["m"]
209
+ end
210
+
211
+ @linkage.link_domain_names( 5 ).should be_an_instance_of( Array )
212
+ @linkage.link_domain_names( 5 ).should be_empty
213
+
214
+ @linkage.link_domain_names( 12 ).should be_an_instance_of( Array )
215
+ @linkage.link_domain_names( 12 ).should be_empty
216
+ end
217
+
218
+
219
+ it "can report on the various cost metrics of the parse" do
220
+ @linkage.unused_word_cost.should be_an_instance_of( Fixnum )
221
+ @linkage.disjunct_cost.should be_an_instance_of( Fixnum )
222
+ @linkage.and_cost.should be_an_instance_of( Fixnum )
223
+ @linkage.link_cost.should be_an_instance_of( Fixnum )
224
+ end
225
+
226
+
227
+ ### :FIXME: I don't know what these do/mean yet, so for now just test to
228
+ ### make sure they're implemented. They should really be tested with
229
+ ### sentences that have predictable results.
230
+ it "implements Link Grammar predicate methods" do
231
+ @linkage.should respond_to( :canonical? )
232
+ @linkage.should respond_to( :improper? )
233
+ @linkage.should respond_to( :has_inconsistent_domains? )
234
+ @linkage.should respond_to( :violation_name )
235
+ end
236
+
237
+
238
+ # LEFT-WALL Xp <---Xp----> Xp .
239
+ # (m) LEFT-WALL Wd <---Wd----> Wd flag.n
240
+ # (m) the D <---Ds----> Ds flag.n
241
+ # (m) flag.n Ss <---Ss----> Ss was.v
242
+ # (m) was.v Pa <---Pa----> Pa wet.a
243
+ # . RW <---RW----> RW RIGHT-WALL
244
+ it "contains link structs describing the linkage" do
245
+ @linkage.should have(6).links
246
+ @linkage.links.should be_an_instance_of( Array )
247
+
248
+ @linkage.links.each do |link|
249
+ link.should be_a_kind_of( Struct )
250
+ end
251
+
252
+ @linkage.links.first.lword.should == 'LEFT-WALL'
253
+ @linkage.links.first.label.should == 'Xp'
254
+ @linkage.links.last.rword.should == 'RIGHT-WALL'
255
+ @linkage.links.last.label.should == 'RW'
256
+ @linkage.links[3].lword.should == 'flag.n'
257
+ @linkage.links[3].rword.should == 'was.v'
258
+ @linkage.links[3].label.should == 'Ss'
259
+ end
260
+
261
+
262
+ it "knows what word is the verb in the sentence" do
263
+ @linkage.verb.should == "was"
264
+ end
265
+
266
+
267
+ it "knows when the sentence doesn't have a direct object" do
268
+ @linkage.object.should be_nil()
269
+ end
270
+
271
+
272
+ MODE1_C_TREE_STRING = "(S (NP The flag)\n (VP was\n (ADJP wet))\n .)\n"
273
+ MODE2_C_TREE_STRING = "[S [NP The flag NP] [VP was [ADJP wet ADJP] VP] . S] \n"
274
+ MODE3_C_TREE_STRING = "(S (NP The flag) (VP was (ADJP wet)) .)\n"
275
+
276
+ it "returns an indented sexps for the constituent tree string by default (mode 1)" do
277
+ @linkage.constituent_tree_string.should == MODE1_C_TREE_STRING
278
+ end
279
+
280
+
281
+ it "returns indented sexps for the constituent tree string if fetched with explicit mode '1'" do
282
+ @linkage.constituent_tree_string( 1 ).should == MODE1_C_TREE_STRING
283
+ end
284
+
285
+ it "returns bracketed constituents if constituent tree string is fetched in mode 2" do
286
+ @linkage.constituent_tree_string( 2 ).should == MODE2_C_TREE_STRING
287
+ end
288
+
289
+ it "returns unindented sexps for the constituent tree string if constituent tree string " +
290
+ "is fetched in mode 3" do
291
+ @linkage.constituent_tree_string( 3 ).should == MODE3_C_TREE_STRING
292
+ end
293
+
294
+ it "raises an exception for any numeric constituent tree string mode greater than 3" do
295
+ lambda {
296
+ @linkage.constituent_tree_string( 4 )
297
+ }.should raise_error( ArgumentError, /illegal mode 4/i )
298
+ end
299
+
300
+ it "raises an exception for any numeric constituent tree string mode less than 1" do
301
+ lambda {
302
+ @linkage.constituent_tree_string( 0 )
303
+ }.should raise_error( ArgumentError, /illegal mode 0/i )
304
+ end
305
+
306
+
307
+ it "raises an exception when a non-numeric constituent tree string mode is given" do
308
+ lambda {
309
+ @linkage.constituent_tree_string( 'glarg' )
310
+ }.should raise_error( TypeError )
311
+ end
312
+
313
+ it "returns an Array of CTree structs for its constituent tree" do
314
+ rval = @linkage.constituent_tree
315
+
316
+ rval.should be_an_instance_of( Array )
317
+ rval.should have(1).members
318
+ rval.first.should be_a_kind_of( Struct )
319
+ rval.first.label.should == 'S'
320
+ rval.first.children.should have(3).members
321
+ rval.first.children.collect {|n| n.label }.should include( 'NP', 'VP', '.' )
322
+ end
323
+
324
+ it "returns 0 as the number of the current sublinkage since it has no conjunctions" do
325
+ @linkage.current_sublinkage.should == 0
326
+ end
327
+
328
+
329
+ it "returns an informational string when inspected" do
330
+ @linkage.inspect.should =~ /Linkage:0x[[:xdigit:]]+: sublinkage 0: \[\d+ links\]/
331
+ end
332
+
333
+
334
+ describe "from a simple sentence with a direct object" do
335
+ before( :each ) do
336
+ @sentence = @dict.parse( "The dog ran home." )
337
+ @linkage = @sentence.linkages.first
338
+ end
339
+
340
+
341
+ it "doesn't have any sublinkages" do
342
+ @linkage.num_sublinkages.should == 1
343
+ end
344
+
345
+ it "doesn't change after computing its union" do
346
+ lambda {
347
+ @linkage.compute_union
348
+ }.should_not change( @linkage, :num_sublinkages )
349
+ end
350
+
351
+
352
+ it "knows what word is the object in the sentence" do
353
+ @linkage.object.should == 'home'
354
+ end
355
+
356
+ end
357
+
358
+
359
+ it "knows that it doesn't have any conjunctions" do
360
+ @linkage.should_not have_conjunction()
361
+ end
362
+
363
+
364
+ describe "from a sentence with a conjunction" do
365
+ before( :each ) do
366
+ @sentence =
367
+ @dict.parse( "The ball rolled down the hill and bumped the curb." )
368
+ @linkage = @sentence.linkages.first
369
+ end
370
+
371
+
372
+ it "knows that it has a conjunction" do
373
+ @linkage.should have_conjunction()
374
+ end
375
+
376
+ it "has two sublinkages" do
377
+ @linkage.num_sublinkages.should == 2
378
+ end
379
+
380
+
381
+ it "adds a sublinkage after computing its union" do
382
+ lambda {
383
+ @linkage.compute_union
384
+ }.should change( @linkage, :num_sublinkages ).from(2).to(3)
385
+ end
386
+
387
+
388
+ it "knows what word is the verb in the current sublinkage" do
389
+ @linkage.verb.should == 'rolled'
390
+ @linkage.current_sublinkage = 1
391
+ @linkage.verb.should == 'bumped'
392
+ end
393
+
394
+
395
+ it "knows what word is the object in the current sublinkage" do
396
+ @linkage.object.should == 'hill'
397
+ @linkage.current_sublinkage = 1
398
+ @linkage.object.should == 'curb'
399
+ end
400
+
401
+ end
402
+
403
+
404
+ it "should know that it's not an imperative sentence" do
405
+ @linkage.imperative?.should be_false()
406
+ end
407
+
408
+
409
+ describe "from an imperative sentence" do
410
+ before( :each ) do
411
+ @sentence = @dict.parse( "Go to the store!" )
412
+ @linkage = @sentence.linkages.first
413
+ end
414
+
415
+
416
+ it "knows that it's an imperative sentence" do
417
+ @linkage.imperative?.should be_true()
418
+ end
419
+
420
+
421
+ end
422
+
423
+
424
+ describe "bugfixes" do
425
+
426
+ it "also strips off the '.p' from the subject and object when they are plural" do
427
+ sent = @dict.parse( 'People like goats.' )
428
+ sent.subject.should_not =~ /people\.p/i
429
+ sent.object.should_not =~ /goats\.p/i
430
+ end
431
+
432
+ end
433
+
434
+ end