2015-05-26 2 views
3

Я пишу чат-сервер в Haskell. Мой исполняемый файл имеет следующий код:Не удается записать на ручку

data Client = Client {idx :: Int, hClient :: Handle} deriving (Show, Eq) 

tellClient :: String -> Client -> IO() 
tellClient = flip $ hPutStrLn . hClient 

askClient :: Client -> IO (String) 
askClient = hGetLine . hClient 

, который я ожидаю, что смогу использовать для записи и чтения из файла. Я пишу тесты против этого кода с помощью HSpec. У меня есть следующие функции для создания временных Client объектов (которая опирается на «временный») библиотеки:

withTempClient :: Int -> (Client -> IO a) -> IO a 
withTempClient cIdx f = withTempFile "tests/generated" "clientFile.tmp" axn 
    where axn _ handle = f $ Client cIdx handle 

Я использую это, чтобы проверить код, приведенный выше следующим образом:

main = hspec $ do 
    describe "client IO" $ do 
    it "can ask and tell" $ withTempClient 1 $ \c -> do 
     tellClient "hello" c 
     hFlush $ hClient c 
     askClient c `shouldReturn` "hello" 

Но тест не пройден со следующей ошибкой:

uncaught exception: IOException of type EOF (test/generated 
    /clientFile11587.tmp: hGetLine: end of file) 

я подумал, что, может быть, я делаю что-то неправильно в withTempClient, поэтому я добавил следующий тестовый пример:

it "opens a handle corectly" $ withTempClient 1 $ \(Client _ h) -> do 
    hIsOpen h `shouldReturn` True 
    hIsWritable h `shouldReturn` True 

но это прошло, поэтому я не уверен, в чем проблема. Что мне не хватает?

ответ

4

При записи в файл ОС отслеживает позицию, в которой вы находитесь в указанном файле. Вы получаете ошибку EOF, потому что вы в конце файла (с начала было пустым, и все, что вы написали, - до текущей позиции).

Чтобы исправить, что вам нужно использовать hSeek, чтобы изменить себя в начале файла, как так:

hSeek (hClient c) AbsoluteSeek 0 

Для получения более подробной информации о поиске, см этот бит real world haskell.

Смежные вопросы