Stack: Fix tool for long stacks

To make the comparison meaningful, better compare integrals rather
than strings.

Test: ./stack_core.py
Change-Id: Ie24bea75d7c0bc57a1b7683b91e62fafead70341
diff --git a/scripts/example_crashes.py b/scripts/example_crashes.py
index 29f4c94..be72f88 100755
--- a/scripts/example_crashes.py
+++ b/scripts/example_crashes.py
@@ -199,3 +199,32 @@
           #00  pc 000076ae  /system/lib/libcutils.so (set_process_name+45)
           #01  pc 000989d6  /system/lib/libandroid_runtime.so (android_os_Process_setArgV0(_JNIEnv*, _jobject*, _jstring*)+125)
 """
+
+# This is a long crash in ASAN format, which does not pad frame numbers. This should be used
+# in a test to ensure that the stack is not split into two (see stack_core's test_long_asan_crash).
+long_asan_crash = """
+Build fingerprint: 'Android/aosp_arm/generic_arm:4.4.3.43.43.43/AOSP/enh06302258:eng/test-keys'
+ABI: 'arm'
+
+     #0 0x727d4dfdaf  (/system/lib/libclang_rt.asan-arm-android.so+0x31daf)
+
+     #1 0x727d4e00af  (/system/lib/libclang_rt.asan-arm-android.so+0x320af)
+
+     #2 0x72778db0cf  (/data/lib/libc.so+0x740cf)
+
+     #3 0x725688a66f  (/does/not/matter/a.so+0x1066f)
+
+     #4 0x72568a02af  (/does/not/matter/a.so+0x262af)
+
+     #5 0x725689e313  (/does/not/matter/a.so+0x24313)
+
+     #6 0x72568a95eb  (/does/not/matter/a.so+0x2f5eb)
+
+     #7 0x725688de6f  (/does/not/matter/a.so+0x13e6f)
+
+     #8 0x72778ceeff  (/does/not/matter/a.so+0x67eff)
+
+     #9 0x7277884983  (/does/not/matter/a.so+0x1d983)
+
+     #10 0x7277884983  (/does/not/matter/a.so+0x1d983)
+"""
diff --git a/scripts/stack_core.py b/scripts/stack_core.py
index 6750667..f792809 100755
--- a/scripts/stack_core.py
+++ b/scripts/stack_core.py
@@ -343,7 +343,7 @@
     trace_line_dict = self.MatchTraceLine(line)
     if trace_line_dict is not None:
       ret = True
-      frame = trace_line_dict["frame"]
+      frame = int(trace_line_dict["frame"])
       code_addr = trace_line_dict["offset"]
       area = trace_line_dict["dso"]
       so_offset = trace_line_dict["so_offset"]
@@ -476,5 +476,26 @@
     self.assertEquals(len(tc.trace_lines), 2)
     tc.PrintOutput(tc.trace_lines, tc.value_lines)
 
+class LongASANStackTests(unittest.TestCase):
+  # Test that a long ASAN-style (non-padded frame numbers) stack trace is not split into two
+  # when the frame number becomes two digits. This happened before as the frame number was
+  # handled as a string and not converted to an integral.
+  def test_long_asan_crash(self):
+    tc = TraceConverter()
+    lines = example_crashes.long_asan_crash.splitlines()
+    symbol.SetAbi(lines)
+    tc.UpdateAbiRegexes()
+    # Test by making sure trace_line_count is monotonically non-decreasing. If the stack trace
+    # is split, a separator is printed and trace_lines is flushed.
+    trace_line_count = 0
+    for line in lines:
+      tc.ProcessLine(line)
+      self.assertLessEqual(trace_line_count, len(tc.trace_lines))
+      trace_line_count = len(tc.trace_lines)
+    # The split happened at transition of frame #9 -> #10. Make sure we have parsed (and stored)
+    # more than ten frames.
+    self.assertGreater(trace_line_count, 10)
+    tc.PrintOutput(tc.trace_lines, tc.value_lines)
+
 if __name__ == '__main__':
     unittest.main()