run
1 #!/usr/bin/env python3 2 3 """ 4 Build arti and rpc client library, and run RPC integration tests. 5 6 ENVIRONMENT VARIABLES: 7 8 - CARGO: the cargo binary to use. Defaults to "cargo". 9 - PYTHON3: path to a python binary to use. Defaults to `sys.executable` 10 - ARTI_RPC_TEST_DIR: A location in which to store arti's state and config. 11 Defaults to ".arti_rpc_test" at the top level of this git repo. 12 13 ARGUMENTS: 14 15 - `--arti-dir=DIR`: Override ARTI_RPC_TEST_DIR. 16 """ 17 18 from __future__ import annotations 19 20 import argparse 21 import os 22 import sys 23 import subprocess 24 25 26 def parent(path: str, n: int = 1): 27 """ 28 Return the parent of (the parent of (... the directory of path)). 29 30 The number of "parent of"s is controlled by "n" 31 """ 32 for _ in range(n): 33 path = os.path.split(path)[0] 34 return path 35 36 37 def cargo_build(packages: list[str], extra_flags: list[str] = []): 38 """ 39 Use cargo to build all of the rust packages in `packages`, 40 passing `extra_flags` on the command line. 41 """ 42 args = [ 43 CARGO, 44 "build", 45 "--profile", 46 CARGO_PROFILE, 47 ] 48 for p in packages: 49 args.extend(["-p", p]) 50 args.extend(extra_flags) 51 52 outcome = subprocess.run(args, cwd=TOPLEVEL) 53 outcome.check_returncode() 54 55 56 ###### 57 # Parse the command line. 58 59 parser = argparse.ArgumentParser( 60 prog="run", description="Invoke Arti RPC integration tests" 61 ) 62 parser.add_argument("--arti-dir", help="Location for Arti proxy storage and config") 63 parser.add_argument("remainder", nargs="*", help="Passed directly to arti_rpc_tests") 64 args = parser.parse_args() 65 66 ###### 67 # Set up locations and paths from the environment. 68 69 CARGO_PROFILE = "quicktest" 70 TOPLEVEL = os.path.abspath(parent(os.path.dirname(__file__), n=3)) 71 CARGO = os.environ.get("CARGO", "cargo") 72 PYTHON3 = os.environ.get("PYTHON3", sys.executable) 73 74 lib_extension = {"win32": "dll", "darwin": "dylib"}.get(sys.platform, "so") 75 76 ARTI = os.path.join(TOPLEVEL, "target", CARGO_PROFILE, "arti") 77 LIBRPC = os.path.join( 78 TOPLEVEL, "target", CARGO_PROFILE, "libarti_rpc_client_core." + lib_extension 79 ) 80 PYRPC = os.path.join(TOPLEVEL, "python", "arti_rpc", "src") 81 PYRPC_TESTS = os.path.join(TOPLEVEL, "python", "arti_rpc_tests", "src") 82 83 if args.arti_dir is not None: 84 ARTI_RPC_TEST_DIR = args.arti_dir 85 else: 86 ARTI_RPC_TEST_DIR = os.environ.get( 87 "ARTI_RPC_TEST_DIR", os.path.join(TOPLEVEL, ".arti_rpc_test") 88 ) 89 os.makedirs(ARTI_RPC_TEST_DIR, mode=0o700, exist_ok=True) 90 91 ##### 92 # Build Arti, and make sure it is there. 93 94 cargo_build(["arti", "arti-rpc-client-core"], ["--all-features"]) 95 96 if not os.path.exists(ARTI): 97 print("whoops no arti at", ARTI) 98 sys.exit(1) 99 if not os.path.exists(ARTI): 100 print("whoops no librpc at", LIBRPC) 101 sys.exit(1) 102 103 ##### 104 # Set up the environment expected by `arti_rpc_tests`. 105 106 os.environ["ARTI"] = ARTI 107 os.environ["LIBARTI_RPC_CLIENT_CORE"] = LIBRPC 108 os.environ["ARTI_RPC_TEST_DIR"] = ARTI_RPC_TEST_DIR 109 110 # Note that we're prepending these locations to PYTHONPATH. 111 # We want to use these versions, not ones that might happen to be installed. 112 pathelts = [PYRPC, PYRPC_TESTS] 113 try: 114 pathelts.append(os.environ["PYTHONPATH"]) 115 except KeyError: 116 pass 117 os.environ["PYTHONPATH"] = os.pathsep.join(pathelts) 118 119 # Run `arti_rpc_tests` and wait for it to finish. 120 outcome = subprocess.run([PYTHON3, "-m", "arti_rpc_tests"] + args.remainder) 121 # Give an error if it failed. 122 outcome.check_returncode()