|
#!/usr/bin/env stack |
|
{- stack script |
|
--resolver lts-14.6 |
|
--package hspec |
|
--package QuickCheck |
|
--package regex |
|
--package regex-with-pcre |
|
-} |
|
|
|
{-# LANGUAGE LambdaCase #-} |
|
{-# LANGUAGE OverloadedStrings #-} |
|
{-# LANGUAGE QuasiQuotes #-} |
|
{-# LANGUAGE ScopedTypeVariables #-} |
|
{-# LANGUAGE TemplateHaskell #-} |
|
|
|
module Main where |
|
|
|
import Combinators |
|
import PositiveExamples |
|
|
|
import Control.Monad (forM_) |
|
|
|
import Test.Hspec |
|
import Test.QuickCheck |
|
import Text.RE.PCRE |
|
import Text.Printf |
|
|
|
main :: IO () |
|
main = |
|
hspec $ do |
|
partATests |
|
partBTests |
|
partCTests |
|
partDTests |
|
partETests |
|
|
|
partATests :: Spec |
|
partATests = |
|
describe ("Part A: " ++ reSource regexPartA) $ do |
|
describe "randomized tests" $ do |
|
it "matches positive examples" $ |
|
property $ \(AlphabeticString str) -> matched $ str ?=~ regexPartA |
|
-- xit "fails negative examples" $ pending |
|
let positives = |
|
[ "abcdef" |
|
, "foobar" |
|
, "AsLongAsEverythingIsAlphabetical" |
|
, "KittGroupLinguistics" |
|
] |
|
negatives = |
|
[ "1234" |
|
, ".-=[]" |
|
, "\\%@!~~~" |
|
, "abc123def" |
|
, "the quick brown fox jumps over the sleazy dog" |
|
] |
|
mkSpecificTests positives negatives regexPartA |
|
|
|
partBTests :: Spec |
|
partBTests = |
|
describe ("Part B: " ++ reSource regexPartB) $ do |
|
describe "randomized tests" $ do |
|
it "matches positive examples" $ |
|
property $ \(LowercaseEndWithB str) -> matched $ str ?=~ regexPartB |
|
-- xit "fails negative examples" $ pending |
|
let positives = ["b", "weionxb", "swnzqqqb"] |
|
negatives = |
|
[ "" |
|
, "Hello" |
|
, "hi" |
|
, "this string has spaces" |
|
, "HasCapitalsb" |
|
, "endswithcapitalB" |
|
] |
|
myRegex = regexPartB |
|
mkSpecificTests positives negatives myRegex |
|
|
|
partCTests :: Spec |
|
partCTests = |
|
describe ("Part C: " ++ reSource regexPartC) $ do |
|
describe "randomized tests" $ do |
|
it "matches positive examples" $ |
|
property $ \(ConsecutiveRepeat str) -> matched $ str ?=~ regexPartC |
|
-- xit "fails negative examples" $ pending |
|
let positives = |
|
[ "This this regex is not case sensitive" |
|
, "this this" |
|
, "that x x y y y z z" |
|
, "pooxz asazz zzpxx zzpxx zzpxx yy11dd" |
|
] |
|
negatives = |
|
[ "this string has no repeated consecutive words." |
|
, "" |
|
, "asd;fijzxi" |
|
, "this string has this string has a multi-word repeating sequence" |
|
] |
|
myRegex = regexPartC |
|
mkSpecificTests positives negatives myRegex |
|
|
|
partDTests :: Spec |
|
partDTests = |
|
describe ("Part D: " ++ reSource regexPartD) $ do |
|
-- describe "randomized tests" $ do |
|
-- xit "matches positive examples" $ do |
|
-- property $ \(BothCaveAndSpider str) -> matched $ str ?=~ regexPartD |
|
-- xit "fails negative examples" $ pending |
|
let positives = |
|
[ "there is a spider in the cave" |
|
, "cave spider" |
|
, "spider cave" |
|
, "asj8nvn cave aj;oefi;j; 48821 spider" |
|
] |
|
negatives = |
|
[ "spiders and caves" |
|
, "the quick brown fox" |
|
, "" |
|
, "cave" |
|
, "spider" |
|
, "spider but not caves" |
|
, "cave but not spiders" |
|
, "spiderman is in a cave" |
|
, "PrefixForcave spider" |
|
, "cave prefixedspider" |
|
] |
|
myRegex = regexPartD |
|
mkSpecificTests positives negatives myRegex |
|
|
|
partETests :: Spec |
|
partETests = |
|
describe ("Part E: " ++ reSource regexPartE) $ do |
|
describe "randomized tests" $ do |
|
it "matches random positive examples" $ |
|
property $ \(NorthDakotaPhone str) -> matched $ str ?=~ regexPartE |
|
-- xit "fails random negative examples" $ pending |
|
describe "specific tests" $ do |
|
describe "positive examples" $ do |
|
let positives = |
|
[ "+17010987654" |
|
, "17010987654" |
|
, "1-701-098-7654" |
|
, "+1 (701) 098 7654" |
|
, "1-(701).098 7654" |
|
] |
|
in forM_ positives $ \numberString -> do |
|
it ("matches " ++ numberString) $ |
|
(numberString ?=~ regexPartE) `shouldSatisfy` matched |
|
describe "negative examples" $ do |
|
let negatives = |
|
[ "+18010987654" |
|
, "7010987654" |
|
, "1-701-098-654" |
|
, "the quick brown fox jumps over the lazy dog" |
|
, "1***(701).098 7654" |
|
] |
|
in forM_ negatives $ \numberString -> do |
|
it ("fails " ++ numberString) $ |
|
(numberString ?=~ regexPartE) `shouldNotSatisfy` matched |
|
|
|
regexPartA :: RE |
|
regexPartA = [re|^[A-Za-z]+$|] |
|
|
|
regexPartB :: RE |
|
regexPartB = [re|^[a-z]*b$|] |
|
|
|
regexPartC :: RE |
|
regexPartC = [reMultilineInsensitive|\b([a-z]+)\s+(\1\s*)+|] |
|
|
|
regexPartD :: RE |
|
regexPartD = [re|(?=.*\bcave\b)(?=.*\bspider\b)|] |
|
|
|
regexPartE :: RE |
|
regexPartE = [re|\+?1[.\- ]*(701|\(701\))[.\- ]*[0-9]{3}[.\- ]*[0-9]{4}|] |
|
-- regexPartE = [re|\+?1( \(|-|\.)*701(\) |-|.)*[0-9]{3}( |-|.)*[0-9]{4}|] |