linkparser 1.0.3

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/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