Skip to content

Commit

Permalink
Merge pull request #72 from input-output-hk/jdral/71-fspath
Browse files Browse the repository at this point in the history
Only generate valid names for `FsPath` tests
  • Loading branch information
jorisdral authored Jun 6, 2024
2 parents 47879aa + c8998df commit 91d748d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
5 changes: 2 additions & 3 deletions fs-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@

### Patch

* Add a clarification in the documentation of `fsPathFromList` that each path
component should be non-empty, because directories/files with empty names are
not valid! Also, add an `assert`ion to `fsPathFromList` for this precondition.
* Add a clarification in the documentation of `FsPath` that the user is
responsible for picking sensible directory/file names.

## 0.2.0.1 -- 2023-10-30

Expand Down
22 changes: 21 additions & 1 deletion fs-api/src/System/FS/API/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,34 @@ allowExisting openMode = case openMode of
-------------------------------------------------------------------------------}

-- | A relative path.
--
-- === Invariant
--
-- The user of this library is tasked with picking sensible names of
-- directories/files on a path. Amongst others, the following should hold:
--
-- * Names are non-empty
--
-- * Names are monotonic, i.e., they are not equal to @..@
--
-- * Names should not contain path separators or drive letters
--
-- In particular, names that satisfy these invariants should result in an
-- 'FsPath' that remains relative to the HasFS instance root. For example, an
-- @'FsPath' ["/"]@ would try to access the root folder, which is most likely
-- outside of the scope of the HasFS instance.
--
-- \"@..@\" should not be used because @fs-sim@ will not be able to follow these
-- types of back-links. @fs-sim@ will interpret \"@..@\" as a directory name
-- instead.
newtype FsPath = UnsafeFsPath { fsPathToList :: [Strict.Text] }
deriving (Eq, Ord, Generic)
deriving newtype NFData

-- | Create a path from a list of directory/file names. All of the names should
-- be non-empty.
fsPathFromList :: [Strict.Text] -> FsPath
fsPathFromList xs = assert (not (any Strict.null xs)) $ UnsafeFsPath (force xs)
fsPathFromList xs = UnsafeFsPath (force xs)

instance Show FsPath where
show = intercalate "/" . map Strict.unpack . fsPathToList
Expand Down
14 changes: 11 additions & 3 deletions fs-api/test/Test/System/FS/API/FsPath.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ tests = testGroup "Test.System.FS.API.FsPath" [

-- | Orphan instance that generates a __non-empty__ text!
instance Arbitrary Text where
arbitrary = Text.pack <$> (arbitrary `suchThat` (not . null))
shrink x = [Text.pack x'' | let x' = Text.unpack x, x'' <- shrink x']
arbitrary = Text.pack <$> QC.listOf (QC.elements validChars) `suchThat` (not . null)
shrink x = [ x''' | let x' = Text.unpack x
, x'' <- shrink x'
, not (null x'')
, let x''' = Text.pack x'' ]

-- | We pick a small subset of characters to use in directory/file names, so
-- that we don't break the invariant of 'FsPath'.
validChars :: [Char]
validChars = concat [['a'..'z'], ['A'..'Z'], ['0'..'9']]

-- | Commutativity property for 'FS.</>' and 'FilePath.</>'.
--
Expand Down Expand Up @@ -65,7 +73,7 @@ prop_addExtensionCommutes mnt path ext =
.&&. FilePath.makeValid lhs === FilePath.makeValid rhs
where
mnt' = filePathFromList mnt
mnt'' = FS.MountPoint (filePathFromList mnt)
mnt'' = FS.MountPoint mnt'
fsp = FS.fsPathFromList path FS.<.> ext
lhs = FS.fsToFilePath mnt'' fsp
rhs = mnt' FilePath.</> filePathFromList path FilePath.<.> ext
Expand Down

0 comments on commit 91d748d

Please sign in to comment.