langchain-hs-0.0.3.0: test/Test/Langchain/DocumentLoader/Core.hs
{-# LANGUAGE OverloadedStrings #-}
module Test.Langchain.DocumentLoader.Core (tests) where
import Data.Aeson (Value (..))
import Data.Map (empty, fromList)
import qualified Data.Map as Map
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import System.FilePath ((</>))
import System.IO.Temp (withSystemTempDirectory)
import Test.Tasty
import Test.Tasty.HUnit
import Langchain.DocumentLoader.Core
import Langchain.DocumentLoader.FileLoader
import Langchain.Utils (showText)
createTestFile :: FilePath -> String -> IO ()
createTestFile = writeFile
withTestFile :: String -> (FilePath -> IO a) -> IO a
withTestFile content action =
withSystemTempDirectory "test-doc-loader" $ \dir -> do
let filePath = dir </> "test-file.txt"
createTestFile filePath content
action filePath
documentTests :: TestTree
documentTests =
testGroup
"Document Tests"
[ testCase "Document Semigroup instance should concatenate content and metadata" $ do
let doc1 = Document "Hello" (fromList [("source", String "file1")])
doc2 = Document " World" (fromList [("page", Number 1)])
combined = doc1 <> doc2
pageContent combined @?= "Hello World"
metadata combined @?= fromList [("source", String "file1"), ("page", Number 1)]
, testCase "Document Monoid instance should have identity element" $ do
let doc = Document "Content" (fromList [("key", String "value")])
doc <> mempty @?= doc
doc @?= doc
pageContent mempty @?= ""
metadata mempty @?= empty
]
fileLoaderTests :: TestTree
fileLoaderTests =
testGroup
"FileLoader Tests"
[ testCase "load should return document with file content and metadata" $
withTestFile "Test content for the file." $ \filePath -> do
result <- load (FileLoader filePath)
case result of
Left err -> assertFailure $ "Expected Right but got Left: " ++ show err
Right docs@(doc : _) -> do
length docs @?= 1
pageContent doc @?= "Test content for the file."
Map.lookup "source" (metadata doc) @?= Just (String $ T.pack filePath)
Right _ -> assertFailure "Document list is empty"
, testCase "load should return error for non-existent file" $ do
result <- load (FileLoader "non-existent-file.txt")
case result of
Left err ->
assertBool
"Error message should mention file not found"
(T.isInfixOf "File not found" (showText err))
Right _ -> assertFailure "Expected Left for non-existent file but got Right"
, testCase "loadAndSplit should split content using defaultCharacterSplitterOps" $
withTestFile "Paragraph 1\n\nParagraph 2\n\nParagraph 3" $ \filePath -> do
result <- loadAndSplit (FileLoader filePath)
case result of
Left err -> assertFailure $ "Expected Right but got Left: " ++ show err
Right chunks -> do
chunks @?= ["Paragraph 1", "Paragraph 2", "Paragraph 3"]
, testCase "loadAndSplit should return error for non-existent file" $ do
result <- loadAndSplit (FileLoader "non-existent-file.txt")
case result of
Left err ->
assertBool
"Error message should mention file not found"
(T.isInfixOf "File not found" (showText err))
Right _ -> assertFailure "Expected Left for non-existent file but got Right"
, testCase "load should handle empty files" $
withTestFile "" $ \filePath -> do
result <- load (FileLoader filePath)
case result of
Left err -> assertFailure $ "Expected Right but got Left: " ++ show err
Right docs@(doc : _) -> do
length docs @?= 1
pageContent doc @?= ""
Right _ -> assertFailure "Document list is empty"
, testCase "load should handle large files" $
withTestFile (concat $ replicate 1000 "Line of test content\n") $ \filePath -> do
result <- load (FileLoader filePath)
case result of
Left err -> assertFailure $ "Expected Right but got Left: " ++ show err
Right docs@(doc : _) -> do
length docs @?= 1
T.length (TL.toStrict $ pageContent doc) @?= 21000 -- 21 chars * 1000
Right _ -> assertFailure "Document list is empty"
]
tests :: TestTree
tests =
testGroup
"Langchain.DocumentLoader Tests"
[ documentTests
, fileLoaderTests
]