diff --git a/.hgignore b/.hgignore index 6f4d65d08ac0636898dbb9e5525e60ab37dc1d7f_LmhnaWdub3Jl..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_LmhnaWdub3Jl 100644 --- a/.hgignore +++ b/.hgignore @@ -2,4 +2,3 @@ ^tmp/ ^cache/ ^datasets/new.toml - diff --git a/bin/bin-env-util b/bin/bin-env-util new file mode 100755 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_YmluL2Jpbi1lbnYtdXRpbA== --- /dev/null +++ b/bin/bin-env-util @@ -0,0 +1,318 @@ +#!/bin/env python3 +# +# Small tool to manipulaote +import argparse +import os +import subprocess +import sys +import tempfile +import toml + +ERR_CODE_NO_KEY = 1 +ERR_CODE_NO_BIN_ENV_SHELL = 2 +ERR_CODE_NO_BIN_ENV_DESC = 3 +ERR_CODE_EXISTS = 4 +ERR_CODE_NO_SETUP_SCRIPT = 6 +ERR_CODE_SETUP_SCRIPT_FAILED = 7 + +BIN_ENV_FILE = 'bin-env.poulpe' +SHELL_FILE = 'bin-env.shell' + + +def _bin_env_file(env_path): + """given the path of env, return the file of description file""" + return os.path.join(env_path, BIN_ENV_FILE) + + +def create_empty(env_path, method="manual"): + """create a new environ (in a non-ready state)""" + os.makedirs(env_path, exist_ok=True) + base_data = { + 'poulpe-environment': { + 'format-version': 0, + 'environment-type': 'binary', + 'setup-method': method, + }, + 'ready': False, + } + file_path = _bin_env_file(env_path) + if os.path.exists(file_path): + err('This is already a bin-env, aborting') + return ERR_CODE_EXISTS + _write_data(file_path, base_data) + return 0 + + +def setup_one(env_path, script): + if not os.access(script, os.X_OK): + err(f'no executable setup scrip at: "{script}"') + return ERR_CODE_NO_SETUP_SCRIPT + create_empty(env_path, method="script") + script = os.path.abspath(script) + try: + subprocess.check_call(script, cwd=env_path) + except subprocess.CalledProcessError as exc: + err(f'script returned with status {exc.returncode}: {script}') + return ERR_CODE_SETUP_SCRIPT_FAILED + + env_file = _bin_env_file(env_path) + data = _get_data(env_file) + vars_file = os.path.join(env_path, "POULPE-VARS") + if os.path.exists(vars_file): + with open(vars_file) as f: + for line in f: + k, v = line.split('=', 1) + k = k.strip() + v = v.strip() + k = f'bin-env-vars.{k}' + _set_one_value(data, k, v) + _write_data(env_file, data) + return mark_ready(env_path) + + +def mark_ready(env_path): + shell_path = os.path.join(env_path, SHELL_FILE) + if not os.access(shell_path, os.X_OK): + err(f'cannot find an executable file at: "{shell_path}"') + return ERR_CODE_NO_BIN_ENV_SHELL + + path = _bin_env_file(env_path) + data = _get_data(path) + if data is None: + err(f'missing file: "{path}"') + return ERR_CODE_NO_BIN_ENV_DESC + data['ready'] = True + _write_data(path, data) + return 0 + + +def _get_data(path): + try: + with open(path) as f: + return toml.load(f) + except FileNotFoundError: + return None + + +def _write_data(path, data): + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + toml.dump(data, f) + os.replace(f.name, path) + + +def _show_one_level(data, indent=''): + for k, v in sorted(data.items()): + if not isinstance(v, dict): + print(f"{indent}{k} = {v}") + else: + print(f"{indent}{k}:") + _show_one_level(v, indent + ' ') + + +def show(env_path): + path = _bin_env_file(env_path) + data = _get_data(path) + if data is None: + err(f'missing file: "{path}"') + return ERR_CODE_NO_BIN_ENV_DESC + _show_one_level(data) + return 0 + + +def get_value(path, key): + data = _get_data(path) + if data is None: + err(f'missing file: "{path}"') + return ERR_CODE_NO_BIN_ENV_DESC + + key_path = key.split('.') + sub = data + for k in key_path: + sub = sub.get(k) + if sub is None: + return ERR_CODE_NO_KEY + return 0 + + +def _set_one_value(data, key, value): + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + val = sub.setdefault(k, {}) + sub = val + sub[key_path[-1]] = value + + +def set_value(path, key, value): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + _set_one_value(data, key, value) + + _write_data(path, data) + return 0 + + +def del_value(path, key): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + sub = sub.setdefault(k, {}) + sub.pop(key_path[-1], None) + + _write_data(path, data) + return 0 + + +def err(*args, **kwargs): + """print something on stderr""" + print(*args, **kwargs, file=sys.stderr) + + +def _parsers(): + top_parser = argparse.ArgumentParser(prog='poulpe-bin-env-util') + subparsers = top_parser.add_subparsers( + help='available sub-command', + dest='command', + required=True + ) + + # XXX having PATH everywhere is not great + + ### bin-env-util create-empty PATH + cmd_parser = subparsers.add_parser( + 'create-empty', + help='create a new empty bin-env' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the (future) environment", + ) + + ### bin-env-util setup-one-sh PATH SCRIPT + cmd_parser = subparsers.add_parser( + 'setup-one', + help='create a new empty bin-env' + ) + cmd_parser.add_argument( + 'PATH', + help="the path of the environment", + ) + cmd_parser.add_argument( + 'SCRIPT', + help="the path to the script to setup the env", + ) + + ### bin-env-util mark-ready PATH + cmd_parser = subparsers.add_parser( + 'mark-ready', + help='mark a bin-env as ready' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the environment", + ) + + ### bin-env-util show PATH + cmd_parser = subparsers.add_parser( + 'show', + help='Show all data we have about this environment' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the environment", + ) + + ### bin-env-util get PATH KEY + cmd_parser = subparsers.add_parser( + 'get', + help='Show a specific bin-env variable' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the environment", + ) + cmd_parser.add_argument( + 'KEY', + help="the path to the variable", + ) + + ### bin-env-util set PATH KEY VALUE + cmd_parser = subparsers.add_parser( + 'set', + help='Show a specific bin-env variable' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the environment", + ) + cmd_parser.add_argument( + 'KEY', + help="the path to the variable", + ) + cmd_parser.add_argument( + 'VALUE', + help="the value to set", + ) + + ### bin-env-util del PATH KEY + cmd_parser = subparsers.add_parser( + 'del', + help='Show a specific bin-env variable' + ) + cmd_parser.add_argument( + 'PATH', + help="the path to the environment", + ) + cmd_parser.add_argument( + 'KEY', + help="the path to the variable", + ) + + return top_parser + + +def main(args): + parser = _parsers() + param = parser.parse_args(args) + if param.command == 'create-empty': + ret = create_empty(param.PATH) + elif param.command == 'setup-one': + ret = setup_one(param.PATH, param.SCRIPT) + elif param.command == 'mark-ready': + ret = mark_ready(param.PATH) + elif param.command == 'show': + ret = show(param.PATH) + elif param.command == 'get': + ret = get_value( + _bin_env_file(param.PATH), + f'bin-env-vars.{param.KEY}', + ) + elif param.command == 'set': + ret = set_value( + _bin_env_file(param.PATH), + f'bin-env-vars.{param.KEY}', + param.VALUE, + ) + elif param.command == 'del': + ret = del_value( + _bin_env_file(param.PATH), + f'bin-env-vars.{param.KEY}', + ) + else: + assert False + return ret + print(param) + + +if __name__ == "__main__": + ret = main(sys.argv[1:]) + assert ret is not None + sys.exit(ret) diff --git a/bin/diff-result b/bin/diff-result new file mode 100755 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_YmluL2RpZmYtcmVzdWx0 --- /dev/null +++ b/bin/diff-result @@ -0,0 +1,127 @@ +#!/bin/env python3 +# +# Small tool to manipulaote +import argparse +import json +import os +import stat +import subprocess +import sys +import tempfile +import toml + + +ERR_CODE_NO_KEY = 1 +ERR_CODE_NO_BIN_ENV_SHELL = 2 +ERR_CODE_NO_BIN_ENV_DESC = 3 +ERR_CODE_EXISTS = 4 +ERR_CODE_NO_SETUP_SCRIPT = 6 +ERR_CODE_SETUP_SCRIPT_FAILED = 7 + +BIN_ENV_FILE = 'bin-env.poulpe' +DATA_ENV_FILE = 'data-env.poulpe' +SHELL_FILE = 'bin-env.shell' + + +def _bin_env_file(bin_env_path): + """given the path of env, return the file of description file""" + return os.path.join(bin_env_path, BIN_ENV_FILE) + +def _bin_env_script(bin_env_path): + """given the path of env, return the file of description file""" + return os.path.join(bin_env_path, SHELL_FILE) + + +def _data_env_file(data_env_path): + """given the path of env, return the file of description file""" + return os.path.join(data_env_path, DATA_ENV_FILE) + + +def _get_data(path): + try: + with open(path) as f: + return toml.load(f) + except FileNotFoundError: + return None + +def _write_data(path, data): + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + toml.dump(data, f) + os.replace(f.name, path) + +def _get_one_value(data, key): + key_path = key.split('.') + sub = data + for k in key_path: + sub = sub.get(k) + if sub is None: + break + return sub + +def _set_one_value(data, key, value): + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + val = sub.setdefault(k, {}) + sub = val + sub[key_path[-1]] = value + + +def set_value(path, key, value): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + _set_one_value(data, key, value) + + _write_data(path, data) + return 0 + + +def err(*args, **kwargs): + """print something on stderr""" + print(*args, **kwargs, file=sys.stderr) + + +def compare(old_path, new_path): + old = _get_data(old_path) + assert old is not None + new = _get_data(new_path) + assert new is not None + + old_median = old['result']['time']['median'] + new_median = new['result']['time']['median'] + + diff = new_median - old_median + ratio = new_median / old_median + + print(f"{old_median:.4f} -> {new_median:.4f}: {diff:.4f} ({ratio:.2f})") + + return 0 + + +def _parsers(): + cmd_parser = argparse.ArgumentParser(prog='poulpe-bin-env-util') + + cmd_parser.add_argument( + 'OLD_RESULT', + help="the path to the binary environment directory", + ) + cmd_parser.add_argument( + 'NEW_RESULT', + help="the path to the data environment directory", + ) + return cmd_parser + + +def main(args): + parser = _parsers() + param = parser.parse_args(args) + ret = compare(param.OLD_RESULT, param.NEW_RESULT) + return ret + +if __name__ == "__main__": + ret = main(sys.argv[1:]) + assert ret is not None + sys.exit(ret) diff --git a/bin/env-desc b/bin/env-desc new file mode 100755 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_YmluL2Vudi1kZXNj --- /dev/null +++ b/bin/env-desc @@ -0,0 +1,147 @@ +#!/bin/env python3 +# +# Small tool to manipulaote +import os +import sys +import tempfile +import toml + +ACTION_SHOW = 'show' +ACTION_SET = 'set' +ACTION_GET = 'get' +ACTION_DEL = 'del' +ALL_ACTIONS = { + ACTION_SHOW, + ACTION_SET, + ACTION_GET, + ACTION_DEL, +} + + +def _get_data(path): + try: + with open(path) as f: + return toml.load(f) + except FileNotFoundError: + return None + +def _write_data(path, data): + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + toml.dump(data, f) + os.replace(f.name, path) + + +def _show_one_level(data, indent=''): + if not isinstance(data, dict): + print(f"{indent}{data}") + return + for k, v in sorted(data.items()): + if isinstance(v, dict): + print(f"{indent}{k}:") + _show_one_level(v, indent + ' ') + elif isinstance(v, list): + print(f"{indent}{k}:") + for i in v: + _show_one_level(i, indent + '- ') + else: + print(f"{indent}{k} = {v}") + + +def show(path): + data = _get_data(path) + if data is None: + err(f'missing file: "{path}"') + return 3 + _show_one_level(data) + + +def get_value(path, key): + data = _get_data(path) + if data is None: + err(f'missing file: "{path}"') + return 3 + + key_path = key.split('.') + sub = data + for k in key_path: + sub = sub.get(k) + if sub is None: + return 1 + print(sub) + return 0 + + +def set_value(path, key, value): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + sub = sub.setdefault(k, {}) + sub[key_path[-1]] = value + + _write_data(path, data) + return 0 + + +def del_value(path, key): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + sub = sub.setdefault(k, {}) + sub.pop(key_path[-1], None) + + _write_data(path, data) + return 0 + +def err(*args, **kwargs): + print(*args, **kwargs, file=sys.stderr) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + t = os.path.split(sys.argv[0])[-1] + err(f"{t}: small utility to manipulate environment description") + err("") + err(f" $ {t} show PATH - Display description content") + err(f" $ {t} get PATH key - Display key value") + err(f" $ {t} set PATH key value - Set key value") + err(f" $ {t} del PATH key - Remove key") + sys.exit(2) + action = sys.argv[1] + path = sys.argv[2] + key = value = None + + if action not in ALL_ACTIONS: + err(f"unknown action: {action}") + err("(use one of: %s)" % ', '.join(sorted(ALL_ACTIONS))) + sys.exit(2) + + if action != ACTION_SHOW: + if len(sys.argv) < 4: + err("missing key") + sys.exit(2) + key = sys.argv[3] + if action == ACTION_SET: + if len(sys.argv) < 5: + err("missing value") + sys.exit(2) + value = sys.argv[4] + + if action == ACTION_SHOW: + ret = show(path) + elif action == ACTION_GET: + ret = get_value(path, key) + elif action == ACTION_SET: + ret = set_value(path, key, value) + elif action == ACTION_DEL: + ret = del_value(path, key) +sys.exit(ret) diff --git a/bin/run-util b/bin/run-util new file mode 100755 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_YmluL3J1bi11dGls --- /dev/null +++ b/bin/run-util @@ -0,0 +1,189 @@ +#!/bin/env python3 +# +# Small tool to manipulaote +import argparse +import json +import os +import stat +import subprocess +import sys +import tempfile +import toml + + +ERR_CODE_NO_KEY = 1 +ERR_CODE_NO_BIN_ENV_SHELL = 2 +ERR_CODE_NO_BIN_ENV_DESC = 3 +ERR_CODE_EXISTS = 4 +ERR_CODE_NO_SETUP_SCRIPT = 6 +ERR_CODE_SETUP_SCRIPT_FAILED = 7 + +BIN_ENV_FILE = 'bin-env.poulpe' +DATA_ENV_FILE = 'data-env.poulpe' +SHELL_FILE = 'bin-env.shell' + + +def _bin_env_file(bin_env_path): + """given the path of env, return the file of description file""" + return os.path.join(bin_env_path, BIN_ENV_FILE) + +def _bin_env_script(bin_env_path): + """given the path of env, return the file of description file""" + return os.path.join(bin_env_path, SHELL_FILE) + + +def _data_env_file(data_env_path): + """given the path of env, return the file of description file""" + return os.path.join(data_env_path, DATA_ENV_FILE) + + +def _get_data(path): + try: + with open(path) as f: + return toml.load(f) + except FileNotFoundError: + return None + +def _write_data(path, data): + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + toml.dump(data, f) + os.replace(f.name, path) + +def _get_one_value(data, key): + key_path = key.split('.') + sub = data + for k in key_path: + sub = sub.get(k) + if sub is None: + break + return sub + +def _set_one_value(data, key, value): + key_path = key.split('.') + sub = data + for k in key_path[:-1]: + val = sub.setdefault(k, {}) + sub = val + sub[key_path[-1]] = value + + +def set_value(path, key, value): + data = _get_data(path) + if data is None: + err(f'creating new file: "{path}"') + data = {} + + _set_one_value(data, key, value) + + _write_data(path, data) + return 0 + + +def err(*args, **kwargs): + """print something on stderr""" + print(*args, **kwargs, file=sys.stderr) + + +def run_one(bin_env_path, data_env_path, benchmark, result): + result_data = {} + + # gather info about the binary environment + bin_env_desc = _bin_env_file(bin_env_path) + bin_env_data = _get_data(bin_env_desc) + result_data['bin-env-vars'] = bin_env_data['bin-env-vars'] + + # gather info about the data environment + data_env_desc = _data_env_file(data_env_path) + data_env_data = _get_data(data_env_desc) + result_data['data-env-vars'] = data_env_data['data-env-vars'] + + benchmark_data = _get_data(benchmark) + assert benchmark_data is not None, benchmark + result_data['benchmark'] = {} + result_data['benchmark']['name'] = benchmark_data['meta']['name'] + + # building the benchmark scenarion, that will likely changes often and quickly + + cmd = benchmark_data['simple-command']['command'] + + variables_data = benchmark_data['simple-command']['variables'] + + variables = {} + for name, value in variables_data.items(): + if value.startswith('DATA-VARS:'): + key = value.split(':', 1)[1] + value = _get_one_value(data_env_data, f'bench-input-vars.{key}') + assert value is not None + variables[name] = value + + cmd = cmd.format(**variables) + + r = _time_command(bin_env_path, data_env_path, cmd) + + # we should store more + result_data['result'] = {} + result_data['result']['time'] = {} + result_data['result']['time']['median'] = r['results'][0]['median'] + + _write_data(result, result_data) + return 0 + + +def _time_command(bin_env_path, data_env_path, cmd): + bin_env_path = os.path.abspath(bin_env_path) + data_env_path = os.path.abspath(data_env_path) + shell_path = _bin_env_script(bin_env_path) + + with tempfile.NamedTemporaryFile('w') as tmp_result: + time_cmd = [ + shell_path, + "hyperfine", + cmd, + "--export-json", + tmp_result.name, + "--ignore-failure", + ] + + subprocess.check_call( + time_cmd, + cwd=data_env_path, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + + with open(tmp_result.name) as f: + return json.load(f) + + +def _parsers(): + cmd_parser = argparse.ArgumentParser(prog='poulpe-bin-env-util') + + cmd_parser.add_argument( + 'BIN_ENV', + help="the path to the binary environment directory", + ) + cmd_parser.add_argument( + 'DATA_ENV', + help="the path to the data environment directory", + ) + cmd_parser.add_argument( + 'BENCHMARK', + help="the path to the benchmark description file", + ) + cmd_parser.add_argument( + 'RESULT', + help="the path to result file", + ) + return cmd_parser + + +def main(args): + parser = _parsers() + param = parser.parse_args(args) + ret = run_one(param.BIN_ENV, param.DATA_ENV, param.BENCHMARK, param.RESULT) + return ret + +if __name__ == "__main__": + ret = main(sys.argv[1:]) + assert ret is not None + sys.exit(ret) diff --git a/tests/test-bin-env-util.t b/tests/test-bin-env-util.t new file mode 100644 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_dGVzdHMvdGVzdC1iaW4tZW52LXV0aWwudA== --- /dev/null +++ b/tests/test-bin-env-util.t @@ -0,0 +1,216 @@ +Test the utility that manage bin-env creation +--------------------------------------------- + + $ PATH="${TESTDIR}/../bin:$PATH" + +Check basic invocation + + $ bin-env-util --help + usage: poulpe-bin-env-util [-h] + {create-empty,setup-one,mark-ready,show,get,set,del} + ... + + positional arguments: + {create-empty,setup-one,mark-ready,show,get,set,del} + available sub-command + create-empty create a new empty bin-env + setup-one create a new empty bin-env + mark-ready mark a bin-env as ready + show Show all data we have about this environment + get Show a specific bin-env variable + set Show a specific bin-env variable + del Show a specific bin-env variable + + optional arguments: + -h, --help show this help message and exit + + +Check repository creation + +simple creation + + $ bin-env-util create-empty test-create + $ ls -1 test-create + bin-env.poulpe + $ bin-env-util show test-create + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = False + +Running on an existing repo abort and does not destroy it + + $ bin-env-util create-empty test-create + This is already a bin-env, aborting + [4] + $ bin-env-util show test-create + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = False + +Creating a repository on an existing dir + + $ mkdir test-existing-dir + $ bin-env-util create-empty test-existing-dir + $ bin-env-util show test-existing-dir + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = False + +Check manual setup +------------------ + +Check changing variable manually + + $ python3 -m venv test-existing-dir + $ cd test-existing-dir + $ bin/pip3 install --quiet black==18.6b4 + $ bin-env-util set . python.version "`bin/python --version | egrep -o '\S+$'`" + $ bin-env-util set . black.version "`bin/black --version | egrep -o '\S+$'`" + $ bin-env-util set . black.install-method pip + $ bin-env-util show . + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.* (glob) + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = False + +Marking it ready when it is not + + $ bin-env-util mark-ready . + cannot find an executable file at: "./bin-env.shell" + [2] + $ bin-env-util show . + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.* (glob) + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = False + +Manually create an activate script + + $ cat > bin-env.shell << EOF + > #!/bin/bash + > BIN_ENV_PATH="\`dirname \"\$0\"\`" + > . "\$BIN_ENV_PATH"/bin/activate + > "\$@" + > EOF + $ bin-env-util mark-ready . + cannot find an executable file at: "./bin-env.shell" + [2] + $ chmod +x bin-env.shell + +Marking it ready when it is + + $ bin-env-util mark-ready . + $ bin-env-util show . + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.* (glob) + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = manual + ready = True + +Basic test of the result + + $ ./bin-env.shell echo babar + babar + $ ./bin-env.shell black --version + black, version 18.6b4 + $ cd .. + +Test scripted setup +------------------- + +Create setup scripts + + $ cat > setup-error.sh << EOF + > #!/bin/bash + > exit 2 + > EOF + $ chmod +x setup-error.sh + + $ grep -v 'chmod' $TESTDIR/test-data/setup-black.sh > setup-black-bad-activate.sh + $ chmod +x setup-black-bad-activate.sh + +Test a missing script + + $ bin-env-util setup-one env-missing setup-missing.sh + no executable setup scrip at: "setup-missing.sh" + [6] + +Test a setup error + + $ bin-env-util setup-one env-error setup-error.sh + script returned with status 2: $TESTTMP/setup-error.sh + [7] + +Test an invalid activate + + $ bin-env-util setup-one env-bad-activate setup-black-bad-activate.sh + $TESTTMP/setup-black-bad-activate.sh: line 5: BLACK_VERSION: unbound variable + script returned with status 1: $TESTTMP/setup-black-bad-activate.sh + [7] + $ rm -rf env-bad-activate + $ BLACK_VERSION="18.6b4" bin-env-util setup-one env-bad-activate setup-black-bad-activate.sh + cannot find an executable file at: "env-bad-activate/bin-env.shell" + [2] + +Test a succesfull script + + $ BLACK_VERSION="18.6b4" bin-env-util setup-one env-black-18.6b4 \ + > $TESTDIR/test-data/setup-black.sh + $ BLACK_VERSION="18.6b1" bin-env-util setup-one env-black-18.6b1 \ + > $TESTDIR/test-data/setup-black.sh + + $ bin-env-util show env-black-18.6b1 + bin-env-vars: + black: + install-method = pip + version = 18.6b1 + python: + version = 3.9.9 + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = script + ready = True + $ env-black-18.6b1/bin-env.shell black --version + black, version 18.6b1 + + $ bin-env-util show env-black-18.6b4 + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.9.9 + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = script + ready = True + $ env-black-18.6b4/bin-env.shell black --version + black, version 18.6b4 diff --git a/tests/test-data/setup-black.sh b/tests/test-data/setup-black.sh new file mode 100755 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_dGVzdHMvdGVzdC1kYXRhL3NldHVwLWJsYWNrLnNo --- /dev/null +++ b/tests/test-data/setup-black.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -euo pipefail + +python3 -m venv . +bin/pip3 install --quiet black=="$BLACK_VERSION" + +echo python.version="`bin/python --version | egrep -o '\S+$'`" > POULPE-VARS +echo black.version="`bin/black --version | egrep -o '\S+$'`" >> POULPE-VARS +echo black.install-method=pip >> POULPE-VARS + +touch bin-env.shell +chmod +x bin-env.shell + +cat >> bin-env.shell << EOF +#!/bin/bash +set -euo pipefail +BIN_ENV_PATH="\`dirname \"\$0\"\`" +. "\$BIN_ENV_PATH"/bin/activate +"\$@" +EOF diff --git a/tests/test-env-desc.t b/tests/test-env-desc.t new file mode 100644 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_dGVzdHMvdGVzdC1lbnYtZGVzYy50 --- /dev/null +++ b/tests/test-env-desc.t @@ -0,0 +1,108 @@ +Test the small utility that access environment description +---------------------------------------------------------- + + $ PATH="${TESTDIR}/../bin:$PATH" + +Check basic error +---------------- + +no args + + $ env-desc + env-desc: small utility to manipulate environment description + + $ env-desc show PATH - Display description content + $ env-desc get PATH key - Display key value + $ env-desc set PATH key value - Set key value + $ env-desc del PATH key - Remove key + [2] + +too few args + + $ env-desc foo + env-desc: small utility to manipulate environment description + + $ env-desc show PATH - Display description content + $ env-desc get PATH key - Display key value + $ env-desc set PATH key value - Set key value + $ env-desc del PATH key - Remove key + [2] + +bad action + + $ env-desc foo bar + unknown action: foo + (use one of: del, get, set, show) + [2] + +missing GET key + + $ env-desc get no-file + missing key + [2] + +missing SET key + + $ env-desc set no-file + missing key + [2] + +missing SET value + + $ env-desc set no-file key + missing value + [2] + +missing DEL key + + $ env-desc del no-file + missing key + [2] + +Missing file when reading + + $ env-desc show no-file + missing file: "no-file" + [3] + + $ env-desc get no-file no-key + missing file: "no-file" + [3] + +Writing and reading files +------------------------- + +Small and basic usage to smoke test the script + + $ env-desc set bin-env.pe vars.hg.version 6.1.0 + creating new file: "bin-env.pe" + $ env-desc set bin-env.pe vars.hg.flavor pure + $ env-desc set bin-env.pe vars.oops babar + $ env-desc get bin-env.pe vars.hg.version + 6.1.0 + $ env-desc get bin-env.pe vars.hg.flavor + pure + $ env-desc get bin-env.pe vars.oops + babar + $ env-desc show bin-env.pe + vars: + hg: + flavor = pure + version = 6.1.0 + oops = babar + +Modify the file more + + $ env-desc set bin-env.pe vars.hg.version 4.3.0 + $ env-desc del bin-env.pe vars.oops + $ env-desc get bin-env.pe vars.hg.version + 4.3.0 + $ env-desc get bin-env.pe vars.hg.flavor + pure + $ env-desc get bin-env.pe vars.oops + [1] + $ env-desc show bin-env.pe + vars: + hg: + flavor = pure + version = 4.3.0 diff --git a/tests/test-simple-run.t b/tests/test-simple-run.t new file mode 100644 index 0000000000000000000000000000000000000000..fd546c6ebd9c1ca773b9d83d52a9f43b30b190c0_dGVzdHMvdGVzdC1zaW1wbGUtcnVuLnQ= --- /dev/null +++ b/tests/test-simple-run.t @@ -0,0 +1,130 @@ +Check we have enough simple pieces together to do a simple run +-------------------------------------------------------------- + + $ PATH="${TESTDIR}/../bin:$PATH" + +Setup the bin-env +----------------- + + $ BLACK_VERSION="18.6b4" bin-env-util setup-one bin-env-black-18.6b4 \ + > $TESTDIR/test-data/setup-black.sh + $ bin-env-util show bin-env-black-18.6b4 + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.* (glob) + poulpe-environment: + environment-type = binary + format-version = 0 + setup-method = script + ready = True + + +Setup a data-env +---------------- + +(currently built by hand as it simple and mostly innert) + + $ mkdir data-env + $ env-desc set data-env/data-env.poulpe poulpe-environment.environment-type data + creating new file: "data-env/data-env.poulpe" + $ env-desc set data-env/data-env.poulpe poulpe-environment.format-version 0 + $ env-desc set data-env/data-env.poulpe poulpe-environment.setup-method manual + $ env-desc set data-env/data-env.poulpe data-env-vars.name black-bench + $ mkdir data-env/py-files + $ cat << EOF > data-env/py-files/good.py + > foo = [1, 2, 3, 4, 5] + > EOF + $ cat << EOF > data-env/py-files/bad.py + > foo = [1, + > 2, + > 3, + > 4, + > 5] + > EOF + $ env-desc set data-env/data-env.poulpe bench-input-vars.black.check.tiny.good py-files/good.py + $ env-desc set data-env/data-env.poulpe bench-input-vars.black.check.tiny.bad py-files/bad.py + +(that one will be a string, so its not good.) + + $ env-desc set data-env/data-env.poulpe ready 1 + + $ env-desc show data-env/data-env.poulpe + bench-input-vars: + black: + check: + tiny: + bad = py-files/bad.py + good = py-files/good.py + data-env-vars: + name = black-bench + poulpe-environment: + environment-type = data + format-version = 0 + setup-method = manual + ready = 1 + +Define a benchmark +------------------ + + $ env-desc set black-tiny-bad.pbd meta.format 0 + creating new file: "black-tiny-bad.pbd" + $ env-desc set black-tiny-bad.pbd meta.name black.check.tiny + $ env-desc set black-tiny-bad.pbd meta.method simple-command + $ env-desc set black-tiny-bad.pbd simple-command.command "black --check {file}" + $ env-desc set black-tiny-bad.pbd simple-command.variables.file DATA-VARS:black.check.tiny.bad + + $ env-desc show black-tiny-bad.pbd + meta: + format = 0 + method = simple-command + name = black.check.tiny + simple-command: + command = black --check {file} + variables: + file = DATA-VARS:black.check.tiny.bad + +Run the benchmark +----------------- + $ run-util bin-env-black-18.6b4 data-env black-tiny-bad.pbd test-result-18.6b4-bad.pbr + $ env-desc show test-result-18.6b4-bad.pbr + benchmark: + name = black.check.tiny + bin-env-vars: + black: + install-method = pip + version = 18.6b4 + python: + version = 3.* (glob) + data-env-vars: + name = black-bench + result: + time: + median = * (glob) + +Quick comparision of values +--------------------------- + +Get another result +(the sed if likely to not be a viable option in the future) + + $ cp black-tiny-bad.pbd black-tiny-good.pbd + $ sed -i 's/bad/good/g' black-tiny-good.pbd + $ env-desc show black-tiny-good.pbd + meta: + format = 0 + method = simple-command + name = black.check.tiny + simple-command: + command = black --check {file} + variables: + file = DATA-VARS:black.check.tiny.good + + $ run-util bin-env-black-18.6b4 data-env black-tiny-good.pbd test-result-18.6b4-good.pbr + +Compare the result + + $ diff-result test-result-18.6b4-bad.pbr test-result-18.6b4-good.pbr + \d+.\d+ -> \d+.\d+: -?\d+.\d+ \(\d+.\d+\) (re)