Autotest: Filter out invalid test names.

BUG=chromium:253597
DEPLOY=none
TEST=Unittests plus ran script and manually verified.

Change-Id: Ifcdc9934438d9701bfc62e5595bb6b25e4a1e590
Reviewed-on: https://gerrit.chromium.org/gerrit/59841
Commit-Queue: Keyar Hood <keyar@chromium.org>
Reviewed-by: Keyar Hood <keyar@chromium.org>
Tested-by: Keyar Hood <keyar@chromium.org>
diff --git a/frontend/health/complete_failures.py b/frontend/health/complete_failures.py
index fffad8d..c5790ec 100644
--- a/frontend/health/complete_failures.py
+++ b/frontend/health/complete_failures.py
@@ -47,6 +47,25 @@
     storage.close()
 
 
+def is_valid_test_name(name):
+    """
+    Returns if a test name is valid or not.
+
+    There is a bunch of entries in the tko_test table that are not actually
+    test names. They are there as a side effect of how Autotest uses this
+    table.
+
+    Two examples of bad tests names are as follows:
+    link-release/R29-4228.0.0/faft_ec/firmware_ECPowerG3_SERVER_JOB
+    try_new_image-chormeos1-rack2-host2
+
+    @param name: The candidate test names to check.
+    @return True if name is a valid test name and false otherwise.
+
+    """
+    return not '/' in name and not name.startswith('try_new_image')
+
+
 def get_last_pass_times():
     """
     Get all the tests that have passed and the time they last passed.
@@ -58,10 +77,13 @@
     results = tko_models.Test.objects.values('test').filter(
         status=_TEST_PASS_STATUS_INDEX).annotate(
         last_pass=django_models.Max('started_time'))
-    # The shelve module does not accept Unicode objects as keys but utf-8
-    # strings are.
-    return {result['test'].encode('utf8'): result['last_pass']
-            for result in results}
+    results_dict = {result['test']: result['last_pass']
+                    for result in results}
+    valid_test_names = filter(is_valid_test_name, results_dict)
+    # The shelve module does not accept Unicode objects as keys but does
+    # accept utf-8 strings.
+    return {name.encode('utf8'): results_dict[name]
+            for name in valid_test_names}
 
 
 def get_all_test_names():
@@ -71,8 +93,10 @@
     @return a list of all the test names.
 
     """
-    test_names = tko_models.Test.objects.values('test').distinct()
-    return [test['test'].encode('utf8') for test in test_names]
+    results = tko_models.Test.objects.values('test').distinct()
+    test_names = [test['test'] for test in results]
+    valid_test_names = filter(is_valid_test_name, test_names)
+    return [test.encode('utf8') for test in valid_test_names]
 
 
 def get_tests_to_analyze():
diff --git a/frontend/health/complete_failures_functional_test.py b/frontend/health/complete_failures_functional_test.py
index 0b0a944..b6c8585 100755
--- a/frontend/health/complete_failures_functional_test.py
+++ b/frontend/health/complete_failures_functional_test.py
@@ -78,21 +78,21 @@
 
     def test(self):
         """Does a basic test of as much of the system as possible."""
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
-        fail_status = models.Status(status_idx = FAIL_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
+        fail_status = models.Status(status_idx=FAIL_STATUS_IDX)
 
-        passing_test = models.Test(job = job, status = success_status,
-                                   kernel = kernel, machine = machine,
-                                   test = 'test1',
-                                   started_time = self.datetime(2012, 1, 1))
+        passing_test = models.Test(job=job, status=success_status,
+                                   kernel=kernel, machine=machine,
+                                   test='test1',
+                                   started_time=self.datetime(2012, 1, 1))
         passing_test.save()
-        failing_test = models.Test(job = job, status = fail_status,
-                                   kernel = kernel, machine = machine,
-                                   test = 'test2',
-                                   started_time = self.datetime.min)
+        failing_test = models.Test(job=job, status=fail_status,
+                                   kernel=kernel, machine=machine,
+                                   test='test2',
+                                   started_time=self.datetime.min)
         failing_test.save()
 
         complete_failures._DAYS_TO_BE_FAILING_TOO_LONG = 10
diff --git a/frontend/health/complete_failures_unittest.py b/frontend/health/complete_failures_unittest.py
index 044f06e..a08344c 100755
--- a/frontend/health/complete_failures_unittest.py
+++ b/frontend/health/complete_failures_unittest.py
@@ -144,6 +144,27 @@
         self.assertTrue('test' in storage)
 
 
+class IsValidTestNameTests(test.TestCase):
+    """Tests the is_valid_test_name function."""
+
+    def test_returns_true_for_valid_test_name(self):
+        """Test that a valid test name returns True."""
+        name = 'TestName.TestName'
+        self.assertTrue(complete_failures.is_valid_test_name(name))
+
+
+    def test_returns_false_if_name_has_slash_in_it(self):
+        """Test that a name with a slash in it returns False."""
+        name = 'path/to/test'
+        self.assertFalse(complete_failures.is_valid_test_name(name))
+
+
+    def test_returns_false_for_try_new_image_entries(self):
+        """Test that a name that starts with try_new_image returns False."""
+        name = 'try_new_image-blah'
+        self.assertFalse(complete_failures.is_valid_test_name(name))
+
+
 class GetLastPassTimesTests(mox.MoxTestBase, test.TestCase):
     """Tests the get_last_pass_times function."""
 
@@ -162,20 +183,20 @@
         # To add a test entry to the database, Django the test object to
         # be instantiated with various other model instances. We give these
         # instances dummy id values.
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
 
-        early_pass = models.Test(job = job, status = success_status,
-                                 kernel = kernel, machine = machine,
-                                 test = 'test',
-                                 started_time = datetime.datetime(2012, 1, 1))
+        early_pass = models.Test(job=job, status=success_status,
+                                 kernel=kernel, machine=machine,
+                                 test='test',
+                                 started_time=datetime.datetime(2012, 1, 1))
         early_pass.save()
-        late_pass = models.Test(job = job, status = success_status,
-                                kernel = kernel, machine = machine,
-                                test = 'test',
-                                started_time = datetime.datetime(2012, 1, 2))
+        late_pass = models.Test(job=job, status=success_status,
+                                kernel=kernel, machine=machine,
+                                test='test',
+                                started_time=datetime.datetime(2012, 1, 2))
         late_pass.save()
 
         results = complete_failures.get_last_pass_times()
@@ -185,21 +206,21 @@
 
     def test_only_return_passing_tests(self):
         """Tests that only tests that have passed at some point are returned."""
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
-        fail_status = models.Status(status_idx = FAIL_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
+        fail_status = models.Status(status_idx=FAIL_STATUS_IDX)
 
-        passing_test = models.Test(job = job, status = success_status,
-                                   kernel = kernel, machine = machine,
-                                   test = 'passing_test',
-                                   started_time = datetime.datetime(2012, 1, 1))
+        passing_test = models.Test(job=job, status=success_status,
+                                   kernel=kernel, machine=machine,
+                                   test='passing_test',
+                                   started_time=datetime.datetime(2012, 1, 1))
         passing_test.save()
-        failing_test = models.Test(job = job, status = fail_status,
-                                   kernel = kernel, machine = machine,
-                                   test = 'failing_test',
-                                   started_time = datetime.datetime(2012, 1, 1))
+        failing_test = models.Test(job=job, status=fail_status,
+                                   kernel=kernel, machine=machine,
+                                   test='failing_test',
+                                   started_time=datetime.datetime(2012, 1, 1))
         failing_test.save()
 
         results = complete_failures.get_last_pass_times()
@@ -210,20 +231,20 @@
 
     def test_return_all_passing_tests(self):
         """This function returns all tests that passed at least once."""
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
 
-        test1 = models.Test(job = job, status = success_status,
-                            kernel = kernel, machine = machine,
-                            test = 'test1',
-                            started_time = datetime.datetime(2012, 1, 1))
+        test1 = models.Test(job=job, status=success_status,
+                            kernel=kernel, machine=machine,
+                            test='test1',
+                            started_time=datetime.datetime(2012, 1, 1))
         test1.save()
-        test2 = models.Test(job = job, status = success_status,
-                            kernel = kernel, machine = machine,
-                            test = 'test2',
-                            started_time = datetime.datetime(2012, 1, 2))
+        test2 = models.Test(job=job, status=success_status,
+                            kernel=kernel, machine=machine,
+                            test='test2',
+                            started_time=datetime.datetime(2012, 1, 2))
         test2.save()
 
         results = complete_failures.get_last_pass_times()
@@ -232,6 +253,25 @@
                                     'test2': datetime.datetime(2012, 1, 2)})
 
 
+    def test_does_not_return_invalid_test_names(self):
+        """Tests that tests with invalid test names are not returned."""
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
+        fail_status = models.Status(status_idx=FAIL_STATUS_IDX)
+
+        invalid_test = models.Test(job=job, status=success_status,
+                                  kernel=kernel, machine=machine,
+                                  test='invalid_test/name',
+                                  started_time=datetime.datetime(2012, 1, 1))
+        invalid_test.save()
+
+        results = complete_failures.get_last_pass_times()
+
+        self.assertTrue(not results)
+
+
 class GetAllTestNamesTests(mox.MoxTestBase, test.TestCase):
     """Tests the get_all_test_names function."""
 
@@ -247,20 +287,20 @@
 
     def test_return_all_tests(self):
         """Test that the function does as it says it does."""
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
 
-        test1 = models.Test(job = job, status = success_status,
-                            kernel = kernel, machine = machine,
-                            test = 'test1',
-                            started_time = datetime.datetime(2012, 1, 1))
+        test1 = models.Test(job=job, status=success_status,
+                            kernel=kernel, machine=machine,
+                            test='test1',
+                            started_time=datetime.datetime(2012, 1, 1))
         test1.save()
-        test2 = models.Test(job = job, status = success_status,
-                            kernel = kernel, machine = machine,
-                            test = 'test2',
-                            started_time = datetime.datetime(2012, 1, 2))
+        test2 = models.Test(job=job, status=success_status,
+                            kernel=kernel, machine=machine,
+                            test='test2',
+                            started_time=datetime.datetime(2012, 1, 2))
         test2.save()
 
         results = complete_failures.get_all_test_names()
@@ -270,20 +310,20 @@
 
     def test_returns_no_duplicate_names(self):
         """Test that each test name appears only once."""
-        job = models.Job(job_idx = 1)
-        kernel = models.Kernel(kernel_idx = 1)
-        machine = models.Machine(machine_idx = 1)
-        success_status = models.Status(status_idx = GOOD_STATUS_IDX)
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
 
-        test = models.Test(job = job, status = success_status,
-                           kernel = kernel, machine = machine,
-                           test = 'test',
-                           started_time = datetime.datetime(2012, 1, 1))
+        test = models.Test(job=job, status=success_status,
+                           kernel=kernel, machine=machine,
+                           test='test',
+                           started_time=datetime.datetime(2012, 1, 1))
         test.save()
-        duplicate = models.Test(job = job, status = success_status,
-                                kernel = kernel, machine = machine,
-                                test = 'test',
-                                started_time = datetime.datetime(2012, 1, 2))
+        duplicate = models.Test(job=job, status=success_status,
+                                kernel=kernel, machine=machine,
+                                test='test',
+                                started_time=datetime.datetime(2012, 1, 2))
         duplicate.save()
 
         results = complete_failures.get_all_test_names()
@@ -291,6 +331,24 @@
         self.assertEqual(len(results), 1)
 
 
+    def test_does_not_return_invalid_test_names(self):
+        """Tests that only tests with invalid test names are not returned."""
+        job = models.Job(job_idx=1)
+        kernel = models.Kernel(kernel_idx=1)
+        machine = models.Machine(machine_idx=1)
+        success_status = models.Status(status_idx=GOOD_STATUS_IDX)
+
+        invalid_test = models.Test(job=job, status=success_status,
+                                   kernel=kernel, machine=machine,
+                                   test='invalid_test/name',
+                                   started_time=datetime.datetime(2012, 1, 1))
+        invalid_test.save()
+
+        results = complete_failures.get_all_test_names()
+
+        self.assertTrue(not results)
+
+
 class GetTestsToAnalyzeTests(mox.MoxTestBase):
     """Tests the get_tests_to_analyze function."""