The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

use strict;
use warnings;
no  warnings 'syntax';

use Regexp::Common;
use Test::More;

my $r = eval "require Test::Regexp; 1";

unless ($r) {
    print "1..0 # SKIP Test::Regexp not found\n";
    exit;
}

my @valid = ((map {sprintf "%04d" => $_}
               200,          800 ..  801,  804,          810 ..  815,
               820 ..  822,  828 ..  832,  834 ..  840,  845 ..  847,
               850 ..  854,  860 ..  862,  870 ..  875,  880 ..  881,
               885 ..  886,  909),

              1215,   1220, 1225,   1230, 1235,   1240, 1300,   1335, 
              1340,   1350, 1355,   1360, 1435,   1445, 1450,   1455,
              1460,         1465 .. 1466, 1470,   1475, 1480 .. 1481,
              1485,   1490, 1495,   1499, 1515,   1560, 1565,   1570,
              1585,   1590, 1595,   1630, 1635,   1640, 1655,   1660,
              1670,   1675, 1680,   1685, 1700 .. 1701, 1710,   1715,
              1730,   1750, 1755,   1765, 1790,   1800, 1805,   1811,
              1825,   1835, 1851,   1860, 1871,   1875, 1885,   1890,

              2000 .. 2002, 2004,         2006 .. 2012, 2015 .. 2050,
              2052,   2057, 2059 .. 2077, 2079 .. 2090, 2092 .. 2097,
              2099 .. 2138, 2140 .. 2148, 2150 .. 2168, 2170 .. 2179,
              2190 .. 2200, 2203 .. 2214, 2216 .. 2234, 2250 .. 2251,
              2256 .. 2265, 2267,   2278, 2280 .. 2287, 2289 .. 2300,
              2302 .. 2312, 2314 .. 2330, 2333 .. 2348, 2350 .. 2361,
              2365,         2369 .. 2372, 2379 .. 2382, 2386 .. 2388,
              2390,         2395 .. 2406, 2408 .. 2411, 2415,
              2420 .. 2431, 2439 .. 2441, 2443 .. 2450, 2452 .. 2456,
              2460,         2462 .. 2466, 2469 .. 2490, 2500,   2502,
              2505 .. 2506, 2508,         2515 .. 2520, 2522,
              2525 .. 2530, 2533 .. 2541, 2545 .. 2546, 2548 .. 2551,
              2555 .. 2560, 2563 .. 2588, 2590,   2594,
              2600 .. 2612, 2614 .. 2633, 2640 .. 2653, 2655 .. 2656,
              2658 .. 2661, 2663,         2665 .. 2666, 2668 .. 2669,
              2671 .. 2672, 2675,   2678, 2680 .. 2681, 2700 .. 2703,
              2705 .. 2708, 2710 .. 2717, 2720 .. 2722, 2725 .. 2727,
              2729 .. 2739, 2745,         2747 .. 2754, 2756 .. 2763,
              2765 .. 2770, 2773 .. 2780, 2782 .. 2787, 2790 .. 2795,
              2797 .. 2800, 2803 .. 2810, 2817 .. 2818, 2820 .. 2836,
              2838 .. 2840, 2842 .. 2850, 2852,         2864 .. 2871,
              2873 .. 2880, 2890,         2898 .. 2906, 2911 .. 2914,

              3000 .. 3004, 3006,   3008, 3010 .. 3013, 3015 .. 3016,
              3018 .. 3034, 3036 .. 3068, 3070 .. 3076, 3078 .. 3079,
              3081 .. 3085, 3087 .. 3091, 3093 .. 3097, 3099,
              3101 .. 3109, 3111,         3113 .. 3116, 3121 .. 3156,
              3158 .. 3202, 3204 .. 3207, 3211 .. 3228, 3230 .. 3243,
              3249 .. 3251, 3254,   3260, 3264 .. 3287, 3289,
              3292 .. 3294, 3300 .. 3305, 3309 .. 3312, 3314 .. 3315,
              3317 .. 3319, 3321 .. 3325, 3328 .. 3335, 3337 .. 3338,
              3340 .. 3342, 3345,         3350 .. 3357, 3360 .. 3361,
              3363 .. 3364, 3370 .. 3371, 3373 .. 3375, 3377 .. 3381,
              3384 .. 3385, 3387 .. 3388, 3390 .. 3393, 3395 .. 3396,
              3400 .. 3402, 3407,   3409, 3412 .. 3415, 3418 .. 3420,
              3423 .. 3424, 3427 .. 3435, 3437 .. 3438, 3440 .. 3442,
              3444,         3446 .. 3448, 3450 .. 3451, 3453,   3458,
              3460 .. 3465, 3467 .. 3469, 3472,   3475, 3477 .. 3478,
              3480,         3482 .. 3483, 3485,         3487 .. 3491,
              3494,   3496, 3498,         3500 .. 3502, 3505 .. 3507,
              3509,   3512, 3515 .. 3518, 3520 .. 3523, 3525,   3527,
              3529 .. 3531, 3533,   3537, 3540,   3542, 3544,   3546,
              3549 .. 3552, 3554 .. 3559, 3561 .. 3568, 3570 .. 3573,
              3575 .. 3576, 3579 .. 3581, 3583 .. 3586, 3588 .. 3591,
              3594 .. 3597, 3599,         3607 .. 3608, 3610,   3612,
              3614,         3616 .. 3624, 3629 .. 3641, 3643 .. 3644,
              3646 .. 3647, 3649,         3658 .. 3666, 3669 .. 3673,
              3675 .. 3678, 3682 .. 3683, 3685,         3687 .. 3691,
              3694 .. 3695, 3697 .. 3701, 3704 .. 3705, 3707 .. 3709,
              3711 .. 3715, 3717 .. 3720, 3722 .. 3728, 3730,
              3732 .. 3733, 3735 .. 3741, 3744,         3746 .. 3747,
              3749 .. 3767, 3770,   3775, 3777 .. 3779, 3781 .. 3783,
              3785 .. 3789, 3791 .. 3793, 3795 .. 3797, 3799 .. 3800,
              3802 .. 3810, 3812 .. 3816, 3818,         3820 .. 3825,
              3831 .. 3833, 3835,         3840 .. 3842, 3844,
              3847,         3850 .. 3854, 3856 .. 3860, 3862,
              3864 .. 3865, 3869 .. 3871, 3873 .. 3875, 3878,   3880,
              3882,         3885 .. 3893, 3895 .. 3896, 3898,   3900,
              3902 .. 3904, 3909 .. 3913, 3915 .. 3916, 3918 .. 3923,
              3925 .. 3931, 3933 .. 3934, 3936 .. 3946, 3950 .. 3951,
              3953 .. 3954, 3956 .. 3960, 3962,         3964 .. 3967,
              3971,         3975 .. 3981, 3984,         3987 .. 3988,
              3990 .. 3992, 3995 .. 3996,

              4000 .. 4014, 4017 .. 4022, 4025,         4029 .. 4032,
              4034 .. 4037, 4051,         4053 .. 4055, 4059 .. 4061,
              4064 .. 4070, 4072 .. 4078, 4101 .. 4125, 4127 .. 4133,
              4151 .. 4161, 4163 .. 4165, 4169 .. 4174, 4178 .. 4179,
              4183 .. 4184, 4205,         4207 .. 4230, 4270 .. 4272,
              4275,   4280, 4285,   4287, 4300 .. 4301, 4303 .. 4307,
              4309 .. 4313, 4340 .. 4347, 4350,         4352 .. 4365,
              4370 .. 4378, 4380 .. 4385, 4387 .. 4388, 4390,
              4400 .. 4408, 4410 .. 4413, 4415 .. 4428, 4454 .. 4455,
              4461 .. 4462, 4465,         4467 .. 4468, 4470 .. 4472,
              4474 .. 4475, 4477 .. 4482, 4486 .. 4494, 4496 .. 4498,
              4500 .. 4512, 4514 .. 4521, 4550 .. 4575, 4580 .. 4581,
              4600 .. 4601, 4605 .. 4606, 4608,         4610 .. 4615,
              4620 .. 4621, 4625 .. 4627, 4630,   4650, 4655,
              4659 .. 4660, 4662,         4670 .. 4671, 4673 .. 4674,
              4676 .. 4678, 4680,         4694 .. 4695, 4697,
              4699 .. 4707, 4709 .. 4728, 4730 .. 4733, 4735 .. 4746,
              4750 .. 4751, 4753 .. 4754, 4756 .. 4757, 4798 .. 4800,
              4802 .. 4825, 4828 .. 4830, 4849 .. 4850, 4852,
              4854 .. 4861, 4865,         4868 .. 4888, 4890 .. 4892,
              4895,

              5000 .. 5001, 5006 .. 5025, 5031 .. 5035, 5037 .. 5052,
              5061 .. 5076, 5081 .. 5098, 5106 .. 5118, 5120 .. 5121,
              5125 .. 5127, 5131 .. 5134, 5136 .. 5142, 5144,
              5150 .. 5174, 5201 .. 5204, 5210 .. 5214, 5220 .. 5223,
              5231 .. 5238, 5240 .. 5245, 5250 .. 5256, 5259 .. 5273,
              5275 .. 5280, 5290 .. 5291, 5301 .. 5304, 5306 .. 5311,
              5320 .. 5322, 5330 .. 5333, 5340 .. 5346, 5350 .. 5357,
              5360,         5371 .. 5374, 5381,         5400 .. 5401,
              5410 .. 5422, 5431 .. 5434, 5440,         5451 .. 5455,
              5460 .. 5462, 5464,         5470 .. 5473, 5480 .. 5483,
              5485,         5490 .. 5491, 5493,   5495, 5501 .. 5502,
              5510,         5520 .. 5523, 5540,   5550, 5552,
              5554 .. 5556, 5558,   5560, 5570 .. 5573, 5575 .. 5577,
              5580 .. 5583, 5600 .. 5609, 5630 .. 5633, 5640 .. 5642,
              5650 .. 5655, 5660 .. 5661, 5670 .. 5671, 5680,   5690,
              5700 .. 5701, 5710,         5719 .. 5720, 5722 .. 5725,
              5730 .. 5734, 5942,   5950,

              6000 .. 6001, 6003 .. 6012, 6014 .. 6038, 6041 .. 6044,
              6050 .. 6074, 6076 .. 6079, 6081 .. 6084, 6090,
              6100 .. 6112, 6121 .. 6126, 6147 .. 6176, 6180 .. 6182,
              6207 .. 6211, 6213 .. 6215, 6218,         6220 .. 6221,
              6223 .. 6233, 6236 .. 6237, 6239 .. 6240, 6243 .. 6244,
              6251 .. 6256, 6258,   6260, 6262,   6271, 6275,
              6280 .. 6282, 6284 .. 6286, 6288,   6290, 6302,   6304,
              6306,         6308 .. 6309, 6311 .. 6313, 6315 .. 6318,
              6320 .. 6324, 6326 .. 6328, 6330 .. 6333, 6335 .. 6338,
              6341,   6343, 6346,   6348, 6350 .. 6353, 6355 .. 6359,
              6361,   6363, 6365,         6367 .. 6370, 6372 .. 6373,
              6375,         6383 .. 6386, 6390 .. 6398, 6401,   6403,
              6405,   6407, 6409 .. 6415, 6418 .. 6434, 6436 .. 6438,
              6440,         6442 .. 6443, 6445 .. 6448, 6450,   6452,
              6460 .. 6463, 6465 .. 6468, 6470,         6472 .. 6473,
              6475 .. 6477, 6479 .. 6480, 6484 .. 6485, 6487 .. 6490,
              6501 .. 6507, 6509 .. 6519, 6521 .. 6522, 6525,   6528,
              6530 .. 6532, 6535 .. 6537, 6556,   6558, 6560,   6562,
              6564,         6566 .. 6569, 6571 .. 6572, 6574 .. 6575,
              6603,         6605 .. 6606, 6608 .. 6609, 6612 .. 6614,
              6616,   6620, 6623,   6625, 6627 .. 6628, 6630 .. 6632,
              6635,         6638 .. 6640, 6642,   6646, 6701,   6705,
              6707,         6710 .. 6714, 6716,   6718, 6720 .. 6722,
              6725 .. 6726, 6728,   6731, 6733,   6740, 6743,   6751,
              6753 .. 6754, 6758,   6760, 6762,   6765, 6770,
              6798 .. 6799, 6831,         6837 .. 6850, 6865,   6872,
              6892,         6901 .. 6907, 6909 .. 6926, 6929,
              6931 .. 6936, 6939,         6941 .. 6947, 6951 .. 6961,
              6963 .. 6970, 6979,         6981 .. 6992, 6997,

              7000 .. 7002, 7004 .. 7012, 7015 .. 7027, 7030,
              7050 .. 7055, 7109,         7112 .. 7113, 7116 .. 7117,
              7119 .. 7120, 7139 .. 7140, 7150 .. 7151, 7155,
              7162 .. 7163, 7170 .. 7180, 7182 .. 7187, 7190,
              7209 .. 7216, 7248 .. 7250, 7252 .. 7265, 7267 .. 7268,
              7270,         7275 .. 7277, 7290 .. 7292, 7300 .. 7307,
              7310,         7315 .. 7316, 7320 .. 7322, 7325,
              7330 .. 7331, 7466 .. 7470,

              8001 .. 8012,

              9726,
);

my %valid        =   map {$_  =>  1} @valid;
my %invalid      =   map {$_  =>  1} grep {!$valid {$_}} "0000" .. "9999";
my @invalid      =  sort {$a <=> $b} keys %invalid;


my $Test = Test::Regexp:: -> new -> init (
    pattern       =>  $RE {zip} {Australia},
    keep_pattern  =>  $RE {zip} {Australia} {-keep},
    name          => "Australian zip codes",
);

my $Test_lax = Test::Regexp:: -> new -> init (
    pattern       =>  $RE {zip} {Australia} {-lax},
    keep_pattern  =>  $RE {zip} {Australia} {-keep} {-lax},
    name          => "Australian zip codes, leading zero optional",
);

#
# Test all valid numbers
#
foreach my $valid (@valid) {
    $Test -> match ($valid,
                   [$valid, undef, $valid],
                   test => "Postal code $valid");
    $Test_lax -> match ($valid,
                       [$valid, undef, $valid],
                       test => "Postal code $valid");
    if ($valid =~ /^0/) {
        my $shorter = substr $valid, 1;
        $Test -> no_match  ($shorter, reason => "Leading 0 not optional");
        $Test_lax -> match ($shorter,
                           [$shorter, undef, $shorter],
                           test => "Postal code $valid with leading 0 omitted");
    }
}

#
# Test all invalid 4-digit numbers
#
foreach my $invalid (@invalid) {
    $Test     -> no_match ($invalid, reason => "Unused zip code $invalid");
    $Test_lax -> no_match ($invalid, reason => "Unused zip code $invalid");
}


#
# Can we prefix the zip code?
#
foreach my $test_obj ($Test, $Test_lax) {
    $test_obj -> match ("AU-0909",
                       ["AU-0909", "AU", "0909"],
                       test => "Use iso prefix");

    $test_obj -> match ("AUS-0909",
                       ["AUS-0909", "AUS", "0909"],
                       test => "Use cept prefix");

    $test_obj -> no_match ("AUT-0909", reason => "Invalid prefix");
}

done_testing;