diff options
Diffstat (limited to 'spec/ruby/core/array/pack')
32 files changed, 2969 insertions, 0 deletions
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb new file mode 100644 index 0000000000..e7fbdcd179 --- /dev/null +++ b/spec/ruby/core/array/pack/a_spec.rb @@ -0,0 +1,59 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/string', __FILE__) + +describe "Array#pack with format 'A'" do + it_behaves_like :array_pack_basic, 'A' + it_behaves_like :array_pack_basic_non_float, 'A' + it_behaves_like :array_pack_no_platform, 'A' + it_behaves_like :array_pack_string, 'A' + + it "adds all the bytes to the output when passed the '*' modifier" do + ["abc"].pack("A*").should == "abc" + end + + it "padds the output with spaces when the count exceeds the size of the String" do + ["abc"].pack("A6").should == "abc " + end + + it "adds a space when the value is nil" do + [nil].pack("A").should == " " + end + + it "pads the output with spaces when the value is nil" do + [nil].pack("A3").should == " " + end + + it "does not pad with spaces when passed the '*' modifier and the value is nil" do + [nil].pack("A*").should == "" + end +end + +describe "Array#pack with format 'a'" do + it_behaves_like :array_pack_basic, 'a' + it_behaves_like :array_pack_basic_non_float, 'a' + it_behaves_like :array_pack_no_platform, 'a' + it_behaves_like :array_pack_string, 'a' + + it "adds all the bytes to the output when passed the '*' modifier" do + ["abc"].pack("a*").should == "abc" + end + + it "padds the output with NULL bytes when the count exceeds the size of the String" do + ["abc"].pack("a6").should == "abc\x00\x00\x00" + end + + it "adds a NULL byte when the value is nil" do + [nil].pack("a").should == "\x00" + end + + it "pads the output with NULL bytes when the value is nil" do + [nil].pack("a3").should == "\x00\x00\x00" + end + + it "does not pad with NULL bytes when passed the '*' modifier and the value is nil" do + [nil].pack("a*").should == "" + end +end diff --git a/spec/ruby/core/array/pack/at_spec.rb b/spec/ruby/core/array/pack/at_spec.rb new file mode 100644 index 0000000000..dd538e8951 --- /dev/null +++ b/spec/ruby/core/array/pack/at_spec.rb @@ -0,0 +1,30 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) + +describe "Array#pack with format '@'" do + it_behaves_like :array_pack_basic, '@' + it_behaves_like :array_pack_basic_non_float, '@' + it_behaves_like :array_pack_no_platform, '@' + + it "moves the insertion point to the index specified by the count modifier" do + [1, 2, 3, 4, 5].pack("C4@2C").should == "\x01\x02\x05" + end + + it "does not consume any elements" do + [1, 2, 3].pack("C@3C").should == "\x01\x00\x00\x02" + end + + it "extends the string with NULL bytes if the string size is less than the count" do + [1, 2, 3].pack("@3C*").should == "\x00\x00\x00\x01\x02\x03" + end + + it "truncates the string if the string size is greater than the count" do + [1, 2, 3].pack("Cx5@2C").should == "\x01\x00\x02" + end + + it "implicitly has a count of one when no count modifier is passed" do + [1, 2, 3].pack("C*@").should == "\x01" + end +end diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb new file mode 100644 index 0000000000..62294ab8d1 --- /dev/null +++ b/spec/ruby/core/array/pack/b_spec.rb @@ -0,0 +1,105 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/encodings', __FILE__) + +describe "Array#pack with format 'B'" do + it_behaves_like :array_pack_basic, 'B' + it_behaves_like :array_pack_basic_non_float, 'B' + it_behaves_like :array_pack_arguments, 'B' + it_behaves_like :array_pack_hex, 'B' + + it "calls #to_str to convert an Object to a String" do + obj = mock("pack H string") + obj.should_receive(:to_str).and_return("``abcdef") + [obj].pack("B*").should == "\x2a" + end + + it "encodes one bit for each character starting with the most significant bit" do + [ [["0"], "\x00"], + [["1"], "\x80"] + ].should be_computed_by(:pack, "B") + end + + it "implicitly has a count of one when not passed a count modifier" do + ["1"].pack("B").should == "\x80" + end + + it "implicitly has count equal to the string length when passed the '*' modifier" do + [ [["00101010"], "\x2a"], + [["00000000"], "\x00"], + [["11111111"], "\xff"], + [["10000000"], "\x80"], + [["00000001"], "\x01"] + ].should be_computed_by(:pack, "B*") + end + + it "encodes the least significant bit of a character other than 0 or 1" do + [ [["bbababab"], "\x2a"], + [["^&#&#^#^"], "\x2a"], + [["(()()()("], "\x2a"], + [["@@%@%@%@"], "\x2a"], + [["ppqrstuv"], "\x2a"], + [["rqtvtrqp"], "\x42"] + ].should be_computed_by(:pack, "B*") + end + + it "returns an ASCII-8BIT string" do + ["1"].pack("B").encoding.should == Encoding::ASCII_8BIT + end + + it "encodes the string as a sequence of bytes" do + ["ああああああああ"].pack("B*").should == "\xdbm\xb6" + end +end + +describe "Array#pack with format 'b'" do + it_behaves_like :array_pack_basic, 'b' + it_behaves_like :array_pack_basic_non_float, 'b' + it_behaves_like :array_pack_arguments, 'b' + it_behaves_like :array_pack_hex, 'b' + + it "calls #to_str to convert an Object to a String" do + obj = mock("pack H string") + obj.should_receive(:to_str).and_return("`abcdef`") + [obj].pack("b*").should == "\x2a" + end + + it "encodes one bit for each character starting with the least significant bit" do + [ [["0"], "\x00"], + [["1"], "\x01"] + ].should be_computed_by(:pack, "b") + end + + it "implicitly has a count of one when not passed a count modifier" do + ["1"].pack("b").should == "\x01" + end + + it "implicitly has count equal to the string length when passed the '*' modifier" do + [ [["0101010"], "\x2a"], + [["00000000"], "\x00"], + [["11111111"], "\xff"], + [["10000000"], "\x01"], + [["00000001"], "\x80"] + ].should be_computed_by(:pack, "b*") + end + + it "encodes the least significant bit of a character other than 0 or 1" do + [ [["bababab"], "\x2a"], + [["&#&#^#^"], "\x2a"], + [["()()()("], "\x2a"], + [["@%@%@%@"], "\x2a"], + [["pqrstuv"], "\x2a"], + [["qrtrtvs"], "\x41"] + ].should be_computed_by(:pack, "b*") + end + + it "returns an ASCII-8BIT string" do + ["1"].pack("b").encoding.should == Encoding::ASCII_8BIT + end + + it "encodes the string as a sequence of bytes" do + ["ああああああああ"].pack("b*").should == "\xdb\xb6m" + end +end diff --git a/spec/ruby/core/array/pack/c_spec.rb b/spec/ruby/core/array/pack/c_spec.rb new file mode 100644 index 0000000000..74afa72f56 --- /dev/null +++ b/spec/ruby/core/array/pack/c_spec.rb @@ -0,0 +1,75 @@ +# -*- encoding: ascii-8bit -*- + +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) + +describe :array_pack_8bit, shared: true do + it "encodes the least significant eight bits of a positive number" do + [ [[49], "1"], + [[0b11111111], "\xFF"], + [[0b100000000], "\x00"], + [[0b100000001], "\x01"] + ].should be_computed_by(:pack, pack_format) + end + + it "encodes the least significant eight bits of a negative number" do + [ [[-1], "\xFF"], + [[-0b10000000], "\x80"], + [[-0b11111111], "\x01"], + [[-0b100000000], "\x00"], + [[-0b100000001], "\xFF"] + ].should be_computed_by(:pack, pack_format) + end + + it "encodes a Float truncated as an Integer" do + [ [[5.2], "\x05"], + [[5.8], "\x05"] + ].should be_computed_by(:pack, pack_format) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(5) + [obj].pack(pack_format).should == "\x05" + end + + it "encodes the number of array elements specified by the count modifier" do + [ [[1, 2, 3], pack_format(3), "\x01\x02\x03"], + [[1, 2, 3], pack_format(2) + pack_format(1), "\x01\x02\x03"] + ].should be_computed_by(:pack) + end + + it "encodes all remaining elements when passed the '*' modifier" do + [1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05" + end + + it "ignores NULL bytes between directives" do + [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02" + end + + it "ignores spaces between directives" do + [1, 2, 3].pack(pack_format(' ', 2)).should == "\x01\x02" + end +end + +describe "Array#pack with format 'C'" do + it_behaves_like :array_pack_basic, 'C' + it_behaves_like :array_pack_basic_non_float, 'C' + it_behaves_like :array_pack_8bit, 'C' + it_behaves_like :array_pack_arguments, 'C' + it_behaves_like :array_pack_numeric_basic, 'C' + it_behaves_like :array_pack_integer, 'C' + it_behaves_like :array_pack_no_platform, 'C' +end + +describe "Array#pack with format 'c'" do + it_behaves_like :array_pack_basic, 'c' + it_behaves_like :array_pack_basic_non_float, 'c' + it_behaves_like :array_pack_8bit, 'c' + it_behaves_like :array_pack_arguments, 'c' + it_behaves_like :array_pack_numeric_basic, 'c' + it_behaves_like :array_pack_integer, 'c' + it_behaves_like :array_pack_no_platform, 'c' +end diff --git a/spec/ruby/core/array/pack/comment_spec.rb b/spec/ruby/core/array/pack/comment_spec.rb new file mode 100644 index 0000000000..00c5fb6ecd --- /dev/null +++ b/spec/ruby/core/array/pack/comment_spec.rb @@ -0,0 +1,25 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) + +describe "Array#pack" do + it "ignores directives text from '#' to the first newline" do + [1, 2, 3].pack("c#this is a comment\nc").should == "\x01\x02" + end + + it "ignores directives text from '#' to the end if no newline is present" do + [1, 2, 3].pack("c#this is a comment c").should == "\x01" + end + + it "ignores comments at the start of the directives string" do + [1, 2, 3].pack("#this is a comment\nc").should == "\x01" + end + + it "ignores the entire directive string if it is a comment" do + [1, 2, 3].pack("#this is a comment").should == "" + end + + it "ignores multiple comments" do + [1, 2, 3].pack("c#comment\nc#comment\nc#c").should == "\x01\x02\x03" + end +end diff --git a/spec/ruby/core/array/pack/d_spec.rb b/spec/ruby/core/array/pack/d_spec.rb new file mode 100644 index 0000000000..40f28d1e52 --- /dev/null +++ b/spec/ruby/core/array/pack/d_spec.rb @@ -0,0 +1,39 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/float', __FILE__) + +describe "Array#pack with format 'D'" do + it_behaves_like :array_pack_basic, 'D' + it_behaves_like :array_pack_basic_float, 'D' + it_behaves_like :array_pack_arguments, 'D' + it_behaves_like :array_pack_no_platform, 'D' + it_behaves_like :array_pack_numeric_basic, 'D' + it_behaves_like :array_pack_float, 'D' + + little_endian do + it_behaves_like :array_pack_double_le, 'D' + end + + big_endian do + it_behaves_like :array_pack_double_be, 'D' + end +end + +describe "Array#pack with format 'd'" do + it_behaves_like :array_pack_basic, 'd' + it_behaves_like :array_pack_basic_float, 'd' + it_behaves_like :array_pack_arguments, 'd' + it_behaves_like :array_pack_no_platform, 'd' + it_behaves_like :array_pack_numeric_basic, 'd' + it_behaves_like :array_pack_float, 'd' + + little_endian do + it_behaves_like :array_pack_double_le, 'd' + end + + big_endian do + it_behaves_like :array_pack_double_be, 'd' + end +end diff --git a/spec/ruby/core/array/pack/e_spec.rb b/spec/ruby/core/array/pack/e_spec.rb new file mode 100644 index 0000000000..9c6a1b5485 --- /dev/null +++ b/spec/ruby/core/array/pack/e_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/float', __FILE__) + +describe "Array#pack with format 'E'" do + it_behaves_like :array_pack_basic, 'E' + it_behaves_like :array_pack_basic_float, 'E' + it_behaves_like :array_pack_arguments, 'E' + it_behaves_like :array_pack_no_platform, 'E' + it_behaves_like :array_pack_numeric_basic, 'E' + it_behaves_like :array_pack_float, 'E' + it_behaves_like :array_pack_double_le, 'E' +end + +describe "Array#pack with format 'e'" do + it_behaves_like :array_pack_basic, 'e' + it_behaves_like :array_pack_basic_float, 'e' + it_behaves_like :array_pack_arguments, 'e' + it_behaves_like :array_pack_no_platform, 'e' + it_behaves_like :array_pack_numeric_basic, 'e' + it_behaves_like :array_pack_float, 'e' + it_behaves_like :array_pack_float_le, 'e' +end diff --git a/spec/ruby/core/array/pack/empty_spec.rb b/spec/ruby/core/array/pack/empty_spec.rb new file mode 100644 index 0000000000..701e20b0af --- /dev/null +++ b/spec/ruby/core/array/pack/empty_spec.rb @@ -0,0 +1,11 @@ +require File.expand_path('../../../../spec_helper', __FILE__) + +describe "Array#pack with empty format" do + it "returns an empty String" do + [1, 2, 3].pack("").should == "" + end + + it "returns a String with US-ASCII encoding" do + [1, 2, 3].pack("").encoding.should == Encoding::US_ASCII + end +end diff --git a/spec/ruby/core/array/pack/f_spec.rb b/spec/ruby/core/array/pack/f_spec.rb new file mode 100644 index 0000000000..94ce57f34d --- /dev/null +++ b/spec/ruby/core/array/pack/f_spec.rb @@ -0,0 +1,39 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/float', __FILE__) + +describe "Array#pack with format 'F'" do + it_behaves_like :array_pack_basic, 'F' + it_behaves_like :array_pack_basic_float, 'F' + it_behaves_like :array_pack_arguments, 'F' + it_behaves_like :array_pack_no_platform, 'F' + it_behaves_like :array_pack_numeric_basic, 'F' + it_behaves_like :array_pack_float, 'F' + + little_endian do + it_behaves_like :array_pack_float_le, 'F' + end + + big_endian do + it_behaves_like :array_pack_float_be, 'F' + end +end + +describe "Array#pack with format 'f'" do + it_behaves_like :array_pack_basic, 'f' + it_behaves_like :array_pack_basic_float, 'f' + it_behaves_like :array_pack_arguments, 'f' + it_behaves_like :array_pack_no_platform, 'f' + it_behaves_like :array_pack_numeric_basic, 'f' + it_behaves_like :array_pack_float, 'f' + + little_endian do + it_behaves_like :array_pack_float_le, 'f' + end + + big_endian do + it_behaves_like :array_pack_float_be, 'f' + end +end diff --git a/spec/ruby/core/array/pack/g_spec.rb b/spec/ruby/core/array/pack/g_spec.rb new file mode 100644 index 0000000000..a0a902ebbe --- /dev/null +++ b/spec/ruby/core/array/pack/g_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/float', __FILE__) + +describe "Array#pack with format 'G'" do + it_behaves_like :array_pack_basic, 'G' + it_behaves_like :array_pack_basic_float, 'G' + it_behaves_like :array_pack_arguments, 'G' + it_behaves_like :array_pack_no_platform, 'G' + it_behaves_like :array_pack_numeric_basic, 'G' + it_behaves_like :array_pack_float, 'G' + it_behaves_like :array_pack_double_be, 'G' +end + +describe "Array#pack with format 'g'" do + it_behaves_like :array_pack_basic, 'g' + it_behaves_like :array_pack_basic_float, 'g' + it_behaves_like :array_pack_arguments, 'g' + it_behaves_like :array_pack_no_platform, 'g' + it_behaves_like :array_pack_numeric_basic, 'g' + it_behaves_like :array_pack_float, 'g' + it_behaves_like :array_pack_float_be, 'g' +end diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb new file mode 100644 index 0000000000..2412bf57c9 --- /dev/null +++ b/spec/ruby/core/array/pack/h_spec.rb @@ -0,0 +1,197 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/encodings', __FILE__) + +describe "Array#pack with format 'H'" do + it_behaves_like :array_pack_basic, 'H' + it_behaves_like :array_pack_basic_non_float, 'H' + it_behaves_like :array_pack_arguments, 'H' + it_behaves_like :array_pack_hex, 'H' + + it "calls #to_str to convert an Object to a String" do + obj = mock("pack H string") + obj.should_receive(:to_str).and_return("a") + [obj].pack("H").should == "\xa0" + end + + it "encodes the first character as the most significant nibble when passed no count modifier" do + ["ab"].pack("H").should == "\xa0" + end + + it "implicitly has count equal to the string length when passed the '*' modifier" do + ["deadbeef"].pack("H*").should == "\xde\xad\xbe\xef" + end + + it "encodes count nibbles when passed a count modifier exceeding the string length" do + ["ab"].pack('H8').should == "\xab\x00\x00\x00" + end + + it "encodes the first character as the most significant nibble of a hex value" do + [ [["0"], "\x00"], + [["1"], "\x10"], + [["2"], "\x20"], + [["3"], "\x30"], + [["4"], "\x40"], + [["5"], "\x50"], + [["6"], "\x60"], + [["7"], "\x70"], + [["8"], "\x80"], + [["9"], "\x90"], + [["a"], "\xa0"], + [["b"], "\xb0"], + [["c"], "\xc0"], + [["d"], "\xd0"], + [["e"], "\xe0"], + [["f"], "\xf0"], + [["A"], "\xa0"], + [["B"], "\xb0"], + [["C"], "\xc0"], + [["D"], "\xd0"], + [["E"], "\xe0"], + [["F"], "\xf0"] + ].should be_computed_by(:pack, "H") + end + + it "encodes the second character as the least significant nibble of a hex value" do + [ [["00"], "\x00"], + [["01"], "\x01"], + [["02"], "\x02"], + [["03"], "\x03"], + [["04"], "\x04"], + [["05"], "\x05"], + [["06"], "\x06"], + [["07"], "\x07"], + [["08"], "\x08"], + [["09"], "\x09"], + [["0a"], "\x0a"], + [["0b"], "\x0b"], + [["0c"], "\x0c"], + [["0d"], "\x0d"], + [["0e"], "\x0e"], + [["0f"], "\x0f"], + [["0A"], "\x0a"], + [["0B"], "\x0b"], + [["0C"], "\x0c"], + [["0D"], "\x0d"], + [["0E"], "\x0e"], + [["0F"], "\x0f"] + ].should be_computed_by(:pack, "H2") + end + + it "encodes the least significant nibble of a non alphanumeric character as the most significant nibble of the hex value" do + [ [["^"], "\xe0"], + [["*"], "\xa0"], + [["#"], "\x30"], + [["["], "\xb0"], + [["]"], "\xd0"], + [["@"], "\x00"], + [["!"], "\x10"], + [["H"], "\x10"], + [["O"], "\x80"], + [["T"], "\xd0"], + [["Z"], "\x30"], + ].should be_computed_by(:pack, "H") + end + + it "returns an ASCII-8BIT string" do + ["41"].pack("H").encoding.should == Encoding::ASCII_8BIT + end +end + +describe "Array#pack with format 'h'" do + it_behaves_like :array_pack_basic, 'h' + it_behaves_like :array_pack_basic_non_float, 'h' + it_behaves_like :array_pack_arguments, 'h' + it_behaves_like :array_pack_hex, 'h' + + it "calls #to_str to convert an Object to a String" do + obj = mock("pack H string") + obj.should_receive(:to_str).and_return("a") + [obj].pack("h").should == "\x0a" + end + + it "encodes the first character as the least significant nibble when passed no count modifier" do + ["ab"].pack("h").should == "\x0a" + end + + it "implicitly has count equal to the string length when passed the '*' modifier" do + ["deadbeef"].pack("h*").should == "\xed\xda\xeb\xfe" + end + + it "encodes count nibbles when passed a count modifier exceeding the string length" do + ["ab"].pack('h8').should == "\xba\x00\x00\x00" + end + + it "encodes the first character as the least significant nibble of a hex value" do + [ [["0"], "\x00"], + [["1"], "\x01"], + [["2"], "\x02"], + [["3"], "\x03"], + [["4"], "\x04"], + [["5"], "\x05"], + [["6"], "\x06"], + [["7"], "\x07"], + [["8"], "\x08"], + [["9"], "\x09"], + [["a"], "\x0a"], + [["b"], "\x0b"], + [["c"], "\x0c"], + [["d"], "\x0d"], + [["e"], "\x0e"], + [["f"], "\x0f"], + [["A"], "\x0a"], + [["B"], "\x0b"], + [["C"], "\x0c"], + [["D"], "\x0d"], + [["E"], "\x0e"], + [["F"], "\x0f"] + ].should be_computed_by(:pack, "h") + end + + it "encodes the second character as the most significant nibble of a hex value" do + [ [["00"], "\x00"], + [["01"], "\x10"], + [["02"], "\x20"], + [["03"], "\x30"], + [["04"], "\x40"], + [["05"], "\x50"], + [["06"], "\x60"], + [["07"], "\x70"], + [["08"], "\x80"], + [["09"], "\x90"], + [["0a"], "\xa0"], + [["0b"], "\xb0"], + [["0c"], "\xc0"], + [["0d"], "\xd0"], + [["0e"], "\xe0"], + [["0f"], "\xf0"], + [["0A"], "\xa0"], + [["0B"], "\xb0"], + [["0C"], "\xc0"], + [["0D"], "\xd0"], + [["0E"], "\xe0"], + [["0F"], "\xf0"] + ].should be_computed_by(:pack, "h2") + end + + it "encodes the least significant nibble of a non alphanumeric character as the least significant nibble of the hex value" do + [ [["^"], "\x0e"], + [["*"], "\x0a"], + [["#"], "\x03"], + [["["], "\x0b"], + [["]"], "\x0d"], + [["@"], "\x00"], + [["!"], "\x01"], + [["H"], "\x01"], + [["O"], "\x08"], + [["T"], "\x0d"], + [["Z"], "\x03"], + ].should be_computed_by(:pack, "h") + end + + it "returns an ASCII-8BIT string" do + ["41"].pack("h").encoding.should == Encoding::ASCII_8BIT + end +end diff --git a/spec/ruby/core/array/pack/i_spec.rb b/spec/ruby/core/array/pack/i_spec.rb new file mode 100644 index 0000000000..c22f367a65 --- /dev/null +++ b/spec/ruby/core/array/pack/i_spec.rb @@ -0,0 +1,133 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'I'" do + it_behaves_like :array_pack_basic, 'I' + it_behaves_like :array_pack_basic_non_float, 'I' + it_behaves_like :array_pack_arguments, 'I' + it_behaves_like :array_pack_numeric_basic, 'I' + it_behaves_like :array_pack_integer, 'I' +end + +describe "Array#pack with format 'i'" do + it_behaves_like :array_pack_basic, 'i' + it_behaves_like :array_pack_basic_non_float, 'i' + it_behaves_like :array_pack_arguments, 'i' + it_behaves_like :array_pack_numeric_basic, 'i' + it_behaves_like :array_pack_integer, 'i' +end + +describe "Array#pack with format 'I'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_32bit_le, 'I<' + end + + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'I<_' + it_behaves_like :array_pack_32bit_le, 'I_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'I<!' + it_behaves_like :array_pack_32bit_le, 'I!<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_32bit_be, 'I>' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'I>_' + it_behaves_like :array_pack_32bit_be, 'I_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'I>!' + it_behaves_like :array_pack_32bit_be, 'I!>' + end +end + +describe "Array#pack with format 'i'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_32bit_le, 'i<' + end + + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'i<_' + it_behaves_like :array_pack_32bit_le, 'i_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'i<!' + it_behaves_like :array_pack_32bit_le, 'i!<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_32bit_be, 'i>' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'i>_' + it_behaves_like :array_pack_32bit_be, 'i_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'i>!' + it_behaves_like :array_pack_32bit_be, 'i!>' + end +end + +little_endian do + describe "Array#pack with format 'I'" do + it_behaves_like :array_pack_32bit_le, 'I' + end + + describe "Array#pack with format 'I' with modifier '_'" do + it_behaves_like :array_pack_32bit_le_platform, 'I_' + end + + describe "Array#pack with format 'I' with modifier '!'" do + it_behaves_like :array_pack_32bit_le_platform, 'I!' + end + + describe "Array#pack with format 'i'" do + it_behaves_like :array_pack_32bit_le, 'i' + end + + describe "Array#pack with format 'i' with modifier '_'" do + it_behaves_like :array_pack_32bit_le_platform, 'i_' + end + + describe "Array#pack with format 'i' with modifier '!'" do + it_behaves_like :array_pack_32bit_le_platform, 'i!' + end +end + +big_endian do + describe "Array#pack with format 'I'" do + it_behaves_like :array_pack_32bit_be, 'I' + end + + describe "Array#pack with format 'I' with modifier '_'" do + it_behaves_like :array_pack_32bit_be_platform, 'I_' + end + + describe "Array#pack with format 'I' with modifier '!'" do + it_behaves_like :array_pack_32bit_be_platform, 'I!' + end + + describe "Array#pack with format 'i'" do + it_behaves_like :array_pack_32bit_be, 'i' + end + + describe "Array#pack with format 'i' with modifier '_'" do + it_behaves_like :array_pack_32bit_be_platform, 'i_' + end + + describe "Array#pack with format 'i' with modifier '!'" do + it_behaves_like :array_pack_32bit_be_platform, 'i!' + end +end diff --git a/spec/ruby/core/array/pack/j_spec.rb b/spec/ruby/core/array/pack/j_spec.rb new file mode 100644 index 0000000000..88f074724c --- /dev/null +++ b/spec/ruby/core/array/pack/j_spec.rb @@ -0,0 +1,222 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +ruby_version_is '2.3' do + # To handle the special case of x64-mingw32 + pointer_size = RUBY_PLATFORM =~ /\bx64\b/ ? 64 : 1.size * 8 + + guard -> { pointer_size == 64 } do + describe "Array#pack with format 'J'" do + it_behaves_like :array_pack_basic, 'J' + it_behaves_like :array_pack_basic_non_float, 'J' + it_behaves_like :array_pack_arguments, 'J' + it_behaves_like :array_pack_numeric_basic, 'J' + it_behaves_like :array_pack_integer, 'J' + end + + describe "Array#pack with format 'j'" do + it_behaves_like :array_pack_basic, 'j' + it_behaves_like :array_pack_basic_non_float, 'j' + it_behaves_like :array_pack_arguments, 'j' + it_behaves_like :array_pack_numeric_basic, 'j' + it_behaves_like :array_pack_integer, 'j' + end + + little_endian do + describe "Array#pack with format 'J'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_64bit_le, 'J_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_64bit_le, 'J!' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_64bit_le, 'j_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_64bit_le, 'j!' + end + end + end + + big_endian do + describe "Array#pack with format 'J'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_64bit_be, 'J_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_64bit_be, 'J!' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_64bit_be, 'j_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_64bit_be, 'j!' + end + end + end + + describe "Array#pack with format 'J'" do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_64bit_le, 'J<_' + it_behaves_like :array_pack_64bit_le, 'J_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_64bit_le, 'J<!' + it_behaves_like :array_pack_64bit_le, 'J!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_64bit_be, 'J>_' + it_behaves_like :array_pack_64bit_be, 'J_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_64bit_be, 'J>!' + it_behaves_like :array_pack_64bit_be, 'J!>' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_64bit_le, 'j<_' + it_behaves_like :array_pack_64bit_le, 'j_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_64bit_le, 'j<!' + it_behaves_like :array_pack_64bit_le, 'j!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_64bit_be, 'j>_' + it_behaves_like :array_pack_64bit_be, 'j_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_64bit_be, 'j>!' + it_behaves_like :array_pack_64bit_be, 'j!>' + end + end + end + + guard -> { pointer_size == 32 } do + describe "Array#pack with format 'J'" do + it_behaves_like :array_pack_basic, 'J' + it_behaves_like :array_pack_basic_non_float, 'J' + it_behaves_like :array_pack_arguments, 'J' + it_behaves_like :array_pack_numeric_basic, 'J' + it_behaves_like :array_pack_integer, 'J' + end + + describe "Array#pack with format 'j'" do + it_behaves_like :array_pack_basic, 'j' + it_behaves_like :array_pack_basic_non_float, 'j' + it_behaves_like :array_pack_arguments, 'j' + it_behaves_like :array_pack_numeric_basic, 'j' + it_behaves_like :array_pack_integer, 'j' + end + + big_endian do + describe "Array#pack with format 'J'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_32bit_be, 'J_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_32bit_be, 'J!' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_32bit_be, 'j_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_32bit_be, 'j!' + end + end + end + + little_endian do + describe "Array#pack with format 'J'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_32bit_le, 'J_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_32bit_le, 'J!' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '_'" do + it_behaves_like :array_pack_32bit_le, 'j_' + end + + describe "with modifier '!'" do + it_behaves_like :array_pack_32bit_le, 'j!' + end + end + end + + describe "Array#pack with format 'J'" do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'J<_' + it_behaves_like :array_pack_32bit_le, 'J_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'J<!' + it_behaves_like :array_pack_32bit_le, 'J!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'J>_' + it_behaves_like :array_pack_32bit_be, 'J_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'J>!' + it_behaves_like :array_pack_32bit_be, 'J!>' + end + end + + describe "Array#pack with format 'j'" do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'j<_' + it_behaves_like :array_pack_32bit_le, 'j_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'j<!' + it_behaves_like :array_pack_32bit_le, 'j!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'j>_' + it_behaves_like :array_pack_32bit_be, 'j_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'j>!' + it_behaves_like :array_pack_32bit_be, 'j!>' + end + end + end +end diff --git a/spec/ruby/core/array/pack/l_spec.rb b/spec/ruby/core/array/pack/l_spec.rb new file mode 100644 index 0000000000..5c1ad21d12 --- /dev/null +++ b/spec/ruby/core/array/pack/l_spec.rb @@ -0,0 +1,221 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'L'" do + it_behaves_like :array_pack_basic, 'L' + it_behaves_like :array_pack_basic_non_float, 'L' + it_behaves_like :array_pack_arguments, 'L' + it_behaves_like :array_pack_numeric_basic, 'L' + it_behaves_like :array_pack_integer, 'L' +end + +describe "Array#pack with format 'l'" do + it_behaves_like :array_pack_basic, 'l' + it_behaves_like :array_pack_basic_non_float, 'l' + it_behaves_like :array_pack_arguments, 'l' + it_behaves_like :array_pack_numeric_basic, 'l' + it_behaves_like :array_pack_integer, 'l' +end + +describe "Array#pack with format 'L'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_32bit_le, 'L<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_32bit_be, 'L>' + end + + guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'L<_' + it_behaves_like :array_pack_32bit_le, 'L_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'L<!' + it_behaves_like :array_pack_32bit_le, 'L!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'L>_' + it_behaves_like :array_pack_32bit_be, 'L_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'L>!' + it_behaves_like :array_pack_32bit_be, 'L!>' + end + end + + guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_64bit_le, 'L<_' + it_behaves_like :array_pack_64bit_le, 'L_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_64bit_le, 'L<!' + it_behaves_like :array_pack_64bit_le, 'L!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_64bit_be, 'L>_' + it_behaves_like :array_pack_64bit_be, 'L_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_64bit_be, 'L>!' + it_behaves_like :array_pack_64bit_be, 'L!>' + end + end +end + +describe "Array#pack with format 'l'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_32bit_le, 'l<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_32bit_be, 'l>' + end + + guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_32bit_le, 'l<_' + it_behaves_like :array_pack_32bit_le, 'l_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_32bit_le, 'l<!' + it_behaves_like :array_pack_32bit_le, 'l!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_32bit_be, 'l>_' + it_behaves_like :array_pack_32bit_be, 'l_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_32bit_be, 'l>!' + it_behaves_like :array_pack_32bit_be, 'l!>' + end + end + + guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_64bit_le, 'l<_' + it_behaves_like :array_pack_64bit_le, 'l_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_64bit_le, 'l<!' + it_behaves_like :array_pack_64bit_le, 'l!<' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_64bit_be, 'l>_' + it_behaves_like :array_pack_64bit_be, 'l_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_64bit_be, 'l>!' + it_behaves_like :array_pack_64bit_be, 'l!>' + end + end +end + +little_endian do + describe "Array#pack with format 'L'" do + it_behaves_like :array_pack_32bit_le, 'L' + end + + describe "Array#pack with format 'l'" do + it_behaves_like :array_pack_32bit_le, 'l' + end + + guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do + describe "Array#pack with format 'L' with modifier '_'" do + it_behaves_like :array_pack_32bit_le, 'L_' + end + + describe "Array#pack with format 'L' with modifier '!'" do + it_behaves_like :array_pack_32bit_le, 'L!' + end + + describe "Array#pack with format 'l' with modifier '_'" do + it_behaves_like :array_pack_32bit_le, 'l_' + end + + describe "Array#pack with format 'l' with modifier '!'" do + it_behaves_like :array_pack_32bit_le, 'l!' + end + end + + guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do + describe "Array#pack with format 'L' with modifier '_'" do + it_behaves_like :array_pack_64bit_le, 'L_' + end + + describe "Array#pack with format 'L' with modifier '!'" do + it_behaves_like :array_pack_64bit_le, 'L!' + end + + describe "Array#pack with format 'l' with modifier '_'" do + it_behaves_like :array_pack_64bit_le, 'l_' + end + + describe "Array#pack with format 'l' with modifier '!'" do + it_behaves_like :array_pack_64bit_le, 'l!' + end + end +end + +big_endian do + describe "Array#pack with format 'L'" do + it_behaves_like :array_pack_32bit_be, 'L' + end + + describe "Array#pack with format 'l'" do + it_behaves_like :array_pack_32bit_be, 'l' + end + + guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do + describe "Array#pack with format 'L' with modifier '_'" do + it_behaves_like :array_pack_32bit_be, 'L_' + end + + describe "Array#pack with format 'L' with modifier '!'" do + it_behaves_like :array_pack_32bit_be, 'L!' + end + + describe "Array#pack with format 'l' with modifier '_'" do + it_behaves_like :array_pack_32bit_be, 'l_' + end + + describe "Array#pack with format 'l' with modifier '!'" do + it_behaves_like :array_pack_32bit_be, 'l!' + end + end + + guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do + describe "Array#pack with format 'L' with modifier '_'" do + it_behaves_like :array_pack_64bit_be, 'L_' + end + + describe "Array#pack with format 'L' with modifier '!'" do + it_behaves_like :array_pack_64bit_be, 'L!' + end + + describe "Array#pack with format 'l' with modifier '_'" do + it_behaves_like :array_pack_64bit_be, 'l_' + end + + describe "Array#pack with format 'l' with modifier '!'" do + it_behaves_like :array_pack_64bit_be, 'l!' + end + end +end diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb new file mode 100644 index 0000000000..36d996cba6 --- /dev/null +++ b/spec/ruby/core/array/pack/m_spec.rb @@ -0,0 +1,306 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) + +describe "Array#pack with format 'M'" do + it_behaves_like :array_pack_basic, 'M' + it_behaves_like :array_pack_basic_non_float, 'M' + it_behaves_like :array_pack_arguments, 'M' + + it "encodes an empty string as an empty string" do + [""].pack("M").should == "" + end + + it "encodes nil as an empty string" do + [nil].pack("M").should == "" + end + + it "appends a soft line break at the end of an encoded string" do + ["a"].pack("M").should == "a=\n" + end + + it "does not append a soft break if the string ends with a newline" do + ["a\n"].pack("M").should == "a\n" + end + + it "encodes one element for each directive" do + ["a", "b", "c"].pack("MM").should == "a=\nb=\n" + end + + it "encodes byte values 33..60 directly" do + [ [["!\"\#$%&'()*+,-./"], "!\"\#$%&'()*+,-./=\n"], + [["0123456789"], "0123456789=\n"], + [[":;<"], ":;<=\n"] + ].should be_computed_by(:pack, "M") + end + + it "encodes byte values 62..126 directly" do + [ [[">?@"], ">?@=\n"], + [["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], "ABCDEFGHIJKLMNOPQRSTUVWXYZ=\n"], + [["[\\]^_`"], "[\\]^_`=\n"], + [["abcdefghijklmnopqrstuvwxyz"], "abcdefghijklmnopqrstuvwxyz=\n"], + [["{|}~"], "{|}~=\n"] + ].should be_computed_by(:pack, "M") + end + + it "encodes an '=' character in hex format" do + ["="].pack("M").should == "=3D=\n" + end + + it "encodes an embedded space directly" do + ["a b"].pack("M").should == "a b=\n" + end + + it "encodes a space at the end of the string directly" do + ["a "].pack("M").should == "a =\n" + end + + it "encodes an embedded tab directly" do + ["a\tb"].pack("M").should == "a\tb=\n" + end + + it "encodes a tab at the end of the string directly" do + ["a\t"].pack("M").should == "a\t=\n" + end + + it "encodes an embedded newline directly" do + ["a\nb"].pack("M").should == "a\nb=\n" + end + + it "encodes 0..31 except tab and newline in hex format" do + [ [["\x00\x01\x02\x03\x04\x05\x06"], "=00=01=02=03=04=05=06=\n"], + [["\a\b\v\f\r"], "=07=08=0B=0C=0D=\n"], + [["\x0e\x0f\x10\x11\x12\x13\x14"], "=0E=0F=10=11=12=13=14=\n"], + [["\x15\x16\x17\x18\x19\x1a"], "=15=16=17=18=19=1A=\n"], + [["\e"], "=1B=\n"], + [["\x1c\x1d\x1e\x1f"], "=1C=1D=1E=1F=\n"] + ].should be_computed_by(:pack, "M") + end + + it "encodes a tab followed by a newline with an encoded newline" do + ["\t\n"].pack("M").should == "\t=\n\n" + end + + it "encodes 127..255 in hex format" do + [ [["\x7f\x80\x81\x82\x83\x84\x85\x86"], "=7F=80=81=82=83=84=85=86=\n"], + [["\x87\x88\x89\x8a\x8b\x8c\x8d\x8e"], "=87=88=89=8A=8B=8C=8D=8E=\n"], + [["\x8f\x90\x91\x92\x93\x94\x95\x96"], "=8F=90=91=92=93=94=95=96=\n"], + [["\x97\x98\x99\x9a\x9b\x9c\x9d\x9e"], "=97=98=99=9A=9B=9C=9D=9E=\n"], + [["\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6"], "=9F=A0=A1=A2=A3=A4=A5=A6=\n"], + [["\xa7\xa8\xa9\xaa\xab\xac\xad\xae"], "=A7=A8=A9=AA=AB=AC=AD=AE=\n"], + [["\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6"], "=AF=B0=B1=B2=B3=B4=B5=B6=\n"], + [["\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe"], "=B7=B8=B9=BA=BB=BC=BD=BE=\n"], + [["\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"], "=BF=C0=C1=C2=C3=C4=C5=C6=\n"], + [["\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce"], "=C7=C8=C9=CA=CB=CC=CD=CE=\n"], + [["\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6"], "=CF=D0=D1=D2=D3=D4=D5=D6=\n"], + [["\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde"], "=D7=D8=D9=DA=DB=DC=DD=DE=\n"], + [["\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6"], "=DF=E0=E1=E2=E3=E4=E5=E6=\n"], + [["\xe7\xe8\xe9\xea\xeb\xec\xed\xee"], "=E7=E8=E9=EA=EB=EC=ED=EE=\n"], + [["\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6"], "=EF=F0=F1=F2=F3=F4=F5=F6=\n"], + [["\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"], "=F7=F8=F9=FA=FB=FC=FD=FE=\n"], + [["\xff"], "=FF=\n"] + ].should be_computed_by(:pack, "M") + end + + it "emits a soft line break when the output exceeds 72 characters when passed '*', 0, 1, or no count modifier" do + s1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + r1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=\na=\n" + s2 = "\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19" + r2 = "=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=\n=19=\n" + s3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x15a" + r3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=15=\na=\n" + s4 = "\x15aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x15a" + r4 = "=15aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=\na=15a=\n" + + [ [[s1], "M", r1], + [[s1], "M0", r1], + [[s1], "M1", r1], + [[s2], "M", r2], + [[s2], "M0", r2], + [[s2], "M1", r2], + [[s3], "M", r3], + [[s3], "M0", r3], + [[s3], "M1", r3], + [[s4], "M", r4], + [[s4], "M0", r4], + [[s4], "M1", r4] + ].should be_computed_by(:pack) + end + + it "emits a soft line break when the output exceeds count characters" do + [ [["abcdefghi"], "M2", "abc=\ndef=\nghi=\n"], + [["abcdefghi"], "M3", "abcd=\nefgh=\ni=\n"], + [["abcdefghi"], "M4", "abcde=\nfghi=\n"], + [["abcdefghi"], "M5", "abcdef=\nghi=\n"], + [["abcdefghi"], "M6", "abcdefg=\nhi=\n"], + [["\x19\x19\x19\x19"], "M2", "=19=\n=19=\n=19=\n=19=\n"], + [["\x19\x19\x19\x19"], "M3", "=19=19=\n=19=19=\n"], + [["\x19\x19\x19\x19"], "M4", "=19=19=\n=19=19=\n"], + [["\x19\x19\x19\x19"], "M5", "=19=19=\n=19=19=\n"], + [["\x19\x19\x19\x19"], "M6", "=19=19=19=\n=19=\n"], + [["\x19\x19\x19\x19"], "M7", "=19=19=19=\n=19=\n"] + ].should be_computed_by(:pack) + end + + it "encodes a recursive array" do + empty = ArraySpecs.empty_recursive_array + empty.pack('M').should be_an_instance_of(String) + + array = ArraySpecs.recursive_array + array.pack('M').should == "1=\n" + end + + it "calls #to_s to convert an object to a String" do + obj = mock("pack M string") + obj.should_receive(:to_s).and_return("packing") + + [obj].pack("M").should == "packing=\n" + end + + it "converts the object to a String representation if #to_s does not return a String" do + obj = mock("pack M non-string") + obj.should_receive(:to_s).and_return(2) + + [obj].pack("M").should be_an_instance_of(String) + end + + it "encodes a Symbol as a String" do + [:symbol].pack("M").should == "symbol=\n" + end + + it "encodes an Integer as a String" do + [ [[1], "1=\n"], + [[bignum_value], "#{bignum_value}=\n"] + ].should be_computed_by(:pack, "M") + end + + it "encodes a Float as a String" do + [1.0].pack("M").should == "1.0=\n" + end + + it "converts Floats to the minimum unique representation" do + [1.0 / 3.0].pack("M").should == "0.3333333333333333=\n" + end + + it "sets the output string to US-ASCII encoding" do + ["abcd"].pack("M").encoding.should == Encoding::US_ASCII + end +end + +describe "Array#pack with format 'm'" do + it_behaves_like :array_pack_basic, 'm' + it_behaves_like :array_pack_basic_non_float, 'm' + it_behaves_like :array_pack_arguments, 'm' + + it "encodes an empty string as an empty string" do + [""].pack("m").should == "" + end + + it "appends a newline to the end of the encoded string" do + ["a"].pack("m").should == "YQ==\n" + end + + it "encodes one element per directive" do + ["abc", "DEF"].pack("mm").should == "YWJj\nREVG\n" + end + + it "encodes 1, 2, or 3 characters in 4 output characters (Base64 encoding)" do + [ [["a"], "YQ==\n"], + [["ab"], "YWI=\n"], + [["abc"], "YWJj\n"], + [["abcd"], "YWJjZA==\n"], + [["abcde"], "YWJjZGU=\n"], + [["abcdef"], "YWJjZGVm\n"], + [["abcdefg"], "YWJjZGVmZw==\n"], + ].should be_computed_by(:pack, "m") + end + + it "emits a newline after complete groups of count / 3 input characters when passed a count modifier" do + ["abcdefg"].pack("m3").should == "YWJj\nZGVm\nZw==\n" + end + + it "implicitly has a count of 45 when passed '*', 1, 2 or no count modifier" do + s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + r = "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\nYWFhYWE=\n" + [ [[s], "m", r], + [[s], "m*", r], + [[s], "m1", r], + [[s], "m2", r], + ].should be_computed_by(:pack) + end + + it "encodes all ascii characters" do + [ [["\x00\x01\x02\x03\x04\x05\x06"], "AAECAwQFBg==\n"], + [["\a\b\t\n\v\f\r"], "BwgJCgsMDQ==\n"], + [["\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"], "Dg8QERITFBUW\n"], + [["\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f"], "FxgZGhscHR4f\n"], + [["!\"\#$%&'()*+,-./"], "ISIjJCUmJygpKissLS4v\n"], + [["0123456789"], "MDEyMzQ1Njc4OQ==\n"], + [[":;<=>?@"], "Ojs8PT4/QA==\n"], + [["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\n"], + [["[\\]^_`"], "W1xdXl9g\n"], + [["abcdefghijklmnopqrstuvwxyz"], "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\n"], + [["{|}~"], "e3x9fg==\n"], + [["\x7f\xc2\x80\xc2\x81\xc2\x82\xc2\x83"], "f8KAwoHCgsKD\n"], + [["\xc2\x84\xc2\x85\xc2\x86\xc2\x87\xc2"], "woTChcKGwofC\n"], + [["\x88\xc2\x89\xc2\x8a\xc2\x8b\xc2\x8c"], "iMKJworCi8KM\n"], + [["\xc2\x8d\xc2\x8e\xc2\x8f\xc2\x90\xc2"], "wo3CjsKPwpDC\n"], + [["\x91\xc2\x92\xc2\x93\xc2\x94\xc2\x95"], "kcKSwpPClMKV\n"], + [["\xc2\x96\xc2\x97\xc2\x98\xc2\x99\xc2"], "wpbCl8KYwpnC\n"], + [["\x9a\xc2\x9b\xc2\x9c\xc2\x9d\xc2\x9e"], "msKbwpzCncKe\n"], + [["\xc2\x9f\xc2\xa0\xc2\xa1\xc2\xa2\xc2"], "wp/CoMKhwqLC\n"], + [["\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7"], "o8KkwqXCpsKn\n"], + [["\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2"], "wqjCqcKqwqvC\n"], + [["\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0"], "rMKtwq7Cr8Kw\n"], + [["\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2"], "wrHCssKzwrTC\n"], + [["\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9"], "tcK2wrfCuMK5\n"], + [["\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2"], "wrrCu8K8wr3C\n"], + [["\xbe\xc2\xbf\xc3\x80\xc3\x81\xc3\x82"], "vsK/w4DDgcOC\n"], + [["\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3"], "w4PDhMOFw4bD\n"], + [["\x87\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b"], "h8OIw4nDisOL\n"], + [["\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3"], "w4zDjcOOw4/D\n"], + [["\x90\xc3\x91\xc3\x92\xc3\x93\xc3\x94"], "kMORw5LDk8OU\n"], + [["\xc3\x95\xc3\x96\xc3\x97\xc3\x98\xc3"], "w5XDlsOXw5jD\n"], + [["\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d"], "mcOaw5vDnMOd\n"], + [["\xc3\x9e\xc3\x9f\xc3\xa0\xc3\xa1\xc3"], "w57Dn8Ogw6HD\n"], + [["\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6"], "osOjw6TDpcOm\n"], + [["\xc3\xa7\xc3\xa8\xc3\xa9\xc3\xaa\xc3"], "w6fDqMOpw6rD\n"], + [["\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf"], "q8Osw63DrsOv\n"], + [["\xc3\xb0\xc3\xb1\xc3\xb2\xc3\xb3\xc3"], "w7DDscOyw7PD\n"], + [["\xb4\xc3\xb5\xc3\xb6\xc3\xb7\xc3\xb8"], "tMO1w7bDt8O4\n"], + [["\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3"], "w7nDusO7w7zD\n"], + [["\xbd\xc3\xbe\xc3\xbf"], "vcO+w78=\n"] + ].should be_computed_by(:pack, "m") + end + + it "calls #to_str to convert an object to a String" do + obj = mock("pack m string") + obj.should_receive(:to_str).and_return("abc") + [obj].pack("m").should == "YWJj\n" + end + + it "raises a TypeError if #to_str does not return a String" do + obj = mock("pack m non-string") + lambda { [obj].pack("m") }.should raise_error(TypeError) + end + + it "raises a TypeError if passed nil" do + lambda { [nil].pack("m") }.should raise_error(TypeError) + end + + it "raises a TypeError if passed an Integer" do + lambda { [0].pack("m") }.should raise_error(TypeError) + lambda { [bignum_value].pack("m") }.should raise_error(TypeError) + end + + it "does not emit a newline if passed zero as the count modifier" do + s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + r = "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE=" + [s].pack("m0").should == r + end + + it "sets the output string to US-ASCII encoding" do + ["abcd"].pack("m").encoding.should == Encoding::US_ASCII + end +end diff --git a/spec/ruby/core/array/pack/n_spec.rb b/spec/ruby/core/array/pack/n_spec.rb new file mode 100644 index 0000000000..72a83e082b --- /dev/null +++ b/spec/ruby/core/array/pack/n_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'N'" do + it_behaves_like :array_pack_basic, 'N' + it_behaves_like :array_pack_basic_non_float, 'N' + it_behaves_like :array_pack_arguments, 'N' + it_behaves_like :array_pack_numeric_basic, 'N' + it_behaves_like :array_pack_integer, 'N' + it_behaves_like :array_pack_no_platform, 'N' + it_behaves_like :array_pack_32bit_be, 'N' +end + +describe "Array#pack with format 'n'" do + it_behaves_like :array_pack_basic, 'n' + it_behaves_like :array_pack_basic_non_float, 'n' + it_behaves_like :array_pack_arguments, 'n' + it_behaves_like :array_pack_numeric_basic, 'n' + it_behaves_like :array_pack_integer, 'n' + it_behaves_like :array_pack_no_platform, 'n' + it_behaves_like :array_pack_16bit_be, 'n' +end diff --git a/spec/ruby/core/array/pack/p_spec.rb b/spec/ruby/core/array/pack/p_spec.rb new file mode 100644 index 0000000000..65a08281e2 --- /dev/null +++ b/spec/ruby/core/array/pack/p_spec.rb @@ -0,0 +1,11 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) + +describe "Array#pack with format 'P'" do + it_behaves_like :array_pack_basic_non_float, 'P' +end + +describe "Array#pack with format 'p'" do + it_behaves_like :array_pack_basic_non_float, 'p' +end diff --git a/spec/ruby/core/array/pack/percent_spec.rb b/spec/ruby/core/array/pack/percent_spec.rb new file mode 100644 index 0000000000..55d6de3424 --- /dev/null +++ b/spec/ruby/core/array/pack/percent_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../../spec_helper', __FILE__) + +describe "Array#pack with format '%'" do + it "raises an Argument Error" do + lambda { [1].pack("%") }.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/core/array/pack/q_spec.rb b/spec/ruby/core/array/pack/q_spec.rb new file mode 100644 index 0000000000..83e115c54a --- /dev/null +++ b/spec/ruby/core/array/pack/q_spec.rb @@ -0,0 +1,61 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'Q'" do + it_behaves_like :array_pack_basic, 'Q' + it_behaves_like :array_pack_basic_non_float, 'Q' + it_behaves_like :array_pack_arguments, 'Q' + it_behaves_like :array_pack_numeric_basic, 'Q' + it_behaves_like :array_pack_integer, 'Q' +end + +describe "Array#pack with format 'q'" do + it_behaves_like :array_pack_basic, 'q' + it_behaves_like :array_pack_basic_non_float, 'q' + it_behaves_like :array_pack_arguments, 'q' + it_behaves_like :array_pack_numeric_basic, 'q' + it_behaves_like :array_pack_integer, 'q' +end + +describe "Array#pack with format 'Q'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_64bit_le, 'Q<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_64bit_be, 'Q>' + end +end + +describe "Array#pack with format 'q'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_64bit_le, 'q<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_64bit_be, 'q>' + end +end + +little_endian do + describe "Array#pack with format 'Q'" do + it_behaves_like :array_pack_64bit_le, 'Q' + end + + describe "Array#pack with format 'q'" do + it_behaves_like :array_pack_64bit_le, 'q' + end +end + +big_endian do + describe "Array#pack with format 'Q'" do + it_behaves_like :array_pack_64bit_be, 'Q' + end + + describe "Array#pack with format 'q'" do + it_behaves_like :array_pack_64bit_be, 'q' + end +end diff --git a/spec/ruby/core/array/pack/s_spec.rb b/spec/ruby/core/array/pack/s_spec.rb new file mode 100644 index 0000000000..b2f8cb48f8 --- /dev/null +++ b/spec/ruby/core/array/pack/s_spec.rb @@ -0,0 +1,133 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'S'" do + it_behaves_like :array_pack_basic, 'S' + it_behaves_like :array_pack_basic_non_float, 'S' + it_behaves_like :array_pack_arguments, 'S' + it_behaves_like :array_pack_numeric_basic, 'S' + it_behaves_like :array_pack_integer, 'S' +end + +describe "Array#pack with format 's'" do + it_behaves_like :array_pack_basic, 's' + it_behaves_like :array_pack_basic_non_float, 's' + it_behaves_like :array_pack_arguments, 's' + it_behaves_like :array_pack_numeric_basic, 's' + it_behaves_like :array_pack_integer, 's' +end + +describe "Array#pack with format 'S'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_16bit_le, 'S<' + end + + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_16bit_le, 'S<_' + it_behaves_like :array_pack_16bit_le, 'S_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_16bit_le, 'S<!' + it_behaves_like :array_pack_16bit_le, 'S!<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_16bit_be, 'S>' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_16bit_be, 'S>_' + it_behaves_like :array_pack_16bit_be, 'S_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_16bit_be, 'S>!' + it_behaves_like :array_pack_16bit_be, 'S!>' + end +end + +describe "Array#pack with format 's'" do + describe "with modifier '<'" do + it_behaves_like :array_pack_16bit_le, 's<' + end + + describe "with modifier '<' and '_'" do + it_behaves_like :array_pack_16bit_le, 's<_' + it_behaves_like :array_pack_16bit_le, 's_<' + end + + describe "with modifier '<' and '!'" do + it_behaves_like :array_pack_16bit_le, 's<!' + it_behaves_like :array_pack_16bit_le, 's!<' + end + + describe "with modifier '>'" do + it_behaves_like :array_pack_16bit_be, 's>' + end + + describe "with modifier '>' and '_'" do + it_behaves_like :array_pack_16bit_be, 's>_' + it_behaves_like :array_pack_16bit_be, 's_>' + end + + describe "with modifier '>' and '!'" do + it_behaves_like :array_pack_16bit_be, 's>!' + it_behaves_like :array_pack_16bit_be, 's!>' + end +end + +little_endian do + describe "Array#pack with format 'S'" do + it_behaves_like :array_pack_16bit_le, 'S' + end + + describe "Array#pack with format 'S' with modifier '_'" do + it_behaves_like :array_pack_16bit_le, 'S_' + end + + describe "Array#pack with format 'S' with modifier '!'" do + it_behaves_like :array_pack_16bit_le, 'S!' + end + + describe "Array#pack with format 's'" do + it_behaves_like :array_pack_16bit_le, 's' + end + + describe "Array#pack with format 's' with modifier '_'" do + it_behaves_like :array_pack_16bit_le, 's_' + end + + describe "Array#pack with format 's' with modifier '!'" do + it_behaves_like :array_pack_16bit_le, 's!' + end +end + +big_endian do + describe "Array#pack with format 'S'" do + it_behaves_like :array_pack_16bit_be, 'S' + end + + describe "Array#pack with format 'S' with modifier '_'" do + it_behaves_like :array_pack_16bit_be, 'S_' + end + + describe "Array#pack with format 'S' with modifier '!'" do + it_behaves_like :array_pack_16bit_be, 'S!' + end + + describe "Array#pack with format 's'" do + it_behaves_like :array_pack_16bit_be, 's' + end + + describe "Array#pack with format 's' with modifier '_'" do + it_behaves_like :array_pack_16bit_be, 's_' + end + + describe "Array#pack with format 's' with modifier '!'" do + it_behaves_like :array_pack_16bit_be, 's!' + end +end diff --git a/spec/ruby/core/array/pack/shared/basic.rb b/spec/ruby/core/array/pack/shared/basic.rb new file mode 100644 index 0000000000..39ab15308d --- /dev/null +++ b/spec/ruby/core/array/pack/shared/basic.rb @@ -0,0 +1,65 @@ +describe :array_pack_arguments, shared: true do + it "raises an ArgumentError if there are fewer elements than the format requires" do + lambda { [].pack(pack_format(1)) }.should raise_error(ArgumentError) + end +end + +describe :array_pack_basic, shared: true do + before :each do + @obj = ArraySpecs.universal_pack_object + end + + it "raises a TypeError when passed nil" do + lambda { [@obj].pack(nil) }.should raise_error(TypeError) + end + + it "raises a TypeError when passed an Integer" do + lambda { [@obj].pack(1) }.should raise_error(TypeError) + end +end + +describe :array_pack_basic_non_float, shared: true do + before :each do + @obj = ArraySpecs.universal_pack_object + end + + it "ignores whitespace in the format string" do + [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String) + end + + it "calls #to_str to coerce the directives string" do + d = mock("pack directive") + d.should_receive(:to_str).and_return("x"+pack_format) + [@obj, @obj].pack(d).should be_an_instance_of(String) + end + + it "taints the output string if the format string is tainted" do + [@obj, @obj].pack("x"+pack_format.taint).tainted?.should be_true + end +end + +describe :array_pack_basic_float, shared: true do + it "ignores whitespace in the format string" do + [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String) + end + + it "calls #to_str to coerce the directives string" do + d = mock("pack directive") + d.should_receive(:to_str).and_return("x"+pack_format) + [1.2, 4.7].pack(d).should be_an_instance_of(String) + end + + it "taints the output string if the format string is tainted" do + [3.2, 2.8].pack("x"+pack_format.taint).tainted?.should be_true + end +end + +describe :array_pack_no_platform, shared: true do + it "raises ArgumentError when the format modifier is '_'" do + lambda{ [1].pack(pack_format("_")) }.should raise_error(ArgumentError) + end + + it "raises ArgumentError when the format modifier is '!'" do + lambda{ [1].pack(pack_format("!")) }.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/core/array/pack/shared/encodings.rb b/spec/ruby/core/array/pack/shared/encodings.rb new file mode 100644 index 0000000000..3724a5d859 --- /dev/null +++ b/spec/ruby/core/array/pack/shared/encodings.rb @@ -0,0 +1,16 @@ +describe :array_pack_hex, shared: true do + it "encodes no bytes when passed zero as the count modifier" do + ["abc"].pack(pack_format(0)).should == "" + end + + it "raises a TypeError if the object does not respond to #to_str" do + obj = mock("pack hex non-string") + lambda { [obj].pack(pack_format) }.should raise_error(TypeError) + end + + it "raises a TypeError if #to_str does not return a String" do + obj = mock("pack hex non-string") + obj.should_receive(:to_str).and_return(1) + lambda { [obj].pack(pack_format) }.should raise_error(TypeError) + end +end diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb new file mode 100644 index 0000000000..082de27acd --- /dev/null +++ b/spec/ruby/core/array/pack/shared/float.rb @@ -0,0 +1,249 @@ +# -*- encoding: ascii-8bit -*- + +describe :array_pack_float_le, shared: true do + it "encodes a positive Float" do + [1.42].pack(pack_format).should == "\x8f\xc2\xb5?" + end + + it "encodes a negative Float" do + [-34.2].pack(pack_format).should == "\xcd\xcc\x08\xc2" + end + + it "converts an Integer to a Float" do + [8].pack(pack_format).should == "\x00\x00\x00A" + end + + it "raises a TypeError if passed a String representation of a floating point number" do + lambda { ["13"].pack(pack_format) }.should raise_error(TypeError) + end + + it "encodes the number of array elements specified by the count modifier" do + [2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "\x9a\x999@33\xb3?" + end + + it "encodes all remaining elements when passed the '*' modifier" do + [2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A" + end + + it "ignores NULL bytes between directives" do + [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A" + end + + it "ignores spaces between directives" do + [5.3, 9.2].pack(pack_format(" ", 2)).should == "\x9a\x99\xa9@33\x13A" + end + + it "encodes positive Infinity" do + [infinity_value].pack(pack_format).should == "\x00\x00\x80\x7f" + end + + it "encodes negative Infinity" do + [-infinity_value].pack(pack_format).should == "\x00\x00\x80\xff" + end + + platform_is "86" do # x86 / x86_64 + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x00\x00\xc0\xff" + end + end + + platform_is "powerpc64" do + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x00\x00\xc0\x7f" + end + end + + it "encodes a positive Float outside the range of a single precision float" do + [1e150].pack(pack_format).should == "\x00\x00\x80\x7f" + end + + it "encodes a negative Float outside the range of a single precision float" do + [-1e150].pack(pack_format).should == "\x00\x00\x80\xff" + end +end + +describe :array_pack_float_be, shared: true do + it "encodes a positive Float" do + [1.42].pack(pack_format).should == "?\xb5\xc2\x8f" + end + + it "encodes a negative Float" do + [-34.2].pack(pack_format).should == "\xc2\x08\xcc\xcd" + end + + it "converts an Integer to a Float" do + [8].pack(pack_format).should == "A\x00\x00\x00" + end + + it "raises a TypeError if passed a String representation of a floating point number" do + lambda { ["13"].pack(pack_format) }.should raise_error(TypeError) + end + + it "encodes the number of array elements specified by the count modifier" do + [2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "@9\x99\x9a?\xb333" + end + + it "encodes all remaining elements when passed the '*' modifier" do + [2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333" + end + + it "ignores NULL bytes between directives" do + [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333" + end + + it "ignores spaces between directives" do + [5.3, 9.2].pack(pack_format(" ", 2)).should == "@\xa9\x99\x9aA\x1333" + end + + it "encodes positive Infinity" do + [infinity_value].pack(pack_format).should == "\x7f\x80\x00\x00" + end + + it "encodes negative Infinity" do + [-infinity_value].pack(pack_format).should == "\xff\x80\x00\x00" + end + + platform_is "86" do # x86 / x86_64 + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\xff\xc0\x00\x00" + end + end + + platform_is "powerpc64" do + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x7f\xc0\x00\x00" + end + end + + it "encodes a positive Float outside the range of a single precision float" do + [1e150].pack(pack_format).should == "\x7f\x80\x00\x00" + end + + it "encodes a negative Float outside the range of a single precision float" do + [-1e150].pack(pack_format).should == "\xff\x80\x00\x00" + end +end + +describe :array_pack_double_le, shared: true do + it "encodes a positive Float" do + [1.42].pack(pack_format).should == "\xb8\x1e\x85\xebQ\xb8\xf6?" + end + + it "encodes a negative Float" do + [-34.2].pack(pack_format).should == "\x9a\x99\x99\x99\x99\x19A\xc0" + end + + it "converts an Integer to a Float" do + [8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@" + end + + it "raises a TypeError if passed a String representation of a floating point number" do + lambda { ["13"].pack(pack_format) }.should raise_error(TypeError) + end + + it "encodes the number of array elements specified by the count modifier" do + [2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "333333\x07@ffffff\xf6?" + end + + it "encodes all remaining elements when passed the '*' modifier" do + [2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@" + end + + it "ignores NULL bytes between directives" do + [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@" + end + + it "ignores spaces between directives" do + [5.3, 9.2].pack(pack_format(" ", 2)).should == "333333\x15@ffffff\x22@" + end + + it "encodes positive Infinity" do + [infinity_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf0\x7f" + end + + it "encodes negative Infinity" do + [-infinity_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf0\xff" + end + + platform_is "86" do # x86 / x86_64 + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\xff" + end + end + + platform_is "powerpc64" do + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\x7f" + end + end + + it "encodes a positive Float outside the range of a single precision float" do + [1e150].pack(pack_format).should == "\xaf\x96P\x2e5\x8d\x13_" + end + + it "encodes a negative Float outside the range of a single precision float" do + [-1e150].pack(pack_format).should == "\xaf\x96P\x2e5\x8d\x13\xdf" + end +end + +describe :array_pack_double_be, shared: true do + it "encodes a positive Float" do + [1.42].pack(pack_format).should == "?\xf6\xb8Q\xeb\x85\x1e\xb8" + end + + it "encodes a negative Float" do + [-34.2].pack(pack_format).should == "\xc0A\x19\x99\x99\x99\x99\x9a" + end + + it "converts an Integer to a Float" do + [8].pack(pack_format).should == "@\x20\x00\x00\x00\x00\x00\x00" + end + + it "raises a TypeError if passed a String representation of a floating point number" do + lambda { ["13"].pack(pack_format) }.should raise_error(TypeError) + end + + it "encodes the number of array elements specified by the count modifier" do + [2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "@\x07333333?\xf6ffffff" + end + + it "encodes all remaining elements when passed the '*' modifier" do + [2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff" + end + + it "ignores NULL bytes between directives" do + [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff" + end + + it "ignores spaces between directives" do + [5.3, 9.2].pack(pack_format(" ", 2)).should == "@\x15333333@\x22ffffff" + end + + it "encodes positive Infinity" do + [infinity_value].pack(pack_format).should == "\x7f\xf0\x00\x00\x00\x00\x00\x00" + end + + it "encodes negative Infinity" do + [-infinity_value].pack(pack_format).should == "\xff\xf0\x00\x00\x00\x00\x00\x00" + end + + platform_is "86" do # x86 / x86_64 + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\xff\xf8\x00\x00\x00\x00\x00\x00" + end + end + + platform_is "powerpc64" do + it "encodes NaN" do + [nan_value].pack(pack_format).should == "\x7f\xf8\x00\x00\x00\x00\x00\x00" + end + end + + it "encodes a positive Float outside the range of a single precision float" do + [1e150].pack(pack_format).should == "_\x13\x8d5\x2eP\x96\xaf" + end + + it "encodes a negative Float outside the range of a single precision float" do + [-1e150].pack(pack_format).should == "\xdf\x13\x8d5\x2eP\x96\xaf" + end +end diff --git a/spec/ruby/core/array/pack/shared/integer.rb b/spec/ruby/core/array/pack/shared/integer.rb new file mode 100644 index 0000000000..0df03bbfd1 --- /dev/null +++ b/spec/ruby/core/array/pack/shared/integer.rb @@ -0,0 +1,381 @@ +# -*- encoding: ascii-8bit -*- + +describe :array_pack_16bit_le, shared: true do + it "encodes the least significant 16 bits of a positive number" do + [ [[0x0000_0021], "\x21\x00"], + [[0x0000_4321], "\x21\x43"], + [[0x0065_4321], "\x21\x43"], + [[0x7865_4321], "\x21\x43"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 16 bits of a negative number" do + [ [[-0x0000_0021], "\xdf\xff"], + [[-0x0000_4321], "\xdf\xbc"], + [[-0x0065_4321], "\xdf\xbc"], + [[-0x7865_4321], "\xdf\xbc"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[2019902241.2], "\x21\x43"], + [[2019902241.8], "\x21\x43"], + [[-2019902241.2], "\xdf\xbc"], + [[-2019902241.8], "\xdf\xbc"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678) + [obj].pack(pack_format()).should == "\x78\x56" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x78\x65\xcd\xab" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x78\x65\xcd\xab\x21\x43" + end + + it "ignores NULL bytes between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) + str.should == "\x78\x65\xcd\xab" + end + + it "ignores spaces between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) + str.should == "\x78\x65\xcd\xab" + end +end + +describe :array_pack_16bit_be, shared: true do + it "encodes the least significant 16 bits of a positive number" do + [ [[0x0000_0021], "\x00\x21"], + [[0x0000_4321], "\x43\x21"], + [[0x0065_4321], "\x43\x21"], + [[0x7865_4321], "\x43\x21"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 16 bits of a negative number" do + [ [[-0x0000_0021], "\xff\xdf"], + [[-0x0000_4321], "\xbc\xdf"], + [[-0x0065_4321], "\xbc\xdf"], + [[-0x7865_4321], "\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[2019902241.2], "\x43\x21"], + [[2019902241.8], "\x43\x21"], + [[-2019902241.2], "\xbc\xdf"], + [[-2019902241.8], "\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678) + [obj].pack(pack_format()).should == "\x56\x78" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x65\x78\xab\xcd" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x65\x78\xab\xcd\x43\x21" + end + + it "ignores NULL bytes between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) + str.should == "\x65\x78\xab\xcd" + end + + it "ignores spaces between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) + str.should == "\x65\x78\xab\xcd" + end +end + +describe :array_pack_32bit_le, shared: true do + it "encodes the least significant 32 bits of a positive number" do + [ [[0x0000_0021], "\x21\x00\x00\x00"], + [[0x0000_4321], "\x21\x43\x00\x00"], + [[0x0065_4321], "\x21\x43\x65\x00"], + [[0x7865_4321], "\x21\x43\x65\x78"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 32 bits of a negative number" do + [ [[-0x0000_0021], "\xdf\xff\xff\xff"], + [[-0x0000_4321], "\xdf\xbc\xff\xff"], + [[-0x0065_4321], "\xdf\xbc\x9a\xff"], + [[-0x7865_4321], "\xdf\xbc\x9a\x87"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[2019902241.2], "\x21\x43\x65\x78"], + [[2019902241.8], "\x21\x43\x65\x78"], + [[-2019902241.2], "\xdf\xbc\x9a\x87"], + [[-2019902241.8], "\xdf\xbc\x9a\x87"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678) + [obj].pack(pack_format()).should == "\x78\x56\x34\x12" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78" + end + + it "ignores NULL bytes between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde" + end + + it "ignores spaces between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde" + end +end + +describe :array_pack_32bit_be, shared: true do + it "encodes the least significant 32 bits of a positive number" do + [ [[0x0000_0021], "\x00\x00\x00\x21"], + [[0x0000_4321], "\x00\x00\x43\x21"], + [[0x0065_4321], "\x00\x65\x43\x21"], + [[0x7865_4321], "\x78\x65\x43\x21"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 32 bits of a negative number" do + [ [[-0x0000_0021], "\xff\xff\xff\xdf"], + [[-0x0000_4321], "\xff\xff\xbc\xdf"], + [[-0x0065_4321], "\xff\x9a\xbc\xdf"], + [[-0x7865_4321], "\x87\x9a\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[2019902241.2], "\x78\x65\x43\x21"], + [[2019902241.8], "\x78\x65\x43\x21"], + [[-2019902241.2], "\x87\x9a\xbc\xdf"], + [[-2019902241.8], "\x87\x9a\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678) + [obj].pack(pack_format()).should == "\x12\x34\x56\x78" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21" + end + + it "ignores NULL bytes between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd" + end + + it "ignores spaces between directives" do + str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd" + end +end + +describe :array_pack_32bit_le_platform, shared: true do + it "encodes the least significant 32 bits of a number" do + [ [[0x7865_4321], "\x21\x43\x65\x78"], + [[-0x7865_4321], "\xdf\xbc\x9a\x87"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78" + end + + platform_is wordsize: 64 do + it "encodes the least significant 32 bits of a number that is greater than 32 bits" do + [ [[0xff_7865_4321], "\x21\x43\x65\x78"], + [[-0xff_7865_4321], "\xdf\xbc\x9a\x87"] + ].should be_computed_by(:pack, pack_format()) + end + end +end + +describe :array_pack_32bit_be_platform, shared: true do + it "encodes the least significant 32 bits of a number" do + [ [[0x7865_4321], "\x78\x65\x43\x21"], + [[-0x7865_4321], "\x87\x9a\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2)) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*')) + str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21" + end + + platform_is wordsize: 64 do + it "encodes the least significant 32 bits of a number that is greater than 32 bits" do + [ [[0xff_7865_4321], "\x78\x65\x43\x21"], + [[-0xff_7865_4321], "\x87\x9a\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + end +end + +describe :array_pack_64bit_le, shared: true do + it "encodes the least significant 64 bits of a positive number" do + [ [[0x0000_0000_0000_0021], "\x21\x00\x00\x00\x00\x00\x00\x00"], + [[0x0000_0000_0000_4321], "\x21\x43\x00\x00\x00\x00\x00\x00"], + [[0x0000_0000_0065_4321], "\x21\x43\x65\x00\x00\x00\x00\x00"], + [[0x0000_0000_7865_4321], "\x21\x43\x65\x78\x00\x00\x00\x00"], + [[0x0000_0090_7865_4321], "\x21\x43\x65\x78\x90\x00\x00\x00"], + [[0x0000_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\x00\x00"], + [[0x00dc_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\xdc\x00"], + [[0x7edc_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\xdc\x7e"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 64 bits of a negative number" do + [ [[-0x0000_0000_0000_0021], "\xdf\xff\xff\xff\xff\xff\xff\xff"], + [[-0x0000_0000_0000_4321], "\xdf\xbc\xff\xff\xff\xff\xff\xff"], + [[-0x0000_0000_0065_4321], "\xdf\xbc\x9a\xff\xff\xff\xff\xff"], + [[-0x0000_0000_7865_4321], "\xdf\xbc\x9a\x87\xff\xff\xff\xff"], + [[-0x0000_0090_7865_4321], "\xdf\xbc\x9a\x87\x6f\xff\xff\xff"], + [[-0x0000_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\xff\xff"], + [[-0x00dc_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\x23\xff"], + [[-0x7edc_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\x23\x81"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[9.14138647331322368e+18], "\x00\x44\x65\x78\x90\xba\xdc\x7e"], + [[-9.14138647331322368e+18], "\x00\xbc\x9a\x87\x6f\x45\x23\x81"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678_90ab_cdef) + [obj].pack(pack_format()).should == "\xef\xcd\xab\x90\x78\x56\x34\x12" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1234_5678_90ab_cdef, + 0xdef0_abcd_3412_7856, + 0x7865_4321_dcba_def0].pack(pack_format(2)) + str.should == "\xef\xcd\xab\x90\x78\x56\x34\x12\x56\x78\x12\x34\xcd\xab\xf0\xde" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format('*')) + str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78" + end + + it "ignores NULL bytes between directives" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2)) + str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78" + end + + it "ignores spaces between directives" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2)) + str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78" + end +end + +describe :array_pack_64bit_be, shared: true do + it "encodes the least significant 64 bits of a positive number" do + [ [[0x0000_0000_0000_0021], "\x00\x00\x00\x00\x00\x00\x00\x21"], + [[0x0000_0000_0000_4321], "\x00\x00\x00\x00\x00\x00\x43\x21"], + [[0x0000_0000_0065_4321], "\x00\x00\x00\x00\x00\x65\x43\x21"], + [[0x0000_0000_7865_4321], "\x00\x00\x00\x00\x78\x65\x43\x21"], + [[0x0000_0090_7865_4321], "\x00\x00\x00\x90\x78\x65\x43\x21"], + [[0x0000_ba90_7865_4321], "\x00\x00\xba\x90\x78\x65\x43\x21"], + [[0x00dc_ba90_7865_4321], "\x00\xdc\xba\x90\x78\x65\x43\x21"], + [[0x7edc_ba90_7865_4321], "\x7e\xdc\xba\x90\x78\x65\x43\x21"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes the least significant 64 bits of a negative number" do + [ [[-0x0000_0000_0000_0021], "\xff\xff\xff\xff\xff\xff\xff\xdf"], + [[-0x0000_0000_0000_4321], "\xff\xff\xff\xff\xff\xff\xbc\xdf"], + [[-0x0000_0000_0065_4321], "\xff\xff\xff\xff\xff\x9a\xbc\xdf"], + [[-0x0000_0000_7865_4321], "\xff\xff\xff\xff\x87\x9a\xbc\xdf"], + [[-0x0000_0090_7865_4321], "\xff\xff\xff\x6f\x87\x9a\xbc\xdf"], + [[-0x0000_ba90_7865_4321], "\xff\xff\x45\x6f\x87\x9a\xbc\xdf"], + [[-0x00dc_ba90_7865_4321], "\xff\x23\x45\x6f\x87\x9a\xbc\xdf"], + [[-0x7edc_ba90_7865_4321], "\x81\x23\x45\x6f\x87\x9a\xbc\xdf"] + ].should be_computed_by(:pack, pack_format()) + end + + it "encodes a Float truncated as an Integer" do + [ [[9.14138647331322368e+18], "\x7e\xdc\xba\x90\x78\x65\x44\x00"], + [[-9.14138647331322368e+18], "\x81\x23\x45\x6f\x87\x9a\xbc\x00"] + ].should be_computed_by(:pack, pack_format()) + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(0x1234_5678_90ab_cdef) + [obj].pack(pack_format()).should == "\x12\x34\x56\x78\x90\xab\xcd\xef" + end + + it "encodes the number of array elements specified by the count modifier" do + str = [0x1234_5678_90ab_cdef, + 0xdef0_abcd_3412_7856, + 0x7865_4321_dcba_def0].pack(pack_format(2)) + str.should == "\x12\x34\x56\x78\x90\xab\xcd\xef\xde\xf0\xab\xcd\x34\x12\x78\x56" + end + + it "encodes all remaining elements when passed the '*' modifier" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format('*')) + str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0" + end + + it "ignores NULL bytes between directives" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2)) + str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0" + end + + it "ignores spaces between directives" do + str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2)) + str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0" + end +end diff --git a/spec/ruby/core/array/pack/shared/numeric_basic.rb b/spec/ruby/core/array/pack/shared/numeric_basic.rb new file mode 100644 index 0000000000..9224d6080e --- /dev/null +++ b/spec/ruby/core/array/pack/shared/numeric_basic.rb @@ -0,0 +1,44 @@ +describe :array_pack_numeric_basic, shared: true do + it "returns an empty String if count is zero" do + [1].pack(pack_format(0)).should == "" + end + + it "raises a TypeError when passed nil" do + lambda { [nil].pack(pack_format) }.should raise_error(TypeError) + end + + it "raises a TypeError when passed true" do + lambda { [true].pack(pack_format) }.should raise_error(TypeError) + end + + it "raises a TypeError when passed false" do + lambda { [false].pack(pack_format) }.should raise_error(TypeError) + end + + it "returns an ASCII-8BIT string" do + [0xFF].pack(pack_format).encoding.should == Encoding::ASCII_8BIT + [0xE3, 0x81, 0x82].pack(pack_format(3)).encoding.should == Encoding::ASCII_8BIT + end +end + +describe :array_pack_integer, shared: true do + it "raises a TypeError when the object does not respond to #to_int" do + obj = mock('not an integer') + lambda { [obj].pack(pack_format) }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a String" do + lambda { ["5"].pack(pack_format) }.should raise_error(TypeError) + end +end + +describe :array_pack_float, shared: true do + it "raises a TypeError if a String does not represent a floating point number" do + lambda { ["a"].pack(pack_format) }.should raise_error(TypeError) + end + + it "raises a TypeError when the object does not respond to #to_f" do + obj = mock('not an float') + lambda { [obj].pack(pack_format) }.should raise_error(TypeError) + end +end diff --git a/spec/ruby/core/array/pack/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb new file mode 100644 index 0000000000..cedb0886e2 --- /dev/null +++ b/spec/ruby/core/array/pack/shared/string.rb @@ -0,0 +1,80 @@ +# -*- encoding: binary -*- +describe :array_pack_string, shared: true do + it "adds count bytes of a String to the output" do + ["abc"].pack(pack_format(2)).should == "ab" + end + + it "implicitly has a count of one when no count is specified" do + ["abc"].pack(pack_format).should == "a" + end + + it "does not add any bytes when the count is zero" do + ["abc"].pack(pack_format(0)).should == "" + end + + it "is not affected by a previous count modifier" do + ["abcde", "defg"].pack(pack_format(3)+pack_format).should == "abcd" + end + + it "raises an ArgumentError when the Array is empty" do + lambda { [].pack(pack_format) }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when the Array has too few elements" do + lambda { ["a"].pack(pack_format(nil, 2)) }.should raise_error(ArgumentError) + end + + it "calls #to_str to convert the element to a String" do + obj = mock('pack string') + obj.should_receive(:to_str).and_return("abc") + + [obj].pack(pack_format).should == "a" + end + + it "raises a TypeError when the object does not respond to #to_str" do + obj = mock("not a string") + lambda { [obj].pack(pack_format) }.should raise_error(TypeError) + end + + it "returns a tainted string when a pack argument is tainted" do + ["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true + end + + it "does not return a tainted string when the array is tainted" do + ["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false + end + + it "returns a tainted string when the format is tainted" do + ["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true + end + + it "returns a tainted string when an empty format is tainted" do + ["abcd", 0x20].pack("".taint).tainted?.should be_true + end + + it "returns a untrusted string when the format is untrusted" do + ["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true + end + + it "returns a untrusted string when the empty format is untrusted" do + ["abcd", 0x20].pack("".untrust).untrusted?.should be_true + end + + it "returns a untrusted string when a pack argument is untrusted" do + ["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true + end + + it "returns a trusted string when the array is untrusted" do + ["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false + end + + it "returns a string in encoding of common to the concatenated results" do + f = pack_format("*") + [ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::ASCII_8BIT], + [["abcde\xd1", "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT], + [["a".force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT], + # under discussion [ruby-dev:37294] + [["\u{3042 3044 3046 3048}", 1].pack(f+"N"), Encoding::ASCII_8BIT] + ].should be_computed_by(:encoding) + end +end diff --git a/spec/ruby/core/array/pack/shared/unicode.rb b/spec/ruby/core/array/pack/shared/unicode.rb new file mode 100644 index 0000000000..e16110c491 --- /dev/null +++ b/spec/ruby/core/array/pack/shared/unicode.rb @@ -0,0 +1,94 @@ +# -*- encoding: utf-8 -*- + +describe :array_pack_unicode, shared: true do + it "encodes ASCII values as a Unicode codepoint" do + [ [[0], "\x00"], + [[1], "\x01"], + [[8], "\x08"], + [[15], "\x0f"], + [[24], "\x18"], + [[31], "\x1f"], + [[127], "\x7f"], + [[128], "\xc2\x80"], + [[129], "\xc2\x81"], + [[255], "\xc3\xbf"] + ].should be_computed_by(:pack, "U") + end + + it "encodes UTF-8 BMP codepoints" do + [ [[0x80], "\xc2\x80"], + [[0x7ff], "\xdf\xbf"], + [[0x800], "\xe0\xa0\x80"], + [[0xffff], "\xef\xbf\xbf"] + ].should be_computed_by(:pack, "U") + end + + it "constructs strings with valid encodings" do + str = [0x85].pack("U*") + str.should == "\xc2\x85" + str.valid_encoding?.should be_true + end + + it "encodes values larger than UTF-8 max codepoints" do + [ + [[0x00110000], [244, 144, 128, 128].pack('C*').force_encoding('utf-8')], + [[0x04000000], [252, 132, 128, 128, 128, 128].pack('C*').force_encoding('utf-8')], + [[0x7FFFFFFF], [253, 191, 191, 191, 191, 191].pack('C*').force_encoding('utf-8')] + ].should be_computed_by(:pack, "U") + end + + it "encodes UTF-8 max codepoints" do + [ [[0x10000], "\xf0\x90\x80\x80"], + [[0xfffff], "\xf3\xbf\xbf\xbf"], + [[0x100000], "\xf4\x80\x80\x80"], + [[0x10ffff], "\xf4\x8f\xbf\xbf"] + ].should be_computed_by(:pack, "U") + end + + it "encodes the number of array elements specified by the count modifier" do + [ [[0x41, 0x42, 0x43, 0x44], "U2", "\x41\x42"], + [[0x41, 0x42, 0x43, 0x44], "U2U", "\x41\x42\x43"] + ].should be_computed_by(:pack) + end + + it "encodes all remaining elements when passed the '*' modifier" do + [0x41, 0x42, 0x43, 0x44].pack("U*").should == "\x41\x42\x43\x44" + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(5) + [obj].pack("U").should == "\x05" + end + + it "raises a TypeError if #to_int does not return an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return("5") + lambda { [obj].pack("U") }.should raise_error(TypeError) + end + + it "ignores NULL bytes between directives" do + [1, 2, 3].pack("U\x00U").should == "\x01\x02" + end + + it "ignores spaces between directives" do + [1, 2, 3].pack("U U").should == "\x01\x02" + end + + it "raises a RangeError if passed a negative number" do + lambda { [-1].pack("U") }.should raise_error(RangeError) + end + + it "raises a RangeError if passed a number larger than an unsigned 32-bit integer" do + lambda { [2**32].pack("U") }.should raise_error(RangeError) + end + + it "sets the output string to UTF-8 encoding" do + [ [[0x00].pack("U"), Encoding::UTF_8], + [[0x41].pack("U"), Encoding::UTF_8], + [[0x7F].pack("U"), Encoding::UTF_8], + [[0x80].pack("U"), Encoding::UTF_8], + [[0x10FFFF].pack("U"), Encoding::UTF_8] + ].should be_computed_by(:encoding) + end +end diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb new file mode 100644 index 0000000000..0bc78fcb88 --- /dev/null +++ b/spec/ruby/core/array/pack/u_spec.rb @@ -0,0 +1,128 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/unicode', __FILE__) + +describe "Array#pack with format 'U'" do + it_behaves_like :array_pack_basic, 'U' + it_behaves_like :array_pack_basic_non_float, 'U' + it_behaves_like :array_pack_arguments, 'U' + it_behaves_like :array_pack_unicode, 'U' +end + +describe "Array#pack with format 'u'" do + it_behaves_like :array_pack_basic, 'u' + it_behaves_like :array_pack_basic_non_float, 'u' + it_behaves_like :array_pack_arguments, 'u' + + it "encodes an empty string as an empty string" do + [""].pack("u").should == "" + end + + it "appends a newline to the end of the encoded string" do + ["a"].pack("u").should == "!80``\n" + end + + it "encodes one element per directive" do + ["abc", "DEF"].pack("uu").should == "#86)C\n#1$5&\n" + end + + it "prepends the length of each segment of the input string as the first character (+32) in each line of the output" do + ["abcdefghijklm"].pack("u7").should == "&86)C9&5F\n&9VAI:FML\n!;0``\n" + end + + it "encodes 1, 2, or 3 characters in 4 output characters (uuencoding)" do + [ [["a"], "!80``\n"], + [["ab"], "\"86(`\n"], + [["abc"], "#86)C\n"], + [["abcd"], "$86)C9```\n"], + [["abcde"], "%86)C9&4`\n"], + [["abcdef"], "&86)C9&5F\n"], + [["abcdefg"], "'86)C9&5F9P``\n"], + ].should be_computed_by(:pack, "u") + end + + it "emits a newline after complete groups of count / 3 input characters when passed a count modifier" do + ["abcdefg"].pack("u3").should == "#86)C\n#9&5F\n!9P``\n" + end + + it "implicitly has a count of 45 when passed '*', 0, 1, 2 or no count modifier" do + s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + r = "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n%86%A86$`\n" + [ [[s], "u", r], + [[s], "u*", r], + [[s], "u0", r], + [[s], "u1", r], + [[s], "u2", r], + ].should be_computed_by(:pack) + end + + it "encodes all ascii characters" do + [ [["\x00\x01\x02\x03\x04\x05\x06"], "'``$\"`P0%!@``\n"], + [["\a\b\t\n\v\f\r"], "'!P@)\"@L,#0``\n"], + [["\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"], ")\#@\\0$1(3%!46\n"], + [["\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f"], ")%Q@9&AL<'1X?\n"], + [["!\"\#$%&'()*+,-./"], "/(2(C)\"4F)R@I*BLL+2XO\n"], + [["0123456789"], "*,\#$R,S0U-C<X.0``\n"], + [[":;<=>?@"], "'.CL\\/3X_0```\n"], + [["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], ":04)#1$5&1TA)2DM,34Y/4%%24U155E=865H`\n"], + [["[\\]^_`"], "&6UQ=7E]@\n"], + [["abcdefghijklmnopqrstuvwxyz"], ":86)C9&5F9VAI:FML;6YO<'%R<W1U=G=X>7H`\n"], + [["{|}~"], "$>WQ]?@``\n"], + [["\x7f\xc2\x80\xc2\x81\xc2\x82\xc2\x83"], ")?\\*`PH'\"@L*#\n"], + [["\xc2\x84\xc2\x85\xc2\x86\xc2\x87\xc2"], ")PH3\"A<*&PH?\"\n"], + [["\x88\xc2\x89\xc2\x8a\xc2\x8b\xc2\x8c"], ")B,*)PHK\"B\\*,\n"], + [["\xc2\x8d\xc2\x8e\xc2\x8f\xc2\x90\xc2"], ")PHW\"CL*/PI#\"\n"], + [["\x91\xc2\x92\xc2\x93\xc2\x94\xc2\x95"], ")D<*2PI/\"E,*5\n"], + [["\xc2\x96\xc2\x97\xc2\x98\xc2\x99\xc2"], ")PI;\"E\\*8PIG\"\n"], + [["\x9a\xc2\x9b\xc2\x9c\xc2\x9d\xc2\x9e"], ")FL*;PIS\"G<*>\n"], + [["\xc2\x9f\xc2\xa0\xc2\xa1\xc2\xa2\xc2"], ")PI_\"H,*APJ+\"\n"], + [["\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7"], ")H\\*DPJ7\"IL*G\n"], + [["\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2"], ")PJC\"J<*JPJO\"\n"], + [["\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0"], ")K,*MPJ[\"K\\*P\n"], + [["\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2"], ")PK'\"LL*SPK3\"\n"], + [["\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9"], ")M<*VPK?\"N,*Y\n"], + [["\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2"], ")PKK\"N\\*\\PKW\"\n"], + [["\xbe\xc2\xbf\xc3\x80\xc3\x81\xc3\x82"], ")OL*_PX#\#@<.\"\n"], + [["\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3"], ")PX/#A,.%PX;#\n"], + [["\x87\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b"], ")A\\.(PXG#BL.+\n"], + [["\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3"], ")PXS#C<..PX_#\n"], + [["\x90\xc3\x91\xc3\x92\xc3\x93\xc3\x94"], ")D,.1PY+#D\\.4\n"], + [["\xc3\x95\xc3\x96\xc3\x97\xc3\x98\xc3"], ")PY7#EL.7PYC#\n"], + [["\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d"], ")F<.:PYO#G,.=\n"], + [["\xc3\x9e\xc3\x9f\xc3\xa0\xc3\xa1\xc3"], ")PY[#G\\.@PZ'#\n"], + [["\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6"], ")HL.CPZ3#I<.F\n"], + [["\xc3\xa7\xc3\xa8\xc3\xa9\xc3\xaa\xc3"], ")PZ?#J,.IPZK#\n"], + [["\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf"], ")J\\.LPZW#KL.O\n"], + [["\xc3\xb0\xc3\xb1\xc3\xb2\xc3\xb3\xc3"], ")P[##L<.RP[/#\n"], + [["\xb4\xc3\xb5\xc3\xb6\xc3\xb7\xc3\xb8"], ")M,.UP[;#M\\.X\n"], + [["\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3"], ")P[G#NL.[P[S#\n"], + [["\xbd\xc3\xbe\xc3\xbf"], "%O<.^P[\\`\n"] + ].should be_computed_by(:pack, "u") + end + + it "calls #to_str to convert an object to a String" do + obj = mock("pack m string") + obj.should_receive(:to_str).and_return("abc") + [obj].pack("u").should == "#86)C\n" + end + + it "raises a TypeError if #to_str does not return a String" do + obj = mock("pack m non-string") + lambda { [obj].pack("u") }.should raise_error(TypeError) + end + + it "raises a TypeError if passed nil" do + lambda { [nil].pack("u") }.should raise_error(TypeError) + end + + it "raises a TypeError if passed an Integer" do + lambda { [0].pack("u") }.should raise_error(TypeError) + lambda { [bignum_value].pack("u") }.should raise_error(TypeError) + end + + it "sets the output string to US-ASCII encoding" do + ["abcd"].pack("u").encoding.should == Encoding::US_ASCII + end +end diff --git a/spec/ruby/core/array/pack/v_spec.rb b/spec/ruby/core/array/pack/v_spec.rb new file mode 100644 index 0000000000..8ebb863686 --- /dev/null +++ b/spec/ruby/core/array/pack/v_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) +require File.expand_path('../shared/integer', __FILE__) + +describe "Array#pack with format 'V'" do + it_behaves_like :array_pack_basic, 'V' + it_behaves_like :array_pack_basic_non_float, 'V' + it_behaves_like :array_pack_arguments, 'V' + it_behaves_like :array_pack_numeric_basic, 'V' + it_behaves_like :array_pack_integer, 'V' + it_behaves_like :array_pack_no_platform, 'V' + it_behaves_like :array_pack_32bit_le, 'V' +end + +describe "Array#pack with format 'v'" do + it_behaves_like :array_pack_basic, 'v' + it_behaves_like :array_pack_basic_non_float, 'v' + it_behaves_like :array_pack_arguments, 'v' + it_behaves_like :array_pack_numeric_basic, 'v' + it_behaves_like :array_pack_integer, 'v' + it_behaves_like :array_pack_no_platform, 'v' + it_behaves_like :array_pack_16bit_le, 'v' +end diff --git a/spec/ruby/core/array/pack/w_spec.rb b/spec/ruby/core/array/pack/w_spec.rb new file mode 100644 index 0000000000..9ada3e84cb --- /dev/null +++ b/spec/ruby/core/array/pack/w_spec.rb @@ -0,0 +1,42 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/numeric_basic', __FILE__) + +describe "Array#pack with format 'w'" do + it_behaves_like :array_pack_basic, 'w' + it_behaves_like :array_pack_basic_non_float, 'w' + it_behaves_like :array_pack_arguments, 'w' + it_behaves_like :array_pack_numeric_basic, 'w' + + it "encodes a BER-compressed integer" do + [ [[0], "\x00"], + [[1], "\x01"], + [[9999], "\xce\x0f"], + [[2**65], "\x84\x80\x80\x80\x80\x80\x80\x80\x80\x00"] + ].should be_computed_by(:pack, "w") + end + + it "calls #to_int to convert the pack argument to an Integer" do + obj = mock('to_int') + obj.should_receive(:to_int).and_return(5) + [obj].pack("w").should == "\x05" + end + + it "ignores NULL bytes between directives" do + [1, 2, 3].pack("w\x00w").should == "\x01\x02" + end + + it "ignores spaces between directives" do + [1, 2, 3].pack("w w").should == "\x01\x02" + end + + it "raises an ArgumentError when passed a negative value" do + lambda { [-1].pack("w") }.should raise_error(ArgumentError) + end + + it "returns an ASCII-8BIT string" do + [1].pack('w').encoding.should == Encoding::ASCII_8BIT + end +end diff --git a/spec/ruby/core/array/pack/x_spec.rb b/spec/ruby/core/array/pack/x_spec.rb new file mode 100644 index 0000000000..8d54ab84ee --- /dev/null +++ b/spec/ruby/core/array/pack/x_spec.rb @@ -0,0 +1,64 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) + +describe "Array#pack with format 'x'" do + it_behaves_like :array_pack_basic, 'x' + it_behaves_like :array_pack_basic_non_float, 'x' + it_behaves_like :array_pack_no_platform, 'x' + + it "adds a NULL byte with an empty array" do + [].pack("x").should == "\x00" + end + + it "adds a NULL byte without consuming an element" do + [1, 2].pack("CxC").should == "\x01\x00\x02" + end + + it "is not affected by a previous count modifier" do + [].pack("x3x").should == "\x00\x00\x00\x00" + end + + it "adds multiple NULL bytes when passed a count modifier" do + [].pack("x3").should == "\x00\x00\x00" + end + + it "does not add a NULL byte if the count modifier is zero" do + [].pack("x0").should == "" + end + + it "does not add a NULL byte when passed the '*' modifier" do + [].pack("x*").should == "" + end +end + +describe "Array#pack with format 'X'" do + it_behaves_like :array_pack_basic, 'X' + it_behaves_like :array_pack_basic_non_float, 'X' + it_behaves_like :array_pack_no_platform, 'X' + + it "reduces the output string by one byte at the point it is encountered" do + [1, 2, 3].pack("C2XC").should == "\x01\x03" + end + + it "does not consume any elements" do + [1, 2, 3].pack("CXC").should == "\x02" + end + + it "reduces the output string by multiple bytes when passed a count modifier" do + [1, 2, 3, 4, 5].pack("C2X2C").should == "\x03" + end + + it "has no affect when passed the '*' modifier" do + [1, 2, 3].pack("C2X*C").should == "\x01\x02\x03" + end + + it "raises an ArgumentError if the output string is empty" do + lambda { [1, 2, 3].pack("XC") }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError if the count modifier is greater than the bytes in the string" do + lambda { [1, 2, 3].pack("C2X3") }.should raise_error(ArgumentError) + end +end diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb new file mode 100644 index 0000000000..b28a460a8e --- /dev/null +++ b/spec/ruby/core/array/pack/z_spec.rb @@ -0,0 +1,32 @@ +# -*- encoding: ascii-8bit -*- +require File.expand_path('../../../../spec_helper', __FILE__) +require File.expand_path('../../fixtures/classes', __FILE__) +require File.expand_path('../shared/basic', __FILE__) +require File.expand_path('../shared/string', __FILE__) + +describe "Array#pack with format 'Z'" do + it_behaves_like :array_pack_basic, 'Z' + it_behaves_like :array_pack_basic_non_float, 'Z' + it_behaves_like :array_pack_no_platform, 'Z' + it_behaves_like :array_pack_string, 'Z' + + it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do + ["abc"].pack("Z*").should == "abc\x00" + end + + it "padds the output with NULL bytes when the count exceeds the size of the String" do + ["abc"].pack("Z6").should == "abc\x00\x00\x00" + end + + it "adds a NULL byte when the value is nil" do + [nil].pack("Z").should == "\x00" + end + + it "pads the output with NULL bytes when the value is nil" do + [nil].pack("Z3").should == "\x00\x00\x00" + end + + it "does not append a NULL byte when passed the '*' modifier and the value is nil" do + [nil].pack("Z*").should == "\x00" + end +end |