class TestCase::Digest::MD5 {
  use Fn;
  use Digest::MD5;
  use Format;
  
  # Class Methods
  static method md5 : int () {
    {
      my $input = Fn->repeat("a", 10);
      my $output = Digest::MD5->md5($input);
      
      my $output_hex = "";
      
      for (my $i = 0; $i < 16; $i++) {
        $output_hex .= Format->sprintf("%x", [(object)(((int)$output->[$i]) & 0xFF)]);
      }
      
      unless ($output_hex eq "e09c80c42fda55f9d992e59ca6b3307d") {
        return 0;
      }
      
      return 1;
    }
    
    # Exception
    {
      eval { Digest::MD5->md5(undef); };
      unless (Fn->contains($@, "\$data must be defined")) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method md5_hex : int () {
    # Align
    {
      my $str = Fn->substr(Fn->repeat("\100", 20),1);
      unless (Digest::MD5->md5_hex($str) eq "c7ebb510e59ee96f404f288d14cc656a") {
        return 0;
      }
    }
    
    # Various inputs
    {
      my $expected_outputs = [
        "d41d8cd98f00b204e9800998ecf8427e",
        "0cc175b9c0f1b6a831c399e269772661",
        "4124bc0a9335c27f086f24ba207a4912",
        "47bce5c74f589f4867dbd57e9ca9f808",
        "74b87337454200d4d33f80c4663dc5e5",
        "594f803b380a41396ed63dca39503542",
        "0b4e7a0e5fe84ad35fb5f95b9ceeac79",
        "5d793fc5b00a2348c3fb9ab59e5ca98a",
        "3dbe00a167653a1aaee01d93e77e730e",
        "552e6a97297c53e592208cf97fbb3b60",
         "e09c80c42fda55f9d992e59ca6b3307d",
         "d57f21e6a273781dbf8b7657940f3b03",
         "45e4812014d83dde5666ebdf5a8ed1ed",
         "c162de19c4c3731ca3428769d0cd593d",
         "451599a5f9afa91a0f2097040a796f3d",
         "12f9cf6998d52dbe773b06f848bb3608",
         "23ca472302f49b3ea5592b146a312da0",
         "88e42e96cc71151b6e1938a1699b0a27",
         "2c60c24e7087e18e45055a33f9a5be91",
         "639d76897485360b3147e66e0a8a3d6c",
         "22d42eb002cefa81e9ad604ea57bc01d",
         "bd049f221af82804c5a2826809337c9b",
         "ff49cfac3968dbce26ebe7d4823e58bd",
         "d95dbfee231e34cccb8c04444412ed7d",
         "40edae4bad0e5bf6d6c2dc5615a86afb",
         "a5a8bfa3962f49330227955e24a2e67c",
         "ae791f19bdf77357ff10bb6b0e97e121",
         "aaab9c59a88bf0bdfcb170546c5459d6",
         "b0f0545856af1a340acdedce23c54b97",
         "f7ce3d7d44f3342107d884bfa90c966a",
         "59e794d45697b360e18ba972bada0123",
         "3b0845db57c200be6052466f87b2198a",
         "5eca9bd3eb07c006cd43ae48dfde7fd3",
         "b4f13cb081e412f44e99742cb128a1a5",
         "4c660346451b8cf91ef50f4634458d41",
         "11db24dc3f6c2145701db08625dd6d76",
         "80dad3aad8584778352c68ab06250327",
         "1227fe415e79db47285cb2689c93963f",
         "8e084f489f1bdf08c39f98ff6447ce6d",
         "08b2f2b0864bac1ba1585043362cbec9",
         "4697843037d962f62a5a429e611e0f5f",
         "10c4da18575c092b486f8ab96c01c02f",
         "af205d729450b663f48b11d839a1c8df",
         "0d3f91798fac6ee279ec2485b25f1124",
         "4c3c7c067634daec9716a80ea886d123",
         "d1e358e6e3b707282cdd06e919f7e08c",
         "8c6ded4f0af86e0a7e301f8a716c4363",
         "4c2d8bcb02d982d7cb77f649c0a2dea8",
         "bdb662f765cd310f2a547cab1cfecef6",
         "08ff5f7301d30200ab89169f6afdb7af",
         "6eb6a030bcce166534b95bc2ab45d9cf",
         "1bb77918e5695c944be02c16ae29b25e",
         "b6fe77c19f0f0f4946c761d62585bfea",
         "e9e7e260dce84ffa6e0e7eb5fd9d37fc",
         "eced9e0b81ef2bba605cbc5e2e76a1d0",
         "ef1772b6dff9a122358552954ad0df65",
         "3b0c8ac703f828b04c6c197006d17218",
         "652b906d60af96844ebd21b674f35e93",
         "dc2f2f2462a0d72358b2f99389458606",
         "762fc2665994b217c52c3c2eb7d9f406",
         "cc7ed669cf88f201c3297c6a91e1d18d",
         "cced11f7bbbffea2f718903216643648",
         "24612f0ce2c9d2cf2b022ef1e027a54f",
         "b06521f39153d618550606be297466d5",
         "014842d480b571495a4a0363793f7367",
         "c743a45e0d2e6a95cb859adae0248435",
         "def5d97e01e1219fb2fc8da6c4d6ba2f",
         "92cb737f8687ccb93022fdb411a77cca",
         "a0d1395c7fb36247bfe2d49376d9d133",
         "ab75504250558b788f99d1ebd219abf2",
         "0f5c6c4e740bfcc08c3c26ccb2673d46",
         "cddd19bec7f310d8c87149ef47a1828f",
         "96b39b8b95e016c79d104d83395b8133",
         "f1fc0b14ff8fa674b02344577e23eeb1",
         "0e8d28a1cafa3ffcff22afd480cce7d8",
         "448539ffc17e1e81005b65581855cef4",
         "61e39aae7c53e6e77db2e4405d9fb157",
         "618a426895ee6133a372bebd1129b63e",
         "046c90690c9e36578b9d4a7e1d249c75",
         "aadab38075c43296ee7e12466ebb03e3",
         "b15af9cdabbaea0516866a33d8fd0f98",
         "986e6938ed767a8ae9530eef54bfe5f1",
         "7ae25a72b71a42ccbc5477fd989cd512",
         "98d34e50d4aa7a893cc7919a91acb0e3",
         "3fc53fc22ea40f1a0afd78fc2cd9aa0f",
         "923e37c738b9d7b1526f70b65229cc3d",
         "b3966b7a08e5d46fd0774b797ba78dc2",
         "f50c7286b540bb181db1d6e05a51a296",
         "4efd6c8826e65a61f82af954d431b59b",
         "ef1031e79e7a15a4470a5e98b23781b5",
         "067876bfd0df0f4c5002780ec85e6f8c",
         "789851dfa4c03563e9cef5f7bc050a7e",
         "baf934720818ee49477e74fc644faa5e",
         "9a0ea77ca26d2c121ddcc179edb76308",
         "20c825561572e33d026f99ddfd999538",
         "464c461455c5a927079a13609c20b637",
         "cf37d42f89b6adb0e1a9e99104501b82",
         "d266af45e3d06b70d9f52e2df4344186",
         "f8b59fa22eb0ba944e2b7aa24d67b681",
         "0918d7c2f9062743450a86eae9dde1a3",
        "36a92cc94a9e0fa21f625f8bfb007adf",
        "681d73898dad5685d48b5e8438bc3a66",
        "337ccef058459c3c16411381778da0c4",
        "6ccdfcc742862036ce07583633c5f77e",
        "ddfa1adc974649dc5b414be86def7457",
        "650ebc28ad85f11aa4b63b6ee565b89d",
        "e4571793bcaba284017eeabd8df85697",
        "4fc040d354ad9ba5e4f62862109d3e17",
        "25814274e02aa7cc03d6314eb703e655",
        "11378ecaee0089c840d26352704027e3",
        "86f950bfcd824d5546da01c40576db31",
        "089f243d1e831c5879aa375ee364a06e",
        "9146ef3527c7cfcc66dc615c3986e391",
        "d727cfdfc9ed0347e6917a68b982f7bc",
        "da8f45e1fdc12deecfe56aeb5288796e",
        "29cfcf52d8250a253a535cf7989c7bd2",
        "0f6eb555b8e3c35411eebe9348594193",
        "a922439f963e7e59040e4756992c6f1b",
        "81f8453cf3f7e5ee5479c777e5a8d80c",
        "8a7bd0732ed6a28ce75f6dabc90e1613",
        "5f61c0ccad4cac44c75ff505e1f1e537",
        "f6acfca2d47c87f2b14ca038234d3614",
        "269fc62c517f3d55c368152addca57e7",
        "50587cb16413da779b35508018721647",
        "5e4a3ecfdaa4636b84a39b6a7be7c047",
        "c5339dc2af6bf595580281ffb07353f6",
        "e51176a47347e167ed0ed766b6de1a0c",
        "020406e1d05cdc2aa287641f7ae2cc39",
        "e510683b3f5ffe4093d021808bc6ff70",
        "b325dc1c6f5e7a2b7cf465b9feab7948",
        "e016e4ccc7fdaea56fc377600b58c4cb",
        "3870ec709d2fc64b255d65be3123ad69",
        "a92bde1f862c3fe797ecd69510bbd266",
        "04daa146f3a2256fdcbf015c0f67e168",
        "3d13c8bf627421ccc937aa1c9ac87bf1",
        "247dc7ffc545e4dda64ae12def481c4e",
        "2dfd4def392ee9563241b7db7eb7c346",
        "d11a18a4743a1a0a699d1704efb74a0d",
        "55b62fabd9c77d44d86e992eeeb093e6",
        "9a72cf7d0bd5ae2907c79f91837e3ced",
        "d3828cce1835534475029202ebd799e4",
        "b0bebbf0015658d4740679f263a3f01f",
        "02368ebf1f53bc4634211b1693021666",
        "04960f7d18960e348372949e4baa9752",
        "c6041e7a86d407e9402b175670519260",
        "439fd4c056bec1d14acd393746f6ae59",
        "81a855120e04494c5a6c874a2360fd57",
        "ef57bd47a964dc3aadd959c4131e64ac",
        "0b0ab27b16cbba267c141fe0f4ee9189",
        "abccd84f340bfe4ba59095cc3d5ca6ad",
        "bc620e8c15265f195c8818e2f3e3c58b",
        "fdcd84c4143286f6fc70c69208acd18d",
        "50e05071e773b1e9f3009a4a559ce6b2",
        "9e69c7a6c1863fbba2532f09ba665bde",
        "47a962111aa5187eeef3d17a278d95f2",
        "c13e57e33526bc713b5a1825f92651bc",
        "72b392f15593e42404b38e5c889fa75e",
        "5327acd3278274265d44e22ccfc4042c",
        "930dcac6da160b2a4c51879da76d3417",
        "41292c326f926f1534ead47fe302f0a0",
        "2bdecb5cf6b69a00f7832299ef2fb5a5",
        "8bf93e9e8a3e4396de3f211c788e177e",
        "eea9cb566e19d6a7f55fbae78d94ef2a",
        "3b8452700a829dec78397aa5c0458dd3",
        "7950059f699eaea1e0a1759340d7c153",
        "40840c5f1de00f17a8e70d5bd4d00af2",
        "80f86f6af38be9ca8e40c2dc44491a0a",
        "7aab2c2e72c77163e7102412dc332125",
        "bfd6869ae2ee2fe2675846d341eaa67d",
        "7e4d976f6d552d1d5bac7e2693dc8759",
        "37d9884c32abfc6f372ee899434e64ad",
        "e362cd83a4b49d81ac6788b7839a56fd",
        "9203cbb93b25d80b9d1b75e3c6c4b0dc",
        "77441eda11554ec5b915d942605f66ed",
        "e0fe0c02b5c9c5afe10ab9d6a3769efe",
        "cc7682cf11b214e928f3df899772e789",
        "ade0901d347afb25ecf9df4955bb8061",
        "987379587cbe8e94b7057269232ff826",
        "fd44a60101b04b7ddbc2b4e9b509ca1f",
        "53107a7f1e6f13a2e63239b6f2bf0ef1",
        "0b82cdd562f26aaa2459610a7ba8cd76",
        "79f12de7255e9c8c0ec9a9be45ee6210",
        "92338d8de02ed7aa8b3adc9120b94e71",
        "8fc48efda580fce85b8705d540e8382e",
        "63642b027ee89938c922722650f2eb9b",
        "fe54daa473502e9cc2c26dd66d564eab",
        "b90f3d4b7dcd8cdd8d96cb14695f4793",
        "3e73392e7a03bca45b67650d79a8fc63",
        "7fe51f2642dffbabc33eea2fcc2039ba",
        "bc33790e52f99718cf920329961ee753",
        "54d1e41ebac5db7886f01ab0afb65b17",
        "16e2824f7a3f00ef0028994182071953",
        "234c07907df5019d5f40f03936939bce",
        "8ea3af1d9476fa0b6c04ce4f3a336c03",
        "e95b69eae07d498d484afc771d1c45fc",
        "f22a673abbc4372544ba37b51a5f5a91",
        "7e6161eb1be7b06928c536fada91b7f1",
        "4dfe3c301e88fff67822e1cfcfece43f",
        "edda210ac6645fbf5815eb4c58821f6d",
        "6a514de2bf1926129b08f9234cd0115e",
        "887f30b43b2867f4a9accceee7d16e6c",
        "15936442c22dab9b685de350bfe75971",
        "281a39e10bab29f1f2dead149a1f3f87",
        "04d5f8a53b0eeda82d3c0ccafd02c98e",
        "a91e6b80fe9d6db74fac76c7a67f065a",
        "30334486fa9841044afb07f2573107a5",
        "0183c0cf15a3c2ed97d326f421b6d62c",
        "4dc2a01b2161653753019b5228f765f8",
        "71ef2dbdec7f78005354abebbfec8d8f",
        "a1d1cd1446c113726ba50cc86d8b6519",
        "ed6da79cfd13ece051c4cb7c88e80c2e",
        "d2047852ce178d4ddb7978da3883f9c5",
        "d75382e07dd096b618faeeac033eefff",
        "3fb48e286d462dcc237c3335aa63ba14",
        "55b959972677ea06c4d0e32f7fb2f10a",
        "0a479c3623cfb9745e54d3376d0b9ae2",
        "7825ad1ba19db7eec57d88b16936f32f",
        "833ccf25509cb423a4aa98accb15512d",
        "cae9609b05a9782610a5a43d7cd4b8ff",
        "6c303e1da7f8a3032d13fe995847a722",
        "4c47143a568e30ecde86dafe3bcb0558",
        "9c48f0592f504b86360cfb6de00203b3",
        "e1524f5686f170209366f9723880d9b0",
        "a96164a43a192543d40e538b9e9e4ece",
        "b774a4f788458a60e131d998705e4a06",
        "1e97f0a7dfd3fac6ae585acdcf51a549",
        "b6364c77b6dd495c2a7f6b0211ac6fce",
        "5d22315e78df2bc4146aa66f6c405dbb",
        "2a773d5b04e910612543a42deeaaaa62",
        "0165449ac66b086accdec3051e0b691e",
        "54884ba571054eae72b2a5271828a1fc",
        "520fb61f8625ea916d72a54a37937bc6",
        "7717f05d6e424a2c7a20ab7977b21ec8",
        "b64e4f62e3e14317e3a90f9ff2cde576",
        "a49128259cfe50ba3bed80bbd11add7f",
        "b10cb153b79c2e4af6a8431c265aa82d",
        "2e50fee6f574241042bdfabfdd46a153",
        "5d5656a09b98c24edd01c530d3aad5e2",
        "5ac1e1609d82274371c349d5b7875298",
        "b7b40d64ffccebd78abcf522376b3aae",
        "8619933469d908a2d4a2d890909bea43",
        "591a0ee6dccd872b46ae184eb0f9450e",
        "8cd256a02c8c5c1676e9220e655d9ac4",
        "e48c0e2ed3e4e299a6e62e5416eb6d83",
        "f30f75dce71e757ee562218c1efa0645",
        "06bd7e90c0410dacb155732cf956f520",
        "531a0a821a9304c215f1829b880306f1",
        "93f4621c0b88499297ec3f8fbb3fb9c4",
        "6af3d61e2e3ef8e189cffbea802c7e69",
        "df84d21c884f99d6764d9bca4dec26e1",
        "1bdbdf1c9087c796394bcda5789f7206",
        "21f5b107cda33036590a19419afd7fb6",
        "0eae304c738191613302fb6721ea3605",
        "abed9cdef66dcec954b87124ba18c1ab",
        "dfde09457e2017e31d4ecfaea010db8f",
        "46bc249a5a8fc5d622cf12c42c463ae0",
        "81109eec5aa1a284fb5327b10e9c16b9",
      ];

      my $ok = 1;
      for (my $i = 0; $i <= 256; $i++) {
        my $input = Fn->repeat("a", $i);
        
        my $output = Digest::MD5->md5_hex($input);
        unless ($output eq $expected_outputs->[$i]) {
          $ok = 0;
        }
      }
      
      unless ($ok) {
        return 0;
      }
    }
    # Exception
    {
      eval { Digest::MD5->md5_hex(undef); };
      unless (Fn->contains($@, "\$data must be defined")) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method new : int () {
    {
      my $md5 = Digest::MD5->new;
      
      unless ($md5 is_type Digest::MD5) {
        return 0;
      }
    }
    
    return 1;
  }
  
  # Instance Methods
  static method add : int () {
    {
      my $input = Fn->repeat("a", 10);
      my $md5 = Digest::MD5->new;
      $md5->add($input);
      my $output = $md5->hexdigest;
      unless ($output eq "e09c80c42fda55f9d992e59ca6b3307d") {
        return 0;
      }
    }
    
    # Exception
    {
      eval { Digest::MD5->new->add(undef); };
      unless (Fn->contains($@, "\$data must be defined")) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method digest : int () {
    {
      my $input = Fn->repeat("a", 10);
      my $md5 = Digest::MD5->new;
      $md5->add($input);
      my $output = $md5->digest;
      
      my $output_hex = "";
      
      for (my $i = 0; $i < 16; $i++) {
        $output_hex .= Format->sprintf("%x", [(object)(((int)$output->[$i]) & 0xFF)]);
      }
      
      unless ($output_hex eq "e09c80c42fda55f9d992e59ca6b3307d") {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method hexdigest : int () {
    {
      my $input = Fn->repeat("a", 10);
      my $md5 = Digest::MD5->new;
      $md5->add($input);
      my $output = $md5->hexdigest;
      unless ($output eq "e09c80c42fda55f9d992e59ca6b3307d") {
        return 0;
      }
    }
    
    return 1;
  }
  
}