Safe Haskell | None |
---|---|

Language | Haskell2010 |

`HasFS`

instance wrapping `SimFS`

that generates errors, suitable for
testing error handling.

## Synopsis

- mkSimErrorHasFS ∷ ∀ m. (MonadSTM m, MonadThrow m) ⇒ StrictTVar m MockFS → StrictTVar m Errors → HasFS m HandleMock
- runSimErrorFS ∷ (MonadSTM m, MonadThrow m) ⇒ MockFS → Errors → (StrictTVar m Errors → HasFS m HandleMock → m a) → m (a, MockFS)
- withErrors ∷ MonadSTM m ⇒ StrictTVar m Errors → Errors → m a → m a
- type ErrorStream = Stream FsErrorType
- type ErrorStreamGetSome = Stream (Either FsErrorType Partial)
- type ErrorStreamPutSome = Stream (Either (FsErrorType, Maybe PutCorruption) Partial)
- newtype Stream a = Stream {}
- always ∷ a → Stream a
- mkStream ∷ [Maybe a] → Stream a
- mkStreamGen ∷ Int → Gen a → Gen (Stream a)
- null ∷ Stream a → Bool
- runStream ∷ Stream a → (Maybe a, Stream a)
- newtype Partial = Partial Word64
- hGetSomePartial ∷ Partial → Word64 → Word64
- hPutSomePartial ∷ Partial → ByteString → ByteString
- data PutCorruption
- corrupt ∷ ByteString → PutCorruption → ByteString
- data Errors = Errors {
- dumpStateE ∷ ErrorStream
- hOpenE ∷ ErrorStream
- hCloseE ∷ ErrorStream
- hSeekE ∷ ErrorStream
- hGetSomeE ∷ ErrorStreamGetSome
- hGetSomeAtE ∷ ErrorStreamGetSome
- hPutSomeE ∷ ErrorStreamPutSome
- hTruncateE ∷ ErrorStream
- hGetSizeE ∷ ErrorStream
- createDirectoryE ∷ ErrorStream
- createDirectoryIfMissingE ∷ ErrorStream
- listDirectoryE ∷ ErrorStream
- doesDirectoryExistE ∷ ErrorStream
- doesFileExistE ∷ ErrorStream
- removeFileE ∷ ErrorStream
- renameFileE ∷ ErrorStream

- allNull ∷ Errors → Bool
- genErrors ∷ Bool → Bool → Gen Errors
- simpleErrors ∷ ErrorStream → Errors

# Simulate Errors monad

mkSimErrorHasFS ∷ ∀ m. (MonadSTM m, MonadThrow m) ⇒ StrictTVar m MockFS → StrictTVar m Errors → HasFS m HandleMock Source #

Introduce possibility of errors

TODO: Lenses would be nice for the setters

runSimErrorFS ∷ (MonadSTM m, MonadThrow m) ⇒ MockFS → Errors → (StrictTVar m Errors → HasFS m HandleMock → m a) → m (a, MockFS) Source #

withErrors ∷ MonadSTM m ⇒ StrictTVar m Errors → Errors → m a → m a Source #

# Streams

type ErrorStream = Stream FsErrorType Source #

An `ErrorStream`

is a possibly infinite `Stream`

of (`Maybe`

)

s.`FsErrorType`

`Nothing`

indicates that there is no error.

Each time the `ErrorStream`

is used (see `runErrorStream`

), the first
element (`Nothing`

in case the list is empty) is taken from the list and an
`ErrorStream`

with the remainder of the list is returned. The first element
represents whether an error should be returned or not.

An `FsError`

consists of a number of fields: `fsErrorType`

, a
`fsErrorPath`

, etc. Only the first fields is interesting. Therefore, we
only generate the `FsErrorType`

. The `FsErrorType`

will be used to
construct the actual `FsError`

.

type ErrorStreamGetSome = Stream (Either FsErrorType Partial) Source #

`ErrorStream`

for `hGetSome`

: an error or a partial get.

type ErrorStreamPutSome = Stream (Either (FsErrorType, Maybe PutCorruption) Partial) Source #

`ErrorStream`

for `hPutSome`

: an error and possibly some corruption, or a
partial write.

mkStreamGen ∷ Int → Gen a → Gen (Stream a) Source #

Make a `Stream`

generator based on a `a`

generator.

The generator generates a finite stream of 10 elements, where each element
has a chance of being either `Nothing`

or an element generated with the
given `a`

generator (wrapped in a `Just`

).

The first argument is the likelihood (as used by `frequency`

) of a
`Just`

where `Nothing`

has likelihood 2.

# Generating partial reads/writes

Given a

where `Partial`

p`p > 0`

, we do the following to make a call
to `hGetSome`

or `hPutSome`

partial:

`hGetSome`

: we subtract`p`

from the number of requested bytes. If that would result in 0 requested bytes or less, we request 1 byte. If the number of requested bytes was already 0, leave it untouched, as we can't simulate a partial read in this case.`hPutSome`

: we drop the last`p`

bytes from the bytestring. If that would result in an empty bytestring, just take the first byte of the bytestring. If the bytestring was already empty, leave it untouched, as we can't simulate a partial write in this case.

# Generating corruption for `hPutSome`

data PutCorruption Source #

Model possible corruptions that could happen to a `hPutSome`

call.

SubstituteWithJunk Blob | The blob to write is substituted with corrupt junk |

PartialWrite Partial | Only perform the write partially |

#### Instances

Show PutCorruption Source # | |

Defined in Test.Util.FS.Sim.Error | |

Arbitrary PutCorruption Source # | |

Defined in Test.Util.FS.Sim.Error arbitrary ∷ Gen PutCorruption shrink ∷ PutCorruption → [PutCorruption] |

corrupt ∷ ByteString → PutCorruption → ByteString Source #

Apply the `PutCorruption`

to the `ByteString`

.

# Error streams for `HasFS`

Error streams for the methods of the `HasFS`

type class.

An `ErrorStream`

is provided for each method of the `HasFS`

type class.
This `ErrorStream`

will be used to generate potential errors that will be
thrown by the corresponding method.

For `hPutSome`

, an `ErrorStreamWithCorruption`

is provided to simulate
corruption.

An `Errors`

is used in conjunction with `SimErrorFS`

, which is a layer on
top of `SimFS`

that simulates methods throwing `FsError`

s.

simpleErrors ∷ ErrorStream → Errors Source #

Use the given `ErrorStream`

for each field/method. No corruption of
`hPutSome`

.