using MsgPack
using Base.Test
using Compat

ck_pack(a, b) = pack(a) == b && unpack(b) == a

# nil
@test ck_pack(nothing, [0xc0])

# bool
@test ck_pack(false, [0xc2])
@test ck_pack(true, [0xc3])

# positive fixint
@test ck_pack(5, [0x05])
# UInt8
@test ck_pack(128, [0xcc,0x80])
# UInt16
@test ck_pack(2^8, [0xcd,0x01,0x00])
# UInt32
@test ck_pack(2^16, [0xce,0x00,0x01,0x00,0x00])
# UInt64
@test ck_pack(2^32, [0xcf,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00])
@test ck_pack((@compat UInt64(2)^64-1), [0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff])

# negative fixint
@test ck_pack(-5, [0xfb])
@test ck_pack(-32, [0xe0])
# Int8
@test ck_pack(-33, [0xd0,0xdf])
@test ck_pack(-2^7, [0xd0,0x80])
# Int16
@test ck_pack(-2^8, [0xd1,0xff,0x00])
@test ck_pack(-2^15, [0xd1,0x80,0x00])
# Int32
@test ck_pack(-2^16, [0xd2,0xff,0xff,0x00,0x00])
@test ck_pack(-2^31, [0xd2,0x80,0x00,0x00,0x00])
# Int64
@test ck_pack(-2^32, [0xd3,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00])
@test ck_pack(-2^63, [0xd3,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00])

# Float32
@test ck_pack((@compat Float32(5.876)), [0xca, 0x40, 0xbc, 0x08, 0x31])
# Float64
@test ck_pack(0.654789321, [0xcb, 0x3f, 0xe4, 0xf4, 0x08, 0xbb, 0xee, 0xe1, 0xa8])

# fixstr
@test ck_pack("Меня зовут Шон",
              [0xba,0xd0,0x9c,0xd0,0xb5,0xd0,0xbd,0xd1,0x8f,
               0x20,0xd0,0xb7,0xd0,0xbe,0xd0,0xb2,0xd1,0x83,
               0xd1,0x82,0x20,0xd0,0xa8,0xd0,0xbe,0xd0,0xbd])
# str8 - currently unimplemented
# str16
s = randstring(2^8)
@test ck_pack(s, vcat(0xda, 0x01, 0x00, convert(Vector{UInt8}, s)))
s = randstring(2^16 - 1)
@test ck_pack(s, vcat(0xda, 0xff, 0xff, convert(Vector{UInt8}, s)))
# str32
s = randstring(2^16)
@test ck_pack(s, vcat(0xdb, 0x00, 0x01, 0x00, 0x00, convert(Vector{UInt8}, s)))
s = ""

# bin8
b = rand(UInt8, 121)
@test ck_pack(b, vcat(0xc4, 0x79, b))
# bin16
b = rand(UInt8, 2^11)
@test ck_pack(b, vcat(0xc5, 0x08, 0x00, b))
# bin32
b = rand(UInt8, 2^20)
@test ck_pack(b, vcat(0xc6, 0x00, 0x10, 0x00, 0x00, b))
b = []

# fixarray
@test ck_pack(Any[1, (@compat Float32(2)), UInt8[0x22, 0x54]],
              [0x93, 0x01, 0xca, 0x40, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x22, 0x54])
@test ck_pack(Any[nothing, "heya", true, false],
              [0x94, 0xc0, 0xa4, 0x68, 0x65, 0x79, 0x61, 0xc3, 0xc2])
@test ck_pack(Any[true, UInt8[0xff, 0xde, 0x11], [1, 2, 3]],
              [0x93, 0xc3, 0xc4, 0x03, 0xff, 0xde, 0x11, 0x93, 0x01, 0x02, 0x03])

# tuple
@test pack(Any[(1, [true, false], UInt8[0xff, 0xde])]) ==
              [0x91, 0x93, 0x01, 0x92, 0xc3, 0xc2, 0xc4, 0x02, 0xff, 0xde]
@test pack(("hi", ((@compat Float32(2)), 0xff))) ==
              [0x92, 0xa2, 0x68, 0x69, 0x92, 0xca, 0x40, 0x00, 0x00, 0x00, 0xcc, 0xff]

# fixmap
@test ck_pack((@compat Dict(1=>2, "hi"=>"mom")),
              [0x82,0xa2,0x68,0x69,0xa3,0x6d,0x6f,0x6d,0x01,0x02])

# fixext 1
@test ck_pack(Ext(4, [0xbb]), [0xd4, 0x04, 0xbb])
# fixext 2
@test ck_pack(Ext(-32, [0x56, 0x8d], impltype=true), [0xd5, 0xe0, 0x56, 0x8d])
# fixext 4
@test ck_pack(Ext(-123, [0x80, 0x7c, 0x8b, 0xf8], impltype=true),
              [0xd6, 0x85, 0x80, 0x7c, 0x8b, 0xf8])
# fixext 8
@test ck_pack(Ext(111, [0x04, 0x16, 0x94, 0x13, 0x0a, 0x7d, 0x6f, 0x0c]),
              [0xd7, 0x6f, 0x04, 0x16, 0x94, 0x13, 0x0a, 0x7d, 0x6f, 0x0c])
# fixext 16
@test ck_pack(Ext(79, [0x00, 0x30, 0xd5, 0x64, 0x0f, 0x8d, 0x92, 0x90,
                       0x98, 0x99, 0x14, 0x57, 0x0e, 0x8d, 0xf1, 0x3a]),
              [0xd8, 0x4f, 0x00, 0x30, 0xd5, 0x64, 0x0f, 0x8d, 0x92,
               0x90, 0x98, 0x99, 0x14, 0x57, 0x0e, 0x8d, 0xf1, 0x3a])
# no elements
@test ck_pack(Ext(-118, UInt8[], impltype=true), [0xc7, 0x00, 0x8a])
# ext 8
@test ck_pack(Ext(50, [0x62, 0x4c, 0x7c, 0x0f, 0x86, 0x04]),
              [0xc7, 0x06, 0x32, 0x62, 0x4c, 0x7c, 0x0f, 0x86, 0x04])
# ext 16
b = rand(UInt8, 2^14)
@test ck_pack(Ext(78, b), vcat(0xc8, 0x40, 0x00, 0x4e, b))
# ext 32
b = rand(UInt8, 2^19)
@test ck_pack(Ext(-123, b, impltype=true),
              vcat(0xc9, 0x00, 0x08, 0x00, 0x00, 0x85, b))
