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