From 7af30cb04fafda8c5761146249f736db26c88841 Mon Sep 17 00:00:00 2001 From: Alex Tercete Date: Wed, 16 Apr 2025 14:10:13 +0100 Subject: [PATCH 1/2] feat(test): add `data` attribute By adding the `data` files to the existing runfiles directory of `src`, they are automatically transferred to the device. --- e2e/test/BUILD.bazel | 15 +++++++++++++++ labgrid/runfiles/defs.bzl | 5 +++-- labgrid/test/rule.bzl | 12 +++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/e2e/test/BUILD.bazel b/e2e/test/BUILD.bazel index 48677fb..a52373c 100644 --- a/e2e/test/BUILD.bazel +++ b/e2e/test/BUILD.bazel @@ -94,3 +94,18 @@ labgrid_test( ], platform = "@rules_labgrid//labgrid/platform:localhost", ) + +py_binary( + name = "inner-without-data", + srcs = ["hello.py"], + main = "hello.py", + deps = ["@rules_python//python/runfiles"], +) + +labgrid_test( + name = "data", + size = "small", + src = ":inner-without-data", + data = [":hello.txt"], + platform = "@rules_labgrid//labgrid/platform:localhost", +) diff --git a/labgrid/runfiles/defs.bzl b/labgrid/runfiles/defs.bzl index a651739..6c2cd5c 100644 --- a/labgrid/runfiles/defs.bzl +++ b/labgrid/runfiles/defs.bzl @@ -1,13 +1,14 @@ load("@aspect_bazel_lib//lib:paths.bzl", "to_rlocation_path") load("@bazel_skylib//lib:paths.bzl", "paths") -def runfiles_dir(ctx, target): +def runfiles_dir(ctx, target, additional_files = []): """ Generate a runfiles directory adjacent to the target path, .runfiles. """ runfiles = [] runfiles_base = "{}.runfiles".format(target.label.name) - for file in target.default_runfiles.files.to_list(): + files = target.default_runfiles.files.to_list() + for file in files + additional_files: out = ctx.actions.declare_file(paths.join(runfiles_base, to_rlocation_path(ctx, file))) ctx.actions.symlink( output = out, diff --git a/labgrid/test/rule.bzl b/labgrid/test/rule.bzl index 2755102..fe2070f 100644 --- a/labgrid/test/rule.bzl +++ b/labgrid/test/rule.bzl @@ -23,6 +23,13 @@ ATTRS = { doc = "Environment variables to set in the test environment.", default = {}, ), + "data": attr.label_list( + allow_files = True, + doc = "The data files to add to the test environment.", + providers = [DefaultInfo], + cfg = "target", + default = [], + ), "_executor": attr.label( doc = "The labgrid environment executor", default = "//labgrid/executor", @@ -50,6 +57,9 @@ def _get(pair): key, value = pair return ["--get", "{}:{}".format(key, value)] +def _files(targets): + return [f for t in targets for f in t.files.to_list()] + def implementation(ctx): env = _run_env(ctx.attr.src) | ctx.attr.env | { "XML_OUTPUT_FILE": "results.xml", @@ -83,7 +93,7 @@ def implementation(ctx): runfiles = runfiles.merge(ctx.attr._executor.default_runfiles) runfiles = runfiles.merge(ctx.attr._run.default_runfiles) runfiles = runfiles.merge(ctx.attr.src.default_runfiles) - runfiles = runfiles.merge(runfiles_dir(ctx, ctx.attr.src)) + runfiles = runfiles.merge(runfiles_dir(ctx, ctx.attr.src, additional_files = _files(ctx.attr.data))) return DefaultInfo(executable = executable, files = files, runfiles = runfiles) -- GitLab From 4394abde65abc0f87aeab0268a2f2a1e2627905f Mon Sep 17 00:00:00 2001 From: Alex Tercete Date: Wed, 16 Apr 2025 15:03:43 +0100 Subject: [PATCH 2/2] feat(test): support `$(location)` substitution in `env` This allows saving the remote path of a file provided under `data` in an environment variable for later use within `src`. This works for simple cases, but it doesn't support advanced scenarios as path mapping isn't robust yet. --- e2e/test/BUILD.bazel | 28 ++++++++++++++++++++++++++++ labgrid/test/rule.bzl | 15 +++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/e2e/test/BUILD.bazel b/e2e/test/BUILD.bazel index a52373c..5aa1ead 100644 --- a/e2e/test/BUILD.bazel +++ b/e2e/test/BUILD.bazel @@ -109,3 +109,31 @@ labgrid_test( data = [":hello.txt"], platform = "@rules_labgrid//labgrid/platform:localhost", ) + +write_file( + name = "assert-data-from-env", + out = "data-from-env.py", + content = [ + "from os import environ", + "from pathlib import Path", + "assert Path(environ['HELLO_PATH']).read_text().rstrip() == 'world'", + ], +) + +py_binary( + name = "inner-data-from-env", + srcs = ["data-from-env.py"], + main = "data-from-env.py", + deps = ["@rules_python//python/runfiles"], +) + +labgrid_test( + name = "data-from-env", + size = "small", + src = ":inner-data-from-env", + data = [":hello.txt"], + env = { + "HELLO_PATH": "$(location :hello.txt)", + }, + platform = "@rules_labgrid//labgrid/platform:localhost", +) diff --git a/labgrid/test/rule.bzl b/labgrid/test/rule.bzl index fe2070f..cb9e8ac 100644 --- a/labgrid/test/rule.bzl +++ b/labgrid/test/rule.bzl @@ -1,4 +1,5 @@ load("@aspect_bazel_lib//lib:paths.bzl", "to_rlocation_path") +load("@bazel_skylib//lib:paths.bzl", "paths") load("//labgrid/cfg:store.bzl", _cfg = "store") load("//labgrid/runfiles:defs.bzl", "runfiles_dir") @@ -20,7 +21,7 @@ ATTRS = { providers = [platform_common.PlatformInfo], ), "env": attr.string_dict( - doc = "Environment variables to set in the test environment.", + doc = "Environment variables to set in the test environment. Subject to `$(location)` substitution.", default = {}, ), "data": attr.label_list( @@ -49,6 +50,16 @@ def _run_env(target): return target[RunEnvironmentInfo].environment return {} +def _expand(ctx, data, value): + custom_var = { + "RUNFILES_DIR": "{}.runfiles".format(ctx.executable.src.basename), + } + value = value.replace("$(location", paths.join("$(RUNFILES_DIR)", "$(rlocationpath")) + value = ctx.expand_location(value, targets = data) + for k, v in custom_var.items(): + value = value.replace("$({})".format(k), v) + return value + def _env(pair): key, value = pair return ["--env", "{}={}".format(key, value)] @@ -61,7 +72,7 @@ def _files(targets): return [f for t in targets for f in t.files.to_list()] def implementation(ctx): - env = _run_env(ctx.attr.src) | ctx.attr.env | { + env = _run_env(ctx.attr.src) | {k: _expand(ctx, ctx.attr.data, v) for k, v in ctx.attr.env.items()} | { "XML_OUTPUT_FILE": "results.xml", "BAZEL_TEST": "1", } -- GitLab