diff --git a/.gitlab/ci/test/unit.yml b/.gitlab/ci/test/unit.yml index 1d1f19b180421ff62b8386ed3b096e2f80860547..2fd01ea00102a9c4e1cd115ecaa016c0d231bed8 100644 --- a/.gitlab/ci/test/unit.yml +++ b/.gitlab/ci/test/unit.yml @@ -122,7 +122,6 @@ unit:alpha: proto_alpha__lib_protocol__3: > @src/proto_alpha/lib_protocol/test/pbt/runtest @src/proto_alpha/lib_protocol/test/unit/runtest - @src/proto_alpha/lib_protocol/test/regression/runtest proto_alpha: > @src/proto_alpha/lib_benchmark/runtest @src/proto_alpha/lib_client/runtest diff --git a/manifest/main.ml b/manifest/main.ml index e98ff10756743b48ea06cae6aeeef39af75152bc..218017133db4ee2658763b5457207fa36954be59 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -24,6 +24,12 @@ (*****************************************************************************) open Manifest + +let tezt_without_tezt_lib_dependency = tezt + +(* Prevent using [tezt] until we define [tezt_lib]. *) +let tezt = () [@@warning "-unused-value-declaration"] + module V = Version let sf = Printf.sprintf @@ -1276,7 +1282,7 @@ let _tezos_tooling_opam_file_format = let _tezos_tooling_opam_lint = test "opam_lint" - ~runtest:false + ~alias:"" ~path:"src/tooling/opam-lint" ~opam:"tezos-tooling" ~deps:[_tezos_tooling_opam_file_format; unix] @@ -1332,7 +1338,7 @@ let _tezos_p2p_tests = astring; ] ~linkall:true - ~runtest:false + ~alias:"" ~dune: Dune.( (* At the termination of the tests, or if an unexpected @@ -2645,7 +2651,7 @@ let tezos_shell_benchmarks = ] ~linkall:true -let tezt = +let tezt_lib = public_lib "tezt" ~path:"tezt/lib" @@ -2655,13 +2661,21 @@ let tezt = ~bisect_ppx:false ~deps:[re; lwt_unix; ezjsonm] +let tezt ~opam ~path ?(deps = []) ?dep_globs l = + tezt_without_tezt_lib_dependency + ~opam + ~path + ~deps:((tezt_lib |> open_ |> open_ ~m:"Base") :: deps) + ?dep_globs + l + let tezt_performance_regression = public_lib "tezt-performance-regression" ~path:"tezt/lib_performance_regression" ~synopsis:"Performance regression test framework based on Tezt" ~bisect_ppx:false - ~deps:[tezt |> open_ |> open_ ~m:"Base"; uri; cohttp_lwt_unix] + ~deps:[tezt_lib |> open_ |> open_ ~m:"Base"; uri; cohttp_lwt_unix] let tezt_tezos = public_lib @@ -2671,7 +2685,7 @@ let tezt_tezos = ~bisect_ppx:false ~deps: [ - tezt |> open_ |> open_ ~m:"Base"; + tezt_lib |> open_ |> open_ ~m:"Base"; tezt_performance_regression |> open_; uri; hex; @@ -2689,7 +2703,7 @@ let _tezt_self_tests = ~synopsis:"Tests for the Tezos test framework based on Tezt" ~bisect_ppx:false ~static:false - ~deps:[tezt |> open_ |> open_ ~m:"Base"; tezt_tezos |> open_] + ~deps:[tezt_lib |> open_ |> open_ ~m:"Base"; tezt_tezos |> open_] ~cram:true ~dune: Dune. @@ -2708,7 +2722,7 @@ let tezos_openapi = ~synopsis: "Tezos: a library for querying RPCs and converting into the OpenAPI \ format" - ~deps:[ezjsonm; json_data_encoding; tezt] + ~deps:[ezjsonm; json_data_encoding; tezt_lib] let _tezos_protocol_compiler_bin = public_exe @@ -3167,7 +3181,7 @@ end = struct "main" ~path:(path // "lib_protocol/test/unit") ~opam:(sf "tezos-protocol-%s-tests" name_dash) - ~runtest:false + ~alias:"" ~deps: [ tezos_base |> open_ ~m:"TzPervasives" @@ -3196,23 +3210,28 @@ end = struct in let _regresssion = if N.(number >= 014) then - Some - (test - "main" - ~path:(path // "lib_protocol/test/regression") - ~opam:(sf "tezos-protocol-%s-tests" name_dash) - ~deps: - [ - tezt; - tezos_base |> open_ ~m:"TzPervasives"; - main |> open_; - client |> if_some |> open_; - plugin |> if_some |> open_; - test_helpers |> if_some |> open_; - tezos_micheline |> open_; - ] - ~dep_globs:["contracts/*"; "tezt/_regressions/*"]) - else None + (* About [~dep_globs]: this is only needed so that dune re-runs the tests + if those files are modified. Dune will also copy those files in [_build], + but the test uses absolute paths to find those files + (thanks to [DUNE_SOURCEROOT] and [Filename.dirname __FILE__]), + so those copies are not actually used. This is needed so that the test + can be run either with [dune build @runtezt], + with [dune exec src/proto_alpha/lib_protocol/test/regression/main.exe], + or with [dune exec tezt/tests/main.exe -- -f test_logging.ml]. *) + tezt + ["test_logging"] + ~path:(path // "lib_protocol/test/regression") + ~opam:(sf "tezos-protocol-%s-tests" name_dash) + ~deps: + [ + tezos_base |> open_ ~m:"TzPervasives"; + main |> open_; + client |> if_some |> open_; + plugin |> if_some |> open_; + test_helpers |> if_some |> open_; + tezos_micheline |> open_; + ] + ~dep_globs:["contracts/*.tz"; "expected/test_logging.ml/*.out"] in () @@ -3936,7 +3955,7 @@ include Tezos_raw_protocol_%s.Main some_if (active && N.(number >= 013)) @@ fun () -> test "tenderbrute_main" - ~runtest:false + ~alias:"" ~path:(path // "lib_delegate/test/tenderbrute") ~opam:(sf "tezos-baking-%s" name_dash) ~deps: @@ -4347,7 +4366,7 @@ include Tezos_raw_protocol_%s.Main alcotest_lwt; prbnmcn_stats; ] - ~runtest:false + ~alias:"" ~dune: Dune. [ @@ -4519,7 +4538,7 @@ let _tezos_store_tests = tezos_test_helpers; tezos_test_helpers_extra; ] - ~runtest:false + ~alias:"" ~dune: (* [test_slow_manual] is a very long test, running a huge combination of tests that are useful for local testing for a @@ -4990,7 +5009,7 @@ let _tezos_tps_evaluation = Protocol.(client_commands_exn alpha); tezos_client_base_unix; Protocol.(main alpha); - tezt |> open_ |> open_ ~m:"Base"; + tezt_lib |> open_ |> open_ ~m:"Base"; tezt_tezos |> open_; tezt_performance_regression |> open_; uri; @@ -5056,12 +5075,29 @@ let exclude filename = | "tezt" :: "records" :: _ -> true | "tezt" :: "remote_tests" :: _ -> true | "tezt" :: "snoop" :: _ -> true - | "tezt" :: "tests" :: _ -> true | "tezt" :: "vesting_contract_test" :: _ -> true | _ -> false -(* Generate dune and opam files. *) -let () = generate () +let () = + (* [make_tezt_exe] makes the global executable that contains all tests. + [generate] gives it the list of libraries that register Tezt tests + so that it can link all of them. *) + let make_tezt_exe test_libs = + let deps = + [ + tezt_lib |> open_ |> open_ ~m:"Base"; + str; + tezt_tezos |> open_ |> open_ ~m:"Runnable.Syntax"; + data_encoding; + tezos_base; + tezos_base_unix; + tezos_stdlib_unix; + Protocol.(main alpha); + ] + in + test "main" ~alias:"" ~path:"tezt/tests" ~opam:"" ~deps:(deps @ test_libs) + in + generate ~make_tezt_exe (* Generate a dunw-workspace file at the root of the repo *) let () = diff --git a/manifest/manifest.ml b/manifest/manifest.ml index 4429e702181ca8d45b739217a6cd1a8fb308c3b8..ac4033e342bad58310160edb6acbb946755d1b1f 100644 --- a/manifest/manifest.ml +++ b/manifest/manifest.ml @@ -315,10 +315,10 @@ module Dune = struct let run_exe exe_name args = run ("%{exe:" ^ exe_name ^ ".exe}") args - let runtest_js ~package ~dep_files name = + let runtest_js ?(alias = "runtest_js") ?package ~dep_files name = alias_rule - "runtest_js" - ~package + alias + ?package ~deps:dep_files ~action:[S "run"; S "node"; S ("%{dep:./" ^ name ^ ".bc.js}")] @@ -326,15 +326,15 @@ module Dune = struct let glob_files expr = [S "glob_files"; S expr] - let runtest ~package ~dep_files ~dep_globs name = + let runtest ?(alias = "runtest") ?package ~dep_files ~dep_globs name = let deps_dune = let files = List.map (fun s -> S s) dep_files in let globs = List.map glob_files dep_globs in match files @ globs with [] -> None | deps -> Some (of_list deps) in alias_rule - "runtest" - ~package + alias + ?package ?deps_dune ~action:[S "run"; S ("%{dep:./" ^ name ^ ".exe}")] @@ -875,7 +875,10 @@ module Target = struct | Private_library of string | Public_executable of full_name Ne_list.t | Private_executable of string Ne_list.t - | Test_executable of {names : string Ne_list.t; run : bool} + | Test_executable of { + names : string Ne_list.t; + runtest_alias : string option; + } type preprocessor_dep = File of string @@ -1150,7 +1153,7 @@ module Target = struct match opam with | Some "" -> ( match kind with - | Test_executable {names = name, _; run = true; _} -> + | Test_executable {names = name, _; runtest_alias = Some _; _} -> invalid_argf "for targets which provide test executables such as %S, you \ must specify a non-empty ~opam or have it not run by default \ @@ -1165,7 +1168,7 @@ module Target = struct "for targets which provide public executables such as %S, you \ cannot have ~opam set to empty string (\"\")" public_name - | Test_executable {run = false; _} + | Test_executable {runtest_alias = None; _} | Private_library _ | Private_executable _ -> None) | Some opam as x -> @@ -1287,27 +1290,33 @@ module Target = struct | Some modes -> List.mem Dune.Native modes in match (kind, opam, dep_files) with - | Test_executable {names; run = true}, Some package, _ -> + | Test_executable {names; runtest_alias = Some alias}, package, _ -> let runtest_js_rules = if run_js then List.map - (fun name -> Dune.(runtest_js ~dep_files ~package name)) + (fun name -> + Dune.runtest_js + ~alias:(alias ^ "_js") + ~dep_files + ?package + name) (Ne_list.to_list names) else [] in let runtest_rules = if run_native then List.map - (fun name -> Dune.(runtest ~dep_files ~dep_globs ~package name)) + (fun name -> + Dune.runtest ~alias ~dep_files ~dep_globs ?package name) (Ne_list.to_list names) else [] in runtest_rules @ runtest_js_rules - | Test_executable {names = name, _; run = false; _}, _, _ :: _ -> + | Test_executable {names = name, _; runtest_alias = None}, _, _ :: _ -> invalid_argf - "for targets which provide test executables such as %S, \ - [~dep_files] is only meaningful for runtest alias. It cannot be \ - used together with [runtest:false]" + "for targets which provide test executables such as %S, ~dep_files \ + is only meaningful for the runtest alias. It cannot be used with \ + no alias, i.e. ~alias:\"\"." name | _, _, _ :: _ -> assert false | _ -> [] @@ -1406,15 +1415,17 @@ module Target = struct | [] -> invalid_argf "Target.private_exes: at least one name must be given" | head :: tail -> Private_executable (head, tail) - let test ?dep_files ?dep_globs ?(runtest = true) = + let test ?(alias = "runtest") ?dep_files ?dep_globs = + let runtest_alias = if alias = "" then None else Some alias in internal ?dep_files ?dep_globs @@ fun test_name -> - Test_executable {names = (test_name, []); run = runtest} + Test_executable {names = (test_name, []); runtest_alias} - let tests ?dep_files ?dep_globs ?(runtest = true) = + let tests ?(alias = "runtest") ?dep_files ?dep_globs = + let runtest_alias = if alias = "" then None else Some alias in internal ?dep_files ?dep_globs @@ fun test_names -> match test_names with | [] -> invalid_arg "Target.tests: at least one name must be given" - | head :: tail -> Test_executable {names = (head, tail); run = runtest} + | head :: tail -> Test_executable {names = (head, tail); runtest_alias} let vendored_lib ?(released_on_opam = true) ?main_module ?(js_compatible = false) ?(npm_deps = []) name = @@ -1525,6 +1536,71 @@ let if_ condition target = if condition then target else None type release = {version : string; url : Opam.url} +type tezt_target = { + opam : string; + deps : target list; + dep_globs : string list; + modules : string list; +} + +let tezt_targets_by_path : tezt_target String_map.t ref = ref String_map.empty + +let tezt ~opam ~path ?(deps = []) ?(dep_globs = []) modules = + if String_map.mem path !tezt_targets_by_path then + invalid_arg + ("cannot call Manifest.tezt twice for the same directory: " ^ path) ; + let tezt_target = {opam; deps; dep_globs; modules} in + tezt_targets_by_path := String_map.add path tezt_target !tezt_targets_by_path + +let register_tezt_targets ~make_tezt_exe = + let tezt_test_libs = ref [] in + let register_path path {opam; deps; dep_globs; modules} = + let path_with_underscores = + String.map (function '-' | '/' -> '_' | c -> c) path + in + let lib = + (* [linkall] is used to ensure that the test executable is linked with + [module_name] and [tezt]. *) + Target.private_lib + (path_with_underscores ^ "_tezt_lib") + ~path + ~opam:"" + ~deps + ~modules + ~linkall:true + in + tezt_test_libs := lib :: !tezt_test_libs ; + let exe_name = "main" in + let _exe = + (* Alias is "runtezt" and not "runtest" to make sure that the test is + not run in the CI twice (once with [dune @src/.../runtest] and once + with [dune exec tezt/tests/main.exe]). *) + Target.test + exe_name + ~alias:"runtezt" + ~path + ~opam + ~deps:[lib] + ~dep_globs + ~modules:[exe_name] + ~dune: + Dune. + [ + targets_rule + [exe_name ^ ".ml"] + ~action: + [ + S "with-stdout-to"; + S "%{targets}"; + [S "echo"; S "let () = Tezt.Test.run ()"]; + ]; + ] + in + () + in + String_map.iter register_path !tezt_targets_by_path ; + make_tezt_exe !tezt_test_libs + (*****************************************************************************) (* GENERATOR *) (*****************************************************************************) @@ -1720,8 +1796,8 @@ let generate_dune ~dune_file_has_static_profile (internal : Target.internal) = | Test_executable _, Some _ -> (* private executable can't have a package stanza, but we still want the manifest to know about the package *) None - | Test_executable {run = false; _}, None -> None - | Test_executable {run = true; _}, None -> + | Test_executable {runtest_alias = None; _}, None -> None + | Test_executable {runtest_alias = Some _; _}, None -> (* Prevented by [Target.internal]. *) assert false in @@ -2033,23 +2109,55 @@ let generate_opam ?release for_package (internals : Target.internal list) : with_test = Never; } in - let runtest with_test : Opam.build_instruction list = - match with_test with - | Never -> [] - | _ -> - [ - { - command = - [S "dune"; S "runtest"; S "-p"; A "name"; S "-j"; A "jobs"]; - with_test; - }; - ] - in let with_test = match internals with [] -> Never | head :: _ -> head.opam_with_test in - [{Opam.command = [S "rm"; S "-r"; S "vendors"]; with_test = Never}; build] - @ runtest with_test + let runtests = + let get_alias (internal : Target.internal) = + match internal.kind with + | Test_executable {runtest_alias; _} -> runtest_alias + | Public_library _ | Private_library _ | Public_executable _ + | Private_executable _ -> + None + in + let make_runtest alias : Opam.build_instruction list = + match (with_test, alias) with + | Never, _ -> [] + | _, "runtest" -> + (* Special case: Dune has a special command to run this alias. *) + [ + { + command = + [S "dune"; S "runtest"; S "-p"; A "name"; S "-j"; A "jobs"]; + with_test; + }; + ] + | _ -> + [ + { + command = + [ + S "dune"; + S "build"; + S ("@" ^ alias); + S "-p"; + A "name"; + S "-j"; + A "jobs"; + ]; + with_test; + }; + ] + in + internals |> List.filter_map get_alias + (* We have to add [runtest] because some targets define the [runtest] + alias manually and use [~alias:""]. *) + |> (fun l -> "runtest" :: l) + |> String_set.of_list |> String_set.elements + |> List.concat_map make_runtest + in + {Opam.command = [S "rm"; S "-r"; S "vendors"]; with_test = Never} + :: build :: runtests in let licenses = match @@ -2678,9 +2786,10 @@ let generate_opam_ci () = delayed_by package_name) -let generate () = +let generate ~make_tezt_exe = Printexc.record_backtrace true ; try + register_tezt_targets ~make_tezt_exe ; generate_dune_files () ; generate_opam_files () ; generate_dune_project_files () ; diff --git a/manifest/manifest.mli b/manifest/manifest.mli index 23c19b16e73ed4e9369e2860d1283df785ec7c32..5a6cf492bdde17d4b12c35c60259af7d86c7cac1 100644 --- a/manifest/manifest.mli +++ b/manifest/manifest.mli @@ -763,8 +763,8 @@ val private_exes : string list maker (** Register and return an internal test. - - [runtest]: if true, setup runtest aliases for the given - test. If unspecified, [runtest] is set true. + - [alias]: if non-empty, an alias is set up for the given test, named [alias]. + Default is ["runtest"]. Note that for JS tests, ["_js"] is appended to this alias. - [dep_files]: a list of files to add as dependencies using [(deps (file ...))] in the [runtest] alias. @@ -775,18 +775,45 @@ val private_exes : string list maker Since tests are private, they have no public name: the ['a] argument of [maker] is the internal name. *) val test : + ?alias:string -> ?dep_files:string list -> ?dep_globs:string list -> - ?runtest:bool -> string maker (** Same as {!test} but with several names, to define multiple tests at once. *) val tests : + ?alias:string -> ?dep_files:string list -> ?dep_globs:string list -> - ?runtest:bool -> string list maker +(** Register a Tezt test. + + Usage: [tezt module_names] + + This declares: + - a library [PACKAGE_tezt_lib] in [path] where [PACKAGE] is the name of the + opam package denoted by [opam]; + - an executable [main] in [path] that links with [PACKAGE_tezt_lib] + and runs [Tezt.Test.run]. + + [module_names] is the list of modules to link in [PACKAGE_tezt_lib]. + Those should be files in [path] that call [Tezt.Test.register]. + + Note that a wrapper in [main.ml] adds a dependency to the [tezt] library + and [-open]s modules [Tezt] and [Tezt.Base] when compiling [module_names]. + + Additionally, the library [PACKAGE_tezt_lib] is also linked in [tezt/tests/main.exe] + so that this executable can be used to run all tests with auto-balancing + and other Tezt features. *) +val tezt : + opam:string -> + path:string -> + ?deps:target list -> + ?dep_globs:string list -> + string list -> + unit + (** Make an external vendored library, for use in internal target dependencies. [main_module] is the name of the main module provided by the library (see [open_]). @@ -796,9 +823,9 @@ val tests : [npm_deps]: npm dependencies used when targeting JavaScript. - [released_on_opam]: whether the library is available on the upstream opam-repository (default true). - In case the lib is not available on opam, tezos packages depending on it won't be installable on opam. - *) + [released_on_opam]: whether the library is available on the upstream opam-repository + (default true). In case the lib is not available on opam, tezos packages depending + on it won't be installable on opam. *) val vendored_lib : ?released_on_opam:bool -> ?main_module:string -> @@ -952,8 +979,11 @@ val name_for_errors : target -> string (** Generate dune and opam files. Call this after you declared all your targets with functions such as - [public_lib], [test], etc. *) -val generate : unit -> unit + [public_lib], [test], etc. + + [make_tezt_exe] is given the list of libraries that register Tezt tests + and shall create a test executable that links all of them. *) +val generate : make_tezt_exe:(target list -> target) -> unit (** Run various checks. diff --git a/opam/tezos-protocol-alpha-tests.opam b/opam/tezos-protocol-alpha-tests.opam index b28095948d258e6120f4e6a9d7ac2441663f346d..576a888398053aa08acb41a7287863949685b815 100644 --- a/opam/tezos-protocol-alpha-tests.opam +++ b/opam/tezos-protocol-alpha-tests.opam @@ -34,5 +34,6 @@ build: [ ["rm" "-r" "vendors"] ["dune" "build" "-p" name "-j" jobs] ["dune" "runtest" "-p" name "-j" jobs] {with-test} + ["dune" "build" "@runtezt" "-p" name "-j" jobs] {with-test} ] synopsis: "Tezos/Protocol: tests for economic-protocol definition" diff --git a/scripts/snapshot_alpha.sh b/scripts/snapshot_alpha.sh index 697fedf9cd03c24c311eafbb86aae3032222a7ce..d8c60df68923eacfccd884e57c13d23a253f92e0 100755 --- a/scripts/snapshot_alpha.sh +++ b/scripts/snapshot_alpha.sh @@ -211,10 +211,13 @@ cd lib_protocol sed -i.old -e 's/"hash": "[^"]*",/"hash": "'$long_hash'",/' \ TEZOS_PROTOCOL -sed -i.old -e s/protocol_alpha/protocol_${version}_${short_hash}/ \ - -e s/protocol-alpha/protocol-${version}-${short_hash}/ \ - -e s/protocol-functor-alpha/protocol-functor-${version}-${short_hash}/ \ - $(find . -type f) +# We use -exec instead of just passing the result of find to sed in order +# to support spaces in filenames. +find . -type f -exec \ + sed -i.old -e s/protocol_alpha/protocol_${version}_${short_hash}/ \ + -e s/protocol-alpha/protocol-${version}-${short_hash}/ \ + -e s/protocol-functor-alpha/protocol-functor-${version}-${short_hash}/ \ + {} \; # add this protocol to the immutable list printf \\n$long_hash >> ../../lib_protocol_compiler/final_protocol_versions diff --git a/src/proto_alpha/lib_protocol/test/regression/dune b/src/proto_alpha/lib_protocol/test/regression/dune index c87df26eba04af6d0d513dec7a75ef438c62698d..03d79cc3cb17d6626e0745b73a4e80843a1c4f75 100644 --- a/src/proto_alpha/lib_protocol/test/regression/dune +++ b/src/proto_alpha/lib_protocol/test/regression/dune @@ -1,8 +1,9 @@ ; This file was automatically generated, do not edit. ; Edit file manifest/main.ml instead. -(executable - (name main) +(library + (name src_proto_alpha_lib_protocol_test_regression_tezt_lib) + (instrumentation (backend bisect_ppx)) (libraries tezt tezos-base @@ -11,17 +12,33 @@ tezos-protocol-plugin-alpha tezos-alpha-test-helpers tezos-micheline) + (library_flags (:standard -linkall)) (flags (:standard) + -open Tezt + -open Tezt.Base -open Tezos_base.TzPervasives -open Tezos_protocol_alpha -open Tezos_client_alpha -open Tezos_protocol_plugin_alpha -open Tezos_alpha_test_helpers - -open Tezos_micheline)) + -open Tezos_micheline) + (modules test_logging)) + +(executable + (name main) + (libraries + src_proto_alpha_lib_protocol_test_regression_tezt_lib) + (modules main)) (rule - (alias runtest) + (alias runtezt) (package tezos-protocol-alpha-tests) - (deps (glob_files contracts/*) (glob_files tezt/_regressions/*)) + (deps + (glob_files contracts/*.tz) + (glob_files expected/test_logging.ml/*.out)) (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_alpha/lib_protocol/test/regression/main.ml b/src/proto_alpha/lib_protocol/test/regression/main.ml deleted file mode 100644 index 055d1d7ba7c9a5dce654cad4718ea6f14156dfe2..0000000000000000000000000000000000000000 --- a/src/proto_alpha/lib_protocol/test/regression/main.ml +++ /dev/null @@ -1,39 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2021 Nomadic Labs *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** Testing - ------- - Component: Protocol - Invocation: cd src/proto_alpha/lib_protocol/test/regression && dune exec ./main.exe - Subject: Protocol Regressions - *) - -(* This module runs the tests implemented in all other modules of this directory. - Each module defines tests which are thematically related, - as functions to be called here. *) -let () = - Test_logging.register () ; - (* Test.run () should be the last statement, don't register afterwards! *) - Tezt.Test.run () diff --git a/src/proto_alpha/lib_protocol/test/regression/test_logging.ml b/src/proto_alpha/lib_protocol/test/regression/test_logging.ml index 0a5ea868c431f5e666aca8781f6be9c07fa758fd..2a79d955f06bf0537f4ab8dc86962b7b19cd3bc7 100644 --- a/src/proto_alpha/lib_protocol/test/regression/test_logging.ml +++ b/src/proto_alpha/lib_protocol/test/regression/test_logging.ml @@ -158,7 +158,11 @@ let test_context () = let run_script {filename; amount; storage; parameter} () = let get_log, logger = logger () in let script = - Contract_helpers.read_file @@ Base.(("contracts" // filename) ^ ".tz") + let filename = + project_root // Filename.dirname __FILE__ // "contracts" + // (filename ^ ".tz") + in + Contract_helpers.read_file filename in let* ctxt = test_context () in let step_constants = @@ -195,11 +199,22 @@ let fail_on_error f () = | Ok () -> return () | Error e -> Test.fail "%a" Error_monad.pp_print_trace e +(* Make sure that after a snapshot the snapshotted version of the test + has a different [~title], because all tests are linked in [tezt/tests/main.exe]. *) +let protocol = + match __FILE__ =~* rex "^src/proto_([0-9a-zA-Z_]*)/" with + | None -> + Stdlib.failwith ("failed to extract protocol name from path: " ^ __FILE__) + | Some name -> name + let register_script contract = + (* [~title] must be unique across the codebase, so we prefix it with the protocol name. + [~file] however is better kept the same across protocols to simplify snapshotting. *) Regression.register ~__FILE__ - ~title:contract.filename + ~title:(protocol ^ ": " ^ contract.filename) ~tags:["protocol"; "regression"; "logging"] + ~file:contract.filename (fail_on_error @@ run_script contract) (* These tests should always cover: @@ -210,7 +225,7 @@ let register_script contract = what is being logged and what is not. We are not concerned with gas, because that's kept track of by regular regression tests. Actually, gas is unaccounted for in all the tests in this module. *) -let register () = +let () = Array.iter register_script [| diff --git a/tezt/lib/base.ml b/tezt/lib/base.ml index b0f7012150766c967d668d2d583ead92de7d661e..aa81dfac23926c7251640deeb94aa20dc8804ca8 100644 --- a/tezt/lib/base.ml +++ b/tezt/lib/base.ml @@ -207,3 +207,16 @@ module String_set = struct (fun fmt -> Format.fprintf fmt "%S")) (elements set) end + +let project_root = + match Sys.getenv_opt "DUNE_SOURCEROOT" with + | Some x -> x + | None -> ( + match Sys.getenv_opt "PWD" with + | Some x -> x + | None -> + (* For some reason, under [dune runtest], [PWD] and + [getcwd] have different values. [getcwd] is in + [_build/default], and [PWD] is where [dune runtest] was + executed, which is closer to what we want. *) + Sys.getcwd ()) diff --git a/tezt/lib/base.mli b/tezt/lib/base.mli index 70584eff245ed5c47807a76f9b664f331e9c85a2..9df58e82380df6806492ec3072f1ac8e65d94cc1 100644 --- a/tezt/lib/base.mli +++ b/tezt/lib/base.mli @@ -176,3 +176,10 @@ module String_set : sig and the result is surrounded by braces. *) val pp : Format.formatter -> t -> unit end + +(** {2 Environment} *) + +(** Path to the root of the project. + + This is [DUNE_SOURCEROOT] is defined, [PWD] otherwise. *) +val project_root : string diff --git a/tezt/lib/regression.ml b/tezt/lib/regression.ml index 93483bd1d4ab41640f727b7a3b1d644e23305ff4..2ca0d4fb45123a4c352a445601b76578cdc16f57 100644 --- a/tezt/lib/regression.ml +++ b/tezt/lib/regression.ml @@ -88,41 +88,29 @@ let log_regression_diff diff = In the map, output files can be in subdirectories (i.e. they can contain '/'). *) let output_dirs_and_files : String_set.t String_map.t ref = ref String_map.empty -let register ~__FILE__ ~title ~tags f = +let register ~__FILE__ ~title ~tags ?file f = let tags = "regression" :: tags in - let output_dir = - let project_root = - match Sys.getenv_opt "DUNE_SOURCEROOT" with - | Some x -> x - | None -> ( - match Sys.getenv_opt "PWD" with - | Some x -> x - | None -> - (* For some reason, under [dune runtest], [PWD] and - [getcwd] have different values. [getcwd] is in - [_build/default], and [PWD] is where [dune runtest] was - executed, which is closer to what we want. *) - Sys.getcwd ()) - in - project_root // Filename.dirname __FILE__ // "expected" - in + let output_dir = project_root // Filename.dirname __FILE__ // "expected" in let relative_output_file = - let sanitized_title = - (* We exclude ':' because of Windows. *) - let sanitize_char = function - | ( 'a' .. 'z' - | 'A' .. 'Z' - | '0' .. '9' - | '_' | '-' | '.' | ' ' | '(' | ')' ) as x -> - x - | _ -> '-' - in - let full = String.map sanitize_char title in - let max_length = 80 in - if String.length full > max_length then String.sub full 0 max_length - else full + let file = + match file with + | Some file -> file + | None -> + (* Sanitize title. We exclude ':' because of Windows. *) + let sanitize_char = function + | ( 'a' .. 'z' + | 'A' .. 'Z' + | '0' .. '9' + | '_' | '-' | '.' | ' ' | '(' | ')' ) as x -> + x + | _ -> '-' + in + let full = String.map sanitize_char title in + let max_length = 80 in + if String.length full > max_length then String.sub full 0 max_length + else full in - Filename.basename __FILE__ // (sanitized_title ^ ".out") + Filename.basename __FILE__ // (file ^ ".out") in let old_relative_output_files = String_map.find_opt output_dir !output_dirs_and_files diff --git a/tezt/lib/regression.mli b/tezt/lib/regression.mli index 1b1800e2b80905a3119f249eb4941ea275fe4056..f39c2d9995d021fcd608bdcf56b20eadcb141b3d 100644 --- a/tezt/lib/regression.mli +++ b/tezt/lib/regression.mli @@ -36,16 +36,18 @@ to the [tags] list provided by the argument. Output which is captured (with {!capture}) is recorded in a file named - [//expected//.out] where: + [<ROOT>/<DIR>/expected/<BASE>/<FILE>.out] where: - [<ROOT>] is the root directory of the project, read from environment variable [DUNE_SOURCEROOT] if available, else [PWD] if available, else using [Sys.getcwd]; - [<DIR>] is [Filename.dirname __FILE__]; - [<BASE>] is [Filename.basename __FILE__]; - - [<TITLE>] is a sanitized and possibly truncated version of [~title]. *) + - [<FILE>] is [~file], which defaults to a sanitized and possibly truncated + version of [~title]. *) val register : __FILE__:string -> title:string -> tags:string list -> + ?file:string -> (unit -> unit Lwt.t) -> unit diff --git a/tezt/tests/dune b/tezt/tests/dune index 62f43d97f7f23452d91e76bd8abe55b8e5c14aa2..1e8e4a73009d953b916ec1b5bda3f756ecec80bd 100644 --- a/tezt/tests/dune +++ b/tezt/tests/dune @@ -1,15 +1,21 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + (executable (name main) - (libraries str - tezt-tezos - data-encoding - tezos-base - tezos-base.unix - tezos-stdlib-unix - tezos-protocol-alpha) + (libraries + tezt + str + tezt-tezos + data-encoding + tezos-base + tezos-base.unix + tezos-stdlib-unix + tezos-protocol-alpha + src_proto_alpha_lib_protocol_test_regression_tezt_lib) (flags - (:standard - -open Tezt - -open Tezt_tezos - -open Tezt_tezos.Runnable.Syntax - -open Tezt.Base))) + (:standard) + -open Tezt + -open Tezt.Base + -open Tezt_tezos + -open Tezt_tezos.Runnable.Syntax))