Properly escape '(' and ')' in globs when compiling to regexp.

And take the opportunity to improve our tests for special regexp characters in globs.

RELNOTES: None.
PiperOrigin-RevId: 306925343
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java b/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java
index f3ab083..3608775 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/UnixGlob.java
@@ -249,10 +249,19 @@
         case '?':
           regexp.append('.');
           break;
-        //escape the regexp special characters that are allowed in wildcards
-        case '^': case '$': case '|': case '+':
-        case '{': case '}': case '[': case ']':
-        case '\\': case '.':
+        case '^':
+        case '$':
+        case '|':
+        case '+':
+        case '(':
+        case ')':
+        case '{':
+        case '}':
+        case '[':
+        case ']':
+        case '\\':
+        case '.':
+          // escape the regexp special characters that are allowed in wildcards
           regexp.append('\\');
           regexp.append(c);
           break;
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
index f31bb71..6d17bba 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/GlobTest.java
@@ -276,11 +276,27 @@
     FileSystemUtils.createDirectoryAndParents(tmpPath2);
     Path aDotB = tmpPath2.getChild("a.b");
     FileSystemUtils.createEmptyFile(aDotB);
+    Path aPlusB = tmpPath2.getChild("a+b");
+    FileSystemUtils.createEmptyFile(aPlusB);
+    Path aWordCharacterB = tmpPath2.getChild("a\\wb");
+    FileSystemUtils.createEmptyFile(aWordCharacterB);
+    Path groupsAndBrackets = tmpPath2.getChild("(a|b){1,2}[ab]");
+    FileSystemUtils.createEmptyFile(groupsAndBrackets);
+    Path lineNoise = tmpPath2.getChild("\\|}{[(])(.+");
+    FileSystemUtils.createEmptyFile(lineNoise);
     FileSystemUtils.createEmptyFile(tmpPath2.getChild("aab"));
-    // Note: this contains two asterisks because otherwise a RE is not built,
+    // Note: these contain two asterisks because otherwise a RE is not built,
     // as an optimization.
-    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*a.b*").globInterruptible()).containsExactly(
-        aDotB);
+    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*a.b*").globInterruptible())
+        .containsExactly(aDotB);
+    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*a+b*").globInterruptible())
+        .containsExactly(aPlusB);
+    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*a\\wb*").globInterruptible())
+        .containsExactly(aWordCharacterB);
+    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*(a|b){1,2}[ab]*").globInterruptible())
+        .containsExactly(groupsAndBrackets);
+    assertThat(UnixGlob.forPath(tmpPath2).addPattern("*\\|}{[(])(.+*").globInterruptible())
+        .containsExactly(lineNoise);
   }
 
   @Test