{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import qualified Data.Text as T import qualified Data.Vector as V import qualified Data.Vector.Unboxed as VU import qualified DataFrame as D import qualified DataFrame.Internal.Column as DI import qualified DataFrame.Operations.Typing as D import qualified System.Exit as Exit import Data.Time import Test.HUnit import qualified Functions import qualified Operations.Aggregations import qualified Operations.Apply import qualified Operations.Core import qualified Operations.Derive import qualified Operations.Filter import qualified Operations.GroupBy import qualified Operations.InsertColumn import qualified Operations.Join import qualified Operations.Merge import qualified Operations.ReadCsv import qualified Operations.Sort import qualified Operations.Statistics import qualified Operations.Take import qualified Parquet testData :: D.DataFrame testData = D.fromNamedColumns [ ("test1", DI.fromList ([1 .. 26] :: [Int])) , ("test2", DI.fromList ['a' .. 'z']) ] -- Dimensions correctDimensions :: Test correctDimensions = TestCase (assertEqual "should be (26, 2)" (26, 2) (D.dimensions testData)) emptyDataframeDimensions :: Test emptyDataframeDimensions = TestCase (assertEqual "should be (0, 0)" (0, 0) (D.dimensions D.empty)) dimensionsTest :: [Test] dimensionsTest = [ TestLabel "dimensions_correctDimensions" correctDimensions , TestLabel "dimensions_emptyDataframeDimensions" emptyDataframeDimensions ] -- PARSING TESTS ------- 1. SIMPLE CASES parseInts :: Test parseInts = let afterParse :: [Int] afterParse = [1 .. 50] beforeParse :: [T.Text] beforeParse = T.pack . show <$> [1 .. 50] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints without missing values as UnboxedColumn of Ints" expected actual ) parseDoubles :: Test parseDoubles = let afterParse :: [Double] afterParse = [1.0 .. 50.0] ++ [3.14, 2.22, 8.55, 23.3, 12.22222235049450945049504950] beforeParse :: [T.Text] beforeParse = T.pack . show <$> [1.0 .. 50.0] ++ [3.14, 2.22, 8.55, 23.3, 12.22222235049450945049504950] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Doubles without missing values as UnboxedColumn of Doubles" expected actual ) parseDates :: Test parseDates = let afterParse :: [Day] afterParse = [ fromGregorian 2020 02 12 , fromGregorian 2020 02 13 , fromGregorian 2020 02 14 , fromGregorian 2020 02 15 , fromGregorian 2020 02 16 , fromGregorian 2020 02 17 , fromGregorian 2020 02 18 , fromGregorian 2020 02 19 , fromGregorian 2020 02 20 , fromGregorian 2020 02 21 , fromGregorian 2020 02 22 , fromGregorian 2020 02 23 , fromGregorian 2020 02 24 , fromGregorian 2020 02 25 , fromGregorian 2020 02 26 ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates without missing values as BoxedColumn of Days" expected actual ) parseTexts :: Test parseTexts = let afterParse :: [T.Text] afterParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "Surrender now or prepare to fight!" , "Meowth, that's right!" ] beforeParse :: [T.Text] beforeParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "Surrender now or prepare to fight!" , "Meowth, that's right!" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Text without missing values as BoxedColumn of Text" expected actual ) --- 2. COMBINATION CASES parseIntsAndDoublesAsDoubles :: Test parseIntsAndDoublesAsDoubles = let afterParse :: [Double] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0 , 8.0 , 9.0 , 10.0 , 11.0 , 12.0 , 13.0 , 14.0 , 15.0 , 16.0 , 17.0 , 18.0 , 19.0 , 20.0 , 21.0 , 22.0 , 23.0 , 24.0 , 25.0 , 26.0 , 27.0 , 28.0 , 29.0 , 30.0 , 31.0 , 32.0 , 33.0 , 34.0 , 35.0 , 36.0 , 37.0 , 38.0 , 39.0 , 40.0 , 41.0 , 42.0 , 43.0 , 44.0 , 45.0 , 46.0 , 47.0 , 48.0 , 49.0 , 50.0 , 3.14 , 2.22 , 8.55 , 23.3 , 12.22222235049450945049504950 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Doubles as UnboxedColumn of Doubles" expected actual ) parseIntsAndDatesAsTexts :: Test parseIntsAndDatesAsTexts = let afterParse :: [T.Text] afterParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Dates as BoxedColumn of Texts" expected actual ) parseTextsAndDoublesAsTexts :: Test parseTextsAndDoublesAsTexts = let afterParse :: [T.Text] afterParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] beforeParse :: [T.Text] beforeParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Texts and Doubles as BoxedColumn of Texts" expected actual ) parseDatesAndTextsAsTexts :: Test parseDatesAndTextsAsTexts = let afterParse :: [T.Text] afterParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" , "Jessie" , "James" , "Meowth" ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" , "Jessie" , "James" , "Meowth" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Dates and Texts as BoxedColumn of Texts" expected actual ) -- 3A. PARSING WITH SAFEREAD OFF parseIntsWithoutSafeRead :: Test parseIntsWithoutSafeRead = let afterParse :: [Int] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints without missing values as UnboxedColumn of Ints, when safeRead is off" expected actual ) parseDoublesWithoutSafeRead :: Test parseDoublesWithoutSafeRead = let afterParse :: [Double] afterParse = [ 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0 , 8.0 , 9.0 , 10.0 , 11.0 , 12.0 , 13.0 , 14.0 , 15.0 , 16.0 , 17.0 , 18.0 , 19.0 , 20.0 , 21.0 , 22.0 , 23.0 , 24.0 , 25.0 , 26.0 , 27.0 , 28.0 , 29.0 , 30.0 , 31.0 , 32.0 , 33.0 , 34.0 , 35.0 , 36.0 , 37.0 , 38.0 , 39.0 , 40.0 , 41.0 , 42.0 , 43.0 , 44.0 , 45.0 , 46.0 , 47.0 , 48.0 , 49.0 , 50.0 , 3.14 , 2.22 , 8.55 , 23.3 , 12.22222235049450945049504950 ] beforeParse :: [T.Text] beforeParse = [ "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Doubles without missing values as UnboxedColumn of Doubles, when safeRead is off" expected actual ) parseDatesWithoutSafeRead :: Test parseDatesWithoutSafeRead = let afterParse :: [Day] afterParse = [ fromGregorian 2020 02 12 , fromGregorian 2020 02 13 , fromGregorian 2020 02 14 , fromGregorian 2020 02 15 , fromGregorian 2020 02 16 , fromGregorian 2020 02 17 , fromGregorian 2020 02 18 , fromGregorian 2020 02 19 , fromGregorian 2020 02 20 , fromGregorian 2020 02 21 , fromGregorian 2020 02 22 , fromGregorian 2020 02 23 , fromGregorian 2020 02 24 , fromGregorian 2020 02 25 , fromGregorian 2020 02 26 ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates without missing values as BoxedColumn of Days" expected actual ) parseTextsWithoutSafeRead :: Test parseTextsWithoutSafeRead = let afterParse :: [T.Text] afterParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "Surrender now or prepare to fight!" , "Meowth, that's right!" ] beforeParse :: [T.Text] beforeParse = [ "To" , "protect" , "the" , "world" , "from" , "devastation" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "Surrender now or prepare to fight!" , "Meowth, that's right!" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Text without missing values as BoxedColumn of Text" expected actual ) parseIntsAndEmptyStringsWithoutSafeRead :: Test parseIntsAndEmptyStringsWithoutSafeRead = let afterParse :: [Maybe Int] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Just 1 , Just 2 , Just 3 , Just 4 , Just 5 , Just 6 , Just 7 , Just 8 , Just 9 , Just 10 , Just 11 , Just 12 , Just 13 , Just 14 , Just 15 , Just 16 , Just 17 , Just 18 , Just 19 , Just 20 , Just 21 , Just 22 , Just 23 , Just 24 , Just 25 , Just 26 , Just 27 , Just 28 , Just 29 , Just 30 , Just 31 , Just 32 , Just 33 , Just 34 , Just 35 , Just 36 , Just 37 , Just 38 , Just 39 , Just 40 , Just 41 , Just 42 , Just 43 , Just 44 , Just 45 , Just 46 , Just 47 , Just 48 , Just 49 , Just 50 ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints and empty strings as OptionalColumn of Ints, when safeRead is off" expected actual ) parseIntsAndDoublesAndEmptyStringsWithoutSafeRead :: Test parseIntsAndDoublesAndEmptyStringsWithoutSafeRead = let afterParse :: [Maybe Double] afterParse = [ Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Nothing , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Nothing , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Nothing , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Nothing , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Nothing , Just 3.14 , Just 2.22 , Just 8.55 , Just 23.3 , Just 12.22222235049451 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses combination of Ints, Doubles and empty strings as OptionalColumn of Doubles, when safeRead is off" expected actual ) parseDatesAndEmptyStringsWithoutSafeRead :: Test parseDatesAndEmptyStringsWithoutSafeRead = let afterParse :: [Maybe Day] afterParse = [ Just $ fromGregorian 2020 02 12 , Just $ fromGregorian 2020 02 13 , Just $ fromGregorian 2020 02 14 , Nothing , Just $ fromGregorian 2020 02 15 , Just $ fromGregorian 2020 02 16 , Just $ fromGregorian 2020 02 17 , Nothing , Just $ fromGregorian 2020 02 18 , Just $ fromGregorian 2020 02 19 , Just $ fromGregorian 2020 02 20 , Nothing , Just $ fromGregorian 2020 02 21 , Just $ fromGregorian 2020 02 22 , Just $ fromGregorian 2020 02 23 , Nothing , Just $ fromGregorian 2020 02 24 , Just $ fromGregorian 2020 02 25 , Just $ fromGregorian 2020 02 26 , Nothing ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "" , "2020-02-24" , "2020-02-25" , "2020-02-26" , "" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates and Empty Strings as OptionalColumn of Dates, with safeRead off" expected actual ) parseTextsAndEmptyStringsWithoutSafeRead :: Test parseTextsAndEmptyStringsWithoutSafeRead = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Just "To" , Just "protect" , Just "the" , Just "world" , Just "from" , Just "devastation" , Nothing , Just "To" , Just "unite" , Just "all" , Just "people" , Just "within" , Just "our" , Just "nation" , Nothing , Just "To" , Just "denounce" , Just "the" , Just "evils" , Just "of" , Just "truth" , Just "and" , Just "love" , Nothing , Just "To" , Just "extend" , Just "our" , Just "reach" , Just "to" , Just "the" , Just "stars" , Just "above" , Nothing , Just "JESSIE!" , Just "JAMES!" , Just "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , Nothing , Just "Surrender now or prepare to fight!" , Nothing , Just "Meowth, that's right!" ] beforeParse :: [T.Text] beforeParse = [ "" , "To" , "protect" , "the" , "world" , "from" , "devastation" , "" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "" , "Surrender now or prepare to fight!" , "" , "Meowth, that's right!" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Texts and Empty Strings as OptionalColumn of Text, with safeRead off" expected actual ) parseIntsAndNullishStringsWithoutSafeRead :: Test parseIntsAndNullishStringsWithoutSafeRead = let afterParse :: [T.Text] afterParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "N/A" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] beforeParse :: [T.Text] beforeParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "N/A" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints with nullish values as BoxedColumn of Texts, when safeRead is off" expected actual ) parseIntsAndDoublesAndNullishStringsWithoutSafeRead :: Test parseIntsAndDoublesAndNullishStringsWithoutSafeRead = let afterParse :: [T.Text] afterParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "Nothing" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "N/A" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "NULL" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "null" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "NAN" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "Nothing" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "N/A" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "NULL" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "null" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "NAN" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses combination of Ints, Doubles and empty strings as OptionalColumn of Doubles, when safeRead is off" expected actual ) parseIntsAndNullishAndEmptyStringsWithoutSafeRead :: Test parseIntsAndNullishAndEmptyStringsWithoutSafeRead = let afterParse :: [Maybe T.Text] afterParse = [ Just "N/A" , Just "N/A" , Just "N/A" , Just "N/A" , Just "N/A" , Nothing , Just "1" , Just "2" , Just "3" , Just "4" , Just "5" , Just "6" , Just "7" , Just "8" , Just "9" , Just "10" , Nothing , Just "11" , Just "12" , Just "13" , Just "14" , Just "15" , Just "16" , Just "17" , Just "18" , Just "19" , Just "20" , Nothing , Just "21" , Just "22" , Just "23" , Just "24" , Just "25" , Just "26" , Just "27" , Just "28" , Just "29" , Just "30" , Nothing , Just "31" , Just "32" , Just "33" , Just "34" , Just "35" , Just "36" , Just "37" , Just "38" , Just "39" , Just "40" , Nothing , Just "41" , Just "42" , Just "43" , Just "44" , Just "45" , Just "46" , Just "47" , Just "48" , Just "49" , Just "50" , Nothing ] beforeParse :: [T.Text] beforeParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "N/A" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints with nullish values AND empty strings as OptionalColumn of Texts, when safeRead is off" expected actual ) parseTextsAndEmptyAndNullishStringsWithoutSafeRead :: Test parseTextsAndEmptyAndNullishStringsWithoutSafeRead = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Just "To" , Just "protect" , Just "the" , Just "world" , Just "from" , Just "devastation" , Nothing , Just "To" , Just "unite" , Just "all" , Just "people" , Just "within" , Just "our" , Just "nation" , Nothing , Just "To" , Just "denounce" , Just "the" , Just "evils" , Just "of" , Just "truth" , Just "and" , Just "love" , Nothing , Just "To" , Just "extend" , Just "our" , Just "reach" , Just "to" , Just "the" , Just "stars" , Just "above" , Nothing , Just "JESSIE!" , Just "JAMES!" , Just "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , Nothing , Just "Surrender now or prepare to fight!" , Nothing , Just "Meowth, that's right!" , Just "NaN" , Just "Nothing" , Just "N/A" ] beforeParse :: [T.Text] beforeParse = [ "" , "To" , "protect" , "the" , "world" , "from" , "devastation" , "" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "" , "Surrender now or prepare to fight!" , "" , "Meowth, that's right!" , "NaN" , "Nothing" , "N/A" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Texts and Empty Strings as OptionalColumn of Text, with safeRead off" expected actual ) -- 3B. PARSING WITH SAFEREAD ON parseIntsAndEmptyStringsWithSafeRead :: Test parseIntsAndEmptyStringsWithSafeRead = let afterParse :: [Maybe Int] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Just 1 , Just 2 , Just 3 , Just 4 , Just 5 , Just 6 , Just 7 , Just 8 , Just 9 , Just 10 , Just 11 , Just 12 , Just 13 , Just 14 , Just 15 , Just 16 , Just 17 , Just 18 , Just 19 , Just 20 , Just 21 , Just 22 , Just 23 , Just 24 , Just 25 , Just 26 , Just 27 , Just 28 , Just 29 , Just 30 , Just 31 , Just 32 , Just 33 , Just 34 , Just 35 , Just 36 , Just 37 , Just 38 , Just 39 , Just 40 , Just 41 , Just 42 , Just 43 , Just 44 , Just 45 , Just 46 , Just 47 , Just 48 , Just 49 , Just 50 ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints and empty strings as OptionalColumn of Ints, when safeRead is on" expected actual ) parseIntsAndDoublesAndEmptyStringsWithSafeRead :: Test parseIntsAndDoublesAndEmptyStringsWithSafeRead = let afterParse :: [Maybe Double] afterParse = [ Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Nothing , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Nothing , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Nothing , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Nothing , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Nothing , Just 3.14 , Just 2.22 , Just 8.55 , Just 23.3 , Just 12.22222235049451 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses combination of Ints, Doubles and empty strings as OptionalColumn of Doubles, when safeRead is on" expected actual ) parseDatesAndEmptyStringsWithSafeRead :: Test parseDatesAndEmptyStringsWithSafeRead = let afterParse :: [Maybe Day] afterParse = [ Just $ fromGregorian 2020 02 12 , Just $ fromGregorian 2020 02 13 , Just $ fromGregorian 2020 02 14 , Nothing , Just $ fromGregorian 2020 02 15 , Just $ fromGregorian 2020 02 16 , Just $ fromGregorian 2020 02 17 , Nothing , Just $ fromGregorian 2020 02 18 , Just $ fromGregorian 2020 02 19 , Just $ fromGregorian 2020 02 20 , Nothing , Just $ fromGregorian 2020 02 21 , Just $ fromGregorian 2020 02 22 , Just $ fromGregorian 2020 02 23 , Nothing , Just $ fromGregorian 2020 02 24 , Just $ fromGregorian 2020 02 25 , Just $ fromGregorian 2020 02 26 , Nothing ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "" , "2020-02-24" , "2020-02-25" , "2020-02-26" , "" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates and Empty Strings as OptionalColumn of Dates, with safeRead on" expected actual ) parseTextsAndEmptyStringsWithSafeRead :: Test parseTextsAndEmptyStringsWithSafeRead = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Just "To" , Just "protect" , Just "the" , Just "world" , Just "from" , Just "devastation" , Nothing , Just "To" , Just "unite" , Just "all" , Just "people" , Just "within" , Just "our" , Just "nation" , Nothing , Just "To" , Just "denounce" , Just "the" , Just "evils" , Just "of" , Just "truth" , Just "and" , Just "love" , Nothing , Just "To" , Just "extend" , Just "our" , Just "reach" , Just "to" , Just "the" , Just "stars" , Just "above" , Nothing , Just "JESSIE!" , Just "JAMES!" , Just "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , Nothing , Just "Surrender now or prepare to fight!" , Nothing , Just "Meowth, that's right!" ] beforeParse :: [T.Text] beforeParse = [ "" , "To" , "protect" , "the" , "world" , "from" , "devastation" , "" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "" , "Surrender now or prepare to fight!" , "" , "Meowth, that's right!" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Texts and Empty Strings as OptionalColumn of Text, with safeRead on" expected actual ) parseIntsAndNullishStringsWithSafeRead :: Test parseIntsAndNullishStringsWithSafeRead = let afterParse :: [Maybe Int] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Just 1 , Just 2 , Just 3 , Just 4 , Just 5 , Just 6 , Just 7 , Just 8 , Just 9 , Just 10 , Just 11 , Just 12 , Just 13 , Just 14 , Just 15 , Just 16 , Just 17 , Just 18 , Just 19 , Just 20 , Just 21 , Just 22 , Just 23 , Just 24 , Just 25 , Just 26 , Just 27 , Just 28 , Just 29 , Just 30 , Just 31 , Just 32 , Just 33 , Just 34 , Just 35 , Just 36 , Just 37 , Just 38 , Just 39 , Just 40 , Just 41 , Just 42 , Just 43 , Just 44 , Just 45 , Just 46 , Just 47 , Just 48 , Just 49 , Just 50 ] beforeParse :: [T.Text] beforeParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "N/A" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints with nullish values as OptionalColumn of Ints, when safeRead is on" expected actual ) parseIntsAndDoublesAndNullishStringsWithSafeRead :: Test parseIntsAndDoublesAndNullishStringsWithSafeRead = let afterParse :: [Maybe Double] afterParse = [ Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Nothing , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Nothing , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Nothing , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Nothing , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Nothing , Just 3.14 , Just 2.22 , Just 8.55 , Just 23.3 , Just 12.03 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "Nothing" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "N/A" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "NULL" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "null" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "NAN" , "3.14" , "2.22" , "8.55" , "23.3" , "12.03" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses combination of Ints, Doubles and empty strings as OptionalColumn of Doubles, when safeRead is off" expected actual ) parseIntsAndNullishAndEmptyStringsWithSafeRead :: Test parseIntsAndNullishAndEmptyStringsWithSafeRead = let afterParse :: [Maybe Int] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just 1 , Just 2 , Just 3 , Just 4 , Just 5 , Just 6 , Just 7 , Just 8 , Just 9 , Just 10 , Nothing , Just 11 , Just 12 , Just 13 , Just 14 , Just 15 , Just 16 , Just 17 , Just 18 , Just 19 , Just 20 , Nothing , Just 21 , Just 22 , Just 23 , Just 24 , Just 25 , Just 26 , Just 27 , Just 28 , Just 29 , Just 30 , Nothing , Just 31 , Just 32 , Just 33 , Just 34 , Just 35 , Just 36 , Just 37 , Just 38 , Just 39 , Just 40 , Nothing , Just 41 , Just 42 , Just 43 , Just 44 , Just 45 , Just 46 , Just 47 , Just 48 , Just 49 , Just 50 , Nothing ] beforeParse :: [T.Text] beforeParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "Nothing" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints with nullish values AND empty strings as OptionalColumn of Ints, when safeRead is on" expected actual ) parseIntsAndDoublesAndNullishAndEmptyStringsWithSafeRead :: Test parseIntsAndDoublesAndNullishAndEmptyStringsWithSafeRead = let afterParse :: [Maybe Double] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just 1 , Just 2 , Just 3 , Just 4 , Just 5 , Just 6 , Just 7 , Just 8 , Just 9 , Just 10 , Nothing , Just 11 , Just 12 , Just 13 , Just 14 , Just 15 , Just 16 , Just 17 , Just 18 , Just 19 , Just 20 , Nothing , Just 21 , Just 22 , Just 23 , Just 24 , Just 25 , Just 26 , Just 27 , Just 28 , Just 29 , Just 30 , Nothing , Just 3.14 ] beforeParse :: [T.Text] beforeParse = [ "N/A" , "N/A" , "N/A" , "N/A" , "Nothing" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "" , "3.14" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints and Doubles with nullish values AND empty strings as OptionalColumn of Doubles, when safeRead is on" expected actual ) parseTextsAndEmptyAndNullishStringsWithSafeRead :: Test parseTextsAndEmptyAndNullishStringsWithSafeRead = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Just "To" , Just "protect" , Just "the" , Just "world" , Just "from" , Just "devastation" , Nothing , Just "To" , Just "unite" , Just "all" , Just "people" , Just "within" , Just "our" , Just "nation" , Nothing , Just "To" , Just "denounce" , Just "the" , Just "evils" , Just "of" , Just "truth" , Just "and" , Just "love" , Nothing , Just "To" , Just "extend" , Just "our" , Just "reach" , Just "to" , Just "the" , Just "stars" , Just "above" , Nothing , Just "JESSIE!" , Just "JAMES!" , Just "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , Nothing , Just "Surrender now or prepare to fight!" , Nothing , Just "Meowth, that's right!" , Nothing , Nothing , Nothing ] beforeParse :: [T.Text] beforeParse = [ "" , "To" , "protect" , "the" , "world" , "from" , "devastation" , "" , "To" , "unite" , "all" , "people" , "within" , "our" , "nation" , "" , "To" , "denounce" , "the" , "evils" , "of" , "truth" , "and" , "love" , "" , "To" , "extend" , "our" , "reach" , "to" , "the" , "stars" , "above" , "" , "JESSIE!" , "JAMES!" , "TEAM ROCKET BLASTS OFF AT THE SPEED OF LIGHT!" , "" , "Surrender now or prepare to fight!" , "" , "Meowth, that's right!" , "NaN" , "Nothing" , "N/A" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Texts and Empty Strings as OptionalColumn of Text, with safeRead off" expected actual ) -- 4. PARSING SHOULD NOT DEPEND ON THE NUMBER OF EXAMPLES. parseIntsWithOneExample :: Test parseIntsWithOneExample = let afterParse :: [Int] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 1 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints without missing values as UnboxedColumn of Ints with only one example" expected actual ) parseIntsWithTwentyFiveExamples :: Test parseIntsWithTwentyFiveExamples = let afterParse :: [Int] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 25 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints without missing values as UnboxedColumn of Ints with some examples" expected actual ) parseIntsWithFortyNineExamples :: Test parseIntsWithFortyNineExamples = let afterParse :: [Int] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 49 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Ints without missing values as UnboxedColumn of Ints with many examples" expected actual ) parseDatesWithOneExample :: Test parseDatesWithOneExample = let afterParse :: [Day] afterParse = [ fromGregorian 2020 02 12 , fromGregorian 2020 02 13 , fromGregorian 2020 02 14 , fromGregorian 2020 02 15 , fromGregorian 2020 02 16 , fromGregorian 2020 02 17 , fromGregorian 2020 02 18 , fromGregorian 2020 02 19 , fromGregorian 2020 02 20 , fromGregorian 2020 02 21 , fromGregorian 2020 02 22 , fromGregorian 2020 02 23 , fromGregorian 2020 02 24 , fromGregorian 2020 02 25 , fromGregorian 2020 02 26 ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 1 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates without missing values as BoxedColumn of Days with only one example" expected actual ) parseDatesWithFifteenExamples :: Test parseDatesWithFifteenExamples = let afterParse :: [Day] afterParse = [ fromGregorian 2020 02 12 , fromGregorian 2020 02 13 , fromGregorian 2020 02 14 , fromGregorian 2020 02 15 , fromGregorian 2020 02 16 , fromGregorian 2020 02 17 , fromGregorian 2020 02 18 , fromGregorian 2020 02 19 , fromGregorian 2020 02 20 , fromGregorian 2020 02 21 , fromGregorian 2020 02 22 , fromGregorian 2020 02 23 , fromGregorian 2020 02 24 , fromGregorian 2020 02 25 , fromGregorian 2020 02 26 ] beforeParse :: [T.Text] beforeParse = [ "2020-02-12" , "2020-02-13" , "2020-02-14" , "2020-02-15" , "2020-02-16" , "2020-02-17" , "2020-02-18" , "2020-02-19" , "2020-02-20" , "2020-02-21" , "2020-02-22" , "2020-02-23" , "2020-02-24" , "2020-02-25" , "2020-02-26" ] expected = DI.BoxedColumn $ V.fromList afterParse actual = D.parseDefault 15 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses Dates without missing values as BoxedColumn of Days with many examples" expected actual ) parseIntsAndDoublesAsDoublesWithOneExample :: Test parseIntsAndDoublesAsDoublesWithOneExample = let afterParse :: [Double] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0 , 8.0 , 9.0 , 10.0 , 11.0 , 12.0 , 13.0 , 14.0 , 15.0 , 16.0 , 17.0 , 18.0 , 19.0 , 20.0 , 21.0 , 22.0 , 23.0 , 24.0 , 25.0 , 26.0 , 27.0 , 28.0 , 29.0 , 30.0 , 31.0 , 32.0 , 33.0 , 34.0 , 35.0 , 36.0 , 37.0 , 38.0 , 39.0 , 40.0 , 41.0 , 42.0 , 43.0 , 44.0 , 45.0 , 46.0 , 47.0 , 48.0 , 49.0 , 50.0 , 3.14 , 2.22 , 8.55 , 23.3 , 12.22222235049450945049504950 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 1 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Doubles as UnboxedColumn of Doubles with just one example" expected actual ) parseIntsAndDoublesAsDoublesWithManyExamples :: Test parseIntsAndDoublesAsDoublesWithManyExamples = let afterParse :: [Double] afterParse = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0 , 8.0 , 9.0 , 10.0 , 11.0 , 12.0 , 13.0 , 14.0 , 15.0 , 16.0 , 17.0 , 18.0 , 19.0 , 20.0 , 21.0 , 22.0 , 23.0 , 24.0 , 25.0 , 26.0 , 27.0 , 28.0 , 29.0 , 30.0 , 31.0 , 32.0 , 33.0 , 34.0 , 35.0 , 36.0 , 37.0 , 38.0 , 39.0 , 40.0 , 41.0 , 42.0 , 43.0 , 44.0 , 45.0 , 46.0 , 47.0 , 48.0 , 49.0 , 50.0 , 3.14 , 2.22 , 8.55 , 23.3 , 12.22222235049450945049504950 ] beforeParse :: [T.Text] beforeParse = [ "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.UnboxedColumn $ VU.fromList afterParse actual = D.parseDefault 50 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Doubles as UnboxedColumn of Doubles with just one example" expected actual ) parseIntsAndDoublesAndEmptyStringsAsDoublesWithOneExampleWithSafeReadOff :: Test parseIntsAndDoublesAndEmptyStringsAsDoublesWithOneExampleWithSafeReadOff = let afterParse :: [Maybe Double] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Just 3.14 , Just 2.22 , Just 8.55 , Just 23.3 , Just 12.22222235049451 ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 1 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Doubles as UnboxedColumn of Doubles with just one example" expected actual ) parseIntsAndDoublesAndEmptyStringsAsDoublesWithManyExamplesWithSafeReadOff :: Test parseIntsAndDoublesAndEmptyStringsAsDoublesWithManyExamplesWithSafeReadOff = let afterParse :: [Maybe Double] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Just 1.0 , Just 2.0 , Just 3.0 , Just 4.0 , Just 5.0 , Just 6.0 , Just 7.0 , Just 8.0 , Just 9.0 , Just 10.0 , Just 11.0 , Just 12.0 , Just 13.0 , Just 14.0 , Just 15.0 , Just 16.0 , Just 17.0 , Just 18.0 , Just 19.0 , Just 20.0 , Just 21.0 , Just 22.0 , Just 23.0 , Just 24.0 , Just 25.0 , Just 26.0 , Just 27.0 , Just 28.0 , Just 29.0 , Just 30.0 , Just 31.0 , Just 32.0 , Just 33.0 , Just 34.0 , Just 35.0 , Just 36.0 , Just 37.0 , Just 38.0 , Just 39.0 , Just 40.0 , Just 41.0 , Just 42.0 , Just 43.0 , Just 44.0 , Just 45.0 , Just 46.0 , Just 47.0 , Just 48.0 , Just 49.0 , Just 50.0 , Just 3.14 , Just 2.22 , Just 8.55 , Just 23.3 , Just 12.22222235049451 ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "21" , "22" , "23" , "24" , "25" , "26" , "27" , "28" , "29" , "30" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "38" , "39" , "40" , "41" , "42" , "43" , "44" , "45" , "46" , "47" , "48" , "49" , "50" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "31.0" , "32.0" , "33.0" , "34.0" , "35.0" , "36.0" , "37.0" , "38.0" , "39.0" , "40.0" , "41.0" , "42.0" , "43.0" , "44.0" , "45.0" , "46.0" , "47.0" , "48.0" , "49.0" , "50.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 30 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints and Doubles as UnboxedColumn of Doubles with just one example" expected actual ) parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithOneExampleWithSafeReadOff :: Test parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithOneExampleWithSafeReadOff = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "1" , Just "2" , Just "3" , Just "4" , Just "5" , Just "6" , Just "7" , Just "8" , Just "9" , Just "10" , Just "11" , Just "12" , Just "13" , Just "14" , Just "15" , Just "16" , Just "17" , Just "18" , Just "19" , Just "20" , Just "1.0" , Just "2.0" , Just "3.0" , Just "4.0" , Just "5.0" , Just "6.0" , Just "7.0" , Just "8.0" , Just "9.0" , Just "10.0" , Just "11.0" , Just "12.0" , Just "13.0" , Just "14.0" , Just "15.0" , Just "16.0" , Just "17.0" , Just "18.0" , Just "19.0" , Just "20.0" , Just "21.0" , Just "22.0" , Just "23.0" , Just "24.0" , Just "25.0" , Just "26.0" , Just "27.0" , Just "28.0" , Just "29.0" , Just "30.0" , Just "3.14" , Just "2.22" , Just "8.55" , Just "23.3" , Just "12.22222235049451" ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 1 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints, Doubles, empty strings, nullish as OptionalColumn of Text with just one example, when safeRead is off" expected actual ) parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithManyExamplesWithSafeReadOff :: Test parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithManyExamplesWithSafeReadOff = let afterParse :: [Maybe T.Text] afterParse = [ Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Nothing , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "NaN" , Just "N/A" , Just "1" , Just "2" , Just "3" , Just "4" , Just "5" , Just "6" , Just "7" , Just "8" , Just "9" , Just "10" , Just "11" , Just "12" , Just "13" , Just "14" , Just "15" , Just "16" , Just "17" , Just "18" , Just "19" , Just "20" , Just "1.0" , Just "2.0" , Just "3.0" , Just "4.0" , Just "5.0" , Just "6.0" , Just "7.0" , Just "8.0" , Just "9.0" , Just "10.0" , Just "11.0" , Just "12.0" , Just "13.0" , Just "14.0" , Just "15.0" , Just "16.0" , Just "17.0" , Just "18.0" , Just "19.0" , Just "20.0" , Just "21.0" , Just "22.0" , Just "23.0" , Just "24.0" , Just "25.0" , Just "26.0" , Just "27.0" , Just "28.0" , Just "29.0" , Just "30.0" , Just "3.14" , Just "2.22" , Just "8.55" , Just "23.3" , Just "12.22222235049451" ] beforeParse :: [T.Text] beforeParse = [ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "NaN" , "N/A" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "11" , "12" , "13" , "14" , "15" , "16" , "17" , "18" , "19" , "20" , "1.0" , "2.0" , "3.0" , "4.0" , "5.0" , "6.0" , "7.0" , "8.0" , "9.0" , "10.0" , "11.0" , "12.0" , "13.0" , "14.0" , "15.0" , "16.0" , "17.0" , "18.0" , "19.0" , "20.0" , "21.0" , "22.0" , "23.0" , "24.0" , "25.0" , "26.0" , "27.0" , "28.0" , "29.0" , "30.0" , "3.14" , "2.22" , "8.55" , "23.3" , "12.22222235049451" ] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 30 False "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase ( assertEqual "Correctly parses a mixture of Ints, Doubles, empty strings, nullish as OptionalColumn of Text with many examples, when safeRead is off" expected actual ) -- 5. EDGE CASES THAT HAVE TO BE INTERPRETED CORRECTLY parseManyNullishAndOneInt :: Test parseManyNullishAndOneInt = let afterParse :: [Maybe Int] afterParse = replicate 100 Nothing ++ [Just 100000] beforeParse :: [T.Text] beforeParse = replicate 100 "NaN" ++ ["100000"] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase (assertEqual "Correctly parses many Nulls followed by one Int" expected actual) parseManyNullishAndOneDouble :: Test parseManyNullishAndOneDouble = let afterParse :: [Maybe Double] afterParse = replicate 100 Nothing ++ [Just 3.14] beforeParse :: [T.Text] beforeParse = replicate 100 "NaN" ++ ["3.14"] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase (assertEqual "Correctly parses many Nulls followed by one Int" expected actual) parseManyNullishAndOneDate :: Test parseManyNullishAndOneDate = let afterParse :: [Maybe Day] afterParse = replicate 100 Nothing ++ [Just $ fromGregorian 2024 12 25] beforeParse :: [T.Text] beforeParse = replicate 100 "NaN" ++ ["2024-12-25"] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase (assertEqual "Correctly parses many Nulls followed by one Int" expected actual) parseManyNullishAndIncorrectDates :: Test parseManyNullishAndIncorrectDates = let afterParse :: [Maybe T.Text] afterParse = replicate 100 Nothing ++ [Just "2024-12-25", Just "2024-12-w6"] beforeParse :: [T.Text] beforeParse = replicate 100 "NaN" ++ ["2024-12-25", "2024-12-w6"] expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase (assertEqual "Correctly parses many Nulls followed by one Int" expected actual) parseRepeatedNullish :: Test parseRepeatedNullish = let afterParse :: [Maybe T.Text] afterParse = replicate 100 Nothing beforeParse :: [T.Text] beforeParse = replicate 100 "NaN" expected = DI.OptionalColumn $ V.fromList afterParse actual = D.parseDefault 10 True "%Y-%m-%d" $ DI.fromVector $ V.fromList beforeParse in TestCase (assertEqual "Correctly parses many Nulls followed by one Int" expected actual) parseTests :: [Test] parseTests = [ -- 1. SIMPLE CASES TestLabel "parseInts" parseInts , TestLabel "parseDoubles" parseDoubles , TestLabel "parseDates" parseDates , TestLabel "parseTexts" parseTexts , -- 2. COMBINATION CASES TestLabel "parseIntsAndDoublesAsDoubles" parseIntsAndDoublesAsDoubles , TestLabel "parseIntsAndDatesAsTexts" parseIntsAndDatesAsTexts , TestLabel "parseTextsAndDoublesAsTexts" parseTextsAndDoublesAsTexts , TestLabel "parseDatesAndTextsAsTexts" parseDatesAndTextsAsTexts , -- 3A. PARSING WITH SAFEREAD OFF TestLabel "parseIntsWithoutSafeRead" parseIntsWithoutSafeRead , TestLabel "parseDoublesWithoutSafeRead" parseDoublesWithoutSafeRead , TestLabel "parseDatesWithoutSafeRead" parseDatesWithoutSafeRead , TestLabel "parseTextsWithoutSafeRead" parseTextsWithoutSafeRead , TestLabel "parseIntsAndEmptyStringsWithoutSafeRead" parseIntsAndEmptyStringsWithoutSafeRead , TestLabel "parseIntsAndDoublesAndEmptyStringsWithoutSafeRead" parseIntsAndDoublesAndEmptyStringsWithoutSafeRead , TestLabel "parseDatesAndEmptyStringsWithoutSafeRead" parseDatesAndEmptyStringsWithoutSafeRead , TestLabel "parseTextsAndEmptyStringsWithoutSafeRead" parseTextsAndEmptyStringsWithoutSafeRead , TestLabel "parseIntsAndNullishStringsWithoutSafeRead" parseIntsAndNullishStringsWithoutSafeRead , TestLabel "parseIntsAndDoublesAndNullishStringsWithoutSafeRead" parseIntsAndDoublesAndNullishStringsWithoutSafeRead , TestLabel "parseIntsAndNullishAndEmptyStringsWithoutSafeRead" parseIntsAndNullishAndEmptyStringsWithoutSafeRead , TestLabel "parseTextsAndEmptyAndNullishStringsWithoutSafeRead" parseTextsAndEmptyAndNullishStringsWithoutSafeRead , -- 3B. PARSING WITH SAFEREAD ON TestLabel "parseIntsAndEmptyStringsWithSafeRead" parseIntsAndEmptyStringsWithSafeRead , TestLabel "parseIntsAndDoublesAndEmptyStringsWithSafeRead" parseIntsAndDoublesAndEmptyStringsWithSafeRead , TestLabel "parseDatesAndEmptyStringsWithSafeRead" parseDatesAndEmptyStringsWithSafeRead , TestLabel "parseTextsAndEmptyStringsWithSafeRead" parseTextsAndEmptyStringsWithSafeRead , TestLabel "parseIntsAndNullishStringsWithSafeRead" parseIntsAndNullishStringsWithSafeRead , TestLabel "parseIntsAndDoublesAndNullishStringsWithSafeRead" parseIntsAndDoublesAndNullishStringsWithSafeRead , TestLabel "parseIntsAndDoublesAndNullishAndEmptyStringsWithSafeRead" parseIntsAndDoublesAndNullishAndEmptyStringsWithSafeRead , TestLabel "parseIntsAndNullishAndEmptyStringsWithSafeRead" parseIntsAndNullishAndEmptyStringsWithSafeRead , TestLabel "parseTextsAndEmptyAndNullishStringsWithSafeRead" parseTextsAndEmptyAndNullishStringsWithSafeRead , -- 4A. PARSING MUST NOT DEPEND ON THE NUMBER OF EXAMPLES TestLabel "parseIntsWithOneExample" parseIntsWithOneExample , TestLabel "parseIntsWithTwentyFiveExamples" parseIntsWithTwentyFiveExamples , TestLabel "parseIntsWithFortyNineExamples" parseIntsWithFortyNineExamples , TestLabel "parseDatesWithOneExample" parseDatesWithOneExample , TestLabel "parseDatesWithFifteenExamples" parseDatesWithFifteenExamples , TestLabel "parseIntsAndDoublesAsDoublesWithOneExample" parseIntsAndDoublesAsDoublesWithOneExample , TestLabel "parseIntsAndDoublesAsDoublesWithManyExamples" parseIntsAndDoublesAsDoublesWithManyExamples , TestLabel "parseIntsAndDoublesAndEmptyStringsAsDoublesWithOneExampleWithSafeReadOff" parseIntsAndDoublesAndEmptyStringsAsDoublesWithOneExampleWithSafeReadOff , TestLabel "parseIntsAndDoublesAndEmptyStringsAsDoublesWithManyExamplesWithSafeReadOff" parseIntsAndDoublesAndEmptyStringsAsDoublesWithManyExamplesWithSafeReadOff , TestLabel "parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithOneExampleWithSafeReadOff" parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithOneExampleWithSafeReadOff , TestLabel "parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithManyExamplesWithSafeReadOff" parseIntsAndDoublesAndEmptyStringsAndNullishAsStringssWithManyExamplesWithSafeReadOff , -- 5. EDGE CASES THAT HAVE TO BE PARSED CORRECTLY TestLabel "parseManyNullishAndOneInt" parseManyNullishAndOneInt , TestLabel "parseManyNullishAndOneDouble" parseManyNullishAndOneDouble , TestLabel "parseRepeatedNullish" parseRepeatedNullish ] tests :: Test tests = TestList $ dimensionsTest ++ Operations.Aggregations.tests ++ Operations.Apply.tests ++ Operations.Core.tests ++ Operations.Derive.tests ++ Operations.Filter.tests ++ Operations.GroupBy.tests ++ Operations.InsertColumn.tests ++ Operations.Join.tests ++ Operations.Merge.tests ++ Operations.ReadCsv.tests ++ Operations.Sort.tests ++ Operations.Statistics.tests ++ Operations.Take.tests ++ Functions.tests ++ Parquet.tests ++ parseTests main :: IO () main = do result <- runTestTT tests if failures result > 0 || errors result > 0 then Exit.exitFailure else Exit.exitSuccess