Test and fix root symlink edge case in runfiles library

Due to incomplete test coverage for the case of a root symlink named like a Bazel module, the Bash runfiles libraries behaved incorrectly in this case. This commit fixes that and adds proper test coverage for all libraries by adding repo mappings that conflict with the existing rlocation testcase for `config.json`.

Closes #17317.

PiperOrigin-RevId: 505873412
Change-Id: I72019d329b72cab9cf893deb714da8889d371617
diff --git a/tools/bash/runfiles/runfiles.bash b/tools/bash/runfiles/runfiles.bash
index 6607317..540eb90 100644
--- a/tools/bash/runfiles/runfiles.bash
+++ b/tools/bash/runfiles/runfiles.bash
@@ -142,7 +142,10 @@
 
   if [[ -f "$RUNFILES_REPO_MAPPING" ]]; then
     local -r target_repo_apparent_name=$(echo "$1" | cut -d / -f 1)
-    local -r remainder=$(echo "$1" | cut -d / -f 2-)
+     # Use -s to get an empty remainder if the argument does not contain a slash.
+    # The repo mapping should not be applied to single segment paths, which may
+    # be root symlinks.
+    local -r remainder=$(echo "$1" | cut -s -d / -f 2-)
     if [[ -n "$remainder" ]]; then
       if [[ -z "${2+x}" ]]; then
         local -r source_repo=$(runfiles_current_repository 2)
diff --git a/tools/bash/runfiles/runfiles_test.bash b/tools/bash/runfiles/runfiles_test.bash
index 1e1c096..d9c3847 100755
--- a/tools/bash/runfiles/runfiles_test.bash
+++ b/tools/bash/runfiles/runfiles_test.bash
@@ -216,10 +216,12 @@
   export RUNFILES_DIR=${tmpdir}/mock/runfiles
   mkdir -p "$RUNFILES_DIR"
   cat > "$RUNFILES_DIR/_repo_mapping" <<EOF
+,config.json,config.json~1.2.3
 ,my_module,_main
 ,my_protobuf,protobuf~3.19.2
 ,my_workspace,_main
 protobuf~3.19.2,protobuf,protobuf~3.19.2
+protobuf~3.19.2,config.json,config.json~1.2.3
 EOF
   export RUNFILES_MANIFEST_FILE=
   source "$runfiles_lib_path"
@@ -258,10 +260,12 @@
   export RUNFILES_DIR=${tmpdir}/mock/runfiles
   mkdir -p "$RUNFILES_DIR"
   cat > "$RUNFILES_DIR/_repo_mapping" <<EOF
+,config.json,config.json~1.2.3
 ,my_module,_main
 ,my_protobuf,protobuf~3.19.2
 ,my_workspace,_main
 protobuf~3.19.2,protobuf,protobuf~3.19.2
+protobuf~3.19.2,config.json,config.json~1.2.3
 EOF
   export RUNFILES_MANIFEST_FILE=
   source "$runfiles_lib_path"
@@ -296,10 +300,12 @@
   local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
 
   cat > "$tmpdir/foo.repo_mapping" <<EOF
+,config.json,config.json~1.2.3
 ,my_module,_main
 ,my_protobuf,protobuf~3.19.2
 ,my_workspace,_main
 protobuf~3.19.2,protobuf,protobuf~3.19.2
+protobuf~3.19.2,config.json,config.json~1.2.3
 EOF
   export RUNFILES_DIR=
   export RUNFILES_MANIFEST_FILE="$tmpdir/foo.runfiles_manifest"
@@ -344,10 +350,12 @@
   local tmpdir="$(mktemp -d $TEST_TMPDIR/tmp.XXXXXXXX)"
 
   cat > "$tmpdir/foo.repo_mapping" <<EOF
+,config.json,config.json~1.2.3
 ,my_module,_main
 ,my_protobuf,protobuf~3.19.2
 ,my_workspace,_main
 protobuf~3.19.2,protobuf,protobuf~3.19.2
+protobuf~3.19.2,config.json,config.json~1.2.3
 EOF
   export RUNFILES_DIR=
   export RUNFILES_MANIFEST_FILE="$tmpdir/foo.runfiles_manifest"
diff --git a/tools/cpp/runfiles/runfiles_test.cc b/tools/cpp/runfiles/runfiles_test.cc
index 4abb19f3..122b184 100644
--- a/tools/cpp/runfiles/runfiles_test.cc
+++ b/tools/cpp/runfiles/runfiles_test.cc
@@ -586,10 +586,12 @@
 
 TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromMain) {
   string uid = LINE_AS_STRING();
-  unique_ptr<MockFile> rm(MockFile::Create(
-      "foo" + uid + ".repo_mapping",
-      {",my_module,_main", ",my_protobuf,protobuf~3.19.2",
-       ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
+  unique_ptr<MockFile> rm(
+      MockFile::Create("foo" + uid + ".repo_mapping",
+                       {",config.json,config.json~1.2.3", ",my_module,_main",
+                        ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main",
+                        "protobuf~3.19.2,config.json,config.json~1.2.3",
+                        "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
   ASSERT_TRUE(rm != nullptr);
   unique_ptr<MockFile> mf(MockFile::Create(
       "foo" + uid + ".runfiles_manifest",
@@ -644,10 +646,12 @@
 
 TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromOtherRepo) {
   string uid = LINE_AS_STRING();
-  unique_ptr<MockFile> rm(MockFile::Create(
-      "foo" + uid + ".repo_mapping",
-      {",my_module,_main", ",my_protobuf,protobuf~3.19.2",
-       ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
+  unique_ptr<MockFile> rm(
+      MockFile::Create("foo" + uid + ".repo_mapping",
+                       {",config.json,config.json~1.2.3", ",my_module,_main",
+                        ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main",
+                        "protobuf~3.19.2,config.json,config.json~1.2.3",
+                        "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
   ASSERT_TRUE(rm != nullptr);
   unique_ptr<MockFile> mf(MockFile::Create(
       "foo" + uid + ".runfiles_manifest",
@@ -699,10 +703,12 @@
 
 TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromMain) {
   string uid = LINE_AS_STRING();
-  unique_ptr<MockFile> rm(MockFile::Create(
-      "foo" + uid + ".runfiles/_repo_mapping",
-      {",my_module,_main", ",my_protobuf,protobuf~3.19.2",
-       ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
+  unique_ptr<MockFile> rm(
+      MockFile::Create("foo" + uid + ".runfiles/_repo_mapping",
+                       {",config.json,config.json~1.2.3", ",my_module,_main",
+                        ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main",
+                        "protobuf~3.19.2,config.json,config.json~1.2.3",
+                        "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
   ASSERT_TRUE(rm != nullptr);
   string dir = rm->DirName();
   string argv0(dir.substr(0, dir.size() - string(".runfiles").size()));
@@ -746,10 +752,12 @@
 
 TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromOtherRepo) {
   string uid = LINE_AS_STRING();
-  unique_ptr<MockFile> rm(MockFile::Create(
-      "foo" + uid + ".runfiles/_repo_mapping",
-      {",my_module,_main", ",my_protobuf,protobuf~3.19.2",
-       ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
+  unique_ptr<MockFile> rm(
+      MockFile::Create("foo" + uid + ".runfiles/_repo_mapping",
+                       {",config.json,config.json~1.2.3", ",my_module,_main",
+                        ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main",
+                        "protobuf~3.19.2,config.json,config.json~1.2.3",
+                        "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
   ASSERT_TRUE(rm != nullptr);
   string dir = rm->DirName();
   string argv0(dir.substr(0, dir.size() - string(".runfiles").size()));
@@ -790,10 +798,12 @@
 TEST_F(RunfilesTest,
        DirectoryBasedRlocationWithRepoMapping_fromOtherRepo_withSourceRepo) {
   string uid = LINE_AS_STRING();
-  unique_ptr<MockFile> rm(MockFile::Create(
-      "foo" + uid + ".runfiles/_repo_mapping",
-      {",my_module,_main", ",my_protobuf,protobuf~3.19.2",
-       ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
+  unique_ptr<MockFile> rm(
+      MockFile::Create("foo" + uid + ".runfiles/_repo_mapping",
+                       {",config.json,config.json~1.2.3", ",my_module,_main",
+                        ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main",
+                        "protobuf~3.19.2,config.json,config.json~1.2.3",
+                        "protobuf~3.19.2,protobuf,protobuf~3.19.2"}));
   ASSERT_TRUE(rm != nullptr);
   string dir = rm->DirName();
   string argv0(dir.substr(0, dir.size() - string(".runfiles").size()));
diff --git a/tools/java/runfiles/testing/RunfilesTest.java b/tools/java/runfiles/testing/RunfilesTest.java
index 8b88ce2..92d420f 100644
--- a/tools/java/runfiles/testing/RunfilesTest.java
+++ b/tools/java/runfiles/testing/RunfilesTest.java
@@ -264,9 +264,11 @@
         tempFile(
             "foo.repo_mapping",
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Path mf =
         tempFile(
@@ -318,9 +320,11 @@
         tempFile(
             "foo.repo_mapping",
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Path mf =
         tempFile(
@@ -367,9 +371,11 @@
         tempFile(
             "foo.repo_mapping",
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Path mf =
         tempFile(
@@ -419,9 +425,11 @@
         tempFile(
             dir.resolve("_repo_mapping").toString(),
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Runfiles r = Runfiles.createDirectoryBasedForTesting(dir.toString()).withSourceRepository("");
 
@@ -458,9 +466,11 @@
         tempFile(
             dir.resolve("_repo_mapping").toString(),
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Runfiles r = Runfiles.createDirectoryBasedForTesting(dir.toString()).unmapped();
 
@@ -497,9 +507,11 @@
         tempFile(
             dir.resolve("_repo_mapping").toString(),
             ImmutableList.of(
+                ",config.json,config.json~1.2.3",
                 ",my_module,_main",
                 ",my_protobuf,protobuf~3.19.2",
                 ",my_workspace,_main",
+                "protobuf~3.19.2,config.json,config.json~1.2.3",
                 "protobuf~3.19.2,protobuf,protobuf~3.19.2"));
     Runfiles r =
         Runfiles.createDirectoryBasedForTesting(dir.toString())