tests: convert the test suite to use more of the LLVM test utilities

This converts the project from the custom test runner to use the LLVM
test tools.  While this is still not ready to integrate into the test
runs on CI, this is slowly working towards that polish.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58f5b79..8c539d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -334,6 +334,20 @@
   if (IS_DIRECTORY "${PROJECT_SOURCE_DIR}/tests")
     enable_testing()
 
+    find_package(Python COMPONENTS Interpreter)
+    if(Python_FOUND)
+      set(BLOATY_SRC_DIR ${PROJECT_SOURCE_DIR})
+      set(BLOATY_OBJ_DIR ${PROJECT_BINARY_DIR})
+      configure_file(tests/lit.site.cfg.in tests/lit.site.cfg @ONLY)
+
+      # TODO(abdulras) polish this further and convert this to `add_test` so that
+      # the default test suite run executes the tests.
+      add_custom_target(check-bloaty
+        COMMAND ${Python_EXECUTABLE} ${LIT_EXECUTABLE} -sv ${PROJECT_BINARY_DIR}/tests
+        COMMENT "Running bloaty tests..."
+        USES_TERMINAL)
+    endif()
+
     if(BUILD_TESTING)
       option(INSTALL_GTEST "" OFF)
       add_subdirectory(third_party/googletest)
diff --git a/README.md b/README.md
index 096d7a8..fa5f66b 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,32 @@
 $ make -j6
 ```
 
+### Running the new extended test suite
+
+> NOTE: these tests are still experimental and not covered under CI yet.  Please
+> report any issues in running them.
+
+When configuring the project via CMake, a few additional parameters must be
+specified currently:
+- `-DLIT_EXECUTABLE=<PATH>`: specifies where to find the lit tool
+- `-DFILECHECK_EXECUTABLE=<PATH>`: specifies where to find the FileCheck tool
+- `-DYAML2OBJ_EXECUTABLE=<PATH>`: specifies where to find the yaml2obj tool
+
+You can install lit via pip:
+```sh
+pip install --user lit
+```
+
+The FileCheck utility and yaml2obj currently need to be provided by the user.
+These are part of the LLVM toolchain and require a very recent build
+(development release from the main branch) to run the tests.
+
+```sh
+cmake -B build -G Ninja -S . -DLIT_EXECUTABLE=${HOME}/Library/Python/3.8/bin/lit -DFILECHECK_EXECUTABLE=${HOME}/BinaryCache/llvm.org/bin/FileCheck -DYAML2OBJ_EXECUTABLE=${HOME}/BinaryCache/llvm.org/bin/yaml2obj
+cmake --build build --config Debug
+cmake --build build --target check-bloaty
+```
+
 ## Running Bloaty
 
 Run it directly on a binary target.  For example, run it on itself.
diff --git a/tests/dwarf/range_lists/base-addr-selection.test b/tests/dwarf/range_lists/base-addr-selection.test
index 8efc530..faa5dea 100644
--- a/tests/dwarf/range_lists/base-addr-selection.test
+++ b/tests/dwarf/range_lists/base-addr-selection.test
@@ -3,6 +3,9 @@
 # a special kind of entry where the end address signifies the new base
 # address.
 
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty %t.obj --debug-file %t.dwo --raw-map --domain=vm | %FileCheck %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -86,12 +89,8 @@
         - AbbrCode:        0x0
 ...
 
-$ bloaty 1 --debug-file=2 -d compileunits --raw-map --domain=vm
-Maps for 1:
-
-VM MAP:
-0000-1000	       4096		[-- Nothing mapped --]
-1000-1042	         66		[section .text]
-1042-1047	          5		test.c
-1047-1151	        266		[section .text]
-
+# CHECK: VM MAP:
+# CHECK: 0000-1000	       4096		[-- Nothing mapped --]
+# CHECK: 1000-1042	         66		[section .text]
+# CHECK: 1042-1047	          5		test.c
+# CHECK: 1047-1151	        266		[section .text]
diff --git a/tests/elf/sections/empty-bin-64.test b/tests/elf/sections/empty-bin-64.test
index 9df7eb3..5cb78fb 100644
--- a/tests/elf/sections/empty-bin-64.test
+++ b/tests/elf/sections/empty-bin-64.test
@@ -1,3 +1,6 @@
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty --raw-map %t.obj | %FileCheck -check-prefix %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -47,24 +50,20 @@
     Section:         .comment
 ...
 
-$ bloaty --raw-map 1
-Maps for 1:
+# CHECK: FILE MAP:
+# CHECK: 000-040	         64		[ELF Headers]
+# CHECK: 040-070	         48		.comment
+# CHECK: 070-118	        168		.symtab
+# CHECK: 118-148	         48		.strtab
+# CHECK: 148-190	         72		.shstrtab
+# CHECK: 190-1d0	         64		[ELF Headers]
+# CHECK: 1d0-210	         64		.text
+# CHECK: 210-250	         64		.data
+# CHECK: 250-290	         64		.bss
+# CHECK: 290-2d0	         64		.comment
+# CHECK: 2d0-310	         64		.note.GNU-stack
+# CHECK: 310-350	         64		.symtab
+# CHECK: 350-390	         64		.strtab
+# CHECK: 390-3d0	         64		.shstrtab
 
-FILE MAP:
-000-040	         64		[ELF Headers]
-040-070	         48		.comment
-070-118	        168		.symtab
-118-148	         48		.strtab
-148-190	         72		.shstrtab
-190-1d0	         64		[ELF Headers]
-1d0-210	         64		.text
-210-250	         64		.data
-250-290	         64		.bss
-290-2d0	         64		.comment
-2d0-310	         64		.note.GNU-stack
-310-350	         64		.symtab
-350-390	         64		.strtab
-390-3d0	         64		.shstrtab
-
-VM MAP:
-
+# CHECK: VM MAP:
diff --git a/tests/elf/sections/empty-obj-64.test b/tests/elf/sections/empty-obj-64.test
index fa94d1e..1645417 100644
--- a/tests/elf/sections/empty-obj-64.test
+++ b/tests/elf/sections/empty-obj-64.test
@@ -1,3 +1,6 @@
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty --raw-map %t.obj | %FileCheck %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -47,24 +50,20 @@
     Section:         .comment
 ...
 
-$ bloaty --raw-map 1
-Maps for 1:
+# CHECK: FILE MAP:
+# CHECK: 000-040	         64		[ELF Headers]
+# CHECK: 040-070	         48		.comment
+# CHECK: 070-118	        168		.symtab
+# CHECK: 118-148	         48		.strtab
+# CHECK: 148-190	         72		.shstrtab
+# CHECK: 190-1d0	         64		[ELF Headers]
+# CHECK: 1d0-210	         64		.text
+# CHECK: 210-250	         64		.data
+# CHECK: 250-290	         64		.bss
+# CHECK: 290-2d0	         64		.comment
+# CHECK: 2d0-310	         64		.note.GNU-stack
+# CHECK: 310-350	         64		.symtab
+# CHECK: 350-390	         64		.strtab
+# CHECK: 390-3d0	         64		.shstrtab
 
-FILE MAP:
-000-040	         64		[ELF Headers]
-040-070	         48		.comment
-070-118	        168		.symtab
-118-148	         48		.strtab
-148-190	         72		.shstrtab
-190-1d0	         64		[ELF Headers]
-1d0-210	         64		.text
-210-250	         64		.data
-250-290	         64		.bss
-290-2d0	         64		.comment
-2d0-310	         64		.note.GNU-stack
-310-350	         64		.symtab
-350-390	         64		.strtab
-390-3d0	         64		.shstrtab
-
-VM MAP:
-
+# CHECK: VM MAP:
diff --git a/tests/elf/sections/musl-static-bin.test b/tests/elf/sections/musl-static-bin.test
index 06c46ce..829ff65 100644
--- a/tests/elf/sections/musl-static-bin.test
+++ b/tests/elf/sections/musl-static-bin.test
@@ -18,6 +18,9 @@
 # This binary does not successfully run due to bugs in obj2yaml
 # (or possibly yaml2obj). The binary did not fully round-trip successfully.
 
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty --raw-map %t.obj | %FileCheck %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -32,20 +35,20 @@
     Align:           0x0000000000001000
   - Type:            PT_LOAD
     Flags:           [ PF_X, PF_R ]
-    FirstSec:        .init
-    LastSec:         .fini
+#    FirstSec:        .init
+#    LastSec:         .fini
     VAddr:           0x0000000000401000
     Align:           0x0000000000001000
   - Type:            PT_LOAD
     Flags:           [ PF_R ]
-    FirstSec:        .rodata
-    LastSec:         .eh_frame
+#    FirstSec:        .rodata
+#    LastSec:         .eh_frame
     VAddr:           0x0000000000402000
     Align:           0x0000000000001000
   - Type:            PT_LOAD
     Flags:           [ PF_W, PF_R ]
-    FirstSec:        .init_array
-    LastSec:         .bss
+#    FirstSec:        .init_array
+#    LastSec:         .bss
     VAddr:           0x0000000000403FE8
     FileSize:        0x228
     MemSize:         0x510
@@ -55,8 +58,8 @@
     Align:           0x0000000000000010
   - Type:            PT_GNU_RELRO
     Flags:           [ PF_R ]
-    FirstSec:        .init_array
-    LastSec:         .got
+#    FirstSec:        .init_array
+#    LastSec:         .got
     VAddr:           0x0000000000403FE8
 Sections:
   - Name:            .init
@@ -530,62 +533,58 @@
     Size:            0x0000000000000008
 ...
 
-$ bloaty --raw-map 1
-Maps for 1:
+# CHECK: FILE MAP:
+# CHECK: 0000-0040	         64		[ELF Headers]
+# CHECK: 0040-0078	         56		[LOAD #0 [R]]
+# CHECK: 0078-00b0	         56		[LOAD #1 [RX]]
+# CHECK: 00b0-00e8	         56		[LOAD #2 [R]]
+# CHECK: 00e8-0120	         56		[LOAD #3 [RW]]
+# CHECK: 0120-0158	         56		[LOAD #4 [RW]]
+# CHECK: 0158-0190	         56		[LOAD #5 [R]]
+# CHECK: 0190-01a0	         16		.init
+# CHECK: 01a0-09f9	       2137		.text
+# CHECK: 09f9-0a00	          7		.fini
+# CHECK: 0a00-0d20	        800		.rodata
+# CHECK: 0d20-0d50	         48		.eh_frame
+# CHECK: 0d50-0d58	          8		.init_array
+# CHECK: 0d58-0d60	          8		.fini_array
+# CHECK: 0d60-0d68	          8		.got
+# CHECK: 0d68-0d80	         24		.got.plt
+# CHECK: 0d80-0f78	        504		.data
+# CHECK: 0f78-0f80	          8		.data
+# CHECK: 0f80-0fd8	         88		.comment
+# CHECK: 0fd8-1710	       1848		.symtab
+# CHECK: 1710-1a43	        819		.strtab
+# CHECK: 1a43-1ac0	        125		.shstrtab
+# CHECK: 1ac0-1b00	         64		[ELF Headers]
+# CHECK: 1b00-1b40	         64		.init
+# CHECK: 1b40-1b80	         64		.text
+# CHECK: 1b80-1bc0	         64		.fini
+# CHECK: 1bc0-1c00	         64		.rodata
+# CHECK: 1c00-1c40	         64		.eh_frame
+# CHECK: 1c40-1c80	         64		.init_array
+# CHECK: 1c80-1cc0	         64		.fini_array
+# CHECK: 1cc0-1d00	         64		.got
+# CHECK: 1d00-1d40	         64		.got.plt
+# CHECK: 1d40-1d80	         64		.data
+# CHECK: 1d80-1dc0	         64		.bss
+# CHECK: 1dc0-1e00	         64		.comment
+# CHECK: 1e00-1e40	         64		.symtab
+# CHECK: 1e40-1e80	         64		.strtab
+# CHECK: 1e80-1ec0	         64		.shstrtab
 
-FILE MAP:
-0000-0040	         64		[ELF Headers]
-0040-0078	         56		[LOAD #0 [R]]
-0078-00b0	         56		[LOAD #1 [RX]]
-00b0-00e8	         56		[LOAD #2 [R]]
-00e8-0120	         56		[LOAD #3 [RW]]
-0120-0158	         56		[LOAD #4 [RW]]
-0158-0190	         56		[LOAD #5 [R]]
-0190-01a0	         16		.init
-01a0-09f9	       2137		.text
-09f9-0a00	          7		.fini
-0a00-0d20	        800		.rodata
-0d20-0d50	         48		.eh_frame
-0d50-0d58	          8		.init_array
-0d58-0d60	          8		.fini_array
-0d60-0d68	          8		.got
-0d68-0d80	         24		.got.plt
-0d80-0f78	        504		.data
-0f78-0f80	          8		.data
-0f80-0fd8	         88		.comment
-0fd8-1710	       1848		.symtab
-1710-1a43	        819		.strtab
-1a43-1ac0	        125		.shstrtab
-1ac0-1b00	         64		[ELF Headers]
-1b00-1b40	         64		.init
-1b40-1b80	         64		.text
-1b80-1bc0	         64		.fini
-1bc0-1c00	         64		.rodata
-1c00-1c40	         64		.eh_frame
-1c40-1c80	         64		.init_array
-1c80-1cc0	         64		.fini_array
-1cc0-1d00	         64		.got
-1d00-1d40	         64		.got.plt
-1d40-1d80	         64		.data
-1d80-1dc0	         64		.bss
-1dc0-1e00	         64		.comment
-1e00-1e40	         64		.symtab
-1e40-1e80	         64		.strtab
-1e80-1ec0	         64		.shstrtab
-
-VM MAP:
-000000-401000	    4198400		[-- Nothing mapped --]
-401000-401010	         16		.init
-401010-401869	       2137		.text
-401869-40186c	          3		.fini
-40186c-402000	       1940		[-- Nothing mapped --]
-402000-402320	        800		.rodata
-402320-402350	         48		.eh_frame
-402350-403fe8	       7320		[-- Nothing mapped --]
-403fe8-403ff0	          8		.init_array
-403ff0-403ff8	          8		.fini_array
-403ff8-404000	          8		.got
-404000-404020	         32		.got.plt
-404020-404220	        512		.data
-404220-4044f8	        728		.bss
-
+# CHECK: VM MAP:
+# CHECK: 000000-401000	    4198400		[-- Nothing mapped --]
+# CHECK: 401000-401010	         16		.init
+# CHECK: 401010-401869	       2137		.text
+# CHECK: 401869-40186c	          3		.fini
+# CHECK: 40186c-402000	       1940		[-- Nothing mapped --]
+# CHECK: 402000-402320	        800		.rodata
+# CHECK: 402320-402350	         48		.eh_frame
+# CHECK: 402350-403fe8	       7320		[-- Nothing mapped --]
+# CHECK: 403fe8-403ff0	          8		.init_array
+# CHECK: 403ff0-403ff8	          8		.fini_array
+# CHECK: 403ff8-404000	          8		.got
+# CHECK: 404000-404020	         32		.got.plt
+# CHECK: 404020-404220	        512		.data
+# CHECK: 404220-4044f8	        728		.bss
diff --git a/tests/elf/sections/normal-obj.test b/tests/elf/sections/normal-obj.test
index 1473507..f481b1a 100644
--- a/tests/elf/sections/normal-obj.test
+++ b/tests/elf/sections/normal-obj.test
@@ -1,3 +1,6 @@
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty --raw-map %t.obj | %FileCheck %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -83,43 +86,39 @@
     Size:            0x0000000000000315
 ...
 
-$ bloaty --raw-map 1
-Maps for 1:
+# CHECK: FILE MAP:
+# CHECK: 000-040	         64		[ELF Headers]
+# CHECK: 040-050	         16		.text
+# CHECK: 050-220	        464		.data
+# CHECK: 220-535	        789		.rodata
+# CHECK: 535-558	         35		.comment
+# CHECK: 558-590	         56		.eh_frame
+# CHECK: 590-5a8	         24		.rela.eh_frame
+# CHECK: 5a8-650	        168		.symtab
+# CHECK: 650-66b	         27		.strtab
+# CHECK: 66b-6d8	        109		.shstrtab
+# CHECK: 6d8-718	         64		[ELF Headers]
+# CHECK: 718-758	         64		.text
+# CHECK: 758-798	         64		.bss
+# CHECK: 798-7d8	         64		.data
+# CHECK: 7d8-818	         64		.rodata
+# CHECK: 818-858	         64		.comment
+# CHECK: 858-898	         64		.note.GNU-stack
+# CHECK: 898-8d8	         64		.eh_frame
+# CHECK: 8d8-918	         64		.rela.eh_frame
+# CHECK: 918-958	         64		.llvm_addrsig
+# CHECK: 958-998	         64		.symtab
+# CHECK: 998-9d8	         64		.strtab
+# CHECK: 9d8-a18	         64		.shstrtab
 
-FILE MAP:
-000-040	         64		[ELF Headers]
-040-050	         16		.text
-050-220	        464		.data
-220-535	        789		.rodata
-535-558	         35		.comment
-558-590	         56		.eh_frame
-590-5a8	         24		.rela.eh_frame
-5a8-650	        168		.symtab
-650-66b	         27		.strtab
-66b-6d8	        109		.shstrtab
-6d8-718	         64		[ELF Headers]
-718-758	         64		.text
-758-798	         64		.bss
-798-7d8	         64		.data
-7d8-818	         64		.rodata
-818-858	         64		.comment
-858-898	         64		.note.GNU-stack
-898-8d8	         64		.eh_frame
-8d8-918	         64		.rela.eh_frame
-918-958	         64		.llvm_addrsig
-958-998	         64		.symtab
-998-9d8	         64		.strtab
-9d8-a18	         64		.shstrtab
-
-VM MAP:
-00000000000-10000000000	 1099511627776		[-- Nothing mapped --]
-10000000000-1000000000b	         11		.text
-1000000000b-20000000000	 1099511627765		[-- Nothing mapped --]
-20000000000-2000000007b	        123		.bss
-2000000007b-30000000000	 1099511627653		[-- Nothing mapped --]
-30000000000-300000001c8	        456		.data
-300000001c8-40000000000	 1099511627320		[-- Nothing mapped --]
-40000000000-40000000315	        789		.rodata
-40000000315-70000000000	 3298534882539		[-- Nothing mapped --]
-70000000000-70000000038	         56		.eh_frame
-
+# CHECK: VM MAP:
+# CHECK: 00000000000-10000000000	 1099511627776		[-- Nothing mapped --]
+# CHECK: 10000000000-1000000000b	         11		.text
+# CHECK: 1000000000b-20000000000	 1099511627765		[-- Nothing mapped --]
+# CHECK: 20000000000-2000000007b	        123		.bss
+# CHECK: 2000000007b-30000000000	 1099511627653		[-- Nothing mapped --]
+# CHECK: 30000000000-300000001c8	        456		.data
+# CHECK: 300000001c8-40000000000	 1099511627320		[-- Nothing mapped --]
+# CHECK: 40000000000-40000000315	        789		.rodata
+# CHECK: 40000000315-70000000000	 3298534882539		[-- Nothing mapped --]
+# CHECK: 70000000000-70000000038	         56		.eh_frame
diff --git a/tests/elf/sections/shn-xindex.test b/tests/elf/sections/shn-xindex.test
index ed068f3..396f33d 100644
--- a/tests/elf/sections/shn-xindex.test
+++ b/tests/elf/sections/shn-xindex.test
@@ -7,6 +7,9 @@
 # These special cases are documented here:
 #  https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-94076/index.html
 
+# RUN: %yaml2obj %s -o %t.obj
+# RUN: %bloaty --raw-map %t.obj | %FileCheck %s
+
 --- !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -21,16 +24,12 @@
     Size: 0x3
 ...
 
-$ bloaty --raw-map 1
-Maps for 1:
+# CHECK: FILE MAP:
+# CHECK: 000-040	         64		[ELF Headers]
+# CHECK: 040-041	          1		.strtab
+# CHECK: 041-058	         23		.shstrtab
+# CHECK: 058-098	         64		[ELF Headers]
+# CHECK: 098-0d8	         64		.strtab
+# CHECK: 0d8-118	         64		.shstrtab
 
-FILE MAP:
-000-040	         64		[ELF Headers]
-040-041	          1		.strtab
-041-058	         23		.shstrtab
-058-098	         64		[ELF Headers]
-098-0d8	         64		.strtab
-0d8-118	         64		.shstrtab
-
-VM MAP:
-
+# CHECK: VM MAP:
diff --git a/tests/lit.cfg b/tests/lit.cfg
new file mode 100644
index 0000000..7d0e68e
--- /dev/null
+++ b/tests/lit.cfg
@@ -0,0 +1,46 @@
+# -*- Python -*-
+
+import os
+import platform
+import subprocess
+
+import lit
+import lit.formats
+import lit.util
+
+### Helper Functions
+
+def make_path(*args):
+  return os.path.normpath(os.path.join(*args))
+
+kIsWindows = platform.system() == 'Windows'
+
+###
+
+config.name = 'bloaty'
+
+bloaty_src_root = getattr(config, 'bloaty_src_root', None)
+if not bloaty_src_root:
+  lit_config.fatal("missing 'bloaty_src_root' key in the site specific config")
+bloaty_src_root = os.path.normpath(bloaty_src_root)
+
+bloaty_obj_root = getattr(config, 'bloaty_obj_root', None)
+if not bloaty_obj_root:
+  lit_config.fatal("missing 'bloaty_obj_root' key in the site specific config")
+bloaty_obj_root = os.path.normpath(bloaty_obj_root)
+
+use_lit_shell = os.environ.get('LIT_USE_INTERNAL_SHELL', kIsWindows)
+if not use_lit_shell:
+  config.available_features.add('shell')
+
+config.test_format = lit.formats.ShTest(execute_external = False)
+
+config.suffixes = ['.test']
+config.excludes = ['testdata']
+
+config.test_source_root = os.path.join(bloaty_src_root, 'tests')
+config.test_exec_root = os.path.join(bloaty_obj_root, 'tests')
+
+config.substitutions.append(('%FileCheck', config.filecheck_path))
+config.substitutions.append(('%yaml2obj', config.yaml2obj_path))
+config.substitutions.append(('%bloaty', make_path(config.bloaty_obj_root, 'bloaty')))
diff --git a/tests/lit.site.cfg.in b/tests/lit.site.cfg.in
new file mode 100644
index 0000000..6459ad1
--- /dev/null
+++ b/tests/lit.site.cfg.in
@@ -0,0 +1,13 @@
+# -*- Python -*-
+
+import os
+
+config.bloaty_src_root = "@BLOATY_SRC_DIR@"
+config.bloaty_obj_root = "@BLOATY_OBJ_DIR@"
+
+config.filecheck_path = "@FILECHECK_EXECUTABLE@"
+config.yaml2obj_path = "@YAML2OBJ_EXECUTABLE@"
+
+if not config.test_exec_root:
+  config.test_exec_root = os.path.dirname(os.path.realpath(__file__))
+lit_config.load_config(config, "@BLOATY_SRC_DIR@/tests/lit.cfg")
diff --git a/tests/tester.py b/tests/tester.py
deleted file mode 100755
index 556d579..0000000
--- a/tests/tester.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/python3
-
-import os
-import glob
-import re
-import sys
-import subprocess
-import shutil
-import tempfile
-
-successes = 0
-failures = []
-
-def TestFile(filename):
-  cwd = os.getcwd()
-  abspath = os.path.abspath(filename)
-  global successes
-  global failures
-  with open(abspath) as f:
-    print(filename)
-    tmpdir = tempfile.mkdtemp(prefix="/tmp/bloaty-")
-    contents = f.read()
-    file_count = len(re.findall(r'^---', contents, flags=re.MULTILINE))
-    for i in range(1, file_count + 1):
-      subprocess.check_call('yaml2obj {0} --docnum={1} > {1}'.format(abspath, str(i)), shell=True, cwd=tmpdir)
-    lines = contents.splitlines()
-    while len(lines[0]) == 0 or lines[0][0] != '$':
-      lines.pop(0)
-    bloaty_invocation = os.path.join(cwd, lines[0][2:]) + ' > actual'
-    lines.pop(0)
-    expected_output = "\n".join(lines) + "\n"
-    failure = None
-    if subprocess.call(bloaty_invocation, shell=True, cwd=tmpdir) != 0:
-      failure = "CRASHED"
-    else:
-      with open(os.path.join(tmpdir, 'expected'), 'w') as expected:
-        expected.write(expected_output)
-      if subprocess.call('diff -u expected actual', shell=True, cwd=tmpdir) != 0:
-        failure = "FAILED"
-
-    if failure:
-      print("{}: {}".format(failure, filename))
-      print("{}: output in {}".format(failure, tmpdir))
-      failures.append((filename, tmpdir))
-    else:
-      successes += 1
-      shutil.rmtree(tmpdir)
-
-def TestArg(arg):
-  if os.path.isdir(arg):
-    files = sorted(glob.glob(os.path.join(arg, "**/*.test"), recursive=True))
-    for file in files:
-      TestFile(file)
-  else:
-    TestFile(arg)
-
-args = sys.argv[1:]
-
-if not args:
-  print("Usage: tester.py <FILE-OR-DIR> ...")
-  sys.exit(1)
-
-for arg in sys.argv[1:]:
-  TestArg(arg)
-
-if not failures:
-  print("SUCCESS: {} test(s) passed".format(successes))
-else:
-  print("\nFAILURE: {} tests passed, {} tests failed:".format(successes, len(failures)))
-  for failure in failures:
-    print("  - {} (output in {})".format(*failure))
-  sys.exit(1)