packages feed

geolite-csv-0.1.0: test/Spec.hs

{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Test.HUnit                           (Assertion,(@?=),assertBool,assertFailure)
import Test.Framework                       (defaultMainWithOpts, interpretArgsOrExit,
                                             testGroup, Test)
import Test.Framework.Providers.HUnit       (testCase)
import Test.Framework.Runners.TestPattern   (parseTestPattern)
import Test.Framework.Runners.Options       (RunnerOptions'(..))
import Geolite.Csv                          (cities,blocks)
import Data.Text                            (Text)
import Colonnade.Types
import Siphon.Types
import Data.Functor.Identity
import Control.Monad                        (unless)
import System.Environment                   (getArgs)
import System.Directory                     (doesDirectoryExist)
import System.IO                            (withFile,IOMode(ReadMode))
import qualified Data.Text                  as Text
import qualified Pipes.Prelude              as Pipes
import qualified Pipes.ByteString           as PB
import qualified Pipes.Text.Encoding        as PT
import qualified Siphon.Decoding            as SD
import qualified Colonnade.Decoding         as Decoding
import Pipes

------------------------------------------------
-- The default behavior of this test suite is to
-- test the CSV decoders against small samples of
-- the GeoLite2 databases. These small samples are
-- included as part of this repository. If you give
-- this test suite an argument named "large", it
-- will run against the full CSVs, which are around
-- 350MB. These are not included
-- as part of the repository, so they need to be
-- downloaded. The script found in
-- scripts/load-full-databases will download the full
-- archive, decompress it, and move the files to
-- the appropriate directory for this test suite
-- to run on them.
-----------------------------------------------

main :: IO ()
main = do
  xs <- getArgs
  ropts' <- interpretArgsOrExit xs
  let ropts = ropts'
        { ropt_test_patterns = case ropt_test_patterns ropts' of
            Nothing -> Just [parseTestPattern "small"]
            Just xs -> Just xs
        }
  defaultMainWithOpts tests ropts

tests :: [Test]
tests = flip concatMap ["small","large"] $ \size ->
  [ testGroup size
    [ testCase "Network Blocks" $ streamFileWith
        ("data/" ++ size ++ "/GeoLite2-City-Blocks-IPv4.csv")
        blocks
    , testCase "English City Locations" $ streamFileWith
        ("data/" ++ size ++ "/GeoLite2-City-Locations-en.csv")
        cities
    , testCase "Japanese City Locations" $ streamFileWith
        ("data/" ++ size ++ "/GeoLite2-City-Locations-ja.csv")
        cities
    ]
  ]

streamFileWith ::
     String
  -> Pipe Text a IO (DecodingRowError Headed Text)
  -> Assertion
streamFileWith filename decodingPipe = do
  r <- withFile filename ReadMode $ \h -> runEffect $
        fmap (SD.convertDecodeError "utf-8") (PT.decode (PT.utf8 . PT.eof) $ PB.fromHandle h)
    >-> fmap Just decodingPipe
    >-> Pipes.drain
  case r of
    Nothing -> assertBool "impossible" True
    Just err -> assertFailure (Decoding.prettyError Text.unpack err)

-- let dirPiece = case xs of
--       ["full"] -> "large/"
--       _        -> "small/"
--     fullDirName = "data/" ++ dirPiece
--     errMsg = concat
--       [ "The "
--       , fullDirName
--       , " directory does not exist in the geolite project"
--       ]