diff options
Diffstat (limited to 'stdlib/source/test/lux/world/file.lux')
-rw-r--r-- | stdlib/source/test/lux/world/file.lux | 252 |
1 files changed, 237 insertions, 15 deletions
diff --git a/stdlib/source/test/lux/world/file.lux b/stdlib/source/test/lux/world/file.lux index 39e8d13dd..ee313599f 100644 --- a/stdlib/source/test/lux/world/file.lux +++ b/stdlib/source/test/lux/world/file.lux @@ -1,19 +1,239 @@ (.using - [library - [lux "*" - ["_" test {"+" Test}] - [abstract - [monad {"+" do}]] - [control - ["[0]" io]] - [math - ["[0]" random]]]] - ["[0]" / "_" - ["[1][0]" watch]] - [\\library - ["[0]" /]] - [\\specification - ["$[0]" /]]) + [library + [lux "*" + ["_" test {"+" Test}] + [abstract + ["[0]" monad {"+" do}]] + [control + ["[0]" io {"+" IO}] + ["[0]" try {"+" Try}] + [concurrency + [async {"+" Async}] + ["[0]" atom {"+" Atom}]]] + [data + ["[0]" binary {"+" Binary} ("[1]#[0]" monoid)] + ["[0]" text ("[1]#[0]" equivalence)] + [collection + ["[0]" dictionary {"+" Dictionary}] + ["[0]" list]]] + [math + ["[0]" random]] + [time + ["[0]" instant {"+" Instant}]]]] + ["[0]" / "_" + ["[1][0]" watch]] + [\\library + ["[0]" /]] + [\\specification + ["$[0]" /]]) + +(type: Disk + (Dictionary /.Path (Either [Instant Binary] (List Text)))) + +(def: (file? disk @) + (-> (Atom Disk) (-> /.Path (IO Bit))) + (do io.monad + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#None} false + {.#Some {.#Left _}} true + {.#Some {.#Right _}} false)))) + +(def: (directory? disk @) + (-> (Atom Disk) (-> /.Path (IO Bit))) + (do io.monad + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#None} false + {.#Some {.#Left _}} false + {.#Some {.#Right _}} true)))) + +(def: (alert_parent! disk alert @) + (-> (Atom Disk) + (-> (List /.Path) (List /.Path)) + (-> /.Path (IO (Try Any)))) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#Some {.#Right siblings}} + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.has @ {.#Right (alert siblings)} disk') disk)] + (in {try.#Success []})) + + _ + (in {try.#Failure ""})))) + +(def: (write fs disk it @) + (-> (/.System Async) (Atom Disk) (-> Binary /.Path (IO (Try Any)))) + (do [! io.monad] + [now instant.now + disk' (atom.read! disk)] + (case (dictionary.value @ disk') + (^or {.#None} + {.#Some {.#Left _}}) + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.has @ {.#Left [now it]} disk') disk)] + (case (/.parent fs @) + {.#Some parent} + (alert_parent! disk (|>> (list& @)) parent) + + {.#None} + (in {try.#Success []}))) + + _ + (in {try.#Failure ""})))) + +(def: (read disk @) + (-> (Atom Disk) (-> /.Path (IO (Try Binary)))) + (do io.monad + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#Some {.#Left [_ it]}} + {try.#Success it} + + _ + {try.#Failure ""})))) + +(def: (delete fs disk @) + (-> (/.System Async) (Atom Disk) + (-> /.Path (IO (Try Any)))) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#Some {.#Right children}} + (if (list.empty? children) + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.lacks @ disk') disk)] + (in {try.#Success []})) + (in {try.#Failure ""})) + + {.#Some {.#Left [_ data]}} + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.lacks @ disk') disk)] + (case (/.parent fs @) + {.#Some parent} + (alert_parent! disk (list.only (|>> (text#= @) not)) parent) + + {.#None} + (in {try.#Success []}))) + + _ + (in {try.#Failure ""})))) + +(def: (fs /) + (-> Text (/.System IO)) + (let [disk (: (Atom Disk) + (atom.atom (dictionary.empty text.hash))) + mock (/.mock /)] + (implementation + (def: separator /) + + (def: file? (..file? disk)) + (def: directory? (..directory? disk)) + (def: write (..write mock disk)) + (def: read (..read disk)) + (def: delete (..delete mock disk)) + + (def: (file_size @) + (do [! io.monad] + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#Some {.#Left [_ it]}} + {try.#Success (binary.size it)} + + _ + {try.#Failure ""})))) + (def: (last_modified @) + (do [! io.monad] + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#Some {.#Left [it _]}} + {try.#Success it} + + _ + {try.#Failure ""})))) + (def: (can_execute? @) + (do [! io.monad] + [disk (atom.read! disk)] + (in (case (dictionary.value @ disk) + {.#Some {.#Left _}} + {try.#Success false} + + _ + {try.#Failure ""})))) + + (def: (make_directory @) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#None} + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.has @ {.#Right (list)} disk') disk)] + (case (/.parent mock @) + {.#Some parent} + (alert_parent! disk (|>> (list& @)) parent) + + {.#None} + (in {try.#Success []}))) + + _ + (in {try.#Failure ""})))) + (def: (directory_files @) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#Some {.#Right children}} + (|> children + (monad.only ! (..file? disk)) + (# ! each (|>> {try.#Success}))) + + _ + (in {try.#Failure ""})))) + (def: (sub_directories @) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#Some {.#Right children}} + (|> children + (monad.only ! (..directory? disk)) + (# ! each (|>> {try.#Success}))) + + _ + (in {try.#Failure ""})))) + (def: (append it @) + (do [! io.monad] + [now instant.now + disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#None} + (..write mock disk it @) + + {.#Some {.#Left [_ old]}} + (do ! + [_ (atom.compare_and_swap! disk' + (dictionary.has @ {.#Left [now (binary#composite old it)]} disk') + disk)] + (in {try.#Success []})) + + _ + (in {try.#Failure ""})))) + (def: (modify it @) + (do [! io.monad] + [disk' (atom.read! disk)] + (case (dictionary.value @ disk') + {.#Some {.#Left [_ data]}} + (do ! + [_ (atom.compare_and_swap! disk' (dictionary.has @ {.#Left [it data]} disk') disk)] + (in {try.#Success []})) + + _ + (in {try.#Failure ""})))) + (def: (move it @) + (do [! (try.with io.monad)] + [data (..read disk @) + write (..write mock disk data it)] + (..delete mock disk @))) + ))) (def: .public test Test @@ -23,6 +243,8 @@ ($_ _.and (_.for [/.mock] ($/.spec (io.io (/.mock /)))) + (_.for [/.async] + ($/.spec (io.io (/.async (..fs /))))) /watch.test )))) |