Various minor improvements to recipe_simulation_test.py.

* Implicitly append '*' to the test glob. That way
  'recipe_simluation_test train <recipe_name>' will actually discover required
  tests (named <recipe_name>.<test_name>) which is expected behavior.
* Print a message and fail the run if given test glob doesn't match any tests.
* Do not break in mods.step.API.__call__ when running in debug mode. It's
  very confusing. Still break at GenSteps though.

R=iannucci@chromium.org
BUG=

Review URL: https://codereview.chromium.org/240053005

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/build@264370 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/scripts/slave/unittests/expect_tests/main.py b/scripts/slave/unittests/expect_tests/main.py
index c2ab701..5d8c7db 100644
--- a/scripts/slave/unittests/expect_tests/main.py
+++ b/scripts/slave/unittests/expect_tests/main.py
@@ -62,7 +62,8 @@
         'test_glob', nargs='*', help=(
             'glob to filter the tests acted on. If the glob begins with "-" '
             'then it acts as a negation glob and anything which matches it '
-            'will be skipped.'))
+            'will be skipped. If a glob doesn\'t have "*" in it, "*" will be '
+            'implicitly appended to the end'))
 
   opts = parser.parse_args(args)
 
diff --git a/scripts/slave/unittests/expect_tests/pipeline.py b/scripts/slave/unittests/expect_tests/pipeline.py
index d3fb32a..09136b2 100644
--- a/scripts/slave/unittests/expect_tests/pipeline.py
+++ b/scripts/slave/unittests/expect_tests/pipeline.py
@@ -10,7 +10,8 @@
 import traceback
 
 from .type_definitions import (
-    Test, UnknownError, TestError, Result, ResultStageAbort)
+    Test, UnknownError, TestError, NoMatchingTestsError,
+    Result, ResultStageAbort)
 
 
 def gen_loop_process(gen, test_queue, result_queue, opts, kill_switch,
@@ -28,18 +29,22 @@
   @type kill_switch: multiprocessing.Event()
   @type cover_ctx: cover.CoverageContext().create_subprocess_context()
   """
+  # Implicitly append '*'' to globs that don't specify it.
+  globs = ['%s%s' % (g, '*' if '*' not in g else '') for g in opts.test_glob]
+
   matcher = re.compile(
       '^%s$' % '|'.join('(?:%s)' % glob.fnmatch.translate(g)
-                        for g in opts.test_glob if g[0] != '-'))
+                        for g in globs if g[0] != '-'))
   if matcher.pattern == '^$':
     matcher = re.compile('^.*$')
 
   neg_matcher = re.compile(
       '^%s$' % '|'.join('(?:%s)' % glob.fnmatch.translate(g[1:])
-                        for g in opts.test_glob if g[0] == '-'))
+                        for g in globs if g[0] == '-'))
 
   def generate_tests():
     paths_seen = set()
+    seen_tests = False
     try:
       for test in gen():
         if kill_switch.is_set():
@@ -58,7 +63,10 @@
         else:
           paths_seen.add(test_path)
           if not neg_matcher.match(test.name) and matcher.match(test.name):
+            seen_tests = True
             yield test
+      if not seen_tests:
+        result_queue.put_nowait(NoMatchingTestsError())
     except KeyboardInterrupt:
       pass
     finally:
diff --git a/scripts/slave/unittests/expect_tests/type_definitions.py b/scripts/slave/unittests/expect_tests/type_definitions.py
index 4959876..913d26f 100644
--- a/scripts/slave/unittests/expect_tests/type_definitions.py
+++ b/scripts/slave/unittests/expect_tests/type_definitions.py
@@ -8,6 +8,7 @@
 
 UnknownError = namedtuple('UnknownError', 'message')
 TestError = namedtuple('TestError', 'test message')
+NoMatchingTestsError = namedtuple('NoMatchingTestsError', '')
 Result = namedtuple('Result', 'data')
 
 class ResultStageAbort(Exception):
@@ -169,6 +170,11 @@
       """
       return getattr(self, 'handle_' + type(obj).__name__, self.__unknown)(obj)
 
+    def handle_NoMatchingTestsError(self, _error):
+      print 'No tests found that match the glob: %s' % (
+          ' '.join(self.opts.test_glob),)
+      return Failure()
+
     def __unknown(self, obj):
       if self.opts.verbose:
         print 'UNHANDLED:', obj
diff --git a/scripts/slave/unittests/recipe_simulation_test.py b/scripts/slave/unittests/recipe_simulation_test.py
index d45149f..66e5601 100755
--- a/scripts/slave/unittests/recipe_simulation_test.py
+++ b/scripts/slave/unittests/recipe_simulation_test.py
@@ -29,8 +29,6 @@
 
 
 def GenerateTests():
-  mods = recipe_loader.load_recipe_modules(recipe_loader.MODULE_DIRS())
-
   for recipe_path, recipe_name in recipe_loader.loop_over_recipes():
     recipe = recipe_loader.load_recipe(recipe_name)
     test_api = recipe_loader.create_test_api(recipe.DEPS)
@@ -45,7 +43,7 @@
           RunRecipe, args=(test_data,),
           expect_dir=expect_path,
           expect_base=test_data.name,
-          break_funcs=(mods.step.API.__call__, recipe.GenSteps)
+          break_funcs=(recipe.GenSteps,)
       )