The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl
# ripped largely from MIME-Base64's t/ directory
use warnings;
use strict;
use Text::Pipe;
use Test::More tests => 538;

BEGIN {
    if (ord('A') == 0x41) {
        *ASCII = sub { return $_[0] };
    } else {
        require Encode;
        *ASCII = sub { Encode::encode('ascii', $_[0]) };
    }
}
my @encode_tests = (

    # All values
    [ "\000"         => "AA==" ],
    [ "\001"         => "AQ==" ],
    [ "\002"         => "Ag==" ],
    [ "\003"         => "Aw==" ],
    [ "\004"         => "BA==" ],
    [ "\005"         => "BQ==" ],
    [ "\006"         => "Bg==" ],
    [ "\007"         => "Bw==" ],
    [ "\010"         => "CA==" ],
    [ "\011"         => "CQ==" ],
    [ "\012"         => "Cg==" ],
    [ "\013"         => "Cw==" ],
    [ "\014"         => "DA==" ],
    [ "\015"         => "DQ==" ],
    [ "\016"         => "Dg==" ],
    [ "\017"         => "Dw==" ],
    [ "\020"         => "EA==" ],
    [ "\021"         => "EQ==" ],
    [ "\022"         => "Eg==" ],
    [ "\023"         => "Ew==" ],
    [ "\024"         => "FA==" ],
    [ "\025"         => "FQ==" ],
    [ "\026"         => "Fg==" ],
    [ "\027"         => "Fw==" ],
    [ "\030"         => "GA==" ],
    [ "\031"         => "GQ==" ],
    [ "\032"         => "Gg==" ],
    [ "\033"         => "Gw==" ],
    [ "\034"         => "HA==" ],
    [ "\035"         => "HQ==" ],
    [ "\036"         => "Hg==" ],
    [ "\037"         => "Hw==" ],
    [ "\040"         => "IA==" ],
    [ "\041"         => "IQ==" ],
    [ "\042"         => "Ig==" ],
    [ "\043"         => "Iw==" ],
    [ "\044"         => "JA==" ],
    [ "\045"         => "JQ==" ],
    [ "\046"         => "Jg==" ],
    [ "\047"         => "Jw==" ],
    [ "\050"         => "KA==" ],
    [ "\051"         => "KQ==" ],
    [ "\052"         => "Kg==" ],
    [ "\053"         => "Kw==" ],
    [ "\054"         => "LA==" ],
    [ "\055"         => "LQ==" ],
    [ "\056"         => "Lg==" ],
    [ "\057"         => "Lw==" ],
    [ "\060"         => "MA==" ],
    [ "\061"         => "MQ==" ],
    [ "\062"         => "Mg==" ],
    [ "\063"         => "Mw==" ],
    [ "\064"         => "NA==" ],
    [ "\065"         => "NQ==" ],
    [ "\066"         => "Ng==" ],
    [ "\067"         => "Nw==" ],
    [ "\070"         => "OA==" ],
    [ "\071"         => "OQ==" ],
    [ "\072"         => "Og==" ],
    [ "\073"         => "Ow==" ],
    [ "\074"         => "PA==" ],
    [ "\075"         => "PQ==" ],
    [ "\076"         => "Pg==" ],
    [ "\077"         => "Pw==" ],
    [ "\100"         => "QA==" ],
    [ "\101"         => "QQ==" ],
    [ "\102"         => "Qg==" ],
    [ "\103"         => "Qw==" ],
    [ "\104"         => "RA==" ],
    [ "\105"         => "RQ==" ],
    [ "\106"         => "Rg==" ],
    [ "\107"         => "Rw==" ],
    [ "\110"         => "SA==" ],
    [ "\111"         => "SQ==" ],
    [ "\112"         => "Sg==" ],
    [ "\113"         => "Sw==" ],
    [ "\114"         => "TA==" ],
    [ "\115"         => "TQ==" ],
    [ "\116"         => "Tg==" ],
    [ "\117"         => "Tw==" ],
    [ "\120"         => "UA==" ],
    [ "\121"         => "UQ==" ],
    [ "\122"         => "Ug==" ],
    [ "\123"         => "Uw==" ],
    [ "\124"         => "VA==" ],
    [ "\125"         => "VQ==" ],
    [ "\126"         => "Vg==" ],
    [ "\127"         => "Vw==" ],
    [ "\130"         => "WA==" ],
    [ "\131"         => "WQ==" ],
    [ "\132"         => "Wg==" ],
    [ "\133"         => "Ww==" ],
    [ "\134"         => "XA==" ],
    [ "\135"         => "XQ==" ],
    [ "\136"         => "Xg==" ],
    [ "\137"         => "Xw==" ],
    [ "\140"         => "YA==" ],
    [ "\141"         => "YQ==" ],
    [ "\142"         => "Yg==" ],
    [ "\143"         => "Yw==" ],
    [ "\144"         => "ZA==" ],
    [ "\145"         => "ZQ==" ],
    [ "\146"         => "Zg==" ],
    [ "\147"         => "Zw==" ],
    [ "\150"         => "aA==" ],
    [ "\151"         => "aQ==" ],
    [ "\152"         => "ag==" ],
    [ "\153"         => "aw==" ],
    [ "\154"         => "bA==" ],
    [ "\155"         => "bQ==" ],
    [ "\156"         => "bg==" ],
    [ "\157"         => "bw==" ],
    [ "\160"         => "cA==" ],
    [ "\161"         => "cQ==" ],
    [ "\162"         => "cg==" ],
    [ "\163"         => "cw==" ],
    [ "\164"         => "dA==" ],
    [ "\165"         => "dQ==" ],
    [ "\166"         => "dg==" ],
    [ "\167"         => "dw==" ],
    [ "\170"         => "eA==" ],
    [ "\171"         => "eQ==" ],
    [ "\172"         => "eg==" ],
    [ "\173"         => "ew==" ],
    [ "\174"         => "fA==" ],
    [ "\175"         => "fQ==" ],
    [ "\176"         => "fg==" ],
    [ "\177"         => "fw==" ],
    [ "\200"         => "gA==" ],
    [ "\201"         => "gQ==" ],
    [ "\202"         => "gg==" ],
    [ "\203"         => "gw==" ],
    [ "\204"         => "hA==" ],
    [ "\205"         => "hQ==" ],
    [ "\206"         => "hg==" ],
    [ "\207"         => "hw==" ],
    [ "\210"         => "iA==" ],
    [ "\211"         => "iQ==" ],
    [ "\212"         => "ig==" ],
    [ "\213"         => "iw==" ],
    [ "\214"         => "jA==" ],
    [ "\215"         => "jQ==" ],
    [ "\216"         => "jg==" ],
    [ "\217"         => "jw==" ],
    [ "\220"         => "kA==" ],
    [ "\221"         => "kQ==" ],
    [ "\222"         => "kg==" ],
    [ "\223"         => "kw==" ],
    [ "\224"         => "lA==" ],
    [ "\225"         => "lQ==" ],
    [ "\226"         => "lg==" ],
    [ "\227"         => "lw==" ],
    [ "\230"         => "mA==" ],
    [ "\231"         => "mQ==" ],
    [ "\232"         => "mg==" ],
    [ "\233"         => "mw==" ],
    [ "\234"         => "nA==" ],
    [ "\235"         => "nQ==" ],
    [ "\236"         => "ng==" ],
    [ "\237"         => "nw==" ],
    [ "\240"         => "oA==" ],
    [ "\241"         => "oQ==" ],
    [ "\242"         => "og==" ],
    [ "\243"         => "ow==" ],
    [ "\244"         => "pA==" ],
    [ "\245"         => "pQ==" ],
    [ "\246"         => "pg==" ],
    [ "\247"         => "pw==" ],
    [ "\250"         => "qA==" ],
    [ "\251"         => "qQ==" ],
    [ "\252"         => "qg==" ],
    [ "\253"         => "qw==" ],
    [ "\254"         => "rA==" ],
    [ "\255"         => "rQ==" ],
    [ "\256"         => "rg==" ],
    [ "\257"         => "rw==" ],
    [ "\260"         => "sA==" ],
    [ "\261"         => "sQ==" ],
    [ "\262"         => "sg==" ],
    [ "\263"         => "sw==" ],
    [ "\264"         => "tA==" ],
    [ "\265"         => "tQ==" ],
    [ "\266"         => "tg==" ],
    [ "\267"         => "tw==" ],
    [ "\270"         => "uA==" ],
    [ "\271"         => "uQ==" ],
    [ "\272"         => "ug==" ],
    [ "\273"         => "uw==" ],
    [ "\274"         => "vA==" ],
    [ "\275"         => "vQ==" ],
    [ "\276"         => "vg==" ],
    [ "\277"         => "vw==" ],
    [ "\300"         => "wA==" ],
    [ "\301"         => "wQ==" ],
    [ "\302"         => "wg==" ],
    [ "\303"         => "ww==" ],
    [ "\304"         => "xA==" ],
    [ "\305"         => "xQ==" ],
    [ "\306"         => "xg==" ],
    [ "\307"         => "xw==" ],
    [ "\310"         => "yA==" ],
    [ "\311"         => "yQ==" ],
    [ "\312"         => "yg==" ],
    [ "\313"         => "yw==" ],
    [ "\314"         => "zA==" ],
    [ "\315"         => "zQ==" ],
    [ "\316"         => "zg==" ],
    [ "\317"         => "zw==" ],
    [ "\320"         => "0A==" ],
    [ "\321"         => "0Q==" ],
    [ "\322"         => "0g==" ],
    [ "\323"         => "0w==" ],
    [ "\324"         => "1A==" ],
    [ "\325"         => "1Q==" ],
    [ "\326"         => "1g==" ],
    [ "\327"         => "1w==" ],
    [ "\330"         => "2A==" ],
    [ "\331"         => "2Q==" ],
    [ "\332"         => "2g==" ],
    [ "\333"         => "2w==" ],
    [ "\334"         => "3A==" ],
    [ "\335"         => "3Q==" ],
    [ "\336"         => "3g==" ],
    [ "\337"         => "3w==" ],
    [ "\340"         => "4A==" ],
    [ "\341"         => "4Q==" ],
    [ "\342"         => "4g==" ],
    [ "\343"         => "4w==" ],
    [ "\344"         => "5A==" ],
    [ "\345"         => "5Q==" ],
    [ "\346"         => "5g==" ],
    [ "\347"         => "5w==" ],
    [ "\350"         => "6A==" ],
    [ "\351"         => "6Q==" ],
    [ "\352"         => "6g==" ],
    [ "\353"         => "6w==" ],
    [ "\354"         => "7A==" ],
    [ "\355"         => "7Q==" ],
    [ "\356"         => "7g==" ],
    [ "\357"         => "7w==" ],
    [ "\360"         => "8A==" ],
    [ "\361"         => "8Q==" ],
    [ "\362"         => "8g==" ],
    [ "\363"         => "8w==" ],
    [ "\364"         => "9A==" ],
    [ "\365"         => "9Q==" ],
    [ "\366"         => "9g==" ],
    [ "\367"         => "9w==" ],
    [ "\370"         => "+A==" ],
    [ "\371"         => "+Q==" ],
    [ "\372"         => "+g==" ],
    [ "\373"         => "+w==" ],
    [ "\374"         => "/A==" ],
    [ "\375"         => "/Q==" ],
    [ "\376"         => "/g==" ],
    [ "\377"         => "/w==" ],
    [ "\000\377"     => "AP8=" ],
    [ "\377\000"     => "/wA=" ],
    [ "\000\000\000" => "AAAA" ],
    [ ''             => '' ],
    [ ASCII('a')     => 'YQ==' ],
    [ ASCII('aa')    => 'YWE=' ],
    [ ASCII('aaa')   => 'YWFh' ],
    [ ASCII('aaa')   => 'YWFh' ],
    [ ASCII('aaa')   => 'YWFh' ],
    [ ASCII('aaa')   => 'YWFh' ],

    # from HTTP spec
    [ ASCII('Aladdin:open sesame') => 'QWxhZGRpbjpvcGVuIHNlc2FtZQ==' ],
    [ ASCII('a') x 100             => 'YWFh' x 33 . 'YQ==' ],
    [   ASCII(
'Multipurpose Internet Mail Extensions: The Base64 Content-Transfer-Encoding is designed to represent sequences of octets in a form that is not humanly readable. '
          ) =>
"TXVsdGlwdXJwb3NlIEludGVybmV0IE1haWwgRXh0ZW5zaW9uczogVGhlIEJhc2U2NCBDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nIGlzIGRlc2lnbmVkIHRvIHJlcHJlc2VudCBzZXF1ZW5jZXMgb2Ygb2N0ZXRzIGluIGEgZm9ybSB0aGF0IGlzIG5vdCBodW1hbmx5IHJlYWRhYmxlLiA="
    ],
);
my $enc_pipe = Text::Pipe->new('Encoding::Base64::Encode');
my $dec_pipe = Text::Pipe->new('Encoding::Base64::Decode');
for (@encode_tests) {
    my ($plain, $expected) = @$_;
    my $encoded = $enc_pipe->filter($plain);
    is($encoded,                    $expected, "encoded ($plain)");
    is($dec_pipe->filter($encoded), $plain,    "decoded ($encoded)");
}