# coding: ascii-8bit
require 'test/unit'
class TestPackUnpack < Test::Unit::TestCase
def test_pack_unpack
# hex数値 to hex文字列
assert_equal(0x12345678.to_s(16),"12345678")
assert_equal(0x1234_5678.to_s(16),"12345678")
assert_equal(0x12_34_56_78.to_s(16),"12345678")
# hex文字列 to hex数値
assert_equal("12345678".to_i(16), 0x1234_5678)
assert_equal("ab cd".split, ["ab","cd"])
assert_equal("12 34".split.collect{|c| c.to_i(16)}, [0x12,0x34])
# hex文字列 to バイナリーデータ
# Array#pack('C*')は、配列に入っているものを8ビット符号なし整数と見てpackする
assert_equal("61 62 63 64".split.collect{|c| c.to_i(16)}.pack('C*'), "abcd")
assert_equal("61 62 63 64".split.collect{|c| c.to_i(16)}.pack('C*'), "\x61\x62\x63\x64")
assert_equal("90 a0 e0 f0".split.collect{|c| c.to_i(16)}.pack('C*'), "\x90\xa0\xe0\xf0")
# バイナリーデータ to hex文字列
# String#unpack('C*')は、文字列を8ビット符号なし整数の配列にunpackする
assert_equal("\x90\xa0\xe0\xf0".unpack('C*').collect{|d| sprintf("%02x",d)}.join(' '), "90 a0 e0 f0")
hex_line = "00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0"
num_array = [0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240]
bin_data = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xa0\xb0\xc0\xd0\xe0\xf0"
assert_equal(hex_line.split.collect{|c| c.to_i(16)}.pack('C*'),bin_data)
# hex文字列 to バイナリーデータ
assert_equal(hex_line.split.collect{|c| c.to_i(16)}, num_array)
assert_equal(hex_line.split.collect{|c| c.to_i(16)}.pack('C*'), bin_data)
# バイナリーデータ to hex文字列
assert_equal(bin_data.unpack('C*'), num_array)
assert_equal(bin_data.unpack('C*').collect{|d| sprintf("%02x",d)}.join(' '), hex_line)
# endian reverse unsigned 16bit
assert_equal("\001\002".unpack("n"), [0x0102])
assert_equal("\001\002".unpack("n").pack("v"),"\002\001")
assert_equal("\001\002".unpack("v"), [0x0201])
assert_equal("\001\002".unpack("v").pack("n"),"\002\001")
# endian reverse unsigned 32bit
assert_equal("\001\002\003\004".unpack("N"), [0x01020304])
assert_equal("\001\002\003\004".unpack("N").pack("V"),"\004\003\002\001")
assert_equal("\001\002\003\004".unpack("n2"), [0x0102, 0x0304])
assert_equal("\001\002\003\004".unpack("n2").reverse, [0x0304, 0x0102])
assert_equal("\001\002\003\004".unpack("n2").reverse.pack("v2"),"\004\003\002\001")
# endian reverse unsigned 64bit
assert_equal("\001\002\003\004\005\006\a\b".unpack("N2").reverse.pack("V2"),"\b\a\006\005\004\003\002\001")
assert_equal("\001\002\003\004","\x01\x02\x03\x04")
# big endian unsigned 16bit to integer
assert_equal("\001\002".unpack("n"),[258])
assert_equal("\001\002".unpack("n")[0],258)
assert_equal("\001\002".unpack("n1")[0], 0x0102)
# big endian unsigned 32bit to integer
assert_equal("\001\002\003\004".unpack("N1")[0], 0x01020304)
# big endian unsigned 64bit to integer
b = "\001\002\003\004\005\006\a\b"
assert_equal(0x1_0000_0000 * (b.unpack("N2")[0]) + b.unpack("N2")[1], 0x0102030405060708)
# big endian unsigned 32bit to 4 unsigned 8bit
adrs = 0x11223344
assert_equal([adrs].pack("N*"), "\x11\x22\x33\x44")
assert_equal([adrs].pack("N*").unpack("C*"), [0x11,0x22,0x33,0x44])
adrs = 0xFFEEDDCC
assert_equal([adrs].pack("N*").unpack("C*"), [0xFF,0xEE,0xDD,0xCC])
# 0x01020304を"1.2.3.4"にする
adrs = 0x01020304
assert_equal([adrs].pack("N*"), "\x01\x02\x03\x04")
assert_equal([adrs].pack("N*").unpack("C*"), [1, 2, 3, 4])
assert_equal([adrs].pack("N*").unpack("C*").join("."), "1.2.3.4")
# big endian unsigned 32bit to IP Address
# "\x01\x02\x03\x04"を"1.2.3.4"にする
assert_equal("\x01\x02\x03\x04".unpack("C4"), [1, 2, 3, 4])
assert_equal("\x01\x02\x03\x04".unpack("C4").map{|d| d.to_s}, ["1", "2", "3", "4"])
assert_equal("\x01\x02\x03\x04".unpack("C4").map{|d| d.to_s}.join("."), "1.2.3.4")
assert_equal("\x01\x02\x03\x04".unpack("C4").join("."), "1.2.3.4")
assert_equal("\xC0\xC1\xC2\xC3".unpack("C4").join("."), "192.193.194.195")
# "1.2.3.4"を"\x01\x02\x03\x04" にする
assert_equal("1.2.3.4".split("."), ["1", "2", "3", "4"])
assert_equal("1.2.3.4".split(".").map{|s| s.to_i}, [1, 2, 3, 4])
assert_equal("1.2.3.4".split(".").map{|s| s.to_i}.pack("C4"), "\x01\x02\x03\x04")
assert_equal("192.193.194.195".split(".").map{|s| s.to_i}.pack("C4"), "\xC0\xC1\xC2\xC3")
end
end
IyBjb2Rpbmc6IGFzY2lpLThiaXQKCnJlcXVpcmUgJ3Rlc3QvdW5pdCcKCmNsYXNzIFRlc3RQYWNrVW5wYWNrIDwgVGVzdDo6VW5pdDo6VGVzdENhc2UKICBkZWYgdGVzdF9wYWNrX3VucGFjawogICAgCiAgICAjIGhleOaVsOWApCB0byBoZXjmloflrZfliJcKICAgIGFzc2VydF9lcXVhbCgweDEyMzQ1Njc4LnRvX3MoMTYpLCIxMjM0NTY3OCIpCiAgICBhc3NlcnRfZXF1YWwoMHgxMjM0XzU2NzgudG9fcygxNiksIjEyMzQ1Njc4IikKICAgIGFzc2VydF9lcXVhbCgweDEyXzM0XzU2Xzc4LnRvX3MoMTYpLCIxMjM0NTY3OCIpCiAgICAKICAgICMgaGV45paH5a2X5YiXIHRvIGhleOaVsOWApAogICAgYXNzZXJ0X2VxdWFsKCIxMjM0NTY3OCIudG9faSgxNiksIDB4MTIzNF81Njc4KQogICAgYXNzZXJ0X2VxdWFsKCJhYiBjZCIuc3BsaXQsIFsiYWIiLCJjZCJdKQogICAgYXNzZXJ0X2VxdWFsKCIxMiAzNCIuc3BsaXQuY29sbGVjdHt8Y3wgYy50b19pKDE2KX0sIFsweDEyLDB4MzRdKQogICAgCiAgICAjIGhleOaWh+Wtl+WIlyB0byDjg5DjgqTjg4rjg6rjg7zjg4fjg7zjgr8KICAgICMgQXJyYXkjcGFjaygnQyonKeOBr+OAgemFjeWIl+OBq+WFpeOBo+OBpuOBhOOCi+OCguOBruOCkjjjg5Pjg4Pjg4jnrKblj7fjgarjgZfmlbTmlbDjgajopovjgaZwYWNr44GZ44KLCiAgICBhc3NlcnRfZXF1YWwoIjYxIDYyIDYzIDY0Ii5zcGxpdC5jb2xsZWN0e3xjfCBjLnRvX2koMTYpfS5wYWNrKCdDKicpLCAiYWJjZCIpCiAgICBhc3NlcnRfZXF1YWwoIjYxIDYyIDYzIDY0Ii5zcGxpdC5jb2xsZWN0e3xjfCBjLnRvX2koMTYpfS5wYWNrKCdDKicpLCAiXHg2MVx4NjJceDYzXHg2NCIpCiAgICBhc3NlcnRfZXF1YWwoIjkwIGEwIGUwIGYwIi5zcGxpdC5jb2xsZWN0e3xjfCBjLnRvX2koMTYpfS5wYWNrKCdDKicpLCAiXHg5MFx4YTBceGUwXHhmMCIpCiAgICAjIOODkOOCpOODiuODquODvOODh+ODvOOCvyB0byBoZXjmloflrZfliJcKICAgICMgU3RyaW5nI3VucGFjaygnQyonKeOBr+OAgeaWh+Wtl+WIl+OCkjjjg5Pjg4Pjg4jnrKblj7fjgarjgZfmlbTmlbDjga7phY3liJfjgat1bnBhY2vjgZnjgosKICAgIGFzc2VydF9lcXVhbCgiXHg5MFx4YTBceGUwXHhmMCIudW5wYWNrKCdDKicpLmNvbGxlY3R7fGR8IHNwcmludGYoIiUwMngiLGQpfS5qb2luKCcgJyksICI5MCBhMCBlMCBmMCIpCgogICAgaGV4X2xpbmUgPSAiMDAgMTAgMjAgMzAgNDAgNTAgNjAgNzAgODAgOTAgYTAgYjAgYzAgZDAgZTAgZjAiCiAgICBudW1fYXJyYXkgPSBbMCwgMTYsIDMyLCA0OCwgNjQsIDgwLCA5NiwgMTEyLCAxMjgsIDE0NCwgMTYwLCAxNzYsIDE5MiwgMjA4LCAyMjQsIDI0MF0KICAgIGJpbl9kYXRhID0gIlx4MDBceDEwXHgyMFx4MzBceDQwXHg1MFx4NjBceDcwXHg4MFx4OTBceGEwXHhiMFx4YzBceGQwXHhlMFx4ZjAiCiAgICBhc3NlcnRfZXF1YWwoaGV4X2xpbmUuc3BsaXQuY29sbGVjdHt8Y3wgYy50b19pKDE2KX0ucGFjaygnQyonKSxiaW5fZGF0YSkKICAgICMgaGV45paH5a2X5YiXIHRvIOODkOOCpOODiuODquODvOODh+ODvOOCvwogICAgYXNzZXJ0X2VxdWFsKGhleF9saW5lLnNwbGl0LmNvbGxlY3R7fGN8IGMudG9faSgxNil9LCBudW1fYXJyYXkpCiAgICBhc3NlcnRfZXF1YWwoaGV4X2xpbmUuc3BsaXQuY29sbGVjdHt8Y3wgYy50b19pKDE2KX0ucGFjaygnQyonKSwgYmluX2RhdGEpCiAgICAjIOODkOOCpOODiuODquODvOODh+ODvOOCvyB0byBoZXjmloflrZfliJcKICAgIGFzc2VydF9lcXVhbChiaW5fZGF0YS51bnBhY2soJ0MqJyksIG51bV9hcnJheSkKICAgIGFzc2VydF9lcXVhbChiaW5fZGF0YS51bnBhY2soJ0MqJykuY29sbGVjdHt8ZHwgc3ByaW50ZigiJTAyeCIsZCl9LmpvaW4oJyAnKSwgaGV4X2xpbmUpCiAgICAKICAgICMgZW5kaWFuIHJldmVyc2UgdW5zaWduZWQgMTZiaXQKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDIiLnVucGFjaygibiIpLCBbMHgwMTAyXSkKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDIiLnVucGFjaygibiIpLnBhY2soInYiKSwiXDAwMlwwMDEiKQogICAgYXNzZXJ0X2VxdWFsKCJcMDAxXDAwMiIudW5wYWNrKCJ2IiksIFsweDAyMDFdKQogICAgYXNzZXJ0X2VxdWFsKCJcMDAxXDAwMiIudW5wYWNrKCJ2IikucGFjaygibiIpLCJcMDAyXDAwMSIpCiAgICAKICAgICMgZW5kaWFuIHJldmVyc2UgdW5zaWduZWQgMzJiaXQKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDJcMDAzXDAwNCIudW5wYWNrKCJOIiksIFsweDAxMDIwMzA0XSkKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDJcMDAzXDAwNCIudW5wYWNrKCJOIikucGFjaygiViIpLCJcMDA0XDAwM1wwMDJcMDAxIikKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDJcMDAzXDAwNCIudW5wYWNrKCJuMiIpLCBbMHgwMTAyLCAweDAzMDRdKQogICAgYXNzZXJ0X2VxdWFsKCJcMDAxXDAwMlwwMDNcMDA0Ii51bnBhY2soIm4yIikucmV2ZXJzZSwgWzB4MDMwNCwgMHgwMTAyXSkKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDJcMDAzXDAwNCIudW5wYWNrKCJuMiIpLnJldmVyc2UucGFjaygidjIiKSwiXDAwNFwwMDNcMDAyXDAwMSIpCiAgICAKICAgICMgZW5kaWFuIHJldmVyc2UgdW5zaWduZWQgNjRiaXQKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDJcMDAzXDAwNFwwMDVcMDA2XGFcYiIudW5wYWNrKCJOMiIpLnJldmVyc2UucGFjaygiVjIiKSwiXGJcYVwwMDZcMDA1XDAwNFwwMDNcMDAyXDAwMSIpCiAgICBhc3NlcnRfZXF1YWwoIlwwMDFcMDAyXDAwM1wwMDQiLCJceDAxXHgwMlx4MDNceDA0IikKICAgIAogICAgIyBiaWcgZW5kaWFuIHVuc2lnbmVkIDE2Yml0IHRvIGludGVnZXIKICAgIGFzc2VydF9lcXVhbCgiXDAwMVwwMDIiLnVucGFjaygibiIpLFsyNThdKQogICAgYXNzZXJ0X2VxdWFsKCJcMDAxXDAwMiIudW5wYWNrKCJuIilbMF0sMjU4KQogICAgYXNzZXJ0X2VxdWFsKCJcMDAxXDAwMiIudW5wYWNrKCJuMSIpWzBdLCAweDAxMDIpCiAgICAKICAgICMgYmlnIGVuZGlhbiB1bnNpZ25lZCAzMmJpdCB0byBpbnRlZ2VyCiAgICBhc3NlcnRfZXF1YWwoIlwwMDFcMDAyXDAwM1wwMDQiLnVucGFjaygiTjEiKVswXSwgMHgwMTAyMDMwNCkKICAgIAogICAgIyBiaWcgZW5kaWFuIHVuc2lnbmVkIDY0Yml0IHRvIGludGVnZXIKICAgIGIgPSAiXDAwMVwwMDJcMDAzXDAwNFwwMDVcMDA2XGFcYiIKICAgIGFzc2VydF9lcXVhbCgweDFfMDAwMF8wMDAwICogKGIudW5wYWNrKCJOMiIpWzBdKSArIGIudW5wYWNrKCJOMiIpWzFdLCAweDAxMDIwMzA0MDUwNjA3MDgpCiAgICAKICAgICMgYmlnIGVuZGlhbiB1bnNpZ25lZCAzMmJpdCB0byA0IHVuc2lnbmVkIDhiaXQKICAgIGFkcnMgPSAweDExMjIzMzQ0CiAgICBhc3NlcnRfZXF1YWwoW2FkcnNdLnBhY2soIk4qIiksICJceDExXHgyMlx4MzNceDQ0IikKICAgIGFzc2VydF9lcXVhbChbYWRyc10ucGFjaygiTioiKS51bnBhY2soIkMqIiksIFsweDExLDB4MjIsMHgzMywweDQ0XSkKICAgIGFkcnMgPSAweEZGRUVERENDCiAgICBhc3NlcnRfZXF1YWwoW2FkcnNdLnBhY2soIk4qIikudW5wYWNrKCJDKiIpLCBbMHhGRiwweEVFLDB4REQsMHhDQ10pCiAgICAKICAgICMgMHgwMTAyMDMwNOOCkiIxLjIuMy40IuOBq+OBmeOCiwogICAgYWRycyA9IDB4MDEwMjAzMDQKICAgIGFzc2VydF9lcXVhbChbYWRyc10ucGFjaygiTioiKSwgIlx4MDFceDAyXHgwM1x4MDQiKQogICAgYXNzZXJ0X2VxdWFsKFthZHJzXS5wYWNrKCJOKiIpLnVucGFjaygiQyoiKSwgWzEsIDIsIDMsIDRdKQogICAgYXNzZXJ0X2VxdWFsKFthZHJzXS5wYWNrKCJOKiIpLnVucGFjaygiQyoiKS5qb2luKCIuIiksICIxLjIuMy40IikKICAgIAogICAgIyBiaWcgZW5kaWFuIHVuc2lnbmVkIDMyYml0IHRvIElQIEFkZHJlc3MKICAgICMgIlx4MDFceDAyXHgwM1x4MDQi44KSIjEuMi4zLjQi44Gr44GZ44KLCiAgICBhc3NlcnRfZXF1YWwoIlx4MDFceDAyXHgwM1x4MDQiLnVucGFjaygiQzQiKSwgWzEsIDIsIDMsIDRdKQogICAgYXNzZXJ0X2VxdWFsKCJceDAxXHgwMlx4MDNceDA0Ii51bnBhY2soIkM0IikubWFwe3xkfCBkLnRvX3N9LCBbIjEiLCAiMiIsICIzIiwgIjQiXSkKICAgIGFzc2VydF9lcXVhbCgiXHgwMVx4MDJceDAzXHgwNCIudW5wYWNrKCJDNCIpLm1hcHt8ZHwgZC50b19zfS5qb2luKCIuIiksICIxLjIuMy40IikKICAgIGFzc2VydF9lcXVhbCgiXHgwMVx4MDJceDAzXHgwNCIudW5wYWNrKCJDNCIpLmpvaW4oIi4iKSwgIjEuMi4zLjQiKQogICAgYXNzZXJ0X2VxdWFsKCJceEMwXHhDMVx4QzJceEMzIi51bnBhY2soIkM0Iikuam9pbigiLiIpLCAiMTkyLjE5My4xOTQuMTk1IikKICAgIAogICAgIyAiMS4yLjMuNCLjgpIiXHgwMVx4MDJceDAzXHgwNCIg44Gr44GZ44KLCiAgICBhc3NlcnRfZXF1YWwoIjEuMi4zLjQiLnNwbGl0KCIuIiksIFsiMSIsICIyIiwgIjMiLCAiNCJdKQogICAgYXNzZXJ0X2VxdWFsKCIxLjIuMy40Ii5zcGxpdCgiLiIpLm1hcHt8c3wgcy50b19pfSwgWzEsIDIsIDMsIDRdKQogICAgYXNzZXJ0X2VxdWFsKCIxLjIuMy40Ii5zcGxpdCgiLiIpLm1hcHt8c3wgcy50b19pfS5wYWNrKCJDNCIpLCAiXHgwMVx4MDJceDAzXHgwNCIpCiAgICBhc3NlcnRfZXF1YWwoIjE5Mi4xOTMuMTk0LjE5NSIuc3BsaXQoIi4iKS5tYXB7fHN8IHMudG9faX0ucGFjaygiQzQiKSwgIlx4QzBceEMxXHhDMlx4QzMiKQogIGVuZAplbmQ=