2021-02-24 10:56:04 +03:00
|
|
|
# tests for built-in IO functions
|
2020-11-13 23:25:21 +03:00
|
|
|
|
|
|
|
Tests for IO builtins which wired to foreign haskell calls.
|
|
|
|
|
|
|
|
## Setup
|
|
|
|
|
|
|
|
You can skip the section which is just needed to make the transcript self-contained.
|
|
|
|
|
|
|
|
TempDirs/autoCleaned is an ability/hanlder which allows you to easily
|
|
|
|
create a scratch directory which will automatically get cleaned up.
|
|
|
|
|
|
|
|
## Basic File Functions
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2020-12-02 22:03:21 +03:00
|
|
|
### Creating/Deleting/Renaming Directories
|
|
|
|
|
2024-07-10 19:27:02 +03:00
|
|
|
Tests:
|
|
|
|
|
|
|
|
- createDirectory,
|
|
|
|
- isDirectory,
|
|
|
|
- fileExists,
|
|
|
|
- renameDirectory,
|
|
|
|
- deleteDirectory
|
2020-12-02 22:03:21 +03:00
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2020-12-02 00:05:29 +03:00
|
|
|
testCreateRename : '{io2.IO} [Result]
|
|
|
|
testCreateRename _ =
|
|
|
|
test = 'let
|
2021-02-24 10:56:04 +03:00
|
|
|
tempDir = newTempDir "fileio"
|
2020-12-02 00:05:29 +03:00
|
|
|
fooDir = tempDir ++ "/foo"
|
|
|
|
barDir = tempDir ++ "/bar"
|
2022-12-02 08:51:11 +03:00
|
|
|
void x = ()
|
|
|
|
void (createDirectory.impl fooDir)
|
2021-02-24 10:56:04 +03:00
|
|
|
check "create a foo directory" (isDirectory fooDir)
|
|
|
|
check "directory should exist" (fileExists fooDir)
|
|
|
|
renameDirectory fooDir barDir
|
|
|
|
check "foo should no longer exist" (not (fileExists fooDir))
|
|
|
|
check "directory should no longer exist" (not (fileExists fooDir))
|
|
|
|
check "bar should now exist" (fileExists barDir)
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2020-12-02 22:03:21 +03:00
|
|
|
bazDir = barDir ++ "/baz"
|
2022-12-02 08:51:11 +03:00
|
|
|
void (createDirectory.impl bazDir)
|
|
|
|
void (removeDirectory.impl barDir)
|
2020-12-02 22:03:21 +03:00
|
|
|
|
2021-02-24 10:56:04 +03:00
|
|
|
check "removeDirectory works recursively" (not (isDirectory barDir))
|
|
|
|
check "removeDirectory works recursively" (not (isDirectory bazDir))
|
2020-12-02 22:03:21 +03:00
|
|
|
|
2020-12-02 00:05:29 +03:00
|
|
|
runTest test
|
2020-12-02 22:03:21 +03:00
|
|
|
```
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2023-12-22 14:55:24 +03:00
|
|
|
Loading changes detected in scratch.u.
|
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
I found and typechecked these definitions in scratch.u. If you
|
|
|
|
do an `add` or `update`, here's how your codebase would
|
|
|
|
change:
|
|
|
|
|
|
|
|
⍟ These new definitions are ok to `add`:
|
|
|
|
|
|
|
|
testCreateRename : '{IO} [Result]
|
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testCreateRename : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testCreateRename
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testCreateRename ◉ create a foo directory
|
|
|
|
◉ directory should exist
|
|
|
|
◉ foo should no longer exist
|
|
|
|
◉ directory should no longer exist
|
|
|
|
◉ bar should now exist
|
|
|
|
◉ removeDirectory works recursively
|
|
|
|
◉ removeDirectory works recursively
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
✅ 7 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
```
|
2020-12-02 22:03:21 +03:00
|
|
|
### Opening / Closing files
|
|
|
|
|
2024-07-10 19:27:02 +03:00
|
|
|
Tests:
|
|
|
|
|
|
|
|
- openFile
|
|
|
|
- closeFile
|
|
|
|
- isFileOpen
|
2020-12-02 22:03:21 +03:00
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2020-12-02 00:05:29 +03:00
|
|
|
testOpenClose : '{io2.IO} [Result]
|
|
|
|
testOpenClose _ =
|
|
|
|
test = 'let
|
2021-02-24 10:56:04 +03:00
|
|
|
tempDir = (newTempDir "seek")
|
2020-12-02 00:05:29 +03:00
|
|
|
fooFile = tempDir ++ "/foo"
|
2021-02-24 10:56:04 +03:00
|
|
|
handle1 = openFile fooFile FileMode.Write
|
|
|
|
check "file should be open" (isFileOpen handle1)
|
2021-05-06 23:21:00 +03:00
|
|
|
setBuffering handle1 (SizedBlockBuffering 1024)
|
2022-01-06 19:22:43 +03:00
|
|
|
check "file handle buffering should match what we just set." (getBuffering handle1 == SizedBlockBuffering 1024)
|
2021-05-06 23:21:00 +03:00
|
|
|
setBuffering handle1 (getBuffering handle1)
|
|
|
|
putBytes handle1 0xs01
|
|
|
|
setBuffering handle1 NoBuffering
|
|
|
|
setBuffering handle1 (getBuffering handle1)
|
|
|
|
putBytes handle1 0xs23
|
|
|
|
setBuffering handle1 BlockBuffering
|
|
|
|
setBuffering handle1 (getBuffering handle1)
|
|
|
|
putBytes handle1 0xs45
|
|
|
|
setBuffering handle1 LineBuffering
|
|
|
|
setBuffering handle1 (getBuffering handle1)
|
|
|
|
putBytes handle1 0xs67
|
2021-02-24 10:56:04 +03:00
|
|
|
closeFile handle1
|
|
|
|
check "file should be closed" (not (isFileOpen handle1))
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-05-06 23:21:00 +03:00
|
|
|
-- make sure the bytes have been written
|
|
|
|
handle2 = openFile fooFile FileMode.Read
|
|
|
|
check "bytes have been written" (getBytes handle2 4 == 0xs01234567)
|
|
|
|
closeFile handle2
|
|
|
|
|
|
|
|
-- checking that ReadWrite mode works fine
|
|
|
|
handle3 = openFile fooFile FileMode.ReadWrite
|
|
|
|
check "bytes have been written" (getBytes handle3 4 == 0xs01234567)
|
|
|
|
closeFile handle3
|
|
|
|
|
|
|
|
check "file should be closed" (not (isFileOpen handle1))
|
|
|
|
|
2020-12-02 00:05:29 +03:00
|
|
|
runTest test
|
2020-12-02 22:03:21 +03:00
|
|
|
```
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2023-12-22 14:55:24 +03:00
|
|
|
Loading changes detected in scratch.u.
|
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
I found and typechecked these definitions in scratch.u. If you
|
|
|
|
do an `add` or `update`, here's how your codebase would
|
|
|
|
change:
|
|
|
|
|
|
|
|
⍟ These new definitions are ok to `add`:
|
|
|
|
|
|
|
|
testOpenClose : '{IO} [Result]
|
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testOpenClose : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testOpenClose
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testOpenClose ◉ file should be open
|
|
|
|
◉ file handle buffering should match what we just set.
|
|
|
|
◉ file should be closed
|
|
|
|
◉ bytes have been written
|
|
|
|
◉ bytes have been written
|
|
|
|
◉ file should be closed
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2022-01-06 19:22:43 +03:00
|
|
|
✅ 6 test(s) passing
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2022-04-05 01:56:08 +03:00
|
|
|
```
|
|
|
|
### Reading files with getSomeBytes
|
|
|
|
|
2024-07-10 19:27:02 +03:00
|
|
|
Tests:
|
|
|
|
|
|
|
|
- getSomeBytes
|
|
|
|
- putBytes
|
|
|
|
- isFileOpen
|
|
|
|
- seekHandle
|
2022-04-05 01:56:08 +03:00
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2022-04-05 01:56:08 +03:00
|
|
|
testGetSomeBytes : '{io2.IO} [Result]
|
|
|
|
testGetSomeBytes _ =
|
|
|
|
test = 'let
|
|
|
|
tempDir = (newTempDir "getSomeBytes")
|
|
|
|
fooFile = tempDir ++ "/foo"
|
|
|
|
|
|
|
|
testData = "0123456789"
|
|
|
|
testSize = size testData
|
|
|
|
|
|
|
|
chunkSize = 7
|
|
|
|
check "chunk size splits data into 2 uneven sides" ((chunkSize > (testSize / 2)) && (chunkSize < testSize))
|
|
|
|
|
|
|
|
|
|
|
|
-- write testData to a temporary file
|
|
|
|
fooWrite = openFile fooFile Write
|
|
|
|
putBytes fooWrite (toUtf8 testData)
|
|
|
|
closeFile fooWrite
|
|
|
|
check "file should be closed" (not (isFileOpen fooWrite))
|
|
|
|
|
|
|
|
-- reopen for reading back the data in chunks
|
|
|
|
fooRead = openFile fooFile Read
|
|
|
|
|
|
|
|
-- read first part of file
|
|
|
|
chunk1 = getSomeBytes fooRead chunkSize |> fromUtf8
|
|
|
|
check "first chunk matches first part of testData" (chunk1 == take chunkSize testData)
|
|
|
|
|
|
|
|
-- read rest of file
|
|
|
|
chunk2 = getSomeBytes fooRead chunkSize |> fromUtf8
|
|
|
|
check "second chunk matches rest of testData" (chunk2 == drop chunkSize testData)
|
|
|
|
|
|
|
|
check "should be at end of file" (isFileEOF fooRead)
|
|
|
|
|
|
|
|
readAtEOF = getSomeBytes fooRead chunkSize
|
|
|
|
check "reading at end of file results in Bytes.empty" (readAtEOF == Bytes.empty)
|
|
|
|
|
|
|
|
-- request many bytes from the start of the file
|
|
|
|
seekHandle fooRead AbsoluteSeek +0
|
|
|
|
bigRead = getSomeBytes fooRead (testSize * 999) |> fromUtf8
|
|
|
|
check "requesting many bytes results in what's available" (bigRead == testData)
|
|
|
|
|
|
|
|
closeFile fooRead
|
|
|
|
check "file should be closed" (not (isFileOpen fooRead))
|
|
|
|
|
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2022-04-05 01:56:08 +03:00
|
|
|
|
2023-12-22 14:55:24 +03:00
|
|
|
Loading changes detected in scratch.u.
|
|
|
|
|
2022-04-05 01:56:08 +03:00
|
|
|
I found and typechecked these definitions in scratch.u. If you
|
|
|
|
do an `add` or `update`, here's how your codebase would
|
|
|
|
change:
|
|
|
|
|
|
|
|
⍟ These new definitions are ok to `add`:
|
|
|
|
|
|
|
|
testGetSomeBytes : '{IO} [Result]
|
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2022-04-05 01:56:08 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testGetSomeBytes : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testGetSomeBytes
|
2022-04-05 01:56:08 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testGetSomeBytes ◉ chunk size splits data into 2 uneven sides
|
|
|
|
◉ file should be closed
|
|
|
|
◉ first chunk matches first part of testData
|
|
|
|
◉ second chunk matches rest of testData
|
|
|
|
◉ should be at end of file
|
|
|
|
◉ reading at end of file results in Bytes.empty
|
|
|
|
◉ requesting many bytes results in what's available
|
|
|
|
◉ file should be closed
|
2022-04-05 01:56:08 +03:00
|
|
|
|
|
|
|
✅ 8 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2022-04-05 01:56:08 +03:00
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
```
|
2020-12-02 22:03:21 +03:00
|
|
|
### Seeking in open files
|
|
|
|
|
2024-07-10 19:27:02 +03:00
|
|
|
Tests:
|
|
|
|
|
|
|
|
- openFile
|
|
|
|
- putBytes
|
|
|
|
- closeFile
|
|
|
|
- isSeekable
|
|
|
|
- isFileEOF
|
|
|
|
- seekHandle
|
|
|
|
- getBytes
|
|
|
|
- getLine
|
2024-07-10 17:46:18 +03:00
|
|
|
|
|
|
|
``` unison
|
2020-12-02 00:05:29 +03:00
|
|
|
testSeek : '{io2.IO} [Result]
|
|
|
|
testSeek _ =
|
|
|
|
test = 'let
|
2021-02-24 10:56:04 +03:00
|
|
|
tempDir = newTempDir "seek"
|
2021-01-29 00:57:03 +03:00
|
|
|
emit (Ok "seeked")
|
2020-12-02 00:05:29 +03:00
|
|
|
fooFile = tempDir ++ "/foo"
|
2021-02-24 10:56:04 +03:00
|
|
|
handle1 = openFile fooFile FileMode.Append
|
2020-12-02 00:05:29 +03:00
|
|
|
putBytes handle1 (toUtf8 "12345678")
|
|
|
|
closeFile handle1
|
|
|
|
|
2021-02-24 10:56:04 +03:00
|
|
|
handle3 = openFile fooFile FileMode.Read
|
|
|
|
check "readable file should be seekable" (isSeekable handle3)
|
|
|
|
check "shouldn't be the EOF" (not (isFileEOF handle3))
|
|
|
|
expectU "we should be at position 0" 0 (handlePosition handle3)
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-02-24 10:56:04 +03:00
|
|
|
seekHandle handle3 AbsoluteSeek +1
|
|
|
|
expectU "we should be at position 1" 1 (handlePosition handle3)
|
|
|
|
bytes3a = getBytes handle3 1000
|
|
|
|
text3a = Text.fromUtf8 bytes3a
|
2020-12-02 00:05:29 +03:00
|
|
|
expectU "should be able to read our temporary file after seeking" "2345678" text3a
|
|
|
|
closeFile handle3
|
|
|
|
|
2021-07-23 21:43:39 +03:00
|
|
|
barFile = tempDir ++ "/bar"
|
|
|
|
handle4 = openFile barFile FileMode.Append
|
|
|
|
putBytes handle4 (toUtf8 "foobar\n")
|
|
|
|
closeFile handle4
|
|
|
|
|
|
|
|
handle5 = openFile barFile FileMode.Read
|
|
|
|
expectU "getLine should get a line" "foobar" (getLine handle5)
|
|
|
|
closeFile handle5
|
|
|
|
|
2020-12-02 00:05:29 +03:00
|
|
|
runTest test
|
|
|
|
|
|
|
|
testAppend : '{io2.IO} [Result]
|
|
|
|
testAppend _ =
|
|
|
|
test = 'let
|
2021-02-24 10:56:04 +03:00
|
|
|
tempDir = newTempDir "openFile"
|
2020-12-02 00:05:29 +03:00
|
|
|
fooFile = tempDir ++ "/foo"
|
2021-02-24 10:56:04 +03:00
|
|
|
handle1 = openFile fooFile FileMode.Write
|
|
|
|
putBytes handle1 (toUtf8 "test1")
|
|
|
|
closeFile handle1
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-02-24 10:56:04 +03:00
|
|
|
handle2 = openFile fooFile FileMode.Append
|
|
|
|
putBytes handle2 (toUtf8 "test2")
|
|
|
|
closeFile handle2
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-02-24 10:56:04 +03:00
|
|
|
handle3 = openFile fooFile FileMode.Read
|
|
|
|
bytes3 = getBytes handle3 1000
|
|
|
|
text3 = Text.fromUtf8 bytes3
|
2021-01-29 00:57:03 +03:00
|
|
|
|
2020-12-02 00:05:29 +03:00
|
|
|
expectU "should be able to read our temporary file" "test1test2" text3
|
|
|
|
|
|
|
|
closeFile handle3
|
|
|
|
|
|
|
|
runTest test
|
2020-12-02 22:03:21 +03:00
|
|
|
```
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2023-12-22 14:55:24 +03:00
|
|
|
Loading changes detected in scratch.u.
|
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
I found and typechecked these definitions in scratch.u. If you
|
|
|
|
do an `add` or `update`, here's how your codebase would
|
|
|
|
change:
|
|
|
|
|
|
|
|
⍟ These new definitions are ok to `add`:
|
|
|
|
|
|
|
|
testAppend : '{IO} [Result]
|
|
|
|
testSeek : '{IO} [Result]
|
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testAppend : '{IO} [Result]
|
|
|
|
testSeek : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testSeek
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testSeek ◉ seeked
|
|
|
|
◉ readable file should be seekable
|
|
|
|
◉ shouldn't be the EOF
|
|
|
|
◉ we should be at position 0
|
|
|
|
◉ we should be at position 1
|
|
|
|
◉ should be able to read our temporary file after seeking
|
|
|
|
◉ getLine should get a line
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2021-07-23 21:43:39 +03:00
|
|
|
✅ 7 test(s) passing
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testAppend
|
2020-12-02 00:05:29 +03:00
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testAppend ◉ should be able to read our temporary file
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
✅ 1 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
```
|
2020-12-02 22:03:21 +03:00
|
|
|
### SystemTime
|
2024-07-10 17:46:18 +03:00
|
|
|
|
|
|
|
``` unison
|
2020-12-02 00:05:29 +03:00
|
|
|
testSystemTime : '{io2.IO} [Result]
|
|
|
|
testSystemTime _ =
|
|
|
|
test = 'let
|
2021-02-24 10:56:04 +03:00
|
|
|
t = !systemTime
|
2021-01-14 01:20:57 +03:00
|
|
|
check "systemTime should be sane" ((t > 1600000000) && (t < 2000000000))
|
2020-12-02 00:05:29 +03:00
|
|
|
|
|
|
|
runTest test
|
|
|
|
```
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2023-12-22 14:55:24 +03:00
|
|
|
Loading changes detected in scratch.u.
|
|
|
|
|
2021-05-05 20:57:38 +03:00
|
|
|
I found and typechecked these definitions in scratch.u. If you
|
|
|
|
do an `add` or `update`, here's how your codebase would
|
|
|
|
change:
|
|
|
|
|
|
|
|
⍟ These new definitions are ok to `add`:
|
|
|
|
|
|
|
|
testSystemTime : '{IO} [Result]
|
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testSystemTime : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testSystemTime
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testSystemTime ◉ systemTime should be sane
|
2021-05-05 20:57:38 +03:00
|
|
|
|
|
|
|
✅ 1 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-05 20:57:38 +03:00
|
|
|
|
2021-10-23 01:12:10 +03:00
|
|
|
```
|
|
|
|
### Get temp directory
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2021-10-23 01:12:10 +03:00
|
|
|
testGetTempDirectory : '{io2.IO} [Result]
|
|
|
|
testGetTempDirectory _ =
|
|
|
|
test = 'let
|
|
|
|
tempDir = reraise !getTempDirectory.impl
|
|
|
|
check "Temp directory is directory" (isDirectory tempDir)
|
|
|
|
check "Temp directory should exist" (fileExists tempDir)
|
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testGetTempDirectory : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testGetTempDirectory
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testGetTempDirectory ◉ Temp directory is directory
|
|
|
|
◉ Temp directory should exist
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
✅ 2 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
```
|
|
|
|
### Get current directory
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2021-10-23 01:12:10 +03:00
|
|
|
testGetCurrentDirectory : '{io2.IO} [Result]
|
|
|
|
testGetCurrentDirectory _ =
|
|
|
|
test = 'let
|
|
|
|
currentDir = reraise !getCurrentDirectory.impl
|
|
|
|
check "Current directory is directory" (isDirectory currentDir)
|
|
|
|
check "Current directory should exist" (fileExists currentDir)
|
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testGetCurrentDirectory : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testGetCurrentDirectory
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testGetCurrentDirectory ◉ Current directory is directory
|
|
|
|
◉ Current directory should exist
|
2021-10-23 01:12:10 +03:00
|
|
|
|
|
|
|
✅ 2 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-10-23 01:12:10 +03:00
|
|
|
|
2020-12-02 00:05:29 +03:00
|
|
|
```
|
2021-05-22 03:30:22 +03:00
|
|
|
### Get directory contents
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2021-05-22 03:30:22 +03:00
|
|
|
testDirContents : '{io2.IO} [Result]
|
2021-05-26 19:47:51 +03:00
|
|
|
testDirContents _ =
|
2021-05-22 03:30:22 +03:00
|
|
|
test = 'let
|
|
|
|
tempDir = newTempDir "dircontents"
|
|
|
|
c = reraise (directoryContents.impl tempDir)
|
|
|
|
check "directory size should be" (size c == 2)
|
2021-06-11 19:04:06 +03:00
|
|
|
check "directory contents should have current directory and parent" let
|
|
|
|
(c == [".", ".."]) || (c == ["..", "."])
|
2021-05-22 03:30:22 +03:00
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-05-22 03:30:22 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testDirContents : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testDirContents
|
2021-05-22 03:30:22 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testDirContents ◉ directory size should be
|
|
|
|
◉ directory contents should have current directory and parent
|
2021-05-22 03:30:22 +03:00
|
|
|
|
2021-05-26 19:47:51 +03:00
|
|
|
✅ 2 test(s) passing
|
2021-05-22 03:30:22 +03:00
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-05-22 03:30:22 +03:00
|
|
|
|
|
|
|
```
|
2021-07-20 23:56:09 +03:00
|
|
|
### Read environment variables
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2022-02-23 22:43:17 +03:00
|
|
|
testGetEnv : '{io2.IO} [Result]
|
|
|
|
testGetEnv _ =
|
2021-07-20 23:56:09 +03:00
|
|
|
test = 'let
|
2022-02-23 22:43:17 +03:00
|
|
|
path = reraise (getEnv.impl "PATH") -- PATH exists on windows, mac and linux.
|
|
|
|
check "PATH environent variable should be set" (size path > 0)
|
2024-04-29 04:30:02 +03:00
|
|
|
match getEnv.impl "DOESNTEXIST" with
|
2021-07-20 23:56:09 +03:00
|
|
|
Right _ -> emit (Fail "env var shouldn't exist")
|
|
|
|
Left _ -> emit (Ok "DOESNTEXIST didn't exist")
|
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-07-20 23:56:09 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
2022-02-23 22:43:17 +03:00
|
|
|
testGetEnv : '{IO} [Result]
|
2021-07-20 23:56:09 +03:00
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testGetEnv
|
2021-07-20 23:56:09 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testGetEnv ◉ PATH environent variable should be set
|
|
|
|
◉ DOESNTEXIST didn't exist
|
2021-07-20 23:56:09 +03:00
|
|
|
|
|
|
|
✅ 2 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2021-07-20 23:56:09 +03:00
|
|
|
|
|
|
|
```
|
2021-10-23 10:00:46 +03:00
|
|
|
### Read command line args
|
|
|
|
|
2024-04-29 04:30:02 +03:00
|
|
|
`runMeWithNoArgs`, `runMeWithOneArg`, and `runMeWithTwoArgs` raise exceptions
|
2021-10-24 04:21:15 +03:00
|
|
|
unless they called with the right number of arguments.
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2021-10-23 10:00:46 +03:00
|
|
|
testGetArgs.fail : Text -> Failure
|
|
|
|
testGetArgs.fail descr = Failure (typeLink IOFailure) descr !Any
|
|
|
|
|
|
|
|
testGetArgs.runMeWithNoArgs : '{io2.IO, Exception} ()
|
|
|
|
testGetArgs.runMeWithNoArgs = 'let
|
|
|
|
args = reraise !getArgs.impl
|
|
|
|
match args with
|
|
|
|
[] -> printLine "called with no args"
|
2024-08-26 20:37:19 +03:00
|
|
|
_ -> raise (testGetArgs.fail "called with args")
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
testGetArgs.runMeWithOneArg : '{io2.IO, Exception} ()
|
|
|
|
testGetArgs.runMeWithOneArg = 'let
|
|
|
|
args = reraise !getArgs.impl
|
|
|
|
match args with
|
2024-08-26 20:37:19 +03:00
|
|
|
[] -> raise (testGetArgs.fail "called with no args")
|
2021-10-23 10:00:46 +03:00
|
|
|
[_] -> printLine "called with one arg"
|
2024-08-26 20:37:19 +03:00
|
|
|
_ -> raise (testGetArgs.fail "called with too many args")
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
testGetArgs.runMeWithTwoArgs : '{io2.IO, Exception} ()
|
|
|
|
testGetArgs.runMeWithTwoArgs = 'let
|
|
|
|
args = reraise !getArgs.impl
|
|
|
|
match args with
|
2024-08-26 20:37:19 +03:00
|
|
|
[] -> raise (testGetArgs.fail "called with no args")
|
|
|
|
[_] -> raise (testGetArgs.fail "called with one arg")
|
2021-10-23 10:00:46 +03:00
|
|
|
[_, _] -> printLine "called with two args"
|
2024-08-26 20:37:19 +03:00
|
|
|
_ -> raise (testGetArgs.fail "called with too many args")
|
2021-10-23 10:00:46 +03:00
|
|
|
```
|
|
|
|
|
2021-10-24 04:21:15 +03:00
|
|
|
Test that they can be run with the right number of args.
|
2024-07-10 17:46:18 +03:00
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testGetArgs.fail : Text -> Failure
|
|
|
|
testGetArgs.runMeWithNoArgs : '{IO, Exception} ()
|
|
|
|
testGetArgs.runMeWithOneArg : '{IO, Exception} ()
|
|
|
|
testGetArgs.runMeWithTwoArgs : '{IO, Exception} ()
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithNoArgs
|
2021-10-23 10:00:46 +03:00
|
|
|
|
2022-08-15 21:30:14 +03:00
|
|
|
()
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithOneArg foo
|
2021-10-24 04:21:15 +03:00
|
|
|
|
2022-08-15 21:30:14 +03:00
|
|
|
()
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithTwoArgs foo bar
|
2021-10-24 04:21:15 +03:00
|
|
|
|
2022-08-15 21:30:14 +03:00
|
|
|
()
|
|
|
|
|
2021-10-23 10:00:46 +03:00
|
|
|
```
|
2021-10-24 04:21:15 +03:00
|
|
|
Calling our examples with the wrong number of args will error.
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithNoArgs foo
|
2021-10-24 04:21:15 +03:00
|
|
|
|
|
|
|
💔💥
|
|
|
|
|
|
|
|
The program halted with an unhandled exception:
|
|
|
|
|
2022-02-13 08:20:06 +03:00
|
|
|
Failure (typeLink IOFailure) "called with args" (Any ())
|
2024-04-16 21:26:28 +03:00
|
|
|
|
2022-10-20 23:21:15 +03:00
|
|
|
Stack trace:
|
|
|
|
##raise
|
2021-10-24 04:21:15 +03:00
|
|
|
|
2021-10-23 10:00:46 +03:00
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithOneArg
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
💔💥
|
|
|
|
|
|
|
|
The program halted with an unhandled exception:
|
|
|
|
|
2022-02-13 08:20:06 +03:00
|
|
|
Failure (typeLink IOFailure) "called with no args" (Any ())
|
2024-04-16 21:26:28 +03:00
|
|
|
|
2022-10-20 23:21:15 +03:00
|
|
|
Stack trace:
|
|
|
|
##raise
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithOneArg foo bar
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
💔💥
|
|
|
|
|
|
|
|
The program halted with an unhandled exception:
|
|
|
|
|
|
|
|
Failure
|
2022-02-13 08:20:06 +03:00
|
|
|
(typeLink IOFailure) "called with too many args" (Any ())
|
2024-04-16 21:26:28 +03:00
|
|
|
|
2022-10-20 23:21:15 +03:00
|
|
|
Stack trace:
|
|
|
|
##raise
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
```
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run runMeWithTwoArgs
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
💔💥
|
|
|
|
|
|
|
|
The program halted with an unhandled exception:
|
|
|
|
|
2022-02-13 08:20:06 +03:00
|
|
|
Failure (typeLink IOFailure) "called with no args" (Any ())
|
2024-04-16 21:26:28 +03:00
|
|
|
|
2022-10-20 23:21:15 +03:00
|
|
|
Stack trace:
|
|
|
|
##raise
|
2021-10-23 10:00:46 +03:00
|
|
|
|
|
|
|
```
|
2023-06-22 07:46:40 +03:00
|
|
|
### Get the time zone
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2023-06-22 07:46:40 +03:00
|
|
|
testTimeZone = do
|
|
|
|
(offset, summer, name) = Clock.internals.systemTimeZone +0
|
2023-06-22 10:02:49 +03:00
|
|
|
_ = (offset : Int, summer : Nat, name : Text)
|
|
|
|
()
|
2023-06-22 07:46:40 +03:00
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2023-06-22 07:46:40 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
2023-06-22 10:02:49 +03:00
|
|
|
testTimeZone : '{IO} ()
|
2023-06-22 07:46:40 +03:00
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> run testTimeZone
|
2023-06-22 07:46:40 +03:00
|
|
|
|
2023-06-22 10:02:49 +03:00
|
|
|
()
|
2023-06-22 07:46:40 +03:00
|
|
|
|
|
|
|
```
|
2023-07-02 07:31:11 +03:00
|
|
|
### Get some random bytes
|
|
|
|
|
2024-07-10 17:46:18 +03:00
|
|
|
``` unison
|
2023-07-02 07:31:11 +03:00
|
|
|
testRandom : '{io2.IO} [Result]
|
|
|
|
testRandom = do
|
|
|
|
test = do
|
|
|
|
bytes = IO.randomBytes 10
|
|
|
|
check "randomBytes returns the right number of bytes" (size bytes == 10)
|
|
|
|
runTest test
|
|
|
|
```
|
|
|
|
|
2024-07-10 19:17:15 +03:00
|
|
|
``` ucm
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> add
|
2023-07-02 07:31:11 +03:00
|
|
|
|
|
|
|
⍟ I've added these definitions:
|
|
|
|
|
|
|
|
testRandom : '{IO} [Result]
|
|
|
|
|
2024-06-12 01:22:09 +03:00
|
|
|
scratch/main> io.test testGetEnv
|
2023-07-02 07:31:11 +03:00
|
|
|
|
|
|
|
New test results:
|
|
|
|
|
2024-06-27 08:14:37 +03:00
|
|
|
1. testGetEnv ◉ PATH environent variable should be set
|
|
|
|
◉ DOESNTEXIST didn't exist
|
2023-07-02 07:31:11 +03:00
|
|
|
|
|
|
|
✅ 2 test(s) passing
|
|
|
|
|
2024-06-26 23:01:36 +03:00
|
|
|
Tip: Use view 1 to view the source of a test.
|
2023-07-02 07:31:11 +03:00
|
|
|
|
|
|
|
```
|