packages feed

knob 0.1 → 0.1.1

raw patch · 6 files changed

+439/−5 lines, 6 filesdep ~basedep ~bytestringdep ~transformersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, bytestring, transformers

API changes (from Hackage documentation)

Files

knob.cabal view
@@ -1,5 +1,5 @@ name: knob-version: 0.1+version: 0.1.1 license: MIT license-file: license.txt author: John Millikin <jmillikin@gmail.com>@@ -13,7 +13,7 @@  synopsis: Memory-backed handles description:-  Create memory-backed 'IO.Handle's, referencing virtual files. This is+  Create memory-backed 'Handle's, referencing virtual files. This is   mostly useful for testing 'Handle'-based APIs without having to   interact with the filesystem.   .@@ -29,6 +29,14 @@   >     bytes <- Data.Knob.getContents knob   >     putStrLn ("Wrote bytes: " ++ show bytes) +extra-source-files:+  scripts/common.bash+  scripts/run-coverage+  scripts/run-tests+  --+  tests/knob-tests.cabal+  tests/KnobTests.hs+ source-repository head   type: bazaar   location: https://john-millikin.com/software/knob/@@ -36,7 +44,7 @@ source-repository this   type: bazaar   location: https://john-millikin.com/branches/knob/0.1/-  tag: knob_0.1+  tag: knob_0.1.1  library   hs-source-dirs: lib@@ -44,8 +52,8 @@    build-depends:       base >= 4.2 && < 5.0-    , bytestring >= 0.9 && < 0.10-    , transformers >= 0.2 && < 0.3+    , bytestring >= 0.9+    , transformers >= 0.2    exposed-modules:     Data.Knob
+ scripts/common.bash view
@@ -0,0 +1,23 @@+PATH="$PATH:$PWD/cabal-dev/bin/"++VERSION=$(awk '/^version:/{print $2}' knob.cabal)++CABAL_DEV=$(which cabal-dev)+XZ=$(which xz)++require_cabal_dev()+{+	if [ -z "$CABAL_DEV" ]; then+		echo "Can't find 'cabal-dev' executable; make sure it exists on your "'$PATH'+		echo "Cowardly refusing to fuck with the global package database"+		exit 1+	fi+}++clean_dev_install()+{+	require_cabal_dev+	+	rm -rf dist+	$CABAL_DEV install || exit 1+}
+ scripts/run-coverage view
@@ -0,0 +1,23 @@+#!/bin/bash+if [ ! -f 'knob.cabal' ]; then+	echo -n "Can't find knob.cabal; please run this script as"+	echo -n " ./scripts/run-coverage from within the knob source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install --flags="coverage" || exit 1+popd++rm -f knob_tests.tix+cabal-dev/bin/knob_tests $@++EXCLUDES="--exclude=Main"++hpc markup --srcdir=src/ --srcdir=tests/ knob_tests.tix --destdir=hpc-markup $EXCLUDES > /dev/null+hpc report --srcdir=src/ --srcdir=tests/ knob_tests.tix $EXCLUDES
+ scripts/run-tests view
@@ -0,0 +1,20 @@+#!/bin/bash+if [ ! -f 'knob.cabal' ]; then+	echo -n "Can't find knob.cabal; please run this script as"+	echo -n " ./scripts/run-tests from within the knob source"+	echo " directory"+	exit 1+fi++. scripts/common.bash++require_cabal_dev++clean_dev_install++pushd tests+rm -rf dist+$CABAL_DEV -s ../cabal-dev install || exit 1+popd++cabal-dev/bin/knob_tests
+ tests/KnobTests.hs view
@@ -0,0 +1,338 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++-- Copyright (C) 2011 John Millikin <jmillikin@gmail.com>+--+-- See license.txt for details+module Main+	( tests+	, main+	) where++import           Control.Monad.IO.Class (liftIO)+import qualified Data.ByteString+import           Data.ByteString.Char8 ()+import           Data.ByteString.Unsafe (unsafePackCStringLen)+import           Foreign (nullPtr)+import qualified GHC.IO.Exception as GHC+import           System.IO+import           Test.Chell++import           Data.Knob++main :: IO ()+main = Test.Chell.defaultMain tests++tests :: [Suite]+tests = [test_File, test_Duplex]++test_File :: Suite+test_File = suite "file"+	[ suite "read"+		[ test_ReadFromStart+		, test_ReadFromOffset+		, test_ReadToEOF+		, test_ReadPastEOF+		]+	, suite "write"+		[ test_WriteFromStart+		, test_WriteFromOffset+		, test_WritePastEOF+		, test_WriteAppended+		]+	, suite "seek"+		[ test_SeekAbsolute+		, test_SeekRelative+		, test_SeekFromEnd+		, test_SeekBeyondMaxInt+		]+	, suite "setSize"+		[ test_SetSize_Read+		, test_SetSize_Write+		, test_SetSize_ReadWrite+		, test_SetSize_Append+		]+	+	, test_Ready+	, test_Close+	, test_SetContents+	, test_WithFileHandle+	]++test_ReadFromStart :: Suite+test_ReadFromStart = assertions "from-start" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	bytes <- liftIO $ Data.ByteString.hGet h 3+	$expect (equal bytes "abc")+	+	off <- liftIO $ hTell h+	$expect (equal off 3)++test_ReadFromOffset :: Suite+test_ReadFromOffset = assertions "from-offset" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	liftIO $ hSeek h AbsoluteSeek 1+	bytes <- liftIO $ Data.ByteString.hGet h 3+	$expect (equal bytes "bcd")+	+	off <- liftIO $ hTell h+	$expect (equal off 4)++test_ReadToEOF :: Suite+test_ReadToEOF = assertions "to-eof" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	bytes <- liftIO $ Data.ByteString.hGet h 10+	$expect (equal bytes "abcde")+	+	off <- liftIO $ hTell h+	$expect (equal off 5)++test_ReadPastEOF :: Suite+test_ReadPastEOF = assertions "past-eof" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	liftIO $ hSeek h AbsoluteSeek 10+	bytes <- liftIO $ Data.ByteString.hGet h 10+	$expect (equal bytes "")+	+	off <- liftIO $ hTell h+	$expect (equal off 10)++test_WriteFromStart :: Suite+test_WriteFromStart = assertions "from-start" $ do+	k <- newKnob ""+	h <- newFileHandle k "foo.txt" WriteMode+	liftIO $ hSetBuffering h NoBuffering+	+	liftIO $ Data.ByteString.hPut h "abcde"+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "abcde")++test_WriteFromOffset :: Suite+test_WriteFromOffset = assertions "from-offset" $ do+	k <- newKnob ""+	h <- newFileHandle k "foo.txt" WriteMode+	liftIO $ hSetBuffering h NoBuffering+	+	liftIO $ Data.ByteString.hPut h "abcde"+	liftIO $ hSeek h AbsoluteSeek 2+	liftIO $ Data.ByteString.hPut h "abcde"+	+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "ababcde")++test_WritePastEOF :: Suite+test_WritePastEOF = assertions "past-eof" $ do+	k <- newKnob ""+	h <- newFileHandle k "foo.txt" WriteMode+	liftIO $ hSetBuffering h NoBuffering+	+	liftIO $ hSeek h AbsoluteSeek 2+	liftIO $ Data.ByteString.hPut h "abcde"+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "\0\0abcde")++test_WriteAppended :: Suite+test_WriteAppended = assertions "appended" $ do+	k <- newKnob "foo"+	h <- newFileHandle k "foo.txt" AppendMode+	liftIO $ hSetBuffering h NoBuffering+	+	liftIO $ Data.ByteString.hPut h "bar"+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "foobar")++test_SeekAbsolute :: Suite+test_SeekAbsolute = assertions "absolute" $ do+	k <- newKnob ""+	h <- newFileHandle k "foo.txt" ReadMode+	+	before <- liftIO $ hTell h+	liftIO $ hSeek h AbsoluteSeek 2+	after <- liftIO $ hTell h+	+	$expect (equal before 0)+	$expect (equal after 2)++test_SeekRelative :: Suite+test_SeekRelative = assertions "relative" $ do+	k <- newKnob ""+	h <- newFileHandle k "foo.txt" ReadMode+	+	before <- liftIO $ hTell h+	liftIO $ hSeek h RelativeSeek 2+	after1 <- liftIO $ hTell h+	liftIO $ hSeek h RelativeSeek 2+	after2 <- liftIO $ hTell h+	+	$expect (equal before 0)+	$expect (equal after1 2)+	$expect (equal after2 4)++test_SeekFromEnd :: Suite+test_SeekFromEnd = assertions "from-end" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	before <- liftIO $ hTell h+	liftIO $ hSeek h SeekFromEnd (- 2)+	after <- liftIO $ hTell h+	+	$expect (equal before 0)+	$expect (equal after 3)++test_SeekBeyondMaxInt :: Suite+test_SeekBeyondMaxInt = assertions "beyond-max-int" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	let intPlusOne = toInteger (maxBound :: Int) + 1+	+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSeek" "offset > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSeek h AbsoluteSeek intPlusOne)+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSeek" "offset > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSeek h RelativeSeek intPlusOne)+	+	-- testing this with real contents is difficult/impossible on a+	-- 64-bit system, so use an unsafe function to corrupt the knob's+	-- internal buffer first.+	hugeBytes <- liftIO (unsafePackCStringLen (nullPtr, maxBound))+	liftIO $ hSeek h AbsoluteSeek (intPlusOne - 1)+	setContents k hugeBytes+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSeek" "offset > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSeek h SeekFromEnd 2)++test_Ready :: Suite+test_Ready = assertions "ready" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	ready <- liftIO $ hReady h+	$expect ready+	+	_ <- liftIO $ Data.ByteString.hGet h 10+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.EOF "hWaitForInput" "" Nothing (Just "foo.txt"))+		(hReady h)++test_Close :: Suite+test_Close = assertions "close" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	liftIO $ hClose h+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.IllegalOperation "hGetBuf" "handle is closed" Nothing (Just "foo.txt"))+		(Data.ByteString.hGet h 1)+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.IllegalOperation "hWaitForInput" "handle is closed" Nothing (Just "foo.txt"))+		(hReady h)++test_SetSize_Read :: Suite+test_SetSize_Read = assertions "ReadMode" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadMode+	+	let intPlusOne = toInteger (maxBound :: Int) + 1+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSetFileSize" "size > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSetFileSize h intPlusOne)+	+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.IllegalOperation "hSetFileSize" "handle in ReadMode" Nothing (Just "foo.txt"))+		(hSetFileSize h 2)++test_SetSize_Write :: Suite+test_SetSize_Write = assertions "WriteMode" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" WriteMode+	+	let intPlusOne = toInteger (maxBound :: Int) + 1+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSetFileSize" "size > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSetFileSize h intPlusOne)+	+	-- Resets contents to all NULL, regardless of offset+	liftIO $ hSeek h AbsoluteSeek 2+	liftIO $ hSetFileSize h 4+	+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "\0\0\0\0")++test_SetSize_ReadWrite :: Suite+test_SetSize_ReadWrite = assertions "ReadWriteMode" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" ReadWriteMode+	+	let intPlusOne = toInteger (maxBound :: Int) + 1+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSetFileSize" "size > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSetFileSize h intPlusOne)+	+	-- Truncates contents, regardless of offset+	do+		liftIO $ hSeek h AbsoluteSeek 2+		liftIO $ hSetFileSize h 4+		bytes <- Data.Knob.getContents k+		$expect (equal bytes "abcd")+	+	do+		liftIO $ hSetFileSize h 6+		bytes <- Data.Knob.getContents k+		$expect (equal bytes "abcd\0\0")++test_SetSize_Append :: Suite+test_SetSize_Append = assertions "AppendMode" $ do+	k <- newKnob "abcde"+	h <- newFileHandle k "foo.txt" AppendMode+	+	let intPlusOne = toInteger (maxBound :: Int) + 1+	$expect $ throwsEq+		(GHC.IOError (Just h) GHC.InvalidArgument "hSetFileSize" "size > (maxBound :: Int)" Nothing (Just "foo.txt"))+		(hSetFileSize h intPlusOne)+	+	do+		liftIO $ hSetFileSize h 4+		bytes <- Data.Knob.getContents k+		$expect (equal bytes "abcd")+	+	do+		liftIO $ hSetFileSize h 6+		bytes <- Data.Knob.getContents k+		$expect (equal bytes "abcd\0\0")++test_SetContents :: Suite+test_SetContents = assertions "setContents" $ do+	k <- newKnob "abcde"+	before <- Data.Knob.getContents k+	setContents k "foo"+	after <- Data.Knob.getContents k+	+	$expect (equal before "abcde")+	$expect (equal after "foo")++test_WithFileHandle :: Suite+test_WithFileHandle = assertions "withFileHandle" $ do+	k <- newKnob ""+	h <- withFileHandle k "test.txt" WriteMode $ \h -> do+		Data.ByteString.hPut h "abcde"+		return h+	+	bytes <- Data.Knob.getContents k+	$expect (equal bytes "abcde")+	+	closed <- liftIO $ hIsClosed h+	$expect closed++test_Duplex :: Suite+test_Duplex = suite "duplex" []
+ tests/knob-tests.cabal view
@@ -0,0 +1,22 @@+name: knob-tests+version: 0+build-type: Simple+cabal-version: >= 1.6++flag coverage+  default: False+  manual: True++executable knob_tests+  main-is: KnobTests.hs+  ghc-options: -Wall+  hs-source-dirs: ../lib,.++  if flag(coverage)+    ghc-options: -fhpc++  build-depends:+      base >= 4.2 && < 5.0+    , bytestring >= 0.9 && < 0.10+    , chell >= 0.2 && < 0.3+    , transformers >= 0.2 && < 0.3