This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
37
unikernel/duniverse/dune_/test/expect-tests/dune_pkg/dune
Normal file
37
unikernel/duniverse/dune_/test/expect-tests/dune_pkg/dune
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
(library
|
||||
(name dune_pkg_unit_tests)
|
||||
(inline_tests
|
||||
(deps tar-inputs/plaintext.md tarball.tar.gz %{bin:git} %{bin:curl}))
|
||||
(libraries
|
||||
dune_tests_common
|
||||
stdune
|
||||
dune_pkg
|
||||
dune_engine
|
||||
dune_util
|
||||
dune_lang
|
||||
dune_vcs
|
||||
fiber
|
||||
http
|
||||
opam_core
|
||||
threads.posix
|
||||
unix
|
||||
base
|
||||
;; This is because of the (implicit_transitive_deps false)
|
||||
;; in dune-project
|
||||
ppx_expect.config
|
||||
ppx_expect.config_types
|
||||
ppx_inline_test.config)
|
||||
(preprocess
|
||||
(pps ppx_expect)))
|
||||
|
||||
(rule
|
||||
(target tarball.tar.gz)
|
||||
(deps
|
||||
(source_tree tar-inputs))
|
||||
(action
|
||||
(run tar -czf %{target} %{deps})))
|
||||
|
||||
(alias
|
||||
(name pkg)
|
||||
(deps
|
||||
(alias runtest)))
|
||||
|
|
@ -0,0 +1,566 @@
|
|||
open Stdune
|
||||
module Checksum = Dune_pkg.Checksum
|
||||
module Lock_dir = Dune_pkg.Lock_dir
|
||||
module Dependency = Dune_pkg.Lock_dir.Dependency
|
||||
module Opam_repo = Dune_pkg.Opam_repo
|
||||
module Expanded_variable_bindings = Dune_pkg.Solver_stats.Expanded_variable_bindings
|
||||
module Package_variable_name = Dune_lang.Package_variable_name
|
||||
module Variable_value = Dune_pkg.Variable_value
|
||||
module Rev_store = Dune_pkg.Rev_store
|
||||
module Package_version = Dune_pkg.Package_version
|
||||
module Source = Dune_pkg.Source
|
||||
module Package_name = Dune_lang.Package_name
|
||||
module Scheduler = Dune_engine.Scheduler
|
||||
|
||||
let () = Dune_tests_common.init ()
|
||||
|
||||
module Update = struct
|
||||
open Dyn
|
||||
|
||||
let update_source ~commit = function
|
||||
| String url as v ->
|
||||
let opam_url = OpamUrl.parse url in
|
||||
(match Option.equal String.equal opam_url.hash (Some commit) with
|
||||
| false -> v
|
||||
| true ->
|
||||
let opam_url = { opam_url with hash = Some "MATCHES_EXPECTED" } in
|
||||
String (OpamUrl.to_string opam_url))
|
||||
| otherwise -> otherwise
|
||||
;;
|
||||
|
||||
let update_used ~commit = function
|
||||
| Option (Some (List xs)) ->
|
||||
let xs =
|
||||
List.map xs ~f:(function
|
||||
| Variant (("opam_repo_serializable" as u), [ source ]) ->
|
||||
let source = update_source ~commit source in
|
||||
Variant (u, [ source ])
|
||||
| otherwise -> otherwise)
|
||||
in
|
||||
Option (Some (List xs))
|
||||
| otherwise -> otherwise
|
||||
;;
|
||||
|
||||
let update_repositories ~commit = function
|
||||
| Record xs ->
|
||||
let xs =
|
||||
List.map xs ~f:(function
|
||||
| ("used" as u), dyn -> u, update_used ~commit dyn
|
||||
| otherwise -> otherwise)
|
||||
in
|
||||
Record xs
|
||||
| otherwise -> otherwise
|
||||
;;
|
||||
|
||||
let update_lock_dir_dyn ~commit = function
|
||||
| Record xs ->
|
||||
let xs =
|
||||
List.map xs ~f:(function
|
||||
| ("repos" as u), dyn -> u, update_repositories ~commit dyn
|
||||
| otherwise -> otherwise)
|
||||
in
|
||||
Record xs
|
||||
| otherwise -> otherwise
|
||||
;;
|
||||
end
|
||||
|
||||
let lock_dir_encode_decode_round_trip_test ?commit ~lock_dir_path ~lock_dir () =
|
||||
let lock_dir_path = Path.Source.of_string lock_dir_path in
|
||||
Lock_dir.Write_disk.(
|
||||
prepare ~portable_lock_dir:false ~lock_dir_path ~files:Package_name.Map.empty lock_dir
|
||||
|> commit);
|
||||
let lock_dir_round_tripped =
|
||||
try Lock_dir.read_disk_exn lock_dir_path with
|
||||
| User_error.E _ as exn ->
|
||||
let metadata_path =
|
||||
Path.Source.relative lock_dir_path Lock_dir.metadata_filename |> Path.source
|
||||
in
|
||||
let metadata_file_contents = Io.read_file metadata_path in
|
||||
print_endline
|
||||
"Failed to parse lockdir. Dumping raw metadata file to assist debugging.";
|
||||
print_endline metadata_file_contents;
|
||||
Exn.raise exn
|
||||
in
|
||||
let lock_dir_round_tripped', lock_dir' =
|
||||
Lock_dir.remove_locs lock_dir_round_tripped, Lock_dir.remove_locs lock_dir
|
||||
in
|
||||
if Lock_dir.equal lock_dir_round_tripped' lock_dir'
|
||||
then print_endline "lockdir matches after roundtrip:"
|
||||
else (
|
||||
print_endline "lockdir doesn't match after roundtrip:";
|
||||
print_endline (Lock_dir.to_dyn lock_dir |> Dyn.to_string));
|
||||
let dyn_lock_dir = Lock_dir.to_dyn lock_dir_round_tripped in
|
||||
let dyn_lock_dir =
|
||||
match commit with
|
||||
| None -> dyn_lock_dir
|
||||
| Some commit -> Update.update_lock_dir_dyn ~commit dyn_lock_dir
|
||||
in
|
||||
print_endline (dyn_lock_dir |> Dyn.to_string)
|
||||
;;
|
||||
|
||||
let run thunk =
|
||||
let on_event _config _event = () in
|
||||
let config : Scheduler.Config.t =
|
||||
{ concurrency = 1; stats = None; print_ctrl_c_warning = false; watch_exclusions = [] }
|
||||
in
|
||||
Scheduler.Run.go config ~on_event thunk
|
||||
;;
|
||||
|
||||
let%expect_test "encode/decode round trip test for lockdir with no deps" =
|
||||
lock_dir_encode_decode_round_trip_test
|
||||
~lock_dir_path:"empty_lock_dir"
|
||||
~lock_dir:
|
||||
(Lock_dir.create_latest_version
|
||||
Package_name.Map.empty
|
||||
~local_packages:[]
|
||||
~ocaml:None
|
||||
~repos:None
|
||||
~expanded_solver_variable_bindings:Expanded_variable_bindings.empty
|
||||
~solved_for_platform:None)
|
||||
();
|
||||
[%expect
|
||||
{|
|
||||
lockdir matches after roundtrip:
|
||||
{ version = (0, 1)
|
||||
; dependency_hash = None
|
||||
; packages = map {}
|
||||
; ocaml = None
|
||||
; repos = { complete = true; used = None }
|
||||
; expanded_solver_variable_bindings =
|
||||
{ variable_values = []; unset_variables = [] }
|
||||
; solved_for_platforms = ("<none>:1", [])
|
||||
}
|
||||
|}]
|
||||
;;
|
||||
|
||||
let empty_package name ~version =
|
||||
{ Lock_dir.Pkg.build_command = Lock_dir.Conditional_choice.empty
|
||||
; install_command = Lock_dir.Conditional_choice.empty
|
||||
; depends = Lock_dir.Conditional_choice.empty
|
||||
; depexts = []
|
||||
; info =
|
||||
{ Lock_dir.Pkg_info.name
|
||||
; version
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
;;
|
||||
|
||||
let%expect_test "encode/decode round trip test for lockdir with simple deps" =
|
||||
lock_dir_encode_decode_round_trip_test
|
||||
~lock_dir_path:"simple_lock_dir"
|
||||
~lock_dir:
|
||||
(let mk_pkg_basic ~name ~version =
|
||||
let name = Package_name.of_string name in
|
||||
name, empty_package name ~version
|
||||
in
|
||||
Lock_dir.create_latest_version
|
||||
~local_packages:[]
|
||||
~ocaml:(Some (Loc.none, Package_name.of_string "ocaml"))
|
||||
~repos:None
|
||||
~expanded_solver_variable_bindings:
|
||||
{ Expanded_variable_bindings.variable_values =
|
||||
[ Package_variable_name.os, Variable_value.string "linux" ]
|
||||
; unset_variables = [ Package_variable_name.os_family ]
|
||||
}
|
||||
~solved_for_platform:None
|
||||
(Package_name.Map.of_list_exn
|
||||
[ mk_pkg_basic ~name:"foo" ~version:(Package_version.of_string "0.1.0")
|
||||
; mk_pkg_basic ~name:"bar" ~version:(Package_version.of_string "0.2.0")
|
||||
]))
|
||||
();
|
||||
[%expect
|
||||
{|
|
||||
lockdir matches after roundtrip:
|
||||
{ version = (0, 1)
|
||||
; dependency_hash = None
|
||||
; packages =
|
||||
map
|
||||
{ "bar" :
|
||||
map
|
||||
{ "0.2.0" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "bar"
|
||||
; version = "0.2.0"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
; "foo" :
|
||||
map
|
||||
{ "0.1.0" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "foo"
|
||||
; version = "0.1.0"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
}
|
||||
; ocaml = Some ("simple_lock_dir/lock.dune:3", "ocaml")
|
||||
; repos = { complete = true; used = None }
|
||||
; expanded_solver_variable_bindings =
|
||||
{ variable_values = [ ("os", "linux") ]
|
||||
; unset_variables = [ "os-family" ]
|
||||
}
|
||||
; solved_for_platforms = ("<none>:1", [])
|
||||
}
|
||||
|}]
|
||||
;;
|
||||
|
||||
let%expect_test "encode/decode round trip test for lockdir with complex deps" =
|
||||
let module Action = Dune_lang.Action in
|
||||
let module String_with_vars = Dune_lang.String_with_vars in
|
||||
let make_conditional value =
|
||||
Lock_dir.Conditional_choice.singleton Dune_pkg.Solver_env.empty value
|
||||
in
|
||||
let lock_dir =
|
||||
let pkg_a =
|
||||
let name = Package_name.of_string "a" in
|
||||
let extra_source : Source.t =
|
||||
Source.external_copy (Loc.none, Path.External.of_string "/tmp/a")
|
||||
in
|
||||
( name
|
||||
, let pkg = empty_package name ~version:(Package_version.of_string "0.1.0") in
|
||||
{ pkg with
|
||||
build_command =
|
||||
make_conditional
|
||||
(Lock_dir.Build_command.Action
|
||||
Action.(Progn [ Echo [ String_with_vars.make_text Loc.none "hello" ] ]))
|
||||
; install_command =
|
||||
make_conditional
|
||||
(Action.System
|
||||
(* String_with_vars.t doesn't round trip so we have to set
|
||||
[quoted] if the string would be quoted *)
|
||||
(String_with_vars.make_text ~quoted:true Loc.none "echo 'world'"))
|
||||
; info =
|
||||
{ pkg.info with
|
||||
dev = false
|
||||
; source = Some extra_source
|
||||
; extra_sources =
|
||||
[ Path.Local.of_string "one", extra_source
|
||||
; ( Path.Local.of_string "two"
|
||||
, { url = Loc.none, OpamUrl.of_string "file://randomurl"
|
||||
; checksum = None
|
||||
} )
|
||||
]
|
||||
}
|
||||
; exported_env =
|
||||
[ { Action.Env_update.op = Eq
|
||||
; var = "foo"
|
||||
; value = String_with_vars.make_text Loc.none "bar"
|
||||
}
|
||||
]
|
||||
} )
|
||||
in
|
||||
let pkg_b =
|
||||
let name = Package_name.of_string "b" in
|
||||
( name
|
||||
, let pkg = empty_package name ~version:(Package_version.of_string "dev") in
|
||||
{ pkg with
|
||||
install_command = Lock_dir.Conditional_choice.empty
|
||||
; depends = make_conditional [ { Dependency.loc = Loc.none; name = fst pkg_a } ]
|
||||
; info =
|
||||
{ pkg.info with
|
||||
dev = true
|
||||
; source =
|
||||
Some
|
||||
{ url = Loc.none, OpamUrl.of_string "https://github.com/foo/b"
|
||||
; checksum =
|
||||
Some
|
||||
( Loc.none
|
||||
, Checksum.of_string
|
||||
"sha256=adfc38f14c0188a2ad80d61451d011d27ab8839b717492d7ad42f7cb911c54c3"
|
||||
)
|
||||
}
|
||||
}
|
||||
} )
|
||||
in
|
||||
let pkg_c =
|
||||
let name = Package_name.of_string "c" in
|
||||
( name
|
||||
, let pkg = empty_package name ~version:(Package_version.of_string "0.2") in
|
||||
{ pkg with
|
||||
depends =
|
||||
make_conditional
|
||||
[ { Dependency.loc = Loc.none; name = fst pkg_a }
|
||||
; { Dependency.loc = Loc.none; name = fst pkg_b }
|
||||
]
|
||||
; info =
|
||||
{ pkg.info with
|
||||
dev = false
|
||||
; source =
|
||||
Some
|
||||
{ url = Loc.none, OpamUrl.of_string "https://github.com/foo/c"
|
||||
; checksum = None
|
||||
}
|
||||
}
|
||||
} )
|
||||
in
|
||||
let opam_repo =
|
||||
let source = Some "https://github.com/ocaml/dune" in
|
||||
Opam_repo.Private.create ~source
|
||||
in
|
||||
Lock_dir.create_latest_version
|
||||
~local_packages:[]
|
||||
~ocaml:(Some (Loc.none, Package_name.of_string "ocaml"))
|
||||
~repos:(Some [ opam_repo ])
|
||||
~expanded_solver_variable_bindings:Expanded_variable_bindings.empty
|
||||
~solved_for_platform:None
|
||||
(Package_name.Map.of_list_exn [ pkg_a; pkg_b; pkg_c ])
|
||||
in
|
||||
lock_dir_encode_decode_round_trip_test ~lock_dir_path:"complex_lock_dir" ~lock_dir ();
|
||||
[%expect
|
||||
{|
|
||||
lockdir matches after roundtrip:
|
||||
{ version = (0, 1)
|
||||
; dependency_hash = None
|
||||
; packages =
|
||||
map
|
||||
{ "a" :
|
||||
map
|
||||
{ "0.1.0" :
|
||||
{ build_command =
|
||||
[ { condition = [ map {} ]
|
||||
; value = Action [ "progn"; [ "echo"; "hello" ] ]
|
||||
}
|
||||
]
|
||||
; install_command =
|
||||
[ { condition = [ map {} ]
|
||||
; value = [ "system"; "echo 'world'" ]
|
||||
}
|
||||
]
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "a"
|
||||
; version = "0.1.0"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source =
|
||||
Some { url = "file:///tmp/a"; checksum = None }
|
||||
; extra_sources =
|
||||
[ ("one", { url = "file:///tmp/a"; checksum = None })
|
||||
; ("two",
|
||||
{ url = "file://randomurl"; checksum = None })
|
||||
]
|
||||
}
|
||||
; exported_env = [ { op = "="; var = "foo"; value = "bar" } ]
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
; "b" :
|
||||
map
|
||||
{ "dev" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends =
|
||||
[ { condition = [ map {} ]
|
||||
; value =
|
||||
[ { loc = "complex_lock_dir/b.pkg:3"; name = "a" }
|
||||
]
|
||||
}
|
||||
]
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "b"
|
||||
; version = "dev"
|
||||
; dev = true
|
||||
; avoid = false
|
||||
; source =
|
||||
Some
|
||||
{ url = "https://github.com/foo/b"
|
||||
; checksum =
|
||||
Some
|
||||
"sha256=adfc38f14c0188a2ad80d61451d011d27ab8839b717492d7ad42f7cb911c54c3"
|
||||
}
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
; "c" :
|
||||
map
|
||||
{ "0.2" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends =
|
||||
[ { condition = [ map {} ]
|
||||
; value =
|
||||
[ { loc = "complex_lock_dir/c.pkg:3"; name = "a" }
|
||||
; { loc = "complex_lock_dir/c.pkg:3"; name = "b" }
|
||||
]
|
||||
}
|
||||
]
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "c"
|
||||
; version = "0.2"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source =
|
||||
Some
|
||||
{ url = "https://github.com/foo/c"
|
||||
; checksum = None
|
||||
}
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
}
|
||||
; ocaml = Some ("complex_lock_dir/lock.dune:3", "ocaml")
|
||||
; repos =
|
||||
{ complete = true
|
||||
; used = Some [ opam_repo_serializable "https://github.com/ocaml/dune" ]
|
||||
}
|
||||
; expanded_solver_variable_bindings =
|
||||
{ variable_values = []; unset_variables = [] }
|
||||
; solved_for_platforms = ("<none>:1", [])
|
||||
}
|
||||
|}]
|
||||
;;
|
||||
|
||||
let%expect_test "encode/decode round trip test with locked repo revision" =
|
||||
let open Fiber.O in
|
||||
let module Action = Dune_lang.Action in
|
||||
let module String_with_vars = Dune_lang.String_with_vars in
|
||||
run (fun () ->
|
||||
let cwd = Path.External.cwd () |> Path.external_ in
|
||||
let other_dir = Path.relative cwd "random-git-repo" in
|
||||
let+ git_hash = Rev_store_tests.create_repo_at other_dir in
|
||||
let lock_dir =
|
||||
let pkg_a =
|
||||
let name = Package_name.of_string "a" in
|
||||
name, empty_package name ~version:(Package_version.of_string "0.1.0")
|
||||
in
|
||||
let pkg_b =
|
||||
let name = Package_name.of_string "b" in
|
||||
name, empty_package name ~version:(Package_version.of_string "dev")
|
||||
in
|
||||
let pkg_c =
|
||||
let name = Package_name.of_string "c" in
|
||||
name, empty_package name ~version:(Package_version.of_string "0.2")
|
||||
in
|
||||
let opam_repo =
|
||||
let source = Some (sprintf "https://github.com/ocaml/dune#%s" git_hash) in
|
||||
Opam_repo.Private.create ~source
|
||||
in
|
||||
Lock_dir.create_latest_version
|
||||
~local_packages:[]
|
||||
~ocaml:(Some (Loc.none, Package_name.of_string "ocaml"))
|
||||
~repos:(Some [ opam_repo ])
|
||||
~expanded_solver_variable_bindings:Expanded_variable_bindings.empty
|
||||
~solved_for_platform:None
|
||||
(Package_name.Map.of_list_exn [ pkg_a; pkg_b; pkg_c ])
|
||||
in
|
||||
lock_dir_encode_decode_round_trip_test
|
||||
~commit:git_hash
|
||||
~lock_dir_path:"complex_lock_dir"
|
||||
~lock_dir
|
||||
());
|
||||
[%expect
|
||||
{|
|
||||
lockdir matches after roundtrip:
|
||||
{ version = (0, 1)
|
||||
; dependency_hash = None
|
||||
; packages =
|
||||
map
|
||||
{ "a" :
|
||||
map
|
||||
{ "0.1.0" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "a"
|
||||
; version = "0.1.0"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
; "b" :
|
||||
map
|
||||
{ "dev" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "b"
|
||||
; version = "dev"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
; "c" :
|
||||
map
|
||||
{ "0.2" :
|
||||
{ build_command = []
|
||||
; install_command = []
|
||||
; depends = []
|
||||
; depexts = []
|
||||
; info =
|
||||
{ name = "c"
|
||||
; version = "0.2"
|
||||
; dev = false
|
||||
; avoid = false
|
||||
; source = None
|
||||
; extra_sources = []
|
||||
}
|
||||
; exported_env = []
|
||||
; enabled_on_platforms = []
|
||||
}
|
||||
}
|
||||
}
|
||||
; ocaml = Some ("complex_lock_dir/lock.dune:3", "ocaml")
|
||||
; repos =
|
||||
{ complete = true
|
||||
; used =
|
||||
Some
|
||||
[ opam_repo_serializable
|
||||
"https://github.com/ocaml/dune#MATCHES_EXPECTED"
|
||||
]
|
||||
}
|
||||
; expanded_solver_variable_bindings =
|
||||
{ variable_values = []; unset_variables = [] }
|
||||
; solved_for_platforms = ("<none>:1", [])
|
||||
}
|
||||
|}]
|
||||
;;
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
open Stdune
|
||||
module Scheduler = Dune_engine.Scheduler
|
||||
module Checksum = Dune_pkg.Checksum
|
||||
module Fetch = Dune_pkg.Fetch
|
||||
|
||||
let plaintext_md = "tar-inputs/plaintext.md"
|
||||
let () = Dune_tests_common.init ()
|
||||
|
||||
let url ~port ~filename =
|
||||
let localhost = Unix.inet_addr_loopback |> Unix.string_of_inet_addr in
|
||||
Format.sprintf "http://%s:%d/%s" localhost port filename |> OpamUrl.of_string
|
||||
;;
|
||||
|
||||
let calculate_checksum ~filename = OpamHash.compute filename |> Checksum.of_opam_hash
|
||||
|
||||
let wrong_checksum =
|
||||
OpamHash.compute_from_string "random content" |> Checksum.of_opam_hash
|
||||
;;
|
||||
|
||||
let archive = "tarball.tar.gz"
|
||||
|
||||
let subdir destination =
|
||||
let ext = Path.External.of_filename_relative_to_initial_cwd destination in
|
||||
Path.external_ ext
|
||||
;;
|
||||
|
||||
let serve_once ~filename =
|
||||
let host = Unix.inet_addr_loopback in
|
||||
let addr = Unix.ADDR_INET (host, 0) in
|
||||
let server = Http.Server.make addr in
|
||||
Http.Server.start server;
|
||||
let port = Http.Server.port server in
|
||||
let thread =
|
||||
Thread.create
|
||||
(fun server ->
|
||||
Http.Server.accept server ~f:(fun session ->
|
||||
let () = Http.Server.accept_request session in
|
||||
Http.Server.respond_file session ~file:filename);
|
||||
Http.Server.stop server)
|
||||
server
|
||||
in
|
||||
port, thread
|
||||
;;
|
||||
|
||||
let download ?(reproducible = true) ~unpack ~port ~filename ~target ?checksum () =
|
||||
let open Fiber.O in
|
||||
let url = url ~port ~filename in
|
||||
let* res = Fetch.fetch ~unpack ~checksum ~target ~url:(Loc.none, url) in
|
||||
match res with
|
||||
| Error (Unavailable None) ->
|
||||
let errs = [ Pp.text "Failure while downloading" ] in
|
||||
User_error.raise ~loc:Loc.none errs
|
||||
| Error (Unavailable (Some msg)) ->
|
||||
User_error.raise ~loc:Loc.none [ User_message.pp msg ]
|
||||
| Error (Checksum_mismatch actual_checksum) ->
|
||||
let expected_checksum = Option.value_exn checksum in
|
||||
User_error.raise
|
||||
~loc:Loc.none
|
||||
[ Pp.text "Expected checksum was"
|
||||
; Pp.verbatim @@ Checksum.to_string expected_checksum
|
||||
; Pp.text "but got"
|
||||
; (if reproducible
|
||||
then Pp.verbatim @@ Checksum.to_string actual_checksum
|
||||
else Pp.text "<REDACTED>")
|
||||
]
|
||||
| Ok () ->
|
||||
print_endline "Done downloading";
|
||||
Fiber.return ()
|
||||
;;
|
||||
|
||||
let run thunk =
|
||||
let on_event _config _event = () in
|
||||
let config : Scheduler.Config.t =
|
||||
{ concurrency = 1; stats = None; print_ctrl_c_warning = false; watch_exclusions = [] }
|
||||
in
|
||||
Scheduler.Run.go config ~on_event (fun () ->
|
||||
let open Fiber.O in
|
||||
Rev_store_tests.git_init_and_config_user (Path.of_string ".") >>> thunk ())
|
||||
;;
|
||||
|
||||
let%expect_test "downloading simple file" =
|
||||
let filename = plaintext_md in
|
||||
let port, server = serve_once ~filename in
|
||||
let destination = "destination.md" in
|
||||
run
|
||||
(download
|
||||
~unpack:false
|
||||
~port
|
||||
~filename:""
|
||||
~target:(subdir destination)
|
||||
~checksum:(calculate_checksum ~filename));
|
||||
Thread.join server;
|
||||
let served_content = Io.String_path.read_file filename in
|
||||
let downloaded_content = Io.String_path.read_file destination in
|
||||
Printf.printf
|
||||
"Served file:\n%s\nDownloaded file:\n%s\nEqual: %B"
|
||||
served_content
|
||||
downloaded_content
|
||||
(String.equal served_content downloaded_content);
|
||||
[%expect
|
||||
{|
|
||||
Done downloading
|
||||
Served file:
|
||||
Plaintext
|
||||
=========
|
||||
|
||||
This is a plaintext file to make sure that downloading files from the internal
|
||||
webserver works as desired.
|
||||
|
||||
Downloaded file:
|
||||
Plaintext
|
||||
=========
|
||||
|
||||
This is a plaintext file to make sure that downloading files from the internal
|
||||
webserver works as desired.
|
||||
|
||||
Equal: true |}]
|
||||
;;
|
||||
|
||||
let%expect_test "downloading but the checksums don't match" =
|
||||
let port, server = serve_once ~filename:plaintext_md in
|
||||
let destination = "destination.md" in
|
||||
run
|
||||
(download
|
||||
~unpack:false
|
||||
~port
|
||||
~filename:""
|
||||
~target:(subdir destination)
|
||||
~checksum:wrong_checksum);
|
||||
Thread.join server;
|
||||
print_endline "Finished successfully?";
|
||||
[%expect.unreachable]
|
||||
[@@expect.uncaught_exn
|
||||
{|
|
||||
(Dune_util__Report_error.Already_reported)
|
||||
Trailing output
|
||||
---------------
|
||||
Error: Expected checksum was
|
||||
md5=c533195dc4253503071a19d42f08e877
|
||||
but got
|
||||
md5=cbe78b067d4739684e86edfd2cb518bd |}]
|
||||
;;
|
||||
|
||||
let%expect_test "downloading, without any checksum" =
|
||||
let port, server = serve_once ~filename:plaintext_md in
|
||||
let destination = "destination.md" in
|
||||
run (download ~unpack:false ~port ~filename:"" ~target:(subdir destination));
|
||||
Thread.join server;
|
||||
print_endline "Finished successfully, no checksum verification";
|
||||
[%expect
|
||||
{|
|
||||
Done downloading
|
||||
Finished successfully, no checksum verification |}]
|
||||
;;
|
||||
|
||||
let%expect_test "downloading, tarball" =
|
||||
let port, server = serve_once ~filename:archive in
|
||||
let destination = "tarball" in
|
||||
run
|
||||
(download
|
||||
(* the tar utility that produces [filename] isn't portable and/or
|
||||
deterministic enough to print the actual checksum *)
|
||||
~reproducible:false
|
||||
~unpack:true
|
||||
~checksum:wrong_checksum
|
||||
~port
|
||||
~filename:""
|
||||
~target:(subdir destination));
|
||||
Thread.join server;
|
||||
print_endline "Finished successfully, no checksum verification";
|
||||
[%expect.unreachable]
|
||||
[@@expect.uncaught_exn
|
||||
{|
|
||||
(Dune_util__Report_error.Already_reported)
|
||||
Trailing output
|
||||
---------------
|
||||
Error: Expected checksum was
|
||||
md5=c533195dc4253503071a19d42f08e877
|
||||
but got
|
||||
<REDACTED> |}]
|
||||
;;
|
||||
|
||||
let%expect_test "downloading, tarball with no checksum match" =
|
||||
(* This test ensures that the contents of the extracted tarball are in the
|
||||
correct location. *)
|
||||
let port, server = serve_once ~filename:archive in
|
||||
let target = subdir "tarball" in
|
||||
run (download ~reproducible:false ~unpack:true ~port ~filename:"" ~target);
|
||||
Thread.join server;
|
||||
print_endline "Finished successfully, no checksum verification";
|
||||
(* print all the files in the target directory *)
|
||||
let () =
|
||||
print_endline "------\nfiles in target dir:";
|
||||
Dune_engine.No_io.Path.Untracked.readdir_unsorted target
|
||||
|> Result.value ~default:[]
|
||||
|> List.sort ~compare:String.compare
|
||||
|> List.iter ~f:print_endline
|
||||
in
|
||||
[%expect
|
||||
{|
|
||||
Done downloading
|
||||
Finished successfully, no checksum verification
|
||||
------
|
||||
files in target dir:
|
||||
file2.md
|
||||
plaintext.md |}]
|
||||
;;
|
||||
|
||||
let download_git rev_store url ~target =
|
||||
let open Fiber.O in
|
||||
Rev_store_tests.git_init_and_config_user (Path.of_string ".")
|
||||
>>> Fetch.fetch_git rev_store ~target ~url:(Loc.none, url)
|
||||
>>| function
|
||||
| Error _ ->
|
||||
let errs = [ Pp.text "Failure while downloading" ] in
|
||||
User_error.raise ~loc:Loc.none errs
|
||||
| Ok () -> ()
|
||||
;;
|
||||
|
||||
let%expect_test "downloading via git" =
|
||||
let source = subdir "source-repository" in
|
||||
let url = OpamUrl.parse (sprintf "git+file://%s" (Path.to_string source)) in
|
||||
let rev_store_dir = subdir "rev-store" in
|
||||
let target = subdir "checkout-into-here" in
|
||||
(* The file at [entry] is created by [create_repo_at] *)
|
||||
let entry = Path.relative target "entry" in
|
||||
Path.mkdir_p target;
|
||||
run (fun () ->
|
||||
let open Fiber.O in
|
||||
let* rev_store = Dune_pkg.Rev_store.load_or_create ~dir:rev_store_dir in
|
||||
let* (_commit : string) = Rev_store_tests.create_repo_at source in
|
||||
let+ () = download_git rev_store url ~target in
|
||||
print_endline (Io.read_file entry));
|
||||
[%expect {| just some content |}]
|
||||
;;
|
||||
|
||||
let%expect_test "attempting to download an invalid git url" =
|
||||
let source = subdir "source" in
|
||||
let url = OpamUrl.parse "git+file://foo/bar" in
|
||||
let rev_store_dir = subdir "rev-store-dir" in
|
||||
let target = subdir "target" in
|
||||
let entry = Path.relative target "e" in
|
||||
run (fun () ->
|
||||
let open Fiber.O in
|
||||
let* rev_store = Dune_pkg.Rev_store.load_or_create ~dir:rev_store_dir in
|
||||
let* (_commit : string) = Rev_store_tests.create_repo_at source in
|
||||
let+ () = download_git rev_store url ~target in
|
||||
print_endline (Io.read_file entry));
|
||||
[%expect.unreachable]
|
||||
[@@expect.uncaught_exn
|
||||
{|
|
||||
(Dune_util__Report_error.Already_reported)
|
||||
Trailing output
|
||||
---------------
|
||||
fatal: '/bar' does not appear to be a git repository
|
||||
fatal: Could not read from remote repository.
|
||||
|
||||
Please make sure you have the correct access rights
|
||||
and the repository exists.
|
||||
Error: Failed to run external command:
|
||||
'git ls-remote "file://foo/bar"'
|
||||
Hint: Check that this Git URL in the project configuration is correct:
|
||||
"file://foo/bar" |}]
|
||||
;;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
module T4 = struct
|
||||
type ('a, 'b, 'c, 'd) t = 'a * 'b * 'c * 'd
|
||||
|
||||
let to_dyn f g h i (a, b, c, d) = Dyn.Tuple [ f a; g b; h c; i d ]
|
||||
end
|
||||
|
||||
module Git_config_parser = struct
|
||||
let to_dyn = T4.to_dyn Dyn.string (Dyn.option Dyn.string) Dyn.string Dyn.string
|
||||
end
|
||||
|
||||
let print_or_fail l =
|
||||
match Dune_pkg.Rev_store.At_rev.Config.parse l with
|
||||
| Some v -> print_endline @@ Dyn.to_string @@ Git_config_parser.to_dyn v
|
||||
| None -> Printf.eprintf "Failed to parse %S\n" l
|
||||
;;
|
||||
|
||||
let%expect_test "parsing simple section" =
|
||||
let config = "foo.bar=baz" in
|
||||
print_or_fail config;
|
||||
[%expect
|
||||
{|
|
||||
("foo", None, "bar", "baz")
|
||||
|}]
|
||||
;;
|
||||
|
||||
let%expect_test "parsing with arguments" =
|
||||
let config = "foo.bar.baz=qux" in
|
||||
print_or_fail config;
|
||||
[%expect
|
||||
{|
|
||||
("foo", Some "bar", "baz", "qux")
|
||||
|}]
|
||||
;;
|
||||
|
||||
let%expect_test "parsing with dots in name" =
|
||||
let config = "branch.compat-5.0-dune-2.9.remote=origin" in
|
||||
print_or_fail config;
|
||||
[%expect
|
||||
{|
|
||||
("branch", Some "compat-5.0-dune-2.9", "remote", "origin")
|
||||
|}]
|
||||
;;
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
open Stdune
|
||||
open Fiber.O
|
||||
module Scheduler = Dune_engine.Scheduler
|
||||
module Process = Dune_engine.Process
|
||||
module Display = Dune_engine.Display
|
||||
module Rev_store = Dune_pkg.Rev_store
|
||||
module Opam_repo = Dune_pkg.Opam_repo
|
||||
module Vcs = Dune_vcs.Vcs
|
||||
|
||||
let () = Dune_tests_common.init ()
|
||||
|
||||
let run thunk =
|
||||
let on_event _config _event = () in
|
||||
let config : Scheduler.Config.t =
|
||||
{ concurrency = 1; stats = None; print_ctrl_c_warning = false; watch_exclusions = [] }
|
||||
in
|
||||
Scheduler.Run.go config ~on_event thunk
|
||||
;;
|
||||
|
||||
let display = Display.Quiet
|
||||
let output_limit = Sys.max_string_length
|
||||
let make_stdout () = Process.Io.make_stdout ~output_on_success:Swallow ~output_limit
|
||||
let make_stderr () = Process.Io.make_stderr ~output_on_success:Swallow ~output_limit
|
||||
|
||||
let git ~dir =
|
||||
let stdout_to = make_stdout () in
|
||||
let stderr_to = make_stdout () in
|
||||
let git = Lazy.force Vcs.git in
|
||||
let failure_mode = Process.Failure_mode.Strict in
|
||||
fun args -> Process.run ~dir ~display ~stdout_to ~stderr_to failure_mode git args
|
||||
;;
|
||||
|
||||
let git_out ~dir =
|
||||
let stderr_to = make_stdout () in
|
||||
let git = Lazy.force Vcs.git in
|
||||
let failure_mode = Process.Failure_mode.Strict in
|
||||
fun args -> Process.run_capture_line ~dir ~display ~stderr_to failure_mode git args
|
||||
;;
|
||||
|
||||
let git_init_and_config_user dir =
|
||||
Path.mkdir_p dir;
|
||||
let git = git ~dir in
|
||||
git [ "init" ]
|
||||
>>> git [ "config"; "user.name"; "\"Test Name\"" ]
|
||||
>>> git [ "config"; "user.email"; "\"test@example.com\"" ]
|
||||
;;
|
||||
|
||||
let create_repo_at dir =
|
||||
let git = git ~dir in
|
||||
let git_out = git_out ~dir in
|
||||
let* () = git_init_and_config_user dir in
|
||||
let entry_name = "entry" in
|
||||
let entry = Path.relative dir entry_name in
|
||||
Io.write_lines entry [ "just some content" ];
|
||||
let* () = git [ "add"; entry_name ] in
|
||||
let* () = git [ "commit"; "-m 'Initial commit'" ] in
|
||||
git_out [ "rev-parse"; "HEAD" ]
|
||||
;;
|
||||
|
||||
let%expect_test "adding remotes" =
|
||||
let cwd = Path.External.cwd () |> Path.external_ in
|
||||
let dir = Path.relative cwd "git-repo" in
|
||||
run (fun () ->
|
||||
let* rev_store = Rev_store.load_or_create ~dir in
|
||||
let remote_path = Path.relative cwd "git-remote" in
|
||||
let* _head = create_repo_at remote_path in
|
||||
let opam_url = remote_path |> Path.to_string |> OpamUrl.parse in
|
||||
Dune_pkg.OpamUrl.resolve opam_url ~loc:Loc.none rev_store
|
||||
>>= function
|
||||
| Error _ -> Fiber.return @@ print_endline "Unable to find revision"
|
||||
| Ok r ->
|
||||
print_endline "Successfully found remote";
|
||||
Dune_pkg.OpamUrl.fetch_revision opam_url ~loc:Loc.none r rev_store
|
||||
>>| (function
|
||||
| Error _ -> print_endline "Unable to fetch revision"
|
||||
| Ok _ -> print_endline "successfully fetched revision"));
|
||||
[%expect
|
||||
{|
|
||||
Successfully found remote
|
||||
successfully fetched revision
|
||||
|}]
|
||||
;;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Plaintext
|
||||
=========
|
||||
|
||||
This is a plaintext file to make sure that downloading files from the internal
|
||||
webserver works as desired.
|
||||
Loading…
Add table
Add a link
Reference in a new issue