BEGIN { $| = 1; print "1..88\n"; }

use common::sense;
use Convert::BER::XS ':all';

our $test;
sub ok($;$) {
   print $_[0] ? "" : "not ", "ok ", ++$test, " # $_[1]\n";
}

sub roundtrip {
   my ($hex, $is, $hex2) = @_;

   $hex2 ||= $hex;

   y/ //d for $hex, $hex2;

   my $bin2 = pack "H*", $hex2;

   my $dec = ber_decode pack "H*", $hex;
   ok (&ber_is ($dec, @$is), "decode $hex => @$dec");
   my $enc = ber_encode $dec;
   ok ($enc eq $bin2, "encode $hex2 == " . unpack "H*", $enc);
}

sub fail {
   my ($hex, $match) = @_;

   y/ //d for $hex;

   ok (!eval { ber_decode pack "H*", $hex; 1 }, "# fail $hex");
   $@ =~ s/ at .*//s;
   ok ($@ =~ $match, "# $@ =~ $match");
}

roundtrip "020105", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 5];
roundtrip "0201ff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, -1];
roundtrip "020200ff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 255];
roundtrip "0204ffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, -1], "0201ff";
roundtrip "020500ffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 4294967295];
roundtrip "020488776655", [ASN_UNIVERSAL, ASN_INTEGER32, 0, -2005440939];
roundtrip "02050088776655", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 2289526357];

# 64 bit tests, clunky
if (8 == length pack "j", 0) {
   roundtrip "0208ffffffffffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, -1], "0201ff";
   roundtrip "020900ffffffffffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 18446744073709551615];
   roundtrip "0209007fffffffffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 9223372036854775807], "02087fffffffffffffff";
   roundtrip "0209008fffffffffffffff", [ASN_UNIVERSAL, ASN_INTEGER32, 0, 10376293541461622783], "0209008fffffffffffffff";
} else  {
   ok (1) for 1 .. 2 * 3;
}

roundtrip "010100", [ASN_UNIVERSAL, ASN_BOOLEAN, 0, 0];
roundtrip "010101", [ASN_UNIVERSAL, ASN_BOOLEAN, 0, 1], "0101ff";
roundtrip "010180", [ASN_UNIVERSAL, ASN_BOOLEAN, 0, 1], "0101ff";
roundtrip "0101ff", [ASN_UNIVERSAL, ASN_BOOLEAN, 0, 1], "0101ff";
fail "0100"    , "BER_TYPE_BOOLEAN value with invalid length";
fail "01020000", "BER_TYPE_BOOLEAN value with invalid length";

roundtrip "0303353637", [ASN_UNIVERSAL, ASN_BIT_STRING, 0, "567"];
roundtrip "0403353637", [ASN_UNIVERSAL, ASN_OCTET_STRING, 0, "567"];
roundtrip "0402a0ff", [ASN_UNIVERSAL, ASN_OCTET_STRING, 0, "\xa0\xff"];
roundtrip "0400", [ASN_UNIVERSAL, ASN_OCTET_STRING, 0, ""];
fail "040201", "unexpected end of message buffer";
roundtrip "0500", [ASN_UNIVERSAL, ASN_NULL, 0];
roundtrip "0500", [ASN_UNIVERSAL, ASN_NULL, 0];
fail "050101", "BER_TYPE_NULL value with non-zero length";

roundtrip "06053305818219", [ASN_UNIVERSAL, ASN_OBJECT_IDENTIFIER, 0, "1.11.5.16665"];
fail "06053305818299", "unexpected end of message buffer";
roundtrip "0d053305818219", [ASN_UNIVERSAL, ASN_RELATIVE_OID, 0, "51.5.16665"];
roundtrip "0703353739", [ASN_UNIVERSAL, ASN_OBJECT_DESCRIPTOR, 0, "579"];
roundtrip "0a0177", [ASN_UNIVERSAL, ASN_ENUMERATED, 0, 0x77];
roundtrip "2b00", [ASN_UNIVERSAL, ASN_EMBEDDED_PDV, 1];
roundtrip "0c04c2a0c3bf", [ASN_UNIVERSAL, ASN_UTF8_STRING, 0, "\xa0\xff"];
roundtrip "3000", [ASN_UNIVERSAL, ASN_SEQUENCE, 1];
roundtrip "3100", [ASN_UNIVERSAL, ASN_SET, 1];
roundtrip "1603393334", [ASN_UNIVERSAL, ASN_ASCII_STRING, 0, "934"];

roundtrip "1c0400000031", [ASN_UNIVERSAL, ASN_UNIVERSAL_STRING, 0, "1"];
roundtrip "1c0411223344", [ASN_UNIVERSAL, ASN_UNIVERSAL_STRING, 0, chr 0x11223344];
fail "1c0111", "BER_TYPE_UCS has an invalid number of octets";
fail "1c021122", "BER_TYPE_UCS has an invalid number of octets";
fail "1c03112234", "BER_TYPE_UCS has an invalid number of octets";

roundtrip "1e0400310037", [ASN_UNIVERSAL, ASN_BMP_STRING, 0, "17"];
roundtrip "1e0411223344", [ASN_UNIVERSAL, ASN_BMP_STRING, 0, "\x{1122}\x{3344}"];
fail "1e0111", "BER_TYPE_UCS has an invalid number of octets";
fail "1e03112234", "BER_TYPE_UCS has an invalid number of octets";

# TODO, verify they are all raw octets
# ASN_NUMERIC_STRING    = 0x12,
# ASN_PRINTABLE_STRING  = 0x13,
# ASN_TELETEX_STRING    = 0x14,
# ASN_T61_STRING        = 0x14,
# ASN_VIDEOTEX_STRING   = 0x15,
# ASN_IA5_STRING        = 0x16,
# ASN_UTC_TIME          = 0x17,
# ASN_GENERALIZED_TIME  = 0x18,
# ASN_GRAPHIC_STRING    = 0x19,
# ASN_VISIBLE_STRING    = 0x1a,
# ASN_ISO646_STRING     = 0x1a,
# ASN_GENERAL_STRING    = 0x1b,
# ASN_CHARACTER_STRING  = 0x1d,

