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