diff options
Diffstat (limited to 'spec/ruby/library/stringscanner')
51 files changed, 1273 insertions, 0 deletions
diff --git a/spec/ruby/library/stringscanner/append_spec.rb b/spec/ruby/library/stringscanner/append_spec.rb new file mode 100644 index 0000000000..fef5dcf2bd --- /dev/null +++ b/spec/ruby/library/stringscanner/append_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'shared/concat' +require 'strscan' + +describe "StringScanner#<<" do + it_behaves_like :strscan_concat, :<< +end + +describe "StringScanner#<< when passed an Integer" do + it_behaves_like :strscan_concat_fixnum, :<< +end diff --git a/spec/ruby/library/stringscanner/beginning_of_line_spec.rb b/spec/ruby/library/stringscanner/beginning_of_line_spec.rb new file mode 100644 index 0000000000..3f6f0da75f --- /dev/null +++ b/spec/ruby/library/stringscanner/beginning_of_line_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/bol' +require 'strscan' + +describe "StringScanner#beginning_of_line?" do + it_behaves_like :strscan_bol, :beginning_of_line? +end diff --git a/spec/ruby/library/stringscanner/bol_spec.rb b/spec/ruby/library/stringscanner/bol_spec.rb new file mode 100644 index 0000000000..d31766e0e2 --- /dev/null +++ b/spec/ruby/library/stringscanner/bol_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/bol' +require 'strscan' + +describe "StringScanner#bol?" do + it_behaves_like :strscan_bol, :bol? +end diff --git a/spec/ruby/library/stringscanner/check_spec.rb b/spec/ruby/library/stringscanner/check_spec.rb new file mode 100644 index 0000000000..21da785515 --- /dev/null +++ b/spec/ruby/library/stringscanner/check_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#check" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the value that scan would return, without advancing the scan pointer" do + @s.check(/This/).should == "This" + @s.matched.should == "This" + @s.pos.should == 0 + @s.check(/is/).should == nil + @s.matched.should == nil + end + + ruby_version_is "2.7" do + it "treats String as the pattern itself" do + @s.check("This").should == "This" + @s.matched.should == "This" + @s.pos.should == 0 + @s.check(/is/).should == nil + @s.matched.should == nil + end + end + +end diff --git a/spec/ruby/library/stringscanner/check_until_spec.rb b/spec/ruby/library/stringscanner/check_until_spec.rb new file mode 100644 index 0000000000..ad222fd76b --- /dev/null +++ b/spec/ruby/library/stringscanner/check_until_spec.rb @@ -0,0 +1,21 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#check_until" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the same value of scan_until, but don't advances the scan pointer" do + @s.check_until(/a/).should == "This is a" + @s.pos.should == 0 + @s.matched.should == "a" + @s.check_until(/test/).should == "This is a test" + end + + it "raises TypeError if given a String" do + -> { + @s.check_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end +end diff --git a/spec/ruby/library/stringscanner/clear_spec.rb b/spec/ruby/library/stringscanner/clear_spec.rb new file mode 100644 index 0000000000..7ae089704a --- /dev/null +++ b/spec/ruby/library/stringscanner/clear_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require_relative 'shared/terminate' +require 'strscan' + +describe "StringScanner#clear" do + it_behaves_like :strscan_terminate, :clear + + it "warns in verbose mode that the method is obsolete" do + s = StringScanner.new("abc") + -> { + s.clear + }.should complain(/clear.*obsolete.*terminate/, verbose: true) + + -> { + s.clear + }.should_not complain(verbose: false) + end +end diff --git a/spec/ruby/library/stringscanner/concat_spec.rb b/spec/ruby/library/stringscanner/concat_spec.rb new file mode 100644 index 0000000000..4f790e2505 --- /dev/null +++ b/spec/ruby/library/stringscanner/concat_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'shared/concat' +require 'strscan' + +describe "StringScanner#concat" do + it_behaves_like :strscan_concat, :concat +end + +describe "StringScanner#concat when passed an Integer" do + it_behaves_like :strscan_concat_fixnum, :concat +end diff --git a/spec/ruby/library/stringscanner/dup_spec.rb b/spec/ruby/library/stringscanner/dup_spec.rb new file mode 100644 index 0000000000..0fc52a1477 --- /dev/null +++ b/spec/ruby/library/stringscanner/dup_spec.rb @@ -0,0 +1,39 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#dup" do + before :each do + @string = "this is a test" + @orig_s = StringScanner.new(@string) + end + + it "copies the passed StringScanner's content to self" do + s = @orig_s.dup + s.string.should == @string + end + + it "copies the passed StringScanner's position to self" do + @orig_s.pos = 5 + s = @orig_s.dup + s.pos.should eql(5) + end + + it "copies previous match state" do + @orig_s.scan(/\w+/) + @orig_s.scan(/\s/) + + @orig_s.pre_match.should == "this" + + s = @orig_s.dup + s.pre_match.should == "this" + + s.unscan + s.scan(/\s/).should == " " + end + + it "copies the passed StringScanner scan pointer to self" do + @orig_s.terminate + s = @orig_s.dup + s.eos?.should be_true + end +end diff --git a/spec/ruby/library/stringscanner/element_reference_spec.rb b/spec/ruby/library/stringscanner/element_reference_spec.rb new file mode 100644 index 0000000000..60fe15d807 --- /dev/null +++ b/spec/ruby/library/stringscanner/element_reference_spec.rb @@ -0,0 +1,60 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#[]" do + before :each do + @s = StringScanner.new("Fri Jun 13 2008 22:43") + end + + it "returns nil if there is no current match" do + @s[0].should be_nil + end + + it "returns the n-th subgroup in the most recent match" do + @s.scan(/(\w+) (\w+) (\d+) /) + @s[0].should == "Fri Jun 13 " + @s[1].should == "Fri" + @s[2].should == "Jun" + @s[3].should == "13" + @s[-3].should == "Fri" + @s[-2].should == "Jun" + @s[-1].should == "13" + end + + it "returns nil if index is outside of self" do + @s.scan(/(\w+) (\w+) (\d+) /) + @s[5].should == nil + @s[-5].should == nil + end + + it "calls to_int on the given index" do + @s.scan(/(\w+) (\w+) (\d+) /) + @s[0.5].should == "Fri Jun 13 " + end + + it "raises a TypeError if the given index is nil" do + @s.scan(/(\w+) (\w+) (\d+) /) + -> { @s[nil]}.should raise_error(TypeError) + end + + it "raises a TypeError when a Range is as argument" do + @s.scan(/(\w+) (\w+) (\d+) /) + -> { @s[0..2]}.should raise_error(TypeError) + end + + it "raises a IndexError when there's no named capture" do + @s.scan(/(\w+) (\w+) (\d+) /) + -> { @s["wday"]}.should raise_error(IndexError) + -> { @s[:wday]}.should raise_error(IndexError) + end + + it "returns named capture" do + @s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) + @s["wday"].should == "Fri" + @s["month"].should == "Jun" + @s["day"].should == "13" + @s[:wday].should == "Fri" + @s[:month].should == "Jun" + @s[:day].should == "13" + end +end diff --git a/spec/ruby/library/stringscanner/empty_spec.rb b/spec/ruby/library/stringscanner/empty_spec.rb new file mode 100644 index 0000000000..d9449bea6e --- /dev/null +++ b/spec/ruby/library/stringscanner/empty_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require_relative 'shared/eos' +require 'strscan' + +describe "StringScanner#empty?" do + it_behaves_like :strscan_eos, :empty? + + it "warns in verbose mode that the method is obsolete" do + s = StringScanner.new("abc") + -> { + s.empty? + }.should complain(/empty?.*obsolete.*eos?/, verbose: true) + + -> { + s.empty? + }.should_not complain(verbose: false) + end +end diff --git a/spec/ruby/library/stringscanner/eos_spec.rb b/spec/ruby/library/stringscanner/eos_spec.rb new file mode 100644 index 0000000000..b58ee1e473 --- /dev/null +++ b/spec/ruby/library/stringscanner/eos_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/eos' +require 'strscan' + +describe "StringScanner#eos?" do + it_behaves_like :strscan_eos, :eos? +end diff --git a/spec/ruby/library/stringscanner/exist_spec.rb b/spec/ruby/library/stringscanner/exist_spec.rb new file mode 100644 index 0000000000..ff860a0d3e --- /dev/null +++ b/spec/ruby/library/stringscanner/exist_spec.rb @@ -0,0 +1,30 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#exist?" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the index of the first occurrence of the given pattern" do + @s.exist?(/s/).should == 4 + @s.scan(/This is/) + @s.exist?(/s/).should == 6 + end + + it "returns 0 if the pattern is empty" do + @s.exist?(//).should == 0 + end + + it "returns nil if the pattern isn't found in the string" do + @s.exist?(/S/).should == nil + @s.scan(/This is/) + @s.exist?(/i/).should == nil + end + + it "raises TypeError if given a String" do + -> { + @s.exist?('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end +end diff --git a/spec/ruby/library/stringscanner/get_byte_spec.rb b/spec/ruby/library/stringscanner/get_byte_spec.rb new file mode 100644 index 0000000000..29e2f557de --- /dev/null +++ b/spec/ruby/library/stringscanner/get_byte_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/get_byte' +require 'strscan' + +describe "StringScanner#get_byte" do + it_behaves_like :strscan_get_byte, :get_byte +end diff --git a/spec/ruby/library/stringscanner/getbyte_spec.rb b/spec/ruby/library/stringscanner/getbyte_spec.rb new file mode 100644 index 0000000000..e0659a5829 --- /dev/null +++ b/spec/ruby/library/stringscanner/getbyte_spec.rb @@ -0,0 +1,21 @@ +require_relative '../../spec_helper' +require_relative 'shared/get_byte' +require_relative 'shared/extract_range' +require 'strscan' + +describe "StringScanner#getbyte" do + it_behaves_like :strscan_get_byte, :getbyte + + it "warns in verbose mode that the method is obsolete" do + s = StringScanner.new("abc") + -> { + s.getbyte + }.should complain(/getbyte.*obsolete.*get_byte/, verbose: true) + + -> { + s.getbyte + }.should_not complain(verbose: false) + end + + it_behaves_like :extract_range, :getbyte +end diff --git a/spec/ruby/library/stringscanner/getch_spec.rb b/spec/ruby/library/stringscanner/getch_spec.rb new file mode 100644 index 0000000000..a6be0d4221 --- /dev/null +++ b/spec/ruby/library/stringscanner/getch_spec.rb @@ -0,0 +1,35 @@ +# -*- encoding: binary -*- +require_relative '../../spec_helper' +require_relative 'shared/extract_range' +require 'strscan' + +describe "StringScanner#getch" do + it "scans one character and returns it" do + s = StringScanner.new('abc') + s.getch.should == "a" + s.getch.should == "b" + s.getch.should == "c" + end + + it "is multi-byte character sensitive" do + # Japanese hiragana "A" in EUC-JP + src = "\244\242".force_encoding("euc-jp") + + s = StringScanner.new(src) + s.getch.should == src + end + + it "returns nil at the end of the string" do + # empty string case + s = StringScanner.new('') + s.getch.should == nil + s.getch.should == nil + + # non-empty string case + s = StringScanner.new('a') + s.getch # skip one + s.getch.should == nil + end + + it_behaves_like :extract_range, :getch +end diff --git a/spec/ruby/library/stringscanner/initialize_spec.rb b/spec/ruby/library/stringscanner/initialize_spec.rb new file mode 100644 index 0000000000..047d9d058b --- /dev/null +++ b/spec/ruby/library/stringscanner/initialize_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#initialize" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "is a private method" do + StringScanner.should have_private_instance_method(:initialize) + end + + it "returns an instance of StringScanner" do + @s.should be_kind_of(StringScanner) + @s.eos?.should be_false + end + + it "converts the argument into a string using #to_str" do + m = mock(:str) + + s = "test" + m.should_receive(:to_str).and_return(s) + + scan = StringScanner.new(m) + scan.string.should == s + end +end diff --git a/spec/ruby/library/stringscanner/inspect_spec.rb b/spec/ruby/library/stringscanner/inspect_spec.rb new file mode 100644 index 0000000000..ff6b97eb91 --- /dev/null +++ b/spec/ruby/library/stringscanner/inspect_spec.rb @@ -0,0 +1,20 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#inspect" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns a String object" do + @s.inspect.should be_kind_of(String) + end + + it "returns a string that represents the StringScanner object" do + @s.inspect.should == "#<StringScanner 0/14 @ \"This ...\">" + @s.scan_until(/is/) + @s.inspect.should == "#<StringScanner 4/14 \"This\" @ \" is a...\">" + @s.terminate + @s.inspect.should == "#<StringScanner fin>" + end +end diff --git a/spec/ruby/library/stringscanner/match_spec.rb b/spec/ruby/library/stringscanner/match_spec.rb new file mode 100644 index 0000000000..ec59680914 --- /dev/null +++ b/spec/ruby/library/stringscanner/match_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#match?" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the length of the match and the scan pointer is not advanced" do + @s.match?(/\w+/).should == 4 + @s.match?(/\w+/).should == 4 + @s.pos.should == 0 + end + + it "returns nil if there's no match" do + @s.match?(/\d+/).should == nil + @s.match?(/\s+/).should == nil + end + + it "effects pre_match" do + @s.scan(/\w+/) + @s.scan(/\s/) + + @s.pre_match.should == "This" + @s.match?(/\w+/) + @s.pre_match.should == "This " + end +end diff --git a/spec/ruby/library/stringscanner/matched_size_spec.rb b/spec/ruby/library/stringscanner/matched_size_spec.rb new file mode 100644 index 0000000000..d9c338a07e --- /dev/null +++ b/spec/ruby/library/stringscanner/matched_size_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#matched_size" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the size of the most recent match" do + @s.check(/This/) + @s.matched_size.should == 4 + @s.matched_size.should == 4 + @s.scan(//) + @s.matched_size.should == 0 + end + + it "returns nil if there was no recent match" do + @s.matched_size.should == nil + @s.check(/\d+/) + @s.matched_size.should == nil + @s.terminate + @s.matched_size.should == nil + end +end diff --git a/spec/ruby/library/stringscanner/matched_spec.rb b/spec/ruby/library/stringscanner/matched_spec.rb new file mode 100644 index 0000000000..c020bd3eae --- /dev/null +++ b/spec/ruby/library/stringscanner/matched_spec.rb @@ -0,0 +1,41 @@ +require_relative '../../spec_helper' +require_relative 'shared/extract_range_matched' +require 'strscan' + +describe "StringScanner#matched" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the last matched string" do + @s.match?(/\w+/) + @s.matched.should == "This" + @s.getch + @s.matched.should == "T" + @s.get_byte + @s.matched.should == "h" + end + + it "returns nil if there's no match" do + @s.match?(/\d+/) + @s.matched.should == nil + end + + it_behaves_like :extract_range_matched, :matched +end + +describe "StringScanner#matched?" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns true if the last match was successful" do + @s.match?(/\w+/) + @s.matched?.should be_true + end + + it "returns false if there's no match" do + @s.match?(/\d+/) + @s.matched?.should be_false + end +end diff --git a/spec/ruby/library/stringscanner/must_C_version_spec.rb b/spec/ruby/library/stringscanner/must_C_version_spec.rb new file mode 100644 index 0000000000..fcc5b596f6 --- /dev/null +++ b/spec/ruby/library/stringscanner/must_C_version_spec.rb @@ -0,0 +1,8 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner.must_C_version" do + it "returns self" do + StringScanner.must_C_version.should == StringScanner + end +end diff --git a/spec/ruby/library/stringscanner/peek_spec.rb b/spec/ruby/library/stringscanner/peek_spec.rb new file mode 100644 index 0000000000..cbb5630ff9 --- /dev/null +++ b/spec/ruby/library/stringscanner/peek_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/peek' +require 'strscan' + +describe "StringScanner#peek" do + it_behaves_like :strscan_peek, :peek +end diff --git a/spec/ruby/library/stringscanner/peep_spec.rb b/spec/ruby/library/stringscanner/peep_spec.rb new file mode 100644 index 0000000000..bf6d579325 --- /dev/null +++ b/spec/ruby/library/stringscanner/peep_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require_relative 'shared/peek' +require 'strscan' + +describe "StringScanner#peep" do + it_behaves_like :strscan_peek, :peep + + it "warns in verbose mode that the method is obsolete" do + s = StringScanner.new("abc") + -> { + s.peep(1) + }.should complain(/peep.*obsolete.*peek/, verbose: true) + + -> { + s.peep(1) + }.should_not complain(verbose: false) + end +end diff --git a/spec/ruby/library/stringscanner/pointer_spec.rb b/spec/ruby/library/stringscanner/pointer_spec.rb new file mode 100644 index 0000000000..bc0c0c50b7 --- /dev/null +++ b/spec/ruby/library/stringscanner/pointer_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'shared/pos' +require 'strscan' + +describe "StringScanner#pointer" do + it_behaves_like :strscan_pos, :pointer +end + +describe "StringScanner#pointer=" do + it_behaves_like :strscan_pos_set, :pointer= +end diff --git a/spec/ruby/library/stringscanner/pos_spec.rb b/spec/ruby/library/stringscanner/pos_spec.rb new file mode 100644 index 0000000000..275fecf0f3 --- /dev/null +++ b/spec/ruby/library/stringscanner/pos_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'shared/pos' +require 'strscan' + +describe "StringScanner#pos" do + it_behaves_like :strscan_pos, :pos +end + +describe "StringScanner#pos=" do + it_behaves_like :strscan_pos_set, :pos= +end diff --git a/spec/ruby/library/stringscanner/post_match_spec.rb b/spec/ruby/library/stringscanner/post_match_spec.rb new file mode 100644 index 0000000000..720dc3530d --- /dev/null +++ b/spec/ruby/library/stringscanner/post_match_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' +require_relative 'shared/extract_range_matched' +require 'strscan' + +describe "StringScanner#post_match" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the post-match (in the regular expression sense) of the last scan" do + @s.post_match.should == nil + @s.scan(/\w+\s/) + @s.post_match.should == "is a test" + @s.getch + @s.post_match.should == "s a test" + @s.get_byte + @s.post_match.should == " a test" + @s.get_byte + @s.post_match.should == "a test" + end + + it "returns nil if there's no match" do + @s.scan(/\s+/) + @s.post_match.should == nil + end + + it_behaves_like :extract_range_matched, :post_match +end diff --git a/spec/ruby/library/stringscanner/pre_match_spec.rb b/spec/ruby/library/stringscanner/pre_match_spec.rb new file mode 100644 index 0000000000..1c2c511d5c --- /dev/null +++ b/spec/ruby/library/stringscanner/pre_match_spec.rb @@ -0,0 +1,41 @@ +require_relative '../../spec_helper' +require_relative 'shared/extract_range_matched' +require 'strscan' + +describe "StringScanner#pre_match" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the pre-match (in the regular expression sense) of the last scan" do + @s.pre_match.should == nil + @s.scan(/\w+\s/) + @s.pre_match.should == "" + @s.getch + @s.pre_match.should == "This " + @s.get_byte + @s.pre_match.should == "This i" + @s.get_byte + @s.pre_match.should == "This is" + end + + it "returns nil if there's no match" do + @s.scan(/\s+/) + @s.pre_match.should == nil + end + + it "is more than just the data from the last match" do + @s.scan(/\w+/) + @s.scan_until(/a te/) + @s.pre_match.should == "This is " + end + + it "is not changed when the scanner's position changes" do + @s.scan_until(/\s+/) + @s.pre_match.should == "This" + @s.pos -= 1 + @s.pre_match.should == "This" + end + + it_behaves_like :extract_range_matched, :pre_match +end diff --git a/spec/ruby/library/stringscanner/reset_spec.rb b/spec/ruby/library/stringscanner/reset_spec.rb new file mode 100644 index 0000000000..a10ca2d838 --- /dev/null +++ b/spec/ruby/library/stringscanner/reset_spec.rb @@ -0,0 +1,15 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#reset" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "reset the scan pointer and clear matching data" do + @s.scan(/This/) + @s.reset + @s.pos.should == 0 + @s.matched.should == nil + end +end diff --git a/spec/ruby/library/stringscanner/rest_size_spec.rb b/spec/ruby/library/stringscanner/rest_size_spec.rb new file mode 100644 index 0000000000..e62e3a8f8c --- /dev/null +++ b/spec/ruby/library/stringscanner/rest_size_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/rest_size' +require 'strscan' + +describe "StringScanner#rest_size" do + it_behaves_like :strscan_rest_size, :rest_size +end diff --git a/spec/ruby/library/stringscanner/rest_spec.rb b/spec/ruby/library/stringscanner/rest_spec.rb new file mode 100644 index 0000000000..67072f880d --- /dev/null +++ b/spec/ruby/library/stringscanner/rest_spec.rb @@ -0,0 +1,48 @@ +require_relative '../../spec_helper' +require_relative 'shared/extract_range_matched' +require 'strscan' + +describe "StringScanner#rest" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the rest of the string" do + @s.scan(/This\s+/) + @s.rest.should == "is a test" + end + + it "returns self in the reset position" do + @s.reset + @s.rest.should == @s.string + end + + it "returns an empty string in the terminate position" do + @s.terminate + @s.rest.should == "" + end + + it_behaves_like :extract_range_matched, :rest + +end + +describe "StringScanner#rest?" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns true if there is more data in the string" do + @s.rest?.should be_true + @s.scan(/This/) + @s.rest?.should be_true + end + + it "returns false if there is no more data in the string" do + @s.terminate + @s.rest?.should be_false + end + + it "is the opposite of eos?" do + @s.rest?.should_not == @s.eos? + end +end diff --git a/spec/ruby/library/stringscanner/restsize_spec.rb b/spec/ruby/library/stringscanner/restsize_spec.rb new file mode 100644 index 0000000000..710520afae --- /dev/null +++ b/spec/ruby/library/stringscanner/restsize_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require_relative 'shared/rest_size' +require 'strscan' + +describe "StringScanner#restsize" do + it_behaves_like :strscan_rest_size, :restsize + + it "warns in verbose mode that the method is obsolete" do + s = StringScanner.new("abc") + -> { + s.restsize + }.should complain(/restsize.*obsolete.*rest_size/, verbose: true) + + -> { + s.restsize + }.should_not complain(verbose: false) + end +end diff --git a/spec/ruby/library/stringscanner/scan_full_spec.rb b/spec/ruby/library/stringscanner/scan_full_spec.rb new file mode 100644 index 0000000000..ed34d7d3f6 --- /dev/null +++ b/spec/ruby/library/stringscanner/scan_full_spec.rb @@ -0,0 +1,30 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#scan_full" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of bytes advanced" do + orig_pos = @s.pos + @s.scan_full(/This/, false, false).should == 4 + @s.pos.should == orig_pos + end + + it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do + @s.scan_full(/This/, true, false).should == 4 + @s.pos.should == 4 + end + + it "returns the matched string if the third argument is true" do + orig_pos = @s.pos + @s.scan_full(/This/, false, true).should == "This" + @s.pos.should == orig_pos + end + + it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do + @s.scan_full(/This/, true, true).should == "This" + @s.pos.should == 4 + end +end diff --git a/spec/ruby/library/stringscanner/scan_spec.rb b/spec/ruby/library/stringscanner/scan_spec.rb new file mode 100644 index 0000000000..2269abd6b3 --- /dev/null +++ b/spec/ruby/library/stringscanner/scan_spec.rb @@ -0,0 +1,97 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#scan" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the matched string" do + @s.scan(/\w+/).should == "This" + @s.scan(/.../).should == " is" + @s.scan(//).should == "" + @s.scan(/\s+/).should == " " + end + + it "treats ^ as matching from the beginning of the current position" do + @s.scan(/\w+/).should == "This" + @s.scan(/^\d/).should be_nil + @s.scan(/^\s/).should == " " + end + + it "treats ^ as matching from the beginning of the current position when it's not the first character in the regexp" do + @s.scan(/\w+/).should == "This" + @s.scan(/( is not|^ is a)/).should == " is a" + end + + it "treats \\A as matching from the beginning of the current position" do + @s.scan(/\w+/).should == "This" + @s.scan(/\A\d/).should be_nil + @s.scan(/\A\s/).should == " " + end + + it "treats \\A as matching from the beginning of the current position when it's not the first character in the regexp" do + @s.scan(/\w+/).should == "This" + @s.scan(/( is not|\A is a)/).should == " is a" + end + + it "returns nil if there's no match" do + @s.scan(/\d/).should == nil + end + + it "returns nil when there is no more to scan" do + @s.scan(/[\w\s]+/).should == "This is a test" + @s.scan(/\w+/).should be_nil + end + + it "returns an empty string when the pattern matches empty" do + @s.scan(/.*/).should == "This is a test" + @s.scan(/.*/).should == "" + @s.scan(/./).should be_nil + end + + ruby_version_is ""..."2.7" do + it "raises a TypeError if pattern is a String" do + -> { @s.scan("aoeu") }.should raise_error(TypeError) + end + end + + ruby_version_is "2.7" do + it "treats String as the pattern itself" do + @s.scan("this").should be_nil + @s.scan("This").should == "This" + end + end + + it "raises a TypeError if pattern isn't a Regexp nor String" do + -> { @s.scan(5) }.should raise_error(TypeError) + -> { @s.scan(:test) }.should raise_error(TypeError) + -> { @s.scan(mock('x')) }.should raise_error(TypeError) + end +end + +describe "StringScanner#scan with fixed_anchor: true" do + before :each do + @s = StringScanner.new("This\nis\na\ntest", fixed_anchor: true) + end + + ruby_version_is "2.7" do + it "returns the matched string" do + @s.scan(/\w+/).should == "This" + @s.scan(/.../m).should == "\nis" + @s.scan(//).should == "" + @s.scan(/\s+/).should == "\n" + end + + it "treats ^ as matching from the beginning of line" do + @s.scan(/\w+\n/).should == "This\n" + @s.scan(/^\w/).should == "i" + @s.scan(/^\w/).should be_nil + end + + it "treats \\A as matching from the beginning of string" do + @s.scan(/\A\w/).should == "T" + @s.scan(/\A\w/).should be_nil + end + end +end diff --git a/spec/ruby/library/stringscanner/scan_until_spec.rb b/spec/ruby/library/stringscanner/scan_until_spec.rb new file mode 100644 index 0000000000..6b7782572d --- /dev/null +++ b/spec/ruby/library/stringscanner/scan_until_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#scan_until" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the substring up to and including the end of the match" do + @s.scan_until(/a/).should == "This is a" + @s.pre_match.should == "This is " + @s.post_match.should == " test" + end + + it "returns nil if there's no match" do + @s.scan_until(/\d/).should == nil + end + + it "can match anchors properly" do + @s.scan(/T/) + @s.scan_until(/^h/).should == "h" + end + + it "raises TypeError if given a String" do + -> { + @s.scan_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end +end diff --git a/spec/ruby/library/stringscanner/search_full_spec.rb b/spec/ruby/library/stringscanner/search_full_spec.rb new file mode 100644 index 0000000000..7d2a714fa5 --- /dev/null +++ b/spec/ruby/library/stringscanner/search_full_spec.rb @@ -0,0 +1,36 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#search_full" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of bytes advanced" do + orig_pos = @s.pos + @s.search_full(/This/, false, false).should == 4 + @s.pos.should == orig_pos + end + + it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do + @s.search_full(/This/, true, false).should == 4 + @s.pos.should == 4 + end + + it "returns the matched string if the third argument is true" do + orig_pos = @s.pos + @s.search_full(/This/, false, true).should == "This" + @s.pos.should == orig_pos + end + + it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do + @s.search_full(/This/, true, true).should == "This" + @s.pos.should == 4 + end + + it "raises TypeError if given a String" do + -> { + @s.search_full('T', true, true) + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end +end diff --git a/spec/ruby/library/stringscanner/shared/bol.rb b/spec/ruby/library/stringscanner/shared/bol.rb new file mode 100644 index 0000000000..ebcdd7938f --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/bol.rb @@ -0,0 +1,25 @@ +describe :strscan_bol, shared: true do + it "returns true if the scan pointer is at the beginning of the line, false otherwise" do + s = StringScanner.new("This is a test") + s.send(@method).should be_true + s.scan(/This/) + s.send(@method).should be_false + s.terminate + s.send(@method).should be_false + + s = StringScanner.new("hello\nworld") + s.bol?.should be_true + s.scan(/\w+/) + s.bol?.should be_false + s.scan(/\n/) + s.bol?.should be_true + s.unscan + s.bol?.should be_false + end + + it "returns true if the scan pointer is at the end of the line of an empty string." do + s = StringScanner.new('') + s.terminate + s.send(@method).should be_true + end +end diff --git a/spec/ruby/library/stringscanner/shared/concat.rb b/spec/ruby/library/stringscanner/shared/concat.rb new file mode 100644 index 0000000000..cb884a5c01 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/concat.rb @@ -0,0 +1,30 @@ +describe :strscan_concat, shared: true do + it "concatenates the given argument to self and returns self" do + s = StringScanner.new("hello ") + s.send(@method, 'world').should == s + s.string.should == "hello world" + s.eos?.should be_false + end + + it "raises a TypeError if the given argument can't be converted to a String" do + -> { StringScanner.new('hello').send(@method, :world) }.should raise_error(TypeError) + -> { StringScanner.new('hello').send(@method, mock('x')) }.should raise_error(TypeError) + end +end + +describe :strscan_concat_fixnum, shared: true do + it "raises a TypeError" do + a = StringScanner.new("hello world") + -> { a.send(@method, 333) }.should raise_error(TypeError) + b = StringScanner.new("") + -> { b.send(@method, (256 * 3 + 64)) }.should raise_error(TypeError) + -> { b.send(@method, -200) }.should raise_error(TypeError) + end + + it "doesn't call to_int on the argument" do + x = mock('x') + x.should_not_receive(:to_int) + + -> { StringScanner.new("").send(@method, x) }.should raise_error(TypeError) + end +end diff --git a/spec/ruby/library/stringscanner/shared/eos.rb b/spec/ruby/library/stringscanner/shared/eos.rb new file mode 100644 index 0000000000..ea04c764a2 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/eos.rb @@ -0,0 +1,17 @@ +describe :strscan_eos, shared: true do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns true if the scan pointer is at the end of the string" do + @s.terminate + @s.send(@method).should be_true + + s = StringScanner.new('') + s.send(@method).should be_true + end + + it "returns false if the scan pointer is not at the end of the string" do + @s.send(@method).should be_false + end +end diff --git a/spec/ruby/library/stringscanner/shared/extract_range.rb b/spec/ruby/library/stringscanner/shared/extract_range.rb new file mode 100644 index 0000000000..1c14f716c9 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/extract_range.rb @@ -0,0 +1,24 @@ +describe :extract_range, shared: true do + it "returns an instance of String when passed a String subclass" do + cls = Class.new(String) + sub = cls.new("abc") + + s = StringScanner.new(sub) + ch = s.send(@method) + ch.should_not be_kind_of(cls) + ch.should be_an_instance_of(String) + end + + ruby_version_is ''...'2.7' do + it "taints the returned String if the input was tainted" do + str = 'abc' + str.taint + + s = StringScanner.new(str) + + s.send(@method).tainted?.should be_true + s.send(@method).tainted?.should be_true + s.send(@method).tainted?.should be_true + end + end +end diff --git a/spec/ruby/library/stringscanner/shared/extract_range_matched.rb b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb new file mode 100644 index 0000000000..5c536f5c01 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/extract_range_matched.rb @@ -0,0 +1,24 @@ +describe :extract_range_matched, shared: true do + it "returns an instance of String when passed a String subclass" do + cls = Class.new(String) + sub = cls.new("abc") + + s = StringScanner.new(sub) + s.scan(/\w{1}/) + + ch = s.send(@method) + ch.should_not be_kind_of(cls) + ch.should be_an_instance_of(String) + end + + ruby_version_is ''...'2.7' do + it "taints the returned String if the input was tainted" do + str = 'abc' + str.taint + + s = StringScanner.new(str) + s.scan(/\w{1}/) + s.send(@method).tainted?.should be_true + end + end +end diff --git a/spec/ruby/library/stringscanner/shared/get_byte.rb b/spec/ruby/library/stringscanner/shared/get_byte.rb new file mode 100644 index 0000000000..763ab6f4a4 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/get_byte.rb @@ -0,0 +1,29 @@ +# -*- encoding: binary -*- +describe :strscan_get_byte, shared: true do + it "scans one byte and returns it" do + s = StringScanner.new('abc5.') + s.send(@method).should == 'a' + s.send(@method).should == 'b' + s.send(@method).should == 'c' + s.send(@method).should == '5' + s.send(@method).should == '.' + end + + it "is not multi-byte character sensitive" do + s = StringScanner.new("\244\242") + s.send(@method).should == "\244" + s.send(@method).should == "\242" + end + + it "returns nil at the end of the string" do + # empty string case + s = StringScanner.new('') + s.send(@method).should == nil + s.send(@method).should == nil + + # non-empty string case + s = StringScanner.new('a') + s.send(@method) # skip one + s.send(@method).should == nil + end +end diff --git a/spec/ruby/library/stringscanner/shared/peek.rb b/spec/ruby/library/stringscanner/shared/peek.rb new file mode 100644 index 0000000000..4e2e643353 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/peek.rb @@ -0,0 +1,49 @@ +describe :strscan_peek, shared: true do + before :each do + @s = StringScanner.new('This is a test') + end + + it "returns at most the specified number of bytes from the current position" do + @s.send(@method, 4).should == "This" + @s.pos.should == 0 + @s.pos = 5 + @s.send(@method, 2).should == "is" + @s.send(@method, 1000).should == "is a test" + + s = StringScanner.new("été") + s.send(@method, 2).should == "é" + end + + it "returns an empty string when the passed argument is zero" do + @s.send(@method, 0).should == "" + end + + it "raises a ArgumentError when the passed argument is negative" do + -> { @s.send(@method, -2) }.should raise_error(ArgumentError) + end + + it "raises a RangeError when the passed argument is a Bignum" do + -> { @s.send(@method, bignum_value) }.should raise_error(RangeError) + end + + it "returns an instance of String when passed a String subclass" do + cls = Class.new(String) + sub = cls.new("abc") + + s = StringScanner.new(sub) + + ch = s.send(@method, 1) + ch.should_not be_kind_of(cls) + ch.should be_an_instance_of(String) + end + + ruby_version_is ''...'2.7' do + it "taints the returned String if the input was tainted" do + str = 'abc' + str.taint + + s = StringScanner.new(str) + s.send(@method, 1).tainted?.should be_true + end + end +end diff --git a/spec/ruby/library/stringscanner/shared/pos.rb b/spec/ruby/library/stringscanner/shared/pos.rb new file mode 100644 index 0000000000..6d540881f2 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/pos.rb @@ -0,0 +1,52 @@ +describe :strscan_pos, shared: true do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the position of the scan pointer" do + @s.send(@method).should == 0 + @s.scan_until(/This is/) + @s.send(@method).should == 7 + @s.get_byte + @s.send(@method).should == 8 + @s.terminate + @s.send(@method).should == 14 + end + + it "returns 0 in the reset position" do + @s.reset + @s.send(@method).should == 0 + end + + it "returns the length of the string in the terminate position" do + @s.terminate + @s.send(@method).should == @s.string.length + end +end + +describe :strscan_pos_set, shared: true do + before :each do + @s = StringScanner.new("This is a test") + end + + it "modify the scan pointer" do + @s.send(@method, 5) + @s.rest.should == "is a test" + end + + it "positions from the end if the argument is negative" do + @s.send(@method, -2) + @s.rest.should == "st" + @s.pos.should == 12 + end + + it "raises a RangeError if position too far backward" do + -> { + @s.send(@method, -20) + }.should raise_error(RangeError) + end + + it "raises a RangeError when the passed argument is out of range" do + -> { @s.send(@method, 20) }.should raise_error(RangeError) + end +end diff --git a/spec/ruby/library/stringscanner/shared/rest_size.rb b/spec/ruby/library/stringscanner/shared/rest_size.rb new file mode 100644 index 0000000000..4c4f49e45c --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/rest_size.rb @@ -0,0 +1,18 @@ +describe :strscan_rest_size, shared: true do + before :each do + @s = StringScanner.new('This is a test') + end + + it "returns the length of the rest of the string" do + @s.send(@method).should == 14 + @s.scan(/This/) + @s.send(@method).should == 10 + @s.terminate + @s.send(@method).should == 0 + end + + it "is equivalent to rest.size" do + @s.scan(/This/) + @s.send(@method).should == @s.rest.size + end +end diff --git a/spec/ruby/library/stringscanner/shared/terminate.rb b/spec/ruby/library/stringscanner/shared/terminate.rb new file mode 100644 index 0000000000..bf41d097e2 --- /dev/null +++ b/spec/ruby/library/stringscanner/shared/terminate.rb @@ -0,0 +1,8 @@ +describe :strscan_terminate, shared: true do + it "set the scan pointer to the end of the string and clear matching data." do + s = StringScanner.new('This is a test') + s.send(@method) + s.bol?.should be_false + s.eos?.should be_true + end +end diff --git a/spec/ruby/library/stringscanner/size_spec.rb b/spec/ruby/library/stringscanner/size_spec.rb new file mode 100644 index 0000000000..3e475489e3 --- /dev/null +++ b/spec/ruby/library/stringscanner/size_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#size" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of captures groups of the last match" do + @s.scan(/(.)(.)(.)/) + @s.size.should == 4 + end + + it "returns nil if there is no last match" do + @s.size.should == nil + end +end diff --git a/spec/ruby/library/stringscanner/skip_spec.rb b/spec/ruby/library/stringscanner/skip_spec.rb new file mode 100644 index 0000000000..473361782c --- /dev/null +++ b/spec/ruby/library/stringscanner/skip_spec.rb @@ -0,0 +1,18 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#skip" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns length of the match" do + @s.skip(/\w+/).should == 4 + @s.skip(/\s+\w+/).should == 3 + end + + it "returns nil if there's no match" do + @s.skip(/\s+/).should == nil + @s.skip(/\d+/).should == nil + end +end diff --git a/spec/ruby/library/stringscanner/skip_until_spec.rb b/spec/ruby/library/stringscanner/skip_until_spec.rb new file mode 100644 index 0000000000..7b56f13e4f --- /dev/null +++ b/spec/ruby/library/stringscanner/skip_until_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#skip_until" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of bytes advanced and advances the scan pointer until pattern is matched and consumed" do + @s.skip_until(/a/).should == 9 + @s.pos.should == 9 + @s.matched.should == "a" + end + + it "returns nil if no match was found" do + @s.skip_until(/d+/).should == nil + end + + it "raises TypeError if given a String" do + -> { + @s.skip_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end +end diff --git a/spec/ruby/library/stringscanner/string_spec.rb b/spec/ruby/library/stringscanner/string_spec.rb new file mode 100644 index 0000000000..28e2f0ed37 --- /dev/null +++ b/spec/ruby/library/stringscanner/string_spec.rb @@ -0,0 +1,40 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#string" do + before :each do + @string = "This is a test" + @s = StringScanner.new(@string) + end + + it "returns the string being scanned" do + @s.string.should == "This is a test" + @s << " case" + @s.string.should == "This is a test case" + end + + it "returns the identical object passed in" do + @s.string.equal?(@string).should be_true + end +end + +describe "StringScanner#string=" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "changes the string being scanned to the argument and resets the scanner" do + @s.string = "Hello world" + @s.string.should == "Hello world" + end + + it "converts the argument into a string using #to_str" do + m = mock(:str) + + s = "test" + m.should_receive(:to_str).and_return(s) + + @s.string = m + @s.string.should == s + end +end diff --git a/spec/ruby/library/stringscanner/terminate_spec.rb b/spec/ruby/library/stringscanner/terminate_spec.rb new file mode 100644 index 0000000000..249023f1ab --- /dev/null +++ b/spec/ruby/library/stringscanner/terminate_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'shared/terminate' +require 'strscan' + +describe "StringScanner#terminate" do + it_behaves_like :strscan_terminate, :terminate +end diff --git a/spec/ruby/library/stringscanner/unscan_spec.rb b/spec/ruby/library/stringscanner/unscan_spec.rb new file mode 100644 index 0000000000..df0ea43367 --- /dev/null +++ b/spec/ruby/library/stringscanner/unscan_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#unscan" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "set the scan pointer to the previous position" do + @s.scan(/This/) + @s.unscan + @s.matched.should == nil + @s.pos.should == 0 + end + + it "remember only one previous position" do + @s.scan(/This/) + pos = @s.pos + @s.scan(/ is/) + @s.unscan + @s.pos.should == pos + end + + it "raises a ScanError when the previous match had failed" do + -> { @s.unscan }.should raise_error(ScanError) + -> { @s.scan(/\d/); @s.unscan }.should raise_error(ScanError) + end +end |
