diff --git a/Makefile b/Makefile index 37a78fcdaf5ceaceac33d29b856ed3121b75bd05..4fe6afbf747acced944f68d7d06a98326048eb6e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ build: configure cabal build --ghc-options=-Werror test: build - cabal test + cabal test --test-option=--hide-successes --test-option=--color haddock: configure cabal haddock diff --git a/Test/AddDays.hs b/Test/AddDays.hs index 006667356b3968eb8f4cb081acfa035c8599b9dd..8543c1546d1045a1be5fd2e319dbd594070519fe 100644 --- a/Test/AddDays.hs +++ b/Test/AddDays.hs @@ -1,14 +1,9 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.AddDays where import Data.Time.Calendar - import Test.TestUtil import Test.AddDaysRef --- - days ::[Day] days = [ @@ -42,6 +37,5 @@ resultDays = do return ((showGregorian day) ++ " + " ++ (show increment) ++ " * " ++ aname ++ " = " ++ showGregorian (adder increment day)) addDaysTest :: Test -addDaysTest - = Test $ pure "addDays" - $ diff addDaysRef $ unlines resultDays +addDaysTest = pureTest "addDays" $ + diff addDaysRef $ unlines resultDays diff --git a/Test/ClipDates.hs b/Test/ClipDates.hs index 761b9e9b461d519ada8e9ee5af7eb937b4b7de21..54667a628d1caa259ef613fd7d2aab9ede9f8a14 100644 --- a/Test/ClipDates.hs +++ b/Test/ClipDates.hs @@ -1,4 +1,3 @@ -{-# OPTIONS -Wall -Werror #-} {-# Language TupleSections #-} module Test.ClipDates where @@ -6,12 +5,9 @@ module Test.ClipDates where import Data.Time.Calendar.OrdinalDate import Data.Time.Calendar.WeekDate import Data.Time.Calendar - import Test.TestUtil import Test.ClipDatesRef --- - yearAndDay :: (Integer,Int) -> String yearAndDay (y,d) = (show y) ++ "-" ++ (show d) ++ " = " ++ (showOrdinalDate (fromOrdinalDate y d)) @@ -34,23 +30,17 @@ tupleUp3 l1 l2 l3 -- clipDates :: Test -clipDates - = Test $ pure "clipDates" - $ let yad = unlines $ map yearAndDay - $ tupleUp2 [1968,1969,1971] [-4,0,1,200,364,365,366,367,700] +clipDates = pureTest "clipDates" $ + let + yad = unlines $ map yearAndDay $ + tupleUp2 [1968,1969,1971] [-4,0,1,200,364,365,366,367,700] - greg = unlines $ map gregorian - $ tupleUp3 [1968,1969,1971] - [-20,-1,0,1,2,12,13,17] - [-7,-1,0,1,2,27,28,29,30,31,32,40] + greg = unlines $ map gregorian $ + tupleUp3 [1968,1969,1971] [-20,-1,0,1,2,12,13,17] [-7,-1,0,1,2,27,28,29,30,31,32,40] - iso = unlines $ map iSOWeekDay - $ tupleUp3 [1968,1969,2004] - [-20,-1,0,1,20,51,52,53,54] - [-2,-1,0,1,4,6,7,8,9] + iso = unlines $ map iSOWeekDay $ + tupleUp3 [1968,1969,2004] [-20,-1,0,1,20,51,52,53,54] [-2,-1,0,1,4,6,7,8,9] - in diff clipDatesRef - $ concat [ "YearAndDay\n", yad - , "Gregorian\n", greg - , "ISOWeekDay\n", iso ] + in diff clipDatesRef $ + concat [ "YearAndDay\n", yad, "Gregorian\n", greg, "ISOWeekDay\n", iso ] diff --git a/Test/ConvertBack.hs b/Test/ConvertBack.hs index 857e80f23fbb8753a188425e44b43caaf15a6f81..a0c43a447b10e3fe67712ecc412c058e9e4372e4 100644 --- a/Test/ConvertBack.hs +++ b/Test/ConvertBack.hs @@ -1,16 +1,11 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.ConvertBack where import Data.Time.Calendar.OrdinalDate import Data.Time.Calendar.Julian import Data.Time.Calendar.WeekDate import Data.Time.Calendar - import Test.TestUtil --- - checkDay :: (Show t) => (Day -> t) -> (t -> Day) -> (t -> Maybe Day) -> Day -> String checkDay encodeDay decodeDay decodeDayValid day = let st = encodeDay day @@ -41,6 +36,5 @@ days = [ModifiedJulianDay 50000 .. ModifiedJulianDay 50200] ++ (fmap (\year -> (fromGregorian year 1 4)) [1980..2000]) convertBack :: Test -convertBack - = Test $ pure "convertBack" - $ diff "" $ concatMap (\ch -> concatMap ch days) checkers +convertBack = pureTest "convertBack" $ + diff "" $ concatMap (\ch -> concatMap ch days) checkers diff --git a/Test/LongWeekYears.hs b/Test/LongWeekYears.hs index 220b3c78fddc7a8198cb092af622a41bf43402bc..31c551f7fff1ca5df71121eda89c017f22e79d40 100644 --- a/Test/LongWeekYears.hs +++ b/Test/LongWeekYears.hs @@ -1,15 +1,10 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.LongWeekYears where import Data.Time.Calendar.WeekDate import Data.Time.Calendar - import Test.TestUtil import Test.LongWeekYearsRef --- - longYear :: Integer -> Bool longYear year = case toWeekDate (fromGregorian year 12 31) of (_,53,_) -> True @@ -21,6 +16,5 @@ showLongYear year , (if isLeapYear year then "L" else " ") ++ (if longYear year then "*" else " ") ] longWeekYears :: Test -longWeekYears - = Test $ pure "longWeekYears" - $ diff longWeekYearsRef $ unlines $ map showLongYear [1901 .. 2050] +longWeekYears = pureTest "longWeekYears" $ + diff longWeekYearsRef $ unlines $ map showLongYear [1901 .. 2050] diff --git a/Test/TestCalendars.hs b/Test/TestCalendars.hs index 5f1932ca33991f9a9f425a14f2eaf55f8a7618c2..8be376caa4b858494cebcb0e3a48cc1a1ae74800 100644 --- a/Test/TestCalendars.hs +++ b/Test/TestCalendars.hs @@ -1,16 +1,11 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.TestCalendars where import Data.Time.Calendar.Julian import Data.Time.Calendar.WeekDate import Data.Time.Calendar - import Test.TestUtil import Test.TestCalendarsRef --- - showers :: [(String,Day -> String)] showers = [ ("MJD",show . toModifiedJulianDay), @@ -28,10 +23,8 @@ days = [ ] testCalendars :: Test -testCalendars - = Test $ pure "testCalendars" - $ diff testCalendarsRef - $ unlines $ map (\d -> showShowers d) days - where - showShowers day - = concatMap (\(nm,shower) -> unwords [" ==", nm, shower day]) showers +testCalendars = pureTest "testCalendars" $ + diff testCalendarsRef $ unlines $ map (\d -> showShowers d) days + where + showShowers day = + concatMap (\(nm,shower) -> unwords [" ==", nm, shower day]) showers diff --git a/Test/TestEaster.hs b/Test/TestEaster.hs index e97c84e078c9a02c732ec4fbf759dce035aefbd6..20c88898fa81cffbd5d22535aae8a372256509d6 100644 --- a/Test/TestEaster.hs +++ b/Test/TestEaster.hs @@ -20,21 +20,19 @@ showWithWDay :: Day -> String showWithWDay = formatTime defaultTimeLocale "%F %A" testEaster :: Test -testEaster - = Test $ pure "testEaster" - $ let ds = unlines $ map (\day -> +testEaster = pureTest "testEaster" $ let + ds = unlines $ map (\day -> unwords [ showWithWDay day, "->" , showWithWDay (sundayAfter day)]) days - f y = unwords [ show y ++ ", Gregorian: moon," + f y = unwords [ show y ++ ", Gregorian: moon," , show (gregorianPaschalMoon y) ++ ": Easter," , showWithWDay (gregorianEaster y)] ++ "\n" - g y = unwords [ show y ++ ", Orthodox : moon," + g y = unwords [ show y ++ ", Orthodox : moon," , show (orthodoxPaschalMoon y) ++ ": Easter," , showWithWDay (orthodoxEaster y)] ++ "\n" - in diff testEasterRef - $ ds ++ concatMap (\y -> f y ++ g y) [2000..2020] + in diff testEasterRef $ ds ++ concatMap (\y -> f y ++ g y) [2000..2020] diff --git a/Test/TestFormat.hs b/Test/TestFormat.hs index 3aae5e584e5995038cd4d2c76a1a0a144a60afad..c063847cc33c2ba02776f9db8edcafe558629a61 100644 --- a/Test/TestFormat.hs +++ b/Test/TestFormat.hs @@ -1,21 +1,16 @@ -{-# OPTIONS -XForeignFunctionInterface -Wall -Werror #-} +{-# LANGUAGE ForeignFunctionInterface #-} module Test.TestFormat where import Data.Time import Data.Time.Clock.POSIX - import Data.Char - import System.Locale import Foreign import Foreign.C import Control.Exception; - import Test.TestUtil --- - {- size_t format_time ( char *s, size_t maxsize, @@ -75,17 +70,14 @@ times :: [UTCTime] times = [baseTime0] ++ (fmap getDay [0..23]) ++ (fmap getDay [0..100]) ++ (fmap getYearP1 years) ++ (fmap getYearP2 years) ++ (fmap getYearP3 years) ++ (fmap getYearP4 years) -compareFormat :: String -> (String -> String) -> String -> TimeZone -> UTCTime -> TestInstance -compareFormat testname modUnix fmt zone time = - let ctime = utcToZonedTime zone time in - impure (testname ++ ": " ++ (show fmt) ++ " of " ++ (show ctime)) $ +compareFormat :: String -> (String -> String) -> String -> TimeZone -> UTCTime -> Test +compareFormat testname modUnix fmt zone time = let + ctime = utcToZonedTime zone time + haskellText = formatTime locale fmt ctime + in ioTest (testname ++ ": " ++ (show fmt) ++ " of " ++ (show ctime)) $ do - let haskellText = formatTime locale fmt ctime - unixText <- fmap modUnix (unixFormatTime fmt zone time) - if haskellText == unixText - then return Pass - else return $ Fail $ unwords - [ "Mismatch for", show ctime ++ ": UNIX=\"" ++ unixText ++ "\", TimeLib=\"" ++ haskellText ++ "\"."] + unixText <- fmap modUnix (unixFormatTime fmt zone time) + return $ diff unixText haskellText -- as found in http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html -- plus FgGklz @@ -126,18 +118,13 @@ safeString s = do return (c:ss) [] -> return "" -compareExpected :: (Eq t,Show t,ParseTime t) => String -> String -> String -> Maybe t -> TestInstance -compareExpected testname fmt str expected = impure (testname ++ ": " ++ (show fmt) ++ " on " ++ (show str)) $ do +compareExpected :: (Eq t,Show t,ParseTime t) => String -> String -> String -> Maybe t -> Test +compareExpected testname fmt str expected = ioTest (testname ++ ": " ++ (show fmt) ++ " on " ++ (show str)) $ do let found = parseTime defaultTimeLocale fmt str mex <- getBottom found case mex of Just ex -> return $ Fail $ unwords [ "Exception: expected" , show expected ++ ", caught", show ex] - Nothing -> - if found == expected - then return Pass - else do - sf <- safeString (show found) - return $ Fail $ unwords [ "Mismatch: expected", show expected ++ ", found", sf] + Nothing -> return $ diff expected found class (ParseTime t) => TestParse t where expectedParse :: String -> String -> Maybe t @@ -154,7 +141,7 @@ instance TestParse TimeZone instance TestParse ZonedTime instance TestParse UTCTime -checkParse :: String -> String -> [TestInstance] +checkParse :: String -> String -> [Test] checkParse fmt str = [ compareExpected "Day" fmt str (expectedParse fmt str :: Maybe Day) , compareExpected "TimeOfDay" fmt str (expectedParse fmt str :: Maybe TimeOfDay) @@ -162,20 +149,20 @@ checkParse fmt str , compareExpected "TimeZone" fmt str (expectedParse fmt str :: Maybe TimeZone) , compareExpected "UTCTime" fmt str (expectedParse fmt str :: Maybe UTCTime) ] -testCheckParse :: [TestInstance] +testCheckParse :: [Test] testCheckParse = concatMap (\fmt -> concatMap (\str -> checkParse fmt str) somestrings) formats -testCompareFormat :: [TestInstance] +testCompareFormat :: [Test] testCompareFormat = concatMap (\fmt -> concatMap (\time -> fmap (\zone -> compareFormat "compare format" id fmt zone time) zones) times) formats -testCompareHashFormat :: [TestInstance] +testCompareHashFormat :: [Test] testCompareHashFormat = concatMap (\fmt -> concatMap (\time -> fmap (\zone -> compareFormat "compare hashformat" (fmap toLower) fmt zone time) zones) times) hashformats testFormats :: [Test] testFormats = [ - fastTestInstanceGroup "checkParse" testCheckParse, - fastTestInstanceGroup "compare format" testCompareFormat, - fastTestInstanceGroup "compare hashformat" testCompareHashFormat + testGroup "checkParse" testCheckParse, + testGroup "compare format" testCompareFormat, + testGroup "compare hashformat" testCompareHashFormat ] testFormat :: Test diff --git a/Test/TestMonthDay.hs b/Test/TestMonthDay.hs index fa3bdcca0c3a6aed66519e2dafab47b426f1658d..f97f3f526d02c23ec0d7f3fe11ae70e4c6a5451a 100644 --- a/Test/TestMonthDay.hs +++ b/Test/TestMonthDay.hs @@ -1,29 +1,22 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.TestMonthDay where import Data.Time.Calendar.MonthDay - import Test.TestUtil import Test.TestMonthDayRef --- - showCompare :: (Eq a,Show a) => a -> String -> a -> String showCompare a1 b a2 | a1 == a2 = (show a1) ++ " == " ++ b showCompare a1 b a2 = "DIFF: " ++ (show a1) ++ " -> " ++ b ++ " -> " ++ (show a2) testMonthDay :: Test -testMonthDay - = Test $ pure "testMonthDay" - $ diff testMonthDayRef - $ concat $ map (\isL -> unlines (leap isL : yearDays isL)) [False,True] - where - leap isLeap = if isLeap then "Leap:" else "Regular:" - - yearDays isLeap - = map (\yd -> let (m,d) = dayOfYearToMonthAndDay isLeap yd - yd' = monthAndDayToDayOfYear isLeap m d - mdtext = show m ++ "-" ++ show d - in showCompare yd mdtext yd') - [-2..369] +testMonthDay = pureTest "testMonthDay" $ + diff testMonthDayRef $ concat $ map (\isL -> unlines (leap isL : yearDays isL)) [False,True] + where + leap isLeap = if isLeap then "Leap:" else "Regular:" + yearDays isLeap = + map (\yd -> let + (m,d) = dayOfYearToMonthAndDay isLeap yd + yd' = monthAndDayToDayOfYear isLeap m d + mdtext = show m ++ "-" ++ show d + in showCompare yd mdtext yd') + [-2..369] diff --git a/Test/TestParseDAT.hs b/Test/TestParseDAT.hs index 313758d48afaafe27162474426b7ad9887517f01..31b6ea5ac851302fbe118a95e3a95e0026855f9c 100644 --- a/Test/TestParseDAT.hs +++ b/Test/TestParseDAT.hs @@ -1,16 +1,11 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.TestParseDAT where import Data.Time import Data.Time.Clock.TAI - import Test.TestUtil import Test.TestParseDAT_Ref import Test.TAI_UTC_DAT --- - tods :: [TimeOfDay] tods = [ TimeOfDay 0 0 0, @@ -42,19 +37,17 @@ times = fmap (LocalTime (fromGregorian 1999 01 02)) tods testParseDAT :: Test -testParseDAT - = Test $ pure "testParseDAT" - $ diff testParseDAT_Ref parseDAT - where - parseDAT = - let lst = parseTAIUTCDATFile taiUTC_DAT - in unlines $ - map (\lt -> - let utcTime = localTimeToUTC utc lt - taiTime = utcToTAITime lst utcTime - utcTime' = taiToUTCTime lst taiTime - in if utcTime == utcTime' - then unwords [show utcTime, "==", show taiTime] - else unwords [ "correction:", show utcTime - , "->", show taiTime, "->", show utcTime']) - times +testParseDAT = pureTest "testParseDAT" $ diff testParseDAT_Ref parseDAT where + parseDAT = + let lst = parseTAIUTCDATFile taiUTC_DAT in + unlines $ map + (\lt -> + let + utcTime = localTimeToUTC utc lt + taiTime = utcToTAITime lst utcTime + utcTime' = taiToUTCTime lst taiTime + in if utcTime == utcTime' + then unwords [show utcTime, "==", show taiTime] + else unwords [ "correction:", show utcTime, "->", show taiTime, "->", show utcTime'] + ) + times diff --git a/Test/TestParseTime.hs b/Test/TestParseTime.hs index b3d1b2fcf462b521f38d2cb52c3471aae3a0bdf8..823a3c1e1567a81bbed054fda7cba1e5ad260704 100644 --- a/Test/TestParseTime.hs +++ b/Test/TestParseTime.hs @@ -1,4 +1,4 @@ -{-# OPTIONS -Wall -Werror -fno-warn-type-defaults -fno-warn-unused-binds -fno-warn-orphans #-} +{-# OPTIONS -fno-warn-type-defaults -fno-warn-unused-binds -fno-warn-orphans #-} {-# LANGUAGE FlexibleInstances, ExistentialQuantification #-} module Test.TestParseTime where @@ -6,90 +6,84 @@ module Test.TestParseTime where import Control.Monad import Data.Char import Data.Ratio -import Data.Maybe import Data.Time import Data.Time.Calendar.OrdinalDate import Data.Time.Calendar.WeekDate import Data.Time.Clock.POSIX import System.Locale -import System.Exit -import Test.QuickCheck -import Test.QuickCheck.Batch +import Test.QuickCheck hiding (Result) +--import qualified Test.QuickCheck +import Test.TestUtil +--import qualified Test.TestUtil -class RunTest p where - runTest :: p -> IO TestResult - -instance RunTest (IO TestResult) where - runTest iob = iob - -instance RunTest Property where - runTest p = run p (TestOptions {no_of_tests = 10000,length_of_tests = 0,debug_tests = False}) - -data ExhaustiveTest = forall t. (Show t) => MkExhaustiveTest [t] (t -> IO Bool) - -instance RunTest ExhaustiveTest where - runTest (MkExhaustiveTest cases f) = do - results <- mapM (\t -> do {b <- f t;return (b,show t)}) cases - let failures = mapMaybe (\(b,n) -> if b then Nothing else Just n) results - let fcount = length failures - return (if fcount == 0 then TestOk "OK" 0 [] else TestFailed failures fcount) +--instance RunTest Property where +-- runTest p = run p (TestOptions {no_of_tests = 10000,length_of_tests = 0,debug_tests = False}) ntest :: Int ntest = 1000 +type NamedProperty = (String, Property) + testParseTime :: Test -testParseTime - = impureTest $ Test "testParseTime" - $ good1 <- checkAll extests - good2 <- checkAll properties - putStrLn "Known failures:" - _ <- checkAll knownFailures - return $ if good1 && good2 - then Pass - else Fail "testParseTime failed and gave a redundant error message" - -days2011 :: [Day] -days2011 = [(fromGregorian 2011 1 1) .. (fromGregorian 2011 12 31)] - -extests :: [(String,ExhaustiveTest)] -extests = [ - ("parse %y",MkExhaustiveTest [0..99] parseYY), - ("parse %C %y 1900s",MkExhaustiveTest [0..99] (parseCYY 19)), - ("parse %C %y 2000s",MkExhaustiveTest [0..99] (parseCYY 20)), - ("parse %C %y 1400s",MkExhaustiveTest [0..99] (parseCYY 14)), - ("parse %C %y 700s",MkExhaustiveTest [0..99] (parseCYY 7)), - ("parse %Y%m%d",MkExhaustiveTest days2011 parseYMD), - ("parse %Y %m %d",MkExhaustiveTest days2011 parseYearDayD), - ("parse %Y %-m %e",MkExhaustiveTest days2011 parseYearDayE) +testParseTime = testGroup "testParseTime" + [ + testGroup "extests" (fmap exhaustiveTestInstances extests), + testGroup "properties" (fmap (\(n,prop) -> testProperty n prop) properties) ] -parseYMD :: Day -> IO Bool +{- +knownFailures +-} +yearDays :: Integer -> [Day] +yearDays y = [(fromGregorian y 1 1) .. (fromGregorian y 12 31)] + +extests :: [ExhaustiveTest] +extests = [ + MkExhaustiveTest "parse %y" [0..99] parseYY, + MkExhaustiveTest "parse %C %y 1900s" [0..99] (parseCYY 19), + MkExhaustiveTest "parse %C %y 2000s" [0..99] (parseCYY 20), + MkExhaustiveTest "parse %C %y 1400s" [0..99] (parseCYY 14), + MkExhaustiveTest "parse %C %y 700s" [0..99] (parseCYY2 7), + MkExhaustiveTest "parse %C %y 700s" [0..99] (parseCYY 7) + ] ++ + (concat $ fmap + (\y -> [ + (MkExhaustiveTest "parse %Y%m%d" (yearDays y) parseYMD), + (MkExhaustiveTest "parse %Y %m %d" (yearDays y) parseYearDayD), + (MkExhaustiveTest "parse %Y %-m %e" (yearDays y) parseYearDayE) + ]) [1,20,753,2000,2011,10001]) + +parseYMD :: Day -> IO Result parseYMD day = case toGregorian day of - (y,m,d) -> return $ (parse "%Y%m%d" ((show y) ++ (show2 m) ++ (show2 d))) == Just day + (y,m,d) -> return $ diff (Just day) (parse "%Y%m%d" ((show y) ++ (show2 m) ++ (show2 d))) -parseYearDayD :: Day -> IO Bool +parseYearDayD :: Day -> IO Result parseYearDayD day = case toGregorian day of - (y,m,d) -> return $ (parse "%Y %m %d" ((show y) ++ " " ++ (show2 m) ++ " " ++ (show2 d))) == Just day + (y,m,d) -> return $ diff (Just day) (parse "%Y %m %d" ((show y) ++ " " ++ (show2 m) ++ " " ++ (show2 d))) -parseYearDayE :: Day -> IO Bool +parseYearDayE :: Day -> IO Result parseYearDayE day = case toGregorian day of - (y,m,d) -> return $ (parse "%Y %-m %e" ((show y) ++ " " ++ (show m) ++ " " ++ (show d))) == Just day + (y,m,d) -> return $ diff (Just day) (parse "%Y %-m %e" ((show y) ++ " " ++ (show m) ++ " " ++ (show d))) -- | 1969 - 2068 expectedYear :: Integer -> Integer expectedYear i | i >= 69 = 1900 + i expectedYear i = 2000 + i -show2 :: (Integral n) => n -> String +show2 :: (Show n,Integral n) => n -> String show2 i = (show (div i 10)) ++ (show (mod i 10)) -parseYY :: Integer -> IO Bool -parseYY i = return (parse "%y" (show2 i) == Just (fromGregorian (expectedYear i) 1 1)) +parseYY :: Integer -> IO Result +parseYY i = return $ diff (Just (fromGregorian (expectedYear i) 1 1)) (parse "%y" (show2 i)) + +parseCYY :: Integer -> Integer -> IO Result +parseCYY c i = return $ diff (Just (fromGregorian ((c * 100) + i) 1 1)) (parse "%C %y" ((show c) ++ " " ++ (show2 i))) -parseCYY :: Integer -> Integer -> IO Bool -parseCYY c i = return (parse "%C %y" ((show2 c) ++ " " ++ (show2 i)) == Just (fromGregorian ((c * 100) + i) 1 1)) +parseCYY2 :: Integer -> Integer -> IO Result +parseCYY2 c i = return $ diff (Just (fromGregorian ((c * 100) + i) 1 1)) (parse "%C %y" ((show2 c) ++ " " ++ (show2 i))) +{- checkAll :: RunTest p => [(String,p)] -> IO Bool checkAll ps = fmap and (mapM checkOne ps) @@ -112,7 +106,7 @@ checkOne (n,p) = return (trGood tr) where rpad n' c xs = xs ++ replicate (n' - length xs) c - +-} parse :: ParseTime t => String -> String -> Maybe t parse f t = parseTime defaultTimeLocale f t @@ -123,6 +117,8 @@ format f t = formatTime defaultTimeLocale f t instance Arbitrary Day where arbitrary = liftM ModifiedJulianDay $ choose (-313698, 2973483) -- 1000-01-1 to 9999-12-31 + +instance CoArbitrary Day where coarbitrary (ModifiedJulianDay d) = coarbitrary d instance Arbitrary DiffTime where @@ -133,26 +129,38 @@ instance Arbitrary DiffTime where secondsToDiffTime' = fromInteger picosecondsToDiffTime' :: Integer -> DiffTime picosecondsToDiffTime' x = fromRational (x % 10^12) + +instance CoArbitrary DiffTime where coarbitrary t = coarbitrary (fromEnum t) instance Arbitrary TimeOfDay where arbitrary = liftM timeToTimeOfDay arbitrary + +instance CoArbitrary TimeOfDay where coarbitrary t = coarbitrary (timeOfDayToTime t) instance Arbitrary LocalTime where arbitrary = liftM2 LocalTime arbitrary arbitrary + +instance CoArbitrary LocalTime where coarbitrary t = coarbitrary (truncate (utcTimeToPOSIXSeconds (localTimeToUTC utc t)) :: Integer) instance Arbitrary TimeZone where arbitrary = liftM minutesToTimeZone $ choose (-720,720) + +instance CoArbitrary TimeZone where coarbitrary tz = coarbitrary (timeZoneMinutes tz) instance Arbitrary ZonedTime where arbitrary = liftM2 ZonedTime arbitrary arbitrary + +instance CoArbitrary ZonedTime where coarbitrary t = coarbitrary (truncate (utcTimeToPOSIXSeconds (zonedTimeToUTC t)) :: Integer) instance Arbitrary UTCTime where arbitrary = liftM2 UTCTime arbitrary arbitrary + +instance CoArbitrary UTCTime where coarbitrary t = coarbitrary (truncate (utcTimeToPOSIXSeconds t) :: Integer) -- missing from the time package @@ -209,7 +217,7 @@ prop_fromSundayStartWeek d = -- | Helper for defining named properties. prop_named :: (Arbitrary t, Show t, Testable a) => String -> (FormatString s -> t -> a) -> String -> FormatString s -> NamedProperty -prop_named name prop typeName f = (name ++ " " ++ typeName ++ " " ++ show f, property (prop f)) +prop_named n prop typeName f = (n ++ " " ++ typeName ++ " " ++ show f, property (prop f)) prop_parse_format :: (Eq t, FormatTime t, ParseTime t) => FormatString t -> t -> Bool prop_parse_format (FormatString f) t = parse f (format f t) == Just t @@ -255,6 +263,7 @@ instance Arbitrary Input where arbitrary = liftM Input $ list cs where cs = elements (['0'..'9'] ++ ['-',' ','/'] ++ ['a'..'z'] ++ ['A' .. 'Z']) list g = sized (\n -> choose (0,n) >>= \l -> replicateM l g) +instance CoArbitrary Input where coarbitrary (Input s) = coarbitrary (sum (map ord s)) prop_no_crash_bad_input :: (Eq t, ParseTime t) => FormatString t -> Input -> Property @@ -282,8 +291,6 @@ castFormatString (FormatString f) = FormatString f instance Show (FormatString a) where show (FormatString f) = show f -type NamedProperty = (String, Property) - properties :: [NamedProperty] properties = [("prop_fromMondayStartWeek", property prop_fromMondayStartWeek), diff --git a/Test/TestTime.hs b/Test/TestTime.hs index cfa476b4fd2c632b8278a0a534316d62ce49fa00..86e991938e104eebd5081646832ee882f95293fe 100644 --- a/Test/TestTime.hs +++ b/Test/TestTime.hs @@ -1,16 +1,11 @@ -{-# OPTIONS -Wall -Werror #-} - module Test.TestTime where import Data.Time.Calendar.OrdinalDate import Data.Time.Calendar.WeekDate import Data.Time - import Test.TestUtil import Test.TestTimeRef --- - showCal :: Integer -> String showCal mjd = let date = ModifiedJulianDay mjd @@ -107,6 +102,5 @@ testTimeOfDayToDayFraction , show $ f $ TimeOfDay 12 34 56.789123456789 ] testTime :: Test -testTime - = Test $ pure "testTime" - $ diff testTimeRef $ unlines [testCal, testUTC, testUT1, testTimeOfDayToDayFraction] +testTime = pureTest "testTime" $ + diff testTimeRef $ unlines [testCal, testUTC, testUT1, testTimeOfDayToDayFraction] diff --git a/Test/TestUtil.hs b/Test/TestUtil.hs index 88d95d24a6b16ab24b3743459d7d85e5c6a8e4d3..de22be326c5161bff75a4c305053152431b2a0dc 100644 --- a/Test/TestUtil.hs +++ b/Test/TestUtil.hs @@ -1,46 +1,43 @@ +{-# OPTIONS -fno-warn-overlapping-patterns #-} module Test.TestUtil - ( - module Test.TestUtil - , module Distribution.TestSuite - ) where - -import Distribution.TestSuite - -impure :: String -> IO Result -> TestInstance -impure name mresult = TestInstance { - run = fmap Finished mresult, - name = name, - tags = [], - options = [], - setOption = \_ _ -> Left "unsupported" -} - -pure :: String -> Result -> TestInstance -pure name result = impure name (return result) - -diff :: String -> String -> Result -diff s t | s == t = Pass -diff _ _ = Fail "" - -finish :: IO Progress -> IO Result -finish iop = do - progress <- iop - case progress of - Finished result -> return result - Progress _ iop' -> finish iop' - -concatRun :: [IO Progress] -> IO Result -concatRun [] = return Pass -concatRun (iop:iops) = do - result <- finish iop - case result of - Pass -> concatRun iops - _ -> return result - -concatTestInstance :: String -> [TestInstance] -> TestInstance -concatTestInstance tname tis = impure tname (concatRun (fmap run tis)) - -fastTestInstanceGroup :: String -> [TestInstance] -> Test -fastTestInstanceGroup tname tis | False = testGroup tname (fmap Test tis) -fastTestInstanceGroup tname tis = Test (concatTestInstance tname tis) + ( + module Test.TestUtil, + module Test.Framework, + module Test.Framework.Providers.QuickCheck2 + ) where +import Test.Framework +import Test.Framework.Providers.API +import Test.Framework.Providers.QuickCheck2 + +data Result = Pass | Fail String + +instance Show Result where + show Pass = "passed" + show (Fail s) = "failed: " ++ s + +instance TestResultlike () Result where + testSucceeded Pass = True + testSucceeded (Fail _) = False + +instance Testlike () Result (IO Result) where + testTypeName _ = "Cases" + runTest _ ior = do + r <- ior + return (Finished r,return ()) + +ioTest :: String -> IO Result -> Test +ioTest = Test + +pureTest :: String -> Result -> Test +pureTest name result = ioTest name (return result) + +diff :: (Show a,Eq a) => a -> a -> Result +diff expected found | expected == found = Pass +diff expected found = Fail ("expected [" ++ (show expected) ++ "] but found [" ++ (show found) ++ "]") + +data ExhaustiveTest = forall t. (Show t) => MkExhaustiveTest String [t] (t -> IO Result) + +exhaustiveTestInstances :: ExhaustiveTest -> Test +exhaustiveTestInstances (MkExhaustiveTest name cases f) = testGroup name (fmap toTI cases) where + toTI t = ioTest (show t) (f t) diff --git a/Test/Tests.hs b/Test/Tests.hs index 2185918e3faae1f58c9708d685e7304a3c9afd8d..512b64e1caecdaa3ceba323e36b1180768efbbb8 100644 --- a/Test/Tests.hs +++ b/Test/Tests.hs @@ -1,6 +1,6 @@ module Test.Tests where -import Distribution.TestSuite +import Test.Framework import Test.AddDays import Test.ClipDates @@ -11,10 +11,11 @@ import Test.TestEaster import Test.TestFormat import Test.TestMonthDay import Test.TestParseDAT +import Test.TestParseTime import Test.TestTime -tests :: IO [Test] -tests = return [ addDaysTest +tests :: [Test] +tests = [ addDaysTest , clipDates , convertBack , longWeekYears @@ -23,4 +24,5 @@ tests = return [ addDaysTest , testFormat , testMonthDay , testParseDAT + , testParseTime , testTime ] diff --git a/time.cabal b/time.cabal index 6574f8916275578dada99f73a7514899112c9503..7254d3b4bebce127d6bf3698b27cc66a691db66d 100644 --- a/time.cabal +++ b/time.cabal @@ -34,13 +34,17 @@ extra-tmp-files: include/HsTimeConfig.h library - build-depends: base >= 4, - deepseq >= 1.1, - old-locale + build-depends: + base >= 4, + deepseq >= 1.1, + old-locale ghc-options: -Wall default-language: Haskell2010 if impl(ghc) - default-extensions: Rank2Types DeriveDataTypeable StandaloneDeriving + default-extensions: + Rank2Types + DeriveDataTypeable + StandaloneDeriving cpp-options: -DLANGUAGE_Rank2Types -DLANGUAGE_DeriveDataTypeable -DLANGUAGE_StandaloneDeriving else if impl(hugs) @@ -85,58 +89,78 @@ library HsTime.h HsTimeConfig.h -Test-Suite tests - type: detailed-0.9 - test-module: Test.Tests - default-language: Haskell2010 - default-extensions: Rank2Types, CPP, DeriveDataTypeable, StandaloneDeriving - cpp-options: -DLANGUAGE_Rank2Types -DLANGUAGE_DeriveDataTypeable -DLANGUAGE_StandaloneDeriving - c-sources: cbits/HsTime.c Test/TestFormatStuff.c - include-dirs: include - build-depends: base, deepseq, Cabal >= 1.16, old-locale, process - other-modules: - Test.TestTime - Test.TestTimeRef - Test.TestParseDAT - Test.TAI_UTC_DAT - Test.TestParseDAT_Ref - Test.TestMonthDay - Test.TestMonthDayRef - Test.TestFormat - Test.TestEaster - Test.TestEasterRef - Test.TestCalendars - Test.TestCalendarsRef - Test.LongWeekYears - Test.LongWeekYearsRef - Test.ConvertBack - Test.ClipDates - Test.ClipDatesRef - Test.AddDays - Test.AddDaysRef - Test.TestUtil +test-suite tests + type: exitcode-stdio-1.0 + default-language: Haskell2010 + default-extensions: + Rank2Types + CPP + DeriveDataTypeable + StandaloneDeriving + ExistentialQuantification + MultiParamTypeClasses + FlexibleInstances + UndecidableInstances + ScopedTypeVariables + cpp-options: -DLANGUAGE_Rank2Types -DLANGUAGE_DeriveDataTypeable -DLANGUAGE_StandaloneDeriving + ghc-options: -Wall + c-sources: cbits/HsTime.c Test/TestFormatStuff.c + include-dirs: include + build-depends: + base, + deepseq, + Cabal >= 1.16, + old-locale, + process, + QuickCheck >= 2.5.1, + test-framework >= 0.6.1, + test-framework-quickcheck2 >= 0.2.12 + main-is: Test.hs + other-modules: + Test.Tests + Test.TestTime + Test.TestTimeRef + Test.TestParseDAT + Test.TAI_UTC_DAT + Test.TestParseDAT_Ref + Test.TestParseTime + Test.TestMonthDay + Test.TestMonthDayRef + Test.TestFormat + Test.TestEaster + Test.TestEasterRef + Test.TestCalendars + Test.TestCalendarsRef + Test.LongWeekYears + Test.LongWeekYearsRef + Test.ConvertBack + Test.ClipDates + Test.ClipDatesRef + Test.AddDays + Test.AddDaysRef + Test.TestUtil - Data.Time.Calendar.Private, - Data.Time.Calendar.Days, - Data.Time.Calendar.Gregorian, - Data.Time.Calendar.JulianYearDay, - Data.Time.Clock.Scale, - Data.Time.Clock.UTC, - Data.Time.Clock.CTimeval, - Data.Time.Clock.UTCDiff, - Data.Time.LocalTime.TimeZone, - Data.Time.LocalTime.TimeOfDay, - Data.Time.LocalTime.LocalTime, - Data.Time.Format.Parse - Data.Time.Calendar, - Data.Time.Calendar.MonthDay, - Data.Time.Calendar.OrdinalDate, - Data.Time.Calendar.WeekDate, - Data.Time.Calendar.Julian, - Data.Time.Calendar.Easter, - Data.Time.Clock, - Data.Time.Clock.POSIX, - Data.Time.Clock.TAI, - Data.Time.LocalTime, - Data.Time.Format, - Data.Time + Data.Time.Calendar.Private, + Data.Time.Calendar.Days, + Data.Time.Calendar.Gregorian, + Data.Time.Calendar.JulianYearDay, + Data.Time.Clock.Scale, + Data.Time.Clock.UTC, + Data.Time.Clock.CTimeval, + Data.Time.Clock.UTCDiff, + Data.Time.LocalTime.TimeZone, + Data.Time.LocalTime.TimeOfDay, + Data.Time.LocalTime.LocalTime, + Data.Time.Format.Parse + Data.Time.Calendar, + Data.Time.Calendar.MonthDay, + Data.Time.Calendar.OrdinalDate, + Data.Time.Calendar.WeekDate, + Data.Time.Calendar.Julian, + Data.Time.Calendar.Easter, + Data.Time.Clock, + Data.Time.Clock.POSIX, + Data.Time.Clock.TAI, + Data.Time.LocalTime, + Data.Time.Format, + Data.Time