(.require [library [lux (.except) [abstract [monad (.only do)]] [control ["[0]" pipe] ["[0]" try] [concurrency ["[0]" atom (.only Atom)] ["[0]" async (.only Async)]]] [data ["[0]" binary] ["[0]" text (.only) ["%" \\format (.only format)] [encoding ["[0]" utf8]]] [collection ["[0]" set]]] [math ["[0]" random] [number ["n" nat]]] [world [console (.only Console)] ["[0]" shell (.only Exit Shell)] ["[0]" environment ["program" / (.only Environment)] ["[1]" \\parser]] ["[0]" file (.only) ["[0]" watch]] [time ["[0]" instant]]] [test ["[0]" unit] ["_" property (.only Test)]]]] ["[0]" // ["$[0]" version] ["$[0]" build]] [\\program ["[0]" / (.only) ["//[1]" /// [command (.only Command)] ["[1]" profile (.only Profile)] ["[1][0]" action] [dependency [resolution (.only Resolution)]]]]]) (def (command expected_runs end_signal fs dummy_file) (-> Nat Text (file.System Async) file.Path [(Atom Nat) (-> (Console Async) (Environment Async) (file.System Async) (Shell Async) Resolution (Command [Exit Any]))]) (let [@runs (is (Atom Nat) (atom.atom 0))] [@runs (function (_ console program fs shell resolution profile) (do [! async.monad] [[_ actual_runs] (async.future (atom.update! ++ @runs))] (if (n.= expected_runs actual_runs) (in {try.#Failure end_signal}) (do (try.with !) [_ (of fs write dummy_file (of utf8.codec encoded (%.nat actual_runs))) _ (of fs modify dummy_file (|> actual_runs .int instant.of_millis))] (in [shell.normal []])))))])) (def .public test Test (<| (_.covering /._) (do [! random.monad] [end_signal (random.alphabetic 5) .let [/ (of file.default separator) [fs watcher] (watch.mock /)] program (random.and (random.alphabetic 5) (random.alphabetic 5)) target (random.alphabetic 5) source (random.alphabetic 5) .let [empty_profile (is Profile (of ///.monoid identity)) with_target (is (-> Profile Profile) (has ///.#target target)) with_program (is (-> Profile Profile) (has ///.#program {.#Some program})) profile (|> empty_profile with_program with_target (has ///.#sources (set.of_list text.hash (list source))))] home (random.alphabetic 5) working_directory (random.alphabetic 5) expected_runs (of ! each (|>> (n.% 10) (n.max 2)) random.nat) dummy_path (of ! each (|>> (format source /)) (random.alphabetic 5)) [compiler resolution] $build.resolution] (all _.and (_.coverage [/.delay] (n.> 0 /.delay)) (in (do async.monad [verdict (do ///action.monad [_ (of fs make_directory source) _ (of fs write dummy_path (binary.empty 0)) .let [[@runs command] (..command expected_runs end_signal fs dummy_path)] _ (of watcher poll [])] (do [! async.monad] [no_dangling_process! (|> profile (has ///.#lux compiler) ((/.do! 1 watcher command) ($version.echo "") (program.async (program.mock environment.empty home working_directory)) fs (shell.async ($build.good_shell [])) resolution) (of ! each (|>> (pipe.when {try.#Failure error} (same? end_signal error) {try.#Success _} false)))) correct_number_of_runs! (|> @runs atom.read! async.future (of ! each (n.= expected_runs)))] (in {try.#Success (and correct_number_of_runs! no_dangling_process!)})))] (unit.coverage [/.do!] (try.else false verdict)))) ))))