(.require [library [lux (.except) [abstract [monad (.only do)]] [control ["<>" parser (.only)] ["[0]" maybe] ["[0]" try] ["[0]" exception]] [data ["[0]" product] ["[0]" binary (.use "[1]#[0]" equivalence monoid) ["" \\parser] ["[0]" \\format]] ["[0]" text (.use "[1]#[0]" equivalence) ["%" \\format (.only format)] [encoding ["[0]" utf8]] ["[0]" unicode ["[1]" set] ["[1]/[0]" block]]] [collection ["[0]" sequence] ["[0]" list (.use "[1]#[0]" mix)]]] [math ["[0]" random (.only Random)] [number ["n" nat] ["i" int]]] [world [time ["[0]" instant (.only Instant)] ["[0]" duration]]] [test ["_" property (.only Test)]]]] [\\library ["[0]" /]]) (def path Test (_.for [/.Path] (do [! random.monad] [expected (random.lower_case /.path_size) invalid (random.lower_case (++ /.path_size)) not_ascii (random.text (random.char (unicode.set [unicode/block.katakana (list)])) /.path_size)] (`` (all _.and (_.coverage [/.path /.from_path] (when (/.path expected) {try.#Success actual} (text#= expected (/.from_path actual)) {try.#Failure error} false)) (_.coverage [/.no_path] (text#= "" (/.from_path /.no_path))) (_.coverage [/.path_size /.path_is_too_long] (when (/.path invalid) {try.#Success _} false {try.#Failure error} (exception.match? /.path_is_too_long error))) (_.coverage [/.not_ascii] (when (/.path not_ascii) {try.#Success actual} false {try.#Failure error} (exception.match? /.not_ascii error))) ))))) (def name Test (_.for [/.Name] (do [! random.monad] [expected (random.lower_case /.name_size) invalid (random.lower_case (++ /.name_size)) not_ascii (random.text (random.char (unicode.set [unicode/block.katakana (list)])) /.name_size)] (`` (all _.and (_.coverage [/.name /.from_name] (when (/.name expected) {try.#Success actual} (text#= expected (/.from_name actual)) {try.#Failure error} false)) (_.coverage [/.name_size /.name_is_too_long] (when (/.name invalid) {try.#Success _} false {try.#Failure error} (exception.match? /.name_is_too_long error))) (_.coverage [/.not_ascii] (when (/.name not_ascii) {try.#Success actual} false {try.#Failure error} (exception.match? /.not_ascii error))) ))))) (def small Test (_.for [/.Small] (do [! random.monad] [expected (|> random.nat (at ! each (n.% /.small_limit))) invalid (|> random.nat (at ! each (n.max /.small_limit)))] (`` (all _.and (_.coverage [/.small /.from_small] (when (/.small expected) {try.#Success actual} (n.= expected (/.from_small actual)) {try.#Failure error} false)) (_.coverage [/.small_limit /.not_a_small_number] (when (/.small invalid) {try.#Success actual} false {try.#Failure error} (exception.match? /.not_a_small_number error))) ))))) (def big Test (_.for [/.Big] (do [! random.monad] [expected (|> random.nat (at ! each (n.% /.big_limit))) invalid (|> random.nat (at ! each (n.max /.big_limit)))] (`` (all _.and (_.coverage [/.big /.from_big] (when (/.big expected) {try.#Success actual} (n.= expected (/.from_big actual)) {try.#Failure error} false)) (_.coverage [/.big_limit /.not_a_big_number] (when (/.big invalid) {try.#Success actual} false {try.#Failure error} (exception.match? /.not_a_big_number error))) ))))) (def chunk_size 32) (def entry Test (do [! random.monad] [expected_path (random.lower_case (-- /.path_size)) expected_moment (at ! each (|>> (n.% 1,0,00,00,00,00,000) .int instant.of_millis) random.nat) chunk (random.lower_case chunk_size) chunks (at ! each (n.% 100) random.nat) .let [content (|> chunk (list.repeated chunks) text.together (at utf8.codec encoded))]] (`` (all _.and (,, (with_template [ ] [(_.coverage [] (|> (do try.monad [expected_path (/.path expected_path) tar (|> (sequence.sequence { expected_path}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list { actual_path}) (text#= (/.from_path expected_path) (/.from_path actual_path)) _ false))) (try.else false)))] [/.Symbolic_Link /.#Symbolic_Link] [/.Directory /.#Directory] )) (_.for [/.File /.Content /.content /.data] (all _.and (,, (with_template [ ] [(_.coverage [] (|> (do try.monad [expected_path (/.path expected_path) expected_content (/.content content) tar (|> (sequence.sequence { [expected_path expected_moment /.none [/.#user [/.#name /.anonymous /.#id /.no_id] /.#group [/.#name /.anonymous /.#id /.no_id]] expected_content]}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list { [actual_path actual_moment actual_mode actual_ownership actual_content]}) (let [seconds (is (-> Instant Int) (|>> instant.relative (duration.ticks duration.second)))] (and (text#= (/.from_path expected_path) (/.from_path actual_path)) (i.= (seconds expected_moment) (seconds actual_moment)) (binary#= (/.data expected_content) (/.data actual_content)))) _ false))) (try.else false)))] [/.Normal /.#Normal] [/.Contiguous /.#Contiguous] )))))))) (def random_mode (Random /.Mode) (do [! random.monad] [] (random.either (random.either (random.either (in /.execute_by_other) (in /.write_by_other)) (random.either (in /.read_by_other) (in /.execute_by_group))) (random.either (random.either (random.either (in /.write_by_group) (in /.read_by_group)) (random.either (in /.execute_by_owner) (in /.write_by_owner))) (random.either (random.either (in /.read_by_owner) (in /.save_text)) (random.either (in /.set_group_id_on_execution) (in /.set_user_id_on_execution))))))) (def mode Test (_.for [/.Mode /.mode] (do [! random.monad] [path (random.lower_case 10) modes (random.list 4 ..random_mode) .let [expected_mode (list#mix /.and /.none modes)]] (`` (all _.and (_.coverage [/.and] (|> (do try.monad [path (/.path path) content (/.content (binary.empty 0)) tar (|> (sequence.sequence {/.#Normal [path (instant.of_millis +0) expected_mode [/.#user [/.#name /.anonymous /.#id /.no_id] /.#group [/.#name /.anonymous /.#id /.no_id]] content]}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list {/.#Normal [_ _ actual_mode _ _]}) (n.= (/.mode expected_mode) (/.mode actual_mode)) _ false))) (try.else false))) (,, (with_template [] [(_.coverage [] (|> (do try.monad [path (/.path path) content (/.content (binary.empty 0)) tar (|> (sequence.sequence {/.#Normal [path (instant.of_millis +0) [/.#user [/.#name /.anonymous /.#id /.no_id] /.#group [/.#name /.anonymous /.#id /.no_id]] content]}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list {/.#Normal [_ _ actual_mode _ _]}) (n.= (/.mode ) (/.mode actual_mode)) _ false))) (try.else false)))] [/.none] [/.execute_by_other] [/.write_by_other] [/.read_by_other] [/.execute_by_group] [/.write_by_group] [/.read_by_group] [/.execute_by_owner] [/.write_by_owner] [/.read_by_owner] [/.save_text] [/.set_group_id_on_execution] [/.set_user_id_on_execution] ))))))) (def ownership Test (do [! random.monad] [path (random.lower_case /.path_size) expected (random.lower_case /.name_size) invalid (random.lower_case (++ /.name_size)) not_ascii (random.text (random.char (unicode.set [unicode/block.katakana (list)])) /.name_size)] (_.for [/.Ownership /.Owner /.ID] (all _.and (_.coverage [/.name_size /.name_is_too_long] (when (/.name invalid) {try.#Success _} false {try.#Failure error} (exception.match? /.name_is_too_long error))) (_.coverage [/.not_ascii] (when (/.name not_ascii) {try.#Success actual} false {try.#Failure error} (exception.match? /.not_ascii error))) (_.coverage [/.Name /.name /.from_name] (|> (do try.monad [path (/.path path) content (/.content (binary.empty 0)) expected (/.name expected) tar (|> (sequence.sequence {/.#Normal [path (instant.of_millis +0) /.none [/.#user [/.#name expected /.#id /.no_id] /.#group [/.#name /.anonymous /.#id /.no_id]] content]}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list {/.#Normal [_ _ _ actual_ownership _]}) (and (text#= (/.from_name expected) (/.from_name (the [/.#user /.#name] actual_ownership))) (text#= (/.from_name /.anonymous) (/.from_name (the [/.#group /.#name] actual_ownership)))) _ false))) (try.else false))) (_.coverage [/.anonymous /.no_id] (|> (do try.monad [path (/.path path) content (/.content (binary.empty 0)) tar (|> (sequence.sequence {/.#Normal [path (instant.of_millis +0) /.none [/.#user [/.#name /.anonymous /.#id /.no_id] /.#group [/.#name /.anonymous /.#id /.no_id]] content]}) (\\format.result /.format) (.result /.parser))] (in (when (sequence.list tar) (list {/.#Normal [_ _ _ actual_ownership _]}) (and (text#= (/.from_name /.anonymous) (/.from_name (the [/.#user /.#name] actual_ownership))) (n.= (/.from_small /.no_id) (/.from_small (the [/.#user /.#id] actual_ownership))) (text#= (/.from_name /.anonymous) (/.from_name (the [/.#group /.#name] actual_ownership))) (n.= (/.from_small /.no_id) (/.from_small (the [/.#group /.#id] actual_ownership)))) _ false))) (try.else false))) )))) (def .public test Test (<| (_.covering /._) (_.for [/.Tar]) (do random.monad [_ (in [])] (all _.and (_.coverage [/.format /.parser] (|> sequence.empty (\\format.result /.format) (.result /.parser) (at try.monad each sequence.empty?) (try.else false))) (_.coverage [/.invalid_end_of_archive] (let [dump (\\format.result /.format sequence.empty)] (when (.result /.parser (binary#composite dump dump)) {try.#Success _} false {try.#Failure error} (exception.match? /.invalid_end_of_archive error)))) ..path ..name ..small ..big (_.for [/.Entry] (all _.and ..entry ..mode ..ownership )) ))))