[autotest] Bug fix:

1) modified parse.py to log test.testname and test.subdir
2) modified version_1.py to report abort for each unexpected
indent using line.testname as testname.
3) modified version_1_unittest to add test for abort with no
testname or no subdir

BUG=chromium:761689
TEST=Ran unit tests for version_1.py; ran parse.py against several
status.log with and without unexpected indents

Change-Id: I03a3852df38ccfaabf216427398493f50619bbe3
Reviewed-on: https://chromium-review.googlesource.com/648643
Commit-Ready: Sida Liu <sidal@chromium.org>
Tested-by: Sida Liu <sidal@chromium.org>
Reviewed-by: Sida Liu <sidal@chromium.org>
Reviewed-by: Michael Tang <ntang@chromium.org>
(cherry picked from commit afe550a63024ebaf0dcb37870cd394998f748d71)
Reviewed-on: https://chromium-review.googlesource.com/847958
Reviewed-by: Keith Haddow <haddowk@chromium.org>
Commit-Queue: Keith Haddow <haddowk@chromium.org>
Tested-by: Keith Haddow <haddowk@chromium.org>
diff --git a/tko/parse.py b/tko/parse.py
index 2aec4e8..c4b398f 100755
--- a/tko/parse.py
+++ b/tko/parse.py
@@ -412,8 +412,9 @@
     for test in job.tests:
         if not test.subdir:
             continue
-        tko_utils.dprint("* testname, status, reason: %s %s %s"
-                         % (test.subdir, test.status, test.reason))
+        tko_utils.dprint("* testname, subdir, status, reason: %s %s %s %s"
+                         % (test.testname, test.subdir, test.status,
+                            test.reason))
         if test.status != 'GOOD':
             job_successful = False
             message_lines.append(format_failure_message(
diff --git a/tko/parsers/version_1.py b/tko/parsers/version_1.py
index a541979..728ce48 100644
--- a/tko/parsers/version_1.py
+++ b/tko/parsers/version_1.py
@@ -278,7 +278,7 @@
 
     @staticmethod
     def put_back_line_and_abort(
-        line_buffer, line, indent, subdir, timestamp, reason):
+        line_buffer, line, indent, subdir, testname, timestamp, reason):
         """
         Appends a line to the line buffer and aborts.
 
@@ -286,6 +286,7 @@
         @param line: A line to append to the line buffer.
         @param indent: The number of indentation levels.
         @param subdir: The subdirectory name.
+        @param testname: The test name.
         @param timestamp: The timestamp value.
         @param reason: The reason string.
 
@@ -293,11 +294,17 @@
         tko_utils.dprint('Unexpected indent: aborting log parse')
         line_buffer.put_back(line)
         abort = parser.make_dummy_abort(
-            indent, subdir, subdir, timestamp, reason)
+            indent, subdir, testname, timestamp, reason)
         line_buffer.put_back(abort)
 
 
     def state_iterator(self, buffer):
+        """
+        Yields a list of tests out of the buffer.
+
+        @param buffer: a buffer object
+
+        """
         line = None
         new_tests = []
         job_count, boot_count = 0, 0
@@ -308,12 +315,16 @@
         current_reason = None
         started_time_stack = [None]
         subdir_stack = [None]
+        testname_stack = [None]
         running_test = None
         running_reasons = set()
         ignored_lines = []
         yield []   # We're ready to start running.
 
         def print_ignored_lines():
+            """
+            Prints the ignored_lines using tko_utils.dprint method.
+            """
             tko_utils.dprint('The following lines were ignored:')
             for line in ignored_lines:
                 tko_utils.dprint(line)
@@ -382,7 +393,8 @@
                 # ABORT the current level if indentation was unexpectedly low.
                 self.put_back_line_and_abort(
                     buffer, raw_line, stack.size() - 1, subdir_stack[-1],
-                    line.optional_fields.get('timestamp'), line.reason)
+                    testname_stack[-1], line.optional_fields.get('timestamp'),
+                    line.reason)
                 continue
             elif line.indent > expected_indent:
                 # Ignore the log if the indent was unexpectedly high.
@@ -393,6 +405,7 @@
             if line.type == 'START':
                 stack.start()
                 started_time = line.get_timestamp()
+                testname = None
                 if (line.testname is None and line.subdir is None
                     and not running_test):
                     # We just started a client; all tests are relative to here.
@@ -407,6 +420,7 @@
                     msg %= (running_client.status, running_client.testname)
                     tko_utils.dprint(msg)
                     new_tests.append(running_client)
+                    testname = running_client.testname
                 elif stack.size() == min_stack_size + 1 and not running_test:
                     # We just started a new test; insert a running record.
                     running_reasons = set()
@@ -423,8 +437,10 @@
                             running_test.testname, running_test.reason)
                     tko_utils.dprint(msg)
                     new_tests.append(running_test)
+                    testname = running_test.testname
                 started_time_stack.append(started_time)
                 subdir_stack.append(line.subdir)
+                testname_stack.append(testname)
                 continue
             elif line.type == 'INFO':
                 fields = line.optional_fields
@@ -440,6 +456,7 @@
                 # Update the stacks.
                 if line.subdir and stack.size() > min_stack_size:
                     subdir_stack[-1] = line.subdir
+                    testname_stack[-1] = line.testname
                 # Update the status, start and finished times.
                 stack.update(line.status)
                 if status_lib.is_worse_than_or_equal_to(line.status,
@@ -471,8 +488,10 @@
                     and not running_test):
                     min_stack_size = stack.size() - 1
                     subdir_stack.pop()
+                    testname_stack.pop()
                 else:
                     line.subdir = subdir_stack.pop()
+                    testname_stack.pop()
                     if not subdir_stack[-1] and stack.size() > min_stack_size:
                         subdir_stack[-1] = line.subdir
                 # Update the status, start and finished times.
diff --git a/tko/parsers/version_1_unittest.py b/tko/parsers/version_1_unittest.py
index ad5ac93..3af5563 100755
--- a/tko/parsers/version_1_unittest.py
+++ b/tko/parsers/version_1_unittest.py
@@ -325,6 +325,7 @@
 
     def setUp(self):
         self.indent = 3
+        self.subdir = "subdir"
         self.testname = 'testname'
         self.timestamp = 1220565792
         self.reason = 'Job aborted unexpectedly'
@@ -333,19 +334,36 @@
     def test_make_dummy_abort_with_timestamp(self):
         """Tests make_dummy_abort with a timestamp specified."""
         abort = version_1.parser.make_dummy_abort(
+            self.indent, self.subdir, self.testname, self.timestamp,
+            self.reason)
+        self.assertEquals(
+            abort, '%sEND ABORT\t%s\t%s\ttimestamp=%d\t%s' % (
+            '\t' * self.indent, self.subdir, self.testname, self.timestamp,
+            self.reason))
+
+    def test_make_dummy_abort_with_no_subdir(self):
+        """Tests make_dummy_abort with no subdir specified."""
+        abort= version_1.parser.make_dummy_abort(
             self.indent, None, self.testname, self.timestamp, self.reason)
         self.assertEquals(
             abort, '%sEND ABORT\t----\t%s\ttimestamp=%d\t%s' % (
             '\t' * self.indent, self.testname, self.timestamp, self.reason))
 
+    def test_make_dummy_abort_with_no_testname(self):
+        """Tests make_dummy_abort with no testname specified."""
+        abort= version_1.parser.make_dummy_abort(
+        self.indent, self.subdir, None, self.timestamp, self.reason)
+        self.assertEquals(
+            abort, '%sEND ABORT\t%s\t----\ttimestamp=%d\t%s' % (
+            '\t' * self.indent, self.subdir, self.timestamp, self.reason))
 
     def test_make_dummy_abort_no_timestamp(self):
         """Tests make_dummy_abort with no timestamp specified."""
         abort = version_1.parser.make_dummy_abort(
-            self.indent, None, self.testname, None, self.reason)
+            self.indent, self.subdir, self.testname, None, self.reason)
         self.assertEquals(
-            abort, '%sEND ABORT\t----\t%s\t%s' % (
-            '\t' * self.indent, self.testname, self.reason))
+            abort, '%sEND ABORT\t%s\t%s\t%s' % (
+            '\t' * self.indent, self.subdir, self.testname, self.reason))
 
 
 if __name__ == '__main__':