packages feed

pcre-light-0.1: tests/Unit.hs

{-# LANGUAGE OverloadedStrings #-}

import Text.Regex.PCRE.Light
import qualified Text.Regex.PCRE.Light.Char8 as String

import qualified Data.ByteString.Char8 as S
import System.IO

import Test.HUnit
import System.Exit (exitFailure)
import Control.Monad (when)
import System.IO
import Data.Either
import qualified Data.Map as M

testRegex :: S.ByteString
     -> [PCREOption]
     -> [S.ByteString]
     -> [Maybe [S.ByteString]]
     -> Test

testRegex regex options inputs outputs = TestLabel (S.unpack regex) $
  TestCase $ do
     assertEqual "Input/Output Length Check" (length inputs) (length outputs)

     assertBool "ByteString regex" =<<
      case compile regex options of
        Left  s -> do hPutStrLn stderr ("ERROR in ByteString: "++ show s)
                      return False
        Right r -> return $
            and [ match r i [] == o
                | (i,o) <- zip inputs outputs ]

     assertBool "String regex" =<<
      case String.compile (S.unpack regex) options of
        Left  s -> do hPutStrLn stderr ("ERROR in String: "++ show s)
                      return False
        Right r -> return $
            and [ String.match r i [] == o
                | (i,o) <- zip (map (S.unpack) inputs)
                               (map (fmap (map S.unpack)) outputs) ]

main = do counts <- runTestTT tests
          when (errors counts > 0 || failures counts > 0) exitFailure

tests = TestList

    [ testRegex "the quick brown fox" []
           [ "the quick brown fox"
           , "The quick brown FOX"
           , "What do you know about the quick brown fox?"
           , "What do you know about THE QUICK BROWN FOX?"
           ]
           [ Just ["the quick brown fox"]
           , Nothing
           , Just ["the quick brown fox"]
           , Nothing
           ]

--  , testRegex "\0*" [] -- the embedded null in the pattern seems to be a problem
--      ["\0\0\0\0"]
--      [Just ["\0\0\0\0"]]

    , testRegex "\1*" [] -- the embedded null in the pattern seems to be a problem
        ["\1\1\1\1"]
        [Just ["\1\1\1\1"]]

    , testRegex "The quick brown fox" [caseless]
           ["the quick brown fox"
           ,"The quick brown FOX"
           ,"What do you know about the quick brown fox?"
           ,"What do you know about THE QUICK BROWN FOX?"
           ]
           [ Just ["the quick brown fox"]
           , Just ["The quick brown FOX"]
           , Just ["the quick brown fox"]
           , Just ["THE QUICK BROWN FOX"]
           ]

     , testRegex "a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz" []
           ["abxyzpqrrrabbxyyyypqAzz"
           ,"abxyzpqrrrabbxyyyypqAzz"
           ,"aabxyzpqrrrabbxyyyypqAzz"
           ,"aaabxyzpqrrrabbxyyyypqAzz"
           ,"aaaabxyzpqrrrabbxyyyypqAzz"
           ,"abcxyzpqrrrabbxyyyypqAzz"
           ,"aabcxyzpqrrrabbxyyyypqAzz"
           ,"aaabcxyzpqrrrabbxyyyypAzz"
           ,"aaabcxyzpqrrrabbxyyyypqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqqqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqqqqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqqqqqAzz"
           ,"aaaabcxyzpqrrrabbxyyyypqAzz"
           ,"abxyzzpqrrrabbxyyyypqAzz"
           ,"aabxyzzzpqrrrabbxyyyypqAzz"
           ,"aaabxyzzzzpqrrrabbxyyyypqAzz"
           ,"aaaabxyzzzzpqrrrabbxyyyypqAzz"
           ,"abcxyzzpqrrrabbxyyyypqAzz"
           ,"aabcxyzzzpqrrrabbxyyyypqAzz"
           ,"aaabcxyzzzzpqrrrabbxyyyypqAzz"
           ,"aaaabcxyzzzzpqrrrabbxyyyypqAzz"
           ,"aaaabcxyzzzzpqrrrabbbxyyyypqAzz"
           ,"aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"
           ,"aaabcxyzpqrrrabbxyyyypABzz"
           ,"aaabcxyzpqrrrabbxyyyypABBzz"
           ,">>>aaabxyzpqrrrabbxyyyypqAzz"
           ,">aaaabxyzpqrrrabbxyyyypqAzz"
           ,">>>>abcxyzpqrrrabbxyyyypqAzz"
           ,"abxyzpqrrabbxyyyypqAzz"
           ,"abxyzpqrrrrabbxyyyypqAzz"
           ,"abxyzpqrrrabxyyyypqAzz"
           ,"aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz"
           ,"aaaabcxyzzzzpqrrrabbbxyyypqAzz"
           ,"aaabcxyzpqrrrabbxyyyypqqqqqqqAzz"
           ]

           [ Just ["abxyzpqrrrabbxyyyypqAzz"]
           , Just ["abxyzpqrrrabbxyyyypqAzz"]
           , Just ["aabxyzpqrrrabbxyyyypqAzz"]
           , Just ["aaabxyzpqrrrabbxyyyypqAzz"]
           , Just ["aaaabxyzpqrrrabbxyyyypqAzz"]
           , Just ["abcxyzpqrrrabbxyyyypqAzz"]
           , Just ["aabcxyzpqrrrabbxyyyypqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqqqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqqqqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqqqqqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypqqqqqqAzz"]
           , Just ["aaaabcxyzpqrrrabbxyyyypqAzz"]
           , Just ["abxyzzpqrrrabbxyyyypqAzz"]
           , Just ["aabxyzzzpqrrrabbxyyyypqAzz"]
           , Just ["aaabxyzzzzpqrrrabbxyyyypqAzz"]
           , Just ["aaaabxyzzzzpqrrrabbxyyyypqAzz"]
           , Just ["abcxyzzpqrrrabbxyyyypqAzz"]
           , Just ["aabcxyzzzpqrrrabbxyyyypqAzz"]
           , Just ["aaabcxyzzzzpqrrrabbxyyyypqAzz"]
           , Just ["aaaabcxyzzzzpqrrrabbxyyyypqAzz"]
           , Just ["aaaabcxyzzzzpqrrrabbbxyyyypqAzz"]
           , Just ["aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypABzz"]
           , Just ["aaabcxyzpqrrrabbxyyyypABBzz"]
           , Just ["aaabxyzpqrrrabbxyyyypqAzz"]
           , Just ["aaaabxyzpqrrrabbxyyyypqAzz"]
           , Just ["abcxyzpqrrrabbxyyyypqAzz"]
           , Nothing
           , Nothing
           , Nothing
           , Nothing
           , Nothing
           , Nothing
           ]

    , testRegex "^(abc){1,2}zz" []
        ["abczz"
        ,"abcabczz"
        ,"zz"
        ,"abcabcabczz"
        ,">>abczz"]
        [ Just ["abczz","abc"]
        , Just ["abcabczz", "abc"]
        , Nothing
        , Nothing
        , Nothing ]

    , testRegex "^(b+?|a){1,2}?c" []
        ["bc",
         "bbc",
         "bbbc",
         "bac",
         "bbac",
         "aac",
         "abbbbbbbbbbbc",
         "bbbbbbbbbbbac",
         "aaac",
         "abbbbbbbbbbbac"]

        [Just ["bc", "b"],
         Just ["bbc", "b"],
         Just ["bbbc", "bb"],
         Just ["bac", "a"],
         Just ["bbac", "a"],
         Just ["aac", "a"],
         Just ["abbbbbbbbbbbc", "bbbbbbbbbbb"],
         Just ["bbbbbbbbbbbac", "a"],
         Nothing,
         Nothing]

    , testRegex "^(b+|a){1,2}c" []
        ["bc",
         "bbc",
         "bbbc",
         "bac",
         "bbac",
         "aac",
         "abbbbbbbbbbbc",
         "bbbbbbbbbbbac",
         "aaac",
         "abbbbbbbbbbbac"]
        [Just ["bc", "b"],
         Just ["bbc", "bb"],
         Just ["bbbc", "bbb"],
         Just ["bac", "a"],
         Just ["bbac", "a"],
         Just ["aac", "a"],
         Just ["abbbbbbbbbbbc", "bbbbbbbbbbb"],
         Just ["bbbbbbbbbbbac", "a"],
         Nothing,
         Nothing]

    , testRegex "^(b+|a){1,2}?bc" []
        ["bbc"]
        [Just ["bbc", "b"]]

    , testRegex "^(b*|ba){1,2}?bc" []
        ["babc",
         "bbabc",
         "bababc",
         "bababbc",
         "babababc"]
        [Just ["babc","ba"],
         Just ["bbabc","ba"],
         Just ["bababc","ba"],
         Nothing,
         Nothing]

    , testRegex "^(ba|b*){1,2}?bc" []
        ["babc",
         "bbabc",
         "bababc",
         "bababbc",
         "babababc"]
        [Just ["babc","ba"],
         Just ["bbabc","ba"],
         Just ["bababc","ba"],
         Nothing,
         Nothing]

    , testRegex "^[ab\\]cde]" []
        ["athing",
         "bthing",
         "]thing",
         "cthing",
         "dthing",
         "ething",
         "fthing",
         "[thing",
         "\\\\thing"]
        [Just ["a"],
         Just ["b"],
         Just ["]"],
         Just ["c"],
         Just ["d"],
         Just ["e"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^[]cde]" []
        ["]thing",
         "cthing",
         "dthing",
         "ething",
         "athing",
         "fthing"]
        [Just ["]"],
         Just ["c"],
         Just ["d"],
         Just ["e"],
         Nothing,
         Nothing]

    , testRegex "^[^ab\\]cde]" []
        ["fthing",
         "[thing",
         "\\\\thing",
         "athing",
         "bthing",
         "]thing",
         "cthing",
         "dthing",
         "ething"]
        [Just ["f"],
         Just ["["],
         Just ["\\"],
         Nothing,
         Nothing,
         Nothing,
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^\129" []
        ["\129"]
        [Just ["\x81"]]

    , testRegex "^\255" []
        ["\255"]
        [Just ["\xff"]]

    , testRegex "^[0-9]+$" []
        ["0",
         "1",
         "2",
         "3",
         "4",
         "5",
         "6",
         "7",
         "8",
         "9",
         "10",
         "100",
         "abc"]
        [Just ["0"],
         Just ["1"],
         Just ["2"],
         Just ["3"],
         Just ["4"],
         Just ["5"],
         Just ["6"],
         Just ["7"],
         Just ["8"],
         Just ["9"],
         Just ["10"],
         Just ["100"],
         Nothing]

    , testRegex "^.*nter" []
        ["enter",
         "inter",
         "uponter"]
        [Just ["enter"],
         Just ["inter"],
         Just ["uponter"]]

    , testRegex "^xxx[0-9]+$" []
        ["xxx0",
         "xxx1234",
         "xxx"]
        [Just ["xxx0"],
         Just ["xxx1234"],
         Nothing]

    , testRegex "^.+[0-9][0-9][0-9]$" []
        ["x123",
         "xx123",
         "123456",
         "123",
         "x1234"]
        [Just ["x123"],
         Just ["xx123"],
         Just ["123456"],
         Nothing,
         Just ["x1234"]]

    , testRegex "^.+?[0-9][0-9][0-9]$" []
        ["x123",
         "xx123",
         "123456",
         "123",
         "x1234"]
        [Just ["x123"],
         Just ["xx123"],
         Just ["123456"],
         Nothing,
         Just ["x1234"]]

    -- test matching more than 1 subpattern
    , testRegex "^([^!]+)!(.+)=apquxz\\.ixr\\.zzz\\.ac\\.uk$" []
        ["abc!pqr=apquxz.ixr.zzz.ac.uk",
         "!pqr=apquxz.ixr.zzz.ac.uk",
         "abc!=apquxz.ixr.zzz.ac.uk",
         "abc!pqr=apquxz:ixr.zzz.ac.uk",
         "abc!pqr=apquxz.ixr.zzz.ac.ukk"]
        [Just ["abc!pqr=apquxz.ixr.zzz.ac.uk", "abc", "pqr"],
         Nothing,
         Nothing,
         Nothing,
         Nothing]

    , testRegex ":" []
        ["Well, we need a colon: somewhere",
         "*** Fail if we don't"]
        [Just [":"],
         Nothing]

    , testRegex "([\\da-f:]+)$" [caseless]
        ["0abc",
         "abc",
         "fed",
         "E",
         "::",
         "5f03:12C0::932e",
         "fed def",
         "Any old stuff",
         "*** Failers",
         "0zzz",
         "gzzz",
         "fed\x20",
         "Any old rubbish"]
        [Just ["0abc", "0abc"],
         Just ["abc", "abc"],
         Just ["fed", "fed"],
         Just ["E", "E"],
         Just ["::", "::"],
         Just ["5f03:12C0::932e", "5f03:12C0::932e"],
         Just ["def", "def"],
         Just ["ff", "ff"],
         Nothing,
         Nothing,
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^.*\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$" []
        [".1.2.3",
         "A.12.123.0",
         ".1.2.3333",
         "1.2.3",
         "1234.2.3"]
        [Just [".1.2.3", "1", "2", "3"],
         Just ["A.12.123.0", "12", "123", "0"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^(\\d+)\\s+IN\\s+SOA\\s+(\\S+)\\s+(\\S+)\\s*\\(\\s*$" []
        ["1 IN SOA non-sp1 non-sp2(",
         "1    IN    SOA    non-sp1    non-sp2   (",
         "1IN SOA non-sp1 non-sp2("]
        [Just ["1 IN SOA non-sp1 non-sp2(", "1", "non-sp1", "non-sp2"],
         Just ["1    IN    SOA    non-sp1    non-sp2   (", "1", "non-sp1", "non-sp2"],
         Nothing]

    , testRegex "^[a-zA-Z\\d][a-zA-Z\\d\\-]*(\\.[a-zA-Z\\d][a-zA-z\\d\\-]*)*\\.$" []
        ["a.",
         "Z.",
         "2.",
         "ab-c.pq-r.",
         "sxk.zzz.ac.uk.",
         "x-.y-.",
         "*** Failers",
         "-abc.peq."]
        [Just ["a."],
         Just ["Z."],
         Just ["2."],
         Just ["ab-c.pq-r.", ".pq-r"],
         Just ["sxk.zzz.ac.uk.", ".uk"],
         Just ["x-.y-.", ".y-"],
         Nothing,
         Nothing]

    , testRegex "^\\*\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?(\\.[a-z]([a-z\\-\\d]*[a-z\\d]+)?)*$" []
        ["*.a",
         "*.b0-a",
         "*.c3-b.c",
         "*.c-a.b-c",
         "*** Failers",
         "*.0",
         "*.a-",
         "*.a-b.c-",
         "*.c-a.0-c"]
        [Just ["*.a"],
         Just ["*.b0-a", "0-a"],
         Just ["*.c3-b.c", "3-b", ".c"],
         Just ["*.c-a.b-c", "-a", ".b-c", "-c"],
         Nothing,
         Nothing,
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^(?=ab(de))(abd)(e)" []
        ["abde"]
        [Just ["abde", "de", "abd", "e"]]

    , testRegex "^(?!(ab)de|x)(abd)(f)" []
        ["abdf"]
        [Just ["abdf", "", "abd", "f"]]

    , testRegex "^(?=(ab(cd)))(ab)" []
        ["abcd"]
        [Just ["ab", "abcd", "cd", "ab"]]

    , testRegex "^[\\da-f](\\.[\\da-f])*$" [caseless]
        ["a.b.c.d",
         "A.B.C.D",
         "a.b.c.1.2.3.C"]
        [Just ["a.b.c.d", ".d"],
         Just ["A.B.C.D", ".D"],
         Just ["a.b.c.1.2.3.C", ".C"]]

    , testRegex "^\".*\"\\s*(;.*)?$" []
        ["\"1234\"",
         "\"abcd\" ;",
         "\"\" ; rhubarb",
         "*** Failers",
         "\\\"1234\\\" : things"]
        [Just ["\"1234\""],
         Just ["\"abcd\" ;", ";"],
         Just ["\"\" ; rhubarb", "; rhubarb"],
         Nothing,
         Nothing]

    , testRegex "^$" []
        ["",
         "*** Failers"]
        [Just [""],
         Nothing]

    , testRegex "   ^    a   (?# begins with a)  b\\sc (?# then b c) $ (?# then end)" [extended]
        ["ab c",
         "*** Failers",
         "abc",
         "ab cde"]
        [Just ["ab c"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "(?x)   ^    a   (?# begins with a)  b\\sc (?# then b c) $ (?# then end)" []
        ["ab c",
         "*** Failers",
         "abc",
         "ab cde"]
        [Just ["ab c"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^   a\\ b[c ]d       $" [extended]
        ["a bcd",
         "a b d",
         "*** Failers",
         "abcd",
         "ab d"]
        [Just ["a bcd"],
         Just ["a b d"],
         Nothing,
         Nothing,
         Nothing]

    , TestLabel "compile failure" $
            TestCase $ (assertBool "compile failure" $ Left "nothing to repeat"== compile "*" [])

    , testRegex "^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$" []
        ["abcdefhijklm"]
        [Just ["abcdefhijklm",
               "abc", "bc",
               "c", "def",
               "ef", "f",
               "hij", "ij",
               "j", "klm",
               "lm", "m"]]

    , testRegex "^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$" []
        ["abcdefhijklm"]
        [Just ["abcdefhijklm",
             "bc", "c", "ef", "f", "ij", "j", "lm", "m"]]

    , testRegex "^[.^$|()*+?{,}]+" []
        [".^$(*+)|{?,?}"]
        [Just [".^$(*+)|{?,?}"]]

    , testRegex "^a*\\w" []
        ["z",
         "az",
         "aaaz",
         "a",
         "aa",
         "aaaa",
         "a+",
         "aa+"]
        [Just ["z"],
         Just ["az"],
         Just ["aaaz"],
         Just ["a"],
         Just ["aa"],
         Just ["aaaa"],
         Just ["a"],
         Just ["aa"]]

    , testRegex "^a*?\\w" []
        ["z",
         "az",
         "aaaz",
         "a",
         "aa",
         "aaaa",
         "a+",
         "aa+"]
        [Just ["z"],
         Just ["a"],
         Just ["a"],
         Just ["a"],
         Just ["a"],
         Just ["a"],
         Just ["a"],
         Just ["a"]]

    , testRegex "^a+\\w" []
        ["az",
         "aaaz",
         "aa",
         "aaaa",
         "aa+"]
        [Just ["az"],
         Just ["aaaz"],
         Just ["aa"],
         Just ["aaaa"],
         Just ["aa"]]

    , testRegex "^a+?\\w" []
        ["az",
         "aaaz",
         "aa",
         "aaaa",
         "aa+"]
        [Just ["az"],
         Just ["aa"],
         Just ["aa"],
         Just ["aa"],
         Just ["aa"]]

    , testRegex "^\\d{8}\\w{2,}" []
        ["1234567890",
         "12345678ab",
         "12345678__",
         "*** Failers",
         "1234567"]
        [Just ["1234567890"],
         Just ["12345678ab"],
         Just ["12345678__"],
         Nothing,
         Nothing]

    , testRegex "^[aeiou\\d]{4,5}$" []
        ["uoie",
         "1234",
         "12345",
         "aaaaa",
         "*** Failers",
         "123456"]
        [Just ["uoie"],
         Just ["1234"],
         Just ["12345"],
         Just ["aaaaa"],
         Nothing,
         Nothing]

    , testRegex "^[aeiou\\d]{4,5}?" []
        ["uoie",
         "1234",
         "12345",
         "aaaaa",
         "123456"]
        [Just ["uoie"],
         Just ["1234"],
         Just ["1234"],
         Just ["aaaa"],
         Just ["1234"]]

    , testRegex "\\A(abc|def)=(\\1){2,3}\\Z" []
        ["abc=abcabc",
         "def=defdefdef",
         "*** Failers",
         "abc=defdef"]
        [Just ["abc=abcabc", "abc", "abc"],
         Just ["def=defdefdef", "def", "def"],
         Nothing,
         Nothing]

    , testRegex "^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11*(\\3\\4)\\1(?#)2$" []
        ["abcdefghijkcda2",
         "abcdefghijkkkkcda2"]
        [Just ["abcdefghijkcda2", "a", "b",
         "c", "d", "e", "f", "g", "h", "i", "j", "k", "cd"],

         Just ["abcdefghijkkkkcda2", "a", "b", "c", "d",
             "e", "f", "g", "h", "i", "j", "k", "cd"]]

    , testRegex "(cat(a(ract|tonic)|erpillar)) \\1()2(3)" []
        ["cataract cataract23",
         "catatonic catatonic23",
         "caterpillar caterpillar23"]

        [Just ["cataract cataract23", "cataract", "aract", "ract", "", "3"],

         Just ["catatonic catatonic23", "catatonic", "atonic", "tonic", "", "3"],

         Just ["caterpillar caterpillar23", "caterpillar", "erpillar", "", "", "3"]]

    , testRegex "^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]" []
        ["From abcd  Mon Sep 01 12:33:02 1997"]
        [Just ["From abcd  Mon Sep 01 12:33", "abcd"]]

    , testRegex "^From\\s+\\S+\\s+([a-zA-Z]{3}\\s+){2}\\d{1,2}\\s+\\d\\d:\\d\\d" []
        ["From abcd  Mon Sep 01 12:33:02 1997",
         "From abcd  Mon Sep  1 12:33:02 1997",
         "*** Failers",
         "From abcd  Sep 01 12:33:02 1997"]
        [Just ["From abcd  Mon Sep 01 12:33", "Sep "],
         Just ["From abcd  Mon Sep  1 12:33", "Sep  "],
         Nothing,
         Nothing]

    , testRegex "\\w+(?=\t)" []
        ["the quick brown\t fox"]
        [Just ["brown"]]

    , testRegex "foo(?!bar)(.*)" []
        ["foobar is foolish see?"]
        [Just ["foolish see?", "lish see?"]]

    , testRegex "(?:(?!foo)...|^.{0,2})bar(.*)" []
        ["foobar crowbar etc",
         "barrel",
         "2barrel",
         "A barrel"]
        [Just ["rowbar etc", " etc"],
         Just ["barrel",     "rel"],
         Just ["2barrel",    "rel"],
         Just ["A barrel",   "rel"]]

    , testRegex "^(\\D*)(?=\\d)(?!123)" []
        ["abc456",
         "*** Failers",
         "abc123"]
        [Just ["abc", "abc"],
         Nothing,
         Nothing]

    , testRegex "^(a)\\1{2,3}(.)" []
        ["aaab",
         "aaaab",
         "aaaaab",
         "aaaaaab"]
        [Just ["aaab", "a","b"],
         Just ["aaaab","a","b"],
         Just ["aaaaa","a","a"],
         Just ["aaaaa","a","a"]]

    , testRegex "(?!^)abc" []
        ["the abc",
         "*** Failers",
         "abc"]
        [Just ["abc"],
         Nothing,
         Nothing]

    , testRegex "(?=^)abc" []
        ["abc",
         "*** Failers",
         "the abc"]
        [Just ["abc"],
         Nothing,
         Nothing]

    , testRegex "^[ab]{1,3}(ab*|b)" []
        ["aabbbbb"]
        [Just ["aabb", "b"]]

    , testRegex "^[ab]{1,3}?(ab*|b)" []
        ["aabbbbb"]
        [Just ["aabbbbb", "abbbbb"]]

    , testRegex "^[ab]{1,3}?(ab*?|b)" []
        ["aabbbbb"]
        [Just ["aa", "a"]]

    , testRegex "^[ab]{1,3}(ab*?|b)" []
        ["aabbbbb"]
        [Just ["aabb", "b"]]

    , testRegex "^(cow|)\\1(bell)" []
        ["cowcowbell",
         "bell",
         "*** Failers",
         "cowbell"]
        [Just ["cowcowbell", "cow", "bell"],
         Just ["bell", "", "bell"],
         Nothing,
         Nothing]

    , testRegex "^\\s" []
        ["\o40abc",
         "\nabc",
         "\rabc",
         "\tabc",
         "abc"]
        [Just [" "],
         Just ["\x0a"],
         Just ["\x0d"],
         Just ["\x09"],
         Nothing]

    , testRegex "^(a|)\\1*b" []
        ["ab",
         "aaaab",
         "b",
         "acb"]
        [Just ["ab", "a"],
         Just ["aaaab", "a"],
         Just ["b", ""],
         Nothing]

    , testRegex "^(a|)\\1+b" []
        ["aab",
         "aaaab",
         "b",
         "*** Failers",
         "ab"]
        [Just ["aab", "a"],
         Just ["aaaab", "a"],
         Just ["b", ""],
         Nothing,
         Nothing]

    , testRegex "^(a|)\\1?b" []
        ["ab",
         "aab",
         "b",
         "acb"]
        [Just ["ab", "a"],
         Just ["aab", "a"],
         Just ["b", ""],
         Nothing]

    , testRegex "^(a|)\\1{2}b" []
        ["aaab",
         "b",
         "ab",
         "aab",
         "aaaab"]
        [Just ["aaab", "a"],
         Just ["b", ""],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^(a|)\\1{2,3}b" []
        ["aaab",
         "aaaab",
         "b",
         "ab",
         "aab",
         "aaaaab"]
        [Just ["aaab", "a"],
         Just ["aaaab", "a"],
         Just ["b", ""],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "ab{1,3}bc" []
        ["abbbbc",
         "abbbc",
         "abbc",
         "abc",
         "abbbbbc"]
        [Just ["abbbbc"],
         Just ["abbbc"],
         Just ["abbc"],
         Nothing,
         Nothing]

    , testRegex "([^.]*)\\.([^:]*):[T ]+(.*)" []
        ["track1.title:TBlah blah blah"]
        [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]

    , testRegex "([^.]*)\\.([^:]*):[T ]+(.*)" [caseless]
        ["track1.title:TBlah blah blah"]
        [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]

    , testRegex "([^.]*)\\.([^:]*):[t ]+(.*)" [caseless]
        ["track1.title:TBlah blah blah"]
        [Just ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]]

    , testRegex "^[W-c]+$" []
        ["WXY_^abc",
         "wxy"]
        [Just ["WXY_^abc"],
         Nothing]

    , testRegex "^[W-c]+$" [caseless]
        ["WXY_^abc",
         "wxy_^ABC"]
        [Just ["WXY_^abc"],
         Just ["wxy_^ABC"]]

    , testRegex "^[\\x3f-\\x5F]+$" [caseless]
        ["WXY_^abc",
         "wxy_^ABC"]
        [Just ["WXY_^abc"],
         Just ["wxy_^ABC"]]

    , testRegex "^abc$" []
        ["abc",
         "qqq\\nabc",
         "abc\\nzzz",
         "qqq\\nabc\\nzzz"]
        [Just ["abc"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "(?:b)|(?::+)" []
        ["b::c",
         "c::b"]
        [Just ["b"],
         Just ["::"]]

    , testRegex "[-az]+" []
        ["az-",
         "*** Failers",
         "b"]
        [Just ["az-"],
         Just ["a"],
         Nothing]

    , testRegex "[az-]+" []
        ["za-",
         "*** Failers",
         "b"]
        [Just ["za-"],
         Just ["a"],
         Nothing]

    , testRegex "[a\\-z]+" []
        ["a-z",
         "*** Failers",
         "b"]
        [Just ["a-z"],
         Just ["a"],
         Nothing]

    , testRegex "[a-z]+" []
        ["abcdxyz"]
        [Just ["abcdxyz"]]

    , testRegex "[\\d-]+" []
        ["12-34",
         "aaa"]
        [Just ["12-34"],
         Nothing]
    , testRegex "[\\d-z]+" []
        ["12-34z",
         "aaa"]
        [Just ["12-34z"],
         Nothing]

    , testRegex "\\x20Z" []
        ["the Zoo",
         "*** Failers",
         "Zulu"]
        [Just [" Z"],
         Nothing,
         Nothing]

    , testRegex "(abc)\\1" [caseless]
        ["abcabc",
         "ABCabc",
         "abcABC"]
        [Just ["abcabc", "abc"],
         Just ["ABCabc", "ABC"],
         Just ["abcABC", "abc"]]

    , testRegex "ab{3cd" []
        ["ab{3cd"]
        [Just ["ab{3cd"]]

    , testRegex "ab{3,cd" []
        ["ab{3,cd"]
        [Just ["ab{3,cd"]]

    , testRegex "ab{3,4a}cd" []
        ["ab{3,4a}cd"]
        [Just ["ab{3,4a}cd"]]

    , testRegex "{4,5a}bc" []
        ["{4,5a}bc"]
        [Just ["{4,5a}bc"]]

    , testRegex "abc$" []
        ["abc",
         "abc\n",
         "*** Failers",
         "abc\ndef"]
        [Just ["abc"],
         Just ["abc"],
         Nothing,
         Nothing]

    , testRegex "(abc)\\123" []
        ["abc\x53"]
        [Just ["abcS", "abc"]]

    , testRegex "(abc)\\223" []
        ["abc\x93"]
        [Just ["abc\x93", "abc"]]

    , testRegex "(abc)\\323" []
        ["abc\xd3"]
        [Just ["abc\xd3", "abc"]]

    , testRegex "(abc)\\100" []
        ["abc\x40",
         "abc\o100"]
        [Just ["abc@", "abc"],
         Just ["abc@", "abc"]]

    , testRegex "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\12\\123" []
        ["abcdefghijkllS"]
        [Just ["abcdefghijkllS",
             "a",
             "b",
             "c",
             "d",
             "e",
             "f",
             "g",
             "h",
             "i",
             "j",
             "k",
             "l"]]

     , testRegex "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\12\\123" []
        ["abcdefghijk\o12S"]
        [Just ["abcdefghijk\x0aS",
             "a",
             "b",
             "c",
             "d",
             "e",
             "f",
             "g",
             "h",
             "i",
             "j",
             "k"]]

    , testRegex "ab\\idef" []
        ["abidef"]
        [Just ["abidef"]]

    , testRegex "a{0}bc" []
        ["bc"]
        [Just ["bc"]]

    , testRegex "(a|(bc)){0,0}?xyz" []
        ["xyz"]
        [Just ["xyz"]]

    , testRegex "(?s)a.b" []
        ["a\nb"]
        [Just ["a\nb"]]

    , testRegex "^([^a])([^\\b])([^c]*)([^d]{3,4})" []
        ["baNOTccccd",
         "baNOTcccd",
         "baNOTccd",
         "bacccd",
         "anything",
         "b\bc   ",
         "baccd"]
        [Just ["baNOTcccc", "b", "a", "NOT", "cccc"],
         Just ["baNOTccc", "b", "a", "NOT", "ccc"],
         Just ["baNOTcc", "b", "a", "NO", "Tcc"],
         Just ["baccc", "b", "a", "", "ccc"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "^\\d{8,}\\@.+[^k]$" []
        ["12345678@a.b.c.d",
         "123456789@x.y.z",
         "*** Failers",
         "12345678@x.y.uk",
         "1234567@a.b.c.d       "]
        [Just ["12345678@a.b.c.d"],
         Just ["123456789@x.y.z"],
         Nothing,
         Nothing,
         Nothing]

    , testRegex "(a)\\1{8,}" []
        ["aaaaaaaaa",
         "aaaaaaaaaa",
         "*** Failers",
         "aaaaaaa   "]
        [Just ["aaaaaaaaa", "a"],
         Just ["aaaaaaaaaa", "a"],
         Nothing,
         Nothing]

    , testRegex "[^a]" []
        ["aaaabcd",
         "aaAabcd "]
        [Just ["b"],
         Just ["A"]]

    , testRegex "[^a]" [caseless]
        ["aaaabcd",
         "aaAabcd "]
        [Just ["b"],
         Just ["b"]]

    , testRegex "[^az]" []
        ["aaaabcd",
         "aaAabcd "]
        [Just ["b"],
         Just ["A"]]

    , testRegex "[^az]" [caseless]
        ["aaaabcd",
         "aaAabcd "]
        [Just ["b"],
         Just ["b"]]

    , testRegex "P[^*]TAIRE[^*]{1,6}?LL" []
        ["xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"]
        [Just ["PSTAIREISLL"]]

    , testRegex "P[^*]TAIRE[^*]{1,}?LL" []
        ["xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"]
        [Just ["PSTAIREISLL"]]

    , testRegex "(.*?)(\\d+)" []
        ["I have 2 numbers: 53147"]
        [Just ["I have 2", "I have ", "2"]]

    , testRegex "(.*)(\\d+)$" []
        ["I have 2 numbers: 53147"]
        [Just ["I have 2 numbers: 53147", "I have 2 numbers: 5314", "7"]]

    , testRegex "(.*?)(\\d+)$" []
        ["I have 2 numbers: 53147"]
        [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]

    , testRegex "(.*)\\b(\\d+)$" []
        ["I have 2 numbers: 53147"]
        [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]

    , testRegex "(.*\\D)(\\d+)$" []
        ["I have 2 numbers: 53147"]
        [Just ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]]

    , testRegex "word (?:[a-zA-Z0-9]+ ){0,10}otherword" []
        ["word cat dog elephant mussel cow horse canary baboon snake shark otherword",
         "word cat dog elephant mussel cow horse canary baboon snake shark"]
        [Just ["word cat dog elephant mussel cow horse canary baboon snake shark otherword"],
         Nothing]

    , testRegex "word (?:[a-zA-Z0-9]+ ){0,300}otherword" []
        ["word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope"]
        [Nothing]
    , testRegex "^(a){0,0}" []
        ["bcd",
         "abc",
         "aab     "]
        [Just [""],
         Just [""],
         Just [""]]

    , testRegex "^(a){0,1}" []
        ["bcd",
         "abc",
         "aab  "]
        [Just [""],
         Just ["a", "a"],
         Just ["a", "a"]]

    , testRegex "^(a){0,2}" []
        ["bcd",
         "abc",
         "aab  "]
        [Just [""],
         Just ["a", "a"],
         Just ["aa", "a"]]

    , testRegex "^(a){0,3}" []
        ["bcd",
         "abc",
         "aab",
         "aaa   "]
        [Just [""],
         Just ["a", "a"],
         Just ["aa", "a"],
         Just ["aaa", "a"]]

    , testRegex "^(a){0,3}" []
        ["bcd",
         "abc",
         "aab",
         "aaa   "]
        [Just [""],
         Just ["a", "a"],
         Just ["aa", "a"],
         Just ["aaa", "a"]]

    , testRegex "^(a){0,}" []
        ["bcd",
         "abc",
         "aab",
         "aaa",
         "aaaaaaaa    "]
        [Just [""],
         Just ["a", "a"],
         Just ["aa", "a"],
         Just ["aaa", "a"],
         Just ["aaaaaaaa", "a"]]

    , testRegex "^(a){1,1}" []
        ["bcd",
         "abc",
         "aab  "]
        [Nothing,
         Just ["a", "a"],
         Just ["a", "a"]]

    , testRegex "^(a){1,2}" []
        ["bcd",
         "abc",
         "aab  "]
        [Nothing,
         Just ["a", "a"],
         Just ["aa", "a"]]

    , testRegex "^(a){1,3}" []
        ["bcd",
         "abc",
         "aab",
         "aaa   "]
        [Nothing,
         Just ["a", "a"],
         Just ["aa", "a"],
         Just ["aaa", "a"]]

    , testRegex ".*\\.gif" []
        ["borfle\nbib.gif\nno"]
        [Just ["bib.gif"]]

    , testRegex ".{0,}\\.gif" []
        ["borfle\nbib.gif\nno"]
        [Just ["bib.gif"]]

    , testRegex ".*\\.gif" [multiline]
        ["borfle\nbib.gif\nno"]
        [Just ["bib.gif"]]

    , testRegex ".*\\.gif" [dotall]
        ["borfle\nbib.gif\nno"]
        [Just ["borfle\nbib.gif"]]

    , testRegex ".*$" [multiline]
        ["borfle\nbib.gif\nno"]
        [Just ["borfle"]]

    , testRegex ".*$" [dotall]
        ["borfle\nbib.gif\nno"]
        [Just ["borfle\nbib.gif\nno"]]

    , testRegex ".*$" [multiline]
        ["borfle\nbib.gif\nno\\n"]
        [Just ["borfle"]]

    , testRegex "(?ms)^B" []
        ["abc\nB"]
        [Just ["B"]]

    , testRegex "(?s)B$" []
        ["B\n"]
        [Just ["B"]]

    , testRegex "^[abcdefghijklmnopqrstuvwxy0123456789]" []
        ["n",
         "z "]
        [Just ["n"],
         Nothing]

    , testRegex "abcde{0,0}" []
        ["abcd",
         "abce  "]
        [Just ["abcd"],
         Nothing]

    , testRegex "^(b+?|a){1,2}?c" []
        ["bac",
         "bbac",
         "bbbac",
         "bbbbac",
         "bbbbbac "]
        [Just ["bac","a"],
         Just ["bbac","a"],
         Just ["bbbac","a"],
         Just ["bbbbac","a"],
         Just ["bbbbbac","a"]]

    , testRegex "(AB)*?\\1" []
        ["ABABAB"]
        [Just ["ABAB", "AB"]]

    , testRegex "(.*(.)?)*" []
        ["abcd"]
        [Just ["abcd", ""]]

{-
    , testRegex "(?:a|)*\\d" []
        ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]
        [Nothing,
         Just ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]]
-}

    , testRegex "^(?:a(?:(?:))+)+" []
        ["aaaa"]
        [Just ["aaaa"]]

    , testRegex "^(a()+)+" []
        ["aaaa"]
        [Just ["aaaa", "a", ""]]

    , testRegex "^(?:a(?:(?:))*)*" []
        ["aaaa"]
        [Just ["aaaa"]]

    , testRegex "^(a()*)*" []
        ["aaaa"]
        [Just ["aaaa", "a", ""]]

  ]