packages feed

hw-dsv-0.3.8: test/HaskellWorks/Data/Dsv/Lazy/CursorSpec.hs

{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}

module HaskellWorks.Data.Dsv.Lazy.CursorSpec (spec) where

import Data.Semigroup                      ((<>))
import HaskellWorks.Data.Bits.BitShown
import HaskellWorks.Data.Dsv.Internal.Char (comma)
import HaskellWorks.Hspec.Hedgehog
import Hedgehog
import Test.Hspec

import qualified Data.ByteString.Lazy                   as LBS
import qualified Data.Vector                            as DV
import qualified HaskellWorks.Data.Dsv.Lazy.Cursor      as SVL
import qualified HaskellWorks.Data.Dsv.Lazy.Cursor.Lazy as SVLL

{-# ANN module ("HLint: ignore Redundant do"        :: String) #-}
{-# ANN module ("HLint: ignore Reduce duplication"  :: String) #-}
{-# ANN module ("HLint: ignore Redundant bracket"   :: String) #-}

subjectEmpty, subjectSS, subjectSM, subjectMS, subjectMM :: LBS.ByteString
expectedEmpty, expectedSS, expectedSM, expectedMS, expectedMM :: [DV.Vector LBS.ByteString]
subjectEmpty = ""
expectedEmpty = mkExpected []
subjectSS = "hello"
expectedSS = mkExpected [["hello"]]
subjectSM = "hello\nyes"
expectedSM = mkExpected [["hello"],["yes"]]
subjectMS = "hello,goodbye"
expectedMS = mkExpected [["hello","goodbye"]]
subjectMM = "hello,goodbye\nyes,no"
expectedMM = mkExpected [["hello","goodbye"],["yes","no"]]

testToListVector :: LBS.ByteString -> [DV.Vector LBS.ByteString]
testToListVector = SVLL.toListVector . SVL.makeCursor comma

testToListList :: LBS.ByteString -> [[LBS.ByteString]]
testToListList = fmap DV.toList . testToListVector

-- Adds a terminal newline to the file
testToListVector' :: LBS.ByteString -> [DV.Vector LBS.ByteString]
testToListVector' = testToListVector . (<> "\n")

mkExpected :: [[LBS.ByteString]] -> [DV.Vector LBS.ByteString]
mkExpected = fmap DV.fromList

spec :: Spec
spec = describe "HaskellWorks.Data.Dsv.Lazy.CursorSpec" $ do
  -- no terminal newline
  it "Case 1" $ requireTest $ do
    testToListVector subjectEmpty === expectedEmpty
  it "Case 2" $ requireTest $ do
    testToListVector subjectSS === expectedSS
  it "Case 3" $ requireTest $ do
    testToListVector subjectSM === expectedSM
  it "Case 4" $ requireTest $ do
    testToListVector subjectMS === expectedMS
  it "Case 5" $ requireTest $ do
    testToListVector subjectMM === expectedMM
  -- terminal newline
  -- the following test does not pass
  --it "Case 6" $ requireTest $ do
    --testToListVector' subjectEmpty === expectedEmpty
  it "Case 7" $ requireTest $ do
    testToListVector' subjectSS === expectedSS
  it "Case 8" $ requireTest $ do
    testToListVector' subjectSM === expectedSM
  it "Case 9" $ requireTest $ do
    testToListVector' subjectMS === expectedMS
  it "Case 10" $ requireTest $ do
    testToListVector' subjectMM === expectedMM
  describe "boundaries" $ do
    it "513 bytes" $ requireTest $ do
      let actual = testToListList $ LBS.intercalate "\n"
            [ "id,group_id,arm,first_name,last_name,email,contact_number,start_date,status,dose_smart_id,fitbit_id,glyco_id,sms_reminder,email_reminder,inactive_reminder,starting_weight,starting_bmi,starting_hba1c"
            , "10,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,1,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,2018-01-01 00:00:00 UTC,Active,,,,Never,Weekly,Never,100.01,10.01,1.0e-2"
            ]
      actual ===
        [ [ "id"
          , "group_id"
          , "arm"
          , "first_name"
          , "last_name"
          , "email"
          , "contact_number"
          , "start_date"
          , "status"
          , "dose_smart_id"
          , "fitbit_id"
          , "glyco_id"
          , "sms_reminder"
          , "email_reminder"
          , "inactive_reminder"
          , "starting_weight"
          , "starting_bmi"
          , "starting_hba1c"
          ]
        , [ "10"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "1"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "2018-01-01 00:00:00 UTC"
          , "Active"
          , ""
          , ""
          , ""
          , "Never"
          , "Weekly"
          , "Never"
          , "100.01"
          , "10.01"
          , "1.0e-2"
          ]
        ]
    it "512 bytes" $ requireTest $ do
      let actual = testToListList $ LBS.intercalate "\n"
            [ "id,group_id,arm,first_name,last_name,email,contact_number,start_date,status,dose_smart_id,fitbit_id,glyco_id,sms_reminder,email_reminder,inactive_reminder,starting_weight,starting_bmi,starting_hba1c"
            , "10,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,1,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,2018-01-01 00:00:00 UTC,Active,,,,Never,Weekly,Never,100.01,10.01,1.0e-2"
            ]
      actual ===
        [ [ "id"
          , "group_id"
          , "arm"
          , "first_name"
          , "last_name"
          , "email"
          , "contact_number"
          , "start_date"
          , "status"
          , "dose_smart_id"
          , "fitbit_id"
          , "glyco_id"
          , "sms_reminder"
          , "email_reminder"
          , "inactive_reminder"
          , "starting_weight"
          , "starting_bmi"
          , "starting_hba1c"
          ]
        , [ "10"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "1"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "2018-01-01 00:00:00 UTC"
          , "Active"
          , ""
          , ""
          , ""
          , "Never"
          , "Weekly"
          , "Never"
          , "100.01"
          , "10.01"
          , "1.0e-2"
          ]
        ]

    it "511 bytes" $ requireTest $ do
      let actual = testToListList $ LBS.intercalate "\n"
            [ "id,group_id,arm,first_name,last_name,email,contact_number,start_date,status,dose_smart_id,fitbit_id,glyco_id,sms_reminder,email_reminder,inactive_reminder,starting_weight,starting_bmi,starting_hba1c"
            , "10,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,1,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,aaaaaaa,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,2018-01-01 00:00:00 UTC,Active,,,,Never,Weekly,Never,100.01,10.01,1.0e-2"
            ]
      actual ===
        [ [ "id"
          , "group_id"
          , "arm"
          , "first_name"
          , "last_name"
          , "email"
          , "contact_number"
          , "start_date"
          , "status"
          , "dose_smart_id"
          , "fitbit_id"
          , "glyco_id"
          , "sms_reminder"
          , "email_reminder"
          , "inactive_reminder"
          , "starting_weight"
          , "starting_bmi"
          , "starting_hba1c"
          ]
        , [ "10"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "1"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "aaaaaaa"
          , "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
          , "2018-01-01 00:00:00 UTC"
          , "Active"
          , ""
          , ""
          , ""
          , "Never"
          , "Weekly"
          , "Never"
          , "100.01"
          , "10.01"
          , "1.0e-2"
          ]
        ]
  describe "single quoted field with newline at 127-129" $ do
    it "newline at 127 bytes" $ requireTest $ do
      let newlinePos = 127
      let text = "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""
      let expected = [["\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""]]
      let cursor = SVL.makeCursor 44 text
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorMarkers  cursor))
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorNewlines cursor))
      let actual = fmap DV.toList (DV.toList (SVLL.toVectorVector cursor))
      LBS.length text === newlinePos + 2
      LBS.index text newlinePos === 10
      actual === expected
    it "newline at 128 bytes" $ requireTest $ do
      let newlinePos = 128
      let text = "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""
      let expected = [["\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""]]
      let cursor = SVL.makeCursor 44 text
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorMarkers  cursor))
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorNewlines cursor))
      let actual = fmap DV.toList (DV.toList (SVLL.toVectorVector cursor))
      LBS.length text === newlinePos + 2
      LBS.index text newlinePos === 10
      actual === expected
    it "newline at 129 bytes" $ requireTest $ do
      let newlinePos = 129
      let text = "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""
      let expected = [["\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\""]]
      let cursor = SVL.makeCursor 44 text
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorMarkers  cursor))
      _ <- forAll $ pure $ BitShown (head (SVL.dsvCursorNewlines cursor))
      let actual = fmap DV.toList (DV.toList (SVLL.toVectorVector cursor))
      LBS.length text === newlinePos + 2
      LBS.index text newlinePos === 10
      actual === expected