-- | Test patterns {-# LANGUAGE CPP, DeriveDataTypeable, TypeApplications #-} module Test.Tasty.Patterns ( TestPattern(..) , parseExpr , parseTestPattern , noPattern , Path , exprMatches , testPatternMatches ) where import Test.Tasty.Options import Test.Tasty.Patterns.Types import Test.Tasty.Patterns.Parser import Test.Tasty.Patterns.Eval import Data.Char import Data.Coerce (coerce) import Data.List.NonEmpty (nonEmpty) import Data.Maybe (catMaybes) import Data.Typeable import Options.Applicative hiding (Success) #if !MIN_VERSION_base(4,11,0) import Data.Monoid #endif -- | @since 1.0 newtype TestPattern = -- | @since 1.1 TestPattern (Maybe Expr) deriving ( Typeable , Show -- ^ @since 1.1 , Eq -- ^ @since 1.1 ) -- | @since 1.0 noPattern :: TestPattern noPattern = TestPattern Nothing -- | Since tasty-1.5, this option can be specified multiple times on the -- command line. Only the tests matching all given patterns will be selected. instance IsOption TestPattern where defaultValue = noPattern parseValue = parseTestPattern optionName = return "pattern" optionHelp = return "Select only tests which satisfy a pattern or awk expression" optionCLParser = fmap (TestPattern . fmap (foldr1 And) . nonEmpty . catMaybes . coerce @[TestPattern]) . some $ mkOptionCLParser (short 'p' <> metavar "PATTERN") -- | @since 1.2 parseExpr :: String -> Maybe Expr parseExpr s | all (\c -> isAlphaNum c || c `elem` "._- ") s = Just $ ERE s | otherwise = parseAwkExpr s -- | @since 1.0 parseTestPattern :: String -> Maybe TestPattern parseTestPattern s | null s = Just noPattern | otherwise = TestPattern . Just <$> parseExpr s -- | @since 1.2 exprMatches :: Expr -> Path -> Bool exprMatches e fields = case withFields fields $ asB =<< eval e of Left msg -> error msg Right b -> b -- | @since 1.0 testPatternMatches :: TestPattern -> Path -> Bool testPatternMatches pat fields = case pat of TestPattern Nothing -> True TestPattern (Just e) -> exprMatches e fields