packages feed

zim-parser-0.1.0.0: test/Codec/Archive/Zim/ParserSpec.hs

{-# LANGUAGE OverloadedStrings #-}
module Codec.Archive.Zim.ParserSpec (main, spec) where

import Control.Monad (forM_)
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as BL
import Data.Maybe (fromJust, isJust)
import System.IO (Handle, openBinaryFile, IOMode(ReadMode))

import Data.Array.IArray (bounds, (!))

import Test.Hspec

import Codec.Archive.Zim.Parser

testSmallFilePath :: FilePath
testSmallFilePath = "test/wikipedia_en_ray_charles_2015-06.zim"

main :: IO ()
main = hspec spec

setup :: IO (ZimHeader, Handle)
setup = do
    small <- openBinaryFile testSmallFilePath ReadMode
    smallZim <- getZimHeader small
    return (smallZim, small)

spec :: Spec
spec = do
    describe "zim" $ do
      beforeAll setup $ do

        it "can open Ray Charles ZIM" $ \(smallZim, _) -> do
            zimMagicNumber smallZim `shouldBe` 72173914

        it "can get version" $ \(smallZim, _) -> do
            zimVersion smallZim `shouldBe` 5

        it "can get article count" $ \(smallZim, _) -> do
            zimArticleCount smallZim `shouldBe` 458

        it "can get cluster count" $ \(smallZim, _) -> do
            zimClusterCount smallZim `shouldBe` 215

        it "can parse MIME list" $ \(smallZim, small) -> do
            mimeList <- getZimMimeList smallZim small
            mimeList ! 0 `shouldBe` "application/javascript"
            bounds mimeList `shouldBe` (0, 9)

        it "can get main page" $ \(smallZim, _) -> do
            zimMainPage smallZim `shouldBe` Just 238

        it "can get main page URL" $ \_ -> do
            url <- getZimMainPageUrl testSmallFilePath
            url `shouldBe` Just "A/index.htm"

        it "can lookup directory entry by URL index" $ \(smallZim, small) -> do
            de <- getZimDirEntByUrlIndex smallZim small 0
            zimDeType de `shouldBe` ZimRedirectEntry
            zimDeUrl de `shouldBe` "favicon"

        it "can lookup directory entry by Title index" $ \(smallZim, small) -> do
            de <- getZimDirEntByTitleIndex smallZim small 3
            zimDeTitle de `shouldBe` "(The Night Time Is) The Right Time"
            zimDeNamespace de `shouldBe` 'A'

        it "can lookup cluster 0" $ \(smallZim, small) -> do
            cluster <- getZimCluster smallZim small 0
            BL.length  cluster `shouldBe` 2160083

        it "can get cluster 2 blob 0" $ \(smallZim, small) -> do
            blob <- getZimBlob smallZim small 2 0
            BL.take 4 blob `shouldBe` "\137PNG"

        it "can get content for article 11" $ \(smallZim, small) -> do
            bs <- getZimContentByUrlIndex smallZim small 11
            BL.take 12 bs `shouldBe` "<html><head>"

        it "can search for title" $ \(smallZim, small) -> do
            let title = B8.pack "(The Night Time Is) The Right Time"
            res <- searchZimDirEntByTitle smallZim small 'A' title
            (title, res) `shouldSatisfy` (isJust . snd)
            (fst . fromJust $ res) `shouldBe` 3

        it "can search for non-existent title" $ \(smallZim, small) -> do
            let title = B8.pack "nonexistent-title"
            res <- searchZimDirEntByTitle smallZim small 'A' title
            (title, res) `shouldBe` (title, Nothing)

        it "can search for title prefix" $ \(smallZim, small) -> do
            let title = B8.pack "Blue"
            res <- searchZimDirEntByTitlePrefix smallZim small 'A' title
            (title, res) `shouldSatisfy` (isJust . snd)
            let Just ((lb, _), (ub, _)) = res
            (lb, ub) `shouldBe` (22, 25)

        it "can search for non-existent title prefix" $ \(smallZim, small) -> do
            let title = B8.pack "ZZZ"
            res <- searchZimDirEntByTitlePrefix smallZim small 'A' title
            (title, res) `shouldBe` (title, Nothing)

        it "can search for first title prefix" $ \(smallZim, small) -> do
            let title = B8.pack "fav"
            res <- searchZimDirEntByTitlePrefix smallZim small '-' title
            (title, res) `shouldSatisfy` (isJust . snd)
            let Just ((lb, _), (ub, _)) = res
            (lb, ub) `shouldBe` (0, 0)

        it "can search for last title prefix" $ \(smallZim, small) -> do
            let title = B8.pack "Title"
            res <- searchZimDirEntByTitlePrefix smallZim small 'M' title
            (title, res) `shouldSatisfy` (isJust . snd)
            let Just ((lb, _), (ub, _)) = res
            (lb, ub) `shouldBe` (457, 457)

        it "can search for URLs" $ \(smallZim, small) -> do
            let url = "A/A_Fool_for_You.html"
            res <- searchZimDirEntByUrl smallZim small url
            (url, res) `shouldSatisfy` (isJust . snd)
            (fst . fromJust $ res) `shouldBe` 4

        it "can search for non-existent URL" $ \(smallZim, small) -> do
            let url = "a/zzz.html"
            res <- searchZimDirEntByUrl smallZim small url
            res `shouldBe` Nothing

        it "can get (mimetype, content)" $ \_ -> do
            res <- getZimUrlContent testSmallFilePath "A/index.htm"
            res `shouldSatisfy` isJust
            let Just (m, c) = res
            (m, BL.length c) `shouldBe` ("text/html", 8637)

        let searchAllUrls hdr hdl des =
              forM_ des $ \de -> do
                let ns = zimDeNamespace de
                    url = zimDeUrl de
                    url' = ns `B8.cons` '/' `B8.cons` url
                res <- searchZimDirEntByUrl hdr hdl url'
                (url, res) `shouldSatisfy` (isJust . snd)
                (zimDeUrl . snd . fromJust $ res) `shouldBe` url
            getAllArticles hdr hdl n = do
              let ns = [0 .. n - 1]
              forM_ ns $ \i -> do
                de <- getZimDirEntByUrlIndex hdr hdl i
                let url = zimDeUrl de
                bs <- getZimContentByUrlIndex hdr hdl i
                (url, bs) `shouldSatisfy` (\(_, b) -> BL.length b > 0)

        it "can search all URLs" $ \(smallZim, small) -> do
          deList <- mapM (getZimDirEntByUrlIndex smallZim small) [0 .. zimArticleCount smallZim - 1]
          searchAllUrls smallZim small deList

        it "can get content from all URLs" $ \(smallZim, small) -> do
          getAllArticles smallZim small 457