[autotest] add pattern matching ability to test_that's tests arg

This CL adds two type of test pattern matching to test_that. Patterns
can now be specified with e:[test name pattern] or f:[file name pattern]
as the TEST argument to test_that.

It also demotes the complaint "Getting control files for a specific suite
has not been implemented for FileSystemGetter.' to DEBUG level, so it
doesn't cause test_that user confusion.

BUG=chromium:214066
TEST=Unit tests pass. Also...
Suite names still work the same way:
$ test_that [remote] suite:smoke # smoke suite scheduled correctly
Test name patterns work, like this:
$ test_that [remote] e:cantelope # No tests scheduled, test_that errors out
$ test_that [remote] e:dummy # No tests scheduled
$ test_that [remote] e:dummy.* # 6 tests whose name begin with dummy
                               # scheduled
File name pattern work, like this:
$ test_that [remote] f:dummy # # No tests scheduled.
$ test_that [remote] f:.*dummy.* # 8 tests scheduled
$ test_that [remote] f:.*server.*dummy.* # 2 tests scheduled
$ test_that [remote] f:.*client.*dummy.* # 6 tests scheduled

Change-Id: I104847bdf7956e020f2581128946471d1794b8d2
Reviewed-on: https://chromium-review.googlesource.com/167668
Tested-by: Aviv Keshet <akeshet@chromium.org>
Reviewed-by: Prashanth Balasubramanian <beeps@chromium.org>
Commit-Queue: Aviv Keshet <akeshet@chromium.org>
diff --git a/server/cros/dynamic_suite/suite.py b/server/cros/dynamic_suite/suite.py
index 0278c9a..b5405a2 100644
--- a/server/cros/dynamic_suite/suite.py
+++ b/server/cros/dynamic_suite/suite.py
@@ -112,6 +112,39 @@
 
 
     @staticmethod
+    def test_name_matches_pattern_predicate(test_name_pattern):
+        """Returns predicate that matches based on a test's name pattern.
+
+        Builds a predicate that takes in a parsed control file (a ControlData)
+        and returns True if the test name matches the given regular expression.
+
+        @param test_name_pattern: regular expression (string) to match against
+                                  test names.
+        @return a callable that takes a ControlData and returns
+                True if the name fields matches the pattern.
+        """
+        return lambda t: hasattr(t, 'name') and re.match(test_name_pattern,
+                                                         t.name)
+
+
+    @staticmethod
+    def test_file_matches_pattern_predicate(test_file_pattern):
+        """Returns predicate that matches based on a test's file name pattern.
+
+        Builds a predicate that takes in a parsed control file (a ControlData)
+        and returns True if the test's control file name matches the given
+        regular expression.
+
+        @param test_file_pattern: regular expression (string) to match against
+                                  control file names.
+        @return a callable that takes a ControlData and and returns
+                True if control file name matches the pattern.
+        """
+        return lambda t: hasattr(t, 'path') and re.match(test_file_pattern,
+                                                         t.path)
+
+
+    @staticmethod
     def list_all_suites(build, devserver, cf_getter=None):
         """
         Parses all ControlData objects with a SUITE tag and extracts all