Return depset_file subjects from link_action inputs() and outputs()

This is reflective of what they actually are and string formatting works
appropriately (since we sometimes compare files and not strings, simply
setting "format = True" when we create the collection subject does not work).

The depset subject does not support transform() but this is almost always
unnecessary and we can achieve what we need in other ways. If it's ever
truly needed, we can always operate on the underlying data (which is still
just a list) - maybe the depset subject could have a "as_list" method that
returns a corresponding collection subject if this was ever needed.

PiperOrigin-RevId: 963462988
Change-Id: I33772dc8b7efc89b8316303f0ae90f026352e3b6
diff --git a/tests/cc/common/cc_binary_configured_target_tests.bzl b/tests/cc/common/cc_binary_configured_target_tests.bzl
index 464311a..7c60984 100644
--- a/tests/cc/common/cc_binary_configured_target_tests.bzl
+++ b/tests/cc/common/cc_binary_configured_target_tests.bzl
@@ -76,10 +76,9 @@
     )
 
 def _test_headers_not_passed_to_linking_action_impl(env, target):
-    link_action_subject.from_target(env, target).inputs().transform(
-        desc = "extensions",
-        map_each = lambda f: f.extension,
-    ).contains_none_of(["h", "hpp", "hxx"])
+    link_action_subject.from_target(env, target).inputs().not_contains_predicate(
+        matching.file_extension_in(["h", "hpp", "hxx"]),
+    )
 
 def _test_no_duplicate_linkopts(name, **kwargs):
     # Regression test for b/943558: linkopts duplicated in linker invocation
@@ -128,27 +127,24 @@
     executable = target[DefaultInfo].files_to_run.executable
     link_action = link_action_subject.from_target(env, target)
 
+    object_file = "{package}/_objs/{name}/hello.o"
+
     # link.inputs = { hello.o }
-    hello_obj_files = link_action.inputs().transform(
-        desc = "hello object files",
-        filter = lambda f: f.basename.startswith("hello.") and f.extension in ["o", "obj"],
-    )
-    hello_obj_files.has_size(1)
-    obj_file = hello_obj_files.offset(0, subjects.file).actual
+    link_action.inputs().contains(object_file)
 
     # link.outputs = { hello }
-    link_action.outputs().contains_exactly([executable])
+    link_action.outputs().contains_exactly([executable.short_path])
 
-    compile_action = env.expect.that_target(target).action_generating(obj_file.short_path)
+    compile_action = env.expect.that_target(target).action_generating(object_file)
     compile_action.mnemonic().equals("CppCompile")
 
     # compile.inputs = { hello_cc }
     compile_action.inputs().contains("{package}/hello.cc")
 
     # compile.outputs = { hello.o } (mock toolchain doesn't generate .d)
-    compile_outputs = compile_action.actual.outputs.to_list()
-    env.expect.that_collection(compile_outputs).has_size(1)
-    env.expect.that_collection(compile_outputs).contains(obj_file)
+    compile_action.outputs().contains_exactly([
+        object_file,
+    ])
 
     # TODO: Test stripped action
 
@@ -278,10 +274,9 @@
 
 def _test_pic_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    link_action.inputs().transform(
-        desc = "hello pic object files",
-        filter = lambda f: f.basename.startswith("hello.pic.") and f.extension in ["o", "obj"],
-    ).has_size(1)
+    link_action.inputs().contains_predicate(
+        matching.file_basename_equals("hello.pic.o"),
+    )
 
 def _generated_def_file_test(name, impl, with_action_configs = None, **kwargs):
     if with_action_configs == None:
@@ -743,26 +738,17 @@
         "core",
     ]).in_order()
 
-def _input_basenames(link_action):
-    return link_action.inputs().transform(
-        desc = "input basenames",
-        map_each = lambda f: f.basename,
-    )
-
 def _is_shared_library(f):
     return f.extension in ["so", "dylib", "dll", "ifso"] or ".so" in f.basename or ".dylib" in f.basename
 
 def _assert_link_staticness(env, target, expected_static):
     link_action = link_action_subject.from_target(env, target)
-    shared_libs = link_action.inputs().transform(
-        desc = "shared libraries",
-        filter = _is_shared_library,
-    )
+    shared_library_matcher = matching.custom("is shared library", _is_shared_library)
 
     if expected_static:
-        shared_libs.is_empty()
+        link_action.inputs().not_contains_predicate(shared_library_matcher)
     else:
-        shared_libs.is_not_empty()
+        link_action.inputs().contains_predicate(shared_library_matcher)
 
 def _create_dep_tree(name, use_actual_cc_binary = False):
     binary_rule = _actual_cc_binary if use_actual_cc_binary else cc_binary
@@ -892,13 +878,13 @@
 
 def _test_cc_runtimes_added_to_libraries_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    _input_basenames(link_action).contains_at_least([
-        "app.pic.o",
-        "libmiddleware1.a",
-        "libinfrastructure1.a",
-        "liblink_extra_lib.a",
-        "libruntime.a",
-        "linkstamp.o",
+    link_action.inputs().contains_at_least_predicates([
+        matching.file_basename_equals("app.pic.o"),
+        matching.file_basename_equals("libmiddleware1.a"),
+        matching.file_basename_equals("libinfrastructure1.a"),
+        matching.file_basename_equals("liblink_extra_lib.a"),
+        matching.file_basename_equals("libruntime.a"),
+        matching.file_basename_equals("linkstamp.o"),
     ])
 
 def _test_ignore_custom_malloc(name, **kwargs):
@@ -916,9 +902,8 @@
 
 def _test_ignore_custom_malloc_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
-    basenames.contains("libsystem_malloc.a")
-    basenames.not_contains("libmock_malloc.a")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("libsystem_malloc.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmock_malloc.a"))
 
 def _test_custom_malloc(name, **kwargs):
     _create_dep_tree(name, use_actual_cc_binary = True)
@@ -936,9 +921,8 @@
 
 def _test_custom_malloc_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
-    basenames.contains("libmymalloc.a")
-    basenames.not_contains("libmock_malloc.a")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("libmymalloc.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmock_malloc.a"))
 
 def _test_app_linking_static(name, **kwargs):
     _create_dep_tree(name)
@@ -956,18 +940,19 @@
 
 def _test_app_linking_static_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
 
     # Assert inputs
-    basenames.contains("app.pic.o")
-    basenames.contains("libmiddleware1.a")
-    basenames.contains("libinfrastructure1.a")
-    basenames.contains("linkstamp.o")
+    link_action.inputs().contains_at_least_predicates([
+        matching.file_basename_equals("app.pic.o"),
+        matching.file_basename_equals("libmiddleware1.a"),
+        matching.file_basename_equals("libinfrastructure1.a"),
+        matching.file_basename_equals("linkstamp.o"),
+    ])
 
     # Assert NOT inputs
-    basenames.not_contains("libinfrastructure2.a")
-    basenames.not_contains("libmiddleware2.so")
-    basenames.not_contains("libmiddleware3.so.1")
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libinfrastructure2.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware2.so"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware3.so.1"))
 
     # Assert linkopts
     link_action.argv().contains_at_least([
@@ -996,21 +981,22 @@
 
 def _test_app_linking_dynamic_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
 
     # Assert inputs
-    basenames.contains("app.pic.o")
-    basenames.contains("libinfrastructure1.a")
-    basenames.contains("linkstamp.o")
+    link_action.inputs().contains_at_least_predicates([
+        matching.file_basename_equals("app.pic.o"),
+        matching.file_basename_equals("libinfrastructure1.a"),
+        matching.file_basename_equals("linkstamp.o"),
+    ])
 
     # Assert dynamic library symlink (mangled)
-    basenames.contains_predicate(
-        matching.str_endswith("_Slibmiddleware1.ifso"),
+    link_action.inputs().contains_predicate(
+        matching.custom("basename ends with _Slibmiddleware1.ifso", lambda f: f.basename.endswith("_Slibmiddleware1.ifso")),
     )
 
     # Assert NOT inputs
-    basenames.not_contains("libmiddleware1.a")
-    basenames.not_contains("libinfrastructure2.a")
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware1.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("libinfrastructure2.a"))
 
     # Assert linkopts
     link_action.argv().contains_at_least([
@@ -1082,13 +1068,11 @@
 
 def _test_transitive_libs_are_collected_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    input_basenames = _input_basenames(link_action)
-
-    input_basenames.contains_at_least([
-        "foo.pic.o",
-        "libbar.a",
-        "libbaz.a",
-        "linkstamp.o",
+    link_action.inputs().contains_at_least_predicates([
+        matching.file_basename_equals("foo.pic.o"),
+        matching.file_basename_equals("libbar.a"),
+        matching.file_basename_equals("libbaz.a"),
+        matching.file_basename_equals("linkstamp.o"),
     ])
 
 def _test_transitive_linkstamps_are_collected(name, **kwargs):
@@ -1102,10 +1086,8 @@
 
 def _test_transitive_linkstamps_are_collected_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    input_basenames = _input_basenames(link_action)
-
-    input_basenames.contains("linkstamp.o")
-    input_basenames.not_contains("linkstamp.cc")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("linkstamp.o"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("linkstamp.cc"))
 
 def _test_linker_toolchain_feature(name, **kwargs):
     util.helper_target(
@@ -1185,8 +1167,7 @@
             lambda arg: arg.startswith("--option=") and arg.endswith("main.extra_file"),
         ),
     )
-    input_basenames = _input_basenames(link_action)
-    input_basenames.contains("main.extra_file")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("main.extra_file"))
 
 # Regression test for b/193125967
 def _test_conflicting_linkstamps(name, **kwargs):
@@ -1303,9 +1284,8 @@
 
 def _test_pic_mode_prefers_pic_libs_force_pic_disabled_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
-    basenames.contains("dep.nopic.a")
-    basenames.not_contains("dep.pic.a")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("dep.nopic.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.pic.a"))
 
 def _test_pic_mode_prefers_pic_libs_force_pic_enabled(name, **kwargs):
     _create_prefers_pic_libs_dep_tree(name)
@@ -1322,9 +1302,8 @@
 
 def _test_pic_mode_prefers_pic_libs_force_pic_enabled_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
-    basenames.contains("dep.pic.a")
-    basenames.not_contains("dep.nopic.a")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("dep.pic.a"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.a"))
 
 def _test_pic_mode_uses_pic_libs(name, **kwargs):
     util.helper_target(
@@ -1354,7 +1333,7 @@
 
 def _test_pic_mode_uses_pic_libs_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    _input_basenames(link_action).contains("dep.pic.o")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("dep.pic.o"))
 
 def _create_does_not_use_nopic_library_dep_tree(name):
     util.helper_target(
@@ -1384,9 +1363,8 @@
 
 def _test_pic_mode_does_not_use_nopic_library_force_pic_disabled_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    basenames = _input_basenames(link_action)
-    basenames.contains("mybinary.pic.o")
-    basenames.not_contains("dep.nopic.o")
+    link_action.inputs().contains_predicate(matching.file_basename_equals("mybinary.pic.o"))
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.o"))
 
 def _test_pic_mode_does_not_use_nopic_library_force_pic_enabled(name, **kwargs):
     _create_does_not_use_nopic_library_dep_tree(name)
@@ -1403,7 +1381,7 @@
 
 def _test_pic_mode_does_not_use_nopic_library_force_pic_enabled_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    _input_basenames(link_action).not_contains("dep.nopic.o")
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.o"))
 
 def _test_pic_mode_does_not_use_nopic_binary(name, **kwargs):
     util.helper_target(
@@ -1421,7 +1399,7 @@
 
 def _test_pic_mode_does_not_use_nopic_binary_impl(env, target):
     link_action = link_action_subject.from_target(env, target)
-    _input_basenames(link_action).not_contains("xyz.nopic.o")
+    link_action.inputs().not_contains_predicate(matching.file_basename_equals("xyz.nopic.o"))
 
 def _setup_cc_runtimes_mock():
     util.helper_target(
diff --git a/tests/cc/common/compile_build_variables_tests.bzl b/tests/cc/common/compile_build_variables_tests.bzl
index 886abfa..d68e1c4 100644
--- a/tests/cc/common/compile_build_variables_tests.bzl
+++ b/tests/cc/common/compile_build_variables_tests.bzl
@@ -5,7 +5,6 @@
 load("@rules_testing//lib:util.bzl", "TestingAspectInfo", "util")
 load("//cc:cc_binary.bzl", _actual_cc_binary = "cc_binary")
 load("//tests/cc/testutil:cc_analysis_test.bzl", "cc_analysis_test")
-load("//tests/cc/testutil:link_action_subject.bzl", "link_action_subject")
 
 # Wrap cc_binary to mock out common dependencies.
 def cc_binary(name, **kwargs):
@@ -16,18 +15,10 @@
         **kwargs
     )
 
-def _obj_file(env, target, src_base_name):
-    link_action = link_action_subject.from_target(env, target)
-    obj_files = link_action.inputs().transform(
-        desc = "object files matching " + src_base_name,
-        filter = lambda f: f.basename.startswith(src_base_name + ".") and f.extension == "o",
-    )
-    obj_files.has_size(1)
-    return obj_files.offset(0, subjects.file)
-
 def _compile_action(env, target, src_base_name):
-    obj_file_subject = _obj_file(env, target, src_base_name)
-    compile_action = env.expect.that_target(target).action_generating(obj_file_subject.actual.short_path)
+    compile_action = env.expect.that_target(target).action_generating(
+        "{package}/_objs/{name}/" + src_base_name + ".o",
+    )
     compile_action.mnemonic().equals("CppCompile")
     return compile_action
 
@@ -63,7 +54,6 @@
     _variable_list(_compile_action(env, target, "bin"), "source_file").contains_exactly(["{package}/bin.cc"])
 
     # make sure compile action's output matches OUTPUT_FILE
-    _obj_file(env, target, "bin").short_path_equals("{package}/_objs/{name}/bin.o")
     output_name_end = "{package}/_objs/{name}/bin.o".format(
         package = target.label.package,
         name = target.label.name,
diff --git a/tests/cc/testutil/link_action_subject.bzl b/tests/cc/testutil/link_action_subject.bzl
index 63c1b02..01f65dd 100644
--- a/tests/cc/testutil/link_action_subject.bzl
+++ b/tests/cc/testutil/link_action_subject.bzl
@@ -7,8 +7,8 @@
     return struct(
         actual = actual,
         meta = meta,
-        inputs = lambda: subjects.collection(actual.inputs.to_list(), meta = meta.derive("inputs")),
-        outputs = lambda: subjects.collection(actual.outputs.to_list(), meta = meta.derive("outputs")),
+        inputs = lambda: subjects.depset_file(actual.inputs, meta = meta.derive("inputs")),
+        outputs = lambda: subjects.depset_file(actual.outputs, meta = meta.derive("outputs")),
         argv = lambda: subjects.collection(actual.argv, sortable = False, meta = meta.derive("argv")),
         env = lambda: subjects.dict(actual.env, meta = meta.derive("env")),
         execution_info = lambda: subjects.dict(actual.execution_info, meta = meta.derive("execution_info")),