summaryrefslogtreecommitdiff
path: root/spec/ruby/core/array/pack
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/array/pack')
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb59
-rw-r--r--spec/ruby/core/array/pack/at_spec.rb30
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb105
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb75
-rw-r--r--spec/ruby/core/array/pack/comment_spec.rb25
-rw-r--r--spec/ruby/core/array/pack/d_spec.rb39
-rw-r--r--spec/ruby/core/array/pack/e_spec.rb25
-rw-r--r--spec/ruby/core/array/pack/empty_spec.rb11
-rw-r--r--spec/ruby/core/array/pack/f_spec.rb39
-rw-r--r--spec/ruby/core/array/pack/g_spec.rb25
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb197
-rw-r--r--spec/ruby/core/array/pack/i_spec.rb133
-rw-r--r--spec/ruby/core/array/pack/j_spec.rb222
-rw-r--r--spec/ruby/core/array/pack/l_spec.rb221
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb306
-rw-r--r--spec/ruby/core/array/pack/n_spec.rb25
-rw-r--r--spec/ruby/core/array/pack/p_spec.rb11
-rw-r--r--spec/ruby/core/array/pack/percent_spec.rb7
-rw-r--r--spec/ruby/core/array/pack/q_spec.rb61
-rw-r--r--spec/ruby/core/array/pack/s_spec.rb133
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb65
-rw-r--r--spec/ruby/core/array/pack/shared/encodings.rb16
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb249
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb381
-rw-r--r--spec/ruby/core/array/pack/shared/numeric_basic.rb44
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb80
-rw-r--r--spec/ruby/core/array/pack/shared/unicode.rb94
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb128
-rw-r--r--spec/ruby/core/array/pack/v_spec.rb25
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb42
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb64
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb32
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