summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt88
-rw-r--r--test/Makefile.am513
-rw-r--r--test/UTF-8-test.txtbin0 -> 22781 bytes
-rw-r--r--test/aftest.cc63
-rw-r--r--test/ansi-colors.0.in22
-rw-r--r--test/bad-config-json/formats/invalid-json/format.json5
-rw-r--r--test/bad-config-json/formats/invalid-key/format.json27
-rw-r--r--test/bad-config/formats/invalid-json-format/format.json17
-rw-r--r--test/bad-config/formats/invalid-properties/format.json45
-rw-r--r--test/bad-config/formats/invalid-regex/format.json29
-rw-r--r--test/bad-config/formats/invalid-sample/format.json45
-rw-r--r--test/bad-config/formats/invalid-schema/format.json3
-rw-r--r--test/bad-config/formats/invalid-sql/init.sql5
-rw-r--r--test/bad-config/formats/invalid-sql/init2.sql2
-rw-r--r--test/bad-config/formats/no-regexes/format.json7
-rw-r--r--test/bad-config/formats/no-samples/format.json17
-rw-r--r--test/bad-config2/formats/invalid-config/config.bad-schema.json3
-rw-r--r--test/bad-config2/formats/invalid-config/config.json5
-rw-r--r--test/bad-config2/formats/invalid-config/config.malformed.json5
-rw-r--r--test/bad-config2/formats/invalid-config/config.truncated.json2
-rw-r--r--test/books.xml120
-rw-r--r--test/datafile_ipaddr.013
-rw-r--r--test/datafile_simple.025
-rw-r--r--test/datafile_simple.113
-rw-r--r--test/datafile_simple.109
-rw-r--r--test/datafile_simple.1113
-rw-r--r--test/datafile_simple.1210
-rw-r--r--test/datafile_simple.1310
-rw-r--r--test/datafile_simple.1457
-rw-r--r--test/datafile_simple.1575
-rw-r--r--test/datafile_simple.169
-rw-r--r--test/datafile_simple.1722
-rw-r--r--test/datafile_simple.1823
-rw-r--r--test/datafile_simple.1953
-rw-r--r--test/datafile_simple.240
-rw-r--r--test/datafile_simple.2017
-rw-r--r--test/datafile_simple.2126
-rw-r--r--test/datafile_simple.229
-rw-r--r--test/datafile_simple.2388
-rw-r--r--test/datafile_simple.325
-rw-r--r--test/datafile_simple.410
-rw-r--r--test/datafile_simple.510
-rw-r--r--test/datafile_simple.625
-rw-r--r--test/datafile_simple.718
-rw-r--r--test/datafile_simple.844
-rw-r--r--test/datafile_simple.917
-rw-r--r--test/datafile_syslog.023
-rw-r--r--test/datafile_syslog.121
-rw-r--r--test/datafile_xml.026
-rw-r--r--test/dhcp-trunc.pcapngbin0 -> 253 bytes
-rw-r--r--test/dhcp.pcapngbin0 -> 1508 bytes
-rw-r--r--test/document.sections.tests.cc170
-rw-r--r--test/drive_data_scanner.cc310
-rw-r--r--test/drive_grep_proc.cc156
-rw-r--r--test/drive_line_buffer.cc245
-rw-r--r--test/drive_listview.cc139
-rw-r--r--test/drive_logfile.cc194
-rw-r--r--test/drive_mvwattrline.cc119
-rw-r--r--test/drive_readline_curses.cc153
-rw-r--r--test/drive_sequencer.cc150
-rw-r--r--test/drive_shlexer.cc96
-rw-r--r--test/drive_sql.cc78
-rw-r--r--test/drive_sql_anno.cc89
-rw-r--r--test/drive_view_colors.cc106
-rw-r--r--test/drive_vt52_curses.cc129
-rw-r--r--test/expected/expected.am1005
-rw-r--r--test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.err0
-rw-r--r--test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.out1
-rw-r--r--test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.err0
-rw-r--r--test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.out1
-rw-r--r--test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.err8
-rw-r--r--test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.out0
-rw-r--r--test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.err0
-rw-r--r--test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.out3
-rw-r--r--test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.err0
-rw-r--r--test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.out2
-rw-r--r--test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err6
-rw-r--r--test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.out0
-rw-r--r--test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.err0
-rw-r--r--test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.out3
-rw-r--r--test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.err0
-rw-r--r--test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.out3
-rw-r--r--test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.err0
-rw-r--r--test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.out3
-rw-r--r--test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.err0
-rw-r--r--test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.out2
-rw-r--r--test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.err0
-rw-r--r--test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.out1
-rw-r--r--test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.err7
-rw-r--r--test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.out0
-rw-r--r--test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.err0
-rw-r--r--test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.out2
-rw-r--r--test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.err0
-rw-r--r--test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.out2
-rw-r--r--test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.err0
-rw-r--r--test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.out3
-rw-r--r--test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.err0
-rw-r--r--test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.out68
-rw-r--r--test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.err6
-rw-r--r--test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.out0
-rw-r--r--test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.err0
-rw-r--r--test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.out3
-rw-r--r--test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.err0
-rw-r--r--test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.out2
-rw-r--r--test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.err0
-rw-r--r--test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.out12
-rw-r--r--test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.err0
-rw-r--r--test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.out0
-rw-r--r--test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.err0
-rw-r--r--test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.out1
-rw-r--r--test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.err0
-rw-r--r--test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.out1
-rw-r--r--test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.err0
-rw-r--r--test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.out2
-rw-r--r--test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.err6
-rw-r--r--test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.out0
-rw-r--r--test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.err0
-rw-r--r--test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out2
-rw-r--r--test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err0
-rw-r--r--test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out1
-rw-r--r--test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err0
-rw-r--r--test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out23
-rw-r--r--test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err0
-rw-r--r--test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out1
-rw-r--r--test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err0
-rw-r--r--test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.out1
-rw-r--r--test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.err0
-rw-r--r--test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.out2
-rw-r--r--test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.err0
-rw-r--r--test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.out1
-rw-r--r--test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.err0
-rw-r--r--test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.out3
-rw-r--r--test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.err7
-rw-r--r--test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.out0
-rw-r--r--test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.err0
-rw-r--r--test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out3
-rw-r--r--test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err0
-rw-r--r--test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out2
-rw-r--r--test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err0
-rw-r--r--test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out2
-rw-r--r--test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err0
-rw-r--r--test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.out2
-rw-r--r--test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.err0
-rw-r--r--test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.out3
-rw-r--r--test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.err0
-rw-r--r--test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.out3
-rw-r--r--test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.err5
-rw-r--r--test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.out0
-rw-r--r--test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.err0
-rw-r--r--test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.out2
-rw-r--r--test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.err4
-rw-r--r--test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.out0
-rw-r--r--test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.err0
-rw-r--r--test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.out2
-rw-r--r--test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.err0
-rw-r--r--test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.out2
-rw-r--r--test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.err0
-rw-r--r--test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.out1
-rw-r--r--test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.err0
-rw-r--r--test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.out14
-rw-r--r--test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.err8
-rw-r--r--test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.out0
-rw-r--r--test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.err4
-rw-r--r--test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.out0
-rw-r--r--test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.err0
-rw-r--r--test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.out1
-rw-r--r--test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.err0
-rw-r--r--test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.out3
-rw-r--r--test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.err0
-rw-r--r--test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.out5
-rw-r--r--test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.err6
-rw-r--r--test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.out0
-rw-r--r--test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.err0
-rw-r--r--test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.out1
-rw-r--r--test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.err0
-rw-r--r--test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.out3
-rw-r--r--test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.err0
-rw-r--r--test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.out3
-rw-r--r--test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.err0
-rw-r--r--test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.out1
-rw-r--r--test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.err0
-rw-r--r--test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.out1
-rw-r--r--test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.err0
-rw-r--r--test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.out1
-rw-r--r--test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.err6
-rw-r--r--test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.out0
-rw-r--r--test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.err0
-rw-r--r--test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.out37
-rw-r--r--test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.err6
-rw-r--r--test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.out0
-rw-r--r--test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.err0
-rw-r--r--test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.out2
-rw-r--r--test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.err0
-rw-r--r--test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.out3
-rw-r--r--test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.err0
-rw-r--r--test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.out2
-rw-r--r--test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.err0
-rw-r--r--test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.out1
-rw-r--r--test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.err0
-rw-r--r--test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out4
-rw-r--r--test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.err0
-rw-r--r--test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.out2
-rw-r--r--test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.err0
-rw-r--r--test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.out2
-rw-r--r--test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.err3
-rw-r--r--test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.out0
-rw-r--r--test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.err6
-rw-r--r--test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.out0
-rw-r--r--test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.err0
-rw-r--r--test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.out10
-rw-r--r--test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.err7
-rw-r--r--test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.out0
-rw-r--r--test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.err0
-rw-r--r--test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.out12
-rw-r--r--test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.err0
-rw-r--r--test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.out1
-rw-r--r--test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.err0
-rw-r--r--test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.out1
-rw-r--r--test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.err0
-rw-r--r--test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out4417
-rw-r--r--test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.err0
-rw-r--r--test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.out37
-rw-r--r--test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.err0
-rw-r--r--test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.out1
-rw-r--r--test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.err0
-rw-r--r--test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.out2
-rw-r--r--test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.err0
-rw-r--r--test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.out1
-rw-r--r--test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.err0
-rw-r--r--test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.out1
-rw-r--r--test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.err0
-rw-r--r--test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.out1
-rw-r--r--test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.err7
-rw-r--r--test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.out0
-rw-r--r--test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.err0
-rw-r--r--test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.out5
-rw-r--r--test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.err7
-rw-r--r--test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.out0
-rw-r--r--test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.err0
-rw-r--r--test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.out3
-rw-r--r--test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.err0
-rw-r--r--test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.out1
-rw-r--r--test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.err6
-rw-r--r--test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.out0
-rw-r--r--test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.err0
-rw-r--r--test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.out2
-rw-r--r--test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.err0
-rw-r--r--test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.out2
-rw-r--r--test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.err0
-rw-r--r--test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.out1
-rw-r--r--test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.err0
-rw-r--r--test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.out3
-rw-r--r--test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.err0
-rw-r--r--test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.out3
-rw-r--r--test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.err7
-rw-r--r--test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.out0
-rw-r--r--test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.err0
-rw-r--r--test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.out2
-rw-r--r--test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.err0
-rw-r--r--test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.out1
-rw-r--r--test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.err0
-rw-r--r--test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out1
-rw-r--r--test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err0
-rw-r--r--test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out3
-rw-r--r--test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err0
-rw-r--r--test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out3
-rw-r--r--test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err0
-rw-r--r--test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out2
-rw-r--r--test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err0
-rw-r--r--test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.out12
-rw-r--r--test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.err0
-rw-r--r--test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.out2
-rw-r--r--test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.err0
-rw-r--r--test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.out3
-rw-r--r--test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.err6
-rw-r--r--test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.out0
-rw-r--r--test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.err7
-rw-r--r--test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.out0
-rw-r--r--test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.err0
-rw-r--r--test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.out3
-rw-r--r--test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.err0
-rw-r--r--test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out2
-rw-r--r--test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err6
-rw-r--r--test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out0
-rw-r--r--test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.err20
-rw-r--r--test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.out0
-rw-r--r--test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err6
-rw-r--r--test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out0
-rw-r--r--test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err38
-rw-r--r--test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.out0
-rw-r--r--test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.err0
-rw-r--r--test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.out0
-rw-r--r--test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.err12
-rw-r--r--test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.out0
-rw-r--r--test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.err8
-rw-r--r--test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.out0
-rw-r--r--test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.err0
-rw-r--r--test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.out1
-rw-r--r--test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.err0
-rw-r--r--test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.out0
-rw-r--r--test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.err0
-rw-r--r--test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.out6
-rw-r--r--test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.err0
-rw-r--r--test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.out2
-rw-r--r--test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.err0
-rw-r--r--test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.out0
-rw-r--r--test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.err0
-rw-r--r--test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.out3
-rw-r--r--test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.err10
-rw-r--r--test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out0
-rw-r--r--test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err0
-rw-r--r--test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out3
-rw-r--r--test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err0
-rw-r--r--test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out9
-rw-r--r--test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err171
-rw-r--r--test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out0
-rw-r--r--test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err190
-rw-r--r--test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out0
-rw-r--r--test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err61
-rw-r--r--test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out0
-rw-r--r--test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err66
-rw-r--r--test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out0
-rw-r--r--test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err0
-rw-r--r--test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out13
-rw-r--r--test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err0
-rw-r--r--test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.out14
-rw-r--r--test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.err0
-rw-r--r--test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.out192
-rw-r--r--test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.err0
-rw-r--r--test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.out3
-rw-r--r--test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.err0
-rw-r--r--test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.out29
-rw-r--r--test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.err0
-rw-r--r--test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.out4
-rw-r--r--test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.err0
-rw-r--r--test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.out29
-rw-r--r--test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.err0
-rw-r--r--test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.out1
-rw-r--r--test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.err0
-rw-r--r--test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.out12
-rw-r--r--test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.err0
-rw-r--r--test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.out8
-rw-r--r--test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.err0
-rw-r--r--test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.out2
-rw-r--r--test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.err0
-rw-r--r--test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.out14
-rw-r--r--test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.err0
-rw-r--r--test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.out21
-rw-r--r--test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.err0
-rw-r--r--test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.out3
-rw-r--r--test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.err0
-rw-r--r--test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.out4
-rw-r--r--test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.err0
-rw-r--r--test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.out4
-rw-r--r--test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.err0
-rw-r--r--test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.out25
-rw-r--r--test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.err0
-rw-r--r--test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.out4
-rw-r--r--test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.err0
-rw-r--r--test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.out2
-rw-r--r--test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.err0
-rw-r--r--test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.out50
-rw-r--r--test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.err0
-rw-r--r--test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.out4
-rw-r--r--test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.err0
-rw-r--r--test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.out3
-rw-r--r--test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.err0
-rw-r--r--test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.out4
-rw-r--r--test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.err0
-rw-r--r--test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.out4
-rw-r--r--test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.err0
-rw-r--r--test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out3
-rw-r--r--test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.err0
-rw-r--r--test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.out1
-rw-r--r--test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.err0
-rw-r--r--test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.out2
-rw-r--r--test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.err0
-rw-r--r--test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.out2
-rw-r--r--test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.err0
-rw-r--r--test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.out2
-rw-r--r--test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.err0
-rw-r--r--test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.out2
-rw-r--r--test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.err0
-rw-r--r--test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.out4
-rw-r--r--test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.err0
-rw-r--r--test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out10
-rw-r--r--test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err0
-rw-r--r--test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out6
-rw-r--r--test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.err0
-rw-r--r--test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out1
-rw-r--r--test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err0
-rw-r--r--test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out3
-rw-r--r--test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err0
-rw-r--r--test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out11
-rw-r--r--test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err7
-rw-r--r--test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.out0
-rw-r--r--test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.err11
-rw-r--r--test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.out0
-rw-r--r--test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.err0
-rw-r--r--test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.out2
-rw-r--r--test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.err0
-rw-r--r--test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.out5
-rw-r--r--test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.err0
-rw-r--r--test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.out6
-rw-r--r--test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.err0
-rw-r--r--test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.out3
-rw-r--r--test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.err0
-rw-r--r--test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.out2
-rw-r--r--test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.err0
-rw-r--r--test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.out3
-rw-r--r--test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.err0
-rw-r--r--test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.out37
-rw-r--r--test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.err0
-rw-r--r--test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.out4
-rw-r--r--test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.err0
-rw-r--r--test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.out3
-rw-r--r--test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.err0
-rw-r--r--test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.out4
-rw-r--r--test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.err0
-rw-r--r--test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.out4
-rw-r--r--test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.err0
-rw-r--r--test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.out5
-rw-r--r--test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.err0
-rw-r--r--test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.out4
-rw-r--r--test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.err0
-rw-r--r--test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.out4
-rw-r--r--test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err0
-rw-r--r--test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.out8
-rw-r--r--test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.err0
-rw-r--r--test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.out4
-rw-r--r--test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.err0
-rw-r--r--test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.out5
-rw-r--r--test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.err0
-rw-r--r--test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.out5
-rw-r--r--test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.err0
-rw-r--r--test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.out3
-rw-r--r--test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.err0
-rw-r--r--test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out19
-rw-r--r--test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err0
-rw-r--r--test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out3
-rw-r--r--test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.err0
-rw-r--r--test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.out1
-rw-r--r--test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.err2
-rw-r--r--test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.out0
-rw-r--r--test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.err3
-rw-r--r--test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.out0
-rw-r--r--test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.err3
-rw-r--r--test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.out1
-rw-r--r--test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.err1
-rw-r--r--test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.out0
-rw-r--r--test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.err0
-rw-r--r--test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.out4
-rw-r--r--test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.err0
-rw-r--r--test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.out10
-rw-r--r--test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.err34
-rw-r--r--test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.out3
-rw-r--r--test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.err0
-rw-r--r--test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.out2
-rw-r--r--test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.err0
-rw-r--r--test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.out1
-rw-r--r--test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.err3
-rw-r--r--test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.out0
-rw-r--r--test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.err3
-rw-r--r--test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.out0
-rw-r--r--test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.err0
-rw-r--r--test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.out4
-rw-r--r--test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.err1
-rw-r--r--test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.out0
-rw-r--r--test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.err5
-rw-r--r--test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.out0
-rw-r--r--test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.err0
-rw-r--r--test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.out2
-rw-r--r--test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.err3
-rw-r--r--test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.out0
-rw-r--r--test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.err0
-rw-r--r--test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.out3
-rw-r--r--test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.err3
-rw-r--r--test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.out0
-rw-r--r--test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.err4
-rw-r--r--test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.out0
-rw-r--r--test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.err1
-rw-r--r--test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.out0
-rw-r--r--test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.err2
-rw-r--r--test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.out0
-rw-r--r--test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.err0
-rw-r--r--test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.out34
-rw-r--r--test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.err1
-rw-r--r--test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.out0
-rw-r--r--test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.err7
-rw-r--r--test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.out0
-rw-r--r--test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.err0
-rw-r--r--test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.out15
-rw-r--r--test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.err1
-rw-r--r--test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.out0
-rw-r--r--test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err0
-rw-r--r--test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out1
-rw-r--r--test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err0
-rw-r--r--test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out3
-rw-r--r--test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err0
-rw-r--r--test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out0
-rw-r--r--test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err0
-rw-r--r--test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.out0
-rw-r--r--test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.err0
-rw-r--r--test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.out0
-rw-r--r--test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.err0
-rw-r--r--test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.out4
-rw-r--r--test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.err0
-rw-r--r--test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.out36
-rw-r--r--test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err0
-rw-r--r--test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out3
-rw-r--r--test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.err0
-rw-r--r--test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.out33
-rw-r--r--test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err0
-rw-r--r--test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out0
-rw-r--r--test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err0
-rw-r--r--test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.out2
-rw-r--r--test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.err0
-rw-r--r--test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.out11
-rw-r--r--test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.err0
-rw-r--r--test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out0
-rw-r--r--test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err0
-rw-r--r--test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out0
-rw-r--r--test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err0
-rw-r--r--test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out1
-rw-r--r--test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err0
-rw-r--r--test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out1
-rw-r--r--test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.err0
-rw-r--r--test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.out33
-rw-r--r--test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err0
-rw-r--r--test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out7
-rw-r--r--test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err0
-rw-r--r--test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.out7
-rw-r--r--test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.err0
-rw-r--r--test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.out2
-rw-r--r--test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.err0
-rw-r--r--test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.out5
-rw-r--r--test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.err0
-rw-r--r--test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.out7
-rw-r--r--test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.err0
-rw-r--r--test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.out6
-rw-r--r--test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.err0
-rw-r--r--test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.out7
-rw-r--r--test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.err0
-rw-r--r--test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.out6
-rw-r--r--test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.err0
-rw-r--r--test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.out5
-rw-r--r--test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.err0
-rw-r--r--test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.out6
-rw-r--r--test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.err0
-rw-r--r--test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.out9
-rw-r--r--test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.err0
-rw-r--r--test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out6
-rw-r--r--test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err0
-rw-r--r--test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out6
-rw-r--r--test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.err4
-rw-r--r--test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.out0
-rw-r--r--test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err0
-rw-r--r--test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.out2
-rw-r--r--test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.err4
-rw-r--r--test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.out0
-rw-r--r--test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.err0
-rw-r--r--test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.out2
-rw-r--r--test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.err0
-rw-r--r--test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.out3
-rw-r--r--test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.err10
-rw-r--r--test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.out0
-rw-r--r--test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.err6
-rw-r--r--test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.out0
-rw-r--r--test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.err4
-rw-r--r--test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.out0
-rw-r--r--test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err4
-rw-r--r--test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.out0
-rw-r--r--test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.err4
-rw-r--r--test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.out0
-rw-r--r--test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.err0
-rw-r--r--test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.out3
-rw-r--r--test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.err0
-rw-r--r--test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.out2
-rw-r--r--test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.err4
-rw-r--r--test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.out0
-rw-r--r--test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.err5
-rw-r--r--test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.out0
-rw-r--r--test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err4
-rw-r--r--test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.out0
-rw-r--r--test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err4
-rw-r--r--test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.out0
-rw-r--r--test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err4
-rw-r--r--test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.out0
-rw-r--r--test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.err0
-rw-r--r--test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.out2
-rw-r--r--test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.err0
-rw-r--r--test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.out2
-rw-r--r--test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.err5
-rw-r--r--test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.out0
-rw-r--r--test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err7
-rw-r--r--test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.out0
-rw-r--r--test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err4
-rw-r--r--test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.out0
-rw-r--r--test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.err5
-rw-r--r--test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.out0
-rw-r--r--test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.err0
-rw-r--r--test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.out2
-rw-r--r--test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err6
-rw-r--r--test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.out0
-rw-r--r--test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.err6
-rw-r--r--test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.out0
-rw-r--r--test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.err0
-rw-r--r--test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.out2
-rw-r--r--test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.err0
-rw-r--r--test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.out2
-rw-r--r--test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err6
-rw-r--r--test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.out0
-rw-r--r--test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.err0
-rw-r--r--test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.out4
-rw-r--r--test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.err0
-rw-r--r--test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.out4
-rw-r--r--test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.err6
-rw-r--r--test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.out0
-rw-r--r--test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.err0
-rw-r--r--test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.out4
-rw-r--r--test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.err6
-rw-r--r--test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out0
-rw-r--r--test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err4
-rw-r--r--test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out0
-rw-r--r--test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err4
-rw-r--r--test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out0
-rw-r--r--test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.err0
-rw-r--r--test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.out2
-rw-r--r--test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.err0
-rw-r--r--test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.out4
-rw-r--r--test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.err0
-rw-r--r--test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.out4
-rw-r--r--test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.err4
-rw-r--r--test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.out0
-rw-r--r--test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.err0
-rw-r--r--test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.out2
-rw-r--r--test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.err0
-rw-r--r--test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.out5
-rw-r--r--test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.err0
-rw-r--r--test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.out2
-rw-r--r--test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err4
-rw-r--r--test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.out0
-rw-r--r--test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.err0
-rw-r--r--test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.out4
-rw-r--r--test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.err0
-rw-r--r--test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.out3
-rw-r--r--test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.err4
-rw-r--r--test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.out0
-rw-r--r--test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.err0
-rw-r--r--test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.out2
-rw-r--r--test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.err0
-rw-r--r--test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.out2
-rw-r--r--test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.err10
-rw-r--r--test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.out0
-rw-r--r--test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.err0
-rw-r--r--test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.out1
-rw-r--r--test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.err0
-rw-r--r--test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.out3
-rw-r--r--test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.err0
-rw-r--r--test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.out5
-rw-r--r--test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.err0
-rw-r--r--test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.out4
-rw-r--r--test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.err0
-rw-r--r--test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.out6
-rw-r--r--test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.err0
-rw-r--r--test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out2
-rw-r--r--test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err0
-rw-r--r--test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out5
-rw-r--r--test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err0
-rw-r--r--test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out7
-rw-r--r--test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err0
-rw-r--r--test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out7
-rw-r--r--test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err0
-rw-r--r--test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.out6
-rw-r--r--test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.err0
-rw-r--r--test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.out12
-rw-r--r--test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.err0
-rw-r--r--test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.out7
-rw-r--r--test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.err0
-rw-r--r--test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.out10
-rw-r--r--test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.err0
-rw-r--r--test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.out6
-rw-r--r--test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.err0
-rw-r--r--test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.out7
-rw-r--r--test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.err0
-rw-r--r--test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.out10
-rw-r--r--test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.err0
-rw-r--r--test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.out6
-rw-r--r--test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.err0
-rw-r--r--test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.out11
-rw-r--r--test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.err0
-rw-r--r--test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.out10
-rw-r--r--test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.out2
-rw-r--r--test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.err0
-rw-r--r--test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.err1
-rw-r--r--test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.out0
-rw-r--r--test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.err1
-rw-r--r--test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.out0
-rw-r--r--test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.out2
-rw-r--r--test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.err0
-rw-r--r--test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.out2
-rw-r--r--test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.err0
-rw-r--r--test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.out0
-rw-r--r--test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.err0
-rw-r--r--test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.out3
-rw-r--r--test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.err0
-rw-r--r--test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.out5
-rw-r--r--test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.err0
-rw-r--r--test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.out2
-rw-r--r--test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.err0
-rw-r--r--test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.out5
-rw-r--r--test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.err0
-rw-r--r--test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.out3
-rw-r--r--test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.err0
-rw-r--r--test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.out2
-rw-r--r--test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.err0
-rw-r--r--test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.out2
-rw-r--r--test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.err0
-rw-r--r--test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.out5
-rw-r--r--test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.err0
-rw-r--r--test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.out2
-rw-r--r--test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.err4
-rw-r--r--test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.out0
-rw-r--r--test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.err0
-rw-r--r--test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.out3
-rw-r--r--test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.err0
-rw-r--r--test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.out2
-rw-r--r--test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.err0
-rw-r--r--test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.out2
-rw-r--r--test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.err0
-rw-r--r--test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.out2
-rw-r--r--test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.err0
-rw-r--r--test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.out2
-rw-r--r--test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.err0
-rw-r--r--test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.out2
-rw-r--r--test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.err0
-rw-r--r--test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.out2
-rw-r--r--test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.err0
-rw-r--r--test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.out2
-rw-r--r--test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.err1
-rw-r--r--test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.out0
-rw-r--r--test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.err0
-rw-r--r--test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.out2
-rw-r--r--test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.err1
-rw-r--r--test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.out0
-rw-r--r--test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.err0
-rw-r--r--test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.out2
-rw-r--r--test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.err0
-rw-r--r--test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.out3
-rw-r--r--test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.err0
-rw-r--r--test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.out2
-rw-r--r--test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.err0
-rw-r--r--test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.out2
-rw-r--r--test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.err0
-rw-r--r--test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.out2
-rw-r--r--test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.err0
-rw-r--r--test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.out2
-rw-r--r--test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.err0
-rw-r--r--test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.out2
-rw-r--r--test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.err1
-rw-r--r--test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.out0
-rw-r--r--test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.err0
-rw-r--r--test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.out2
-rw-r--r--test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.err0
-rw-r--r--test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.out2
-rw-r--r--test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.err0
-rw-r--r--test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.out2
-rw-r--r--test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.err0
-rw-r--r--test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.out2
-rw-r--r--test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.err0
-rw-r--r--test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.out2
-rw-r--r--test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.err0
-rw-r--r--test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.out2
-rw-r--r--test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.err0
-rw-r--r--test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.out2
-rw-r--r--test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.err0
-rw-r--r--test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.out2
-rw-r--r--test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.err0
-rw-r--r--test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.out2
-rw-r--r--test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.err0
-rw-r--r--test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.out2
-rw-r--r--test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.err0
-rw-r--r--test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.out2
-rw-r--r--test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.err0
-rw-r--r--test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.out2
-rw-r--r--test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.err1
-rw-r--r--test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.out0
-rw-r--r--test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.err0
-rw-r--r--test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.out2
-rw-r--r--test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.err0
-rw-r--r--test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.out2
-rw-r--r--test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.err0
-rw-r--r--test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.out2
-rw-r--r--test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.err0
-rw-r--r--test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.out3
-rw-r--r--test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.err4
-rw-r--r--test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out0
-rw-r--r--test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err0
-rw-r--r--test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out4
-rw-r--r--test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err0
-rw-r--r--test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out2
-rw-r--r--test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err0
-rw-r--r--test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out27
-rw-r--r--test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err0
-rw-r--r--test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.out2
-rw-r--r--test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.err9
-rw-r--r--test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.out0
-rw-r--r--test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.err0
-rw-r--r--test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.out2
-rw-r--r--test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.err0
-rw-r--r--test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.out2
-rw-r--r--test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.err0
-rw-r--r--test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.out2
-rw-r--r--test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.err0
-rw-r--r--test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.out12
-rw-r--r--test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.err0
-rw-r--r--test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.out4
-rw-r--r--test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.err0
-rw-r--r--test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.out24
-rw-r--r--test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.err0
-rw-r--r--test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.out6
-rw-r--r--test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.err0
-rw-r--r--test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.out2
-rw-r--r--test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.err0
-rw-r--r--test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out2
-rw-r--r--test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.err0
-rw-r--r--test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.out2
-rw-r--r--test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err0
-rw-r--r--test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out64
-rw-r--r--test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err0
-rw-r--r--test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out198
-rw-r--r--test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err0
-rw-r--r--test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out2
-rw-r--r--test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err0
-rw-r--r--test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.out8
-rw-r--r--test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.err1
-rw-r--r--test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.out0
-rw-r--r--test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.err0
-rw-r--r--test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.out2
-rw-r--r--test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.err0
-rw-r--r--test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.out8
-rw-r--r--test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.err0
-rw-r--r--test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.out2
-rw-r--r--test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.err0
-rw-r--r--test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.out2
-rw-r--r--test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.err0
-rw-r--r--test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.out2
-rw-r--r--test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.err1
-rw-r--r--test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.out0
-rw-r--r--test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.err0
-rw-r--r--test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.out2
-rw-r--r--test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.err0
-rw-r--r--test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.out2
-rw-r--r--test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.err0
-rw-r--r--test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.out2
-rw-r--r--test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.err0
-rw-r--r--test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.out2
-rw-r--r--test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.err0
-rw-r--r--test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.out2
-rw-r--r--test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.err0
-rw-r--r--test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.out2
-rw-r--r--test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.err0
-rw-r--r--test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.out24
-rw-r--r--test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.err0
-rw-r--r--test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.out2
-rw-r--r--test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.err0
-rw-r--r--test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.out3
-rw-r--r--test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.err0
-rw-r--r--test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.out2
-rw-r--r--test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.err0
-rw-r--r--test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.out2
-rw-r--r--test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.err0
-rw-r--r--test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.out6
-rw-r--r--test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.err0
-rw-r--r--test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.out2
-rw-r--r--test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.err0
-rw-r--r--test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.out16
-rw-r--r--test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.err0
-rw-r--r--test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.out3
-rw-r--r--test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.err1
-rw-r--r--test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.out0
-rw-r--r--test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.err0
-rw-r--r--test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.out2
-rw-r--r--test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.err0
-rw-r--r--test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.out2
-rw-r--r--test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.err0
-rw-r--r--test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.out2
-rw-r--r--test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.err0
-rw-r--r--test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.out2
-rw-r--r--test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.err0
-rw-r--r--test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.out2
-rw-r--r--test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.err1
-rw-r--r--test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.out0
-rw-r--r--test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.err0
-rw-r--r--test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.out2
-rw-r--r--test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.err0
-rw-r--r--test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.out2
-rw-r--r--test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.err0
-rw-r--r--test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.out2
-rw-r--r--test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.err1
-rw-r--r--test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.out0
-rw-r--r--test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.err0
-rw-r--r--test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.out2
-rw-r--r--test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.err0
-rw-r--r--test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.out2
-rw-r--r--test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.err0
-rw-r--r--test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.out2
-rw-r--r--test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.err0
-rw-r--r--test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.out2
-rw-r--r--test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.err0
-rw-r--r--test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.out2
-rw-r--r--test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.err1
-rw-r--r--test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.out0
-rw-r--r--test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.err0
-rw-r--r--test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.out3
-rw-r--r--test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.err0
-rw-r--r--test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.out2
-rw-r--r--test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.err0
-rw-r--r--test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.out2
-rw-r--r--test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.err0
-rw-r--r--test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.out16
-rw-r--r--test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.err0
-rw-r--r--test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.out3
-rw-r--r--test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.err0
-rw-r--r--test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.out2
-rw-r--r--test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.err0
-rw-r--r--test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.out2
-rw-r--r--test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.err0
-rw-r--r--test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.out2
-rw-r--r--test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.err1
-rw-r--r--test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.out0
-rw-r--r--test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.err0
-rw-r--r--test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.out2
-rw-r--r--test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.err0
-rw-r--r--test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.out2
-rw-r--r--test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.err0
-rw-r--r--test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.out2
-rw-r--r--test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.err0
-rw-r--r--test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.out2
-rw-r--r--test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.err0
-rw-r--r--test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.out0
-rw-r--r--test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.err1
-rw-r--r--test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.out0
-rw-r--r--test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.err0
-rw-r--r--test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.out2
-rw-r--r--test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.err0
-rw-r--r--test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.out47
-rw-r--r--test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.err0
-rw-r--r--test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.out2
-rw-r--r--test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.err0
-rw-r--r--test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.out0
-rw-r--r--test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.err0
-rw-r--r--test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.out2
-rw-r--r--test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.err0
-rw-r--r--test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.out2
-rw-r--r--test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.err0
-rw-r--r--test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.out2
-rw-r--r--test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.err0
-rw-r--r--test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.out2
-rw-r--r--test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.err0
-rw-r--r--test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.out2
-rw-r--r--test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.err0
-rw-r--r--test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.out2
-rw-r--r--test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.err0
-rw-r--r--test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.out2
-rw-r--r--test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.err0
-rw-r--r--test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.out2
-rw-r--r--test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.err0
-rw-r--r--test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.out2
-rw-r--r--test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.err0
-rw-r--r--test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.out2
-rw-r--r--test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.err1
-rw-r--r--test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.out0
-rw-r--r--test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.err0
-rw-r--r--test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.out2
-rw-r--r--test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.err0
-rw-r--r--test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.out2
-rw-r--r--test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.err0
-rw-r--r--test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.out2
-rw-r--r--test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.err0
-rw-r--r--test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.out2
-rw-r--r--test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.err1
-rw-r--r--test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.out0
-rw-r--r--test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.err1
-rw-r--r--test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.out0
-rw-r--r--test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.err0
-rw-r--r--test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.out2
-rw-r--r--test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.err0
-rw-r--r--test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.out2
-rw-r--r--test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.err0
-rw-r--r--test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.out2
-rw-r--r--test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.err0
-rw-r--r--test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.out2
-rw-r--r--test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.err0
-rw-r--r--test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.out2
-rw-r--r--test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.err0
-rw-r--r--test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.out2
-rw-r--r--test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.err0
-rw-r--r--test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.out19
-rw-r--r--test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.out1
-rw-r--r--test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.out3
-rw-r--r--test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.out1
-rw-r--r--test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out2
-rw-r--r--test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.out1
-rw-r--r--test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.out1
-rw-r--r--test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.err0
-rw-r--r--test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.out3
-rw-r--r--test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.out0
-rw-r--r--test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err4
-rw-r--r--test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.out0
-rw-r--r--test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.err0
-rw-r--r--test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.out0
-rw-r--r--test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.err0
-rw-r--r--test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.out6
-rw-r--r--test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.err0
-rw-r--r--test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.out6
-rw-r--r--test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.err1
-rw-r--r--test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out0
-rw-r--r--test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err1
-rw-r--r--test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out0
-rw-r--r--test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.err4
-rw-r--r--test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.out0
-rw-r--r--test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.err4
-rw-r--r--test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.out0
-rw-r--r--test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err3
-rw-r--r--test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out8
-rw-r--r--test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.err2
-rw-r--r--test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.out0
-rw-r--r--test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err0
-rw-r--r--test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out178
-rw-r--r--test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.err0
-rw-r--r--test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out149
-rw-r--r--test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.err0
-rw-r--r--test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.out111
-rw-r--r--test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err0
-rw-r--r--test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out111
-rw-r--r--test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.err0
-rw-r--r--test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.out2
-rw-r--r--test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.err0
-rw-r--r--test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.out4
-rw-r--r--test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err0
-rw-r--r--test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out74
-rw-r--r--test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.err0
-rw-r--r--test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.out159
-rw-r--r--test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err0
-rw-r--r--test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out58
-rw-r--r--test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.err0
-rw-r--r--test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.out149
-rw-r--r--test/expected_help.txt4013
-rw-r--r--test/file_for_dot_read.sql4
-rw-r--r--test/formats/collision/format.json48
-rw-r--r--test/formats/customlevel/format.json25
-rw-r--r--test/formats/jsontest-subsec/format.json27
-rw-r--r--test/formats/jsontest/format.json36
-rw-r--r--test/formats/jsontest/lnav-logstash.json47
-rw-r--r--test/formats/jsontest/rewrite-user.lnav2
-rw-r--r--test/formats/jsontest2/format.json49
-rw-r--r--test/formats/jsontest3/format.json75
-rw-r--r--test/formats/nestedjson/format.json32
-rw-r--r--test/formats/scripts/multiline-echo.lnav3
-rw-r--r--test/formats/scripts/nested-redirecting.lnav5
-rw-r--r--test/formats/scripts/redirecting.lnav6
-rw-r--r--test/formats/sqldir/init.sql5
-rw-r--r--test/formats/timestamp/format.json26
-rw-r--r--test/formats/xmlmsg/format.json73
-rw-r--r--test/gp_test.cc103
-rw-r--r--test/lb_test.cc65
-rw-r--r--test/listview_output.070
-rw-r--r--test/listview_output.170
-rw-r--r--test/listview_output.270
-rw-r--r--test/listview_output.370
-rw-r--r--test/listview_output.468
-rw-r--r--test/listview_output.559
-rw-r--r--test/listview_output.659
-rw-r--r--test/lnav_doctests.cc231
-rw-r--r--test/log-samples/sample-057d6c669632ef9d07b6adec605f6bdeae19af27.txt13
-rw-r--r--test/log-samples/sample-06aaa6f48a801f592558575d886864d6c3ab9ed4.txt40
-rw-r--r--test/log-samples/sample-1aeb47c0a97d19bb7418f0172480e05e49c6e53e.txt17
-rw-r--r--test/log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt4
-rw-r--r--test/log-samples/sample-3856ad0f551a04fde41a020158d6b33ef97c870a.txt17
-rw-r--r--test/log-samples/sample-45364b3fd51af92a4ad8a309b5f4fd88.txt40
-rw-r--r--test/log-samples/sample-500c9e492e04f5f58862c8086ca301de0dd976ce.txt13
-rw-r--r--test/log-samples/sample-55ac97afae4b0650ccb62e2dbc8d89bb.txt15
-rw-r--r--test/log-samples/sample-6049d4309f26eefb1a3406d937a9ba8a0df592a7.txt13
-rw-r--r--test/log-samples/sample-62315d884afdc4155b35f905415c74bfcfd39fc2.txt17
-rw-r--r--test/log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt4
-rw-r--r--test/log-samples/sample-9cf7fbb3546c676c686fac0ed096d026f46c875f.txt13
-rw-r--r--test/log-samples/sample-a74570613c082c7fe283672031e18e54e8887ffb.txt13
-rw-r--r--test/log-samples/sample-aca2878a2e50779c6697c0747ab1f60e4b368dcb.txt15
-rw-r--r--test/log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt21
-rw-r--r--test/log-samples/sample-bc6f6cf689fa5455616b4d9fbe121a48d3c9de59.txt25
-rw-r--r--test/log-samples/sample-c15acd32844669d23d0cbc88ec548129ed2c592e.txt87
-rw-r--r--test/log-samples/sample-c23f22c1b932b904203e018f78dead95fb89b15d.txt37
-rw-r--r--test/log-samples/sample-d0d6b3fc6766caac5ac3fac4a3754ceaab785eb8.txt33
-rw-r--r--test/log-samples/sample-d4a0aedc8350f64b22403eeef4eca71fbf749d2b.txt9
-rw-r--r--test/log-samples/sample-d714b5e8cd354321f376ed1c0a70ec9a2f58076d.txt9
-rw-r--r--test/log-samples/sample-dd7d406352ec6a11d966b6f015a9482b060f2b29.txt23
-rw-r--r--test/log-samples/sample-e779d1771e34f5203ae73e85802e78002be63db6.txt25
-rw-r--r--test/log-samples/sample-f5afbee90a8c054061c4e9ffe673293cce7761de.txt13
-rw-r--r--test/log-samples/sample-fc8923633e57bacd641d80dde3ff878212230552.txt13
-rw-r--r--test/log.clog2
-rw-r--r--test/logfile_access_log.03
-rw-r--r--test/logfile_access_log.11
-rw-r--r--test/logfile_ansi.01
-rw-r--r--test/logfile_ansi.110
-rw-r--r--test/logfile_bad_access_log.03
-rw-r--r--test/logfile_bad_syslog.04
-rw-r--r--test/logfile_block.14
-rw-r--r--test/logfile_block.22
-rw-r--r--test/logfile_blued.06
-rw-r--r--test/logfile_bro_conn.log.0101
-rw-r--r--test/logfile_bro_http.log.0206
-rw-r--r--test/logfile_crlf.02
-rw-r--r--test/logfile_cxx.01
-rw-r--r--test/logfile_empty.00
-rw-r--r--test/logfile_epoch.02
-rw-r--r--test/logfile_epoch.12
-rw-r--r--test/logfile_filter.013
-rw-r--r--test/logfile_for_join.010
-rw-r--r--test/logfile_generic.02
-rw-r--r--test/logfile_generic.12
-rw-r--r--test/logfile_generic.22
-rw-r--r--test/logfile_generic.32
-rw-r--r--test/logfile_generic_with_header.04
-rw-r--r--test/logfile_glog.07
-rw-r--r--test/logfile_haproxy.017
-rw-r--r--test/logfile_invalid_json.json5
-rw-r--r--test/logfile_invalid_json2.json3
-rw-r--r--test/logfile_journald.json2
-rw-r--r--test/logfile_json.json13
-rw-r--r--test/logfile_json2.json3
-rw-r--r--test/logfile_json3.json3
-rw-r--r--test/logfile_json_subsec.json2
-rw-r--r--test/logfile_leveltest.08
-rw-r--r--test/logfile_logfmt.05
-rw-r--r--test/logfile_mixed_json2.json18
-rw-r--r--test/logfile_multiline.03
-rw-r--r--test/logfile_nested_json.json13
-rw-r--r--test/logfile_openam.02
-rw-r--r--test/logfile_plain.03
-rw-r--r--test/logfile_pretty.023
-rw-r--r--test/logfile_procstate.043
-rw-r--r--test/logfile_rollover.06
-rw-r--r--test/logfile_rollover.15
-rw-r--r--test/logfile_strace_log.09
-rw-r--r--test/logfile_syslog.04
-rw-r--r--test/logfile_syslog.14
-rw-r--r--test/logfile_syslog.23
-rw-r--r--test/logfile_syslog.317
-rw-r--r--test/logfile_syslog_fr.01
-rw-r--r--test/logfile_syslog_with_access_log.05
-rw-r--r--test/logfile_syslog_with_header.06
-rw-r--r--test/logfile_syslog_with_mixed_times.013
-rw-r--r--test/logfile_tai64n.010
-rw-r--r--test/logfile_tcf.030
-rw-r--r--test/logfile_tcf.13
-rw-r--r--test/logfile_tcsh_history.04
-rw-r--r--test/logfile_uwsgi.019
-rw-r--r--test/logfile_vami.04
-rw-r--r--test/logfile_vdsm.016
-rw-r--r--test/logfile_vmw_log.04
-rw-r--r--test/logfile_vpxd.012
-rw-r--r--test/logfile_w3c.05
-rw-r--r--test/logfile_w3c.17
-rw-r--r--test/logfile_w3c.222
-rw-r--r--test/logfile_w3c.310
-rw-r--r--test/logfile_w3c.46
-rw-r--r--test/logfile_w3c.52
-rw-r--r--test/logfile_w3c.65
-rw-r--r--test/logfile_w3c_big.0254
-rw-r--r--test/logfile_with_a_really_long_name_to_test_a_bug_with_long_names.01
-rw-r--r--test/logfile_xml_msg.036
-rw-r--r--test/multiline.lnav14
-rw-r--r--test/mvwattrline_output.049
-rw-r--r--test/nested.lnav2
-rwxr-xr-xtest/parser_debugger.py249
-rw-r--r--test/remote-log-dir/logfile_access_log.03
-rw-r--r--test/remote-log-dir/logfile_access_log.11
-rw-r--r--test/rltest.cc216
-rw-r--r--test/scripty.cc1153
-rw-r--r--test/si_test.cc49
-rw-r--r--test/slicer.cc99
-rw-r--r--test/sql.0.in6
-rw-r--r--test/sql.0.out7
-rw-r--r--test/test_abbrev.cc60
-rw-r--r--test/test_ansi_scrubber.cc98
-rw-r--r--test/test_auto_fd.cc82
-rw-r--r--test/test_auto_mem.cc115
-rw-r--r--test/test_bookmarks.cc146
-rw-r--r--test/test_cli.sh31
-rw-r--r--test/test_cmds.sh515
-rw-r--r--test/test_column_namer.cc68
-rwxr-xr-xtest/test_config.sh39
-rw-r--r--test/test_curl.sh48
-rw-r--r--test/test_data_parser.sh16
-rw-r--r--test/test_date_time_scanner.cc192
-rw-r--r--test/test_events.sh31
-rw-r--r--test/test_format_installer.sh34
-rw-r--r--test/test_format_loader.sh17
-rw-r--r--test/test_grep_proc.sh57
-rw-r--r--test/test_grep_proc2.cc150
-rw-r--r--test/test_json_format.sh141
-rw-r--r--test/test_line_buffer.sh78
-rw-r--r--test/test_line_buffer2.cc157
-rw-r--r--test/test_listview.sh36
-rw-r--r--test/test_log_accel.cc70
-rw-r--r--test/test_logfile.sh701
-rw-r--r--test/test_md2attr_line.cc34
-rw-r--r--test/test_meta.sh110
-rw-r--r--test/test_mvwattrline.sh6
-rw-r--r--test/test_ncurses_unicode.cc40
-rw-r--r--test/test_pretty_print.sh45
-rw-r--r--test/test_regex101.sh77
-rw-r--r--test/test_reltime.cc427
-rw-r--r--test/test_remote.sh119
-rw-r--r--test/test_scripts.sh51
-rw-r--r--test/test_sessions.sh119
-rw-r--r--test/test_shlexer.sh32
-rw-r--r--test/test_sql.sh1097
-rw-r--r--test/test_sql_anno.sh50
-rw-r--r--test/test_sql_coll_func.sh29
-rw-r--r--test/test_sql_fs_func.sh53
-rw-r--r--test/test_sql_indexes.sh45
-rw-r--r--test/test_sql_json_func.sh132
-rw-r--r--test/test_sql_regexp.sh30
-rw-r--r--test/test_sql_search_table.sh26
-rw-r--r--test/test_sql_str_func.sh170
-rw-r--r--test/test_sql_time_func.sh71
-rw-r--r--test/test_sql_views_vtab.sh173
-rw-r--r--test/test_sql_xml_func.sh11
-rw-r--r--test/test_sql_yaml_func.sh5
-rw-r--r--test/test_stubs.cc93
-rw-r--r--test/test_text_anonymizer.cc131
-rw-r--r--test/test_text_file.sh33
-rw-r--r--test/test_top_status.cc90
-rw-r--r--test/test_tui.sh28
-rw-r--r--test/test_view_colors.sh6
-rw-r--r--test/test_vt52_curses.sh6
-rw-r--r--test/textfile_0.md9
-rw-r--r--test/textfile_ansi.01
-rw-r--r--test/textfile_json_indented.012
-rw-r--r--test/textfile_json_one_line.01
-rw-r--r--test/textfile_quoted_json.01
-rw-r--r--test/toplevel.lnav4
-rw-r--r--test/tui-captures/tui_echo.0229
-rw-r--r--test/tui-captures/tui_help.0179
-rwxr-xr-xtest/update_parser_output.sh13
-rw-r--r--test/view_colors_output.054
-rw-r--r--test/vt52_curses_input.049
-rw-r--r--test/vt52_curses_input.138
-rw-r--r--test/vt52_curses_output.039
-rw-r--r--test/vt52_curses_output.138
-rw-r--r--test/xpath_tui.0458
1349 files changed, 29845 insertions, 0 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..df39caa
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,88 @@
+enable_testing()
+
+include_directories(
+ . ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/fmtlib
+ ${CMAKE_CURRENT_BINARY_DIR}/../src ${CMAKE_CURRENT_BINARY_DIR})
+
+add_executable(test_abbrev test_abbrev.cc test_stubs.cc)
+target_link_libraries(test_abbrev diag)
+add_test(NAME test_abbrev COMMAND test_abbrev)
+
+add_executable(test_ansi_scrubber test_ansi_scrubber.cc test_stubs.cc)
+target_link_libraries(test_ansi_scrubber diag)
+add_test(NAME test_ansi_scrubber COMMAND test_ansi_scrubber)
+
+add_executable(test_auto_fd test_auto_fd.cc test_stubs.cc)
+target_link_libraries(test_auto_fd diag)
+add_test(NAME test_auto_fd COMMAND test_auto_fd)
+
+add_executable(test_auto_mem test_auto_mem.cc test_stubs.cc)
+target_link_libraries(test_auto_mem diag)
+add_test(NAME test_auto_mem COMMAND test_auto_mem)
+
+add_executable(test_column_namer test_column_namer.cc test_stubs.cc)
+target_include_directories(test_column_namer PUBLIC ../src/third-party/doctest-root)
+target_link_libraries(test_column_namer diag)
+add_test(NAME test_column_namer COMMAND test_column_namer)
+
+add_executable(document.sections.tests document.sections.tests.cc test_stubs.cc)
+target_include_directories(document.sections.tests PUBLIC ../src/third-party/doctest-root)
+target_link_libraries(document.sections.tests diag)
+add_test(NAME document.sections.tests COMMAND document.sections.tests)
+
+add_executable(test_bookmarks test_bookmarks.cc test_stubs.cc)
+target_link_libraries(test_bookmarks diag)
+add_test(NAME test_bookmarks COMMAND test_bookmarks)
+
+add_executable(test_date_time_scanner test_date_time_scanner.cc)
+target_link_libraries(test_date_time_scanner base lnavdt)
+add_test(NAME test_date_time_scanner COMMAND test_date_time_scanner)
+
+add_executable(test_grep_proc2 test_grep_proc2.cc)
+target_link_libraries(test_grep_proc2 lnavfileio)
+add_test(NAME test_grep_proc2 COMMAND test_grep_proc2)
+
+add_executable(test_line_buffer2 test_line_buffer2.cc)
+target_link_libraries(test_line_buffer2 lnavfileio)
+add_test(NAME test_line_buffer2 COMMAND test_line_buffer2)
+
+add_executable(test_log_accel test_log_accel.cc test_stubs.cc)
+target_link_libraries(test_log_accel diag)
+add_test(NAME test_log_accel COMMAND test_log_accel)
+
+add_executable(lnav_doctests lnav_doctests.cc test_stubs.cc)
+target_include_directories(lnav_doctests PUBLIC ../src/third-party/doctest-root)
+target_link_libraries(lnav_doctests diag ${lnav_LIBS})
+add_test(NAME lnav_doctests COMMAND lnav_doctests)
+
+add_executable(test_reltime test_reltime.cc test_stubs.cc)
+target_include_directories(test_reltime PUBLIC ../src/third-party/doctest-root)
+target_link_libraries(test_reltime diag)
+add_test(NAME test_reltime COMMAND test_reltime)
+
+add_executable(test_top_status test_top_status.cc test_stubs.cc)
+target_link_libraries(test_top_status diag logfmt)
+add_test(NAME test_top_status COMMAND test_top_status)
+
+add_executable(test_text_anonymizer test_text_anonymizer.cc test_stubs.cc)
+target_include_directories(test_text_anonymizer PUBLIC ../src/third-party/doctest-root)
+target_link_libraries(test_text_anonymizer diag)
+add_test(NAME test_text_anonymizer COMMAND test_text_anonymizer)
+
+add_executable(drive_view_colors drive_view_colors.cc test_stubs.cc)
+target_link_libraries(drive_view_colors diag)
+
+add_executable(drive_vt52_curses drive_vt52_curses.cc test_stubs.cc)
+target_link_libraries(drive_vt52_curses diag)
+
+add_executable(drive_logfile drive_logfile.cc test_stubs.cc)
+target_link_libraries(drive_logfile diag)
+
+add_executable(drive_sql_anno drive_sql_anno.cc test_stubs.cc)
+target_link_libraries(drive_sql_anno diag)
+
+add_executable(drive_data_scanner drive_data_scanner.cc test_stubs.cc)
+target_link_libraries(drive_data_scanner diag logfmt)
+
+add_executable(scripty scripty.cc test_stubs.cc)
+target_link_libraries(scripty diag)
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..85eb48d
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,513 @@
+
+include $(top_srcdir)/aminclude_static.am
+
+TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
+LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT
+
+RM_V = $(RM_V_@AM_V@)
+RM_V_ = $(RM_V_@AM_DEFAULT_V@)
+RM_V_0 = @echo " RM " $@;
+
+AM_LIBS = $(CODE_COVERAGE_LIBS)
+AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
+AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
+
+AM_CPPFLAGS = \
+ -Wall \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/fmtlib \
+ -I$(top_srcdir)/src/third-party \
+ -I$(top_srcdir)/src/third-party/scnlib/include \
+ $(CODE_COVERAGE_CPPFLAGS) \
+ $(LIBARCHIVE_CFLAGS) \
+ $(READLINE_CFLAGS) \
+ $(PCRE_CFLAGS) \
+ $(SQLITE3_CFLAGS)
+
+# AM_CFLAGS = -fprofile-arcs -ftest-coverage
+# AM_CXXFLAGS = -fprofile-arcs -ftest-coverage
+
+remote/ssh_host_rsa_key:
+ mkdir -p remote
+ ssh-keygen -f remote/ssh_host_rsa_key -N '' -t rsa
+
+remote/ssh_host_dsa_key:
+ mkdir -p remote
+ ssh-keygen -f remote/ssh_host_dsa_key -N '' -t dsa
+
+remote/id_rsa:
+ mkdir -p remote
+ ssh-keygen -f remote/id_rsa -N '' -t rsa
+ cp -f remote/id_rsa.pub remote/authorized_keys
+
+noinst_LIBRARIES = \
+ libtestdummy.a
+
+libtestdummy_a_SOURCES = \
+ test_stubs.cc
+
+DUMMY_OBJS = \
+ test_stubs.$(OBJEXT)
+
+check_PROGRAMS = \
+ drive_data_scanner \
+ drive_line_buffer \
+ drive_grep_proc \
+ drive_listview \
+ drive_logfile \
+ drive_mvwattrline \
+ drive_shlexer \
+ drive_sql \
+ drive_sql_anno \
+ drive_view_colors \
+ drive_vt52_curses \
+ drive_readline_curses \
+ lnav_doctests \
+ slicer \
+ scripty \
+ test_abbrev \
+ test_ansi_scrubber \
+ test_auto_fd \
+ test_auto_mem \
+ test_bookmarks \
+ test_date_time_scanner \
+ test_grep_proc2 \
+ test_line_buffer2 \
+ test_log_accel \
+ test_ncurses_unicode \
+ test_reltime \
+ test_text_anonymizer \
+ test_top_status
+
+AM_LDFLAGS = \
+ $(LIBARCHIVE_LDFLAGS) \
+ $(STATIC_LDFLAGS) \
+ $(SQLITE3_LDFLAGS) \
+ $(READLINE_LDFLAGS) \
+ $(CURSES_LIB)
+
+CONFIG_OBJS = \
+ ../src/ansi-palette-json.$(OBJEXT) \
+ ../src/default-config.$(OBJEXT) \
+ ../src/xterm-palette-json.$(OBJEXT)
+
+TEXT2C_OBJS = \
+ ../src/builtin-scripts.$(OBJEXT) \
+ ../src/builtin-sh-scripts.$(OBJEXT) \
+ ../src/default-formats.$(OBJEXT) \
+ ../src/time_fmts.$(OBJEXT)
+
+LDADD = \
+ -lz \
+ $(CONFIG_OBJS) \
+ $(TEXT2C_OBJS) \
+ $(DUMMY_OBJS) \
+ ../src/lnav.events.$(OBJEXT) \
+ $(top_builddir)/src/libdiag.a \
+ $(top_builddir)/src/libdatascanner.a \
+ $(top_builddir)/src/formats/logfmt/liblogfmt.a \
+ $(top_builddir)/src/fmtlib/libcppfmt.a \
+ $(top_builddir)/src/pcrepp/libpcrepp.a \
+ $(top_builddir)/src/yajl/libyajl.a \
+ $(top_builddir)/src/yajlpp/libyajlpp.a \
+ $(top_builddir)/src/base/libbase.a \
+ $(top_builddir)/src/pugixml/libpugixml.a \
+ $(top_builddir)/src/third-party/base64/lib/libbase64.a \
+ $(top_builddir)/src/third-party/scnlib/src/libscnlib.a \
+ $(READLINE_LIBS) \
+ $(CURSES_LIB) \
+ $(LIBARCHIVE_LIBS) \
+ $(SQLITE3_LIBS) \
+ $(PCRE_LIBS) \
+ $(LIBCURL)
+
+test_ansi_scrubber_SOURCES = test_ansi_scrubber.cc
+
+test_auto_fd_SOURCES = test_auto_fd.cc
+
+test_auto_mem_SOURCES = test_auto_mem.cc
+
+test_bookmarks_SOURCES = test_bookmarks.cc
+
+test_date_time_scanner_SOURCES = test_date_time_scanner.cc
+
+test_grep_proc2_SOURCES = test_grep_proc2.cc
+
+test_line_buffer2_SOURCES = test_line_buffer2.cc
+
+test_log_accel_SOURCES = test_log_accel.cc
+
+test_text_anonymizer_SOURCES = test_text_anonymizer.cc
+
+test_top_status_SOURCES = test_top_status.cc
+
+test_abbrev_SOURCES = test_abbrev.cc
+
+test_reltime_SOURCES = test_reltime.cc
+
+test_ncurses_unicode_SOURCES = test_ncurses_unicode.cc
+
+lnav_doctests_SOURCES = lnav_doctests.cc
+
+drive_line_buffer_SOURCES = drive_line_buffer.cc
+
+drive_grep_proc_SOURCES = drive_grep_proc.cc
+
+drive_listview_SOURCES = drive_listview.cc
+
+drive_logfile_SOURCES = drive_logfile.cc
+
+drive_shlexer_SOURCES = drive_shlexer.cc
+
+drive_data_scanner_SOURCES = \
+ drive_data_scanner.cc
+
+drive_mvwattrline_SOURCES = drive_mvwattrline.cc
+
+drive_view_colors_SOURCES = drive_view_colors.cc
+
+drive_vt52_curses_SOURCES = drive_vt52_curses.cc
+
+drive_readline_curses_SOURCES = drive_readline_curses.cc
+
+drive_sql_SOURCES = drive_sql.cc
+
+drive_sql_anno_SOURCES = drive_sql_anno.cc
+
+slicer_SOURCES = slicer.cc
+
+scripty_SOURCES = scripty.cc
+
+dist_noinst_SCRIPTS = \
+ parser_debugger.py \
+ test_cli.sh \
+ test_cmds.sh \
+ test_config.sh \
+ test_curl.sh \
+ test_data_parser.sh \
+ test_events.sh \
+ test_format_installer.sh \
+ test_format_loader.sh \
+ test_grep_proc.sh \
+ test_json_format.sh \
+ test_line_buffer.sh \
+ test_listview.sh \
+ test_logfile.sh \
+ test_meta.sh \
+ test_mvwattrline.sh \
+ test_regex101.sh \
+ test_remote.sh \
+ test_scripts.sh \
+ test_sessions.sh \
+ test_shlexer.sh \
+ test_sql.sh \
+ test_sql_anno.sh \
+ test_sql_coll_func.sh \
+ test_sql_fs_func.sh \
+ test_sql_indexes.sh \
+ test_sql_json_func.sh \
+ test_sql_regexp.sh \
+ test_sql_search_table.sh \
+ test_sql_str_func.sh \
+ test_sql_time_func.sh \
+ test_sql_views_vtab.sh \
+ test_sql_xml_func.sh \
+ test_sql_yaml_func.sh \
+ test_text_file.sh \
+ test_tui.sh \
+ test_view_colors.sh \
+ test_vt52_curses.sh \
+ test_pretty_print.sh
+
+include expected/expected.am
+
+dist_noinst_DATA = \
+ $(EXPECTED_FILES) \
+ expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err \
+ expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out \
+ ansi-colors.0.in \
+ bad-config/formats/invalid-json-format/format.json \
+ bad-config/formats/invalid-properties/format.json \
+ bad-config/formats/invalid-regex/format.json \
+ bad-config/formats/invalid-sample/format.json \
+ bad-config/formats/invalid-schema/format.json \
+ bad-config/formats/invalid-sql/init.sql \
+ bad-config/formats/invalid-sql/init2.sql \
+ bad-config/formats/no-regexes/format.json \
+ bad-config/formats/no-samples/format.json \
+ bad-config2/formats/invalid-config/config.json \
+ bad-config2/formats/invalid-config/config.bad-schema.json \
+ bad-config2/formats/invalid-config/config.malformed.json \
+ bad-config2/formats/invalid-config/config.truncated.json \
+ bad-config-json/formats/invalid-json/format.json \
+ bad-config-json/formats/invalid-key/format.json \
+ books.xml \
+ file_for_dot_read.sql \
+ datafile_simple.0 \
+ datafile_simple.1 \
+ datafile_simple.2 \
+ datafile_simple.3 \
+ datafile_simple.4 \
+ datafile_simple.5 \
+ datafile_simple.6 \
+ datafile_simple.7 \
+ datafile_simple.8 \
+ datafile_simple.9 \
+ datafile_simple.10 \
+ datafile_simple.11 \
+ datafile_simple.12 \
+ datafile_simple.13 \
+ datafile_simple.14 \
+ datafile_simple.15 \
+ datafile_simple.16 \
+ datafile_simple.17 \
+ datafile_simple.18 \
+ datafile_simple.19 \
+ datafile_simple.20 \
+ datafile_simple.21 \
+ datafile_simple.22 \
+ datafile_xml.0 \
+ dhcp.pcapng \
+ dhcp-trunc.pcapng \
+ expected_help.txt \
+ listview_output.0 \
+ listview_output.1 \
+ listview_output.2 \
+ listview_output.3 \
+ listview_output.4 \
+ listview_output.5 \
+ listview_output.6 \
+ log.clog \
+ logfile_access_log.0 \
+ logfile_access_log.1 \
+ logfile_ansi.0 \
+ logfile_ansi.1 \
+ logfile_bad_access_log.0 \
+ logfile_bad_syslog.0 \
+ logfile_block.1 \
+ logfile_block.2 \
+ logfile_blued.0 \
+ logfile_bro_conn.log.0 \
+ logfile_bro_http.log.0 \
+ logfile_crlf.0 \
+ logfile_cxx.0 \
+ logfile_empty.0 \
+ logfile_epoch.0 \
+ logfile_epoch.1 \
+ logfile_filter.0 \
+ logfile_for_join.0 \
+ logfile_generic.0 \
+ logfile_generic.1 \
+ logfile_generic.2 \
+ logfile_generic.3 \
+ logfile_generic_with_header.0 \
+ logfile_glog.0 \
+ logfile_haproxy.0 \
+ logfile_invalid_json.json \
+ logfile_invalid_json2.json \
+ logfile_mixed_json2.json \
+ logfile_journald.json \
+ logfile_json.json \
+ logfile_json2.json \
+ logfile_json3.json \
+ logfile_json_subsec.json \
+ logfile_leveltest.0 \
+ logfile_logfmt.0 \
+ logfile_multiline.0 \
+ logfile_nested_json.json \
+ logfile_openam.0 \
+ logfile_plain.0 \
+ logfile_pretty.0 \
+ logfile_procstate.0 \
+ logfile_rollover.0 \
+ logfile_rollover.1 \
+ logfile_strace_log.0 \
+ logfile_syslog.0 \
+ logfile_syslog.1 \
+ logfile_syslog.2 \
+ logfile_syslog.3 \
+ logfile_syslog_fr.0 \
+ logfile_syslog_with_access_log.0 \
+ logfile_syslog_with_header.0 \
+ logfile_syslog_with_mixed_times.0 \
+ logfile_tai64n.0 \
+ logfile_tcf.0 \
+ logfile_tcf.1 \
+ logfile_tcsh_history.0 \
+ logfile_uwsgi.0 \
+ logfile_vami.0 \
+ logfile_vdsm.0 \
+ logfile_vmw_log.0 \
+ logfile_vpxd.0 \
+ logfile_w3c.0 \
+ logfile_w3c.1 \
+ logfile_w3c.2 \
+ logfile_w3c.3 \
+ logfile_w3c.4 \
+ logfile_w3c.5 \
+ logfile_w3c.6 \
+ logfile_w3c_big.0 \
+ logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0 \
+ logfile_xml_msg.0 \
+ multiline.lnav \
+ nested.lnav \
+ mvwattrline_output.0 \
+ textfile_0.md \
+ textfile_ansi.0 \
+ textfile_json_indented.0 \
+ textfile_json_one_line.0 \
+ textfile_quoted_json.0 \
+ toplevel.lnav \
+ UTF-8-test.txt \
+ view_colors_output.0 \
+ vt52_curses_input.0 \
+ vt52_curses_input.1 \
+ vt52_curses_output.0 \
+ vt52_curses_output.1 \
+ xpath_tui.0 \
+ formats/collision/format.json \
+ formats/customlevel/format.json \
+ formats/jsontest/format.json \
+ formats/jsontest/lnav-logstash.json \
+ formats/jsontest/rewrite-user.lnav \
+ formats/jsontest2/format.json \
+ formats/jsontest3/format.json \
+ formats/jsontest-subsec/format.json \
+ formats/nestedjson/format.json \
+ formats/scripts/multiline-echo.lnav \
+ formats/scripts/redirecting.lnav \
+ formats/scripts/nested-redirecting.lnav \
+ formats/sqldir/init.sql \
+ formats/timestamp/format.json \
+ formats/xmlmsg/format.json \
+ log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt \
+ log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt \
+ log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt \
+ remote-log-dir/logfile_access_log.0 \
+ remote-log-dir/logfile_access_log.1 \
+ tui-captures/tui_echo.0 \
+ tui-captures/tui_help.0
+
+TESTS = \
+ lnav_doctests \
+ test_abbrev \
+ test_ansi_scrubber \
+ test_auto_fd \
+ test_auto_mem \
+ test_bookmarks \
+ test_date_time_scanner \
+ test_format_installer.sh \
+ test_format_loader.sh \
+ test_cli.sh \
+ test_cmds.sh \
+ test_config.sh \
+ test_events.sh \
+ test_listview.sh \
+ test_meta.sh \
+ test_mvwattrline.sh \
+ test_grep_proc.sh \
+ test_grep_proc2 \
+ test_json_format.sh \
+ test_log_accel \
+ test_logfile.sh \
+ test_reltime \
+ test_scripts.sh \
+ test_sessions.sh \
+ test_shlexer.sh \
+ test_sql.sh \
+ test_sql_anno.sh \
+ test_sql_coll_func.sh \
+ test_sql_fs_func.sh \
+ test_sql_indexes.sh \
+ test_sql_json_func.sh \
+ test_sql_regexp.sh \
+ test_sql_search_table.sh \
+ test_sql_str_func.sh \
+ test_sql_time_func.sh \
+ test_sql_views_vtab.sh \
+ test_sql_xml_func.sh \
+ test_sql_yaml_func.sh \
+ test_text_anonymizer \
+ test_text_file.sh \
+ test_tui.sh \
+ test_data_parser.sh \
+ test_pretty_print.sh \
+ test_view_colors.sh \
+ test_vt52_curses.sh
+
+DISABLED_TESTS = \
+ test_regex101.sh \
+ test_remote.sh \
+ test_top_status \
+ test_line_buffer2 \
+ test_line_buffer.sh
+
+if HAVE_LIBCURL
+TESTS += \
+ test_curl.sh
+endif
+
+DISTCLEANFILES = \
+ *.cmd \
+ *.dat \
+ *.out \
+ *.err \
+ *.db \
+ *.dpt \
+ *.diff \
+ *.index \
+ *.tmp \
+ *.gz \
+ *.bz2 \
+ *.outbak \
+ *.errbak \
+ *.tmpbak \
+ *.xz \
+ exported-session.0.lnav \
+ hw.txt \
+ hw2.txt \
+ reload_test.0 \
+ truncfile.0 \
+ ln.dbg \
+ logfile_append.0 \
+ logfile_changed.0 \
+ logfile_rollover.1.live \
+ test.log \
+ logfile_stdin.log \
+ logfile_stdin.0.log \
+ logfile_syslog_test.0 \
+ logfile_syslog_test.2 \
+ logfile_syslog_fr_test.0 \
+ logfile_syslog_with_mixed_times_test.0 \
+ textfile_long_lines.0 \
+ not:a:remote:file \
+ rollover_in.0 \
+ test-logs.tgz \
+ test-logs-trunc.tgz \
+ test_pretty_in.* \
+ tmp \
+ unreadable.log \
+ UTF-8-test.md \
+ empty \
+ scripts-empty
+
+test_remote.sh.log: remote/ssh_host_dsa_key remote/ssh_host_rsa_key remote/id_rsa
+
+distclean-local:
+ $(RM_V)rm -rf remote remote-tmp not:a:remote:dir
+ $(RM_V)rm -rf sessions
+ $(RM_V)rm -rf tmp
+ $(RM_V)rm -rf rotmp
+ $(RM_V)rm -rf meta-sessions
+ $(RM_V)rm -rf nested
+ $(RM_V)rm -rf test-config
+ $(RM_V)rm -rf .lnav
+ $(RM_V)rm -rf regex101-home
+ $(RM_V)rm -rf events-home
+ $(RM_V)rm -rf support-dump
+ $(RM_V)rm -rf ../installer-test-home
+
+expected:
+ $(top_srcdir)/update_expected_output.sh $(srcdir) $(builddir)
+
+.PHONY: expected
diff --git a/test/UTF-8-test.txt b/test/UTF-8-test.txt
new file mode 100644
index 0000000..a5b5d50
--- /dev/null
+++ b/test/UTF-8-test.txt
Binary files differ
diff --git a/test/aftest.cc b/test/aftest.cc
new file mode 100644
index 0000000..5707c79
--- /dev/null
+++ b/test/aftest.cc
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base/auto_fd.hh"
+
+void
+foo(int* fd)
+{
+ *fd = 2;
+}
+
+int
+main(int argc, char* argv[])
+{
+ {
+ auto_fd fd(open("/dev/null", O_WRONLY));
+ auto_fd fd2;
+
+ printf("1 fd %d\n", fd.get());
+ fd = -1;
+ printf("2 fd %d\n", fd.get());
+
+ fd = open("/dev/null", O_WRONLY);
+ fd2 = fd;
+ printf("3 fd %d\n", fd.get());
+ printf("4 fd2 %d\n", fd2.get());
+
+ foo(fd2.out());
+ printf("5 fd2 %d\n", fd2.get());
+ }
+
+ printf("nfd %d\n", open("/dev/null", O_WRONLY));
+}
diff --git a/test/ansi-colors.0.in b/test/ansi-colors.0.in
new file mode 100644
index 0000000..8c2573d
--- /dev/null
+++ b/test/ansi-colors.0.in
@@ -0,0 +1,22 @@
+Basic ANSI colors (eight-color, or dim)
+
+ black  black  red  green  yellow  blue  magenta cyan  white 
+bold black  black  red  green  yellow  blue  magenta cyan  white 
+ red  black  red  green  yellow  blue  magenta cyan  white 
+bold red  black  red  green  yellow  blue  magenta cyan  white 
+ green  black  red  green  yellow  blue  magenta cyan  white 
+bold green  black  red  green  yellow  blue  magenta cyan  white 
+ yellow  black  red  green  yellow  blue  magenta cyan  white 
+bold yellow  black  red  green  yellow  blue  magenta cyan  white 
+ blue  black  red  green  yellow  blue  magenta cyan  white 
+bold blue  black  red  green  yellow  blue  magenta cyan  white 
+ magenta  black  red  green  yellow  blue  magenta cyan  white 
+bold magenta  black  red  green  yellow  blue  magenta cyan  white 
+ cyan  black  red  green  yellow  blue  magenta cyan  white 
+bold cyan  black  red  green  yellow  blue  magenta cyan  white 
+ white  black  red  green  yellow  blue  magenta cyan  white 
+bold white  black  red  green  yellow  blue  magenta cyan  white 
+
+Attributes: bold dark italic underline blink concealed
+  testing  testing  testing  testing  testing  testing 
+
diff --git a/test/bad-config-json/formats/invalid-json/format.json b/test/bad-config-json/formats/invalid-json/format.json
new file mode 100644
index 0000000..47369a5
--- /dev/null
+++ b/test/bad-config-json/formats/invalid-json/format.json
@@ -0,0 +1,5 @@
+{
+ "foobar_log": {
+ "abc"
+ }
+}
diff --git a/test/bad-config-json/formats/invalid-key/format.json b/test/bad-config-json/formats/invalid-key/format.json
new file mode 100644
index 0000000..11a3bdd
--- /dev/null
+++ b/test/bad-config-json/formats/invalid-key/format.json
@@ -0,0 +1,27 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "invalid_key_log": {
+ "level-pointer": "abc(",
+ "file-pattern": "def[ghi",
+ "json": true,
+ "regex": {
+ "foo": {
+ "pattern": "jkl"
+ }
+ },
+ "value": {
+ "test": {
+ "identifiers": true
+ },
+ "body": {
+ "kind": "string"
+ }
+ },
+ "line-format": [
+ {
+ "field": "non-existent"
+ }
+ ],
+ "timestamp-divisor": -1.2
+ }
+} \ No newline at end of file
diff --git a/test/bad-config/formats/invalid-json-format/format.json b/test/bad-config/formats/invalid-json-format/format.json
new file mode 100644
index 0000000..0e06a9e
--- /dev/null
+++ b/test/bad-config/formats/invalid-json-format/format.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "bad_json_log": {
+ "json": true,
+ "line-format": [
+ {
+ "field": ""
+ },
+ {
+ "field": "__timestamp__",
+ "timestamp-format": ""
+ }
+ ],
+ "value": {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/bad-config/formats/invalid-properties/format.json b/test/bad-config/formats/invalid-properties/format.json
new file mode 100644
index 0000000..a69a179
--- /dev/null
+++ b/test/bad-config/formats/invalid-properties/format.json
@@ -0,0 +1,45 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "invalid_props_log": {
+ "title": "invalid properties",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\d+): (?<pid>\\w+) (?<body>.*)$"
+ }
+ },
+ "timestamp-field": "ts",
+ "subsecond-field": "ts-sub",
+ "sample": [
+ {
+ "line": "1428634687123: 1234 abc"
+ }
+ ],
+ "value": {
+ "non-existent": {
+ "kind": "string"
+ }
+ },
+ "highlights": {
+ "hl1": {
+ "color": "not a color",
+ "background-color": "also not a color"
+ }
+ },
+ "tags": {
+ "badtag": {
+ "paths": []
+ },
+ "badtag2": {
+ "pattern": ""
+ },
+ "badtag3": {
+ "pattern": "invalid(abc"
+ }
+ },
+ "search-table": {
+ "bad_table_regex": {
+ "pattern": "abc(def"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/bad-config/formats/invalid-regex/format.json b/test/bad-config/formats/invalid-regex/format.json
new file mode 100644
index 0000000..33807a5
--- /dev/null
+++ b/test/bad-config/formats/invalid-regex/format.json
@@ -0,0 +1,29 @@
+{
+ "bad_regex_log": {
+ "title": "invalid regex test",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\d+: (?<body>.*)$"
+ },
+ "incomplete-match": {
+ "pattern": "^(?<timestamp>\\d+);"
+ }
+ },
+ "level": {
+ "error": "(foo"
+ },
+ "timestamp-format": [
+ "%i"
+ ],
+ "sample": [
+ {
+ "line": "1428634687123; foo"
+ }
+ ],
+ "highlights": {
+ "foobar": {
+ "pattern": "abc("
+ }
+ }
+ }
+}
diff --git a/test/bad-config/formats/invalid-sample/format.json b/test/bad-config/formats/invalid-sample/format.json
new file mode 100644
index 0000000..c3509bb
--- /dev/null
+++ b/test/bad-config/formats/invalid-sample/format.json
@@ -0,0 +1,45 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "bad_sample_log": {
+ "title": "invalid sample test",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\d+): (?<pid>\\w+) (?<body>.*)$"
+ },
+ "semi": {
+ "pattern": "^(?<timestamp>\\d+); (?<body>\\w+)$"
+ },
+ "bad-time": {
+ "pattern": "^(?<timestamp>\\w+): (?<body>\\w+)$"
+ },
+ "with-level": {
+ "pattern": "^(?<timestamp>\\d+)\\| (?<level>\\w+) (?<body>\\w+)$"
+ }
+ },
+ "timestamp-format": [
+ "%i"
+ ],
+ "value": {
+ "pid": {
+ "kind": "foo"
+ }
+ },
+ "level-field": "level",
+ "sample": [
+ {
+ "line": "abc: foo"
+ },
+ {
+ "line": "1428634687123| debug hello",
+ "level": "info"
+ },
+ {
+ "line": "1428634687123| debug hello\ngoodbye",
+ "level": "debug"
+ },
+ {
+ "line": "1428634687123; foo bar"
+ }
+ ]
+ }
+}
diff --git a/test/bad-config/formats/invalid-schema/format.json b/test/bad-config/formats/invalid-schema/format.json
new file mode 100644
index 0000000..b011164
--- /dev/null
+++ b/test/bad-config/formats/invalid-schema/format.json
@@ -0,0 +1,3 @@
+{
+ "$schema": "bad"
+} \ No newline at end of file
diff --git a/test/bad-config/formats/invalid-sql/init.sql b/test/bad-config/formats/invalid-sql/init.sql
new file mode 100644
index 0000000..341e675
--- /dev/null
+++ b/test/bad-config/formats/invalid-sql/init.sql
@@ -0,0 +1,5 @@
+
+SELECT * FROM sqlite_master;
+
+-- comment test
+CREATE TALE invalid (x y z);
diff --git a/test/bad-config/formats/invalid-sql/init2.sql b/test/bad-config/formats/invalid-sql/init2.sql
new file mode 100644
index 0000000..9810ea0
--- /dev/null
+++ b/test/bad-config/formats/invalid-sql/init2.sql
@@ -0,0 +1,2 @@
+SELECT regexp_match('abc(', '123')
+FROM sqlite_master;
diff --git a/test/bad-config/formats/no-regexes/format.json b/test/bad-config/formats/no-regexes/format.json
new file mode 100644
index 0000000..f20cde1
--- /dev/null
+++ b/test/bad-config/formats/no-regexes/format.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "no_regexes_log": {
+ "value": {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/bad-config/formats/no-samples/format.json b/test/bad-config/formats/no-samples/format.json
new file mode 100644
index 0000000..5c06294
--- /dev/null
+++ b/test/bad-config/formats/no-samples/format.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "no_sample_log": {
+ "title": "invalid sample test",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\d+): (?<body>.*)$"
+ },
+ "semi": {
+ "pattern": "^(?<timestamp>\\d+); (?<body>\\w+)$"
+ }
+ },
+ "timestamp-format": [
+ "%i"
+ ]
+ }
+}
diff --git a/test/bad-config2/formats/invalid-config/config.bad-schema.json b/test/bad-config2/formats/invalid-config/config.bad-schema.json
new file mode 100644
index 0000000..b011164
--- /dev/null
+++ b/test/bad-config2/formats/invalid-config/config.bad-schema.json
@@ -0,0 +1,3 @@
+{
+ "$schema": "bad"
+} \ No newline at end of file
diff --git a/test/bad-config2/formats/invalid-config/config.json b/test/bad-config2/formats/invalid-config/config.json
new file mode 100644
index 0000000..ba5cf2f
--- /dev/null
+++ b/test/bad-config2/formats/invalid-config/config.json
@@ -0,0 +1,5 @@
+{
+ "ui": {
+ "theme": "foo"
+ }
+} \ No newline at end of file
diff --git a/test/bad-config2/formats/invalid-config/config.malformed.json b/test/bad-config2/formats/invalid-config/config.malformed.json
new file mode 100644
index 0000000..0935e8b
--- /dev/null
+++ b/test/bad-config2/formats/invalid-config/config.malformed.json
@@ -0,0 +1,5 @@
+{
+ "ui": "theme",
+ "abc",
+ "def": ""
+} \ No newline at end of file
diff --git a/test/bad-config2/formats/invalid-config/config.truncated.json b/test/bad-config2/formats/invalid-config/config.truncated.json
new file mode 100644
index 0000000..fc01f0d
--- /dev/null
+++ b/test/bad-config2/formats/invalid-config/config.truncated.json
@@ -0,0 +1,2 @@
+{
+ "ui": "theme"
diff --git a/test/books.xml b/test/books.xml
new file mode 100644
index 0000000..19c4f73
--- /dev/null
+++ b/test/books.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<catalog>
+ <book id="bk101">
+ <author>Gambardella, Matthew</author>
+ <title>XML Developer's Guide</title>
+ <genre>Computer</genre>
+ <price>44.95</price>
+ <publish_date>2000-10-01</publish_date>
+ <description>An in-depth look at creating applications
+ with XML.</description>
+ </book>
+ <book id="bk102">
+ <author>Ralls, Kim</author>
+ <title>Midnight Rain</title>
+ <genre>Fantasy</genre>
+ <price>5.95</price>
+ <publish_date>2000-12-16</publish_date>
+ <description>A former architect battles corporate zombies,
+ an evil sorceress, and her own childhood to become queen
+ of the world.</description>
+ </book>
+ <book id="bk103">
+ <author>Corets, Eva</author>
+ <title>Maeve Ascendant</title>
+ <genre>Fantasy</genre>
+ <price>5.95</price>
+ <publish_date>2000-11-17</publish_date>
+ <description>After the collapse of a nanotechnology
+ society in England, the young survivors lay the
+ foundation for a new society.</description>
+ </book>
+ <book id="bk104">
+ <author>Corets, Eva</author>
+ <title>Oberon's Legacy</title>
+ <genre>Fantasy</genre>
+ <price>5.95</price>
+ <publish_date>2001-03-10</publish_date>
+ <description>In post-apocalypse England, the mysterious
+ agent known only as Oberon helps to create a new life
+ for the inhabitants of London. Sequel to Maeve
+ Ascendant.</description>
+ </book>
+ <book id="bk105">
+ <author>Corets, Eva</author>
+ <title>The Sundered Grail</title>
+ <genre>Fantasy</genre>
+ <price>5.95</price>
+ <publish_date>2001-09-10</publish_date>
+ <description>The two daughters of Maeve, half-sisters,
+ battle one another for control of England. Sequel to
+ Oberon's Legacy.</description>
+ </book>
+ <book id="bk106">
+ <author>Randall, Cynthia</author>
+ <title>Lover Birds</title>
+ <genre>Romance</genre>
+ <price>4.95</price>
+ <publish_date>2000-09-02</publish_date>
+ <description>When Carla meets Paul at an ornithology
+ conference, tempers fly as feathers get ruffled.</description>
+ </book>
+ <book id="bk107">
+ <author>Thurman, Paula</author>
+ <title>Splish Splash</title>
+ <genre>Romance</genre>
+ <price>4.95</price>
+ <publish_date>2000-11-02</publish_date>
+ <description>A deep sea diver finds true love twenty
+ thousand leagues beneath the sea.</description>
+ </book>
+ <book id="bk108">
+ <author>Knorr, Stefan</author>
+ <title>Creepy Crawlies</title>
+ <genre>Horror</genre>
+ <price>4.95</price>
+ <publish_date>2000-12-06</publish_date>
+ <description>An anthology of horror stories about roaches,
+ centipedes, scorpions and other insects.</description>
+ </book>
+ <book id="bk109">
+ <author>Kress, Peter</author>
+ <title>Paradox Lost</title>
+ <genre>Science Fiction</genre>
+ <price>6.95</price>
+ <publish_date>2000-11-02</publish_date>
+ <description>After an inadvertant trip through a Heisenberg
+ Uncertainty Device, James Salway discovers the problems
+ of being quantum.</description>
+ </book>
+ <book id="bk110">
+ <author>O'Brien, Tim</author>
+ <title>Microsoft .NET: The Programming Bible</title>
+ <genre>Computer</genre>
+ <price>36.95</price>
+ <publish_date>2000-12-09</publish_date>
+ <description>Microsoft's .NET initiative is explored in
+ detail in this deep programmer's reference.</description>
+ </book>
+ <book id="bk111">
+ <author>O'Brien, Tim</author>
+ <title>MSXML3: A Comprehensive Guide</title>
+ <genre>Computer</genre>
+ <price>36.95</price>
+ <publish_date>2000-12-01</publish_date>
+ <description>The Microsoft MSXML3 parser is covered in
+ detail, with attention to XML DOM interfaces, XSLT processing,
+ SAX and more.</description>
+ </book>
+ <book id="bk112">
+ <author>Galos, Mike</author>
+ <title>Visual Studio 7: A Comprehensive Guide</title>
+ <genre>Computer</genre>
+ <price>49.95</price>
+ <publish_date>2001-04-16</publish_date>
+ <description>Microsoft Visual Studio 7 is explored in depth,
+ looking at how Visual Basic, Visual C++, C#, and ASP+ are
+ integrated into a comprehensive development
+ environment.</description>
+ </book>
+</catalog>
diff --git a/test/datafile_ipaddr.0 b/test/datafile_ipaddr.0
new file mode 100644
index 0000000..e04c467
--- /dev/null
+++ b/test/datafile_ipaddr.0
@@ -0,0 +1,13 @@
+ IPv4=192.168.1.2 IPv6_LL=fe80::c62c:3ff:fe0e:e44a%en0 IPV6=fdca:a98b:b1bf:e05d:7c49:35b3:5949:ec6f
+ key 0:4 ^--^ IPv4
+ipv4 5:16 ^---------^ 192.168.1.2
+ val 5:16 ^---------^ 192.168.1.2
+pair 0:16 ^--------------^ IPv4=192.168.1.2
+ key 17:24 ^-----^ IPv6_LL
+ipv6 25:53 ^--------------------------^ fe80::c62c:3ff:fe0e:e44a%en0
+ val 25:53 ^--------------------------^ fe80::c62c:3ff:fe0e:e44a%en0
+pair 17:53 ^----------------------------------^ IPv6_LL=fe80::c62c:3ff:fe0e:e44a%en0
+ key 54:58 ^--^ IPV6
+ipv6 59:98 ^-------------------------------------^ fdca:a98b:b1bf:e05d:7c49:35b3:5949:ec6f
+ val 59:98 ^-------------------------------------^ fdca:a98b:b1bf:e05d:7c49:35b3:5949:ec6f
+pair 54:98 ^------------------------------------------^ IPV6=fdca:a98b:b1bf:e05d:7c49:35b3:5949:ec6f
diff --git a/test/datafile_simple.0 b/test/datafile_simple.0
new file mode 100644
index 0000000..459716a
--- /dev/null
+++ b/test/datafile_simple.0
@@ -0,0 +1,25 @@
+ a=1 b=2 c=3,4
+ key 0:1 ^ a
+ num 2:3 ^ 1
+ val 2:3 ^ 1
+pair 0:3 ^-^ a=1
+ key 4:5 ^ b
+ num 6:7 ^ 2
+ val 6:7 ^ 2
+pair 4:7 ^-^ b=2
+ key 8:9 ^ c
+ num 10:11 ^ 3
+ val 10:11 ^ 3
+pair 8:11 ^-^ c=3
+ key 12:12 ^
+ num 12:13 ^ 4
+ val 12:13 ^ 4
+pair 12:13 ^ 4
+msg :a=1 b=2 c=3,4
+format :a=# b=# c=#,#
+{
+ "a": 1,
+ "b": 2,
+ "c": 3,
+ "col_0": 4
+}
diff --git a/test/datafile_simple.1 b/test/datafile_simple.1
new file mode 100644
index 0000000..48bb61a
--- /dev/null
+++ b/test/datafile_simple.1
@@ -0,0 +1,13 @@
+ current speed: 38 mph
+ key 0:0
+ key 0:13 ^-----------^ current speed
+pair 0:13 ^-----------^ current speed
+ key 15:15 ^
+ num 15:17 ^^ 38
+pair 15:17 ^^ 38
+msg :current speed: 38 mph
+format :#: # mph
+{
+ "col_0": "current speed",
+ "col_1": 38
+}
diff --git a/test/datafile_simple.10 b/test/datafile_simple.10
new file mode 100644
index 0000000..928f183
--- /dev/null
+++ b/test/datafile_simple.10
@@ -0,0 +1,9 @@
+ quoted string u'pm/runtime'
+ key 16:16 ^
+quot 16:26 ^--------^ pm/runtime
+pair 16:26 ^--------^ pm/runtime
+msg :quoted string u'pm/runtime'
+format :quoted string #
+{
+ "col_0": "pm/runtime"
+}
diff --git a/test/datafile_simple.11 b/test/datafile_simple.11
new file mode 100644
index 0000000..f12969f
--- /dev/null
+++ b/test/datafile_simple.11
@@ -0,0 +1,13 @@
+ version numbers 0.6.16 1.2-a1
+ key 17:17 ^
+vers 17:23 ^----^ 0.6.16
+pair 17:23 ^----^ 0.6.16
+ key 25:25 ^
+vers 25:31 ^----^ 1.2-a1
+pair 25:31 ^----^ 1.2-a1
+msg :version numbers 0.6.16 1.2-a1
+format :version numbers # #
+{
+ "col_0": "0.6.16",
+ "col_1": "1.2-a1"
+}
diff --git a/test/datafile_simple.12 b/test/datafile_simple.12
new file mode 100644
index 0000000..e19007e
--- /dev/null
+++ b/test/datafile_simple.12
@@ -0,0 +1,10 @@
+ kickoff_duration=4.41074371338e-05
+ key 0:16 ^--------------^ kickoff_duration
+ num 17:34 ^---------------^ 4.41074371338e-05
+ val 17:34 ^---------------^ 4.41074371338e-05
+pair 0:34 ^--------------------------------^ kickoff_duration=4.41074371338e-05
+msg :kickoff_duration=4.41074371338e-05
+format :kickoff_duration=#
+{
+ "kickoff_duration": 4.41074371338e-05
+}
diff --git a/test/datafile_simple.13 b/test/datafile_simple.13
new file mode 100644
index 0000000..8021010
--- /dev/null
+++ b/test/datafile_simple.13
@@ -0,0 +1,10 @@
+ kickoff_duration=4.41074371338E-05
+ key 0:16 ^--------------^ kickoff_duration
+ num 17:34 ^---------------^ 4.41074371338E-05
+ val 17:34 ^---------------^ 4.41074371338E-05
+pair 0:34 ^--------------------------------^ kickoff_duration=4.41074371338E-05
+msg :kickoff_duration=4.41074371338E-05
+format :kickoff_duration=#
+{
+ "kickoff_duration": 4.41074371338E-05
+}
diff --git a/test/datafile_simple.14 b/test/datafile_simple.14
new file mode 100644
index 0000000..4c548b9
--- /dev/null
+++ b/test/datafile_simple.14
@@ -0,0 +1,57 @@
+ FSChange(Direction.DOWNLOAD, Action.CREATE, name=Fanime 2015, route=[CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names)])
+ key 0:0
+ sym 0:8 ^------^ FSChange
+pair 0:8 ^------^ FSChange
+ key 9:9 ^
+ key 9:9 ^
+ sym 9:27 ^----------------^ Direction.DOWNLOAD
+ val 9:27 ^----------------^ Direction.DOWNLOAD
+pair 9:27 ^----------------^ Direction.DOWNLOAD
+ key 29:29 ^
+ sym 29:42 ^-----------^ Action.CREATE
+ val 29:42 ^-----------^ Action.CREATE
+pair 29:42 ^-----------^ Action.CREATE
+ key 44:48 ^--^ name
+word 49:55 ^----^ Fanime
+wspc 55:56 ^
+ num 56:60 ^--^ 2015
+ val 49:60 ^---------^ Fanime 2015
+pair 44:60 ^--------------^ name=Fanime 2015
+ key 62:67 ^---^ route
+ key 69:79 ^--------^ CloudEntry
+ key 80:86 ^----^ doc_id
+ sym 87:131 ^------------------------------------------^ 1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg
+ val 87:131 ^------------------------------------------^ 1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg
+pair 80:131 ^-------------------------------------------------^ doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg
+ key 132:140 ^------^ filename
+word 141:145 ^--^ Baby
+wspc 145:146 ^
+word 146:151 ^---^ Names
+ val 141:151 ^--------^ Baby Names
+pair 132:151 ^-----------------^ filename=Baby Names
+ grp 80:151 ^---------------------------------------------------------------------^ doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+ val 80:151 ^---------------------------------------------------------------------^ doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+pair 69:151 ^--------------------------------------------------------------------------------^ CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+ grp 69:151 ^--------------------------------------------------------------------------------^ CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+ val 69:151 ^--------------------------------------------------------------------------------^ CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+pair 62:151 ^---------------------------------------------------------------------------------------^ route=[CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+ grp 9:151 ^--------------------------------------------------------------------------------------------------------------------------------------------^ Direction.DOWNLOAD, Action.CREATE, name=Fanime 2015, route=[CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+pair 9:151 ^--------------------------------------------------------------------------------------------------------------------------------------------^ Direction.DOWNLOAD, Action.CREATE, name=Fanime 2015, route=[CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names
+msg :FSChange(Direction.DOWNLOAD, Action.CREATE, name=Fanime 2015, route=[CloudEntry(doc_id=1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg,filename=Baby Names)])
+format :#(#)])
+{
+ "col_0": "FSChange",
+ "col_1": {
+ "col_0": "Direction.DOWNLOAD",
+ "col_1": "Action.CREATE",
+ "name": "Fanime 2015",
+ "route": [
+ {
+ "CloudEntry": {
+ "doc_id": "1g5Yho6JmysVGRO-Xmfurra_cQRFb0nTIfZRhGompweg",
+ "filename": "Baby Names"
+ }
+ }
+ ]
+ }
+}
diff --git a/test/datafile_simple.15 b/test/datafile_simple.15
new file mode 100644
index 0000000..f0e053d
--- /dev/null
+++ b/test/datafile_simple.15
@@ -0,0 +1,75 @@
+ Worker successfully completed [ImmutableChange(Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False)]
+ key 31:31 ^
+ key 31:46 ^-------------^ ImmutableChange
+ key 47:47 ^
+ sym 47:63 ^--------------^ Direction.UPLOAD
+ val 47:63 ^--------------^ Direction.UPLOAD
+pair 47:63 ^--------------^ Direction.UPLOAD
+ key 65:65 ^
+ sym 65:78 ^-----------^ Action.CREATE
+ val 65:78 ^-----------^ Action.CREATE
+pair 65:78 ^-----------^ Action.CREATE
+ key 80:83 ^-^ ino
+ sym 84:91 ^-----^ LocalID
+ key 92:97 ^---^ inode
+ num 98:105 ^-----^ 5567236
+ val 98:105 ^-----^ 5567236
+pair 92:105 ^-----------^ inode=5567236
+ grp 92:105 ^-----------^ inode=5567236
+pair 84:105 ^-------------------^ LocalID(inode=5567236
+ val 84:105 ^-------------------^ LocalID(inode=5567236
+pair 80:105 ^-----------------------^ ino=LocalID(inode=5567236
+ key 108:112 ^--^ path
+quot 115:140 ^-----------------------^ /Users/stack/Google Drive
+ val 115:140 ^-----------------------^ /Users/stack/Google Drive
+pair 108:140 ^------------------------------^ path=u'/Users/stack/Google Drive
+ key 143:147 ^--^ name
+quot 150:167 ^---------------^ pyjsonpath1.patch
+ val 150:167 ^---------------^ pyjsonpath1.patch
+pair 143:167 ^----------------------^ name=u'pyjsonpath1.patch
+ key 170:180 ^--------^ parent_ino
+ sym 181:188 ^-----^ LocalID
+ key 189:194 ^---^ inode
+ num 195:203 ^------^ 46166734
+ val 195:203 ^------^ 46166734
+pair 189:203 ^------------^ inode=46166734
+ grp 189:203 ^------------^ inode=46166734
+pair 181:203 ^--------------------^ LocalID(inode=46166734
+ val 181:203 ^--------------------^ LocalID(inode=46166734
+pair 170:203 ^-------------------------------^ parent_ino=LocalID(inode=46166734
+ key 206:215 ^-------^ is_folder
+cnst 216:221 ^---^ False
+ val 216:221 ^---^ False
+pair 206:221 ^-------------^ is_folder=False
+ grp 47:221 ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False
+ val 47:221 ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False
+pair 31:221 ^--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ ImmutableChange(Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False
+ grp 31:221 ^--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ ImmutableChange(Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False
+pair 31:221 ^--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ ImmutableChange(Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False
+msg :Worker successfully completed [ImmutableChange(Direction.UPLOAD, Action.CREATE, ino=LocalID(inode=5567236), path=u'/Users/stack/Google Drive', name=u'pyjsonpath1.patch', parent_ino=LocalID(inode=46166734), is_folder=False)]
+format :Worker successfully completed [#)]
+[
+ {
+ "ImmutableChange": {
+ "col_0": "Direction.UPLOAD",
+ "col_1": "Action.CREATE",
+ "ino": {
+ "LocalID": [
+ {
+ "inode": 5567236
+ }
+ ]
+ },
+ "path": "/Users/stack/Google Drive",
+ "name": "pyjsonpath1.patch",
+ "parent_ino": {
+ "LocalID": [
+ {
+ "inode": 46166734
+ }
+ ]
+ },
+ "is_folder": false
+ }
+ }
+]
diff --git a/test/datafile_simple.16 b/test/datafile_simple.16
new file mode 100644
index 0000000..f549fc7
--- /dev/null
+++ b/test/datafile_simple.16
@@ -0,0 +1,9 @@
+ test: c'est la vie charlie's
+ key 0:0
+ key 0:4 ^--^ test
+pair 0:4 ^--^ test
+msg :test: c'est la vie charlie's
+format :#: c'est la vie charlie's
+{
+ "col_0": "test"
+}
diff --git a/test/datafile_simple.17 b/test/datafile_simple.17
new file mode 100644
index 0000000..132eda6
--- /dev/null
+++ b/test/datafile_simple.17
@@ -0,0 +1,22 @@
+ foo=[]; bar=['a', 'b']
+ key 0:3 ^-^ foo
+ grp 5:5 ^
+ val 5:5 ^
+pair 0:5 ^---^ foo=[
+ key 8:11 ^-^ bar
+quot 14:15 ^ a
+ val 14:15 ^ a
+quot 19:20 ^ b
+ val 19:20 ^ b
+ grp 14:20 ^----^ a', 'b
+ val 14:20 ^----^ a', 'b
+pair 8:20 ^----------^ bar=['a', 'b
+msg :foo=[]; bar=['a', 'b']
+format :foo=[#]; bar=[#]
+{
+ "foo": null,
+ "bar": [
+ "a",
+ "b"
+ ]
+}
diff --git a/test/datafile_simple.18 b/test/datafile_simple.18
new file mode 100644
index 0000000..55f125b
--- /dev/null
+++ b/test/datafile_simple.18
@@ -0,0 +1,23 @@
+ list [foo(bar=1)]
+ key 6:6 ^
+ key 6:9 ^-^ foo
+ key 10:13 ^-^ bar
+ num 14:15 ^ 1
+ val 14:15 ^ 1
+pair 10:15 ^---^ bar=1
+ grp 10:15 ^---^ bar=1
+ val 10:15 ^---^ bar=1
+pair 6:15 ^-------^ foo(bar=1
+ grp 6:15 ^-------^ foo(bar=1
+pair 6:15 ^-------^ foo(bar=1
+msg :list [foo(bar=1)]
+format :list [#)]
+[
+ {
+ "foo": [
+ {
+ "bar": 1
+ }
+ ]
+ }
+]
diff --git a/test/datafile_simple.19 b/test/datafile_simple.19
new file mode 100644
index 0000000..ce58fc9
--- /dev/null
+++ b/test/datafile_simple.19
@@ -0,0 +1,53 @@
+ list [foo(bar=1), foo(bar=2), foo(bar=3)]
+ key 6:6 ^
+ key 6:9 ^-^ foo
+ key 10:13 ^-^ bar
+ num 14:15 ^ 1
+ val 14:15 ^ 1
+pair 10:15 ^---^ bar=1
+ grp 10:15 ^---^ bar=1
+ val 10:15 ^---^ bar=1
+pair 6:15 ^-------^ foo(bar=1
+ key 18:21 ^-^ foo
+ key 22:25 ^-^ bar
+ num 26:27 ^ 2
+ val 26:27 ^ 2
+pair 22:27 ^---^ bar=2
+ grp 22:27 ^---^ bar=2
+ val 22:27 ^---^ bar=2
+pair 18:27 ^-------^ foo(bar=2
+ key 30:33 ^-^ foo
+ key 34:37 ^-^ bar
+ num 38:39 ^ 3
+ val 38:39 ^ 3
+pair 34:39 ^---^ bar=3
+ grp 34:39 ^---^ bar=3
+ val 34:39 ^---^ bar=3
+pair 30:39 ^-------^ foo(bar=3
+ grp 6:39 ^-------------------------------^ foo(bar=1), foo(bar=2), foo(bar=3
+pair 6:39 ^-------------------------------^ foo(bar=1), foo(bar=2), foo(bar=3
+msg :list [foo(bar=1), foo(bar=2), foo(bar=3)]
+format :list [#)]
+[
+ {
+ "foo": [
+ {
+ "bar": 1
+ }
+ ]
+ },
+ {
+ "foo": [
+ {
+ "bar": 2
+ }
+ ]
+ },
+ {
+ "foo": [
+ {
+ "bar": 3
+ }
+ ]
+ }
+]
diff --git a/test/datafile_simple.2 b/test/datafile_simple.2
new file mode 100644
index 0000000..c141544
--- /dev/null
+++ b/test/datafile_simple.2
@@ -0,0 +1,40 @@
+ 1,2,3,4,five,six,7
+ key 0:0
+ num 0:1 ^ 1
+ val 0:1 ^ 1
+pair 0:1 ^ 1
+ key 2:2 ^
+ num 2:3 ^ 2
+ val 2:3 ^ 2
+pair 2:3 ^ 2
+ key 4:4 ^
+ num 4:5 ^ 3
+ val 4:5 ^ 3
+pair 4:5 ^ 3
+ key 6:6 ^
+ num 6:7 ^ 4
+ val 6:7 ^ 4
+pair 6:7 ^ 4
+ key 8:8 ^
+word 8:12 ^--^ five
+ val 8:12 ^--^ five
+pair 8:12 ^--^ five
+ key 13:13 ^
+word 13:16 ^-^ six
+ val 13:16 ^-^ six
+pair 13:16 ^-^ six
+ key 17:17 ^
+ num 17:18 ^ 7
+ val 17:18 ^ 7
+pair 17:18 ^ 7
+msg :1,2,3,4,five,six,7
+format :#,#,#,#,#,#,#
+{
+ "col_0": 1,
+ "col_1": 2,
+ "col_2": 3,
+ "col_3": 4,
+ "col_4": "five",
+ "col_5": "six",
+ "col_6": 7
+}
diff --git a/test/datafile_simple.20 b/test/datafile_simple.20
new file mode 100644
index 0000000..ea81659
--- /dev/null
+++ b/test/datafile_simple.20
@@ -0,0 +1,17 @@
+ list ["abc", "def", "ghi"]
+ key 7:7 ^
+quot 7:10 ^-^ abc
+ val 7:10 ^-^ abc
+quot 14:17 ^-^ def
+ val 14:17 ^-^ def
+quot 21:24 ^-^ ghi
+ val 21:24 ^-^ ghi
+ grp 7:24 ^---------------^ abc", "def", "ghi
+pair 7:24 ^---------------^ abc", "def", "ghi
+msg :list ["abc", "def", "ghi"]
+format :list [#]
+[
+ "abc",
+ "def",
+ "ghi"
+]
diff --git a/test/datafile_simple.21 b/test/datafile_simple.21
new file mode 100644
index 0000000..e570241
--- /dev/null
+++ b/test/datafile_simple.21
@@ -0,0 +1,26 @@
+ {"correctProperty":"test", "incorrectProperty": "test\"", "nextProperty":"test"}
+ key 2:2 ^
+quot 2:17 ^-------------^ correctProperty
+ val 2:17 ^-------------^ correctProperty
+quot 20:24 ^--^ test
+ val 20:24 ^--^ test
+quot 28:45 ^---------------^ incorrectProperty
+ val 28:45 ^---------------^ incorrectProperty
+quot 49:55 ^----^ test\"
+ val 49:55 ^----^ test\"
+quot 59:71 ^----------^ nextProperty
+ val 59:71 ^----------^ nextProperty
+quot 74:78 ^--^ test
+ val 74:78 ^--^ test
+ grp 2:78 ^--------------------------------------------------------------------------^ correctProperty":"test", "incorrectProperty": "test\"", "nextProperty":"test
+pair 2:78 ^--------------------------------------------------------------------------^ correctProperty":"test", "incorrectProperty": "test\"", "nextProperty":"test
+msg :{"correctProperty":"test", "incorrectProperty": "test\"", "nextProperty":"test"}
+format :{#}
+[
+ "correctProperty",
+ "test",
+ "incorrectProperty",
+ "test\\\"",
+ "nextProperty",
+ "test"
+]
diff --git a/test/datafile_simple.22 b/test/datafile_simple.22
new file mode 100644
index 0000000..501fe36
--- /dev/null
+++ b/test/datafile_simple.22
@@ -0,0 +1,9 @@
+ C:\Program Files (x86)\Google\Chrome\Application\new_chrome.exe
+ key 0:0
+path 0:63 ^-------------------------------------------------------------^ C:\Program Files (x86)\Google\Chrome\Application\new_chrome.exe
+pair 0:63 ^-------------------------------------------------------------^ C:\Program Files (x86)\Google\Chrome\Application\new_chrome.exe
+msg :C:\Program Files (x86)\Google\Chrome\Application\new_chrome.exe
+format :#
+{
+ "col_0": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\new_chrome.exe"
+}
diff --git a/test/datafile_simple.23 b/test/datafile_simple.23
new file mode 100644
index 0000000..d649941
--- /dev/null
+++ b/test/datafile_simple.23
@@ -0,0 +1,88 @@
+ 2022-06-02T12:26:22.072Z info vpxd[47413] [Originator@6876 sub=vpxLro opID=21fa61e9-3e] [VpxLRO] -- BEGIN lro-954041 -- AuthorizationManager -- vim.AuthorizationManager.hasUserPrivilegeOnEntities -- 52768da7-4006-3d4a-4917-ee027373630f(522e0475-8901-e8b8-1eb8-07ec729ac50c)
+ key 23:23 ^
+ sym 23:24 ^ Z
+pair 23:24 ^ Z
+ key 30:30 ^
+ sym 30:34 ^--^ vpxd
+pair 30:34 ^--^ vpxd
+ key 35:35 ^
+ num 35:40 ^---^ 47413
+ val 35:40 ^---^ 47413
+ grp 35:40 ^---^ 47413
+pair 35:40 ^---^ 47413
+ key 43:43 ^
+ key 43:62 ^-----------------^ Originator@6876 sub
+ sym 63:69 ^----^ vpxLro
+ val 63:69 ^----^ vpxLro
+pair 43:69 ^------------------------^ Originator@6876 sub=vpxLro
+ key 70:74 ^--^ opID
+ sym 75:86 ^---------^ 21fa61e9-3e
+ val 75:86 ^---------^ 21fa61e9-3e
+pair 70:86 ^--------------^ opID=21fa61e9-3e
+ grp 43:86 ^-----------------------------------------^ Originator@6876 sub=vpxLro opID=21fa61e9-3e
+pair 43:86 ^-----------------------------------------^ Originator@6876 sub=vpxLro opID=21fa61e9-3e
+ key 89:89 ^
+ sym 89:95 ^----^ VpxLRO
+ val 89:95 ^----^ VpxLRO
+ grp 89:95 ^----^ VpxLRO
+pair 89:95 ^----^ VpxLRO
+ key 97:97 ^
+ sym 97:99 ^^ --
+pair 97:99 ^^ --
+ key 100:100 ^
+ sym 100:105 ^---^ BEGIN
+pair 100:105 ^---^ BEGIN
+ key 106:106 ^
+ sym 106:116 ^--------^ lro-954041
+pair 106:116 ^--------^ lro-954041
+ key 117:117 ^
+ sym 117:119 ^^ --
+pair 117:119 ^^ --
+ key 120:120 ^
+ sym 120:140 ^------------------^ AuthorizationManager
+pair 120:140 ^------------------^ AuthorizationManager
+ key 141:141 ^
+ sym 141:143 ^^ --
+pair 141:143 ^^ --
+ key 144:144 ^
+ sym 144:195 ^-------------------------------------------------^ vim.AuthorizationManager.hasUserPrivilegeOnEntities
+pair 144:195 ^-------------------------------------------------^ vim.AuthorizationManager.hasUserPrivilegeOnEntities
+ key 196:196 ^
+ sym 196:198 ^^ --
+pair 196:198 ^^ --
+ key 199:199 ^
+uuid 199:235 ^----------------------------------^ 52768da7-4006-3d4a-4917-ee027373630f
+pair 199:235 ^----------------------------------^ 52768da7-4006-3d4a-4917-ee027373630f
+ key 236:236 ^
+uuid 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
+ val 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
+ grp 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
+pair 236:272 ^----------------------------------^ 522e0475-8901-e8b8-1eb8-07ec729ac50c
+msg :2022-06-02T12:26:22.072Z info vpxd[47413] [Originator@6876 sub=vpxLro opID=21fa61e9-3e] [VpxLRO] -- BEGIN lro-954041 -- AuthorizationManager -- vim.AuthorizationManager.hasUserPrivilegeOnEntities -- 52768da7-4006-3d4a-4917-ee027373630f(522e0475-8901-e8b8-1eb8-07ec729ac50c)
+format :2022-06-02T12:26:22.072# info #[#] [#] [#] # # # # # # # # #(#)
+{
+ "col_0": "Z",
+ "col_1": "vpxd",
+ "col_2": [
+ 47413
+ ],
+ "col_3": {
+ "Originator@6876 sub": "vpxLro",
+ "opID": "21fa61e9-3e"
+ },
+ "col_4": [
+ "VpxLRO"
+ ],
+ "col_5": "--",
+ "col_6": "BEGIN",
+ "col_7": "lro-954041",
+ "col_8": "--",
+ "col_9": "AuthorizationManager",
+ "col_10": "--",
+ "col_11": "vim.AuthorizationManager.hasUserPrivilegeOnEntities",
+ "col_12": "--",
+ "col_13": "52768da7-4006-3d4a-4917-ee027373630f",
+ "col_14": [
+ "522e0475-8901-e8b8-1eb8-07ec729ac50c"
+ ]
+}
diff --git a/test/datafile_simple.3 b/test/datafile_simple.3
new file mode 100644
index 0000000..6312683
--- /dev/null
+++ b/test/datafile_simple.3
@@ -0,0 +1,25 @@
+ 1 2 3 4 five six 7
+ key 0:0
+ num 0:1 ^ 1
+pair 0:1 ^ 1
+ key 2:2 ^
+ num 2:3 ^ 2
+pair 2:3 ^ 2
+ key 4:4 ^
+ num 4:5 ^ 3
+pair 4:5 ^ 3
+ key 6:6 ^
+ num 6:7 ^ 4
+pair 6:7 ^ 4
+ key 17:17 ^
+ num 17:18 ^ 7
+pair 17:18 ^ 7
+msg :1 2 3 4 five six 7
+format :# # # # five six #
+{
+ "col_0": 1,
+ "col_1": 2,
+ "col_2": 3,
+ "col_3": 4,
+ "col_4": 7
+}
diff --git a/test/datafile_simple.4 b/test/datafile_simple.4
new file mode 100644
index 0000000..339aa41
--- /dev/null
+++ b/test/datafile_simple.4
@@ -0,0 +1,10 @@
+ the-value: "Hello, World!"
+ key 0:9 ^-------^ the-value
+quot 12:25 ^-----------^ Hello, World!
+ val 12:25 ^-----------^ Hello, World!
+pair 0:25 ^-----------------------^ the-value: "Hello, World!
+msg :the-value: "Hello, World!"
+format :the-value: #
+{
+ "the-value": "Hello, World!"
+}
diff --git a/test/datafile_simple.5 b/test/datafile_simple.5
new file mode 100644
index 0000000..606a498
--- /dev/null
+++ b/test/datafile_simple.5
@@ -0,0 +1,10 @@
+ this is a url: http://www.example.com/foo-bar
+ key 0:13 ^-----------^ this is a url
+ url 15:45 ^----------------------------^ http://www.example.com/foo-bar
+ val 15:45 ^----------------------------^ http://www.example.com/foo-bar
+pair 0:45 ^-------------------------------------------^ this is a url: http://www.example.com/foo-bar
+msg :this is a url: http://www.example.com/foo-bar
+format :this is a url: #
+{
+ "this is a url": "http://www.example.com/foo-bar"
+}
diff --git a/test/datafile_simple.6 b/test/datafile_simple.6
new file mode 100644
index 0000000..15cfab1
--- /dev/null
+++ b/test/datafile_simple.6
@@ -0,0 +1,25 @@
+ qualified:name: foo=1 bar=2
+ key 0:0
+word 0:9 ^-------^ qualified
+ val 0:9 ^-------^ qualified
+pair 0:9 ^-------^ qualified
+ key 10:10 ^
+word 10:14 ^--^ name
+ val 10:14 ^--^ name
+pair 10:14 ^--^ name
+ key 16:19 ^-^ foo
+ num 20:21 ^ 1
+ val 20:21 ^ 1
+pair 16:21 ^---^ foo=1
+ key 22:25 ^-^ bar
+ num 26:27 ^ 2
+ val 26:27 ^ 2
+pair 22:27 ^---^ bar=2
+msg :qualified:name: foo=1 bar=2
+format :#:#: foo=# bar=#
+{
+ "col_0": "qualified",
+ "col_1": "name",
+ "foo": 1,
+ "bar": 2
+}
diff --git a/test/datafile_simple.7 b/test/datafile_simple.7
new file mode 100644
index 0000000..3c0810f
--- /dev/null
+++ b/test/datafile_simple.7
@@ -0,0 +1,18 @@
+ func(arg1="a", arg2="b")
+ key 5:5 ^
+ key 5:9 ^--^ arg1
+quot 11:12 ^ a
+ val 11:12 ^ a
+pair 5:12 ^-----^ arg1="a
+ key 15:19 ^--^ arg2
+quot 21:22 ^ b
+ val 21:22 ^ b
+pair 15:22 ^-----^ arg2="b
+ grp 5:22 ^---------------^ arg1="a", arg2="b
+pair 5:22 ^---------------^ arg1="a", arg2="b
+msg :func(arg1="a", arg2="b")
+format :func(#)
+{
+ "arg1": "a",
+ "arg2": "b"
+}
diff --git a/test/datafile_simple.8 b/test/datafile_simple.8
new file mode 100644
index 0000000..c6363c3
--- /dev/null
+++ b/test/datafile_simple.8
@@ -0,0 +1,44 @@
+ Succeeded authorizing right 'system.privilege.taskport.debug' by client '/usr/libexec/taskgated' [76339] for authorization created by '/usr/libexec/taskgated' [77395] (100003,1)
+ key 29:29 ^
+quot 29:60 ^-----------------------------^ system.privilege.taskport.debug
+pair 29:60 ^-----------------------------^ system.privilege.taskport.debug
+ key 73:73 ^
+quot 73:95 ^--------------------^ /usr/libexec/taskgated
+pair 73:95 ^--------------------^ /usr/libexec/taskgated
+ key 98:98 ^
+ num 98:103 ^---^ 76339
+ val 98:103 ^---^ 76339
+ grp 98:103 ^---^ 76339
+pair 98:103 ^---^ 76339
+ key 135:135 ^
+quot 135:157 ^--------------------^ /usr/libexec/taskgated
+pair 135:157 ^--------------------^ /usr/libexec/taskgated
+ key 160:160 ^
+ num 160:165 ^---^ 77395
+ val 160:165 ^---^ 77395
+ grp 160:165 ^---^ 77395
+pair 160:165 ^---^ 77395
+ key 168:168 ^
+ num 168:174 ^----^ 100003
+ val 168:174 ^----^ 100003
+ num 175:176 ^ 1
+ val 175:176 ^ 1
+ grp 168:176 ^------^ 100003,1
+pair 168:176 ^------^ 100003,1
+msg :Succeeded authorizing right 'system.privilege.taskport.debug' by client '/usr/libexec/taskgated' [76339] for authorization created by '/usr/libexec/taskgated' [77395] (100003,1)
+format :Succeeded authorizing right # by client # [#] for authorization created by # [#] (#)
+{
+ "col_0": "system.privilege.taskport.debug",
+ "col_1": "/usr/libexec/taskgated",
+ "col_2": [
+ 76339
+ ],
+ "col_3": "/usr/libexec/taskgated",
+ "col_4": [
+ 77395
+ ],
+ "col_5": [
+ 100003,
+ 1
+ ]
+}
diff --git a/test/datafile_simple.9 b/test/datafile_simple.9
new file mode 100644
index 0000000..85513b9
--- /dev/null
+++ b/test/datafile_simple.9
@@ -0,0 +1,17 @@
+ 12:01 12:01:22 12:01:22.123
+ key 0:0
+time 0:5 ^---^ 12:01
+pair 0:5 ^---^ 12:01
+ key 7:7 ^
+time 7:15 ^------^ 12:01:22
+pair 7:15 ^------^ 12:01:22
+ key 17:17 ^
+time 17:29 ^----------^ 12:01:22.123
+pair 17:29 ^----------^ 12:01:22.123
+msg :12:01 12:01:22 12:01:22.123
+format :# # #
+{
+ "col_0": "12:01",
+ "col_1": "12:01:22",
+ "col_2": "12:01:22.123"
+}
diff --git a/test/datafile_syslog.0 b/test/datafile_syslog.0
new file mode 100644
index 0000000..d37c5cc
--- /dev/null
+++ b/test/datafile_syslog.0
@@ -0,0 +1,23 @@
+ timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
+ key 0:0
+word 0:8 ^------^ timstack
+ val 0:8 ^------^ timstack
+pair 0:8 ^------^ timstack
+ key 11:14 ^-^ TTY
+ sym 15:20 ^---^ pts/6
+ val 15:20 ^---^ pts/6
+pair 11:20 ^-------^ TTY=pts/6
+ key 23:26 ^-^ PWD
+path 27:60 ^-------------------------------^ /auto/wstimstack/rpms/lbuild/test
+ val 27:60 ^-------------------------------^ /auto/wstimstack/rpms/lbuild/test
+pair 23:60 ^-----------------------------------^ PWD=/auto/wstimstack/rpms/lbuild/test
+ key 63:67 ^--^ USER
+word 68:72 ^--^ root
+ val 68:72 ^--^ root
+pair 63:72 ^-------^ USER=root
+ key 75:82 ^-----^ COMMAND
+path 83:96 ^-----------^ /usr/bin/tail
+wspc 96:97 ^
+path 97:114 ^---------------^ /var/log/messages
+ val 83:114 ^-----------------------------^ /usr/bin/tail /var/log/messages
+pair 75:114 ^-------------------------------------^ COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/datafile_syslog.1 b/test/datafile_syslog.1
new file mode 100644
index 0000000..928f11a
--- /dev/null
+++ b/test/datafile_syslog.1
@@ -0,0 +1,21 @@
+ INSERT-HANG-DETECTED: Tx time:3.093364, # of Inserts: 89, # of bytes written: 465365, Did shrink: NO
+ key 0:20 ^------------------^ INSERT-HANG-DETECTED
+word 22:24 ^^ Tx
+ val 22:24 ^^ Tx
+pair 0:24 ^----------------------^ INSERT-HANG-DETECTED: Tx
+ key 25:29 ^--^ time
+ num 30:38 ^------^ 3.093364
+ val 30:38 ^------^ 3.093364
+pair 25:38 ^-----------^ time:3.093364
+ key 40:52 ^----------^ # of Inserts
+ num 54:56 ^^ 89
+ val 54:56 ^^ 89
+pair 40:56 ^--------------^ # of Inserts: 89
+ key 58:76 ^----------------^ # of bytes written
+ num 78:84 ^----^ 465365
+ val 78:84 ^----^ 465365
+pair 58:84 ^------------------------^ # of bytes written: 465365
+ key 86:96 ^--------^ Did shrink
+ sym 98:100 ^^ NO
+ val 98:100 ^^ NO
+pair 86:100 ^------------^ Did shrink: NO
diff --git a/test/datafile_xml.0 b/test/datafile_xml.0
new file mode 100644
index 0000000..9b5a102
--- /dev/null
+++ b/test/datafile_xml.0
@@ -0,0 +1,26 @@
+ <ns1:foo> <elem attr1=xyz attr2="123"> </elem> <closed />
+ key 0:0
+xmlo 0:9 ^-------^ <ns1:foo>
+pair 0:9 ^-------^ <ns1:foo>
+ key 12:12 ^
+xmlo 12:40 ^--------------------------^ <elem attr1=xyz attr2="123">
+pair 12:40 ^--------------------------^ <elem attr1=xyz attr2="123">
+ key 42:42 ^
+xmlc 42:49 ^-----^ </elem>
+pair 42:49 ^-----^ </elem>
+ key 51:51 ^
+xmlt 51:61 ^--------^ <closed />
+pair 51:61 ^--------^ <closed />
+msg :<ns1:foo> <elem attr1=xyz attr2="123"> </elem> <closed />
+format :# # # #
+
+--
+<ns1:foo>
+ <elem attr1=xyz attr2="123"> </elem>
+ <closed />
+{
+ "col_0": "<ns1:foo>",
+ "col_1": "<elem attr1=xyz attr2=\"123\">",
+ "col_2": "</elem>",
+ "col_3": "<closed />"
+}
diff --git a/test/dhcp-trunc.pcapng b/test/dhcp-trunc.pcapng
new file mode 100644
index 0000000..00734ba
--- /dev/null
+++ b/test/dhcp-trunc.pcapng
Binary files differ
diff --git a/test/dhcp.pcapng b/test/dhcp.pcapng
new file mode 100644
index 0000000..530c64c
--- /dev/null
+++ b/test/dhcp.pcapng
Binary files differ
diff --git a/test/document.sections.tests.cc b/test/document.sections.tests.cc
new file mode 100644
index 0000000..8e88b75
--- /dev/null
+++ b/test/document.sections.tests.cc
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2022, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest/doctest.h"
+#include "document.sections.hh"
+
+TEST_CASE("lnav::document::sections::basics")
+{
+ attr_line_t INPUT = R"(
+{
+ "msg": "Hello, World!",
+ "obj": {
+ "a": 1,
+ "b": "Two",
+ "c": 3.0
+ },
+ "arr": [1, 2, 3],
+ "arr2": [
+ 456,
+ 789,
+ {
+ "def": 123,
+ "ghi": null,
+ "jkl": "other"
+ },
+ {
+ "def": 456,
+ "ghi": null,
+ "jkl": "OTHER"
+ },
+ {
+ "def": 789,
+ "ghi": null,
+ "jkl": "OtHeR"
+ }
+ ]
+}
+)";
+
+ auto meta = lnav::document::discover_structure(INPUT, line_range{0, -1});
+
+ meta.m_sections_tree.visit_all([](const auto& intv) {
+ auto ser = intv.value.match(
+ [](const std::string& name) { return name; },
+ [](const size_t index) { return fmt::format("{}", index); });
+ printf("interval %d:%d %s\n", intv.start, intv.stop, ser.c_str());
+ });
+ lnav::document::hier_node::depth_first(
+ meta.m_sections_root.get(), [](const auto* node) {
+ printf("node %p %d\n", node, node->hn_start);
+ for (const auto& pair : node->hn_named_children) {
+ printf(" child: %p %s\n", pair.second, pair.first.c_str());
+ }
+ });
+}
+
+TEST_CASE("lnav::document::sections::empty")
+{
+ attr_line_t INPUT
+ = R"(SOCKET 1 (10) creating new listening socket on port -1)";
+
+ auto meta = lnav::document::discover_structure(INPUT, line_range{0, -1});
+
+ meta.m_sections_tree.visit_all([](const auto& intv) {
+ auto ser = intv.value.match(
+ [](const std::string& name) { return name; },
+ [](const size_t index) { return fmt::format("{}", index); });
+ printf("interval %d:%d %s\n", intv.start, intv.stop, ser.c_str());
+ });
+ lnav::document::hier_node::depth_first(
+ meta.m_sections_root.get(), [](const auto* node) {
+ printf("node %p %d\n", node, node->hn_start);
+ for (const auto& pair : node->hn_named_children) {
+ printf(" child: %p %s\n", pair.second, pair.first.c_str());
+ }
+ });
+}
+
+TEST_CASE("lnav::document::sections::doc")
+{
+ attr_line_t INPUT = R"(
+
+NAME
+ foo -- bar
+
+SYNOPSIS
+ foo -o -b
+
+DESCRIPTION
+ Lorem ipsum
+
+ AbcDef
+ Lorem ipsum
+
+)";
+
+ auto meta = lnav::document::discover_structure(INPUT, line_range{0, -1});
+
+ CHECK(meta.m_sections_root->hn_named_children.size() == 3);
+ meta.m_sections_tree.visit_all([](const auto& intv) {
+ auto ser = intv.value.match(
+ [](const std::string& name) { return name; },
+ [](const size_t index) { return fmt::format("{}", index); });
+ printf("interval %d:%d %s\n", intv.start, intv.stop, ser.c_str());
+ });
+ lnav::document::hier_node::depth_first(
+ meta.m_sections_root.get(), [](const auto* node) {
+ printf("node %p %d\n", node, node->hn_start);
+ for (const auto& pair : node->hn_named_children) {
+ printf(" child: %p %s\n", pair.second, pair.first.c_str());
+ }
+ });
+}
+
+TEST_CASE("lnav::document::sections::sql")
+{
+ attr_line_t INPUT
+ = R"(2022-06-03T22:05:58.186Z verbose -[35642] [Originator@6876 sub=Default] [VdbStatement]Executing SQL:
+--> INSERT INTO PM_CLUSTER_DRAFT_VALIDATION_STATE
+--> (draft_id, errors, hosts) VALUES (?::integer, ?::jsonb, ARRAY[]::text[])
+--> ON CONFLICT (draft_id) DO UPDATE
+--> SET errors = EXCLUDED.errors, hosts = EXCLUDED.hosts
+-->
+)";
+
+ auto meta = lnav::document::discover_structure(INPUT, line_range{0, -1});
+
+ meta.m_sections_tree.visit_all([](const auto& intv) {
+ auto ser = intv.value.match(
+ [](const std::string& name) { return name; },
+ [](const size_t index) { return fmt::format("{}", index); });
+ printf("interval %d:%d %s\n", intv.start, intv.stop, ser.c_str());
+ });
+ lnav::document::hier_node::depth_first(
+ meta.m_sections_root.get(), [](const auto* node) {
+ printf("node %p %d\n", node, node->hn_start);
+ for (const auto& pair : node->hn_named_children) {
+ printf(" child: %p %s\n", pair.second, pair.first.c_str());
+ }
+ });
+}
diff --git a/test/drive_data_scanner.cc b/test/drive_data_scanner.cc
new file mode 100644
index 0000000..a8679c6
--- /dev/null
+++ b/test/drive_data_scanner.cc
@@ -0,0 +1,310 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __CYGWIN__
+# include <alloca.h>
+#endif
+
+#include <fstream>
+#include <iostream>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "base/injector.hh"
+#include "config.h"
+#include "data_parser.hh"
+#include "data_scanner.hh"
+#include "elem_to_json.hh"
+#include "log_format.hh"
+#include "log_format_loader.hh"
+#include "logfile.hh"
+#include "pretty_printer.hh"
+#include "shared_buffer.hh"
+#include "view_curses.hh"
+
+const char* TMP_NAME = "scanned.tmp";
+
+int
+main(int argc, char* argv[])
+{
+ int c, retval = EXIT_SUCCESS;
+ bool prompt = false, is_log = false, pretty_print = false;
+ bool scanner_details = false;
+
+ {
+ static auto builtin_formats
+ = injector::get<std::vector<std::shared_ptr<log_format>>>();
+ auto& root_formats = log_format::get_root_formats();
+
+ log_format::get_root_formats().insert(root_formats.begin(),
+ builtin_formats.begin(),
+ builtin_formats.end());
+ builtin_formats.clear();
+ }
+
+ {
+ std::vector<ghc::filesystem::path> paths;
+ std::vector<lnav::console::user_message> errors;
+
+ load_formats(paths, errors);
+ }
+
+ while ((c = getopt(argc, argv, "pPls")) != -1) {
+ switch (c) {
+ case 'p':
+ prompt = true;
+ break;
+
+ case 'P':
+ pretty_print = true;
+ break;
+
+ case 'l':
+ is_log = true;
+ break;
+
+ case 's':
+ scanner_details = true;
+ break;
+
+ default:
+ retval = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (retval != EXIT_SUCCESS) {
+ } else if (argc < 1) {
+ fprintf(stderr, "error: expecting file name argument(s)\n");
+ retval = EXIT_FAILURE;
+ } else {
+ for (int lpc = 0; lpc < argc; lpc++) {
+ std::unique_ptr<std::ifstream> in_ptr;
+ std::istream* in;
+ FILE* out;
+
+ if (strcmp(argv[lpc], "-") == 0) {
+ in = &std::cin;
+ } else {
+ auto ifs = std::make_unique<std::ifstream>(argv[lpc]);
+
+ if (!ifs->is_open()) {
+ fprintf(stderr, "error: unable to open file\n");
+ retval = EXIT_FAILURE;
+ } else {
+ in_ptr = std::move(ifs);
+ in = in_ptr.get();
+ }
+ }
+
+ if ((out = fopen(TMP_NAME, "w")) == nullptr) {
+ fprintf(stderr,
+ "error: unable to temporary file for writing\n");
+ retval = EXIT_FAILURE;
+ } else {
+ std::shared_ptr<log_format> format;
+ char* log_line;
+ bool found = false;
+ char cmd[2048];
+ std::string line;
+ int rc;
+
+ getline(*in, line);
+ if (strcmp(argv[lpc], "-") == 0) {
+ line = " " + line;
+ }
+
+ log_line = (char*) alloca(line.length());
+ strcpy(log_line, &line[13]);
+ auto sub_line = line.substr(13);
+ struct line_range body(0, sub_line.length());
+ shared_buffer share_manager;
+ logline_value_vector ll_values;
+ auto& sbr = ll_values.lvv_sbr;
+
+ sbr.share(
+ share_manager, (char*) sub_line.c_str(), sub_line.size());
+
+ auto& root_formats = log_format::get_root_formats();
+ std::vector<std::shared_ptr<log_format>>::iterator iter;
+ std::vector<logline> index;
+
+ if (is_log) {
+ logfile_open_options loo;
+ auto open_res = logfile::open(argv[lpc], loo);
+ auto lf = open_res.unwrap();
+ ArenaAlloc::Alloc<char> allocator;
+ scan_batch_context sbc{allocator};
+ for (iter = root_formats.begin();
+ iter != root_formats.end() && !found;
+ ++iter)
+ {
+ line_info li = {{13}};
+
+ (*iter)->clear();
+ if ((*iter)->scan(*lf, index, li, sbr, sbc)
+ == log_format::SCAN_MATCH)
+ {
+ format = (*iter)->specialized();
+ found = true;
+ }
+ }
+
+ if (!found) {
+ fprintf(stderr, "error: log sample does not match\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ string_attrs_t sa;
+
+ if (format.get() != nullptr) {
+ format->annotate(0, sa, ll_values);
+ body = find_string_attr_range(sa, &SA_BODY);
+ }
+
+ data_parser::TRACE_FILE = fopen("scanned.dpt", "w");
+
+ data_scanner ds(sub_line, body.lr_start);
+
+ if (scanner_details) {
+ fprintf(out,
+ " %s\n",
+ ds.get_input().to_string().c_str());
+ while (true) {
+ auto tok_res = ds.tokenize2();
+
+ if (!tok_res) {
+ break;
+ }
+
+ fprintf(out,
+ "%4s %3d:%-3d ",
+ data_scanner::token2name(tok_res->tr_token),
+ tok_res->tr_capture.c_begin,
+ tok_res->tr_capture.c_end);
+ size_t cap_index = 0;
+ for (; cap_index < tok_res->tr_capture.c_end;
+ cap_index++)
+ {
+ if (cap_index == tok_res->tr_capture.c_begin) {
+ fputc('^', out);
+ } else if (cap_index
+ == (tok_res->tr_capture.c_end - 1))
+ {
+ fputc('^', out);
+ } else if (cap_index > tok_res->tr_capture.c_begin)
+ {
+ fputc('-', out);
+ } else {
+ fputc(' ', out);
+ }
+ }
+ for (; cap_index < (int) ds.get_input().length();
+ cap_index++)
+ {
+ fputc(' ', out);
+ }
+
+ auto sub = tok_res->to_string();
+ fprintf(out, " %s\n", sub.c_str());
+ }
+ }
+
+ ds.reset();
+ data_parser dp(&ds);
+ std::string msg_format;
+
+ dp.dp_msg_format = &msg_format;
+ dp.parse();
+ dp.print(out, dp.dp_pairs);
+ fprintf(
+ out, "msg :%s\n", sub_line.c_str() + body.lr_start);
+ fprintf(out, "format :%s\n", msg_format.c_str());
+
+ if (pretty_print) {
+ data_scanner ds2(sub_line, body.lr_start);
+ pretty_printer pp(&ds2, sa);
+ attr_line_t pretty_out;
+
+ pp.append_to(pretty_out);
+ fprintf(out, "\n--\n%s", pretty_out.get_string().c_str());
+ }
+
+ auto_mem<yajl_gen_t> gen(yajl_gen_free);
+
+ gen = yajl_gen_alloc(nullptr);
+ yajl_gen_config(gen.in(), yajl_gen_beautify, true);
+
+ elements_to_json(gen, dp, &dp.dp_pairs);
+
+ const unsigned char* buf;
+ size_t len;
+
+ yajl_gen_get_buf(gen, &buf, &len);
+ fwrite(buf, 1, len, out);
+
+ fclose(out);
+
+ sprintf(cmd, "diff -u %s %s", argv[lpc], TMP_NAME);
+ rc = system(cmd);
+ if (rc != 0) {
+ if (prompt) {
+ char resp[4];
+
+ printf("\nOriginal line:\n%s\n",
+ sub_line.c_str() + body.lr_start);
+ printf(
+ "Would you like to update the original file? "
+ "(y/N) ");
+ fflush(stdout);
+ log_perror(scanf("%3s", resp));
+ if (strcasecmp(resp, "y") == 0) {
+ rename(TMP_NAME, argv[lpc]);
+ } else {
+ retval = EXIT_FAILURE;
+ }
+ } else {
+ fprintf(stderr, "error: mismatch\n");
+ retval = EXIT_FAILURE;
+ }
+ }
+
+ fclose(data_parser::TRACE_FILE);
+ data_parser::TRACE_FILE = nullptr;
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_grep_proc.cc b/test/drive_grep_proc.cc
new file mode 100644
index 0000000..4118f43
--- /dev/null
+++ b/test/drive_grep_proc.cc
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "grep_proc.hh"
+#include "line_buffer.hh"
+#include "listview_curses.hh"
+
+using namespace std;
+
+class my_source : public grep_proc_source<vis_line_t> {
+public:
+ my_source(auto_fd& fd) { this->ms_buffer.set_fd(fd); };
+
+ bool grep_value_for_line(vis_line_t line_number, string& value_out)
+ {
+ bool retval = false;
+
+ try {
+ auto load_result = this->ms_buffer.load_next_line(this->ms_range);
+
+ if (load_result.isOk()) {
+ auto li = load_result.unwrap();
+
+ this->ms_range = li.li_file_range;
+ if (!li.li_file_range.empty()) {
+ auto read_result
+ = this->ms_buffer.read_range(li.li_file_range)
+ .then([&value_out](auto sbr) {
+ value_out = to_string(sbr);
+ });
+
+ retval = read_result.isOk();
+ }
+ }
+ } catch (const line_buffer::error& e) {
+ fprintf(stderr,
+ "error: source buffer error %d %s\n",
+ this->ms_buffer.get_fd(),
+ strerror(e.e_err));
+ }
+
+ return retval;
+ };
+
+private:
+ line_buffer ms_buffer;
+ file_range ms_range;
+};
+
+class my_sink : public grep_proc_sink<vis_line_t> {
+public:
+ my_sink() : ms_finished(false) {}
+
+ void grep_match(grep_proc<vis_line_t>& gp,
+ vis_line_t line,
+ int start,
+ int end)
+ {
+ printf("%d:%d:%d\n", (int) line, start, end);
+ }
+
+ void grep_capture(grep_proc<vis_line_t>& gp,
+ vis_line_t line,
+ int start,
+ int end,
+ char* capture)
+ {
+ fprintf(stderr, "%d(%d:%d)%s\n", (int) line, start, end, capture);
+ }
+
+ void grep_end(grep_proc<vis_line_t>& gp) { this->ms_finished = true; }
+
+ bool ms_finished;
+};
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_fd fd;
+
+ if (argc < 3) {
+ fprintf(stderr, "error: expecting pattern and file arguments\n");
+ retval = EXIT_FAILURE;
+ } else if ((fd = open(argv[2], O_RDONLY)) == -1) {
+ perror("open");
+ retval = EXIT_FAILURE;
+ } else {
+ auto compile_res = lnav::pcre2pp::code::from(
+ string_fragment::from_c_str(argv[1]), PCRE2_CASELESS);
+
+ if (compile_res.isErr()) {
+ auto ce = compile_res.unwrapErr();
+ fprintf(stderr,
+ "error: invalid pattern -- %s\n",
+ ce.get_message().c_str());
+ } else {
+ auto co = compile_res.unwrap().to_shared();
+ auto psuperv = std::make_shared<pollable_supervisor>();
+ my_source ms(fd);
+ my_sink msink;
+
+ grep_proc<vis_line_t> gp(co, ms, psuperv);
+
+ gp.set_sink(&msink);
+ gp.queue_request();
+ gp.start();
+
+ while (!msink.ms_finished) {
+ vector<struct pollfd> pollfds;
+
+ psuperv->update_poll_set(pollfds);
+ poll(&pollfds[0], pollfds.size(), -1);
+
+ psuperv->check_poll_set(pollfds);
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_line_buffer.cc b/test/drive_line_buffer.cc
new file mode 100644
index 0000000..75acba3
--- /dev/null
+++ b/test/drive_line_buffer.cc
@@ -0,0 +1,245 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+#include <random>
+#include <tuple>
+#include <vector>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "base/auto_fd.hh"
+#include "base/string_util.hh"
+#include "config.h"
+#include "line_buffer.hh"
+
+using namespace std;
+
+int
+main(int argc, char* argv[])
+{
+ int c, rnd_iters = 5, retval = EXIT_SUCCESS;
+ vector<tuple<int, off_t, ssize_t> > index;
+ auto_fd fd = auto_fd(STDIN_FILENO), fd_cmp;
+ int offseti = 0;
+ off_t offset = 0;
+ int count = 1000;
+ struct stat st;
+
+ while ((c = getopt(argc, argv, "o:i:n:c:")) != -1) {
+ switch (c) {
+ case 'o':
+ if (sscanf(optarg, "%d", &offseti) != 1) {
+ fprintf(stderr,
+ "error: offset is not an integer -- %s\n",
+ optarg);
+ retval = EXIT_FAILURE;
+ } else {
+ offset = offseti;
+ }
+ break;
+ case 'n':
+ if (sscanf(optarg, "%d", &rnd_iters) != 1) {
+ fprintf(stderr,
+ "error: offset is not an integer -- %s\n",
+ optarg);
+ retval = EXIT_FAILURE;
+ }
+ break;
+ case 'c':
+ if (sscanf(optarg, "%d", &count) != 1) {
+ fprintf(stderr,
+ "error: count is not an integer -- %s\n",
+ optarg);
+ retval = EXIT_FAILURE;
+ }
+ break;
+ case 'i': {
+ FILE* file;
+
+ if ((file = fopen(optarg, "r")) == NULL) {
+ perror("open");
+ retval = EXIT_FAILURE;
+ } else {
+ int line_number = 1, line_offset;
+ off_t last_offset;
+ ssize_t line_size;
+
+ while (fscanf(file, "%d", &line_offset) == 1) {
+ if (line_number > 1) {
+ line_size = line_offset - last_offset;
+ index.emplace_back(
+ line_number - 1, last_offset, line_size);
+ }
+ last_offset = line_offset;
+ line_number += 1;
+ }
+ fclose(file);
+ file = NULL;
+ }
+ } break;
+ default:
+ retval = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (retval != EXIT_SUCCESS) {
+ } else if ((argc == 0) && (index.size() > 0)) {
+ fprintf(stderr, "error: cannot randomize stdin\n");
+ retval = EXIT_FAILURE;
+ } else if ((argc > 0) && (fd = open(argv[0], O_RDONLY)) == -1) {
+ perror("open");
+ retval = EXIT_FAILURE;
+ } else if ((argc > 0) && (fstat(fd, &st) == -1)) {
+ perror("fstat");
+ retval = EXIT_FAILURE;
+ } else if ((argc > 1) && (fd_cmp = open(argv[1], O_RDONLY)) == -1) {
+ perror("open-cmp");
+ retval = EXIT_FAILURE;
+ } else if ((argc > 1) && (fstat(fd_cmp, &st) == -1)) {
+ perror("fstat-cmp");
+ retval = EXIT_FAILURE;
+ } else {
+ try {
+ file_range last_range{offset};
+ line_buffer lb;
+ char* maddr;
+
+ int fd2 = (argc > 1) ? fd_cmp.get() : fd.get();
+ assert(fd2 >= 0);
+ lb.set_fd(fd);
+ if (index.size() == 0) {
+ while (count) {
+ auto load_result = lb.load_next_line(last_range);
+
+ if (load_result.isErr()) {
+ break;
+ }
+
+ auto li = load_result.unwrap();
+
+ if (li.li_file_range.empty()) {
+ break;
+ }
+
+ auto read_result = lb.read_range(li.li_file_range);
+
+ if (read_result.isErr()) {
+ break;
+ }
+
+ auto sbr = read_result.unwrap();
+
+ if (!li.li_valid_utf) {
+ scrub_to_utf8(sbr.get_writable_data(), sbr.length());
+ }
+
+ printf("%.*s", (int) sbr.length(), sbr.get_data());
+ if ((off_t) (li.li_file_range.fr_offset
+ + li.li_file_range.fr_size)
+ < offset) {
+ printf("\n");
+ }
+ last_range = li.li_file_range;
+ count -= 1;
+ }
+ } else if ((maddr = (char*) mmap(NULL,
+ st.st_size,
+ PROT_READ,
+ MAP_FILE | MAP_PRIVATE,
+ fd2,
+ 0))
+ == MAP_FAILED)
+ {
+ perror("mmap");
+ retval = EXIT_FAILURE;
+ } else {
+ file_range range;
+
+ while (true) {
+ auto load_result = lb.load_next_line(range);
+
+ if (load_result.isErr()) {
+ return EXIT_FAILURE;
+ }
+
+ auto li = load_result.unwrap();
+
+ range = li.li_file_range;
+
+ if (range.empty()) {
+ break;
+ }
+ }
+ do {
+ size_t lpc;
+
+ std::random_device rd;
+ std::mt19937 g(rd());
+ std::shuffle(index.begin(), index.end(), g);
+ for (lpc = 0; lpc < index.size(); lpc++) {
+ const auto& index_tuple = index[lpc];
+
+ auto read_result = lb.read_range(
+ {get<1>(index_tuple), get<2>(index_tuple)});
+
+ assert(read_result.isOk());
+
+ auto sbr = read_result.unwrap();
+
+ assert(memcmp(sbr.get_data(),
+ &maddr[get<1>(index_tuple)],
+ sbr.length())
+ == 0);
+ }
+
+ rnd_iters -= 1;
+ } while (rnd_iters);
+
+ printf("All done\n");
+ }
+ } catch (line_buffer::error& e) {
+ fprintf(stderr, "error: %s\n", strerror(e.e_err));
+ retval = EXIT_FAILURE;
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_listview.cc b/test/drive_listview.cc
new file mode 100644
index 0000000..9938431
--- /dev/null
+++ b/test/drive_listview.cc
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "listview_curses.hh"
+
+using namespace std;
+
+static listview_curses lv;
+
+class my_source : public list_data_source {
+public:
+ my_source() : ms_rows(2){};
+
+ size_t listview_rows(const listview_curses& lv)
+ {
+ return this->ms_rows;
+ };
+
+ void listview_value_for_rows(const listview_curses& lv,
+ vis_line_t row,
+ vector<attr_line_t>& rows)
+ {
+ for (auto& value_out : rows) {
+ if (row == 0) {
+ value_out = "Hello";
+ } else if (row == 1) {
+ value_out = "World!";
+ } else if (row < this->ms_rows) {
+ char buffer[32];
+
+ snprintf(buffer, sizeof(buffer), "%d", (int) row);
+ value_out = string(buffer);
+ } else {
+ assert(0);
+ }
+ ++row;
+ }
+ };
+
+ size_t listview_size_for_row(const listview_curses& lv, vis_line_t row)
+ {
+ return 100;
+ };
+
+ bool attrline_next_token(const view_curses& vc,
+ int line,
+ struct line_range& lr,
+ int& attrs_out)
+ {
+ return false;
+ };
+
+ int ms_rows;
+};
+
+int
+main(int argc, char* argv[])
+{
+ int c, retval = EXIT_SUCCESS;
+ bool wait_for_input = false, set_height = false;
+ my_source ms;
+ WINDOW* win;
+
+ win = initscr();
+ lv.set_data_source(&ms);
+ lv.set_window(win);
+ noecho();
+
+ while ((c = getopt(argc, argv, "y:t:l:r:h:w")) != -1) {
+ switch (c) {
+ case 'y':
+ lv.set_y(atoi(optarg));
+ break;
+ case 'h':
+ lv.set_height(vis_line_t(atoi(optarg)));
+ set_height = true;
+ break;
+ case 't':
+ lv.set_top(vis_line_t(atoi(optarg)));
+ break;
+ case 'l':
+ lv.set_left(atoi(optarg));
+ break;
+ case 'w':
+ wait_for_input = true;
+ break;
+ case 'r':
+ ms.ms_rows = atoi(optarg);
+ break;
+ }
+ }
+
+ if (!set_height) {
+ unsigned long height, width;
+ getmaxyx(win, height, width);
+ lv.set_height(vis_line_t(height - lv.get_y()));
+ }
+
+ lv.do_update();
+ refresh();
+ if (wait_for_input) {
+ getch();
+ }
+ endwin();
+
+ return retval;
+}
diff --git a/test/drive_logfile.cc b/test/drive_logfile.cc
new file mode 100644
index 0000000..2da37dd
--- /dev/null
+++ b/test/drive_logfile.cc
@@ -0,0 +1,194 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/injector.hh"
+#include "base/opt_util.hh"
+#include "config.h"
+#include "log_format.hh"
+#include "log_format_loader.hh"
+#include "logfile.hh"
+
+using namespace std;
+
+typedef enum {
+ MODE_NONE,
+ MODE_ECHO,
+ MODE_LINE_COUNT,
+ MODE_TIMES,
+ MODE_LEVELS,
+} dl_mode_t;
+
+time_t
+time(time_t* _unused)
+{
+ return 1194107018;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int c, retval = EXIT_SUCCESS;
+ dl_mode_t mode = MODE_NONE;
+ string expected_format;
+
+ {
+ static auto builtin_formats
+ = injector::get<std::vector<std::shared_ptr<log_format>>>();
+ auto& root_formats = log_format::get_root_formats();
+
+ log_format::get_root_formats().insert(root_formats.begin(),
+ builtin_formats.begin(),
+ builtin_formats.end());
+ builtin_formats.clear();
+ }
+
+ {
+ std::vector<lnav::console::user_message> errors;
+ vector<ghc::filesystem::path> paths;
+
+ getenv_opt("test_dir") |
+ [&paths](auto value) { paths.template emplace_back(value); };
+ load_formats(paths, errors);
+ }
+
+ while ((c = getopt(argc, argv, "ef:ltv")) != -1) {
+ switch (c) {
+ case 'f':
+ expected_format = optarg;
+ break;
+ case 'e':
+ mode = MODE_ECHO;
+ break;
+ case 'l':
+ mode = MODE_LINE_COUNT;
+ break;
+ case 't':
+ mode = MODE_TIMES;
+ break;
+ case 'v':
+ mode = MODE_LEVELS;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (retval == EXIT_FAILURE) {
+ } else if (argc == 0) {
+ fprintf(stderr, "error: expecting log file name\n");
+ } else {
+ logfile_open_options default_loo;
+ auto open_res = logfile::open(argv[0], default_loo);
+
+ if (open_res.isErr()) {
+ fprintf(stderr,
+ "unable to open logfile: %s\n",
+ open_res.unwrapErr().c_str());
+ return EXIT_FAILURE;
+ }
+
+ auto lf = open_res.unwrap();
+ struct stat st;
+
+ stat(argv[0], &st);
+ assert(strcmp(argv[0], lf->get_filename().c_str()) == 0);
+
+ lf->rebuild_index();
+ assert(!lf->is_closed());
+ lf->rebuild_index();
+ assert(!lf->is_closed());
+ lf->rebuild_index();
+ assert(!lf->is_closed());
+ assert(lf->get_activity().la_polls == 3);
+ if (expected_format.empty()) {
+ assert(lf->get_format() == nullptr);
+ } else {
+ // printf("%s %s\n", lf->get_format()->get_name().c_str(),
+ // expected_format.c_str());
+ assert(lf->get_format() != nullptr);
+ assert(lf->get_format()->get_name().to_string() == expected_format);
+ }
+ if (!lf->is_compressed()) {
+ assert(lf->get_modified_time() == st.st_mtime);
+ }
+
+ switch (mode) {
+ case MODE_NONE:
+ break;
+ case MODE_ECHO:
+ for (auto iter = lf->begin(); iter != lf->end(); ++iter) {
+ auto sbr = lf->read_line(iter).unwrap();
+
+ printf("%.*s\n", (int) sbr.length(), sbr.get_data());
+ }
+ break;
+ case MODE_LINE_COUNT:
+ printf("%zd\n", lf->size());
+ break;
+ case MODE_TIMES:
+ for (auto& iter : *lf) {
+ if (iter.is_ignored()) {
+ continue;
+ }
+
+ char buffer[1024];
+ time_t lt;
+
+ lt = iter.get_time();
+ strftime(buffer,
+ sizeof(buffer),
+ "%b %d %H:%M:%S %Y",
+ gmtime(&lt));
+ printf("%s -- %03d\n", buffer, iter.get_millis());
+ }
+ break;
+ case MODE_LEVELS:
+ for (auto& iter : *lf) {
+ log_level_t level = iter.get_level_and_flags();
+ printf("%s 0x%x\n",
+ level_names[level & ~LEVEL__FLAGS],
+ level & LEVEL__FLAGS);
+ }
+ break;
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_mvwattrline.cc b/test/drive_mvwattrline.cc
new file mode 100644
index 0000000..51bddb1
--- /dev/null
+++ b/test/drive_mvwattrline.cc
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2014, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "view_curses.hh"
+
+int
+main(int argc, char* argv[])
+{
+ int c, retval = EXIT_SUCCESS;
+ bool wait_for_input = false;
+
+ while ((c = getopt(argc, argv, "w")) != -1) {
+ switch (c) {
+ case 'w':
+ wait_for_input = true;
+ break;
+ }
+ }
+
+ setenv("LANG", "en_US.utf-8", 1);
+ setlocale(LC_ALL, "");
+
+ {
+ auto sc = screen_curses::create().unwrap();
+ WINDOW* win = sc.get_window();
+ struct line_range lr(0, 40);
+ attr_line_t al;
+ int y = 0;
+
+ curs_set(0);
+ noecho();
+ view_colors::singleton().init(false);
+
+ al.with_string("Plain text");
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ al.clear()
+ .with_string("\tLeading tab")
+ .with_attr(string_attr(line_range(0, 1),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ al.clear()
+ .with_string("Tab\twith text")
+ .with_attr(string_attr(line_range(1, 4),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ al.clear()
+ .with_string("Tab\twith text #2")
+ .with_attr(string_attr(line_range(3, 4),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ al.clear()
+ .with_string("Two\ttabs\twith text")
+ .with_attr(string_attr(line_range(4, 6),
+ VC_STYLE.value(text_attrs{A_REVERSE})))
+ .with_attr(string_attr(line_range(9, 13),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ al.clear()
+ .with_string("Text with mixed attributes.")
+ .with_attr(string_attr(
+ line_range(5, 9),
+ VC_STYLE.value(text_attrs{0, COLOR_RED, COLOR_BLACK})))
+ .with_attr(string_attr(line_range(7, 12),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ const char* text = u8"Text with unicode ▶ characters";
+ int offset = strstr(text, "char") - text;
+ al.clear().with_string(text).with_attr(
+ string_attr(line_range(offset, offset + 4),
+ VC_STYLE.value(text_attrs{A_REVERSE})));
+ view_curses::mvwattrline(win, y++, 0, al, lr);
+
+ wmove(win, y, 0);
+ refresh();
+ if (wait_for_input) {
+ getch();
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_readline_curses.cc b/test/drive_readline_curses.cc
new file mode 100644
index 0000000..54dfebc
--- /dev/null
+++ b/test/drive_readline_curses.cc
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TTYDEFAULTS_H
+# include <sys/ttydefaults.h>
+#endif
+
+#include <algorithm>
+
+#include "../src/lnav_util.hh"
+#include "lnav_util.hh"
+#include "readline_curses.hh"
+
+using namespace std;
+
+static readline_context::command_map_t COMMANDS;
+
+static struct {
+ bool dd_active;
+ readline_curses* dd_rl_view;
+ volatile sig_atomic_t dd_looping;
+} drive_data;
+
+static void
+rl_callback(readline_curses* rc)
+{
+ string line = rc->get_value().get_string();
+
+ if (line == "quit")
+ drive_data.dd_looping = false;
+ fprintf(stderr, "callback\n");
+ drive_data.dd_active = false;
+}
+
+static void
+rl_timeout(readline_curses* rc)
+{
+ fprintf(stderr, "timeout\n");
+}
+
+int
+main(int argc, char* argv[])
+{
+ int c, fd, retval = EXIT_SUCCESS;
+
+ fd = open("/tmp/lnav.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+ fprintf(stderr, "startup\n");
+
+ while ((c = getopt(argc, argv, "h")) != -1) {
+ switch (c) {
+ case 'h':
+ break;
+ default:
+ break;
+ }
+ }
+
+ auto psuperv = std::make_shared<pollable_supervisor>();
+ readline_context context("test", &COMMANDS);
+ readline_curses rlc(psuperv);
+
+ rlc.add_context(1, context);
+ rlc.start();
+
+ drive_data.dd_rl_view = &rlc;
+
+ auto sc = screen_curses::create().unwrap();
+ keypad(stdscr, TRUE);
+ nonl();
+ cbreak();
+ noecho();
+ nodelay(sc.get_window(), 1);
+
+ rlc.set_window(sc.get_window());
+ rlc.set_y(-1);
+ rlc.set_perform_action(rl_callback);
+ rlc.set_timeout_action(rl_timeout);
+
+ drive_data.dd_looping = true;
+ while (drive_data.dd_looping) {
+ vector<struct pollfd> pollfds;
+ int rc;
+
+ pollfds.push_back((struct pollfd){STDIN_FILENO, POLLIN, 0});
+ psuperv->update_poll_set(pollfds);
+
+ rlc.do_update();
+ refresh();
+ rc = poll(&pollfds[0], pollfds.size(), -1);
+ if (rc > 0) {
+ if (pollfd_ready(pollfds, STDIN_FILENO)) {
+ int ch;
+
+ while ((ch = getch()) != ERR) {
+ switch (ch) {
+ case CEOF:
+ case KEY_RESIZE:
+ break;
+
+ default:
+ if (drive_data.dd_active) {
+ rlc.handle_key(ch);
+ } else if (ch == ':') {
+ rlc.focus(1, ":");
+ drive_data.dd_active = true;
+ }
+ break;
+ }
+ }
+ }
+ psuperv->check_poll_set(pollfds);
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_sequencer.cc b/test/drive_sequencer.cc
new file mode 100644
index 0000000..4e39d30
--- /dev/null
+++ b/test/drive_sequencer.cc
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <vector>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "logfile.hh"
+#include "sequence_matcher.hh"
+#include "sequence_sink.hh"
+#include "textview_curses.hh"
+
+using namespace std;
+
+class my_source : public grep_proc_source<vis_line_t> {
+public:
+ my_source(auto_fd& fd) : ms_offset(0) { this->ms_buffer.set_fd(fd); };
+
+ bool grep_value_for_line(vis_line_t line_number, string& value_out)
+ {
+ bool retval = false;
+
+ try {
+#if 0
+ line_value lv;
+
+ if (this->ms_buffer.read_line(this->ms_offset, lv)) {
+ value_out = string(lv.lv_start, lv.lv_len);
+ retval = true;
+ }
+#endif
+ } catch (line_buffer::error& e) {
+ fprintf(stderr,
+ "error: source buffer error %d %s\n",
+ this->ms_buffer.get_fd(),
+ strerror(e.e_err));
+ }
+
+ return retval;
+ };
+
+private:
+ line_buffer ms_buffer;
+ off_t ms_offset;
+};
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ const char* errptr;
+ auto_fd fd;
+ pcre* code;
+ int eoff;
+
+ if (argc < 3) {
+ fprintf(stderr, "error: expecting pattern and file arguments\n");
+ retval = EXIT_FAILURE;
+ } else if ((fd = open(argv[2], O_RDONLY)) == -1) {
+ perror("open");
+ retval = EXIT_FAILURE;
+ } else if ((code
+ = pcre_compile(argv[1], PCRE_CASELESS, &errptr, &eoff, NULL))
+ == NULL)
+ {
+ fprintf(stderr, "error: invalid pattern -- %s\n", errptr);
+ } else {
+ my_source ms(fd);
+
+ sequence_matcher::field_col_t fc;
+
+ fc.resize(2);
+
+ sequence_matcher::field_row_t& frf = fc.front();
+ frf.resize(2);
+ frf[0] = "eth0";
+ frf[1] = "eth0";
+
+ sequence_matcher::field_row_t& frb = fc.back();
+ frb.resize(2);
+ frb[0] = "up";
+ frb[1] = "down";
+
+ static bookmark_type_t SEQUENCE("sequence");
+
+ sequence_matcher sm(fc);
+ vis_bookmarks bm;
+ sequence_sink ss(sm, bm[&SEQUENCE]);
+
+ grep_proc<vis_line_t> gp(code, ms);
+
+ gp.set_sink(&ss);
+ gp.queue_request();
+ gp.start();
+
+ while (bm[&SEQUENCE].size() == 0) {
+ vector<struct pollfd> pollfds;
+
+ poll(&pollfds[0], pollfds.size(), -1);
+
+ gp.check_poll_set(pollfds);
+ }
+
+ for (bookmark_vector<vis_line_t>::iterator iter = bm[&SEQUENCE].begin();
+ iter != bm[&SEQUENCE].end();
+ ++iter)
+ {
+ printf("%d\n", (const int) *iter);
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_shlexer.cc b/test/drive_shlexer.cc
new file mode 100644
index 0000000..fe6f15f
--- /dev/null
+++ b/test/drive_shlexer.cc
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2015, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+#include "config.h"
+#include "shlex.hh"
+
+using namespace std;
+
+const char* ST_TOKEN_NAMES[] = {
+ "err",
+ "wsp",
+ "esc",
+ "dst",
+ "den",
+ "sst",
+ "sen",
+ "ref",
+ "qrf",
+ "til",
+};
+
+int
+main(int argc, char* argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "error: expecting an argument to parse\n");
+ exit(EXIT_FAILURE);
+ }
+
+ shlex lexer(argv[1], strlen(argv[1]));
+ string_fragment cap;
+ shlex_token_t token;
+
+ printf(" %s\n", argv[1]);
+ while (lexer.tokenize(cap, token)) {
+ int lpc;
+
+ printf("%s ", ST_TOKEN_NAMES[(int) token]);
+ for (lpc = 0; lpc < cap.sf_end; lpc++) {
+ if (lpc == cap.sf_begin) {
+ fputc('^', stdout);
+ } else if (lpc == (cap.sf_end - 1)) {
+ fputc('^', stdout);
+ } else if (lpc > cap.sf_begin) {
+ fputc('-', stdout);
+ } else {
+ fputc(' ', stdout);
+ }
+ }
+ printf("\n");
+ }
+
+ lexer.reset();
+ std::string result;
+ if (lexer.eval(result, map<string, string>())) {
+ printf("eval -- %s\n", result.c_str());
+ }
+ lexer.reset();
+ std::vector<std::string> sresult;
+ if (lexer.split(sresult, map<string, string>())) {
+ printf("split:\n");
+ for (size_t lpc = 0; lpc < sresult.size(); lpc++) {
+ printf(" %zu -- %s\n", lpc, sresult[lpc].c_str());
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/drive_sql.cc b/test/drive_sql.cc
new file mode 100644
index 0000000..243e78a
--- /dev/null
+++ b/test/drive_sql.cc
@@ -0,0 +1,78 @@
+#include <iostream>
+
+#include <assert.h>
+#include <sqlite3.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/auto_mem.hh"
+#include "base/injector.hh"
+#include "regexp_vtab.hh"
+#include "sqlite-extension-func.hh"
+#include "xpath_vtab.hh"
+
+struct callback_state {
+ int cs_row;
+};
+
+static int
+sql_callback(void* ptr, int ncols, char** colvalues, char** colnames)
+{
+ struct callback_state* cs = (struct callback_state*) ptr;
+
+ printf("Row %d:\n", cs->cs_row);
+ for (int lpc = 0; lpc < ncols; lpc++) {
+ printf(" Column %10s: %s\n", colnames[lpc], colvalues[lpc]);
+ }
+
+ cs->cs_row += 1;
+
+ return 0;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_mem<sqlite3> db(sqlite3_close);
+ std::string stmt;
+
+ log_argv(argc, argv);
+
+ if (argc == 2) {
+ stmt = argv[1];
+ } else {
+ std::getline(std::cin, stmt, '\0');
+ }
+
+ if (sqlite3_open(":memory:", db.out()) != SQLITE_OK) {
+ fprintf(stderr, "error: unable to make sqlite memory database\n");
+ retval = EXIT_FAILURE;
+ } else {
+ auto_mem<char> errmsg(sqlite3_free);
+ struct callback_state state;
+
+ memset(&state, 0, sizeof(state));
+
+ {
+ int register_collation_functions(sqlite3 * db);
+
+ register_sqlite_funcs(db.in(), sqlite_registration_funcs);
+ register_collation_functions(db.in());
+ }
+
+ register_regexp_vtab(db.in());
+ register_xpath_vtab(db.in());
+
+ if (sqlite3_exec(
+ db.in(), stmt.c_str(), sql_callback, &state, errmsg.out())
+ != SQLITE_OK)
+ {
+ fprintf(stderr, "error: sqlite3_exec failed -- %s\n", errmsg.in());
+ retval = EXIT_FAILURE;
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_sql_anno.cc b/test/drive_sql_anno.cc
new file mode 100644
index 0000000..8486ae2
--- /dev/null
+++ b/test/drive_sql_anno.cc
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2017, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @file drive_sql_anno.cc
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lnav.hh"
+#include "sql_help.hh"
+#include "sql_util.hh"
+#include "sqlite-extension-func.hh"
+
+using namespace std;
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_mem<sqlite3> db(sqlite3_close);
+
+ log_argv(argc, argv);
+
+ if (argc < 2) {
+ fprintf(stderr, "error: expecting an SQL statement\n");
+ retval = EXIT_FAILURE;
+ } else if (sqlite3_open(":memory:", db.out()) != SQLITE_OK) {
+ fprintf(stderr, "error: unable to make sqlite memory database\n");
+ retval = EXIT_FAILURE;
+ } else {
+ register_sqlite_funcs(db.in(), sqlite_registration_funcs);
+
+ attr_line_t al(argv[1]);
+
+ annotate_sql_statement(al);
+
+ printf(" %14s %s\n", " ", argv[1]);
+ for (auto& attr : al.get_attrs()) {
+ auto& lr = attr.sa_range;
+
+ printf(" %14s %s%s\n",
+ attr.sa_type->sat_name,
+ string(lr.lr_start, ' ').c_str(),
+ string(lr.length(), '-').c_str());
+ }
+
+ if (argc == 3) {
+ int near;
+
+ if (sscanf(argv[2], "%d", &near) != 1) {
+ fprintf(stderr, "error: expecting an integer for third arg\n");
+ return EXIT_FAILURE;
+ }
+
+ auto avail_help = find_sql_help_for_line(al, near);
+ for (const auto& ht : avail_help) {
+ printf("%s: %s\n", ht->ht_name, ht->ht_summary);
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/test/drive_view_colors.cc b/test/drive_view_colors.cc
new file mode 100644
index 0000000..f7b38c1
--- /dev/null
+++ b/test/drive_view_colors.cc
@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "view_curses.hh"
+
+class test_colors : public view_curses {
+public:
+ test_colors() : tc_window(nullptr) {}
+
+ void do_update() override
+ {
+ auto& vc = view_colors::singleton();
+ int lpc;
+
+ for (lpc = 0; lpc < 16; lpc++) {
+ text_attrs attrs;
+ char label[64];
+ attr_line_t al;
+ line_range lr;
+
+ snprintf(label, sizeof(label), "This is line: %d", lpc);
+ attrs = vc.attrs_for_ident(label);
+ al = label;
+ al.get_attrs().emplace_back(line_range(0, -1),
+ VC_STYLE.value(attrs));
+ lr.lr_start = 0;
+ lr.lr_end = 40;
+ test_colors::mvwattrline(this->tc_window, lpc, 0, al, lr);
+ }
+
+ attr_line_t al;
+ line_range lr{0, 40};
+
+ al = "before <123> after";
+ al.with_attr({line_range{8, 11},
+ VC_STYLE.value(text_attrs{0, COLOR_CYAN, COLOR_BLACK})});
+ al.with_attr(
+ {line_range{8, 11}, VC_STYLE.value(text_attrs{A_REVERSE})});
+ test_colors::mvwattrline(this->tc_window, lpc, 0, al, lr);
+ };
+
+ WINDOW* tc_window;
+};
+
+int
+main(int argc, char* argv[])
+{
+ int c, retval = EXIT_SUCCESS;
+ bool wait_for_input = false;
+ WINDOW* win;
+ test_colors tc;
+
+ win = initscr();
+ noecho();
+
+ while ((c = getopt(argc, argv, "w")) != -1) {
+ switch (c) {
+ case 'w':
+ wait_for_input = true;
+ break;
+ }
+ }
+
+ view_colors::init(false);
+ curs_set(0);
+ tc.tc_window = win;
+ tc.do_update();
+ refresh();
+ if (wait_for_input) {
+ getch();
+ }
+ endwin();
+
+ return retval;
+}
diff --git a/test/drive_vt52_curses.cc b/test/drive_vt52_curses.cc
new file mode 100644
index 0000000..cc96ff2
--- /dev/null
+++ b/test/drive_vt52_curses.cc
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "base/lnav_log.hh"
+#include "config.h"
+#include "view_curses.hh"
+#include "vt52_curses.hh"
+
+#if defined HAVE_NCURSESW_CURSES_H
+# include <ncursesw/curses.h>
+# include <ncursesw/term.h>
+#elif defined HAVE_NCURSESW_H
+# include <ncursesw.h>
+# include <term.h>
+#elif defined HAVE_NCURSES_CURSES_H
+# include <ncurses/curses.h>
+# include <ncurses/term.h>
+#elif defined HAVE_NCURSES_H
+# include <ncurses.h>
+# include <term.h>
+#elif defined HAVE_CURSES_H
+# include <curses.h>
+# include <term.h>
+#else
+# error "SysV or X/Open-compatible Curses header file required"
+#endif
+
+#undef set_window
+
+int
+main(int argc, char* argv[])
+{
+ int lpc, c, fd, retval = EXIT_SUCCESS;
+ vt52_curses vt;
+
+ setenv("LANG", "en_US.utf-8", 1);
+ setlocale(LC_ALL, "");
+ fd = open("/tmp/lnav.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+ fprintf(stderr, "startup\n");
+ lnav_log_file = stderr;
+
+ while ((c = getopt(argc, argv, "y:")) != -1) {
+ switch (c) {
+ case 'y':
+ vt.set_y(atoi(optarg));
+ break;
+ }
+ }
+
+ for (lpc = 0; lpc < 1000; lpc++) {
+ int len;
+
+ assert(vt.map_input(random(), len) != nullptr);
+ assert(len > 0);
+ }
+
+ tgetent(nullptr, "vt52");
+ {
+ static const char* CANNED_INPUT[] = {
+ "Gru\xC3\x9F",
+ "\r",
+ tgetstr((char*) "ce", nullptr),
+ "de",
+ "\n",
+ "1",
+ "2",
+ "3",
+ "\n",
+ "abc",
+ "\x02",
+ "\a",
+ "ab\bcdef",
+ };
+
+ auto sc = screen_curses::create().unwrap();
+ noecho();
+ vt.set_window(sc.get_window());
+ vt.set_width(10);
+
+ for (const auto* canned : CANNED_INPUT) {
+ vt.map_output(canned, strlen(canned));
+ vt.do_update();
+ refresh();
+ view_curses::awaiting_user_input();
+ getch();
+ }
+
+ view_curses::awaiting_user_input();
+ getch();
+ }
+
+ return retval;
+}
diff --git a/test/expected/expected.am b/test/expected/expected.am
new file mode 100644
index 0000000..1280cda
--- /dev/null
+++ b/test/expected/expected.am
@@ -0,0 +1,1005 @@
+
+EXPECTED_FILES = \
+ $(srcdir)/%reldir%/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.err \
+ $(srcdir)/%reldir%/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.out \
+ $(srcdir)/%reldir%/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.err \
+ $(srcdir)/%reldir%/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.out \
+ $(srcdir)/%reldir%/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.err \
+ $(srcdir)/%reldir%/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.out \
+ $(srcdir)/%reldir%/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.err \
+ $(srcdir)/%reldir%/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.out \
+ $(srcdir)/%reldir%/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.err \
+ $(srcdir)/%reldir%/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err \
+ $(srcdir)/%reldir%/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.out \
+ $(srcdir)/%reldir%/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.err \
+ $(srcdir)/%reldir%/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.out \
+ $(srcdir)/%reldir%/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.err \
+ $(srcdir)/%reldir%/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.out \
+ $(srcdir)/%reldir%/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.err \
+ $(srcdir)/%reldir%/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.out \
+ $(srcdir)/%reldir%/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.err \
+ $(srcdir)/%reldir%/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.out \
+ $(srcdir)/%reldir%/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.err \
+ $(srcdir)/%reldir%/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.out \
+ $(srcdir)/%reldir%/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.err \
+ $(srcdir)/%reldir%/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.out \
+ $(srcdir)/%reldir%/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.err \
+ $(srcdir)/%reldir%/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.out \
+ $(srcdir)/%reldir%/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.err \
+ $(srcdir)/%reldir%/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.out \
+ $(srcdir)/%reldir%/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.err \
+ $(srcdir)/%reldir%/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.out \
+ $(srcdir)/%reldir%/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.err \
+ $(srcdir)/%reldir%/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.out \
+ $(srcdir)/%reldir%/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.err \
+ $(srcdir)/%reldir%/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.out \
+ $(srcdir)/%reldir%/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.err \
+ $(srcdir)/%reldir%/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.out \
+ $(srcdir)/%reldir%/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.err \
+ $(srcdir)/%reldir%/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.out \
+ $(srcdir)/%reldir%/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.err \
+ $(srcdir)/%reldir%/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out \
+ $(srcdir)/%reldir%/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err \
+ $(srcdir)/%reldir%/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out \
+ $(srcdir)/%reldir%/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err \
+ $(srcdir)/%reldir%/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.out \
+ $(srcdir)/%reldir%/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.err \
+ $(srcdir)/%reldir%/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.out \
+ $(srcdir)/%reldir%/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.err \
+ $(srcdir)/%reldir%/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.out \
+ $(srcdir)/%reldir%/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.err \
+ $(srcdir)/%reldir%/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.out \
+ $(srcdir)/%reldir%/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.err \
+ $(srcdir)/%reldir%/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.out \
+ $(srcdir)/%reldir%/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.err \
+ $(srcdir)/%reldir%/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out \
+ $(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err \
+ $(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out \
+ $(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err \
+ $(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out \
+ $(srcdir)/%reldir%/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err \
+ $(srcdir)/%reldir%/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.out \
+ $(srcdir)/%reldir%/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.err \
+ $(srcdir)/%reldir%/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.out \
+ $(srcdir)/%reldir%/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.err \
+ $(srcdir)/%reldir%/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.out \
+ $(srcdir)/%reldir%/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.err \
+ $(srcdir)/%reldir%/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.out \
+ $(srcdir)/%reldir%/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.err \
+ $(srcdir)/%reldir%/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.out \
+ $(srcdir)/%reldir%/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.err \
+ $(srcdir)/%reldir%/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.out \
+ $(srcdir)/%reldir%/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.err \
+ $(srcdir)/%reldir%/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.out \
+ $(srcdir)/%reldir%/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.err \
+ $(srcdir)/%reldir%/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.out \
+ $(srcdir)/%reldir%/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.err \
+ $(srcdir)/%reldir%/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.out \
+ $(srcdir)/%reldir%/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.err \
+ $(srcdir)/%reldir%/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.out \
+ $(srcdir)/%reldir%/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.err \
+ $(srcdir)/%reldir%/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.out \
+ $(srcdir)/%reldir%/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.err \
+ $(srcdir)/%reldir%/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.out \
+ $(srcdir)/%reldir%/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.err \
+ $(srcdir)/%reldir%/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.out \
+ $(srcdir)/%reldir%/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.err \
+ $(srcdir)/%reldir%/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.out \
+ $(srcdir)/%reldir%/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.err \
+ $(srcdir)/%reldir%/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.out \
+ $(srcdir)/%reldir%/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.err \
+ $(srcdir)/%reldir%/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.out \
+ $(srcdir)/%reldir%/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.err \
+ $(srcdir)/%reldir%/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.out \
+ $(srcdir)/%reldir%/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.err \
+ $(srcdir)/%reldir%/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.out \
+ $(srcdir)/%reldir%/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.err \
+ $(srcdir)/%reldir%/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.err \
+ $(srcdir)/%reldir%/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.out \
+ $(srcdir)/%reldir%/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.err \
+ $(srcdir)/%reldir%/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.out \
+ $(srcdir)/%reldir%/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.err \
+ $(srcdir)/%reldir%/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.out \
+ $(srcdir)/%reldir%/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.err \
+ $(srcdir)/%reldir%/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.out \
+ $(srcdir)/%reldir%/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.err \
+ $(srcdir)/%reldir%/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.out \
+ $(srcdir)/%reldir%/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.err \
+ $(srcdir)/%reldir%/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.err \
+ $(srcdir)/%reldir%/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.out \
+ $(srcdir)/%reldir%/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.err \
+ $(srcdir)/%reldir%/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.err \
+ $(srcdir)/%reldir%/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.out \
+ $(srcdir)/%reldir%/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.err \
+ $(srcdir)/%reldir%/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.out \
+ $(srcdir)/%reldir%/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.err \
+ $(srcdir)/%reldir%/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.out \
+ $(srcdir)/%reldir%/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.err \
+ $(srcdir)/%reldir%/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.out \
+ $(srcdir)/%reldir%/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.err \
+ $(srcdir)/%reldir%/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out \
+ $(srcdir)/%reldir%/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.err \
+ $(srcdir)/%reldir%/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.out \
+ $(srcdir)/%reldir%/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.err \
+ $(srcdir)/%reldir%/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.out \
+ $(srcdir)/%reldir%/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.err \
+ $(srcdir)/%reldir%/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.out \
+ $(srcdir)/%reldir%/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.err \
+ $(srcdir)/%reldir%/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.out \
+ $(srcdir)/%reldir%/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.err \
+ $(srcdir)/%reldir%/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.out \
+ $(srcdir)/%reldir%/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.err \
+ $(srcdir)/%reldir%/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.out \
+ $(srcdir)/%reldir%/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.err \
+ $(srcdir)/%reldir%/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.out \
+ $(srcdir)/%reldir%/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.err \
+ $(srcdir)/%reldir%/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.out \
+ $(srcdir)/%reldir%/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.err \
+ $(srcdir)/%reldir%/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.out \
+ $(srcdir)/%reldir%/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.err \
+ $(srcdir)/%reldir%/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.out \
+ $(srcdir)/%reldir%/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.err \
+ $(srcdir)/%reldir%/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.out \
+ $(srcdir)/%reldir%/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.err \
+ $(srcdir)/%reldir%/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.out \
+ $(srcdir)/%reldir%/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err \
+ $(srcdir)/%reldir%/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out \
+ $(srcdir)/%reldir%/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err \
+ $(srcdir)/%reldir%/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out \
+ $(srcdir)/%reldir%/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err \
+ $(srcdir)/%reldir%/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out \
+ $(srcdir)/%reldir%/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.err \
+ $(srcdir)/%reldir%/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.out \
+ $(srcdir)/%reldir%/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.err \
+ $(srcdir)/%reldir%/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.out \
+ $(srcdir)/%reldir%/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.err \
+ $(srcdir)/%reldir%/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.out \
+ $(srcdir)/%reldir%/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.err \
+ $(srcdir)/%reldir%/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out \
+ $(srcdir)/%reldir%/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err \
+ $(srcdir)/%reldir%/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out \
+ $(srcdir)/%reldir%/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err \
+ $(srcdir)/%reldir%/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out \
+ $(srcdir)/%reldir%/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err \
+ $(srcdir)/%reldir%/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.out \
+ $(srcdir)/%reldir%/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.err \
+ $(srcdir)/%reldir%/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.out \
+ $(srcdir)/%reldir%/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.err \
+ $(srcdir)/%reldir%/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.out \
+ $(srcdir)/%reldir%/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.err \
+ $(srcdir)/%reldir%/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.out \
+ $(srcdir)/%reldir%/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.err \
+ $(srcdir)/%reldir%/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.out \
+ $(srcdir)/%reldir%/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.err \
+ $(srcdir)/%reldir%/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.out \
+ $(srcdir)/%reldir%/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.err \
+ $(srcdir)/%reldir%/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.out \
+ $(srcdir)/%reldir%/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.err \
+ $(srcdir)/%reldir%/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.out \
+ $(srcdir)/%reldir%/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.err \
+ $(srcdir)/%reldir%/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.out \
+ $(srcdir)/%reldir%/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.err \
+ $(srcdir)/%reldir%/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.out \
+ $(srcdir)/%reldir%/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.err \
+ $(srcdir)/%reldir%/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out \
+ $(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err \
+ $(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out \
+ $(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err \
+ $(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out \
+ $(srcdir)/%reldir%/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err \
+ $(srcdir)/%reldir%/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out \
+ $(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err \
+ $(srcdir)/%reldir%/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out \
+ $(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err \
+ $(srcdir)/%reldir%/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out \
+ $(srcdir)/%reldir%/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err \
+ $(srcdir)/%reldir%/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.out \
+ $(srcdir)/%reldir%/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.err \
+ $(srcdir)/%reldir%/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.out \
+ $(srcdir)/%reldir%/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.err \
+ $(srcdir)/%reldir%/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.out \
+ $(srcdir)/%reldir%/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.err \
+ $(srcdir)/%reldir%/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.out \
+ $(srcdir)/%reldir%/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.err \
+ $(srcdir)/%reldir%/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.out \
+ $(srcdir)/%reldir%/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.err \
+ $(srcdir)/%reldir%/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.out \
+ $(srcdir)/%reldir%/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.err \
+ $(srcdir)/%reldir%/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.out \
+ $(srcdir)/%reldir%/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.err \
+ $(srcdir)/%reldir%/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.out \
+ $(srcdir)/%reldir%/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.err \
+ $(srcdir)/%reldir%/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.out \
+ $(srcdir)/%reldir%/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.err \
+ $(srcdir)/%reldir%/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.out \
+ $(srcdir)/%reldir%/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.err \
+ $(srcdir)/%reldir%/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.out \
+ $(srcdir)/%reldir%/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.err \
+ $(srcdir)/%reldir%/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.out \
+ $(srcdir)/%reldir%/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.err \
+ $(srcdir)/%reldir%/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.out \
+ $(srcdir)/%reldir%/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.err \
+ $(srcdir)/%reldir%/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.out \
+ $(srcdir)/%reldir%/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.err \
+ $(srcdir)/%reldir%/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.out \
+ $(srcdir)/%reldir%/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.err \
+ $(srcdir)/%reldir%/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.out \
+ $(srcdir)/%reldir%/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.err \
+ $(srcdir)/%reldir%/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.out \
+ $(srcdir)/%reldir%/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.err \
+ $(srcdir)/%reldir%/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.out \
+ $(srcdir)/%reldir%/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.err \
+ $(srcdir)/%reldir%/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.out \
+ $(srcdir)/%reldir%/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.err \
+ $(srcdir)/%reldir%/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.out \
+ $(srcdir)/%reldir%/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.err \
+ $(srcdir)/%reldir%/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.out \
+ $(srcdir)/%reldir%/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.err \
+ $(srcdir)/%reldir%/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out \
+ $(srcdir)/%reldir%/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.err \
+ $(srcdir)/%reldir%/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.out \
+ $(srcdir)/%reldir%/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.err \
+ $(srcdir)/%reldir%/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.out \
+ $(srcdir)/%reldir%/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.err \
+ $(srcdir)/%reldir%/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.out \
+ $(srcdir)/%reldir%/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.err \
+ $(srcdir)/%reldir%/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.out \
+ $(srcdir)/%reldir%/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.err \
+ $(srcdir)/%reldir%/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.out \
+ $(srcdir)/%reldir%/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.err \
+ $(srcdir)/%reldir%/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.out \
+ $(srcdir)/%reldir%/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.err \
+ $(srcdir)/%reldir%/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out \
+ $(srcdir)/%reldir%/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err \
+ $(srcdir)/%reldir%/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out \
+ $(srcdir)/%reldir%/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.err \
+ $(srcdir)/%reldir%/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out \
+ $(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err \
+ $(srcdir)/%reldir%/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out \
+ $(srcdir)/%reldir%/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err \
+ $(srcdir)/%reldir%/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out \
+ $(srcdir)/%reldir%/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err \
+ $(srcdir)/%reldir%/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.out \
+ $(srcdir)/%reldir%/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.err \
+ $(srcdir)/%reldir%/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.out \
+ $(srcdir)/%reldir%/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.err \
+ $(srcdir)/%reldir%/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.out \
+ $(srcdir)/%reldir%/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.err \
+ $(srcdir)/%reldir%/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.out \
+ $(srcdir)/%reldir%/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.err \
+ $(srcdir)/%reldir%/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.out \
+ $(srcdir)/%reldir%/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.err \
+ $(srcdir)/%reldir%/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.out \
+ $(srcdir)/%reldir%/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.err \
+ $(srcdir)/%reldir%/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.out \
+ $(srcdir)/%reldir%/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.err \
+ $(srcdir)/%reldir%/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.out \
+ $(srcdir)/%reldir%/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.err \
+ $(srcdir)/%reldir%/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.out \
+ $(srcdir)/%reldir%/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.err \
+ $(srcdir)/%reldir%/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.out \
+ $(srcdir)/%reldir%/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.err \
+ $(srcdir)/%reldir%/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.out \
+ $(srcdir)/%reldir%/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.err \
+ $(srcdir)/%reldir%/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.out \
+ $(srcdir)/%reldir%/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.err \
+ $(srcdir)/%reldir%/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.out \
+ $(srcdir)/%reldir%/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.err \
+ $(srcdir)/%reldir%/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.out \
+ $(srcdir)/%reldir%/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.err \
+ $(srcdir)/%reldir%/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.out \
+ $(srcdir)/%reldir%/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.err \
+ $(srcdir)/%reldir%/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out \
+ $(srcdir)/%reldir%/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.err \
+ $(srcdir)/%reldir%/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.out \
+ $(srcdir)/%reldir%/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err \
+ $(srcdir)/%reldir%/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out \
+ $(srcdir)/%reldir%/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err \
+ $(srcdir)/%reldir%/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out \
+ $(srcdir)/%reldir%/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err \
+ $(srcdir)/%reldir%/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out \
+ $(srcdir)/%reldir%/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err \
+ $(srcdir)/%reldir%/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.out \
+ $(srcdir)/%reldir%/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.err \
+ $(srcdir)/%reldir%/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.out \
+ $(srcdir)/%reldir%/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.err \
+ $(srcdir)/%reldir%/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.out \
+ $(srcdir)/%reldir%/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.err \
+ $(srcdir)/%reldir%/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.out \
+ $(srcdir)/%reldir%/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err \
+ $(srcdir)/%reldir%/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out \
+ $(srcdir)/%reldir%/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err \
+ $(srcdir)/%reldir%/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out \
+ $(srcdir)/%reldir%/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err \
+ $(srcdir)/%reldir%/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.out \
+ $(srcdir)/%reldir%/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.err \
+ $(srcdir)/%reldir%/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.out \
+ $(srcdir)/%reldir%/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.err \
+ $(srcdir)/%reldir%/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out \
+ $(srcdir)/%reldir%/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err \
+ $(srcdir)/%reldir%/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out \
+ $(srcdir)/%reldir%/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err \
+ $(srcdir)/%reldir%/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out \
+ $(srcdir)/%reldir%/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err \
+ $(srcdir)/%reldir%/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out \
+ $(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err \
+ $(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out \
+ $(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.err \
+ $(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.out \
+ $(srcdir)/%reldir%/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err \
+ $(srcdir)/%reldir%/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.out \
+ $(srcdir)/%reldir%/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.err \
+ $(srcdir)/%reldir%/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.out \
+ $(srcdir)/%reldir%/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.err \
+ $(srcdir)/%reldir%/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.out \
+ $(srcdir)/%reldir%/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.err \
+ $(srcdir)/%reldir%/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.out \
+ $(srcdir)/%reldir%/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.err \
+ $(srcdir)/%reldir%/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.out \
+ $(srcdir)/%reldir%/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.err \
+ $(srcdir)/%reldir%/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.out \
+ $(srcdir)/%reldir%/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.err \
+ $(srcdir)/%reldir%/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.out \
+ $(srcdir)/%reldir%/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err \
+ $(srcdir)/%reldir%/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.out \
+ $(srcdir)/%reldir%/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.err \
+ $(srcdir)/%reldir%/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.out \
+ $(srcdir)/%reldir%/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.err \
+ $(srcdir)/%reldir%/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.out \
+ $(srcdir)/%reldir%/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.err \
+ $(srcdir)/%reldir%/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.out \
+ $(srcdir)/%reldir%/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.err \
+ $(srcdir)/%reldir%/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.out \
+ $(srcdir)/%reldir%/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.err \
+ $(srcdir)/%reldir%/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.out \
+ $(srcdir)/%reldir%/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err \
+ $(srcdir)/%reldir%/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.out \
+ $(srcdir)/%reldir%/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err \
+ $(srcdir)/%reldir%/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.out \
+ $(srcdir)/%reldir%/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err \
+ $(srcdir)/%reldir%/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.out \
+ $(srcdir)/%reldir%/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.err \
+ $(srcdir)/%reldir%/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.out \
+ $(srcdir)/%reldir%/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.err \
+ $(srcdir)/%reldir%/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.out \
+ $(srcdir)/%reldir%/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.err \
+ $(srcdir)/%reldir%/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.out \
+ $(srcdir)/%reldir%/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err \
+ $(srcdir)/%reldir%/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.out \
+ $(srcdir)/%reldir%/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err \
+ $(srcdir)/%reldir%/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.out \
+ $(srcdir)/%reldir%/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.err \
+ $(srcdir)/%reldir%/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.out \
+ $(srcdir)/%reldir%/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.err \
+ $(srcdir)/%reldir%/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.out \
+ $(srcdir)/%reldir%/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err \
+ $(srcdir)/%reldir%/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.out \
+ $(srcdir)/%reldir%/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.err \
+ $(srcdir)/%reldir%/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.out \
+ $(srcdir)/%reldir%/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.err \
+ $(srcdir)/%reldir%/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.out \
+ $(srcdir)/%reldir%/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.err \
+ $(srcdir)/%reldir%/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.out \
+ $(srcdir)/%reldir%/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err \
+ $(srcdir)/%reldir%/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.out \
+ $(srcdir)/%reldir%/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.err \
+ $(srcdir)/%reldir%/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.out \
+ $(srcdir)/%reldir%/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.err \
+ $(srcdir)/%reldir%/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.out \
+ $(srcdir)/%reldir%/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.err \
+ $(srcdir)/%reldir%/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.out \
+ $(srcdir)/%reldir%/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.err \
+ $(srcdir)/%reldir%/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.out \
+ $(srcdir)/%reldir%/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.err \
+ $(srcdir)/%reldir%/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out \
+ $(srcdir)/%reldir%/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err \
+ $(srcdir)/%reldir%/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out \
+ $(srcdir)/%reldir%/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err \
+ $(srcdir)/%reldir%/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out \
+ $(srcdir)/%reldir%/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.err \
+ $(srcdir)/%reldir%/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.out \
+ $(srcdir)/%reldir%/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.err \
+ $(srcdir)/%reldir%/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.out \
+ $(srcdir)/%reldir%/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.err \
+ $(srcdir)/%reldir%/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.out \
+ $(srcdir)/%reldir%/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.err \
+ $(srcdir)/%reldir%/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.out \
+ $(srcdir)/%reldir%/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.err \
+ $(srcdir)/%reldir%/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.out \
+ $(srcdir)/%reldir%/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.err \
+ $(srcdir)/%reldir%/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.out \
+ $(srcdir)/%reldir%/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.err \
+ $(srcdir)/%reldir%/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.out \
+ $(srcdir)/%reldir%/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err \
+ $(srcdir)/%reldir%/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.out \
+ $(srcdir)/%reldir%/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.err \
+ $(srcdir)/%reldir%/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.out \
+ $(srcdir)/%reldir%/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.err \
+ $(srcdir)/%reldir%/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.out \
+ $(srcdir)/%reldir%/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.err \
+ $(srcdir)/%reldir%/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.out \
+ $(srcdir)/%reldir%/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.err \
+ $(srcdir)/%reldir%/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.out \
+ $(srcdir)/%reldir%/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.err \
+ $(srcdir)/%reldir%/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.out \
+ $(srcdir)/%reldir%/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.err \
+ $(srcdir)/%reldir%/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.out \
+ $(srcdir)/%reldir%/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.err \
+ $(srcdir)/%reldir%/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.out \
+ $(srcdir)/%reldir%/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.err \
+ $(srcdir)/%reldir%/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.out \
+ $(srcdir)/%reldir%/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.err \
+ $(srcdir)/%reldir%/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.out \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.err \
+ $(srcdir)/%reldir%/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.out \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.err \
+ $(srcdir)/%reldir%/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.out \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.err \
+ $(srcdir)/%reldir%/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.out \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.err \
+ $(srcdir)/%reldir%/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.out \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.err \
+ $(srcdir)/%reldir%/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.out \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.err \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.out \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.err \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.out \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.err \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.out \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.err \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.out \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.err \
+ $(srcdir)/%reldir%/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.out \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.err \
+ $(srcdir)/%reldir%/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.out \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.err \
+ $(srcdir)/%reldir%/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.out \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err \
+ $(srcdir)/%reldir%/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.out \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.err \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.out \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.err \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.out \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.err \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.out \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.err \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err \
+ $(srcdir)/%reldir%/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out \
+ $(srcdir)/%reldir%/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.err \
+ $(srcdir)/%reldir%/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.out \
+ $(srcdir)/%reldir%/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.err \
+ $(srcdir)/%reldir%/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.out \
+ $(srcdir)/%reldir%/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err \
+ $(srcdir)/%reldir%/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out \
+ $(srcdir)/%reldir%/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.err \
+ $(srcdir)/%reldir%/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out \
+ $(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err \
+ $(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out \
+ $(srcdir)/%reldir%/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.err \
+ $(srcdir)/%reldir%/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.out \
+ $(srcdir)/%reldir%/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.err \
+ $(srcdir)/%reldir%/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.out \
+ $(srcdir)/%reldir%/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err \
+ $(srcdir)/%reldir%/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out \
+ $(srcdir)/%reldir%/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err \
+ $(srcdir)/%reldir%/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out \
+ $(srcdir)/%reldir%/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.err \
+ $(srcdir)/%reldir%/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.out \
+ $()
diff --git a/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.err b/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.err
diff --git a/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.out b/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.out
new file mode 100644
index 0000000..3b130be
--- /dev/null
+++ b/test/expected/test_cli.sh_17a68b798354f9a6cdfab372006caeb74038d15c.out
@@ -0,0 +1 @@
+2021-07-03T21:49:29 Test
diff --git a/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.err b/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.err
diff --git a/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.out b/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.out
new file mode 100644
index 0000000..4c63930
--- /dev/null
+++ b/test/expected/test_cli.sh_5524542b1a6954ff9741155101497270a2f0c557.out
@@ -0,0 +1 @@
+a a a
diff --git a/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.err b/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.err
new file mode 100644
index 0000000..9d07883
--- /dev/null
+++ b/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.err
@@ -0,0 +1,8 @@
+✘ error: invalid value for “-c” option
+ --> command-line argument
+ |  -c foo 
+ |  ^ command type prefix is missing
+ = help: command arguments must start with one of the following symbols to denote the type of command:
+ : - an lnav command (e.g. :goto 42)
+ ; - an SQL statement (e.g. ;SELECT * FROM syslog_log)
+ | - an lnav script (e.g. |rename-stdin foo)
diff --git a/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.out b/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cli.sh_97e19b9ff3775d84074455a2e8993a0611b1c269.out
diff --git a/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.err b/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.err
diff --git a/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.out b/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.out
new file mode 100644
index 0000000..1e0a993
--- /dev/null
+++ b/test/expected/test_cli.sh_a1a09f890f4604309d0a81bbbec8e50fb7d5e887.out
@@ -0,0 +1,3 @@
+2013-06-06T19:13:20.123 Hello, World!
+2013-06-06T19:13:20.123 Goodbye, World!
+2013-06-06T19:13:20.123 ---- END-OF-STDIN ----
diff --git a/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.err b/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.err
diff --git a/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.out b/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.out
new file mode 100644
index 0000000..751c83b
--- /dev/null
+++ b/test/expected/test_cli.sh_f2e41555f1a5f40f54ce241207af602ed1503a2b.out
@@ -0,0 +1,2 @@
+filepath lines 
+stdin   4 
diff --git a/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err
new file mode 100644
index 0000000..0d53487
--- /dev/null
+++ b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.err
@@ -0,0 +1,6 @@
+✘ error: no log files loaded
+ --> command-option:2
+ | :close 
+ = help: :close
+ ══════════════════════════════════════════════════════════════════════
+ Close the top file in the view
diff --git a/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.out b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_017b495b95218b7c083951e2dba331cfec6e90be.out
diff --git a/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.err b/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.err
diff --git a/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.out b/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.out
new file mode 100644
index 0000000..689436e
--- /dev/null
+++ b/test/expected/test_cmds.sh_0b1e4b1523dfca71927b1fe721c74490c51361d1.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:21:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:21:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:21:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.err b/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.err
diff --git a/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.out b/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.out
new file mode 100644
index 0000000..ccd015e
--- /dev/null
+++ b/test/expected/test_cmds.sh_0b41fe57743ba0be088037d9ba29bc465e7c9bf9.out
@@ -0,0 +1,3 @@
+c1,c2
+1,"Hello
+World!"
diff --git a/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.err b/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.err
diff --git a/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.out b/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_0f0ab532d8d845f8201af65bf5f6fc994e21a8aa.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.err b/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.err
diff --git a/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.out b/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_109a44ac6a8f1be2736c8e9c47aeed187e0581ee.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.err b/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.err
diff --git a/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.out b/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.out
new file mode 100644
index 0000000..d18c6b1
--- /dev/null
+++ b/test/expected/test_cmds.sh_12856706bfb4a8e2686098dd2644a7989d370b02.out
@@ -0,0 +1 @@
+How are you?
diff --git a/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.err b/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.err
new file mode 100644
index 0000000..f90b5d3
--- /dev/null
+++ b/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.err
@@ -0,0 +1,7 @@
+✘ error: call to timeslice(time, slice) failed
+ reason: unable to parse time slice value: bad -- Unrecognized input
+ --> command-option:1
+ | :filter-expr timeslice(:log_time_msecs, 'bad') is not null
+ = help: :filter-expr expr
+ ══════════════════════════════════════════════════════════════════════
+ Set the filter expression
diff --git a/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.out b/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_12b4cb9bd6586f9694100db76734b19a75158eab.out
diff --git a/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.err b/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.err
diff --git a/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.out b/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_145126309709179759926289caf729703ef6e1c6.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.err b/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.err
diff --git a/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.out b/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.out
new file mode 100644
index 0000000..6ebd88b
--- /dev/null
+++ b/test/expected/test_cmds.sh_148007d2626b3c92d00ac31639b6918b1fc4aa60.out
@@ -0,0 +1,2 @@
+Hello, World!
+-07-20 22:59:30,221:ERROR:Goodbye, Bork!
diff --git a/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.err b/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.err
diff --git a/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.out b/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.out
new file mode 100644
index 0000000..45e6c41
--- /dev/null
+++ b/test/expected/test_cmds.sh_1cab7d240cf85ff2c3538f5a06af141b01bc83ad.out
@@ -0,0 +1,3 @@
+-07-20 22:59:27,672:DEBUG:Hello, Bork!
+ How are you today?
+-07-20 22:59:30,221:ERROR:Goodbye, Bork!
diff --git a/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.err b/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.err
diff --git a/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.out b/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.out
new file mode 100644
index 0000000..6dfcc1c
--- /dev/null
+++ b/test/expected/test_cmds.sh_1d92c5bc12f5e7aaa6d84c5ed47f0b9f96e36c6a.out
@@ -0,0 +1,68 @@
+[
+ {
+ "log_line": 0,
+ "log_part": null,
+ "log_time": "2009-07-20 22:59:26.000",
+ "log_idle_msecs": 0,
+ "log_level": "info",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "c_ip": "192.168.202.254",
+ "cs_method": "GET",
+ "cs_referer": "-",
+ "cs_uri_query": null,
+ "cs_uri_stem": "/vmw/cgi/tramp",
+ "cs_user_agent": "gPXE/0.9.7",
+ "cs_username": "-",
+ "cs_version": "HTTP/1.0",
+ "sc_bytes": 134,
+ "sc_status": 200,
+ "cs_host": null
+ },
+ {
+ "log_line": 1,
+ "log_part": null,
+ "log_time": "2009-07-20 22:59:29.000",
+ "log_idle_msecs": 3000,
+ "log_level": "error",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "c_ip": "192.168.202.254",
+ "cs_method": "GET",
+ "cs_referer": "-",
+ "cs_uri_query": null,
+ "cs_uri_stem": "/vmw/vSphere/default/vmkboot.gz",
+ "cs_user_agent": "gPXE/0.9.7",
+ "cs_username": "-",
+ "cs_version": "HTTP/1.0",
+ "sc_bytes": 46210,
+ "sc_status": 404,
+ "cs_host": null
+ },
+ {
+ "log_line": 2,
+ "log_part": null,
+ "log_time": "2009-07-20 22:59:29.000",
+ "log_idle_msecs": 0,
+ "log_level": "info",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "c_ip": "192.168.202.254",
+ "cs_method": "GET",
+ "cs_referer": "-",
+ "cs_uri_query": null,
+ "cs_uri_stem": "/vmw/vSphere/default/vmkernel.gz",
+ "cs_user_agent": "gPXE/0.9.7",
+ "cs_username": "-",
+ "cs_version": "HTTP/1.0",
+ "sc_bytes": 78929,
+ "sc_status": 200,
+ "cs_host": null
+ }
+]
diff --git a/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.err b/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.err
new file mode 100644
index 0000000..52606d5
--- /dev/null
+++ b/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.err
@@ -0,0 +1,6 @@
+✘ error: highlight does not exist -- foobar
+ --> command-option:1
+ | :clear-highlight foobar 
+ = help: :clear-highlight pattern
+ ══════════════════════════════════════════════════════════════════════
+ Remove a previously set highlight regular expression
diff --git a/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.out b/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_1e1c8492b295913ce5afcd104cde0ec4ca1dcdac.out
diff --git a/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.err b/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.err
diff --git a/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.out b/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_1f53f5b16c7c5aa695ed2e6427d822a1b940fcf4.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.err b/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.err
diff --git a/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.out b/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_22577861cb0921a7e7f3d1af6485938f4930ba7b.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.err b/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.err
diff --git a/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.out b/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.out
new file mode 100644
index 0000000..83f15c5
--- /dev/null
+++ b/test/expected/test_cmds.sh_2339d09953b6937981d8a448000c3fdc2837f8c4.out
@@ -0,0 +1,12 @@
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: Joining mDNS multicast group on interface virbr0.IPv4 with address 192.168.122.1.
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: New relevant interface virbr0.IPv4 for mDNS.
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: Registering new address record for 192.168.122.1 on virbr0.IPv4.
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: started, version 2.68 cachesize 150
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: DHCP, IP range 192.168.122.2 -- 192.168.122.254, lease time 1h
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: DHCP, sockets bound exclusively to interface virbr0
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: reading /etc/resolv.conf
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: using nameserver 192.168.1.1#53
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: read /etc/hosts - 5 addresses
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: read /var/lib/libvirt/dnsmasq/default.hostsfile
diff --git a/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.err b/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.err
diff --git a/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.out b/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2539ff9c4dbed93df3f0408ccc5fd81df34d1193.out
diff --git a/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.err b/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.err
diff --git a/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.out b/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.out
new file mode 100644
index 0000000..721d34f
--- /dev/null
+++ b/test/expected/test_cmds.sh_29f0c808f4e93c6ef3890e6b793bee274a5b36ca.out
@@ -0,0 +1 @@
+Hello, $XYZ!
diff --git a/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.err b/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.err
diff --git a/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.out b/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.out
new file mode 100644
index 0000000..b693f51
--- /dev/null
+++ b/test/expected/test_cmds.sh_2a449c0a43e895e85c8b1c9547f32d7b5b4f84f6.out
@@ -0,0 +1 @@
+/ui/clock-format = "%Y-%m-%dT%H:%M:%S %Z"
diff --git a/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.err b/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.err
diff --git a/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.out b/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.out
new file mode 100644
index 0000000..6ae2e70
--- /dev/null
+++ b/test/expected/test_cmds.sh_2a535de164de4c060d2bff34aa7cc75ac7cac2c2.out
@@ -0,0 +1,2 @@
+2009-07-20 22:59:27,672:DEBUG:Hello, World!
+ How are you today?
diff --git a/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.err b/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.err
new file mode 100644
index 0000000..30a1ac4
--- /dev/null
+++ b/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.err
@@ -0,0 +1,6 @@
+✘ error: expecting file name or '-' to write to the terminal
+ --> command-option:1
+ | :write-to 
+ = help: :write-to [--anonymize] path
+ ══════════════════════════════════════════════════════════════════════
+ Overwrite the given file with any marked lines in the current view
diff --git a/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.out b/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2cd167954a3be3e130e5f9601b72794a856cef92.out
diff --git a/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.err b/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.err
diff --git a/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out b/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out
new file mode 100644
index 0000000..8d4265f
--- /dev/null
+++ b/test/expected/test_cmds.sh_2de9ec294e2f533d13e04c70d9525f8b58d47bb2.out
@@ -0,0 +1,2 @@
+Hello, World!
+Goodbye, World!
diff --git a/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err b/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.err
diff --git a/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out b/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out
new file mode 100644
index 0000000..8c91cd9
--- /dev/null
+++ b/test/expected/test_cmds.sh_2e123104cdd2087ac40731a0aa533ba6a87ea744.out
@@ -0,0 +1 @@
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
diff --git a/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err b/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.err
diff --git a/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out b/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out
new file mode 100644
index 0000000..3f55261
--- /dev/null
+++ b/test/expected/test_cmds.sh_2e67bdbbc9a14aa772b2a9f755ed8f8124708558.out
@@ -0,0 +1,23 @@
+Apr 7 00:49:42 Tim-Abaft-iMac abashed[0]: Aberrant [abhorrent5701Aberrant]: Link up on en0, 1-Aboard, Full-abortive, Abounding flow-abrupt, Absent [796d,2301,0de1,0300,cde1,3800]
+Apr 7 05:49:53 Tim-Abaft-iMac.absorbing Abstracted[17212]: -[absurd abundant] absurd abusive accept: <acceptable:0x511f30
+ accessible=<KSOmahaServer:0x510d80>
+ url="https://achondroplasia.example.com/account/accurate2"
+ achiever=0
+ acid=1
+ acidic=1
+ acoustic=1
+ body=
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <o:gupdate xmlns:o="http://acinetobacter-infections.example.com/accurate2/acrid" protocol="2.0" version="Act-1.2.0.7709" ismachine="1" requestid="{1ca0a968-cbe9-e75b-d00b-4859609878ea}">
+ <o:os platform="mac" version="activity" sp="10.10.2_x86_64h"></o:os>
+ <o:app appid="com.actually.Ad hoc" version="1.2.0.7709" lang="en-us" installage="180" brand="GGLG">
+ <o:ping r="1" a="1"></o:ping>
+ <o:updatecheck></o:updatecheck>
+ </o:app>
+ </o:gupdate>
+ >
+Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: ADDICTED: The Adhesive adjoining adjustment is admit 10.9.2 adorable of 10.10.2. Use advice's afford afraid to get afterthought aggressive agonizing agree
+ Call agreement:
+Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: 0 Ahead 0x00007fff8a9b3d9b ___Adhesive_Air_airplane_airport + 113
+Apr 7 07:31:56 Tim-Abaft-iMac.absorbing Add[36403]: 1 ajar.alarm 0x00007fff8bc84c13 _alcoholic_alert_alike + 8
+Apr 7 07:32:56 Tim-Abaft-iMac.absorbing alive[234]: Bad data { abc, 123, 456 )}]
diff --git a/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err b/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.err
diff --git a/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out b/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out
new file mode 100644
index 0000000..c6eedf2
--- /dev/null
+++ b/test/expected/test_cmds.sh_2ff0fe712c9b0012e42282c5f77b0b83cad37ddf.out
@@ -0,0 +1 @@
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
diff --git a/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err b/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.err
diff --git a/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.out b/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.out
new file mode 100644
index 0000000..8735c57
--- /dev/null
+++ b/test/expected/test_cmds.sh_305b1dfdfe785b945df4220aad6671ae1d364f55.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.err b/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.err
diff --git a/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.out b/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_3429080ed14d01c6a887900186f37750df0d5ff0.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.err b/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.err
diff --git a/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.out b/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.out
new file mode 100644
index 0000000..8ab686e
--- /dev/null
+++ b/test/expected/test_cmds.sh_34a6bcaa2877471b8ea718374101fa9ce3b78235.out
@@ -0,0 +1 @@
+Hello, World!
diff --git a/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.err b/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.err
diff --git a/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.out b/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.out
new file mode 100644
index 0000000..fc2b6b9
--- /dev/null
+++ b/test/expected/test_cmds.sh_35b0dd8a030396742bc5acfde7715fb19f312f29.out
@@ -0,0 +1,3 @@
+/ui/clock-format = "%Y-%m-%dT%H:%M:%S %Z"
+info: changed config option -- /ui/clock-format
+/ui/clock-format = "abc"
diff --git a/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.err b/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.err
new file mode 100644
index 0000000..28d2b21
--- /dev/null
+++ b/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.err
@@ -0,0 +1,7 @@
+✘ error: invalid filter expression: :sc_bytes # ff
+ reason: unrecognized token: "#"
+ --> command-option:1
+ | :filter-expr :sc_bytes # ff 
+ = help: :filter-expr expr
+ ══════════════════════════════════════════════════════════════════════
+ Set the filter expression
diff --git a/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.out b/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_36800217930a6a30e68c4efb20f6959c4f71aeb0.out
diff --git a/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.err b/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.err
diff --git a/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out b/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out
new file mode 100644
index 0000000..9ea386d
--- /dev/null
+++ b/test/expected/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET ⋮ HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET ⋮ HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET ⋮ HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err b/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err
diff --git a/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out b/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err b/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err
diff --git a/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out b/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out
new file mode 100644
index 0000000..dcd3557
--- /dev/null
+++ b/test/expected/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out
@@ -0,0 +1,2 @@
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
diff --git a/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err b/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err
diff --git a/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.out b/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.out
new file mode 100644
index 0000000..8d4265f
--- /dev/null
+++ b/test/expected/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.out
@@ -0,0 +1,2 @@
+Hello, World!
+Goodbye, World!
diff --git a/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.err b/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.err
diff --git a/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.out b/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_4dbe20c11056a07d2c7efb5ed15903050d628216.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.err b/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.err
diff --git a/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.out b/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.out
new file mode 100644
index 0000000..ef822cd
--- /dev/null
+++ b/test/expected/test_cmds.sh_4f06183ed231669965965f5042fbbb507fa7deab.out
@@ -0,0 +1,3 @@
+2009-07-20 22:59:27,672:DEBUG:Hello, World!
+ How are you today?
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
diff --git a/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.err b/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.err
new file mode 100644
index 0000000..60db783
--- /dev/null
+++ b/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.err
@@ -0,0 +1,5 @@
+✘ error: cannot open file: /non-existent
+ reason: No such file or directory
+ --> command-option:2
+ | :open /non-existent 
+ = help: make sure the file exists and is accessible
diff --git a/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.out b/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_512872aebaae73ca4f33fa93acb2f4e3b018f8b4.out
diff --git a/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.err b/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.err
diff --git a/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.out b/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.out
new file mode 100644
index 0000000..39589f4
--- /dev/null
+++ b/test/expected/test_cmds.sh_53a9686102f69b07b034df291f554a00b265ed20.out
@@ -0,0 +1,2 @@
+toplevel here 123 456
+nested here nested.lnav abc 789
diff --git a/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.err b/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.err
new file mode 100644
index 0000000..e90b75a
--- /dev/null
+++ b/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.err
@@ -0,0 +1,4 @@
+✘ error: unknown bookmark type: foobar
+ --> command-option:2
+ | :next-mark foobar 
+ = help: available types: error, file, meta, search, user, user-expr, warning
diff --git a/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.out b/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_55c2fd15ec2c7d96dbef7b36a42a1b7b42f90dbc.out
diff --git a/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.err b/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.err
diff --git a/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.out b/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_5bfd08c1639701476d7b9348c36afd46fdbe6f2a.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.err b/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.err
diff --git a/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.out b/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.out
new file mode 100644
index 0000000..565e1c6
--- /dev/null
+++ b/test/expected/test_cmds.sh_624a41e152675575f4b07c19b2cf0e3a028429a2.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.err b/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.err
diff --git a/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.out b/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.out
new file mode 100644
index 0000000..493283c
--- /dev/null
+++ b/test/expected/test_cmds.sh_62d68c0a11757c996f24c8f003e6b4059c3e30b2.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.err b/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.err
diff --git a/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.out b/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.out
new file mode 100644
index 0000000..541a9b8
--- /dev/null
+++ b/test/expected/test_cmds.sh_661ec61acdd8f6fa6ec1e3c2cf5f896eef431351.out
@@ -0,0 +1,14 @@
+''
+{
+ "foo bar" : null,
+  "array" : [
+  1,
+  2,
+  3
+ ],
+ "obj" : {
+ "one" : 1,
+ "two" : true
+ }
+}
+''
diff --git a/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.err b/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.err
new file mode 100644
index 0000000..bcc3200
--- /dev/null
+++ b/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.err
@@ -0,0 +1,8 @@
+✘ error: expecting file name to open
+ --> command-option:1
+ | :open 
+ = help: :open path1 [... pathN]
+ ══════════════════════════════════════════════════════════════════════
+ Open the given file(s) in lnav. Opening files on machines
+ accessible via SSH can be done using the syntax:
+ [user@]host:/path/to/logs
diff --git a/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.out b/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_6a6031113aca32fabc5a3da64b7be46f5ce5a312.out
diff --git a/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.err b/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.err
new file mode 100644
index 0000000..6c8e8ae
--- /dev/null
+++ b/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.err
@@ -0,0 +1,4 @@
+✘ error: invalid zoom level: bad
+ --> command-option:1
+ | :zoom-to bad 
+ = help: available levels: 1-second, 30-second, 1-minute, 5-minute, 15-minute, 1-hour, 4-hour, 8-hour, 1-day, 1-week
diff --git a/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.out b/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_6e016c0ed61fc652be1a79b864875ffede64f281.out
diff --git a/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.err b/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.err
diff --git a/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.out b/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.out
new file mode 100644
index 0000000..bccea86
--- /dev/null
+++ b/test/expected/test_cmds.sh_7270e37dab4549cfa7c5232451c031e1e04b4aef.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.err b/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.err
diff --git a/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.out b/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_73ea99c84fb1d4570e8bcd45c423b4a28fe41e81.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.err b/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.err
diff --git a/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.out b/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.out
new file mode 100644
index 0000000..7ad9d78
--- /dev/null
+++ b/test/expected/test_cmds.sh_7cb644890c4b945ff3f1e15c86a58c85cb5425c0.out
@@ -0,0 +1,5 @@
+┏━━┳━━━━━━━━━━━━━┓
+┃c1┃ c2 ┃
+┡━━╇━━━━━━━━━━━━━┩
+│ 1│Hello, World!│
+└━━┴━━━━━━━━━━━━━┘
diff --git a/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.err b/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.err
new file mode 100644
index 0000000..22e6c3e
--- /dev/null
+++ b/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.err
@@ -0,0 +1,6 @@
+✘ error: expecting an SQL expression
+ --> command-option:1
+ | :mark-expr 
+ = help: :mark-expr expr
+ ══════════════════════════════════════════════════════════════════════
+ Set the bookmark expression
diff --git a/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.out b/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_7e14e7f18219719453838835fa96c3451f78996d.out
diff --git a/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.err b/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.err
diff --git a/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.out b/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.out
new file mode 100644
index 0000000..67f6093
--- /dev/null
+++ b/test/expected/test_cmds.sh_819b3dd21348f7242f3914ad0a8c5b1cdb3f91af.out
@@ -0,0 +1 @@
+Hello: Jules
diff --git a/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.err b/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.err
diff --git a/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.out b/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.out
new file mode 100644
index 0000000..220b552
--- /dev/null
+++ b/test/expected/test_cmds.sh_8298805f897346b4bb0f14e53c06b4fa28e309e3.out
@@ -0,0 +1,3 @@
+⋮ - - [20/Jul/2009:22:59:26 +0000] "GET ⋮ HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+⋮ - - [20/Jul/2009:22:59:29 +0000] "GET ⋮ HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+⋮ - - [20/Jul/2009:22:59:29 +0000] "GET ⋮ HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.err b/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.err
diff --git a/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.out b/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.out
new file mode 100644
index 0000000..a90f29f
--- /dev/null
+++ b/test/expected/test_cmds.sh_83654557317602d2e00adde1e5cba190d9db0dff.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.err b/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.err
diff --git a/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.out b/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.out
new file mode 100644
index 0000000..6be811e
--- /dev/null
+++ b/test/expected/test_cmds.sh_85ae6ac1eb9a8378f7a6c39659f52671218ce64b.out
@@ -0,0 +1 @@
+1Hello, World!
diff --git a/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.err b/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.err
diff --git a/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.out b/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.out
new file mode 100644
index 0000000..f586ffe
--- /dev/null
+++ b/test/expected/test_cmds.sh_85ed177028f226e86b1d164eb1a4e18eaf036c9d.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.err b/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.err
diff --git a/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.out b/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.out
new file mode 100644
index 0000000..493283c
--- /dev/null
+++ b/test/expected/test_cmds.sh_8758082427d6232a15053433942a4b5ad9f2e3ce.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.err b/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.err
new file mode 100644
index 0000000..2276bac
--- /dev/null
+++ b/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.err
@@ -0,0 +1,6 @@
+✘ error: expecting a unix time value
+ --> command-option:1
+ | :unix-time 
+ = help: :unix-time seconds
+ ══════════════════════════════════════════════════════════════════════
+ Convert epoch time to a human-readable form
diff --git a/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.out b/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_876116da8ab46c0c8a212ce230d1b8a13970f78f.out
diff --git a/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.err b/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.err
diff --git a/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.out b/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.out
new file mode 100644
index 0000000..330e041
--- /dev/null
+++ b/test/expected/test_cmds.sh_8765cbf326648e9014f8cf5f761895010fff443a.out
@@ -0,0 +1,37 @@
+2015-03-12T23:16:52.071:INFO:com.root:Response :
+ <?xml version="1.0"?>
+<response>
+ <locale>en-US</locale>
+ <requestid>ipInfo</requestid>
+ <value id="ipv4Gateway" actions="enabled">198.51.100.253</value>
+ <value id="ipv6Gateway" actions="enabled"/>
+ <value id="ipv6Enabled" actions="enabled">true</value>
+ <value id="ipv4Enabled" actions="enabled">true</value>
+ <value id="name" actions="enabled">nic1</value>
+ <value id="v4config" actions="enabled">
+ <value id="defaultGateway" actions="enabled">0.0.0.0</value>
+ <value id="updateable" actions="enabled">True</value>
+ <value id="prefix" actions="enabled">22</value>
+ <value id="mode" actions="enabled">dhcp</value>
+ <value id="address" actions="enabled">198.51.100.110</value>
+ <value id="interface" actions="enabled">nic1</value>
+ </value>
+ <value id="v6config" actions="enabled">
+ <value id="defaultGateway" actions="enabled">fe80::214:f609:19f7:6bf1</value>
+ <value id="updateable" actions="enabled">True</value>
+ <value id="interface" actions="enabled">nic1</value>
+ <value id="dhcp" actions="enabled">False</value>
+ <value id="autoconf" actions="enabled">False</value>
+ <value id="addresses" actions="enabled">
+ <value id="origin" actions="enabled">other</value>
+ <value id="status" actions="enabled">preferred</value>
+ <value id="prefix" actions="enabled">64</value>
+ <value id="address" actions="enabled">fe80::250:56ff:feaa:5abf</value>
+ </value>
+ </value>
+ <value id="interfaceInfo" actions="enabled">
+ <value id="status" actions="enabled">up</value>
+ <value id="mac" actions="enabled">00:50:56:aa:5a:bf</value>
+ <value id="name" actions="enabled">nic1</value>
+ </value>
+</response>
diff --git a/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.err b/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.err
new file mode 100644
index 0000000..492a07d
--- /dev/null
+++ b/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.err
@@ -0,0 +1,6 @@
+✘ error: write-json-to -- unavailable in secure mode
+ --> command-option:2
+ | :write-json-to /tmp/bad 
+ = help: :write-json-to [--anonymize] path
+ ══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in JSON format
diff --git a/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.out b/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_89afa826d1b33be6926df48443faa1d1c5f285a7.out
diff --git a/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.err b/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.err
diff --git a/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.out b/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.out
new file mode 100644
index 0000000..3cc484d
--- /dev/null
+++ b/test/expected/test_cmds.sh_8d5b43c693e78804a8fb06989392fa8cccb46b7b.out
@@ -0,0 +1,2 @@
+info: hiding lines before 2009-07-20 22:59:29.000
+info: hiding lines before 2009-07-20 22:59:29.000
diff --git a/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.err b/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.err
diff --git a/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.out b/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_9445861db011dfa2d21a44788047de345ee291e8.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.err b/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.err
diff --git a/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.out b/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_95beaabe41d72cf4c6810e79c623da759ac1c71b.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.err b/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.err
diff --git a/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.out b/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.out
new file mode 100644
index 0000000..2678e6c
--- /dev/null
+++ b/test/expected/test_cmds.sh_968dac54dc80d91a5da2322890c6c26dfa0d8462.out
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.err b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.err
diff --git a/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out
new file mode 100644
index 0000000..01761e9
--- /dev/null
+++ b/test/expected/test_cmds.sh_a00943ef715598c7554b85de8502454e41bb9e28.out
@@ -0,0 +1,4 @@
+ Thu Nov 03 09:20:00  1 normal 2 errors 0 warnings  0 marks
+ Thu Nov 03 09:45:00  1 normal 0 errors 0 warnings 0 marks
+ Fri Feb 03 09:20:00  0 normal 1 errors 0 warnings 0 marks
+ Wed Jan 03 09:20:00  1 normal 0 errors 0 warnings 0 marks
diff --git a/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.err b/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.err
diff --git a/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.out b/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.out
new file mode 100644
index 0000000..1d3eae4
--- /dev/null
+++ b/test/expected/test_cmds.sh_a0e6214b2a85c90d31aee12efde850441cca7eb3.out
@@ -0,0 +1,2 @@
+log_top_line() 
+ 51
diff --git a/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.err b/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.err
diff --git a/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.out b/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_a1123427c31c022433d66d05ee5d5e1c8ab415e4.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.err b/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.err
new file mode 100644
index 0000000..5f4c49b
--- /dev/null
+++ b/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.err
@@ -0,0 +1,3 @@
+✘ error: unknown script -- nonexistent.lnav -- file not found
+ --> command-option:1
+ | |nonexistent.lnav 
diff --git a/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.out b/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a190bfc279fa046a823864f1484f899d27d22953.out
diff --git a/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.err b/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.err
new file mode 100644
index 0000000..1c20a91
--- /dev/null
+++ b/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.err
@@ -0,0 +1,6 @@
+✘ error: unknown configuration option -- /bad/option
+ --> command-option:1
+ | :config /bad/option 
+ = help: :config option [value]
+ ══════════════════════════════════════════════════════════════════════
+ Read or write a configuration option
diff --git a/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.out b/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a5742238bad948b1372d32f7a491f03fa4e8b711.out
diff --git a/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.err b/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.err
diff --git a/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.out b/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.out
new file mode 100644
index 0000000..c3813a5
--- /dev/null
+++ b/test/expected/test_cmds.sh_a6c431f2871ea96cfdf4e11465b3bca543c7b678.out
@@ -0,0 +1,10 @@
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: vm_compressor_record_warmup (9478314 - 9492476)
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: AppleBCM5701Ethernet [en0]: 0 0 memWrInd fBJP_Wakeup_Timer
+Sep 13 01:25:39 Tim-Stacks-iMac kernel[0]: AppleThunderboltNHIType2::waitForOk2Go2Sx - retries = 60000
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: hibernate_page_list_setall(preflight 0) start 0xffffff8428276000, 0xffffff8428336000
+Sep 13 03:12:58 Tim-Stacks-iMac kernel[0]: *** kernel exceeded 500 log message per second limit - remaining messages this second discarded ***
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: IOThunderboltSwitch<0xffffff803f4b3000>(0x0)::listenerCallback - Thunderbolt HPD packet for route = 0x0 port = 11 unplug = 0
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: vm_compressor_flush - starting
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: AppleBCM5701Ethernet [en0]: 0 0 memWrInd fBJP_Wakeup_Timer
+Sep 13 03:13:16 Tim-Stacks-iMac kernel[0]: AppleThunderboltNHIType2::waitForOk2Go2Sx - retries = 60000
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: hibernate_page_list_setall(preflight 0) start 0xffffff838f1fc000, 0xffffff838f2bc000
diff --git a/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.err b/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.err
new file mode 100644
index 0000000..644b202
--- /dev/null
+++ b/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.err
@@ -0,0 +1,7 @@
+✘ error: filter limit reached, try combining filters with a pipe symbol (e.g. foo|bar)
+ --> command-option:32
+ | :filter-out 32 
+ = help: :filter-out pattern
+ ══════════════════════════════════════════════════════════════════════
+ Remove lines that match the given regular expression in the current
+ view
diff --git a/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.out b/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_a8006c4169d76baecd99a0699c2fc66a583ad676.out
diff --git a/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.err b/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.err
diff --git a/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.out b/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.out
new file mode 100644
index 0000000..fa6a319
--- /dev/null
+++ b/test/expected/test_cmds.sh_ac45fb0f8f9578c3ded0855f694698ec38ce31ad.out
@@ -0,0 +1,12 @@
+{
+ "foo bar": null,
+ "array": [
+ 1,
+ 2,
+ 3
+ ],
+ "obj": {
+ "one": 1,
+ "two": true
+ }
+}
diff --git a/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.err b/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.err
diff --git a/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.out b/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.out
new file mode 100644
index 0000000..be06882
--- /dev/null
+++ b/test/expected/test_cmds.sh_af0fcbd30b3fd0d13477aa3325ef0302052a4d9f.out
@@ -0,0 +1 @@
+ Sat Nov 03 08:00:00 1 normal 0 errors 0 warnings 0 marks
diff --git a/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.err b/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.err
diff --git a/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.out b/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.out
new file mode 100644
index 0000000..8ab686e
--- /dev/null
+++ b/test/expected/test_cmds.sh_b5a530d16c982cf769151291f0bfd612ea71183f.out
@@ -0,0 +1 @@
+Hello, World!
diff --git a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.err b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.err
diff --git a/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out
new file mode 100644
index 0000000..f828498
--- /dev/null
+++ b/test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out
@@ -0,0 +1,4417 @@
+
+lnav
+
+A fancy log file viewer for the terminal.
+
+Overview
+
+The Logfile Navigator, lnav, is an enhanced log file viewer that takes
+advantage of any semantic information that can be gleaned from the
+files being viewed, such as timestamps and log levels. Using this
+extra semantic information, lnav can do things like interleaving
+messages from different files, generate histograms of messages over
+time, and providing hotkeys for navigating through the file. It is
+hoped that these features will allow the user to quickly and
+efficiently zero in on problems.
+
+Opening Paths/URLs
+
+The main arguments to lnav are the local/remote files, directories,
+glob patterns, or URLs to be viewed. If no arguments are given, the
+default syslog file for your system will be opened. These arguments
+will be polled periodically so that any new data or files will be
+automatically loaded. If a previously loaded file is removed or
+replaced, it will be closed and the replacement opened.
+
+Note: When opening SFTP URLs, if the password is not provided for the
+host, the SSH agent can be used to do authentication.
+
+Options
+
+Lnav takes a list of files to view and/or you can use the flag
+arguments to load well-known log files, such as the syslog log files.
+The flag arguments are:
+
+ •  -a  Load all of the most recent log file types.
+ •  -r  Recursively load files from the given directory
+ hierarchies.
+ •  -R  Load older rotated log files as well.
+
+When using the flag arguments, lnav will look for the files relative
+to the current directory and its parent directories. In other words,
+if you are working within a directory that has the well-known log
+files, those will be preferred over any others.
+
+If you do not want the default syslog file to be loaded when no files
+are specified, you can pass the  -N  flag.
+
+Any files given on the command-line are scanned to determine their log
+file format and to create an index for each line in the file. You do
+not have to manually specify the log file format. The currently
+supported formats are: syslog, apache, strace, tcsh history, and
+generic log files with timestamps.
+
+Lnav will also display data piped in on the standard input. The
+following options are available when doing so:
+
+ •  -t  Prepend timestamps to the lines of data being read
+ in on the standard input.
+ •  -w file  Write the contents of the standard input to
+ this file.
+
+To automatically execute queries or lnav commands after the files have
+been loaded, you can use the following options:
+
+ •  -c cmd  A command, query, or file to execute. The
+ first character determines the type of operation: a colon
+ ( : ) is used for the built-in commands; a semi-colon ( ;
+ ) for SQL queries; and a pipe symbol ( | ) for executing
+ a file containing other commands. For example, to open
+ the file "foo.log" and go to the tenth line in the file,
+ you can do:
+
+ ▌lnav -c ':goto 10' foo.log 
+
+ This option can be given multiple times to execute
+ multiple operations in sequence.
+ •  -f file  A file that contains commands, queries, or
+ files to execute. This option is a shortcut for  -c '|file'
+ . You can use a dash ( - ) to execute commands from the
+ standard input.
+
+To execute commands/queries without opening the interactive text UI,
+you can pass the  -n  option. This combination of options allows you
+to write scripts for processing logs with lnav. For example, to get a
+list of IP addresses that dhclient has bound to in CSV format:
+
+ ▌#! /usr/bin/lnav -nf 
+ ▌ 
+ ▌# Usage: dhcp_ip.lnav /var/log/messages 
+ ▌# Only include lines that look like: 
+ ▌# Apr 29 00:31:56 example-centos5 dhclient: bound to 10.1.10.103 -- renewal in 9938 seconds. 
+ ▌ 
+ ▌:filter-in dhclient: bound to 
+ ▌ 
+ ▌# The log message parser will extract the IP address 
+ ▌# as col_0, so we select that and alias it to "dhcp_ip". 
+ ▌;SELECT DISTINCT col_0 AS dhcp_ip FROM logline; 
+ ▌ 
+ ▌# Finally, write the results of the query to stdout. 
+ ▌:write-csv-to - 
+
+Display
+
+The main part of the display shows the log lines from the files
+interleaved based on time-of-day. New lines are automatically loaded
+as they are appended to the files and, if you are viewing the bottom
+of the files, lnav will scroll down to display the new lines, much
+like  tail -f .
+
+On color displays, the lines will be highlighted as follows:
+
+ • Errors will be colored in red;
+ • warnings will be yellow;
+ • boundaries between days will be underlined; and
+ • various color highlights will be applied to: IP
+ addresses, SQL keywords, XML tags, file and line numbers
+ in Java backtraces, and quoted strings.
+
+To give you an idea of where you are spatially, the right side of the
+display has a proportionally sized 'scroll bar' that indicates your
+current position in the files. The scroll bar will also show areas of
+the file where warnings or errors are detected by coloring the bar
+yellow or red, respectively. Tick marks will also be added to the left
+and right-hand side of the bar, for search hits and bookmarks.
+
+The bar on the left side indicates the file the log message is from. A
+break in the bar means that the next log message comes from a
+different file. The color of the bar is derived from the file name.
+Pressing the left-arrow or  h  will reveal the source file names for
+each message and pressing again will show the full paths.
+
+Above and below the main body are status lines that display a variety
+of information. The top line displays:
+
+ • The current time, configurable by the  /ui/clock-format 
+ property.
+ • The highest priority message from the  lnav_user_notifications 
+ table. You can insert rows into this table to display
+ your own status messages. The default message displayed
+ on startup explains how to focus on the next status line
+ at the top, which is an interactive breadcrumb bar.
+
+The second status line at the top display breadcrumbs for the top line
+in the main view. Pressing  ENTER  will focus input on the breadcrumb
+bar, the cursor keys can be used to select a breadcrumb. The common
+breadcrumbs are:
+
+ • The name of the current view.
+ • In the log view, the timestamp of the top log message.
+ • In the log view, the format of the log file the top log
+ message is from.
+ • The name of the file the top line was pulled from.
+ • If the top line is within a larger chunk of structured
+ data, the path to the value in the top line will be
+ shown.
+
+Notes:
+
+ 1. Pressing  CTRL-A / CTRL-E  will select the first/last
+ breadcrumb.
+ 2. Typing text while a breadcrumb is selected will
+ perform a fuzzy search on the possibilities.
+
+The bottom status bar displays:
+
+ • The line number for the top line in the display.
+ • The current search hit, the total number of hits, and
+ the search term.
+
+If the view supports filtering, there will be a status line showing
+the following:
+
+ • The number of enabled filters and the total number of
+ filters.
+ • The number of lines not displayed because of filtering.
+
+To edit the filters, you can press TAB to change the focus from the
+main view to the filter editor. The editor allows you to create,
+enable/disable, and delete filters easily.
+
+Along with filters, a "Files" panel will also be available for viewing
+and controlling the files that lnav is currently monitoring.
+
+Finally, the last line on the display is where you can enter search
+patterns and execute internal commands, such as converting a
+unix-timestamp into a human-readable date. The command-line is
+implemented using the readline library, so the usual set of keyboard
+shortcuts are available. Most commands and searches also support
+tab-completion.
+
+The body of the display is also used to display other content, such
+as: the help file, histograms of the log messages over time, and SQL
+results. The views are organized into a stack so that any time you
+activate a new view with a key press or command, the new view is
+pushed onto the stack. Pressing the same key again will pop the view
+off of the stack and return you to the previous view. Note that you
+can always use  q  to pop the top view off of the stack.
+
+Default Key Bindings
+
+Views
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ ? View/leave this help message.
+ q Leave the current view or quit the program when in
+ the log file view.
+ Q Similar to  q , except it will try to sync the top
+ time between the current and former views. For
+ example, when leaving the spectrogram view with  Q
+ , the top time in that view will be matched to the
+ top time in the log view.
+ TAB Toggle focusing on the filter editor or the main
+ view.
+ ENTER Focus on the breadcrumb bar.
+ a/A Restore the view that was previously popped with  q
+ / Q . The  A  hotkey will try to match the top
+ times between the two views.
+ X Close the current text file or log file.
+
+Spatial Navigation
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════════
+ g/Home Move to the top of the file.
+ G/End Move to the end of the file. If the view is
+ already at the end, it will move to the last line.
+ SPACE/PgDn Move down a page.
+ b/PgUp Move up a page.
+ j/↓ Move down a line.
+ k/↑ Move up a line.
+ h/← Move to the left. In the log view, moving left
+ will reveal the source log file names for each
+ line. Pressing again will reveal the full path.
+ l/→ Move to the right.
+ H/Shift ← Move to the left by a smaller increment.
+ L/Shift → Move to the right by a smaller increment.
+ e/E Move to the next/previous error.
+ w/W Move to the next/previous warning.
+ n/N Move to the next/previous search hit. When pressed
+ repeatedly within a short time, the view will move
+ at least a full page at a time instead of moving
+ to the next hit.
+ f/F Move to the next/previous file. In the log view,
+ this moves to the next line from a different file.
+ In the text view, this rotates the view to the
+ next file.
+ >/< Move horizontally to the next/previous search hit.
+ o/O Move forward/backward to the log message with a
+ matching 'operation ID' (opid) field.
+ u/U Move forward/backward through any user bookmarks
+ you have added using the 'm' key. This hotkey will
+ also jump to the start of any log partitions that
+ have been created with the 'partition-name'
+ command.
+ s/S Move to the next/previous "slow down" in the log
+ message rate. A slow down is detected by measuring
+ how quickly the message rate has changed over the
+ previous several messages. For example, if one
+ message is logged every second for five seconds
+ and then the last message arrives five seconds
+ later, the last message will be highlighted as a
+ slow down.
+ {/} Move to the previous/next location in history.
+ Whenever you jump to a new location in the view,
+ the location will be added to the history. The
+ history is not updated when using only the arrow
+ keys.
+
+Chronological Navigation
+
+ Key(s) Action
+══════════════════════════════════════════════════════════════════
+ d/D Move forward/backward 24 hours from the current
+ position in the log file.
+ 1-6/Shift 1-6 Move to the next/previous n'th ten minute of the
+ hour. For example, '4' would move to the first log
+ line in the fortieth minute of the current hour in
+ the log. And, '6' would move to the next hour
+ boundary.
+ 7/8 Move to the previous/next minute.
+ 0/Shift 0 Move to the next/previous day boundary.
+ r/R Move forward/backward based on the relative time
+ that was last used with the 'goto' command. For
+ example, executing ':goto a minute later' will
+ move the log view forward a minute and then
+ pressing 'r' will move it forward a minute again.
+ Pressing 'R' will then move the view in the
+ opposite direction, so backwards a minute.
+
+Bookmarks
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ m Mark/unmark the line at the top of the display.
+ The line will be highlighted with reverse video to
+ indicate that it is a user bookmark. You can use
+ the  u  hotkey to iterate through marks you have
+ added.
+ M Mark/unmark all the lines between the top of the
+ display and the last line marked/unmarked.
+ J Mark/unmark the next line after the previously
+ marked line.
+ K Like  J  except it toggles the mark on the
+ previous line.
+ c Copy the marked text to the X11 selection buffer
+ or OS X clipboard.
+ C Clear all marked lines.
+
+Display options
+
+ Key(s) Action
+══════════════════════════════════════════════════════════════════
+ P Switch to/from the pretty-printed view of the log
+ or text files currently displayed. In this view,
+ structured data, such as XML, will be reformatted
+ to make it easier to read.
+ t Switch to/from the text file view. The text file
+ view is for any files that are not recognized as
+ log files.
+ = Pause/unpause loading of new file data.
+ Ctrl-L (Lo-fi mode) Exit screen-mode and write the
+ displayed log lines in plain text to the terminal
+ until a key is pressed. Useful for copying long
+ lines from the terminal without picking up any of
+ the extra decorations.
+ T Toggle the display of the "elapsed time" column
+ that shows the time elapsed since the beginning of
+ the logs or the offset from the previous bookmark.
+ Sharp changes in the message rate are highlighted
+ by coloring the separator between the time column
+ and the log message. A red highlight means the
+ message rate has slowed down and green means it
+ has sped up. You can use the "s/S" hotkeys to scan
+ through the slow downs.
+ i View/leave a histogram of the log messages over
+ time. The histogram counts the number of displayed
+ log lines for each bucket of time. The bars are
+ layed out horizontally with colored segments
+ representing the different log levels. You can use
+ the  z  hotkey to change the size of the time
+ buckets (e.g. ten minutes, one hour, one day).
+ I Switch between the log and histogram views while
+ keeping the time displayed at the top of each view
+ in sync. For example, if the top line in the log
+ view is "11:40", hitting  I  will switch to the
+ histogram view and scrolled to display "11:00" at
+ the top (if the zoom level is hours).
+ z/Shift Z Zoom in or out one step in the histogram view.
+ v Switch to/from the SQL result view.
+ V Switch between the log and SQL result views while
+ keeping the top line number in the log view in
+ sync with the log_line column in the SQL view. For
+ example, doing a query that selects for
+ "log_idle_msecs" and "log_line", you can move the
+ top of the SQL view to a line and hit 'V' to
+ switch to the log view and move to the line number
+ that was selected in the "log_line" column. If
+ there is no "log_line" column, lnav will find the
+ first column with a timestamp and move to
+ corresponding time in the log view.
+ TAB/Shift TAB In the SQL result view, cycle through the columns
+ that are graphed. Initially, all number values are
+ displayed in a stacked graph. Pressing TAB will
+ change the display to only graph the first column.
+ Repeatedly pressing TAB will cycle through the
+ columns until they are all graphed again.
+ p In the log view: enable or disable the display of
+ the fields that the log message parser knows about
+ or has discovered. This overlay is temporarily
+ enabled when the semicolon key (;) is pressed so
+ that it is easier to write queries.
+ In the DB view: enable or disable the display of
+ values in columns containing JSON-encoded values
+ in the top row. The overlay will display the
+ JSON-Pointer reference and value for all fields in
+ the JSON data.
+ CTRL-W Toggle word-wrapping.
+ CTRL-P Show/hide the data preview panel that may be
+ opened when entering commands or SQL queries.
+ CTRL-F Toggle the enabled/disabled state of all filters
+ in the current view.
+ x Toggle the hiding of log message fields. The
+ hidden fields will be replaced with three bullets
+ and highlighted in yellow.
+ F2 Toggle mouse support.
+
+Query
+
+ Key(s) Action
+════════════════════════════════════════════════════════════════════════
+ /regexp Start a search for the given regular expression.
+ The search is live, so when there is a pause in
+ typing, the currently running search will be
+ canceled and a new one started. The first ten
+ lines that match the search will be displayed in
+ the preview window at the bottom of the view.
+ History is maintained for your searches so you can
+ rerun them easily. Words that are currently
+ displayed are also available for tab-completion,
+ so you can easily search for values without
+ needing to copy-and-paste the string. If there is
+ an error encountered while trying to interpret the
+ expression, the error will be displayed in red on
+ the status line. While the search is active, the
+ 'hits' field in the status line will be green,
+ when finished it will turn back to black.
+ :<command> Execute an internal command. The commands are
+ listed below. History is also supported in this
+ context as well as tab-completion for commands and
+ some arguments. The result of the command replaces
+ the command you typed.
+ ;<sql> Execute an SQL query. Most supported log file
+ formats provide a sqlite virtual table backend
+ that can be used in queries. See the SQL section
+ below for more information.
+ |<script> [arg1...] Execute an lnav script contained in a format
+ directory (e.g. ~/.lnav/formats/default). The
+ script can contain lines starting with  : ,  ; ,
+ or  |  to execute commands, SQL queries or execute
+ other files in lnav. Any values after the script
+ name are treated as arguments can be referenced in
+ the script using  $1 ,  $2 , and so on, like in a
+ shell script.
+ CTRL+], ESCAPE Abort command-line entry started with  / ,  : ,  ;
+ , or  | .
+
+ ▌Note: The regular expression format used by lnav is PCRE[1]
+ ▌(Perl-Compatible Regular Expressions).
+ ▌
+ ▌ ▌[1] - http://perldoc.perl.org/perlre.html
+ ▌
+ ▌If the search string is not valid PCRE, a search is done for
+ ▌the exact string instead of doing a regex search.
+
+Session
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ CTRL-R Reset the session state. This will save the
+ current session state (filters, highlights) and
+ then reset the state to the factory default.
+
+Filter Editor
+
+The following hotkeys are only available when the focus is on the
+filter editor. You can change the focus by pressing TAB.
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ q Switch the focus back to the main view.
+ j/↓ Select the next filter.
+ k/↑ Select the previous filter.
+ o Create a new "out" filter.
+ i Create a new "in" filter .
+ SPACE Toggle the enabled/disabled state of the currently
+ selected filter.
+ t Toggle the type of filter between "in" and "out".
+ ENTER Edit the selected filter.
+ D Delete the selected filter.
+
+Mouse Support (experimental)
+
+If you are using Xterm, or a compatible terminal, you can use the
+mouse to mark lines of text and move the view by grabbing the
+scrollbar.
+
+NOTE: You need to manually enable this feature by setting the LNAV_EXP
+environment variable to "mouse". F2 toggles mouse support.
+
+SQL Queries (experimental)
+
+Lnav has support for performing SQL queries on log files using the
+Sqlite3 "virtual" table feature. For all supported log file types,
+lnav will create tables that can be queried using the subset of SQL
+that is supported by Sqlite3. For example, to get the top ten URLs
+being accessed in any loaded Apache log files, you can execute:
+
+ ▌;SELECT cs_uri_stem, count(*) AS total FROM access_log 
+ ▌ GROUP BY cs_uri_stem ORDER BY total DESC LIMIT 10; 
+
+The query result view shows the results and graphs any numeric values
+found in the result, much like the histogram view.
+
+The builtin set of log tables are listed below. Note that only the log
+messages that match a particular format can be queried by a particular
+table. You can find the file format and table name for the top log
+message by looking in the upper right hand corner of the log file
+view.
+
+Some commonly used format tables are:
+
+ Name Description
+════════════════════════════════════════════════════════════════
+ access_log Apache common access log format
+ syslog_log Syslog format
+ strace_log Strace log format
+ generic_log 'Generic' log format. This table contains messages
+ from files that have a very simple format with a
+ leading timestamp followed by the message.
+
+NOTE: You can get a dump of the schema for the internal tables, and
+any attached databases, by running the  .schema  SQL command.
+
+The columns available for the top log line in the view will
+automatically be displayed after pressing the semicolon ( ; ) key. All
+log tables contain at least the following columns:
+
+ Column Description
+═══════════════════════════════════════════════════════════════════
+ log_line The line number in the file, starting at zero.
+ log_part The name of the partition. You can change this
+ column using an UPDATE SQL statement or with the
+ 'partition-name' command. After a value is set,
+ the following log messages will have the same
+ partition name up until another name is set.
+ log_time The time of the log entry.
+ log_idle_msecs The amount of time, in milliseconds, between the
+ current log message and the previous one.
+ log_level The log level (e.g. info, error, etc...).
+ log_mark The bookmark status for the line. This column can
+ be written to using an UPDATE query.
+ log_path The full path to the file.
+ log_text The raw line of text. Note that this column is
+ not included in the result of a 'select *', but it
+ does exist.
+
+The following tables include the basic columns as listed above and
+include a few more columns since the log file format is more
+structured.
+
+ •  syslog_log 
+
+ Column Description
+ ═════════════════════════════════════════════════════════════════
+ log_hostname The hostname the message was received from.
+ log_procname The name of the process that sent the message.
+ log_pid The process ID of the process that sent the
+ message.
+ •  access_log  (The column names are the same as those in
+ the Microsoft LogParser tool.)
+
+ Column Description
+ ══════════════════════════════════════════════════════════
+ c_ip The client IP address.
+ cs_username The client user name.
+ cs_method The HTTP method.
+ cs_uri_stem The stem portion of the URI.
+ cs_uri_query The query portion of the URI.
+ cs_version The HTTP version string.
+ sc_status The status number returned to the client.
+ sc_bytes The number of bytes sent to the client.
+ cs_referrer The URL of the referring page.
+ cs_user_agent The user agent string.
+ •  strace_log  (Currently, you need to run strace with
+ the  -tt -T options so there are timestamps for each
+ function call.)
+
+ Column Description
+ ═══════════════════════════════════════════════════════
+ funcname The name of the syscall.
+ result The result code.
+ duration The amount of time spent in the syscall.
+ arg0 - arg9 The arguments passed to the syscall.
+
+These tables are created dynamically and not stored in memory or on
+disk. If you would like to persist some information from the tables,
+you can attach another database and create tables in that database.
+For example, if you wanted to save the results from the earlier
+example of a top ten query into the "/tmp/topten.db" file, you can do:
+
+ ▌;ATTACH DATABASE '/tmp/topten.db' AS topten; 
+ ▌;CREATE TABLE topten.foo AS SELECT cs_uri_stem, count(*) AS total 
+ ▌ FROM access_log GROUP BY cs_uri_stem ORDER BY total DESC 
+ ▌ LIMIT 10; 
+
+Dynamic logline Table (experimental)
+
+(NOTE: This feature is still very new and not completely reliable yet,
+use with care.)
+
+For log formats that lack message structure, lnav can parse the log
+message and attempt to extract any data fields that it finds. This
+feature is available through the  logline  log table. This table is
+dynamically created and defined based on the message at the top of the
+log view. For example, given the following log message from "sudo",
+lnav will create the "logline" table with columns for "TTY", "PWD",
+"USER", and "COMMAND":
+
+ ▌May 24 06:48:38 Tim-Stacks-iMac.local sudo[76387]: stack : TTY=ttys003 ; PWD=/Users/stack/github/lbuild ; USER=root ; COMMAND=/bin/echo Hello, World! 
+
+Queries executed against this table will then only return results for
+other log messages that have the same format. So, if you were to
+execute the following query while viewing the above line, you might
+get the following results:
+
+ ▌;SELECT USER,COMMAND FROM logline; 
+
+ USER COMMAND
+═════════════════════════════════
+ root /bin/echo Hello, World!
+ mal /bin/echo Goodbye, World!
+
+The log parser works by examining each message for key/value pairs
+separated by an equal sign (=) or a colon (:). For example, in the
+previous example of a "sudo" message, the parser sees the "USER=root"
+string as a pair where the key is "USER" and the value is "root". If
+no pairs can be found, then anything that looks like a value is
+extracted and assigned a numbered column. For example, the following
+line is from "dhcpd":
+
+ ▌Sep 16 22:35:57 drill dhcpd: DHCPDISCOVER from 00:16:ce:54:4e:f3 via hme3 
+
+In this case, the lnav parser recognizes that "DHCPDISCOVER", the MAC
+address and the "hme3" device name are values and not normal words.
+So, it builds a table with three columns for each of these values. The
+regular words in the message, like "from" and "via", are then used to
+find other messages with a similar format.
+
+If you would like to execute queries against log messages of different
+formats at the same time, you can use the 'create-logline-table'
+command to permanently create a table using the top line of the log
+view as a template.
+
+Other SQL Features
+
+Environment variables can be used in SQL statements by prefixing the
+variable name with a dollar-sign ($). For example, to read the value
+of the  HOME  variable, you can do:
+
+ ▌;SELECT $HOME; 
+
+To select the syslog messages that have a hostname field that is equal
+to the  HOSTNAME  variable:
+
+ ▌;SELECT * FROM syslog_log WHERE log_hostname = $HOSTNAME; 
+
+NOTE: Variable substitution is done for fields in the query and is not
+a plain text substitution. For example, the following statement WILL
+NOT WORK:
+
+ ▌;SELECT * FROM $TABLE_NAME; -- Syntax error 
+
+Access to lnav's environment variables is also available via the
+"environ" table. The table has two columns (name, value) and can be
+read and written to using SQL SELECT, INSERT, UPDATE, and DELETE
+statements. For example, to set the "FOO" variable to the value "BAR":
+
+ ▌;INSERT INTO environ SELECT 'FOO', 'BAR'; 
+
+As a more complex example, you can set the variable "LAST" to the last
+syslog line number by doing:
+
+ ▌;INSERT INTO environ SELECT 'LAST', (SELECT max(log_line) FROM syslog_log); 
+
+A delete will unset the environment variable:
+
+ ▌;DELETE FROM environ WHERE name='LAST'; 
+
+The table allows you to easily use the results of a SQL query in lnav
+commands, which is especially useful when scripting lnav.
+
+Contact
+
+For more information, visit the lnav website at:
+
+http://lnav.org
+
+For support questions, email:
+
+ • lnav@googlegroups.com
+ • support@lnav.org
+
+Command Reference
+
+:adjust-log-time timestamp
+══════════════════════════════════════════════════════════════════════
+ Change the timestamps of the top file to be relative to the given
+ date
+Parameter
+ timestamp The new timestamp for the top line in the
+ view
+
+Examples
+#1 To set the top timestamp to a given date:
+ :adjust-log-time 2017-01-02T05:33:00 
+
+
+#2 To set the top timestamp back an hour:
+ :adjust-log-time -1h 
+
+
+
+:alt-msg msg
+══════════════════════════════════════════════════════════════════════
+ Display a message in the alternate command position
+Parameter
+ msg The message to display
+See Also
+ :echo, :eval, :export-session-to, :rebuild, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to
+Example
+#1 To display 'Press t to switch to the text view' on the bottom right:
+ :alt-msg Press t to switch to the text view 
+
+
+
+:append-to path
+══════════════════════════════════════════════════════════════════════
+ Append marked lines in the current view to the given file
+Parameter
+ path The path to the file to append to
+See Also
+ :echo, :export-session-to, :pipe-line-to, :pipe-to, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to, echoln()
+Example
+#1 To append marked lines to the file /tmp/interesting-lines.txt:
+ :append-to /tmp/interesting-lines.txt 
+
+
+
+:clear-comment
+══════════════════════════════════════════════════════════════════════
+ Clear the comment attached to the top log line
+See Also
+ :comment, :tag
+
+:clear-filter-expr
+══════════════════════════════════════════════════════════════════════
+ Clear the filter expression
+See Also
+ :filter-expr, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+
+:clear-highlight pattern
+══════════════════════════════════════════════════════════════════════
+ Remove a previously set highlight regular expression
+Parameter
+ pattern The regular expression previously used with
+ :highlight
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+Example
+#1 To clear the highlight with the pattern 'foobar':
+ :clear-highlight foobar 
+
+
+
+:clear-mark-expr
+══════════════════════════════════════════════════════════════════════
+ Clear the mark expression
+See Also
+ :hide-unmarked-lines, :mark, :mark-expr, :next-mark, :prev-mark
+
+:clear-partition
+══════════════════════════════════════════════════════════════════════
+ Clear the partition the top line is a part of
+
+
+:close
+══════════════════════════════════════════════════════════════════════
+ Close the top file in the view
+
+
+:comment text
+══════════════════════════════════════════════════════════════════════
+ Attach a comment to the top log line. The comment will be displayed
+ right below the log message it is associated with. The comment can
+ be formatted using markdown and you can add new-lines with '\n'.
+Parameter
+ text The comment text
+See Also
+ :clear-comment, :tag
+Example
+#1 To add the comment 'This is where it all went wrong' to the top line:
+ :comment This is where it all went wrong 
+
+
+
+:config option [value]
+══════════════════════════════════════════════════════════════════════
+ Read or write a configuration option
+Parameters
+ option The path to the option to read or write
+ value The value to write. If not given, the current
+ value is returned
+See Also
+ :reset-config
+Examples
+#1 To read the configuration of the '/ui/clock-format' option:
+ :config /ui/clock-format 
+
+
+#2 To set the '/ui/dim-text' option to 'false':
+ :config /ui/dim-text false 
+
+
+
+:create-logline-table table-name
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table using the top line of the log view as a template
+Parameter
+ table-name The name for the new table
+See Also
+ :create-search-table, :create-search-table, :write-csv-to,
+ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to,
+ :write-table-to, :write-view-to
+Example
+#1 To create a logline-style table named 'task_durations':
+ :create-logline-table task_durations 
+
+
+
+:create-search-table table-name [pattern]
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
+Parameters
+ table-name The name of the table to create
+ pattern The regular expression used to capture the
+ table columns. If not given, the current search
+ pattern is used.
+See Also
+ :create-logline-table, :create-logline-table, :delete-search-table,
+ :delete-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To create a table named 'task_durations' that matches log messages with the pattern
+ 'duration=(?<duration>\d+)':
+ :create-search-table task_durations duration=(?<duration>\d+)
+
+
+
+:current-time
+══════════════════════════════════════════════════════════════════════
+ Print the current time in human-readable form and seconds since the
+ epoch
+
+
+:delete-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Delete the filter created with :filter-in or :filter-out
+Parameter
+ pattern The regular expression to match
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To delete the filter with the pattern 'last message repeated':
+ :delete-filter last message repeated 
+
+
+
+:delete-logline-table table-name
+══════════════════════════════════════════════════════════════════════
+ Delete a table created with create-logline-table
+Parameter
+ table-name The name of the table to delete
+See Also
+ :create-logline-table, :create-logline-table, :create-search-table,
+ :create-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To delete the logline-style table named 'task_durations':
+ :delete-logline-table task_durations 
+
+
+
+:delete-search-table table-name
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
+Parameter
+ table-name The name of the table to create
+See Also
+ :create-logline-table, :create-logline-table, :create-search-table,
+ :create-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To delete the search table named 'task_durations':
+ :delete-search-table task_durations 
+
+
+
+:delete-tags tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Remove the given tags from all log lines
+Parameter
+ tag The tags to delete
+See Also
+ :comment, :tag
+Example
+#1 To remove the tags '#BUG123' and '#needs-review' from all log lines:
+ :delete-tags #BUG123 #needs-review 
+
+
+
+:disable-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Disable a filter created with filter-in/filter-out
+Parameter
+ pattern The regular expression used in the filter
+ command
+See Also
+ :enable-filter, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To disable the filter with the pattern 'last message repeated':
+ :disable-filter last message repeated 
+
+
+
+:disable-word-wrap
+══════════════════════════════════════════════════════════════════════
+ Disable word-wrapping for the current view
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+
+:echo [-n] msg
+══════════════════════════════════════════════════════════════════════
+ Echo the given message to the screen or, if :redirect-to has been
+ called, to output file specified in the redirect. Variable
+ substitution is performed on the message. Use a backslash to escape
+ any special characters, like '$'
+Parameters
+ -n Do not print a line-feed at the end of the output
+ msg The message to display
+See Also
+ :alt-msg, :append-to, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-json-to, :write-json-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, echoln()
+Example
+#1 To output 'Hello, World!':
+ :echo Hello, World! 
+
+
+
+:enable-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Enable a previously created and disabled filter
+Parameter
+ pattern The regular expression used in the filter
+ command
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To enable the disabled filter with the pattern 'last message repeated':
+ :enable-filter last message repeated 
+
+
+
+:enable-word-wrap
+══════════════════════════════════════════════════════════════════════
+ Enable word-wrapping for the current view
+See Also
+ :disable-word-wrap, :hide-fields, :highlight
+
+:eval command
+══════════════════════════════════════════════════════════════════════
+ Evaluate the given command/query after doing environment variable
+ substitution
+Parameter
+ command The command or query to perform substitution on.
+See Also
+ :alt-msg, :echo, :export-session-to, :rebuild, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to
+Example
+#1 To substitute the table name from a variable:
+ :eval ;SELECT * FROM ${table} 
+
+
+
+:export-session-to path
+══════════════════════════════════════════════════════════════════════
+ Export the current lnav state to an executable lnav script file that
+ contains the commands needed to restore the current session
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :echo, :echo, :eval, :pipe-line-to, :pipe-to,
+ :rebuild, :redirect-to, :redirect-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-raw-to, :write-raw-to, :write-screen-to,
+ :write-screen-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, :write-view-to, :write-view-to, echoln()
+
+:filter-expr expr
+══════════════════════════════════════════════════════════════════════
+ Set the filter expression
+Parameter
+ expr The SQL expression to evaluate for each log message.
+ The message values can be accessed using column names
+ prefixed with a colon
+See Also
+ :clear-filter-expr, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Examples
+#1 To set a filter expression that matched syslog messages from 'syslogd':
+ :filter-expr :log_procname = 'syslogd' 
+
+
+#2 To set a filter expression that matches log messages where 'id' is followed by a
+ number and contains the string 'foo':
+ :filter-expr :log_body REGEXP 'id\d+' AND :log_body REGEXP 'foo'
+
+
+
+:filter-in pattern
+══════════════════════════════════════════════════════════════════════
+ Only show lines that match the given regular expression in the
+ current view
+Parameter
+ pattern The regular expression to match
+See Also
+ :delete-filter, :disable-filter, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To filter out log messages that do not have the string 'dhclient':
+ :filter-in dhclient 
+
+
+
+:filter-out pattern
+══════════════════════════════════════════════════════════════════════
+ Remove lines that match the given regular expression in the current
+ view
+Parameter
+ pattern The regular expression to match
+See Also
+ :delete-filter, :disable-filter, :filter-in, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To filter out log messages that contain the string 'last message repeated':
+ :filter-out last message repeated 
+
+
+
+:goto line#|N%|timestamp|#anchor
+══════════════════════════════════════════════════════════════════════
+ Go to the given location in the top view
+Parameter
+ line#|N%|timestamp|#anchor A line
+ number, percent into the file,
+ timestamp, or an anchor in a text file
+See Also
+ :next-location, :next-mark, :prev-location, :prev-mark, :relative-goto
+Examples
+#1 To go to line 22:
+ :goto 22 
+
+
+#2 To go to the line 75% of the way into the view:
+ :goto 75% 
+
+
+#3 To go to the first message on the first day of 2017:
+ :goto 2017-01-01 
+
+
+#4 To go to the Screenshots section:
+ :goto #screenshots 
+
+
+
+:help
+══════════════════════════════════════════════════════════════════════
+ Open the help text view
+
+
+:hide-fields field-name1 [... field-nameN]
+══════════════════════════════════════════════════════════════════════
+ Hide log message fields by replacing them with an ellipsis
+Parameter
+ field-name The name of the field to hide in the
+ format for the top log line. A qualified name can be
+ used where the field name is prefixed by the format
+ name and a dot to hide any field.
+See Also
+ :enable-word-wrap, :highlight, :show-fields
+Examples
+#1 To hide the log_procname fields in all formats:
+ :hide-fields log_procname 
+
+
+#2 To hide only the log_procname field in the syslog format:
+ :hide-fields syslog_log.log_procname 
+
+
+
+:hide-file path
+══════════════════════════════════════════════════════════════════════
+ Hide the given file(s) and skip indexing until it is shown again.
+ If no path is given, the current file in the view is hidden
+Parameter
+ path A path or glob pattern that specifies the files to
+ hide
+
+
+:hide-lines-after date
+══════════════════════════════════════════════════════════════════════
+ Hide lines that come after the given date
+Parameter
+ date An absolute or relative date
+See Also
+ :filter-in, :filter-out, :hide-lines-before, :hide-unmarked-lines,
+ :show-lines-before-and-after, :toggle-filtering
+Examples
+#1 To hide the lines after the top line in the view:
+ :hide-lines-after here 
+
+
+#2 To hide the lines after 6 AM today:
+ :hide-lines-after 6am 
+
+
+
+:hide-lines-before date
+══════════════════════════════════════════════════════════════════════
+ Hide lines that come before the given date
+Parameter
+ date An absolute or relative date
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-unmarked-lines,
+ :show-lines-before-and-after, :toggle-filtering
+Examples
+#1 To hide the lines before the top line in the view:
+ :hide-lines-before here 
+
+
+#2 To hide the log messages before 6 AM today:
+ :hide-lines-before 6am 
+
+
+
+:hide-unmarked-lines
+══════════════════════════════════════════════════════════════════════
+ Hide lines that have not been bookmarked
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before, :mark,
+ :next-mark, :prev-mark, :toggle-filtering
+
+:highlight pattern
+══════════════════════════════════════════════════════════════════════
+ Add coloring to log messages fragments that match the given regular
+ expression
+Parameter
+ pattern The regular expression to match
+See Also
+ :clear-highlight, :enable-word-wrap, :hide-fields
+Example
+#1 To highlight numbers with three or more digits:
+ :highlight \d{3,} 
+
+
+
+:load-session
+══════════════════════════════════════════════════════════════════════
+ Load the latest session state
+
+
+:mark
+══════════════════════════════════════════════════════════════════════
+ Toggle the bookmark state for the top line in the current view
+See Also
+ :hide-unmarked-lines, :next-mark, :prev-mark
+
+:mark-expr expr
+══════════════════════════════════════════════════════════════════════
+ Set the bookmark expression
+Parameter
+ expr The SQL expression to evaluate for each log message.
+ The message values can be accessed using column names
+ prefixed with a colon
+See Also
+ :clear-mark-expr, :hide-unmarked-lines, :mark, :next-mark, :prev-mark
+Example
+#1 To mark lines from 'dhclient' that mention 'eth0':
+ :mark-expr :log_procname = 'dhclient' AND :log_body LIKE '%eth0%'
+
+
+
+:next-location
+══════════════════════════════════════════════════════════════════════
+ Move to the next position in the location history
+See Also
+ :goto, :next-mark, :prev-location, :prev-mark, :relative-goto
+
+:next-mark type1 [... typeN]
+══════════════════════════════════════════════════════════════════════
+ Move to the next bookmark of the given type in the current view
+Parameter
+ type The type of bookmark -- error, warning, search, user,
+ file, meta
+See Also
+ :goto, :hide-unmarked-lines, :mark, :next-location, :prev-location,
+ :prev-mark, :prev-mark, :relative-goto
+Example
+#1 To go to the next error:
+ :next-mark error 
+
+
+
+:open path1 [... pathN]
+══════════════════════════════════════════════════════════════════════
+ Open the given file(s) in lnav. Opening files on machines
+ accessible via SSH can be done using the syntax:
+ [user@]host:/path/to/logs
+Parameter
+ path The path to the file to open
+
+Examples
+#1 To open the file '/path/to/file':
+ :open /path/to/file 
+
+
+#2 To open the remote file '/var/log/syslog.log':
+ :open dean@host1.example.com:/var/log/syslog.log 
+
+
+
+:partition-name name
+══════════════════════════════════════════════════════════════════════
+ Mark the top line in the log view as the start of a new partition
+ with the given name
+Parameter
+ name The name for the new partition
+
+Example
+#1 To mark the top line as the start of the partition named 'boot #1':
+ :partition-name boot #1 
+
+
+
+:pipe-line-to shell-cmd
+══════════════════════════════════════════════════════════════════════
+ Pipe the top line to the given shell command
+Parameter
+ shell-cmd The shell command-line to execute
+See Also
+ :append-to, :echo, :export-session-to, :pipe-to, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to, echoln()
+Example
+#1 To write the top line to 'sed' for processing:
+ :pipe-line-to sed -e 's/foo/bar/g' 
+
+
+
+:pipe-to shell-cmd
+══════════════════════════════════════════════════════════════════════
+ Pipe the marked lines to the given shell command
+Parameter
+ shell-cmd The shell command-line to execute
+See Also
+ :append-to, :echo, :export-session-to, :pipe-line-to, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to, echoln()
+Example
+#1 To write marked lines to 'sed' for processing:
+ :pipe-to sed -e s/foo/bar/g 
+
+
+
+:prev-location
+══════════════════════════════════════════════════════════════════════
+ Move to the previous position in the location history
+See Also
+ :goto, :next-location, :next-mark, :prev-mark, :relative-goto
+
+:prev-mark type1 [... typeN]
+══════════════════════════════════════════════════════════════════════
+ Move to the previous bookmark of the given type in the current view
+Parameter
+ type The type of bookmark -- error, warning, search, user,
+ file, meta
+See Also
+ :goto, :hide-unmarked-lines, :mark, :next-location, :next-mark,
+ :next-mark, :prev-location, :relative-goto
+Example
+#1 To go to the previous error:
+ :prev-mark error 
+
+
+
+:prompt type [--alt] [prompt] [initial-value]
+══════════════════════════════════════════════════════════════════════
+ Open the given prompt
+Parameters
+ type The type of prompt -- command,
+ script, search, sql, user
+ --alt Perform the alternate action for
+ this prompt by default
+ prompt The prompt to display
+ initial-value The initial value to fill in for the
+ prompt
+
+Examples
+#1 To open the command prompt with 'filter-in' already filled in:
+ :prompt command : 'filter-in ' 
+
+
+#2 To ask the user a question:
+ :prompt user 'Are you sure? ' 
+
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:rebuild
+══════════════════════════════════════════════════════════════════════
+ Forcefully rebuild file indexes
+See Also
+ :alt-msg, :echo, :eval, :export-session-to, :redirect-to,
+ :write-csv-to, :write-json-to, :write-jsonlines-to, :write-raw-to,
+ :write-screen-to, :write-table-to, :write-to, :write-view-to
+
+:redirect-to [path]
+══════════════════════════════════════════════════════════════════════
+ Redirect the output of commands that write to stdout to the given
+ file
+Parameter
+ path The path to the file to write. If not specified, the
+ current redirect will be cleared
+See Also
+ :alt-msg, :append-to, :echo, :echo, :eval, :export-session-to,
+ :export-session-to, :pipe-line-to, :pipe-to, :rebuild, :write-csv-to,
+ :write-csv-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-raw-to, :write-raw-to, :write-screen-to,
+ :write-screen-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, :write-view-to, :write-view-to, echoln()
+Example
+#1 To write the output of lnav commands to the file /tmp/script-output.txt:
+ :redirect-to /tmp/script-output.txt 
+
+
+
+:redraw
+══════════════════════════════════════════════════════════════════════
+ Do a full redraw of the screen
+
+
+:relative-goto line-count|N%
+══════════════════════════════════════════════════════════════════════
+ Move the current view up or down by the given amount
+Parameter
+ line-count|N% The amount to move the view by.
+See Also
+ :goto, :next-location, :next-mark, :prev-location, :prev-mark
+Examples
+#1 To move 22 lines down in the view:
+ :relative-goto +22 
+
+
+#2 To move 10 percent back in the view:
+ :relative-goto -10% 
+
+
+
+:reset-config option
+══════════════════════════════════════════════════════════════════════
+ Reset the configuration option to its default value
+Parameter
+ option The path to the option to reset
+See Also
+ :config
+Example
+#1 To reset the '/ui/clock-format' option back to the builtin default:
+ :reset-config /ui/clock-format 
+
+
+
+:reset-session
+══════════════════════════════════════════════════════════════════════
+ Reset the session state, clearing all filters, highlights, and
+ bookmarks
+
+
+:save-session
+══════════════════════════════════════════════════════════════════════
+ Save the current state as a session
+
+
+:session lnav-command
+══════════════════════════════════════════════════════════════════════
+ Add the given command to the session file (~/.lnav/session)
+Parameter
+ lnav-command The lnav command to save.
+
+Example
+#1 To add the command ':highlight foobar' to the session file:
+ :session :highlight foobar 
+
+
+
+:set-min-log-level log-level
+══════════════════════════════════════════════════════════════════════
+ Set the minimum log level to display in the log view
+Parameter
+ log-level The new minimum log level
+
+Example
+#1 To set the minimum log level displayed to error:
+ :set-min-log-level error 
+
+
+
+:show-fields field-name1 [... field-nameN]
+══════════════════════════════════════════════════════════════════════
+ Show log message fields that were previously hidden
+Parameter
+ field-name The name of the field to show
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+Example
+#1 To show all the log_procname fields in all formats:
+ :show-fields log_procname 
+
+
+
+:show-file path
+══════════════════════════════════════════════════════════════════════
+ Show the given file(s) and resume indexing.
+Parameter
+ path The path or glob pattern that specifies the files to
+ show
+
+
+:show-lines-before-and-after
+══════════════════════════════════════════════════════════════════════
+ Show lines that were hidden by the 'hide-lines' commands
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+
+:show-only-this-file
+══════════════════════════════════════════════════════════════════════
+ Show only the file for the top line in the view
+
+
+:show-unmarked-lines
+══════════════════════════════════════════════════════════════════════
+ Show lines that have not been bookmarked
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :hide-unmarked-lines, :mark, :next-mark,
+ :prev-mark, :toggle-filtering
+
+:spectrogram field-name
+══════════════════════════════════════════════════════════════════════
+ Visualize the given message field or database column using a
+ spectrogram
+Parameter
+ field-name The name of the numeric field to
+ visualize.
+
+Example
+#1 To visualize the sc_bytes field in the access_log format:
+ :spectrogram sc_bytes 
+
+
+
+:summarize column-name
+══════════════════════════════════════════════════════════════════════
+ Execute a SQL query that computes the characteristics of the values
+ in the given column
+Parameter
+ column-name The name of the column to analyze.
+
+Example
+#1 To get a summary of the sc_bytes column in the access_log table:
+ :summarize sc_bytes 
+
+
+
+:switch-to-view view-name
+══════════════════════════════════════════════════════════════════════
+ Switch to the given view
+Parameter
+ view-name The name of the view to switch to.
+
+Example
+#1 To switch to the 'schema' view:
+ :switch-to-view schema 
+
+
+
+:tag tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Attach tags to the top log line
+Parameter
+ tag The tags to attach
+See Also
+ :comment, :delete-tags, :untag
+Example
+#1 To add the tags '#BUG123' and '#needs-review' to the top line:
+ :tag #BUG123 #needs-review 
+
+
+
+:toggle-filtering
+══════════════════════════════════════════════════════════════════════
+ Toggle the filtering flag for the current view
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines
+
+:toggle-view view-name
+══════════════════════════════════════════════════════════════════════
+ Switch to the given view or, if it is already displayed, switch to
+ the previous view
+Parameter
+ view-name The name of the view to toggle the display
+ of.
+
+Example
+#1 To switch to the 'schema' view if it is not displayed or switch back to the previous
+ view:
+ :toggle-view schema 
+
+
+
+:unix-time seconds
+══════════════════════════════════════════════════════════════════════
+ Convert epoch time to a human-readable form
+Parameter
+ seconds The epoch timestamp to convert
+
+Example
+#1 To convert the epoch time 1490191111:
+ :unix-time 1490191111 
+
+
+
+:untag tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Detach tags from the top log line
+Parameter
+ tag The tags to detach
+See Also
+ :comment, :tag
+Example
+#1 To remove the tags '#BUG123' and '#needs-review' from the top line:
+ :untag #BUG123 #needs-review 
+
+
+
+:write-table-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in a tabular format
+Parameters
+ --anonymize Anonymize the table contents
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to,
+ echoln()
+Example
+#1 To write SQL results as text to /tmp/table.txt:
+ :write-table-to /tmp/table.txt 
+
+
+
+:write-csv-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in CSV format
+Parameters
+ --anonymize Anonymize the row contents
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, :write-view-to, :write-view-to, :write-view-to, echoln()
+Example
+#1 To write SQL results as CSV to /tmp/table.csv:
+ :write-csv-to /tmp/table.csv 
+
+
+
+:write-json-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in JSON format
+Parameters
+ --anonymize Anonymize the JSON values
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, :write-view-to, :write-view-to, :write-view-to, echoln()
+Example
+#1 To write SQL results as JSON to /tmp/table.json:
+ :write-json-to /tmp/table.json 
+
+
+
+:write-jsonlines-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in JSON Lines format
+Parameters
+ --anonymize Anonymize the JSON values
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, :write-view-to, :write-view-to, :write-view-to, echoln()
+Example
+#1 To write SQL results as JSON Lines to /tmp/table.json:
+ :write-jsonlines-to /tmp/table.json 
+
+
+
+:write-raw-to [--view={log,db}] [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ In the log view, write the original log file content of the marked
+ messages to the file. In the DB view, the contents of the cells are
+ written to the output file.
+Parameters
+ --view={log,db} The view to use as the source of
+ data
+ --anonymize Anonymize the lines
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-screen-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-table-to, :write-to, :write-to, :write-view-to, :write-view-to,
+ :write-view-to, echoln()
+Example
+#1 To write the marked lines in the log view to /tmp/table.txt:
+ :write-raw-to /tmp/table.txt 
+
+
+
+:write-screen-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write the displayed text or SQL results to the given file without
+ any formatting
+Parameters
+ --anonymize Anonymize the lines
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-table-to, :write-table-to, :write-table-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to,
+ echoln()
+Example
+#1 To write only the displayed text to /tmp/table.txt:
+ :write-screen-to /tmp/table.txt 
+
+
+
+:write-table-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in a tabular format
+Parameters
+ --anonymize Anonymize the table contents
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to,
+ echoln()
+Example
+#1 To write SQL results as text to /tmp/table.txt:
+ :write-table-to /tmp/table.txt 
+
+
+
+:write-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Overwrite the given file with any marked lines in the current view
+Parameters
+ --anonymize Anonymize the lines
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :echo, :echo, :eval, :export-session-to,
+ :export-session-to, :pipe-line-to, :pipe-to, :rebuild, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-jsonlines-to, :write-jsonlines-to,
+ :write-raw-to, :write-raw-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-view-to, :write-view-to,
+ echoln()
+Example
+#1 To write marked lines to the file /tmp/interesting-lines.txt:
+ :write-to /tmp/interesting-lines.txt 
+
+
+
+:write-view-to [--anonymize] path
+══════════════════════════════════════════════════════════════════════
+ Write the text in the top view to the given file without any
+ formatting
+Parameters
+ --anonymize Anonymize the lines
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :export-session-to, :export-session-to,
+ :pipe-line-to, :pipe-to, :rebuild, :redirect-to, :redirect-to,
+ :write-csv-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-table-to, :write-to,
+ :write-to, echoln()
+Example
+#1 To write the top view to /tmp/table.txt:
+ :write-view-to /tmp/table.txt 
+
+
+
+:zoom-to zoom-level
+══════════════════════════════════════════════════════════════════════
+ Zoom the histogram view to the given level
+Parameter
+ zoom-level The zoom level
+
+Example
+#1 To set the zoom level to '1-week':
+ :zoom-to 1-week 
+
+
+SQL Reference
+
+CAST(expr AS type-name)
+══════════════════════════════════════════════════════════════════════
+ Convert the value of the given expression to a different storage
+ class specified by type-name.
+Parameters
+ expr The value to convert.
+ type-name The name of the type to convert to.
+
+Example
+#1 To cast the value 1.23 as an integer:
+ ;SELECT CAST(1.23 AS INTEGER) 
+
+
+
+OVER([base-window-name] PARTITION BY expr, ... ORDER BY expr, ...,
+ [frame-spec])
+══════════════════════════════════════════════════════════════════════
+ Executes the preceding function over a window
+Parameters
+ base-window-name The name of the window
+ definition
+ expr The values to use for
+ partitioning
+ expr The values used to order the
+ rows in the window
+ frame-spec Determines which output rows
+ are read by an aggregate window function
+
+
+abs(x)
+══════════════════════════════════════════════════════════════════════
+ Return the absolute value of the argument
+Parameter
+ x The number to convert
+See Also
+ acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the absolute value of -1:
+ ;SELECT abs(-1) 
+
+
+
+acos(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arccosine of a number, in radians
+Parameter
+ num A cosine value that is between -1 and 1
+See Also
+ abs(), acosh(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arccosine of 0.2:
+ ;SELECT acos(0.2) 
+
+
+
+acosh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arccosine of a number
+Parameter
+ num A number that is one or more
+See Also
+ abs(), acos(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arccosine of 1.2:
+ ;SELECT acosh(1.2) 
+
+
+
+anonymize(value)
+══════════════════════════════════════════════════════════════════════
+ Replace identifying information with random values.
+Parameter
+ value The text to anonymize
+See Also
+ char(), charindex(), decode(), encode(), endswith(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To anonymize an IP address:
+ ;SELECT anonymize('Hello, 192.168.1.2') 
+
+
+
+asin(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arcsine of a number, in radians
+Parameter
+ num A sine value that is between -1 and 1
+See Also
+ abs(), acos(), acosh(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arcsine of 0.2:
+ ;SELECT asin(0.2) 
+
+
+
+asinh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arcsine of a number
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arcsine of 0.2:
+ ;SELECT asinh(0.2) 
+
+
+
+atan(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arctangent of a number, in radians
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arctangent of 0.2:
+ ;SELECT atan(0.2) 
+
+
+
+atan2(y, x)
+══════════════════════════════════════════════════════════════════════
+ Returns the angle in the plane between the positive X axis and the
+ ray from (0, 0) to the point (x, y)
+Parameters
+ y The y coordinate of the point
+ x The x coordinate of the point
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the angle, in degrees, for the point at (5, 5):
+ ;SELECT degrees(atan2(5, 5)) 
+
+
+
+atanh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arctangent of a number
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arctangent of 0.2:
+ ;SELECT atanh(0.2) 
+
+
+
+atn2(y, x)
+══════════════════════════════════════════════════════════════════════
+ Returns the angle in the plane between the positive X axis and the
+ ray from (0, 0) to the point (x, y)
+Parameters
+ y The y coordinate of the point
+ x The x coordinate of the point
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the angle, in degrees, for the point at (5, 5):
+ ;SELECT degrees(atn2(5, 5)) 
+
+
+
+avg(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the average value of all non-NULL numbers within a group.
+Parameter
+ X The value to compute the average of.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), ceil(), degrees(), exp(), floor(), log(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the average of the column 'ex_duration' from the table 'lnav_example_log':
+ ;SELECT avg(ex_duration) FROM lnav_example_log 
+
+
+#2 To get the average of the column 'ex_duration' from the table 'lnav_example_log'
+ when grouped by 'ex_procname':
+ ;SELECT ex_procname, avg(ex_duration) FROM lnav_example_log GROUP BY ex_procname
+
+
+
+basename(path)
+══════════════════════════════════════════════════════════════════════
+ Extract the base portion of a pathname.
+Parameter
+ path The path
+See Also
+ dirname(), joinpath(), readlink(), realpath()
+Examples
+#1 To get the base of a plain file name:
+ ;SELECT basename('foobar') 
+
+
+#2 To get the base of a path:
+ ;SELECT basename('foo/bar') 
+
+
+#3 To get the base of a directory:
+ ;SELECT basename('foo/bar/') 
+
+
+#4 To get the base of an empty string:
+ ;SELECT basename('') 
+
+
+#5 To get the base of a Windows path:
+ ;SELECT basename('foo\bar') 
+
+
+#6 To get the base of the root directory:
+ ;SELECT basename('/') 
+
+
+
+ceil(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the smallest integer that is not less than the argument
+Parameter
+ num The number to raise to the ceiling
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the ceiling of 1.23:
+ ;SELECT ceil(1.23) 
+
+
+
+changes()
+══════════════════════════════════════════════════════════════════════
+ The number of database rows that were changed, inserted, or deleted
+ by the most recent statement.
+
+
+char(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns a string composed of characters having the given unicode
+ code point values
+Parameter
+ X The unicode code point values
+See Also
+ anonymize(), charindex(), decode(), encode(), endswith(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To get a string with the code points 0x48 and 0x49:
+ ;SELECT char(0x48, 0x49) 
+
+
+
+charindex(needle, haystack, [start])
+══════════════════════════════════════════════════════════════════════
+ Finds the first occurrence of the needle within the haystack and
+ returns the number of prior characters plus 1, or 0 if Y is nowhere
+ found within X
+Parameters
+ needle The string to look for in the haystack
+ haystack The string to search within
+ start The one-based index within the haystack to
+ start the search
+See Also
+ anonymize(), char(), decode(), encode(), endswith(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To search for the string 'abc' within 'abcabc' and starting at position 2:
+ ;SELECT charindex('abc', 'abcabc', 2) 
+
+
+#2 To search for the string 'abc' within 'abcdef' and starting at position 2:
+ ;SELECT charindex('abc', 'abcdef', 2) 
+
+
+
+coalesce(X, Y, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of its first non-NULL argument, or NULL if all
+ arguments are NULL
+Parameters
+ X A value to check for NULL-ness
+ Y A value to check for NULL-ness
+
+Example
+#1 To get the first non-null value from three parameters:
+ ;SELECT coalesce(null, 0, null) 
+
+
+
+count(X)
+══════════════════════════════════════════════════════════════════════
+ If the argument is '*', the total number of rows in the group is
+ returned. Otherwise, the number of times the argument is non-NULL.
+Parameter
+ X The value to count.
+
+Examples
+#1 To get the count of the non-NULL rows of 'lnav_example_log':
+ ;SELECT count(*) FROM lnav_example_log 
+
+
+#2 To get the count of the non-NULL values of 'log_part' from 'lnav_example_log':
+ ;SELECT count(log_part) FROM lnav_example_log 
+
+
+
+cume_dist()
+══════════════════════════════════════════════════════════════════════
+ Returns the cumulative distribution
+See Also
+ dense_rank(), first_value(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+date(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date in this format: YYYY-MM-DD.
+Parameters
+ timestring The string to convert to a date.
+ modifier A transformation that is applied to the
+ value to the left.
+See Also
+ datetime(), humanize_duration(), julianday(), strftime(), time(),
+ timediff(), timeslice()
+Examples
+#1 To get the date portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT date('2017-01-02T03:04:05') 
+
+
+#2 To get the date portion of the timestamp '2017-01-02T03:04:05' plus one day:
+ ;SELECT date('2017-01-02T03:04:05', '+1 day') 
+
+
+#3 To get the date portion of the epoch timestamp 1491341842:
+ ;SELECT date(1491341842, 'unixepoch') 
+
+
+
+datetime(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date and time in this format: YYYY-MM-DD HH:MM:SS.
+Parameters
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the
+ value to the left.
+See Also
+ date(), humanize_duration(), julianday(), strftime(), time(),
+ timediff(), timeslice()
+Examples
+#1 To get the date and time portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT datetime('2017-01-02T03:04:05') 
+
+
+#2 To get the date and time portion of the timestamp '2017-01-02T03:04:05' plus one
+ minute:
+ ;SELECT datetime('2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To get the date and time portion of the epoch timestamp 1491341842:
+ ;SELECT datetime(1491341842, 'unixepoch') 
+
+
+
+decode(value, algorithm)
+══════════════════════════════════════════════════════════════════════
+ Decode the value using the given algorithm
+Parameters
+ value The value to decode
+ algorithm One of the following encoding algorithms:
+ base64, hex, uri
+See Also
+ anonymize(), char(), charindex(), encode(), endswith(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To decode the URI-encoded string '%63%75%72%6c':
+ ;SELECT decode('%63%75%72%6c', 'uri') 
+
+
+
+degrees(radians)
+══════════════════════════════════════════════════════════════════════
+ Converts radians to degrees
+Parameter
+ radians The radians value to convert to degrees
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To convert PI to degrees:
+ ;SELECT degrees(pi()) 
+
+
+
+dense_rank()
+══════════════════════════════════════════════════════════════════════
+ Returns the row_number() of the first peer in each group without
+ gaps
+See Also
+ cume_dist(), first_value(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+dirname(path)
+══════════════════════════════════════════════════════════════════════
+ Extract the directory portion of a pathname.
+Parameter
+ path The path
+See Also
+ basename(), joinpath(), readlink(), realpath()
+Examples
+#1 To get the directory of a relative file path:
+ ;SELECT dirname('foo/bar') 
+
+
+#2 To get the directory of an absolute file path:
+ ;SELECT dirname('/foo/bar') 
+
+
+#3 To get the directory of a file in the root directory:
+ ;SELECT dirname('/bar') 
+
+
+#4 To get the directory of a Windows path:
+ ;SELECT dirname('foo\bar') 
+
+
+#5 To get the directory of an empty path:
+ ;SELECT dirname('') 
+
+
+
+echoln(value)
+══════════════════════════════════════════════════════════════════════
+ Echo the argument to the current output file and return it
+Parameter
+ value The value to write to the current output file
+See Also
+ :append-to, :echo, :export-session-to, :pipe-line-to, :pipe-to,
+ :redirect-to, :write-csv-to, :write-json-to, :write-jsonlines-to,
+ :write-raw-to, :write-screen-to, :write-table-to, :write-to,
+ :write-view-to
+
+encode(value, algorithm)
+══════════════════════════════════════════════════════════════════════
+ Encode the value using the given algorithm
+Parameters
+ value The value to encode
+ algorithm One of the following encoding algorithms:
+ base64, hex, uri
+See Also
+ anonymize(), char(), charindex(), decode(), endswith(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To base64-encode 'Hello, World!':
+ ;SELECT encode('Hello, World!', 'base64') 
+
+
+#2 To hex-encode 'Hello, World!':
+ ;SELECT encode('Hello, World!', 'hex') 
+
+
+#3 To URI-encode 'Hello, World!':
+ ;SELECT encode('Hello, World!', 'uri') 
+
+
+
+endswith(str, suffix)
+══════════════════════════════════════════════════════════════════════
+ Test if a string ends with the given suffix
+Parameters
+ str The string to test
+ suffix The suffix to check in the string
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), extract(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To test if the string 'notbad.jpg' ends with '.jpg':
+ ;SELECT endswith('notbad.jpg', '.jpg') 
+
+
+#2 To test if the string 'notbad.png' starts with '.jpg':
+ ;SELECT endswith('notbad.png', '.jpg') 
+
+
+
+exp(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the value of e raised to the power of x
+Parameter
+ x The exponent
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), floor(), log(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To raise e to 2:
+ ;SELECT exp(2) 
+
+
+
+extract(str)
+══════════════════════════════════════════════════════════════════════
+ Automatically Parse and extract data from a string
+Parameter
+ str The string to parse
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To extract key/value pairs from a string:
+ ;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"') 
+
+
+#2 To extract columnar data from a string:
+ ;SELECT extract('1.0 abc 2.0') 
+
+
+
+first_value(expr)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the first
+ row in the window frame.
+Parameter
+ expr The expression to execute over the first row
+See Also
+ cume_dist(), dense_rank(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+floor(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the largest integer that is not greater than the argument
+Parameter
+ num The number to lower to the floor
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the floor of 1.23:
+ ;SELECT floor(1.23) 
+
+
+
+generate_series(start, stop, [step])
+══════════════════════════════════════════════════════════════════════
+ A table-valued-function that returns the whole numbers between a
+ lower and upper bound, inclusive
+Parameters
+ start The starting point of the series
+ stop The stopping point of the series
+ step The increment between each value
+Result
+ value The number in the series
+
+Examples
+#1 To generate the numbers in the range [10, 14]:
+ ;SELECT value FROM generate_series(10, 14) 
+
+
+#2 To generate every other number in the range [10, 14]:
+ ;SELECT value FROM generate_series(10, 14, 2) 
+
+
+#3 To count down from five to 1:
+ ;SELECT value FROM generate_series(1, 5, -1) 
+
+
+
+gethostbyaddr(hostname)
+══════════════════════════════════════════════════════════════════════
+ Get the hostname for the given IP address
+Parameter
+ hostname The IP address to lookup.
+See Also
+ gethostbyname()
+Example
+#1 To get the hostname for the IP '127.0.0.1':
+ ;SELECT gethostbyaddr('127.0.0.1') 
+
+
+
+gethostbyname(hostname)
+══════════════════════════════════════════════════════════════════════
+ Get the IP address for the given hostname
+Parameter
+ hostname The DNS hostname to lookup.
+See Also
+ gethostbyaddr()
+Example
+#1 To get the IP address for 'localhost':
+ ;SELECT gethostbyname('localhost') 
+
+
+
+glob(pattern, str)
+══════════════════════════════════════════════════════════════════════
+ Match a string against Unix glob pattern
+Parameters
+ pattern The glob pattern
+ str The string to match
+
+Example
+#1 To test if the string 'abc' matches the glob 'a*':
+ ;SELECT glob('a*', 'abc') 
+
+
+
+group_concat(X, [sep])
+══════════════════════════════════════════════════════════════════════
+ Returns a string which is the concatenation of all non-NULL values
+ of X separated by a comma or the given separator.
+Parameters
+ X The value to concatenate.
+ sep The separator to place between the values.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_spooky_hash(), gunzip(), gzip(), humanize_duration(),
+ humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
+ lower(), ltrim(), padc(), padl(), padr(), parse_url(), printf(),
+ proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), unparse_url(), upper(), xpath()
+Examples
+#1 To concatenate the values of the column 'ex_procname' from the table
+ 'lnav_example_log':
+ ;SELECT group_concat(ex_procname) FROM lnav_example_log
+
+
+#2 To join the values of the column 'ex_procname' using the string ', ':
+ ;SELECT group_concat(ex_procname, ', ') FROM lnav_example_log
+
+
+#3 To concatenate the distinct values of the column 'ex_procname' from the table
+ 'lnav_example_log':
+ ;SELECT group_concat(DISTINCT ex_procname) FROM lnav_example_log
+
+
+
+group_spooky_hash(str, ...)
+══════════════════════════════════════════════════════════════════════
+ Compute the hash value for the given arguments
+Parameter
+ str The string to hash
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), gunzip(), gzip(), humanize_duration(),
+ humanize_file_size(), instr(), leftstr(), length(), logfmt2json(),
+ lower(), ltrim(), padc(), padl(), padr(), parse_url(), printf(),
+ proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), unparse_url(), upper(), xpath()
+Example
+#1 To produce a hash of all of the values of 'column1':
+ ;SELECT group_spooky_hash(column1) FROM (VALUES ('abc'), ('123'))
+
+
+
+gunzip(b, ...)
+══════════════════════════════════════════════════════════════════════
+ Decompress a gzip file
+Parameter
+ b The blob to decompress
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+
+gzip(value, ...)
+══════════════════════════════════════════════════════════════════════
+ Compress a string into a gzip file
+Parameter
+ value The value to compress
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+
+hex(X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string which is the upper-case hexadecimal rendering of
+ the content of its argument.
+Parameter
+ X The blob to convert to hexadecimal
+
+Example
+#1 To get the hexadecimal rendering of the string 'abc':
+ ;SELECT hex('abc') 
+
+
+
+humanize_duration(secs)
+══════════════════════════════════════════════════════════════════════
+ Format the given seconds value as an abbreviated duration string
+Parameter
+ secs The duration in seconds
+See Also
+ anonymize(), char(), charindex(), date(), datetime(), decode(),
+ encode(), endswith(), extract(), group_concat(), group_spooky_hash(),
+ gunzip(), gzip(), humanize_file_size(), instr(), julianday(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), strftime(), substr(), time(),
+ timediff(), timeslice(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To format a duration:
+ ;SELECT humanize_duration(15 * 60) 
+
+
+#2 To format a sub-second value:
+ ;SELECT humanize_duration(1.5) 
+
+
+
+humanize_file_size(value)
+══════════════════════════════════════════════════════════════════════
+ Format the given file size as a human-friendly string
+Parameter
+ value The file size to format
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), instr(), leftstr(), length(), logfmt2json(),
+ lower(), ltrim(), padc(), padl(), padr(), parse_url(), printf(),
+ proper(), regexp_capture(), regexp_capture_into_json(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), unparse_url(), upper(), xpath()
+Example
+#1 To format an amount:
+ ;SELECT humanize_file_size(10 * 1024 * 1024) 
+
+
+
+ifnull(X, Y)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of its first non-NULL argument, or NULL if both
+ arguments are NULL
+Parameters
+ X A value to check for NULL-ness
+ Y A value to check for NULL-ness
+
+Example
+#1 To get the first non-null value between null and zero:
+ ;SELECT ifnull(null, 0) 
+
+
+
+instr(haystack, needle)
+══════════════════════════════════════════════════════════════════════
+ Finds the first occurrence of the needle within the haystack and
+ returns the number of prior characters plus 1, or 0 if the needle
+ was not found
+Parameters
+ haystack The string to search within
+ needle The string to look for in the haystack
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To test get the position of 'b' in the string 'abc':
+ ;SELECT instr('abc', 'b') 
+
+
+
+jget(json, ptr, [default])
+══════════════════════════════════════════════════════════════════════
+ Get the value from a JSON object using a JSON-Pointer.
+Parameters
+ json The JSON object to query.
+ ptr The JSON-Pointer to lookup in the object.
+ default The default value if the value was not found
+See Also
+ json_concat(), json_contains(), json_group_array(),
+ json_group_object(), yaml_to_json()
+Examples
+#1 To get the root of a JSON value:
+ ;SELECT jget('1', '') 
+
+
+#2 To get the property named 'b' in a JSON object:
+ ;SELECT jget('{ "a": 1, "b": 2 }', '/b') 
+
+
+#3 To get the 'msg' property and return a default if it does not exist:
+ ;SELECT jget(null, '/msg', 'Hello') 
+
+
+
+joinpath(path, ...)
+══════════════════════════════════════════════════════════════════════
+ Join components of a path together.
+Parameter
+ path One or more path components to join together. If an
+ argument starts with a forward or backward slash, it will be
+ considered an absolute path and any preceding elements will
+ be ignored.
+See Also
+ basename(), dirname(), readlink(), realpath()
+Examples
+#1 To join a directory and file name into a relative path:
+ ;SELECT joinpath('foo', 'bar') 
+
+
+#2 To join an empty component with other names into a relative path:
+ ;SELECT joinpath('', 'foo', 'bar') 
+
+
+#3 To create an absolute path with two path components:
+ ;SELECT joinpath('/', 'foo', 'bar') 
+
+
+#4 To create an absolute path from a path component that starts with a forward slash:
+ ;SELECT joinpath('/', 'foo', '/bar') 
+
+
+
+json_concat(json, value, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns an array with the given values concatenated onto the end.
+ If the initial value is null, the result will be an array with the
+ given elements. If the initial value is an array, the result will
+ be an array with the given values at the end. If the initial value
+ is not null or an array, the result will be an array with two
+ elements: the initial value and the given value.
+Parameters
+ json The initial JSON value.
+ value The value(s) to add to the end of the array.
+See Also
+ jget(), json_contains(), json_group_array(), json_group_object(),
+ yaml_to_json()
+Examples
+#1 To append the number 4 to null:
+ ;SELECT json_concat(NULL, 4) 
+
+
+#2 To append 4 and 5 to the array [1, 2, 3]:
+ ;SELECT json_concat('[1, 2, 3]', 4, 5) 
+
+
+#3 To concatenate two arrays together:
+ ;SELECT json_concat('[1, 2, 3]', json('[4, 5]')) 
+
+
+
+json_contains(json, value)
+══════════════════════════════════════════════════════════════════════
+ Check if a JSON value contains the given element.
+Parameters
+ json The JSON value to query.
+ value The value to look for in the first argument
+See Also
+ jget(), json_concat(), json_group_array(), json_group_object(),
+ yaml_to_json()
+Examples
+#1 To test if a JSON array contains the number 4:
+ ;SELECT json_contains('[1, 2, 3]', 4) 
+
+
+#2 To test if a JSON array contains the string 'def':
+ ;SELECT json_contains('["abc", "def"]', 'def') 
+
+
+
+json_group_array(value, ...)
+══════════════════════════════════════════════════════════════════════
+ Collect the given values from a query into a JSON array
+Parameter
+ value The values to append to the array
+See Also
+ jget(), json_concat(), json_contains(), json_group_object(),
+ yaml_to_json()
+Examples
+#1 To create an array from arguments:
+ ;SELECT json_group_array('one', 2, 3.4) 
+
+
+#2 To create an array from a column of values:
+ ;SELECT json_group_array(column1) FROM (VALUES (1), (2), (3))
+
+
+
+json_group_object(name, value, ...)
+══════════════════════════════════════════════════════════════════════
+ Collect the given values from a query into a JSON object
+Parameters
+ name The property name for the value
+ value The value to add to the object
+See Also
+ jget(), json_concat(), json_contains(), json_group_array(),
+ yaml_to_json()
+Examples
+#1 To create an object from arguments:
+ ;SELECT json_group_object('a', 1, 'b', 2) 
+
+
+#2 To create an object from a pair of columns:
+ ;SELECT json_group_object(column1, column2) FROM (VALUES ('a', 1), ('b', 2))
+
+
+
+julianday(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of days since noon in Greenwich on November 24,
+ 4714 B.C.
+Parameters
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the
+ value to the left.
+See Also
+ date(), datetime(), humanize_duration(), strftime(), time(),
+ timediff(), timeslice()
+Examples
+#1 To get the julian day from the timestamp '2017-01-02T03:04:05':
+ ;SELECT julianday('2017-01-02T03:04:05') 
+
+
+#2 To get the julian day from the timestamp '2017-01-02T03:04:05' plus one minute:
+ ;SELECT julianday('2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To get the julian day from the timestamp 1491341842:
+ ;SELECT julianday(1491341842, 'unixepoch') 
+
+
+
+lag(expr, [offset], [default])
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the previous
+ row in the partition.
+Parameters
+ expr The expression to execute over the previous row
+ offset The offset from the current row in the partition
+ default The default value if the previous row does not
+ exist instead of NULL
+See Also
+ cume_dist(), dense_rank(), first_value(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), rank(), row_number()
+
+last_insert_rowid()
+══════════════════════════════════════════════════════════════════════
+ Returns the ROWID of the last row insert from the database
+ connection which invoked the function
+
+
+last_value(expr)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the last row
+ in the window frame.
+Parameter
+ expr The expression to execute over the last row
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+lead(expr, [offset], [default])
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the next row
+ in the partition.
+Parameters
+ expr The expression to execute over the next row
+ offset The offset from the current row in the partition
+ default The default value if the next row does not exist
+ instead of NULL
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(),
+ nth_value(), ntile(), percent_rank(), rank(), row_number()
+
+leftstr(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N leftmost (UTF-8) characters in the given string.
+Parameters
+ str The string to return subset.
+ N The number of characters from the left side of the
+ string to return.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To get the first character of the string 'abc':
+ ;SELECT leftstr('abc', 1) 
+
+
+#2 To get the first ten characters of a string, regardless of size:
+ ;SELECT leftstr('abc', 10) 
+
+
+
+length(str)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of characters (not bytes) in the given string
+ prior to the first NUL character
+Parameter
+ str The string to determine the length of
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To get the length of the string 'abc':
+ ;SELECT length('abc') 
+
+
+
+like(pattern, str, [escape])
+══════════════════════════════════════════════════════════════════════
+ Match a string against a pattern
+Parameters
+ pattern The pattern to match. A percent symbol (%) will
+ match zero or more characters and an underscore (_) will
+ match a single character.
+ str The string to match
+ escape The escape character that can be used to prefix
+ a literal percent or underscore in the pattern.
+
+Examples
+#1 To test if the string 'aabcc' contains the letter 'b':
+ ;SELECT like('%b%', 'aabcc') 
+
+
+#2 To test if the string 'aab%' ends with 'b%':
+ ;SELECT like('%b:%', 'aab%', ':') 
+
+
+
+likelihood(value, probability)
+══════════════════════════════════════════════════════════════════════
+ Provides a hint to the query planner that the first argument is a
+ boolean that is true with the given probability
+Parameters
+ value The boolean value to return
+ probability A floating point constant between 0.0
+ and 1.0
+
+
+likely(value)
+══════════════════════════════════════════════════════════════════════
+ Short-hand for likelihood(X,0.9375)
+Parameter
+ value The boolean value to return
+
+
+lnav_top_file()
+══════════════════════════════════════════════════════════════════════
+ Return the name of the file that the top line in the current view
+ came from.
+
+
+lnav_version()
+══════════════════════════════════════════════════════════════════════
+ Return the current version of lnav
+
+
+load_extension(path, [entry-point])
+══════════════════════════════════════════════════════════════════════
+ Loads SQLite extensions out of the given shared library file using
+ the given entry point.
+Parameters
+ path The path to the shared library
+ containing the extension.
+ entry-point
+
+
+log(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the natural logarithm of x
+Parameter
+ x The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To get the natual logarithm of 8:
+ ;SELECT log(8) 
+
+
+
+log10(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the base-10 logarithm of X
+Parameter
+ x The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the logarithm of 100:
+ ;SELECT log10(100) 
+
+
+
+log_top_datetime()
+══════════════════════════════════════════════════════════════════════
+ Return the timestamp of the line at the top of the log view.
+
+
+log_top_line()
+══════════════════════════════════════════════════════════════════════
+ Return the line number at the top of the log view.
+
+
+logfmt2json(str)
+══════════════════════════════════════════════════════════════════════
+ Convert a logfmt-encoded string into JSON
+Parameter
+ str The logfmt message to parse
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), lower(), ltrim(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To extract key/value pairs from a log message:
+ ;SELECT logfmt2json('foo=1 bar=2 name="Rolo Tomassi"')
+
+
+
+lower(str)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of the given string with all ASCII characters
+ converted to lower case.
+Parameter
+ str The string to convert.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), ltrim(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To lowercase the string 'AbC':
+ ;SELECT lower('AbC') 
+
+
+
+ltrim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the left side of the first.
+Parameters
+ str The string to trim characters from the left side
+ chars The characters to trim. Defaults to spaces.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), padc(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To trim the leading space characters from the string ' abc':
+ ;SELECT ltrim(' abc') 
+
+
+#2 To trim the characters 'a' or 'b' from the left side of the string 'aaaabbbc':
+ ;SELECT ltrim('aaaabbbc', 'ab') 
+
+
+
+max(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the argument with the maximum value, or return NULL if any
+ argument is NULL.
+Parameter
+ X The numbers to find the maximum of. If only one argument is
+ given, this function operates as an aggregate.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the largest value from the parameters:
+ ;SELECT max(2, 1, 3) 
+
+
+#2 To get the largest value from an aggregate:
+ ;SELECT max(status) FROM http_status_codes 
+
+
+
+min(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the argument with the minimum value, or return NULL if any
+ argument is NULL.
+Parameter
+ X The numbers to find the minimum of. If only one argument is
+ given, this function operates as an aggregate.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the smallest value from the parameters:
+ ;SELECT min(2, 1, 3) 
+
+
+#2 To get the smallest value from an aggregate:
+ ;SELECT min(status) FROM http_status_codes 
+
+
+
+nth_value(expr, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the nth row
+ in the window frame.
+Parameters
+ expr The expression to execute over the nth row
+ N The row number
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ ntile(), percent_rank(), rank(), row_number()
+
+ntile(groups)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of the group that the current row is a part of
+Parameter
+ groups The number of groups
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), percent_rank(), rank(), row_number()
+
+nullif(X, Y)
+══════════════════════════════════════════════════════════════════════
+ Returns its first argument if the arguments are different and NULL
+ if the arguments are the same.
+Parameters
+ X The first argument to compare.
+ Y The argument to compare against the first.
+
+Examples
+#1 To test if 1 is different from 1:
+ ;SELECT nullif(1, 1) 
+
+
+#2 To test if 1 is different from 2:
+ ;SELECT nullif(1, 2) 
+
+
+
+padc(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with enough spaces to make it centered within
+ the given length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padl(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padc('abc', 6) || 'def' 
+
+
+#2 To pad the string 'abcdef' to a length of eight characters:
+ ;SELECT padc('abcdef', 8) || 'ghi' 
+
+
+
+padl(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with leading spaces until it reaches the
+ desired length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padr(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padl('abc', 6) 
+
+
+#2 To pad the string 'abcdef' to a length of four characters:
+ ;SELECT padl('abcdef', 4) 
+
+
+
+padr(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with trailing spaces until it reaches the
+ desired length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), parse_url(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padr('abc', 6) || 'def' 
+
+
+#2 To pad the string 'abcdef' to a length of four characters:
+ ;SELECT padr('abcdef', 4) || 'ghi' 
+
+
+
+parse_url(url)
+══════════════════════════════════════════════════════════════════════
+ Parse a URL and return the components in a JSON object. Limitations:
+ not all URL schemes are supported and repeated query parameters are
+ not captured.
+Parameter
+ url The URL to parse
+Results
+ scheme The URL's scheme
+ username The name of the user specified in the URL
+ password The password specified in the URL
+ host The host name / IP specified in the URL
+ port The port specified in the URL
+ path The path specified in the URL
+ query The query string in the URL
+ parameters An object containing the query parameters
+ fragment The fragment specified in the URL
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), unparse_url(),
+ upper(), xpath()
+Examples
+#1 To parse the URL 'https://example.com/search?q=hello%20world':
+ ;SELECT parse_url('https://example.com/search?q=hello%20world')
+
+
+#2 To parse the URL 'https://alice@[fe80::14ff:4ee5:1215:2fb2]':
+ ;SELECT parse_url('https://alice@[fe80::14ff:4ee5:1215:2fb2]')
+
+
+
+percent_rank()
+══════════════════════════════════════════════════════════════════════
+ Returns (rank - 1) / (partition-rows - 1)
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), rank(), row_number()
+
+pi()
+══════════════════════════════════════════════════════════════════════
+ Returns the value of PI
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To get the value of PI:
+ ;SELECT pi() 
+
+
+
+power(base, exp)
+══════════════════════════════════════════════════════════════════════
+ Returns the base to the given exponent
+Parameters
+ base The base number
+ exp The exponent
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To raise two to the power of three:
+ ;SELECT power(2, 3) 
+
+
+
+printf(format, X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string with this functions arguments substituted into the
+ given format. Substitution points are specified using percent (%)
+ options, much like the standard C printf() function.
+Parameters
+ format The format of the string to return.
+ X The argument to substitute at a given position in
+ the format.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), proper(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Examples
+#1 To substitute 'World' into the string 'Hello, %s!':
+ ;SELECT printf('Hello, %s!', 'World') 
+
+
+#2 To right-align 'small' in the string 'align:' with a column width of 10:
+ ;SELECT printf('align: % 10s', 'small') 
+
+
+#3 To format 11 with a width of five characters and leading zeroes:
+ ;SELECT printf('value: %05d', 11) 
+
+
+
+proper(str)
+══════════════════════════════════════════════════════════════════════
+ Capitalize the first character of words in the given string
+Parameter
+ str The string to capitalize.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), regexp_capture(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To capitalize the words in the string 'hello, world!':
+ ;SELECT proper('hello, world!') 
+
+
+
+quote(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the text of an SQL literal which is the value of its
+ argument suitable for inclusion into an SQL statement.
+Parameter
+ X The string to quote.
+
+Examples
+#1 To quote the string 'abc':
+ ;SELECT quote('abc') 
+
+
+#2 To quote the string 'abc'123':
+ ;SELECT quote('abc''123') 
+
+
+
+radians(degrees)
+══════════════════════════════════════════════════════════════════════
+ Converts degrees to radians
+Parameter
+ degrees The degrees value to convert to radians
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), round(), sign(), square(), sum(), total()
+Example
+#1 To convert 180 degrees to radians:
+ ;SELECT radians(180) 
+
+
+
+raise_error(msg)
+══════════════════════════════════════════════════════════════════════
+ Raises an error with the given message when executed
+Parameter
+ msg The error message
+
+
+random()
+══════════════════════════════════════════════════════════════════════
+ Returns a pseudo-random integer between -9223372036854775808 and
+ +9223372036854775807.
+
+
+randomblob(N)
+══════════════════════════════════════════════════════════════════════
+ Return an N-byte blob containing pseudo-random bytes.
+Parameter
+ N The size of the blob in bytes.
+
+
+rank()
+══════════════════════════════════════════════════════════════════════
+ Returns the row_number() of the first peer in each group with gaps
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), row_number()
+
+readlink(path)
+══════════════════════════════════════════════════════════════════════
+ Read the target of a symbolic link.
+Parameter
+ path The path to the symbolic link.
+See Also
+ basename(), dirname(), joinpath(), realpath()
+
+realpath(path)
+══════════════════════════════════════════════════════════════════════
+ Returns the resolved version of the given path, expanding symbolic
+ links and resolving '.' and '..' references.
+Parameter
+ path The path to resolve.
+See Also
+ basename(), dirname(), joinpath(), readlink()
+
+regexp(re, str)
+══════════════════════════════════════════════════════════════════════
+ Test if a string matches a regular expression
+Parameters
+ re The regular expression to use
+ str The string to test against the regular expression
+
+
+regexp_capture(string, pattern)
+══════════════════════════════════════════════════════════════════════
+ A table-valued function that executes a regular-expression over a
+ string and returns the captured values. If the regex only matches a
+ subset of the input string, it will be rerun on the remaining parts
+ of the string until no more matches are found.
+Parameters
+ string The string to match against the given pattern.
+ pattern The regular expression to match.
+Results
+ match_index The match iteration. This value
+ will increase each time a new match is found in the
+ input string.
+ capture_index The index of the capture in the
+ regex.
+ capture_name The name of the capture in the
+ regex.
+ capture_count The total number of captures in the
+ regex.
+ range_start The start of the capture in the
+ input string.
+ range_stop The stop of the capture in the input
+ string.
+ content The captured value from the string.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture_into_json(),
+ regexp_match(), regexp_replace(), replace(), replicate(), reverse(),
+ rightstr(), rtrim(), sparkline(), spooky_hash(), startswith(),
+ strfilter(), substr(), trim(), unicode(), unparse_url(), upper(),
+ xpath()
+Example
+#1 To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2':
+ ;SELECT * FROM regexp_capture('a=1; b=2', '(\w+)=(\d+)')
+
+
+
+regexp_capture_into_json(string, pattern, [options])
+══════════════════════════════════════════════════════════════════════
+ A table-valued function that executes a regular-expression over a
+ string and returns the captured values as a JSON object. If the
+ regex only matches a subset of the input string, it will be rerun on
+ the remaining parts of the string until no more matches are found.
+Parameters
+ string The string to match against the given pattern.
+ pattern The regular expression to match.
+ options A JSON object with the following option:
+ convert-numbers - True (default) if text that looks like
+ numeric data should be converted to JSON numbers, false if
+ they should be captured as strings.
+Results
+ match_index The match iteration. This value will
+ increase each time a new match is found in the input
+ string.
+ content The captured values from the string.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), unparse_url(), upper(), xpath()
+Example
+#1 To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2':
+ ;SELECT * FROM regexp_capture_into_json('a=1; b=2', '(\w+)=(\d+)')
+
+
+
+regexp_match(re, str)
+══════════════════════════════════════════════════════════════════════
+ Match a string against a regular expression and return the capture
+ groups as JSON.
+Parameters
+ re The regular expression to use
+ str The string to test against the regular expression
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_replace(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To capture the digits from the string '123':
+ ;SELECT regexp_match('(\d+)', '123') 
+
+
+#2 To capture a number and word into a JSON object with the properties 'col_0' and
+ 'col_1':
+ ;SELECT regexp_match('(\d+) (\w+)', '123 four') 
+
+
+#3 To capture a number and word into a JSON object with the named properties 'num' and
+ 'str':
+ ;SELECT regexp_match('(?<num>\d+) (?<str>\w+)', '123 four')
+
+
+
+regexp_replace(str, re, repl)
+══════════════════════════════════════════════════════════════════════
+ Replace the parts of a string that match a regular expression.
+Parameters
+ str The string to perform replacements on
+ re The regular expression to match
+ repl The replacement string. You can reference capture
+ groups with a backslash followed by the number of the group,
+ starting with 1.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_match(), replace(),
+ replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To replace the word at the start of the string 'Hello, World!' with 'Goodbye':
+ ;SELECT regexp_replace('Hello, World!', '^(\w+)', 'Goodbye')
+
+
+#2 To wrap alphanumeric words with angle brackets:
+ ;SELECT regexp_replace('123 abc', '(\w+)', '<\1>') 
+
+
+
+replace(str, old, replacement)
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by substituting the replacement string for
+ every occurrence of the old string in the given string.
+Parameters
+ str The string to perform substitutions on.
+ old The string to be replaced.
+ replacement The string to replace any occurrences of
+ the old string with.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To replace the string 'x' with 'z' in 'abc':
+ ;SELECT replace('abc', 'x', 'z') 
+
+
+#2 To replace the string 'a' with 'z' in 'abc':
+ ;SELECT replace('abc', 'a', 'z') 
+
+
+
+replicate(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the given string concatenated N times.
+Parameters
+ str The string to replicate.
+ N The number of times to replicate the string.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), reverse(), rightstr(), rtrim(), sparkline(), spooky_hash(),
+ startswith(), strfilter(), substr(), trim(), unicode(), unparse_url(),
+ upper(), xpath()
+Example
+#1 To repeat the string 'abc' three times:
+ ;SELECT replicate('abc', 3) 
+
+
+
+reverse(str)
+══════════════════════════════════════════════════════════════════════
+ Returns the reverse of the given string.
+Parameter
+ str The string to reverse.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To reverse the string 'abc':
+ ;SELECT reverse('abc') 
+
+
+
+rightstr(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N rightmost (UTF-8) characters in the given string.
+Parameters
+ str The string to return subset.
+ N The number of characters from the right side of the
+ string to return.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rtrim(), sparkline(), spooky_hash(),
+ startswith(), strfilter(), substr(), trim(), unicode(), unparse_url(),
+ upper(), xpath()
+Examples
+#1 To get the last character of the string 'abc':
+ ;SELECT rightstr('abc', 1) 
+
+
+#2 To get the last ten characters of a string, regardless of size:
+ ;SELECT rightstr('abc', 10) 
+
+
+
+round(num, [digits])
+══════════════════════════════════════════════════════════════════════
+ Returns a floating-point value rounded to the given number of digits
+ to the right of the decimal point.
+Parameters
+ num The value to round.
+ digits The number of digits to the right of the decimal
+ to round to.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), sign(), square(), sum(),
+ total()
+Examples
+#1 To round the number 123.456 to an integer:
+ ;SELECT round(123.456) 
+
+
+#2 To round the number 123.456 to a precision of 1:
+ ;SELECT round(123.456, 1) 
+
+
+#3 To round the number 123.456 to a precision of 5:
+ ;SELECT round(123.456, 5) 
+
+
+
+row_number()
+══════════════════════════════════════════════════════════════════════
+ Returns the number of the row within the current partition, starting
+ from 1.
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), rank()
+Example
+#1 To number messages from a process:
+ ;SELECT row_number() OVER (PARTITION BY ex_procname ORDER BY log_line) AS msg_num,
+  ex_procname, log_body FROM lnav_example_log
+
+
+
+rtrim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the right side of the first.
+Parameters
+ str The string to trim characters from the right side
+ chars The characters to trim. Defaults to spaces.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To trim the space characters from the end of the string 'abc ':
+ ;SELECT rtrim('abc ') 
+
+
+#2 To trim the characters 'b' and 'c' from the string 'abbbbcccc':
+ ;SELECT rtrim('abbbbcccc', 'bc') 
+
+
+
+sign(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the sign of the given number as -1, 0, or 1
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), square(), sum(),
+ total()
+Examples
+#1 To get the sign of 10:
+ ;SELECT sign(10) 
+
+
+#2 To get the sign of 0:
+ ;SELECT sign(0) 
+
+
+#3 To get the sign of -10:
+ ;SELECT sign(-10) 
+
+
+
+sparkline(value, [upper])
+══════════════════════════════════════════════════════════════════════
+ Function used to generate a sparkline bar chart. The non-aggregate
+ version converts a single numeric value on a range to a bar chart
+ character. The aggregate version returns a string with a bar
+ character for every numeric input
+Parameters
+ value The numeric value to convert
+ upper The upper bound of the numeric range. The
+ non-aggregate version defaults to 100. The aggregate
+ version uses the largest value in the inputs.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), spooky_hash(),
+ startswith(), strfilter(), substr(), trim(), unicode(), unparse_url(),
+ upper(), xpath()
+Examples
+#1 To get the unicode block element for the value 32 in the range of 0-128:
+ ;SELECT sparkline(32, 128) 
+
+
+#2 To chart the values in a JSON array:
+ ;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
+
+
+
+spooky_hash(str, ...)
+══════════════════════════════════════════════════════════════════════
+ Compute the hash value for the given arguments.
+Parameter
+ str The string to hash
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ startswith(), strfilter(), substr(), trim(), unicode(), unparse_url(),
+ upper(), xpath()
+Examples
+#1 To produce a hash for the string 'Hello, World!':
+ ;SELECT spooky_hash('Hello, World!') 
+
+
+#2 To produce a hash for the parameters where one is NULL:
+ ;SELECT spooky_hash('Hello, World!', NULL) 
+
+
+#3 To produce a hash for the parameters where one is an empty string:
+ ;SELECT spooky_hash('Hello, World!', '') 
+
+
+#4 To produce a hash for the parameters where one is a number:
+ ;SELECT spooky_hash('Hello, World!', 123) 
+
+
+
+sqlite_compileoption_get(N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N-th compile-time option used to build SQLite or NULL if
+ N is out of range.
+Parameter
+ N The option number to get
+
+
+sqlite_compileoption_used(option)
+══════════════════════════════════════════════════════════════════════
+ Returns true (1) or false (0) depending on whether or not that
+ compile-time option was used during the build.
+Parameter
+ option The name of the compile-time option.
+
+Example
+#1 To check if the SQLite library was compiled with ENABLE_FTS3:
+ ;SELECT sqlite_compileoption_used('ENABLE_FTS3') 
+
+
+
+sqlite_source_id()
+══════════════════════════════════════════════════════════════════════
+ Returns a string that identifies the specific version of the source
+ code that was used to build the SQLite library.
+
+
+sqlite_version()
+══════════════════════════════════════════════════════════════════════
+ Returns the version string for the SQLite library that is running.
+
+
+square(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the square of the argument
+Parameter
+ num The number to square
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), sum(),
+ total()
+Example
+#1 To get the square of two:
+ ;SELECT square(2) 
+
+
+
+startswith(str, prefix)
+══════════════════════════════════════════════════════════════════════
+ Test if a string begins with the given prefix
+Parameters
+ str The string to test
+ prefix The prefix to check in the string
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), strfilter(), substr(), trim(), unicode(), unparse_url(),
+ upper(), xpath()
+Examples
+#1 To test if the string 'foobar' starts with 'foo':
+ ;SELECT startswith('foobar', 'foo') 
+
+
+#2 To test if the string 'foobar' starts with 'bar':
+ ;SELECT startswith('foobar', 'bar') 
+
+
+
+strfilter(source, include)
+══════════════════════════════════════════════════════════════════════
+ Returns the source string with only the characters given in the
+ second parameter
+Parameters
+ source The string to filter
+ include The characters to include in the result
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), substr(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To get the 'b', 'c', and 'd' characters from the string 'abcabc':
+ ;SELECT strfilter('abcabc', 'bcd') 
+
+
+
+strftime(format, timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date formatted according to the format string specified
+ as the first argument.
+Parameters
+ format A format string with substitutions similar
+ to those found in the strftime() standard C library.
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the
+ value to the left.
+See Also
+ date(), datetime(), humanize_duration(), julianday(), time(),
+ timediff(), timeslice()
+Examples
+#1 To get the year from the timestamp '2017-01-02T03:04:05':
+ ;SELECT strftime('%Y', '2017-01-02T03:04:05') 
+
+
+#2 To create a string with the time from the timestamp '2017-01-02T03:04:05' plus one
+ minute:
+ ;SELECT strftime('The time is: %H:%M:%S', '2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To create a string with the Julian day from the epoch timestamp 1491341842:
+ ;SELECT strftime('Julian day: %J', 1491341842, 'unixepoch')
+
+
+
+substr(str, start, [size])
+══════════════════════════════════════════════════════════════════════
+ Returns a substring of input string X that begins with the Y-th
+ character and which is Z characters long.
+Parameters
+ str The string to extract a substring from.
+ start The index within 'str' that is the start of the
+ substring. Indexes begin at 1. A negative value means that
+ the substring is found by counting from the right rather
+ than the left.
+ size The size of the substring. If not given, then all
+ characters through the end of the string are returned. If
+ the value is negative, then the characters before the start
+ are returned.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), trim(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To get the substring starting at the second character until the end of the string
+ 'abc':
+ ;SELECT substr('abc', 2) 
+
+
+#2 To get the substring of size one starting at the second character of the string
+ 'abc':
+ ;SELECT substr('abc', 2, 1) 
+
+
+#3 To get the substring starting at the last character until the end of the string
+ 'abc':
+ ;SELECT substr('abc', -1) 
+
+
+#4 To get the substring starting at the last character and going backwards one step of
+ the string 'abc':
+ ;SELECT substr('abc', -1, -1) 
+
+
+
+sum(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the sum of the values in the group as an integer.
+Parameter
+ X The values to add.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), square(),
+ total()
+Example
+#1 To sum all of the values in the column 'ex_duration' from the table
+ 'lnav_example_log':
+ ;SELECT sum(ex_duration) FROM lnav_example_log 
+
+
+
+time(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the time in this format: HH:MM:SS.
+Parameters
+ timestring The string to convert to a time.
+ modifier A transformation that is applied to the
+ value to the left.
+See Also
+ date(), datetime(), humanize_duration(), julianday(), strftime(),
+ timediff(), timeslice()
+Examples
+#1 To get the time portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT time('2017-01-02T03:04:05') 
+
+
+#2 To get the time portion of the timestamp '2017-01-02T03:04:05' plus one minute:
+ ;SELECT time('2017-01-02T03:04:05', '+1 minute') 
+
+
+#3 To get the time portion of the epoch timestamp 1491341842:
+ ;SELECT time(1491341842, 'unixepoch') 
+
+
+
+timediff(time1, time2)
+══════════════════════════════════════════════════════════════════════
+ Compute the difference between two timestamps in seconds
+Parameters
+ time1 The first timestamp
+ time2 The timestamp to subtract from the first
+See Also
+ date(), datetime(), humanize_duration(), julianday(), strftime(),
+ time(), timeslice()
+Examples
+#1 To get the difference between two timestamps:
+ ;SELECT timediff('2017-02-03T04:05:06', '2017-02-03T04:05:00')
+
+
+#2 To get the difference between relative timestamps:
+ ;SELECT timediff('today', 'yesterday') 
+
+
+
+timeslice(time, slice)
+══════════════════════════════════════════════════════════════════════
+ Return the start of the slice of time that the given timestamp falls
+ in. If the time falls outside of the slice, NULL is returned.
+Parameters
+ time The timestamp to get the time slice for.
+ slice The size of the time slices
+See Also
+ date(), datetime(), humanize_duration(), julianday(), strftime(),
+ time(), timediff()
+Examples
+#1 To get the timestamp rounded down to the start of the ten minute slice:
+ ;SELECT timeslice('2017-01-01T05:05:00', '10m') 
+
+
+#2 To group log messages into five minute buckets and count them:
+ ;SELECT timeslice(log_time_msecs, '5m') AS slice, count(1)
+   FROM lnav_example_log GROUP BY slice
+
+
+#3 To group log messages by those before 4:30am and after:
+ ;SELECT timeslice(log_time_msecs, 'before 4:30am') AS slice, count(1) FROM
+  lnav_example_log GROUP BY slice
+
+
+
+total(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the sum of the values in the group as a floating-point.
+Parameter
+ X The values to add.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), square(),
+ sum()
+Example
+#1 To total all of the values in the column 'ex_duration' from the table
+ 'lnav_example_log':
+ ;SELECT total(ex_duration) FROM lnav_example_log 
+
+
+
+total_changes()
+══════════════════════════════════════════════════════════════════════
+ Returns the number of row changes caused by INSERT, UPDATE or DELETE
+ statements since the current database connection was opened.
+
+
+trim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the left and right sides of the
+ first.
+Parameters
+ str The string to trim characters from the left and
+ right sides.
+ chars The characters to trim. Defaults to spaces.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), unicode(),
+ unparse_url(), upper(), xpath()
+Examples
+#1 To trim spaces from the start and end of the string ' abc ':
+ ;SELECT trim(' abc ') 
+
+
+#2 To trim the characters '-' and '+' from the string '-+abc+-':
+ ;SELECT trim('-+abc+-', '-+') 
+
+
+
+typeof(X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string that indicates the datatype of the expression X:
+ "null", "integer", "real", "text", or "blob".
+Parameter
+ X The expression to check.
+
+Examples
+#1 To get the type of the number 1:
+ ;SELECT typeof(1) 
+
+
+#2 To get the type of the string 'abc':
+ ;SELECT typeof('abc') 
+
+
+
+unicode(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the numeric unicode code point corresponding to the first
+ character of the string X.
+Parameter
+ X The string to examine.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(),
+ unparse_url(), upper(), xpath()
+Example
+#1 To get the unicode code point for the first character of 'abc':
+ ;SELECT unicode('abc') 
+
+
+
+unlikely(value)
+══════════════════════════════════════════════════════════════════════
+ Short-hand for likelihood(X, 0.0625)
+Parameter
+ value The boolean value to return
+
+
+unparse_url(obj)
+══════════════════════════════════════════════════════════════════════
+ Convert a JSON object containing the parts of a URL into a URL
+ string
+Parameter
+ obj The JSON object containing the URL parts
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To unparse the object '{"scheme": "https", "host": "example.com"}':
+ ;SELECT unparse_url('{"scheme": "https", "host": "example.com"}')
+
+
+
+upper(str)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of the given string with all ASCII characters
+ converted to upper case.
+Parameter
+ str The string to convert.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), xpath()
+Example
+#1 To uppercase the string 'aBc':
+ ;SELECT upper('aBc') 
+
+
+
+xpath(xpath, xmldoc)
+══════════════════════════════════════════════════════════════════════
+ A table-valued function that executes an xpath expression over an
+ XML string and returns the selected values.
+Parameters
+ xpath The XPATH expression to evaluate over the XML
+ document.
+ xmldoc The XML document as a string.
+Results
+ result The result of the XPATH expression.
+ node_path The absolute path to the node containing the
+ result.
+ node_attr The node's attributes stored in JSON object.
+ node_text The node's text value.
+See Also
+ anonymize(), char(), charindex(), decode(), encode(), endswith(),
+ extract(), group_concat(), group_spooky_hash(), gunzip(), gzip(),
+ humanize_duration(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ parse_url(), printf(), proper(), regexp_capture(),
+ regexp_capture_into_json(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ unparse_url(), upper()
+Examples
+#1 To select the XML nodes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
+
+
+#2 To select all 'a' attributes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def/@a', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
+
+
+#3 To select the text nodes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def/text()', '<abc><def a="b">Hello &#x2605;</def></abc>')
+
+
+
+yaml_to_json(yaml)
+══════════════════════════════════════════════════════════════════════
+ Convert a YAML document to a JSON-encoded string
+Parameter
+ yaml The YAML value to convert to JSON.
+See Also
+ jget(), json_concat(), json_contains(), json_group_array(),
+ json_group_object()
+Example
+#1 To convert the document "abc: def":
+ ;SELECT yaml_to_json('abc: def') 
+
+
+
+zeroblob(N)
+══════════════════════════════════════════════════════════════════════
+ Returns a BLOB consisting of N bytes of 0x00.
+Parameter
+ N The size of the BLOB.
+
+
+ATTACH DATABASE filename AS schema-name
+══════════════════════════════════════════════════════════════════════
+ Attach a database file to the current connection.
+Parameters
+ filename The path to the database file.
+ schema-name The prefix for tables in this database.
+
+Example
+#1 To attach the database file '/tmp/customers.db' with the name customers:
+ ;ATTACH DATABASE '/tmp/customers.db' AS customers 
+
+
+
+CASE [base-expr] WHEN cmp-expr1 THEN then-expr1 [... WHEN cmp-exprN THEN then-exprN] [ELSE else-expr] END
+══════════════════════════════════════════════════════════════════════
+ Evaluate a series of expressions in order until one evaluates to
+ true and then return it's result. Similar to an IF-THEN-ELSE
+ construct in other languages.
+Parameters
+ base-expr The base expression that is used for
+ comparison in the branches
+ cmp-expr The expression to test if this branch should
+ be taken
+ else-expr The result of this CASE if no branches
+ matched.
+
+Example
+#1 To evaluate the number one and return the string 'one':
+ ;SELECT CASE 1 WHEN 0 THEN 'zero' WHEN 1 THEN 'one' END
+
+
+
+CREATE [TEMP] VIEW [IF NOT EXISTS] [schema-name.] view-name AS select-stmt
+══════════════════════════════════════════════════════════════════════
+ Assign a name to a SELECT statement
+Parameters
+ IF NOT EXISTS Do not create the view if it already
+ exists
+ schema-name. The database to create the view in
+ view-name The name of the view
+ select-stmt The SELECT statement the view
+ represents
+
+
+DELETE FROM table-name [WHERE cond]
+══════════════════════════════════════════════════════════════════════
+ Delete rows from a table
+Parameters
+ table-name The name of the table
+ cond The conditions used to delete the rows.
+
+
+DETACH DATABASE schema-name
+══════════════════════════════════════════════════════════════════════
+ Detach a database from the current connection.
+Parameter
+ schema-name The prefix for tables in this database.
+
+Example
+#1 To detach the database named 'customers':
+ ;DETACH DATABASE customers 
+
+
+
+DROP VIEW [IF EXISTS] [schema-name.] view-name
+══════════════════════════════════════════════════════════════════════
+ Drop a view
+Parameters
+
+
+INSERT INTO [schema-name.] table-name [( column-name1 [, ... column-nameN] )] VALUES ( expr1 [, ... exprN] )
+══════════════════════════════════════════════════════════════════════
+ Insert rows into a table
+Parameters
+
+Example
+#1 To insert the pair containing 'MSG' and 'HELLO, WORLD!' into the
+ 'environ' table:
+ ;INSERT INTO environ VALUES ('MSG', 'HELLO, WORLD!')
+
+
+
+OVER window-name
+══════════════════════════════════════════════════════════════════════
+ Executes the preceding function over a window
+Parameter
+ window-name The name of the window definition
+
+
+SELECT result-column1 [, ... result-columnN] [FROM table1 [, ... tableN]] [WHERE cond] [GROUP BY grouping-expr1 [, ... grouping-exprN]] [ORDER BY ordering-term1 [, ... ordering-termN]] [LIMIT limit-expr1 [, ... limit-exprN]]
+══════════════════════════════════════════════════════════════════════
+ Query the database and return zero or more rows of data.
+Parameters
+ result-column The expression used to generate a
+ result for this column.
+ table The table(s) to query for data
+ cond The conditions used to select the
+ rows to return.
+ grouping-expr The expression to use when grouping
+ rows.
+ ordering-term The values to use when ordering the
+ result set.
+ limit-expr The maximum number of rows to
+ return.
+
+Example
+#1 To select all of the columns from the table 'syslog_log':
+ ;SELECT * FROM syslog_log 
+
+
+
+UPDATE table SET column-name1 = expr1 [, ... column-nameN = exprN] [WHERE cond]
+══════════════════════════════════════════════════════════════════════
+ Modify a subset of values in zero or more rows of the given table
+Parameters
+ table The table to update
+ column-name The columns in the table to update.
+ cond The condition used to determine whether
+ a row should be updated.
+
+Example
+#1 To mark the syslog message at line 40:
+ ;UPDATE syslog_log SET log_mark = 1 WHERE log_line = 40
+
+
+
+WITH [RECURSIVE] cte-table-name AS select-stmt
+══════════════════════════════════════════════════════════════════════
+ Create a temporary view that exists only for the duration of a SQL
+ statement.
+Parameters
+ cte-table-name The name for the temporary table.
+ select-stmt The SELECT statement used to
+ populate the temporary table.
+
diff --git a/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.err b/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.err
diff --git a/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.out b/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.out
new file mode 100644
index 0000000..5fb4d90
--- /dev/null
+++ b/test/expected/test_cmds.sh_b755a8b48c0f602f0270500b0117b76e11db546e.out
@@ -0,0 +1,37 @@
+Apr 7 00:49:42 Tim-Stacks-iMac kernel[0]: Ethernet [AppleBCM5701Ethernet]: Link up on en0, 1-Gigabit, Full-duplex, Symmetric flow-control, Debug [
+ 796d,
+ 2301,
+ 0de1,
+ 0300,
+ cde1,
+ 3800
+]
+Apr 7 05:49:53 Tim-Stacks-iMac.local GoogleSoftwareUpdateDaemon[17212]: -[KSUpdateCheckAction performAction]
+ KSUpdateCheckAction running KSServerUpdateRequest: <KSOmahaServerUpdateRequest:0x511f30
+ server=
+<KSOmahaServer:0x510d80>
+ url="https://tools.google.com/service/update2"
+ runningFetchers=0
+ tickets=1
+ activeTickets=1
+ rollCallTickets=1
+ body=
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <o:gupdate xmlns:o="http://www.google.com/update2/request" protocol="2.0" version="KeystoneDaemon-1.2.0.7709" ismachine="1" requestid="{0DFDBCD1-5E29-4DFC-BD99-31A2397198FE}">
+ <o:os platform="mac" version="MacOSX" sp="10.10.2_x86_64h"></o:os>
+ <o:app appid="com.google.Keystone" version="1.2.0.7709" lang="en-us" installage="180" brand="GGLG">
+ <o:ping r="1" a="1"></o:ping>
+ <o:updatecheck></o:updatecheck>
+ </o:app>
+ </o:gupdate>
+ >
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: WARNING: The Gestalt selector gestaltSystemVersion is returning 10.9.2 instead of 10.10.2. Use NSProcessInfo's operatingSystemVersion property to get correct system version number.
+ Call location:
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: 0 CarbonCore 0x00007fff8a9b3d9b ___Gestalt_SystemVersion_block_invoke + 113
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: 1 libdispatch.dylib 0x00007fff8bc84c13 _dispatch_client_callout + 8
+Apr 7 07:32:56 Tim-Stacks-iMac.local logger[234]: Bad data {
+ abc,
+ 123,
+ 456
+)
+}]
diff --git a/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.err b/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.err
diff --git a/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.out b/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.out
new file mode 100644
index 0000000..51109ea
--- /dev/null
+++ b/test/expected/test_cmds.sh_b7fcd26c45c850c3d43ce25b1f610a311eb898c5.out
@@ -0,0 +1 @@
+Thu Jun 06 19:13:20 2013 +0000 UTC -- 1370546000
diff --git a/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.err b/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.err
diff --git a/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.out b/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.out
new file mode 100644
index 0000000..607eca0
--- /dev/null
+++ b/test/expected/test_cmds.sh_b9f8bf53ec2736432eb048d94a391175eb4dc5bf.out
@@ -0,0 +1,2 @@
+Feb 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Jan 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
diff --git a/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.err b/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.err
diff --git a/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.out b/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.out
new file mode 100644
index 0000000..2678e6c
--- /dev/null
+++ b/test/expected/test_cmds.sh_bc60341827636715c14c562863da9733cbde7e68.out
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.err b/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.err
diff --git a/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.out b/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.out
new file mode 100644
index 0000000..44e294d
--- /dev/null
+++ b/test/expected/test_cmds.sh_be1d9628fc447b6f17121d9457ea1602afe8f3f3.out
@@ -0,0 +1 @@
+Sun Jan 31 05:53:29 2021 +0000 UTC -- 1612072409
diff --git a/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.err b/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.err
diff --git a/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.out b/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.out
new file mode 100644
index 0000000..493283c
--- /dev/null
+++ b/test/expected/test_cmds.sh_be3b7c5874b5f4d86cc230bd2f9802c98909e148.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.err b/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.err
new file mode 100644
index 0000000..07df1b2
--- /dev/null
+++ b/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.err
@@ -0,0 +1,7 @@
+✘ error: invalid timestamp: 2022-06-16Tabc
+ reason: the leading part of the timestamp was matched, however, the trailing text “Tabc” was not
+ --> command-option:1
+ | :goto 2022-06-16Tabc 
+ |  ^--^ unrecognized input 
+ = note: input matched time format “%Y-%m-%d”
+ = help: fix the timestamp or remove the trailing text
diff --git a/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.out b/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_bf4e7fad67e281beaa11b6e2b03a00b419c7c9b0.out
diff --git a/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.err b/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.err
diff --git a/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.out b/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.out
new file mode 100644
index 0000000..705f4ab
--- /dev/null
+++ b/test/expected/test_cmds.sh_c01e10f7cae8d36fa79ae03be887cb5477025f6d.out
@@ -0,0 +1,5 @@
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: IOThunderboltSwitch<0xffffff803f4b3000>(0x0)::listenerCallback - Thunderbolt HPD packet for route = 0x0 port = 11 unplug = 0
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: vm_compressor_flush - starting
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: AppleBCM5701Ethernet [en0]: 0 0 memWrInd fBJP_Wakeup_Timer
+Sep 13 03:13:16 Tim-Stacks-iMac kernel[0]: AppleThunderboltNHIType2::waitForOk2Go2Sx - retries = 60000
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: hibernate_page_list_setall(preflight 0) start 0xffffff838f1fc000, 0xffffff838f2bc000
diff --git a/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.err b/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.err
new file mode 100644
index 0000000..8295272
--- /dev/null
+++ b/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.err
@@ -0,0 +1,7 @@
+✘ error: invalid argument: invalid
+ reason: expecting line number/percentage, timestamp, or relative time
+ --> command-option:1
+ | :goto invalid 
+ = help: :goto line#|N%|timestamp|#anchor
+ ══════════════════════════════════════════════════════════════════════
+ Go to the given location in the top view
diff --git a/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.out b/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c2b4431dd0cc36c6201d263b727b3305e8cda6b1.out
diff --git a/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.err b/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.err
diff --git a/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.out b/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.out
new file mode 100644
index 0000000..f2fef20
--- /dev/null
+++ b/test/expected/test_cmds.sh_c4777849c39a6c34dea5b0279cd7400692f1ab5f.out
@@ -0,0 +1,3 @@
+info: changed config option -- /ui/clock-format
+info: reset option -- /ui/clock-format
+/ui/clock-format = "%Y-%m-%dT%H:%M:%S %Z"
diff --git a/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.err b/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.err
diff --git a/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.out b/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.out
new file mode 100644
index 0000000..8ab686e
--- /dev/null
+++ b/test/expected/test_cmds.sh_c4a15771f7e1487bf73b2e9d1564ad8ecfd76c7e.out
@@ -0,0 +1 @@
+Hello, World!
diff --git a/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.err b/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.err
new file mode 100644
index 0000000..538a78e
--- /dev/null
+++ b/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.err
@@ -0,0 +1,6 @@
+✘ error: invalid unix time -- abc
+ --> command-option:1
+ | :unix-time abc 
+ = help: :unix-time seconds
+ ══════════════════════════════════════════════════════════════════════
+ Convert epoch time to a human-readable form
diff --git a/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.out b/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c72aed622c19d493968e33f20d5dde3838a4258f.out
diff --git a/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.err b/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.err
diff --git a/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.out b/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.out
new file mode 100644
index 0000000..76c53dd
--- /dev/null
+++ b/test/expected/test_cmds.sh_c7fabc25374ff47c47931f63b1d697061b816a28.out
@@ -0,0 +1,2 @@
+ Sat Nov 03 09:20:00 1 normal 2 errors  0 warnings  1 marks
+ Sat Nov 03 09:45:00 1 normal 0 errors 0 warnings 0 marks
diff --git a/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.err b/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.err
diff --git a/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.out b/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.out
new file mode 100644
index 0000000..6ae2e70
--- /dev/null
+++ b/test/expected/test_cmds.sh_ca66660c973f76a3c2a147c7f5035bcb4e8a8bbc.out
@@ -0,0 +1,2 @@
+2009-07-20 22:59:27,672:DEBUG:Hello, World!
+ How are you today?
diff --git a/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.err b/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.err
diff --git a/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.out b/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.out
new file mode 100644
index 0000000..bc67837
--- /dev/null
+++ b/test/expected/test_cmds.sh_ccd326da92d1cacda63501cd1a3077381a18e8f2.out
@@ -0,0 +1 @@
+ Sat Nov 03 00:00:00 2 normal 2 errors 0 warnings 0 marks
diff --git a/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.err b/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.err
diff --git a/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.out b/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_d3b69abdfb39e4bfa5828c2f9593e2b2b7ed4d5d.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.err b/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.err
diff --git a/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.out b/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_cmds.sh_d76d77ad95b9f120825417a6a8220c13df9541fc.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.err b/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.err
new file mode 100644
index 0000000..07df1b2
--- /dev/null
+++ b/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.err
@@ -0,0 +1,7 @@
+✘ error: invalid timestamp: 2022-06-16Tabc
+ reason: the leading part of the timestamp was matched, however, the trailing text “Tabc” was not
+ --> command-option:1
+ | :goto 2022-06-16Tabc 
+ |  ^--^ unrecognized input 
+ = note: input matched time format “%Y-%m-%d”
+ = help: fix the timestamp or remove the trailing text
diff --git a/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.out b/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_d7eebacdcf2cb194f25fa4ef97b7b5376b442467.out
diff --git a/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.err b/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.err
diff --git a/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.out b/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.out
new file mode 100644
index 0000000..1d3eae4
--- /dev/null
+++ b/test/expected/test_cmds.sh_d836c84398c831c976df46f46fe3bf5983c44c37.out
@@ -0,0 +1,2 @@
+log_top_line() 
+ 51
diff --git a/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.err b/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.err
diff --git a/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.out b/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.out
new file mode 100644
index 0000000..aec6735
--- /dev/null
+++ b/test/expected/test_cmds.sh_d8eeef53a58bdeddbc1028d7c525413e3ca1c8df.out
@@ -0,0 +1 @@
+/vmw/cgi/tramp 200
diff --git a/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.err b/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.err
diff --git a/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out b/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out
new file mode 100644
index 0000000..f3d0606
--- /dev/null
+++ b/test/expected/test_cmds.sh_dbdd62995fdefc8318053af05a32416eccfa79fc.out
@@ -0,0 +1 @@
+ Sat Nov 03 08:00:00 2 normal 2 errors 0 warnings 0 marks
diff --git a/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err b/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.err
diff --git a/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out b/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out
new file mode 100644
index 0000000..c1837e7
--- /dev/null
+++ b/test/expected/test_cmds.sh_dd41fbbcd71699314af232156d4155fbdf849131.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [01/Jan/2010:00:00:00 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [01/Jan/2010:00:00:03 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [01/Jan/2010:00:00:03 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err b/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.err
diff --git a/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out b/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out
new file mode 100644
index 0000000..e905c55
--- /dev/null
+++ b/test/expected/test_cmds.sh_df6f4cea16bb8f20e6408fe4b40335e6de8a7f18.out
@@ -0,0 +1,3 @@
+10.0.0.1 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/aberrant HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+10.0.0.1 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/abject/ablaze/able.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+10.0.0.1 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/abject/ablaze/aboard.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err b/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.err
diff --git a/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out b/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out
new file mode 100644
index 0000000..2f2f721
--- /dev/null
+++ b/test/expected/test_cmds.sh_e495cf059477e3f80c3241c6f8d5808b6f1d19c7.out
@@ -0,0 +1,2 @@
+info: hiding lines after 2009-07-20 22:59:29.000
+info: hiding lines after 2009-07-20 22:59:29.000
diff --git a/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err b/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.err
diff --git a/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.out b/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.out
new file mode 100644
index 0000000..21e4506
--- /dev/null
+++ b/test/expected/test_cmds.sh_e7e8244fac65bc51dbd5af31be476fe3b8776bfc.out
@@ -0,0 +1,12 @@
+{
+ "foo bar" : null,
+ "array" : [
+ 1,
+ 2,
+ 3
+ ],
+ "obj" : {
+ "one" : 1,
+  "two" : true
+ }
+}
diff --git a/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.err b/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.err
diff --git a/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.out b/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_cmds.sh_e911aebcb2defb7471aa620c45a86cad449ad505.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.err b/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.err
diff --git a/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.out b/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.out
new file mode 100644
index 0000000..6599581
--- /dev/null
+++ b/test/expected/test_cmds.sh_eb22c3e94c536a1bfaeae0c40d271b5b4b08f4fc.out
@@ -0,0 +1,3 @@
+{"log_line":0,"log_part":null,"log_time":"2009-07-20 22:59:26.000","log_idle_msecs":0,"log_level":"info","log_mark":0,"log_comment":null,"log_tags":null,"log_filters":null,"c_ip":"192.168.202.254","cs_method":"GET","cs_referer":"-","cs_uri_query":null,"cs_uri_stem":"/vmw/cgi/tramp","cs_user_agent":"gPXE/0.9.7","cs_username":"-","cs_version":"HTTP/1.0","sc_bytes":134,"sc_status":200,"cs_host":null}
+{"log_line":1,"log_part":null,"log_time":"2009-07-20 22:59:29.000","log_idle_msecs":3000,"log_level":"error","log_mark":0,"log_comment":null,"log_tags":null,"log_filters":null,"c_ip":"192.168.202.254","cs_method":"GET","cs_referer":"-","cs_uri_query":null,"cs_uri_stem":"/vmw/vSphere/default/vmkboot.gz","cs_user_agent":"gPXE/0.9.7","cs_username":"-","cs_version":"HTTP/1.0","sc_bytes":46210,"sc_status":404,"cs_host":null}
+{"log_line":2,"log_part":null,"log_time":"2009-07-20 22:59:29.000","log_idle_msecs":0,"log_level":"info","log_mark":0,"log_comment":null,"log_tags":null,"log_filters":null,"c_ip":"192.168.202.254","cs_method":"GET","cs_referer":"-","cs_uri_query":null,"cs_uri_stem":"/vmw/vSphere/default/vmkernel.gz","cs_user_agent":"gPXE/0.9.7","cs_username":"-","cs_version":"HTTP/1.0","sc_bytes":78929,"sc_status":200,"cs_host":null}
diff --git a/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.err b/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.err
new file mode 100644
index 0000000..d9db72b
--- /dev/null
+++ b/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.err
@@ -0,0 +1,6 @@
+✘ error: unknown field(s) -- foobar
+ --> command-option:1
+ | :hide-fields foobar 
+ = help: :hide-fields field-name1 [... field-nameN]
+ ══════════════════════════════════════════════════════════════════════
+ Hide log message fields by replacing them with an ellipsis
diff --git a/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.out b/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ec2b28c6ea328e3ea56b13ab8ca3d9ee856a9dda.out
diff --git a/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.err b/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.err
new file mode 100644
index 0000000..929412e
--- /dev/null
+++ b/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.err
@@ -0,0 +1,7 @@
+✘ error: invalid mark expression: :log_procname lik
+ reason: near "lik": syntax error
+ --> command-option:1
+ | :mark-expr :log_procname lik 
+ = help: :mark-expr expr
+ ══════════════════════════════════════════════════════════════════════
+ Set the bookmark expression
diff --git a/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.out b/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ed5b73be0b991e0e8d6735e31df5b37c4286321b.out
diff --git a/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.err b/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.err
diff --git a/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.out b/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.out
new file mode 100644
index 0000000..f0aaf97
--- /dev/null
+++ b/test/expected/test_cmds.sh_f788d5f5932905d09ecbd581040ec5ce76459da5.out
@@ -0,0 +1,3 @@
+info: hiding lines before 2009-07-20 22:00:29.000
+info: hiding lines after 2009-07-20 22:59:29.000
+info: hiding lines before 2009-07-20 22:00:29.000 and after 2009-07-20 22:59:29.000
diff --git a/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.err b/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.err
diff --git a/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out b/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out
new file mode 100644
index 0000000..6ae2e70
--- /dev/null
+++ b/test/expected/test_cmds.sh_ff6faebbde8586e04bfadba14a3d2bb4451784ad.out
@@ -0,0 +1,2 @@
+2009-07-20 22:59:27,672:DEBUG:Hello, World!
+ How are you today?
diff --git a/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err b/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err
new file mode 100644
index 0000000..b1b0ffd
--- /dev/null
+++ b/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.err
@@ -0,0 +1,6 @@
+✘ error: expecting an integer, found: abc
+ --> command-option:1
+ | :config /tuning/archive-manager/min-free-space abc
+ = help: :config option [value]
+ ══════════════════════════════════════════════════════════════════════
+ Read or write a configuration option
diff --git a/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out b/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_2765ea0d4c037b8c935840604edb0ae796c97a04.out
diff --git a/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.err b/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.err
new file mode 100644
index 0000000..092b26a
--- /dev/null
+++ b/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.err
@@ -0,0 +1,20 @@
+✘ error: 'bad' is not a supported configuration $schema version
+ --> {test_dir}/bad-config2/formats/invalid-config/config.bad-schema.json:2
+ |  "$schema": "bad" 
+ = note: expecting one of the following $schema values:
+  https://lnav.org/schemas/config-v1.schema.json
+ = help: Property Synopsis
+ /$schema <schema-uri>
+ Description
+ The URI that specifies the schema that describes this type of file
+ Example
+ https://lnav.org/schemas/config-v1.schema.json
+✘ error: invalid JSON
+ --> {test_dir}/bad-config2/formats/invalid-config/config.malformed.json:3
+ | parse error: object key and value must be separated by a colon (':')
+ |  "ui": "theme", "abc", "def": "" }
+ |  (right here) ------^
+ | 
+✘ error: invalid JSON
+ reason: parse error: premature EOF
+ --> {test_dir}/bad-config2/formats/invalid-config/config.truncated.json:3
diff --git a/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.out b/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_5105c29004e297521310ca0bd0fd560b01c2c549.out
diff --git a/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err b/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err
new file mode 100644
index 0000000..96307c5
--- /dev/null
+++ b/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.err
@@ -0,0 +1,6 @@
+✘ error: unknown configuration option -- /bad/path
+ --> command-option:1
+ | :reset-config /bad/path 
+ = help: :reset-config option
+ ══════════════════════════════════════════════════════════════════════
+ Reset the configuration option to its default value
diff --git a/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out b/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_5fd9fbccc35e9b06abdd913da0c16bdb306b926e.out
diff --git a/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err
new file mode 100644
index 0000000..ec11ba5
--- /dev/null
+++ b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.err
@@ -0,0 +1,38 @@
+✘ error: 'bad' is not a supported configuration $schema version
+ --> {test_dir}/bad-config2/formats/invalid-config/config.bad-schema.json:2
+ |  "$schema": "bad" 
+ = note: expecting one of the following $schema values:
+  https://lnav.org/schemas/config-v1.schema.json
+ = help: Property Synopsis
+ /$schema <schema-uri>
+ Description
+ The URI that specifies the schema that describes this type of file
+ Example
+ https://lnav.org/schemas/config-v1.schema.json
+⚠ warning: unexpected value for property “/ui”
+ --> {test_dir}/bad-config2/formats/invalid-config/config.malformed.json:2
+ |  "ui": "theme", 
+ = help: Available Properties
+ $schema <schema-uri>
+ tuning/
+ ui/
+ log/
+ global/
+✘ error: invalid JSON
+ --> {test_dir}/bad-config2/formats/invalid-config/config.malformed.json:3
+ | parse error: object key and value must be separated by a colon (':')
+ |  "ui": "theme", "abc", "def": "" }
+ |  (right here) ------^
+ | 
+⚠ warning: unexpected value for property “/ui”
+ --> {test_dir}/bad-config2/formats/invalid-config/config.truncated.json:2
+ |  "ui": "theme" 
+ = help: Available Properties
+ $schema <schema-uri>
+ tuning/
+ ui/
+ log/
+ global/
+✘ error: invalid JSON
+ reason: parse error: premature EOF
+ --> {test_dir}/bad-config2/formats/invalid-config/config.truncated.json:3
diff --git a/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.out b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_a0907769aba112d628e7ebe39c4ec252e5e0bc69.out
diff --git a/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.err b/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.err
diff --git a/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.out b/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_b08f7523659d1c12f0e59920cd40d17d4a83b72f.out
diff --git a/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.err b/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.err
new file mode 100644
index 0000000..d8b2b12
--- /dev/null
+++ b/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.err
@@ -0,0 +1,12 @@
+✘ error: invalid value for property “/ui/theme-defs/default/styles/text/color”
+ reason: invalid color -- “#f”
+ |  reason: Could not parse color: #f
+ --> command-option:1
+ = help: Property Synopsis
+ /ui/theme-defs/default/styles/text/color #hex|color_name
+ Description
+ The foreground color value for this style. The value can be the name of an xterm color, the hexadecimal value, or a theme variable reference.
+ Examples
+ #fff
+ Green
+ $black
diff --git a/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.out b/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_d622658dc98327b1b2fd346802d24bc633e34ac7.out
diff --git a/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.err b/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.err
new file mode 100644
index 0000000..93cba93
--- /dev/null
+++ b/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.err
@@ -0,0 +1,8 @@
+✘ error: invalid value for property “/ui/theme”
+ reason: unknown theme -- “baddy”
+ |   = help: The available themes are: default, eldar, grayscale, monocai, night-owl, solarized-dark, solarized-light
+ --> command-option:1
+ = help: Property Synopsis
+ /ui/theme theme_name
+ Description
+ The name of the theme to use.
diff --git a/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.out b/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_d708b6fd32d83ce0ee00ca5383388308ba5a06e1.out
diff --git a/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.err b/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.err
diff --git a/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.out b/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.out
new file mode 100644
index 0000000..8fafd97
--- /dev/null
+++ b/test/expected/test_config.sh_eec3768ebc201ca63bca1411270965f78db1abfc.out
@@ -0,0 +1 @@
+/global/foo = "foo"
diff --git a/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.err b/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.err
diff --git a/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.out b/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_09ba47d70bfca88e89faf29598c1095292cad435.out
diff --git a/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.err b/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.err
diff --git a/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.out b/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.out
new file mode 100644
index 0000000..2ba3232
--- /dev/null
+++ b/test/expected/test_events.sh_153e221f3cb50f4d3e4581be0bf311e62489c42d.out
@@ -0,0 +1,6 @@
+/log/watch-expressions = {
+ "http-errors": {
+ "expr": ":sc_status >= 400",
+ "enabled": true
+ }
+}
diff --git a/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.err b/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.err
diff --git a/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.out b/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.out
new file mode 100644
index 0000000..b701c72
--- /dev/null
+++ b/test/expected/test_events.sh_3dae146ef3bf201c43656344803694a34a3dbfec.out
@@ -0,0 +1,2 @@
+{"content":{"$schema":"https://lnav.org/event-file-open-v1.schema.json","filename":"{test_dir}/logfile_access_log.0"}}
+{"content":{"$schema":"https://lnav.org/event-file-format-detected-v1.schema.json","filename":"{test_dir}/logfile_access_log.0","format":"access_log"}}
diff --git a/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.err b/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.err
diff --git a/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.out b/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_6f9523d43f174397829b6a7fe6ee0090d97df5f9.out
diff --git a/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.err b/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.err
diff --git a/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.out b/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.out
new file mode 100644
index 0000000..019a01b
--- /dev/null
+++ b/test/expected/test_events.sh_729f77b8e7136d64d22a6610a80ba6b584a2d896.out
@@ -0,0 +1,3 @@
+/log/watch-expressions = {
+
+}
diff --git a/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.err b/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.err
new file mode 100644
index 0000000..0e6fb92
--- /dev/null
+++ b/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.err
@@ -0,0 +1,10 @@
+✘ error: invalid value for property “/log/watch-expressions/http-errors/expr”
+ reason: SQL expression is invalid
+ |  reason: no such column: sc_status
+ |   --> /log/watch-expressions/http-errors/expr
+ |   | sc_status >= 400 AND bad 
+ --> command-option:1
+ = help: Property Synopsis
+ /log/watch-expressions/http-errors/expr <SQL-expression>
+ Description
+ The SQL expression to execute for each input line. If expression evaluates to true, a 'log message detected' event will be published.
diff --git a/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out b/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out
diff --git a/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err b/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err
diff --git a/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out b/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out
new file mode 100644
index 0000000..17a8132
--- /dev/null
+++ b/test/expected/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out
@@ -0,0 +1,3 @@
+{"content":{"$schema":"https://lnav.org/event-file-open-v1.schema.json","filename":"{test_dir}/logfile_access_log.0"}}
+{"content":{"$schema":"https://lnav.org/event-file-format-detected-v1.schema.json","filename":"{test_dir}/logfile_access_log.0","format":"access_log"}}
+{"content":{"$schema":"https://lnav.org/event-log-msg-detected-v1.schema.json","watch-name":"http-errors","filename":"{test_dir}/logfile_access_log.0","line-number":1,"format":"access_log","timestamp":"2009-07-20T22:59:29.000","values":{"body":"","c_ip":"192.168.202.254","cs_method":"GET","cs_referer":"-","cs_uri_query":null,"cs_uri_stem":"/vmw/vSphere/default/vmkboot.gz","cs_user_agent":"gPXE/0.9.7","cs_username":"-","cs_version":"HTTP/1.0","sc_bytes":46210,"sc_status":404,"timestamp":"20/Jul/2009:22:59:29 +0000"}}}
diff --git a/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err b/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err
diff --git a/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out b/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out
new file mode 100644
index 0000000..5f62842
--- /dev/null
+++ b/test/expected/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out
@@ -0,0 +1,9 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters
+0,<NULL>,2016-06-30 12:00:01.000,0,trace,0,<NULL>,<NULL>,<NULL>
+1,<NULL>,2016-06-30 12:00:02.000,1000,debug,0,<NULL>,<NULL>,<NULL>
+2,<NULL>,2016-06-30 12:00:03.000,1000,debug2,0,<NULL>,<NULL>,<NULL>
+3,<NULL>,2016-06-30 12:00:04.000,1000,debug3,0,<NULL>,<NULL>,<NULL>
+4,<NULL>,2016-06-30 12:00:05.000,1000,info,0,<NULL>,<NULL>,<NULL>
+5,<NULL>,2016-06-30 12:00:06.000,1000,warning,0,<NULL>,<NULL>,<NULL>
+6,<NULL>,2016-06-30 12:00:07.000,1000,fatal,0,<NULL>,<NULL>,<NULL>
+7,<NULL>,2016-06-30 12:00:08.000,1000,info,0,<NULL>,<NULL>,<NULL>
diff --git a/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err b/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err
new file mode 100644
index 0000000..202b451
--- /dev/null
+++ b/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.err
@@ -0,0 +1,171 @@
+✘ error: “invalid(abc” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_props_log/tags/badtag3/pattern
+ | invalid(abc 
+ |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:35
+ |  "pattern": "invalid(abc"
+ = help: Property Synopsis
+ /invalid_props_log/tags/badtag3/pattern <regex>
+ Description
+ The regular expression to match against the body of the log message
+ Example
+ \w+ is down
+✘ error: “abc(def” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_props_log/search-table/bad_table_regex/pattern
+ | abc(def 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:40
+ |  "pattern": "abc(def" 
+ = help: Property Synopsis
+ /invalid_props_log/search-table/bad_table_regex/pattern <regex>
+ Description
+ The regular expression for this search table.
+✘ error: “^(?<timestamp>\d+: (?<body>.*)$” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /bad_regex_log/regex/std/pattern
+ | ^(?<timestamp>\d+: (?<body>.*)$ 
+ |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:6
+ |  "pattern": "^(?<timestamp>\\d+: (?<body>.*)$"
+ = help: Property Synopsis
+ /bad_regex_log/regex/std/pattern <message-regex>
+ Description
+ The regular expression to match a log message and capture fields.
+✘ error: “(foo” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> pattern
+ | (foo 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:13
+ |  "error": "(foo" 
+ = help: Property Synopsis
+ /bad_regex_log/level/error <pattern|integer>
+ Description
+ The regular expression used to match the log text for this level. For JSON logs with numeric levels, this should be the number for the corresponding level.
+✘ error: “abc(” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /bad_regex_log/highlights/foobar/pattern
+ | abc( 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:25
+ |  "pattern": "abc(" 
+ = help: Property Synopsis
+ /bad_regex_log/highlights/foobar/pattern <regex>
+ Description
+ A regular expression to highlight in logs of this format.
+✘ error: “foo” is not a valid value for option “/bad_sample_log/value/pid/kind”
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:24
+ |  "kind": "foo" 
+ = help: Property Synopsis
+ /bad_sample_log/value/pid/kind <data-type>
+ Description
+ The type of data in the field
+ Allowed Values
+ string, integer, float, boolean, json, struct, quoted, xml
+✘ error: 'bad' is not a supported log format $schema version
+ --> {test_dir}/bad-config/formats/invalid-schema/format.json:2
+ |  "$schema": "bad" 
+ = note: expecting one of the following $schema values:
+  https://lnav.org/schemas/format-v1.schema.json
+ = help: Property Synopsis
+ /$schema The URI of the schema for this file
+ Description
+ Specifies the type of this file
+✘ error: invalid pattern: “incomplete-match”
+ reason: pattern does not match entire message
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:20
+ | 1428634687123; foo 
+ |  ^ matched up to here 
+ = note: incomplete-match = ^(?<timestamp>\d+);
+ = help: update the regular expression to fully capture the sample message
+✘ error: invalid sample log message: "abc: foo"
+ reason: unrecognized timestamp -- abc
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:30
+ = note: the following custom formats were tried:
+ abc
+ ^ “%i” matched up to here
+ = help: If the timestamp format is not supported by default, you can add a custom format with the “timestamp-format” property
+✘ error: invalid sample log message: "1428634687123| debug hello"
+ reason: “debug” does not match the expected level of “info”
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:33
+ = note: matched regex = with-level
+ captured level = “debug”
+✘ error: invalid pattern: “with-level”
+ reason: pattern does not match entire multiline sample message
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:37
+ = note: with-level = ^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$
+ = help: use “.*” to match new-lines
+✘ error: invalid sample log message: "1428634687123; foo bar"
+ reason: sample does not match any patterns
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:41
+ = note: the following shows how each pattern matched this sample:
+ 1428634687123; foo bar
+ ^ bad-time matched up to here
+ ^ semi matched up to here
+ ^ std matched up to here
+ ^ with-level matched up to here
+ = note: bad-time  = “^(?<timestamp>\w+): (?<body>\w+)$”
+ semi  = “^(?<timestamp>\d+); (?<body>\w+)$”
+ std  = “^(?<timestamp>\d+): (?<pid>\w+) (?<body>.*)$”
+ with-level = “^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$”
+
+⚠ warning: invalid pattern: “/bad_sample_log/regex/semi”
+ reason: pattern does not match any samples
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:10
+ = help: every pattern should have at least one sample that it matches
+⚠ warning: invalid pattern: “/bad_sample_log/regex/std”
+ reason: pattern does not match any samples
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:7
+ = help: every pattern should have at least one sample that it matches
+⚠ warning: invalid value “/invalid_props_log/value/non-existent”
+ reason: no patterns have a capture named “non-existent”
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+ = note: the following captures are available:
+ body, pid, timestamp
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag2”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag3”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid value for property “/invalid_props_log/timestamp-field”
+ reason: “ts” was not found in the pattern at /invalid_props_log/regex/std
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+ = note: the following captures are available:
+ body, pid, timestamp
+✘ error: “not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/color”
+ reason: Unknown color: 'not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:23
+✘ error: “also not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/background-color”
+ reason: Unknown color: 'also not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:24
+✘ error: “no_regexes_log” is not a valid log format
+ reason: no regexes specified
+ --> {test_dir}/bad-config/formats/no-regexes/format.json:4
+✘ error: “no_regexes_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config/formats/no-regexes/format.json:4
+✘ error: “no_sample_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config/formats/no-samples/format.json:4
+✘ error: failed to compile SQL statement
+ reason: near "TALE": syntax error
+ --> {test_dir}/bad-config/formats/invalid-sql/init.sql:4
+ | -- comment test 
+ | CREATE TALE invalid (x y z); 
+ |  ^ near "TALE": syntax error 
+✘ error: failed to execute SQL statement
+ reason: ✘ error: “abc(” is not a valid regular expression
+ |  reason: missing closing parenthesis
+ |   --> arg
+ |   | abc( 
+ |   |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-sql/init2.sql
+ | SELECT regexp_match('abc(', '123') 
+ | FROM sqlite_master; 
diff --git a/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out b/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_format_loader.sh_3f1d6f35e8a9ae4fd3e91ffaa82a037b5a847ab7.out
diff --git a/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err b/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err
new file mode 100644
index 0000000..1270517
--- /dev/null
+++ b/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err
@@ -0,0 +1,190 @@
+✘ error: invalid value for option “/bad_json_log/line-format#/timestamp-format”
+ reason: empty values are not allowed
+ --> {test_dir}/bad-config/formats/invalid-json-format/format.json:11
+ |  "timestamp-format": "" 
+ = help: Property Synopsis
+ /bad_json_log/line-format#/timestamp-format <string>
+ Description
+ The strftime(3) format for this field
+✘ error: “invalid(abc” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_props_log/tags/badtag3/pattern
+ | invalid(abc 
+ |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:36
+ |  "pattern": "invalid(abc"
+ = help: Property Synopsis
+ /invalid_props_log/tags/badtag3/pattern <regex>
+ Description
+ The regular expression to match against the body of the log message
+ Example
+ \w+ is down
+✘ error: “abc(def” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_props_log/search-table/bad_table_regex/pattern
+ | abc(def 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:41
+ |  "pattern": "abc(def" 
+ = help: Property Synopsis
+ /invalid_props_log/search-table/bad_table_regex/pattern <regex>
+ Description
+ The regular expression for this search table.
+✘ error: “^(?<timestamp>\d+: (?<body>.*)$” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /bad_regex_log/regex/std/pattern
+ | ^(?<timestamp>\d+: (?<body>.*)$ 
+ |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:6
+ |  "pattern": "^(?<timestamp>\\d+: (?<body>.*)$"
+ = help: Property Synopsis
+ /bad_regex_log/regex/std/pattern <message-regex>
+ Description
+ The regular expression to match a log message and capture fields.
+✘ error: “(foo” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> pattern
+ | (foo 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:13
+ |  "error": "(foo" 
+ = help: Property Synopsis
+ /bad_regex_log/level/error <pattern|integer>
+ Description
+ The regular expression used to match the log text for this level. For JSON logs with numeric levels, this should be the number for the corresponding level.
+✘ error: “abc(” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /bad_regex_log/highlights/foobar/pattern
+ | abc( 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:25
+ |  "pattern": "abc(" 
+ = help: Property Synopsis
+ /bad_regex_log/highlights/foobar/pattern <regex>
+ Description
+ A regular expression to highlight in logs of this format.
+⚠ warning: format file is missing “$schema” property
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json
+ = note: the schema specifies the supported format version and can be used with editors to automatically validate the file
+ = help: add the following property to the top-level JSON object:
+  "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+✘ error: “foo” is not a valid value for option “/bad_sample_log/value/pid/kind”
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:24
+ |  "kind": "foo" 
+ = help: Property Synopsis
+ /bad_sample_log/value/pid/kind <data-type>
+ Description
+ The type of data in the field
+ Allowed Values
+ string, integer, float, boolean, json, struct, quoted, xml
+✘ error: 'bad' is not a supported log format $schema version
+ --> {test_dir}/bad-config/formats/invalid-schema/format.json:2
+ |  "$schema": "bad" 
+ = note: expecting one of the following $schema values:
+  https://lnav.org/schemas/format-v1.schema.json
+ = help: Property Synopsis
+ /$schema The URI of the schema for this file
+ Description
+ Specifies the type of this file
+✘ error: invalid line format element “/bad_json_log/line-format/0/field”
+ reason: “” is not a defined value
+ --> {test_dir}/bad-config/formats/invalid-json-format/format.json:7
+✘ error: invalid pattern: “incomplete-match”
+ reason: pattern does not match entire message
+ --> {test_dir}/bad-config/formats/invalid-regex/format.json:20
+ | 1428634687123; foo 
+ |  ^ matched up to here 
+ = note: incomplete-match = ^(?<timestamp>\d+);
+ = help: update the regular expression to fully capture the sample message
+✘ error: invalid sample log message: "abc: foo"
+ reason: unrecognized timestamp -- abc
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:30
+ = note: the following custom formats were tried:
+ abc
+ ^ “%i” matched up to here
+ = help: If the timestamp format is not supported by default, you can add a custom format with the “timestamp-format” property
+✘ error: invalid sample log message: "1428634687123| debug hello"
+ reason: “debug” does not match the expected level of “info”
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:33
+ = note: matched regex = with-level
+ captured level = “debug”
+✘ error: invalid pattern: “with-level”
+ reason: pattern does not match entire multiline sample message
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:37
+ = note: with-level = ^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$
+ = help: use “.*” to match new-lines
+✘ error: invalid sample log message: "1428634687123; foo bar"
+ reason: sample does not match any patterns
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:41
+ = note: the following shows how each pattern matched this sample:
+ 1428634687123; foo bar
+ ^ bad-time matched up to here
+ ^ semi matched up to here
+ ^ std matched up to here
+ ^ with-level matched up to here
+ = note: bad-time  = “^(?<timestamp>\w+): (?<body>\w+)$”
+ semi  = “^(?<timestamp>\d+); (?<body>\w+)$”
+ std  = “^(?<timestamp>\d+): (?<pid>\w+) (?<body>.*)$”
+ with-level = “^(?<timestamp>\d+)\| (?<level>\w+) (?<body>\w+)$”
+
+⚠ warning: invalid pattern: “/bad_sample_log/regex/semi”
+ reason: pattern does not match any samples
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:10
+ = help: every pattern should have at least one sample that it matches
+⚠ warning: invalid pattern: “/bad_sample_log/regex/std”
+ reason: pattern does not match any samples
+ --> {test_dir}/bad-config/formats/invalid-sample/format.json:7
+ = help: every pattern should have at least one sample that it matches
+⚠ warning: invalid value “/invalid_props_log/value/non-existent”
+ reason: no patterns have a capture named “non-existent”
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+ = note: the following captures are available:
+ body, pid, timestamp
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag2”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid tag definition “/invalid_props_log/tags/badtag3”
+ reason: tag definitions must have a non-empty pattern
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: “invalid_props_log” is not a valid log format
+ reason: “subsecond-unit” must be set when “subsecond-field” is used
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+✘ error: invalid value for property “/invalid_props_log/timestamp-field”
+ reason: “ts” was not found in the pattern at /invalid_props_log/regex/std
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:4
+ = note: the following captures are available:
+ body, pid, timestamp
+✘ error: “not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/color”
+ reason: Unknown color: 'not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:24
+✘ error: “also not a color” is not a valid color value for property “/invalid_props_log/highlights/hl1/background-color”
+ reason: Unknown color: 'also not a color'. See https://jonasjacek.github.io/colors/ for a list of supported color names
+ --> {test_dir}/bad-config/formats/invalid-properties/format.json:25
+✘ error: “no_regexes_log” is not a valid log format
+ reason: no regexes specified
+ --> {test_dir}/bad-config/formats/no-regexes/format.json:4
+✘ error: “no_regexes_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config/formats/no-regexes/format.json:4
+✘ error: “no_sample_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config/formats/no-samples/format.json:4
+✘ error: failed to compile SQL statement
+ reason: near "TALE": syntax error
+ --> {test_dir}/bad-config/formats/invalid-sql/init.sql:4
+ | -- comment test 
+ | CREATE TALE invalid (x y z); 
+ |  ^ near "TALE": syntax error 
+✘ error: failed to execute SQL statement
+ reason: ✘ error: “abc(” is not a valid regular expression
+ |  reason: missing closing parenthesis
+ |   --> arg
+ |   | abc( 
+ |   |  ^ missing closing parenthesis
+ --> {test_dir}/bad-config/formats/invalid-sql/init2.sql
+ | SELECT regexp_match('abc(', '123') 
+ | FROM sqlite_master; 
diff --git a/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out b/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.out
diff --git a/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err b/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err
new file mode 100644
index 0000000..f657d87
--- /dev/null
+++ b/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.err
@@ -0,0 +1,61 @@
+✘ error: invalid JSON
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:4
+ | parse error: object key and value must be separated by a colon (':')
+ |  ar_log": { "abc" } }
+ |  (right here) ------^
+ | 
+✘ error: “abc(” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_key_log/level-pointer
+ | abc( 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
+ |  "level-pointer": "abc(", 
+ = help: Property Synopsis
+ /invalid_key_log/level-pointer
+ Description
+ A regular-expression that matches the JSON-pointer of the level property
+✘ error: “def[ghi” is not a valid regular expression
+ reason: missing terminating ] for character class
+ --> /invalid_key_log/file-pattern
+ | def[ghi 
+ |  ^ missing terminating ] for character class
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:5
+ |  "file-pattern": "def[ghi", 
+ = help: Property Synopsis
+ /invalid_key_log/file-pattern
+ Description
+ A regular expression that restricts this format to log files with a matching name
+⚠ warning: unexpected value for property “/invalid_key_log/value/test/identifiers”
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:14
+ |  "identifiers": true 
+ = help: Available Properties
+ kind <data-type>
+ collate <function>
+ unit/
+ identifier <bool>
+ foreign-key <bool>
+ hidden <bool>
+ action-list <string>
+ rewriter <command>
+ description <string>
+✘ error: “-1.2” is not a valid value for “/invalid_key_log/timestamp-divisor”
+ reason: value cannot be less than or equal to zero
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:25
+ |  "timestamp-divisor": -1.2 
+ = help: Property Synopsis
+ /invalid_key_log/timestamp-divisor <number>
+ Description
+ The value to divide a numeric timestamp by in a JSON log.
+✘ error: “foobar_log” is not a valid log format
+ reason: no regexes specified
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
+✘ error: “foobar_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
+✘ error: “invalid_key_log” is not a valid log format
+ reason: structured logs cannot have regexes
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
+✘ error: invalid line format element “/invalid_key_log/line-format/0/field”
+ reason: “non-existent” is not a defined value
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:22
diff --git a/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out b/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_format_loader.sh_a47f2b090a5d8a226783835c7ff7d1c8821f11ed.out
diff --git a/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err b/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err
new file mode 100644
index 0000000..3272370
--- /dev/null
+++ b/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.err
@@ -0,0 +1,66 @@
+✘ error: invalid JSON
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:4
+ | parse error: object key and value must be separated by a colon (':')
+ |  ar_log": { "abc" } }
+ |  (right here) ------^
+ | 
+⚠ warning: format file is missing “$schema” property
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json
+ = note: the schema specifies the supported format version and can be used with editors to automatically validate the file
+ = help: add the following property to the top-level JSON object:
+  "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+✘ error: “abc(” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> /invalid_key_log/level-pointer
+ | abc( 
+ |  ^ missing closing parenthesis 
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
+ |  "level-pointer": "abc(", 
+ = help: Property Synopsis
+ /invalid_key_log/level-pointer
+ Description
+ A regular-expression that matches the JSON-pointer of the level property
+✘ error: “def[ghi” is not a valid regular expression
+ reason: missing terminating ] for character class
+ --> /invalid_key_log/file-pattern
+ | def[ghi 
+ |  ^ missing terminating ] for character class
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:5
+ |  "file-pattern": "def[ghi", 
+ = help: Property Synopsis
+ /invalid_key_log/file-pattern
+ Description
+ A regular expression that restricts this format to log files with a matching name
+⚠ warning: unexpected value for property “/invalid_key_log/value/test/identifiers”
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:14
+ |  "identifiers": true 
+ = help: Available Properties
+ kind <data-type>
+ collate <function>
+ unit/
+ identifier <bool>
+ foreign-key <bool>
+ hidden <bool>
+ action-list <string>
+ rewriter <command>
+ description <string>
+✘ error: “-1.2” is not a valid value for “/invalid_key_log/timestamp-divisor”
+ reason: value cannot be less than or equal to zero
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:25
+ |  "timestamp-divisor": -1.2 
+ = help: Property Synopsis
+ /invalid_key_log/timestamp-divisor <number>
+ Description
+ The value to divide a numeric timestamp by in a JSON log.
+✘ error: “foobar_log” is not a valid log format
+ reason: no regexes specified
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
+✘ error: “foobar_log” is not a valid log format
+ reason: log message samples must be included in a format definition
+ --> {test_dir}/bad-config-json/formats/invalid-json/format.json:3
+✘ error: “invalid_key_log” is not a valid log format
+ reason: structured logs cannot have regexes
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:4
+✘ error: invalid line format element “/invalid_key_log/line-format/0/field”
+ reason: “non-existent” is not a defined value
+ --> {test_dir}/bad-config-json/formats/invalid-key/format.json:22
diff --git a/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out b/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_format_loader.sh_fca6c1fb9f3aaa69b3ffb2d1a8a86434b2f4a247.out
diff --git a/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err b/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.err
diff --git a/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out b/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out
new file mode 100644
index 0000000..ef750df
--- /dev/null
+++ b/test/expected/test_json_format.sh_168cac40c27f547044c89d39eb0ff2ef81da4b21.out
@@ -0,0 +1,13 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "lvl": "TRACE", "msg": "trace test"}
+{"ts": "2013-09-06T20:00:49.124817Z", "lvl": "INFO", "msg": "Starting up service"}
+{"ts": "2013-09-06T22:00:49.124817Z", "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG5", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG4", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG3", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG2", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG", "msg": "Details..."}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "STATS", "msg": "1 beat per second"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "WARNING", "msg": "not looking good"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "ERROR", "msg": "looking bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "CRITICAL", "msg": "sooo bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "FATAL", "msg": "shoot", "obj": { "field1" : "hi", "field2": 2 }, "arr" : ["hi", {"sub1": true}]}
diff --git a/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err b/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.err
diff --git a/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.out b/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.out
new file mode 100644
index 0000000..59872f2
--- /dev/null
+++ b/test/expected/test_json_format.sh_1bb0fd243e916546aea22029245ac590dae17a86.out
@@ -0,0 +1,14 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,@fields/user,@fields/trace#
+0,<NULL>,2013-09-06 20:00:48.124,0,trace,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+2,<NULL>,2013-09-06 20:00:49.124,1000,info,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+4,<NULL>,2013-09-06 22:00:49.124,7200000,info,0,<NULL>,<NULL>,<NULL>,steve@example.com,<NULL>
+7,<NULL>,2013-09-06 22:00:59.124,10000,debug5,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+9,<NULL>,2013-09-06 22:00:59.124,0,debug4,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+11,<NULL>,2013-09-06 22:00:59.124,0,debug3,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+13,<NULL>,2013-09-06 22:00:59.124,0,debug2,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+15,<NULL>,2013-09-06 22:00:59.124,0,debug,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+17,<NULL>,2013-09-06 22:01:49.124,50000,stats,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+19,<NULL>,2013-09-06 22:01:49.124,0,warning,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+21,<NULL>,2013-09-06 22:01:49.124,0,error,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+23,<NULL>,2013-09-06 22:01:49.124,0,critical,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+25,<NULL>,2013-09-06 22:01:49.124,0,fatal,0,<NULL>,<NULL>,<NULL>,<NULL>,line:1
diff --git a/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.err b/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.err
diff --git a/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.out b/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.out
new file mode 100644
index 0000000..463a734
--- /dev/null
+++ b/test/expected/test_json_format.sh_40223ac4742883f883ccc61044bfffd6e102cca6.out
@@ -0,0 +1,192 @@
+[
+ {
+ "log_line": 0,
+ "log_part": null,
+ "log_time": "2013-09-06 20:00:48.124",
+ "log_idle_msecs": 0,
+ "log_level": "trace",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 2,
+ "log_part": null,
+ "log_time": "2013-09-06 20:00:49.124",
+ "log_idle_msecs": 1000,
+ "log_level": "info",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 4,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:49.124",
+ "log_idle_msecs": 7200000,
+ "log_level": "info",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": "steve@example.com"
+ },
+ {
+ "log_line": 7,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:59.124",
+ "log_idle_msecs": 10000,
+ "log_level": "debug5",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 9,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:59.124",
+ "log_idle_msecs": 0,
+ "log_level": "debug4",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 11,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:59.124",
+ "log_idle_msecs": 0,
+ "log_level": "debug3",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 13,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:59.124",
+ "log_idle_msecs": 0,
+ "log_level": "debug2",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 15,
+ "log_part": null,
+ "log_time": "2013-09-06 22:00:59.124",
+ "log_idle_msecs": 0,
+ "log_level": "debug",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 17,
+ "log_part": null,
+ "log_time": "2013-09-06 22:01:49.124",
+ "log_idle_msecs": 50000,
+ "log_level": "stats",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 19,
+ "log_part": null,
+ "log_time": "2013-09-06 22:01:49.124",
+ "log_idle_msecs": 0,
+ "log_level": "warning",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 21,
+ "log_part": null,
+ "log_time": "2013-09-06 22:01:49.124",
+ "log_idle_msecs": 0,
+ "log_level": "error",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 23,
+ "log_part": null,
+ "log_time": "2013-09-06 22:01:49.124",
+ "log_idle_msecs": 0,
+ "log_level": "critical",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": null,
+ "obj": null,
+ "user": null
+ },
+ {
+ "log_line": 25,
+ "log_part": null,
+ "log_time": "2013-09-06 22:01:49.124",
+ "log_idle_msecs": 0,
+ "log_level": "fatal",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "arr": [
+ "hi",
+ {
+ "sub1": true
+ }
+ ],
+ "obj": {
+ "field1": "hi",
+ "field2": 2
+ },
+ "user": null
+ }
+]
diff --git a/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.err b/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.err
diff --git a/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.out b/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.out
new file mode 100644
index 0000000..30ddacc
--- /dev/null
+++ b/test/expected/test_json_format.sh_4315a3d6124c14cbe3c474b6dbf4cc8720a9859f.out
@@ -0,0 +1,3 @@
+2017-03-24T20:06:26.240 1.1.1.1 GET 200 /example/uri/5
+2017-03-24T20:12:47.764 1.1.1.1 GET 500 /example/uri/5
+2017-03-24T20:15:31.694 1.1.1.1 GET 400 /example/uri/5
diff --git a/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.err b/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.err
diff --git a/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.out b/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.out
new file mode 100644
index 0000000..7cf3887
--- /dev/null
+++ b/test/expected/test_json_format.sh_469f005b0708d629bc95f0c48a5e390f440c1fef.out
@@ -0,0 +1,29 @@
+
+[2013-09-06T20:00:48.124] TRACE trace test
+
+[2013-09-06T20:00:49.124] INFO Starting up service
+
+[2013-09-06T22:00:49.124] INFO Shutting down service
+ user: steve@example.com
+
+[2013-09-06T22:00:59.124] DEBUG5 Details...
+
+[2013-09-06T22:00:59.124] DEBUG4 Details...
+
+[2013-09-06T22:00:59.124] DEBUG3 Details...
+
+[2013-09-06T22:00:59.124] DEBUG2 Details...
+
+[2013-09-06T22:00:59.124] DEBUG Details...
+
+[2013-09-06T22:01:49.124] STATS 1 beat per second
+
+[2013-09-06T22:01:49.124] WARNING not looking good
+
+[2013-09-06T22:01:49.124] ERROR looking bad
+
+[2013-09-06T22:01:49.124] CRITICAL sooo bad
+
+[2013-09-06T22:01:49.124] FATAL shoot
+ obj: { "field1" : "hi", "field2": 2 }
+ arr: ["hi", {"sub1": true}]
diff --git a/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.err b/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.err
diff --git a/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.out b/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.out
new file mode 100644
index 0000000..128f5ab
--- /dev/null
+++ b/test/expected/test_json_format.sh_6fbe20faa161ab9fa77df7568fff84bf3e47e920.out
@@ -0,0 +1,4 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,user,cl
+0,<NULL>,2013-09-06 20:00:49.124,0,info,0,<NULL>,<NULL>,<NULL>,<NULL>,com.exmaple.foo
+1,<NULL>,2013-09-06 22:00:49.124,7200000,info,0,<NULL>,<NULL>,<NULL>,steve@example.com,com.exmaple.foo
+3,<NULL>,2013-09-06 22:01:49.124,60000,error,0,<NULL>,<NULL>,<NULL>,<NULL>,com.exmaple.foo
diff --git a/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.err b/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.err
diff --git a/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.out b/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.out
new file mode 100644
index 0000000..c861d3a
--- /dev/null
+++ b/test/expected/test_json_format.sh_7724d1a96d74d4418dd44d7416270f9bb64b2564.out
@@ -0,0 +1,29 @@
+2013-09-06T20:00:48.124 TRACE trace test
+ @fields: { "lvl": "TRACE", "msg": "trace test"}
+2013-09-06T20:00:49.124 INFO Starting up service
+ @fields: { "lvl": "INFO", "msg": "Starting up service"}
+2013-09-06T22:00:49.124 INFO Shutting down service
+ @fields/user: steve@example.com
+ @fields: { "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}
+2013-09-06T22:00:59.124 DEBUG5 Details...
+ @fields: { "lvl": "DEBUG5", "msg": "Details..."}
+2013-09-06T22:00:59.124 DEBUG4 Details...
+ @fields: { "lvl": "DEBUG4", "msg": "Details..."}
+2013-09-06T22:00:59.124 DEBUG3 Details...
+ @fields: { "lvl": "DEBUG3", "msg": "Details..."}
+2013-09-06T22:00:59.124 DEBUG2 Details...
+ @fields: { "lvl": "DEBUG2", "msg": "Details..."}
+2013-09-06T22:00:59.124 DEBUG Details...
+ @fields: { "lvl": "DEBUG", "msg": "Details..."}
+2013-09-06T22:01:49.124 STATS 1 beat per second
+ @fields: { "lvl": "STATS", "msg": "1 beat per second"}
+2013-09-06T22:01:49.124 WARNING not looking good
+ @fields: { "lvl": "WARNING", "msg": "not looking good"}
+2013-09-06T22:01:49.124 ERROR looking bad
+ @fields: { "lvl": "ERROR", "msg": "looking bad"}
+2013-09-06T22:01:49.124 CRITICAL sooo bad
+ @fields: { "lvl": "CRITICAL", "msg": "sooo bad"}
+2013-09-06T22:01:49.124 FATAL shoot
+ @fields/trace#: line:1
+ @fields/trace#: line:2
+ @fields: { "lvl": "FATAL", "msg": "shoot", "trace": ["line:1", "line:2"]}
diff --git a/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.err b/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.err
diff --git a/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.out b/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.out
new file mode 100644
index 0000000..3b820b6
--- /dev/null
+++ b/test/expected/test_json_format.sh_7aade92cff911c5b3cfc733685809f949ae35778.out
@@ -0,0 +1 @@
+{"@timestamp":"2016-08-03T12:06:31.009-0500","@version":1,"message":";Exception initializing page context;","logger_name":"org.apache.jasper.runtime.JspFactoryImpl","thread_name":"http-bio-0.0.0.0-8081-exec-198","level":"ERROR","level_value":40000,"stack_trace":"java.lang.NoClassDefFoundError: javax/el/StaticFieldELResolver\n\tat org.apache.jasper.runtime.JspFactoryImpl.internalGetPageContext(JspFactoryImpl.java:172)\n\tat org.apache.jasper.runtime.JspFactoryImpl.getPageContext(JspFactoryImpl.java:123)\n\tat org.apache.jsp.errors._404_002dnot_002dfound_jsp._jspService(_404_002dnot_002dfound_jsp.java:38)\n\tat org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:731)\n\tat org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)\n\tat org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)\n\tat org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:731)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat collective.config.startup.DamFilter.doFilter(DamFilter.java:270)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)\n\tat org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)\n\tat org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)\n\tat org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)\n\tat org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:476)\n\tat org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:345)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:210)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)\n\tat org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)\n\tat org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)\n\tat org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)\n\tat org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)\n\tat org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:744)\nCaused by: java.lang.ClassNotFoundException: javax.el.StaticFieldELResolver\n\tat org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)\n\tat org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)\n\t... 33 common frames omitted\n","customer":"foobaz"}
diff --git a/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.err b/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.err
diff --git a/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.out b/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.out
new file mode 100644
index 0000000..ce295e2
--- /dev/null
+++ b/test/expected/test_json_format.sh_7c6529f6bf4a0cb565f5665fdcba032f0ae1ebbe.out
@@ -0,0 +1,12 @@
+2013-09-06T20:00:48.124 TRACE trace test
+ @fields: { "lvl": "TRACE", "msg": "trace test"}
+2013-09-06T20:00:49.124 INFO Starting up service
+ @fields: { "lvl": "INFO", "msg": "Starting up service"}
+[offset: 186] {"ts": "2013-09-06T22:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Shutting down service\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10
+parse error: premature EOF
+ {"ts": "2013-09-06T22:00:49.124
+ (right here) ------^
+2013-09-06T22:00:59.124 DEBUG5 Details...
+ @fields: { "lvl": "DEBUG5", "msg": "Details..."}
+2013-09-06T22:00:59.222 DEBUG4 Details...
+ @fields: { "lvl": "DEBUG4", "msg": "Details..."}
diff --git a/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.err b/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.err
diff --git a/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.out b/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.out
new file mode 100644
index 0000000..bae2626
--- /dev/null
+++ b/test/expected/test_json_format.sh_80959e2bb6a7fdf938c2e4dbd7d7c81eb84fa072.out
@@ -0,0 +1,8 @@
+2013-09-06T20:00:48.124 abc 48 def info - -
+ @fields: { "lvl": "TRACE", "msg": "trace test"}
+2013-09-06T20:00:49.124 abc 49 def info - -
+ @fields: { "lvl": "INFO", "msg": "Starting up service"}
+[offset: 186] {"ts": "2013-09-06T22:00:49.124817Z", "@fields": { "lvl": "INFO", "msg":
+parse error: premature EOF
+ {"ts": "2013-09-06T22:00:49.124
+ (right here) ------^
diff --git a/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.err b/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.err
diff --git a/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.out b/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.out
new file mode 100644
index 0000000..58b44ab
--- /dev/null
+++ b/test/expected/test_json_format.sh_84a71e94dc34661a70bb9015b67ba00e93e9cfb5.out
@@ -0,0 +1,2 @@
+2018-08-21T14:04:21.221 38708007 medusa-GpsLocator.service python[184] FATAL GPS Reference longitude: 7.358143333
+2018-08-21T14:04:21.221 38708007 medusa-GpsLocator.service python[184] INFO GPS Reference latitude: 46.908706667
diff --git a/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.err b/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.err
diff --git a/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.out b/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.out
new file mode 100644
index 0000000..80919e8
--- /dev/null
+++ b/test/expected/test_json_format.sh_85d03b1b41a7f819af135d2521a8f2c59418e907.out
@@ -0,0 +1,14 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,arr,obj,user
+0,<NULL>,2013-09-06 20:00:48.124,0,trace,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+2,<NULL>,2013-09-06 20:00:49.124,1000,info,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+4,<NULL>,2013-09-06 22:00:49.124,7200000,info,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,steve@example.com
+7,<NULL>,2013-09-06 22:00:59.124,10000,debug5,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+9,<NULL>,2013-09-06 22:00:59.124,0,debug4,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+11,<NULL>,2013-09-06 22:00:59.124,0,debug3,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+13,<NULL>,2013-09-06 22:00:59.124,0,debug2,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+15,<NULL>,2013-09-06 22:00:59.124,0,debug,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+17,<NULL>,2013-09-06 22:01:49.124,50000,stats,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+19,<NULL>,2013-09-06 22:01:49.124,0,warning,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+21,<NULL>,2013-09-06 22:01:49.124,0,error,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+23,<NULL>,2013-09-06 22:01:49.124,0,critical,0,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>
+25,<NULL>,2013-09-06 22:01:49.124,0,fatal,0,<NULL>,<NULL>,<NULL>,"[""hi"", {""sub1"": true}]","{ ""field1"" : ""hi"", ""field2"": 2 }",<NULL>
diff --git a/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.err b/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.err
diff --git a/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.out b/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.out
new file mode 100644
index 0000000..338bca9
--- /dev/null
+++ b/test/expected/test_json_format.sh_8f2ebcd319afc7966ef11e31f9dd646bf6f001dd.out
@@ -0,0 +1,21 @@
+2013-09-06T20:00:48.124 abc 48 def TRACE - trace test
+2013-09-06T20:00:49.124 abc 49 def INFO - Starting up service
+2013-09-06T22:00:49.124 abc 49 def INFO - Shutting down service
+ user: steve@example.com
+timestamp="2013-09-06T22:00:50.123000Z" level="INFO" msg="Hello, World"
+panic: foo bar failed baz
+ level1.py:10034
+ level2.py:100
+ level3.py:42
+2013-09-06T22:00:59.124 abc 59 def DEBUG5 - Details...
+2013-09-06T22:00:59.124 abc 59 def DEBUG4 - Details...
+2013-09-06T22:00:59.124 abc 59 def DEBUG3 - Details...
+2013-09-06T22:00:59.124 abc 59 def DEBUG2 - Details...
+2013-09-06T22:00:59.124 abc 59 def DEBUG - Details...
+2013-09-06T22:01:49.124 abc 49 def STATS - 1 beat per second
+2013-09-06T22:01:49.124 abc 49 def WARNING - not looking good
+2013-09-06T22:01:49.124 abc 49 def ERROR - looking bad
+2013-09-06T22:01:49.124 abc 49 def CRITICAL - sooo bad
+2013-09-06T22:01:49.124 abc 49 def FATAL - shoot
+ obj: { "field1" : "hi", "field2": 2 }
+ arr: ["hi", {"sub1": true}]
diff --git a/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.err b/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.err
diff --git a/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.out b/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.out
new file mode 100644
index 0000000..30ddacc
--- /dev/null
+++ b/test/expected/test_json_format.sh_90a037c7d9d70ac4ca97158271ea242787313377.out
@@ -0,0 +1,3 @@
+2017-03-24T20:06:26.240 1.1.1.1 GET 200 /example/uri/5
+2017-03-24T20:12:47.764 1.1.1.1 GET 500 /example/uri/5
+2017-03-24T20:15:31.694 1.1.1.1 GET 400 /example/uri/5
diff --git a/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.err b/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.err
diff --git a/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.out b/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.out
new file mode 100644
index 0000000..eb43a38
--- /dev/null
+++ b/test/expected/test_json_format.sh_952297a90e312d2184fe3e4df795ddc731b096c9.out
@@ -0,0 +1,4 @@
+
+[-09-06T22:00:49.124] INFO Shutting down service
+ user: steve@example.com
+
diff --git a/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.err b/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.err
diff --git a/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.out b/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.out
new file mode 100644
index 0000000..55dcb76
--- /dev/null
+++ b/test/expected/test_json_format.sh_989e52d167582648b73c5d025cc0e814c642b3c8.out
@@ -0,0 +1,4 @@
+2013-09-06T20:00:49.124 abc 49 def 0 c.e.foo Starting up service
+2013-09-06T22:00:49.124 abc 49 def 0 c.e.foo Shutting down service
+ user: steve@example.com
+2013-09-06T22:01:49.124 abc 49 def 10 c.e.foo looking bad
diff --git a/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.err b/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.err
diff --git a/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.out b/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.out
new file mode 100644
index 0000000..6282d17
--- /dev/null
+++ b/test/expected/test_json_format.sh_a06b3cdd46b387e72d6faa4cce648b8b11ae870b.out
@@ -0,0 +1,25 @@
+
+[2013-09-06T20:00:48.124] TRACE trace testbork bork bork
+
+[2013-09-06T20:00:49.124] INFO Starting up servicebork bork bork
+
+[2013-09-06T22:00:49.124] INFO Shutting down servicebork bork bork
+ user:mailto:steve@example.com
+
+[2013-09-06T22:00:59.124] DEBUG5 Details...bork bork bork
+
+[2013-09-06T22:00:59.124] DEBUG4 Details...bork bork bork
+
+[2013-09-06T22:00:59.124] DEBUG3 Details...bork bork bork
+
+[2013-09-06T22:00:59.124] DEBUG2 Details...bork bork bork
+
+[2013-09-06T22:00:59.124] DEBUG Details...bork bork bork
+
+[2013-09-06T22:01:49.124] STATS 1 beat per secondbork bork bork
+
+[2013-09-06T22:01:49.124] WARNING not looking goodbork bork bork
+
+[2013-09-06T22:01:49.124] ERROR looking badbork bork bork
+
+[2013-09-06T22:01:49.124] CRITICAL sooo badbork bork bork
diff --git a/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.err b/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.err
diff --git a/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.out b/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.out
new file mode 100644
index 0000000..b356898
--- /dev/null
+++ b/test/expected/test_json_format.sh_a6be47f1311ed92feaf303142fcb103deb80f456.out
@@ -0,0 +1,4 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,client_ip,request/method,request/uri,request/size,response/status,details1,details2,details3
+0,<NULL>,2017-03-24 20:06:26.240,0,info,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,200,<NULL>,<NULL>,<NULL>
+1,<NULL>,2017-03-24 20:12:47.764,381524,critical,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,500,<NULL>,<NULL>,<NULL>
+2,<NULL>,2017-03-24 20:15:31.694,163930,warning,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,400,"{""foo"": ""bar""}","{""foo"": ""bar""}","{""foo"": ""bar""}"
diff --git a/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.err b/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.err
diff --git a/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.out b/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.out
new file mode 100644
index 0000000..889eb99
--- /dev/null
+++ b/test/expected/test_json_format.sh_c1a23804c39b0f74642286d69865ee9d0961a58a.out
@@ -0,0 +1,2 @@
+2022-09-24T00:00:09.484 Hello, World!
+2022-09-24T00:00:19.222 Goodbye, World!
diff --git a/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.err b/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.err
diff --git a/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.out b/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.out
new file mode 100644
index 0000000..a11ff06
--- /dev/null
+++ b/test/expected/test_json_format.sh_c60050b3469f37c5b0864e1dc7eb354e91d6ec81.out
@@ -0,0 +1,50 @@
+2016-08-03T12:06:31.009 - ;Exception initializing page context; java.lang.NoClassDefFoundError: javax/el/StaticFieldELResolver
+ at org.apache.jasper.runtime.JspFactoryImpl.internalGetPageContext(JspFactoryImpl.java:172)
+ at org.apache.jasper.runtime.JspFactoryImpl.getPageContext(JspFactoryImpl.java:123)
+ at org.apache.jsp.errors._404_002dnot_002dfound_jsp._jspService(_404_002dnot_002dfound_jsp.java:38)
+ at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
+ at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)
+ at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)
+ at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
+ at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
+ at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
+ at collective.config.startup.DamFilter.doFilter(DamFilter.java:270)
+ at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
+ at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
+ at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
+ at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)
+ at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
+ at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
+ at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:476)
+ at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:345)
+ at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:210)
+ at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
+ at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
+ at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
+ at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)
+ at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
+ at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
+ at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
+ at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
+ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
+ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
+ at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
+ at java.lang.Thread.run(Thread.java:744)
+Caused by: java.lang.ClassNotFoundException: javax.el.StaticFieldELResolver
+ at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
+ at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
+ ... 33 common frames omitted
+
+ @version: 1
+ logger_name: org.apache.jasper.runtime.JspFactoryImpl
+ thread_name: http-bio-0.0.0.0-8081-exec-198
+ level: ERROR
+ customer: foobaz
+2016-08-03T12:06:31.009 - ;Exception initializing page context; 
+ @version: 1
+ logger_name: org.apache.jasper.runtime.JspFactoryImpl
+ thread_name: http-bio-0.0.0.0-8081-exec-198
+ level: ERROR
+ customer: foobaz
diff --git a/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.err b/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.err
diff --git a/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.out b/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.out
new file mode 100644
index 0000000..b356898
--- /dev/null
+++ b/test/expected/test_json_format.sh_d0ec34389274affb70a5a76ba4789d51fd60f602.out
@@ -0,0 +1,4 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,client_ip,request/method,request/uri,request/size,response/status,details1,details2,details3
+0,<NULL>,2017-03-24 20:06:26.240,0,info,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,200,<NULL>,<NULL>,<NULL>
+1,<NULL>,2017-03-24 20:12:47.764,381524,critical,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,500,<NULL>,<NULL>,<NULL>
+2,<NULL>,2017-03-24 20:15:31.694,163930,warning,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,400,"{""foo"": ""bar""}","{""foo"": ""bar""}","{""foo"": ""bar""}"
diff --git a/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.err b/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.err
diff --git a/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.out b/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.out
new file mode 100644
index 0000000..951a389
--- /dev/null
+++ b/test/expected/test_json_format.sh_d7362cffc8335c2fe6b6527315de59bd6f5dcc7f.out
@@ -0,0 +1,3 @@
+2017-03-24T16:06:26.240 1.1.1.1 GET 200 /example/uri/5
+2017-03-24T16:12:47.764 1.1.1.1 GET 500 /example/uri/5
+2017-03-24T16:15:31.694 1.1.1.1 GET 400 /example/uri/5
diff --git a/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.err b/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.err
diff --git a/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.out b/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.out
new file mode 100644
index 0000000..c3d0110
--- /dev/null
+++ b/test/expected/test_json_format.sh_dfff27a651650a04d93de9a06ab5480e94ce3a79.out
@@ -0,0 +1,4 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,client_ip,request/method,request/uri,request/size,response/status,details1,details2,details3
+0,<NULL>,2017-03-24 16:06:26.240,0,info,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,200,<NULL>,<NULL>,<NULL>
+1,<NULL>,2017-03-24 16:12:47.764,381524,critical,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,500,<NULL>,<NULL>,<NULL>
+2,<NULL>,2017-03-24 16:15:31.694,163930,warning,0,<NULL>,<NULL>,<NULL>,1.1.1.1,GET,/example/uri/5,166,400,"{""foo"": ""bar""}","{""foo"": ""bar""}","{""foo"": ""bar""}"
diff --git a/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.err b/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.err
diff --git a/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.out b/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.out
new file mode 100644
index 0000000..325af1f
--- /dev/null
+++ b/test/expected/test_json_format.sh_fe19b7ebd349cd689b3f5c22618eab5ce995e68e.out
@@ -0,0 +1,4 @@
+-09-06T22:00:49.124 INFO Shutting down service
+ @fields/user: steve@example.com
+ @fields: { "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}
+
diff --git a/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.err b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.err
diff --git a/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out
new file mode 100644
index 0000000..9b2a7cd
--- /dev/null
+++ b/test/expected/test_logfile.sh_08d731a04c877a34819b35de185e30a74c9fd497.out
@@ -0,0 +1,3 @@
+2600-12-03 09:23:00.000000 0:
+2600-12-03 09:23:00.000000 0:
+2600-12-03 09:23:00.000000 0:
diff --git a/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.err b/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.err
diff --git a/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.out b/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.out
new file mode 100644
index 0000000..9317bcb
--- /dev/null
+++ b/test/expected/test_logfile.sh_09bd16e044302f6b121092534708594bdad11b5a.out
@@ -0,0 +1 @@
++0
diff --git a/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.err b/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.err
diff --git a/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.out b/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.out
new file mode 100644
index 0000000..ff67043
--- /dev/null
+++ b/test/expected/test_logfile.sh_1c6eee38f66356fcd9a9f0faedaea6dbcc901060.out
@@ -0,0 +1,2 @@
+ filepath  descriptor  mimetype  content 
+{test_dir}/logfile_syslog.1.gz net.zlib.gzip.header application/json {"name":"logfile_syslog.1","mtime":"2007-11-03T16:23:00.000","comment":""} 
diff --git a/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.err b/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.err
diff --git a/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.out b/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.out
new file mode 100644
index 0000000..4ed341d
--- /dev/null
+++ b/test/expected/test_logfile.sh_218ecb88b4753010c4264b3ac351260b4811612f.out
@@ -0,0 +1,2 @@
+basename(filepath)  descriptor  mimetype  content 
+logfile_syslog.1.gz net.zlib.gzip.header application/json {"name":"logfile_syslog.1","mtime":"2007-11-03T09:23:00.000","comment":""} 
diff --git a/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.err b/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.err
diff --git a/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.out b/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.out
new file mode 100644
index 0000000..7731fde
--- /dev/null
+++ b/test/expected/test_logfile.sh_290a3c49e53c2229a7400c107338fa0bb38375e2.out
@@ -0,0 +1,2 @@
+#Fields: ? )
+0
diff --git a/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.err b/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.err
diff --git a/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.out b/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.out
new file mode 100644
index 0000000..8d8b6ce
--- /dev/null
+++ b/test/expected/test_logfile.sh_3fc6bfd8a6160817211f3e14fde957af75b9dbe7.out
@@ -0,0 +1,2 @@
+#Date: 20?0-2-02
+0
diff --git a/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.err b/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.err
diff --git a/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.out b/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.out
new file mode 100644
index 0000000..8de34b8
--- /dev/null
+++ b/test/expected/test_logfile.sh_4a2a907fcb069b8d6e65961a7b2e796d6c3a87b1.out
@@ -0,0 +1,4 @@
+#Fields: 0 cs-bytes
+#Fields: 0
+ 0 #
+0
diff --git a/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.err b/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.err
diff --git a/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out b/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out
new file mode 100644
index 0000000..372e078
--- /dev/null
+++ b/test/expected/test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out
@@ -0,0 +1,10 @@
+Sep 19 09:24:04 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Mux ID not found in mapping dictionary
+Sep 19 09:24:04 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Can't handle disconnect with invalid ecid
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: Entered:_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: Entered:_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: tid:191f - Mux ID not found in mapping dictionary
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Mux ID not found in mapping dictionary
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: tid:191f - Can't handle disconnect with invalid ecid
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Can't handle disconnect with invalid ecid
diff --git a/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err b/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err
diff --git a/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out b/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out
new file mode 100644
index 0000000..13576d8
--- /dev/null
+++ b/test/expected/test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out
@@ -0,0 +1,6 @@
+000
+000
+#Fields: 0
+0
+#Fields: 0
+0
diff --git a/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.err b/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.err
diff --git a/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out b/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out
new file mode 100644
index 0000000..963f93c
--- /dev/null
+++ b/test/expected/test_logfile.sh_a7037efd0c4bbf51940137a44e57d94e9307e83e.out
@@ -0,0 +1 @@
+ 00:00
diff --git a/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err b/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.err
diff --git a/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out b/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out
new file mode 100644
index 0000000..0733b93
--- /dev/null
+++ b/test/expected/test_logfile.sh_c18e14a26d8261c9f72747118a469266121d5459.out
@@ -0,0 +1,3 @@
+log_line log_part log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters col_0 col_1
+ 0 <NULL> 2021-05-19 08:00:01.000 0 info 0 <NULL> <NULL> <NULL> 1 /abc/def
+ 2 <NULL> 2021-05-19 08:00:03.000 2000 info 0 <NULL> <NULL> <NULL> 3 /ghi/jkl
diff --git a/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err b/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.err
diff --git a/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out b/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out
new file mode 100644
index 0000000..9de987f
--- /dev/null
+++ b/test/expected/test_logfile.sh_e840b674cd65936a72bd64b1dac1524d16fe44c3.out
@@ -0,0 +1,11 @@
+ log_time  log_body 
+2022-09-19 09:24:04.000 tid:1d1f - Mux ID not found in mapping dictionary 
+2022-09-19 09:24:04.000 tid:1d1f - Can't handle disconnect with invalid ecid
+2022-09-19 09:24:20.000 Entered:_AMMuxedDeviceDisconnected, mux-device:1003 
+2022-09-19 09:24:20.000 Entered:_AMMuxedDeviceDisconnected, mux-device:1003
+2022-09-19 09:24:20.000 Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003 
+2022-09-19 09:24:20.000 Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003
+2022-09-19 09:24:20.000 tid:191f - Mux ID not found in mapping dictionary 
+2022-09-19 09:24:20.000 tid:1d1f - Mux ID not found in mapping dictionary
+2022-09-19 09:24:20.000 tid:191f - Can't handle disconnect with invalid ecid 
+2022-09-19 09:24:20.000 tid:1d1f - Can't handle disconnect with invalid ecid
diff --git a/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err b/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err
new file mode 100644
index 0000000..1f33d64
--- /dev/null
+++ b/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.err
@@ -0,0 +1,7 @@
+✘ error: invalid value for “log_tags” column of table “access_log”
+ reason: unexpected JSON value
+ |   --> access_log.log_tags:1
+ |   | 1 
+ |   = help: expecting an array of tag values
+ --> command-option:1
+ | ;UPDATE access_log SET log_tags = 1 WHERE log_line = 1
diff --git a/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.out b/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_154047fb52e4831aabf7d36512247bad6a6a2cf7.out
diff --git a/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.err b/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.err
new file mode 100644
index 0000000..96a52d7
--- /dev/null
+++ b/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.err
@@ -0,0 +1,11 @@
+✘ error: invalid value for “log_tags” column of table “access_log”
+ reason: “foo” is not a valid value for option “/#”
+ |  reason: value does not match pattern: ^#[^\s]+$
+ |   --> access_log.log_tags:1
+ |   | ["foo"] 
+ |   = help: Property Synopsis
+ |  /# tag
+ |  Description
+ |  A tag for the log line
+ --> command-option:1
+ | ;UPDATE access_log SET log_tags = json_array('foo') WHERE log_line = 1
diff --git a/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.out b/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_3c9b5940f7533c5fc3d4956a6efce50a9e7132d4.out
diff --git a/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.err b/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.err
diff --git a/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.out b/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.out
new file mode 100644
index 0000000..171d0f7
--- /dev/null
+++ b/test/expected/test_meta.sh_41f643bb4f720130625b042563e9591bee4ae588.out
@@ -0,0 +1,2 @@
+log_tags 
+["#foo"]
diff --git a/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.err b/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.err
diff --git a/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.out b/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.out
new file mode 100644
index 0000000..5ed367d
--- /dev/null
+++ b/test/expected/test_meta.sh_45ff39a3d0ac0ca0c95aaca14d043450cec1cedd.out
@@ -0,0 +1,5 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+ ├ Hello, World!
+ └ #foo
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.err b/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.err
diff --git a/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.out b/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.out
new file mode 100644
index 0000000..4731070
--- /dev/null
+++ b/test/expected/test_meta.sh_48e85ba0c0945a5085fb4ee255771406061a9c17.out
@@ -0,0 +1,6 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+ │ Hello, World!
+ │
+ └ This is  markdown  now!
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.err b/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.err
diff --git a/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.out b/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_meta.sh_4c39b356748c67ccf8a6027a1af88da532f8252a.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.err b/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.err
diff --git a/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.out b/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.out
new file mode 100644
index 0000000..78b865d
--- /dev/null
+++ b/test/expected/test_meta.sh_7b75763926d832bf9784ca234a060859770aabe7.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+ └ #foo
diff --git a/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.err b/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.err
diff --git a/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.out b/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_meta.sh_811b1a8a176b25001a89e35b295a1117ab76969b.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.err b/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.err
diff --git a/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.out b/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.out
new file mode 100644
index 0000000..2830598
--- /dev/null
+++ b/test/expected/test_meta.sh_83ac877aa9d38b25945cf96d6326a2468187c40f.out
@@ -0,0 +1,37 @@
+[2020-12-10 06:56:41,061] INFO [m:108] Calling 'x' with params:
+
+[2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text:
+ └ #xml-req
+<?xml version='1.0' encoding='iso-8859-2'?>
+<a-request>
+ <head>
+ x
+ </head>
+ <source>
+ x
+ </source>
+ <request id="1">
+ <name>
+ x
+ </name>
+ </request>
+</a-request>
+
+[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text:
+<?xml version='1.0' encoding='iso-8859-2'?>
+<a-reply>
+ <head>
+ x
+ </head>
+ <reply id="2">
+ <status>
+ <result>OK</result>
+ </status>
+ <name>
+ x
+ </name>
+ </reply>
+ <technical-track>
+ x
+ </technical-track>
+</a-reply>
diff --git a/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.err b/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.err
diff --git a/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.out b/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.out
new file mode 100644
index 0000000..08a6fcb
--- /dev/null
+++ b/test/expected/test_meta.sh_a7489c1f0e001adc732b7e2ab31bb30960fda078.out
@@ -0,0 +1,4 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+ └ Goodbye, World!
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.err b/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.err
diff --git a/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.out b/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_meta.sh_c063f96398650f130941bbbf4cf63c1244fdbee5.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.err b/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.err
diff --git a/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.out b/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.out
new file mode 100644
index 0000000..8462ae3
--- /dev/null
+++ b/test/expected/test_meta.sh_c75128169049bd88d5eaf8b84a7f617e5ae5d936.out
@@ -0,0 +1,4 @@
+log_line  log_comment log_tags 
+ 0 Hello, World! ["#foo"] 
+ 1 <NULL> <NULL>
+ 2 <NULL>  <NULL> 
diff --git a/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.err b/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.err
diff --git a/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.out b/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.out
new file mode 100644
index 0000000..5cf31b1
--- /dev/null
+++ b/test/expected/test_meta.sh_c8fb22932af2467a2651797a8a8d8cddcd09431d.out
@@ -0,0 +1,4 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+ └ #foo
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.err b/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.err
diff --git a/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.out b/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.out
new file mode 100644
index 0000000..a3e5357
--- /dev/null
+++ b/test/expected/test_meta.sh_d6af0b41066ca3be0bbce89c83c011f4ecfa516e.out
@@ -0,0 +1,5 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+ ├ Hello, World!
+ └ #foo
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.err b/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.err
diff --git a/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.out b/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.out
new file mode 100644
index 0000000..b842402
--- /dev/null
+++ b/test/expected/test_meta.sh_fd09cb565f44a114d8c9a519e571918e30262eaf.out
@@ -0,0 +1,4 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+ └ #foo
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.err b/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.err
diff --git a/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.out b/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.out
new file mode 100644
index 0000000..25b6f32
--- /dev/null
+++ b/test/expected/test_meta.sh_fdf4a91aa55262255816dff7d605f1f0a5d6fe92.out
@@ -0,0 +1,4 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+ └ Hello, World!
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err b/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.err
diff --git a/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.out b/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.out
new file mode 100644
index 0000000..35fadf8
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_3c255c3c8b28df9d694b329a265e8b8140dae4a2.out
@@ -0,0 +1,8 @@
+{
+ "wrapper": [
+ {"message":""
+ select Id from Account where id = $sfid
+ ^
+ ERROR at Row:1:Column:34
+ line 1:34 no viable alternative at character '$'
+""}]}
diff --git a/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.err b/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.err
diff --git a/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.out b/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.out
new file mode 100644
index 0000000..f6eae9d
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_4111e649fb49c0a377e552fa0b56c60c370633da.out
@@ -0,0 +1,4 @@
+{
+ Example: foo,
+ bar: baz
+}
diff --git a/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.err b/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.err
diff --git a/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.out b/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.out
new file mode 100644
index 0000000..0808acf
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_675a2ff6306df7c54127e39319cf06a2dd353145.out
@@ -0,0 +1,5 @@
+[2020-12-10 06:56:41,061] INFO [:108] Calling 'x' with params:
+[2020-12-10 06:56:41,092] DEBUG [:69] Full request text:
+/a-request, /a-request/head, /a-request/source, /a-request/request, /a-request/request/name
+[2020-12-10 06:56:41,099] DEBUG [:85] Full reply text:
+/a-reply, /a-reply/head, /a-reply/reply, /a-reply/reply/status, /a-reply/reply/status/result, /a-reply/reply/name, /a-reply/technical-track
diff --git a/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.err b/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.err
diff --git a/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.out b/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.out
new file mode 100644
index 0000000..613cc3a
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_7192f8f68adb14705c8a60e73ff8248c61c7fd03.out
@@ -0,0 +1,5 @@
+2015-04-18T13:16:30.003 {
+ "wrapper": {"msg": r""
+ Hello,
+ World!
+""}}
diff --git a/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.err b/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.err
diff --git a/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.out b/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.out
new file mode 100644
index 0000000..0ac4c9a
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_a5bee322ea3374690e44a88a16cb6b84feaa11d3.out
@@ -0,0 +1,3 @@
+Hello
+World
+
diff --git a/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.err b/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.err
diff --git a/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out b/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out
new file mode 100644
index 0000000..3fb9189
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_a6d9042e5e95f2a49194bd80c1eed154813ddf41.out
@@ -0,0 +1,19 @@
+Mar 24 15:17:38.999 000000000264F I shmem.res 262144 262144 1 chassis_msg_svc/osenv::req_blocking<osenv::req_lambda<tcp_messaging_impl::register_app(svc::messaging_port,
+ defs::atom*,
+ defs::borrowed<svc::messaging_session>,
+ defs::owned<svc::connection_eviction_strategy>&&,
+ svc::messaging::connection_type,
+ svc::messaging::app_param
+)::{lambda()#1}>, osenv::aloc_dynamic_named<tcp_messaging_impl::register_app(svc::messaging_port,
+ defs::atom*,
+ defs::borrowed<svc::messaging_session>,
+ defs::owned<svc::connection_eviction_strategy>&&,
+ svc::messaginconnection_type,
+ svc::messaging::app_param
+)::{lambda()#1}, osenv::temporal, tcp_messaging_impl::register_app(svc::messaging_port,
+ defs::atom*,
+ defs::borrowed<svc::messaging_session>,
+ des::owned<svc::connection_eviction_strategy>&&,
+ svc::messaging::connection_type,
+ svc::messaging::app_param
+)::{lambda()#1}>, osenv::req>->fiber stacks
diff --git a/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err b/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.err
diff --git a/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out b/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out
new file mode 100644
index 0000000..c3e4e85
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_cd361eeca7e91bfab942b75d6c3422c7a456a111.out
@@ -0,0 +1,3 @@
+2015-04-18T13:16:30.003 8.8.8.8
+<foo>8.8.8.8</foo>
+9 8.8.8.8<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6
diff --git a/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.err b/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.err
diff --git a/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.out b/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.out
new file mode 100644
index 0000000..35f3af0
--- /dev/null
+++ b/test/expected/test_pretty_print.sh_f8feb52a321026d9562b271eb37a2c56dfaed329.out
@@ -0,0 +1 @@
+2022-06-22T10:20:33 Example foo
diff --git a/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.err b/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.err
new file mode 100644
index 0000000..cd096a9
--- /dev/null
+++ b/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.err
@@ -0,0 +1,2 @@
+✘ error: regex “std” of format “syslog_log” has not been pushed to regex101.com
+ = help: use the “push” subcommand to create the regex on regex101.com for easy editing
diff --git a/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.out b/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_0fa3663a45aca6a328cb728872af7ed7ee896f1c.out
diff --git a/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.err b/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.err
new file mode 100644
index 0000000..3b83cb4
--- /dev/null
+++ b/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.err
@@ -0,0 +1,3 @@
+✘ error: unable to import: https://regex101.com/r/zpEnjV/1
+ reason: format file already exists: regex101-home/.lnav/formats/installed/unit_test_log.json
+ = help: delete the existing file to continue
diff --git a/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.out b/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_182ae9244db314a953af2bee969726e381bc5a32.out
diff --git a/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.err b/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.err
new file mode 100644
index 0000000..bbcd290
--- /dev/null
+++ b/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.err
@@ -0,0 +1,3 @@
+⚠ warning: not deleting regex101 entry “zpEnjV”
+ reason: delete code is not known for this entry
+ = note: formats created by importing a regex101.com entry will not have a delete code
diff --git a/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.out b/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.out
new file mode 100644
index 0000000..bb52e20
--- /dev/null
+++ b/test/expected/test_regex101.sh_2158f1f011ba8e1b152396c072790c076fdb8ce8.out
@@ -0,0 +1 @@
+✔ deleted regex101 entry: zpEnjV
diff --git a/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.err b/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.err
new file mode 100644
index 0000000..286a1cf
--- /dev/null
+++ b/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.err
@@ -0,0 +1 @@
+✘ error: expecting a regex101.com URL to import
diff --git a/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.out b/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_281af24141680330791db7f7c5fa70833ce08a6b.out
diff --git a/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.err b/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.err
diff --git a/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.out b/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.out
new file mode 100644
index 0000000..a56e549
--- /dev/null
+++ b/test/expected/test_regex101.sh_35703b13990785632cca82123fb3883797959c0b.out
@@ -0,0 +1,4 @@
+✔ converted regex101 entry to format file: regex101-home/.lnav/formats/installed/unit_test_log.json
+ = note: the converted format may still have errors
+ = help: use the following command to patch the regex as more changes are made on regex101.com:
+ lnav -m format unit_test_log regex std regex101 pull
diff --git a/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.err b/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.err
diff --git a/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.out b/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.out
new file mode 100644
index 0000000..7f5397d
--- /dev/null
+++ b/test/expected/test_regex101.sh_366730cac50b4a09b7de4b84641791470b1cb9a3.out
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "unit_test_log": {
+ "regex": {
+ "std": {
+ "pattern": "\\[(?<timestamp>\\d+\\/\\d+\\/\\d+ \\d+:\\d+:\\d+) (?<jobserver>[\\w.]+) (?<workqueue>[\\w.]+) (?<processid>\\d+)\\] (?<body>.*)$"
+ }
+ }
+ }
+}
diff --git a/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.err b/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.err
new file mode 100644
index 0000000..32c87d4
--- /dev/null
+++ b/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.err
@@ -0,0 +1,34 @@
+✘ error: invalid value “/unit_test_log/value/jobserver”
+ reason: no patterns have a capture named “jobserver”
+ = note: the following captures are available:
+
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid value “/unit_test_log/value/processid”
+ reason: no patterns have a capture named “processid”
+ = note: the following captures are available:
+
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid value “/unit_test_log/value/timestamp”
+ reason: no patterns have a capture named “timestamp”
+ = note: the following captures are available:
+
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid value “/unit_test_log/value/workqueue”
+ reason: no patterns have a capture named “workqueue”
+ = note: the following captures are available:
+
+ = help: values are populated from captures in patterns, so at least one pattern must have a capture with this value name
+✘ error: invalid sample log message: "[03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {\"ELAPSED\":\"0.011\",\"LEVEL\":\"info\",\"MESSAGE\":\"finished in 0.011\\n\",\"PREFIX\":\"YFgyWQriCmsAAofJAAAAHg\",\"ROUTINGKEY\":\"EXAMPLE1366.Example.Events._Publish\"}"
+ reason: sample does not match any patterns
+ --> regex101-home/.lnav/formats/installed/unit_test_log.json:26
+ = note: the following shows how each pattern matched this sample:
+ [03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {"ELAPSED":"0.011","LEVEL":"info","MESSAGE":"finished in 0.011\n","PREFIX":"YFgyWQriCmsAAofJAAAAHg","ROUTINGKEY":"EXAMPLE1366.Example.Events._Publish"}
+ = note: std = “”
+
+✘ error: invalid sample log message: "[03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {\"ELAPSED\":\"0.011\",\"LEVEL\":\"info\",\"MESSAGE\":\"finished in 0.011\\n\",\"PREFIX\":\"YFgyWQriCmsAAofJAAAAHg\",\"ROUTINGKEY\":\"EXAMPLE1366.Example.Events._Publish\"}"
+ reason: sample does not match any patterns
+ --> regex101-home/.lnav/formats/installed/unit_test_log.json:30
+ = note: the following shows how each pattern matched this sample:
+ [03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {"ELAPSED":"0.011","LEVEL":"info","MESSAGE":"finished in 0.011\n","PREFIX":"YFgyWQriCmsAAofJAAAAHg","ROUTINGKEY":"EXAMPLE1366.Example.Events._Publish"}
+ = note: std = “”
+
diff --git a/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.out b/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.out
new file mode 100644
index 0000000..93cf6b4
--- /dev/null
+++ b/test/expected/test_regex101.sh_3d18474a3e472fff6e23e0c41337ec9188fee591.out
@@ -0,0 +1,3 @@
+✔ format patch file written to: regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json
+ = help: once the regex has been found to be working correctly, move the contents of the patch file to the original file at:
+ regex101-home/.lnav/formats/installed/unit_test_log.json
diff --git a/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.err b/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.err
diff --git a/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.out b/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.out
new file mode 100644
index 0000000..7329b20
--- /dev/null
+++ b/test/expected/test_regex101.sh_442cc58676590a3604d5c2183f5fe0a75c98351a.out
@@ -0,0 +1,2 @@
+regex101-home/.lnav/formats/installed/unit_test_log.json
+regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json
diff --git a/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.err b/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.err
diff --git a/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.out b/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.out
new file mode 100644
index 0000000..3fd83a6
--- /dev/null
+++ b/test/expected/test_regex101.sh_566fd88d216a44bc1c6e23f2d6f2d0caf99d42f9.out
@@ -0,0 +1 @@
+✔ no regex101 entries found
diff --git a/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.err b/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.err
new file mode 100644
index 0000000..6d4ee32
--- /dev/null
+++ b/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.err
@@ -0,0 +1,3 @@
+✘ error: cannot delete regex101 entry while patch file exists
+ = note: regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json
+ = help: move the contents of the patch file to the main log format and then delete the file to continue
diff --git a/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.out b/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_5f2f7ecb6ab9cbec4b41385b91bd038906b8a7b2.out
diff --git a/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.err b/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.err
new file mode 100644
index 0000000..83dd591
--- /dev/null
+++ b/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.err
@@ -0,0 +1,3 @@
+✘ error: invalid regex “abc(def)” from “https://regex101.com/r/cvCJNP/1”
+ reason: unsupported regex flavor: “gm”
+ = help: the supported flavors are: pcre, pcre2
diff --git a/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.out b/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_629bde30483e0a6461076e9058f3a5eb81ae0425.out
diff --git a/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.err b/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.err
diff --git a/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.out b/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.out
new file mode 100644
index 0000000..8b0d55d
--- /dev/null
+++ b/test/expected/test_regex101.sh_630db454054cf92ec9bd0f4e3e83300047f583ff.out
@@ -0,0 +1,4 @@
+✔ converted regex101 entry to format file: regex101-home/.lnav/formats/installed/unit_test_log.regex101-hGiqBL.json
+ = note: the converted format may still have errors
+ = help: use the following command to patch the regex as more changes are made on regex101.com:
+ lnav -m format unit_test_log regex alt regex101 pull
diff --git a/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.err b/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.err
new file mode 100644
index 0000000..e533bd6
--- /dev/null
+++ b/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.err
@@ -0,0 +1 @@
+✘ error: unknown regex: non-existent
diff --git a/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.out b/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_771af6f3d29b8350542d5c6e98bdbf4c223cd531.out
diff --git a/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.err b/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.err
new file mode 100644
index 0000000..450b99b
--- /dev/null
+++ b/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.err
@@ -0,0 +1,5 @@
+✘ error: expecting an operation to perform on the std regex using regex101.com
+ = help: the available subcommands are:
+ • push: create/update an entry for this regex on regex101.com
+ • pull: create a patch format file for this regular expression based on the entry in regex101.com
+ • delete: delete the entry regex101.com that was created by a push operation
diff --git a/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.out b/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_7991a5b617867cf37c9f7baa85ffa425f7d455a2.out
diff --git a/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.err b/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.err
diff --git a/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.out b/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.out
new file mode 100644
index 0000000..4985cf6
--- /dev/null
+++ b/test/expected/test_regex101.sh_79ee3f5fe71ccec97b2619d8c1f74ca97ffd2243.out
@@ -0,0 +1,2 @@
+✔ local regex is in sync with entry “zpEnjV” on regex101.com
+ = help: make edits on “https://regex101.com/r/zpEnjV” and then run this command again to update the local values
diff --git a/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.err b/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.err
new file mode 100644
index 0000000..8b825ab
--- /dev/null
+++ b/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.err
@@ -0,0 +1,3 @@
+✘ error: unknown regex: s
+ = note: did you mean one of the following?
+ std
diff --git a/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.out b/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_7de76c174c58d67bf93e8f01d6d55ebb6a023f10.out
diff --git a/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.err b/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.err
diff --git a/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.out b/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.out
new file mode 100644
index 0000000..265ad46
--- /dev/null
+++ b/test/expected/test_regex101.sh_8a43e6657d4f60e68d31eb8302542ca28e80d077.out
@@ -0,0 +1,3 @@
+✔ the following regex101 entries were found:
+ format unit_test_log regex std regex101
+
diff --git a/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.err b/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.err
new file mode 100644
index 0000000..db47111
--- /dev/null
+++ b/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.err
@@ -0,0 +1,3 @@
+✘ error: expecting an operation to perform on the std regular expression
+ = help: the available subcommands are:
+ • regex101: use regex101.com to edit this regular expression
diff --git a/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.out b/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_8e93a3b6b941847c71409a297779fbb0a6666a51.out
diff --git a/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.err b/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.err
new file mode 100644
index 0000000..2064fc4
--- /dev/null
+++ b/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.err
@@ -0,0 +1,4 @@
+✘ error: unable to import: abc
+ reason: expecting a format name that matches the regular expression “^\w+$”
+ = note: “def-jkl”
+ ^ matched up to here
diff --git a/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.out b/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_95c56a9d146ec9a7c2196559d316f928b2ae6ae9.out
diff --git a/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.err b/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.err
new file mode 100644
index 0000000..ca5b424
--- /dev/null
+++ b/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.err
@@ -0,0 +1 @@
+✘ error: no regex101 entry for syslog_log/std
diff --git a/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.out b/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_9d101ee29c45cdb8c0f117ad736c9a5dd5da5839.out
diff --git a/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.err b/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.err
new file mode 100644
index 0000000..f705892
--- /dev/null
+++ b/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.err
@@ -0,0 +1,2 @@
+✘ error: unable to get entry “badregex123” on regex101.com
+ reason: received response code 400 content “{"error":"Invalid permalink id",}”
diff --git a/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.out b/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_c43e07df9b3068696fdc8759c7561135db981b38.out
diff --git a/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.err b/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.err
diff --git a/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.out b/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.out
new file mode 100644
index 0000000..c06f523
--- /dev/null
+++ b/test/expected/test_regex101.sh_cbd859487e4ea011cd6e0f0f114d70158bfd8b43.out
@@ -0,0 +1,34 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "unit_test_log": {
+ "description": "Format file generated from regex101 entry -- https://regex101.com/r/zpEnjV/2",
+ "regex": {
+ "std": {
+ "pattern": "\\[(?<timestamp>\\d+\\/\\d+\\/\\d+ \\d+:\\d+:\\d+) (?<jobserver>[\\w.]+) (?<workqueue>[\\w.]+) (?<processid>\\d+)\\] (?<body>.*)$"
+ }
+ },
+ "value": {
+ "jobserver": {
+ "kind": "string"
+ },
+ "processid": {
+ "kind": "string"
+ },
+ "timestamp": {
+ "kind": "string"
+ },
+ "workqueue": {
+ "kind": "string"
+ }
+ },
+ "sample": [
+ {
+ "line": "[03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {\"ELAPSED\":\"0.011\",\"LEVEL\":\"info\",\"MESSAGE\":\"finished in 0.011\\n\",\"PREFIX\":\"YFgyWQriCmsAAofJAAAAHg\",\"ROUTINGKEY\":\"EXAMPLE1366.Example.Events._Publish\"}"
+ },
+ {
+ "description": "sample 1",
+ "line": "[03/22/2021 02:00:02 job1074.example.com db.db81.example_events 54026] {\"ELAPSED\":\"0.011\",\"LEVEL\":\"info\",\"MESSAGE\":\"finished in 0.011\\n\",\"PREFIX\":\"YFgyWQriCmsAAofJAAAAHg\",\"ROUTINGKEY\":\"EXAMPLE1366.Example.Events._Publish\"}"
+ }
+ ]
+ }
+}
diff --git a/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.err b/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.err
new file mode 100644
index 0000000..9b187b7
--- /dev/null
+++ b/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.err
@@ -0,0 +1 @@
+✘ error: unknown format: non-existent
diff --git a/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.out b/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_cf6c0a9f0f04e24ce1fae7a0a434830b14447f83.out
diff --git a/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.err b/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.err
new file mode 100644
index 0000000..85a97ba
--- /dev/null
+++ b/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.err
@@ -0,0 +1,7 @@
+✘ error: expecting an operation to perform on the std regex using regex101.com
+ = note: this regex is currently associated with the following regex101.com entry:
+ https://regex101.com/r/zpEnjV
+ = help: the available subcommands are:
+ • push: create/update an entry for this regex on regex101.com
+ • pull: create a patch format file for this regular expression based on the entry in regex101.com
+ • delete: delete the entry regex101.com that was created by a push operation
diff --git a/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.out b/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_d84597760285c3964b258726341e018f6cd49954.out
diff --git a/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.err b/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.err
diff --git a/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.out b/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.out
new file mode 100644
index 0000000..d37aaa6
--- /dev/null
+++ b/test/expected/test_regex101.sh_f23e393dbf23d0d8e276e9b7610c7b74d79980f8.out
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "unit_test_log": {
+ "regex": {
+ "alt": {
+ "pattern": "^\\[(?<timestamp>\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3,6})?)Z?\\](?<body>.*)$"
+ }
+ },
+ "sample": [
+ {
+ "line": "[2021-05-21T21:58:57.022497Z]"
+ }
+ ]
+ }
+}
diff --git a/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.err b/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.err
new file mode 100644
index 0000000..494a387
--- /dev/null
+++ b/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.err
@@ -0,0 +1 @@
+✘ error: “bro” is an internal format that is not defined in a configuration file
diff --git a/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.out b/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_regex101.sh_fc41b6ee90cbf038620151f16d164b361acf82dd.out
diff --git a/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err b/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.err
diff --git a/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out b/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out
new file mode 100644
index 0000000..bccea86
--- /dev/null
+++ b/test/expected/test_sessions.sh_0300a1391c33b1c45ddfa90198a6bd0a5404a77f.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err b/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.err
diff --git a/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out b/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out
new file mode 100644
index 0000000..2140e81
--- /dev/null
+++ b/test/expected/test_sessions.sh_17b85654b929b2a8fc1705a170ced544783292fa.out
@@ -0,0 +1,3 @@
+⋮ - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+⋮ - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+⋮ - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err b/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.err
diff --git a/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out b/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_345b0e66dab7b881397c4b38380da81092ab70dd.out
diff --git a/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err b/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.err
diff --git a/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.out b/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_430b9522ba1a37983138f3c4935cba91b781e415.out
diff --git a/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.err b/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.err
diff --git a/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.out b/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_4f13dd3858546b6e04a27e244159d355e368f2ae.out
diff --git a/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.err b/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.err
diff --git a/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.out b/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.out
new file mode 100644
index 0000000..d07a9c0
--- /dev/null
+++ b/test/expected/test_sessions.sh_68a89b56c5e7f7db620084cca1eb547cbb19a2c9.out
@@ -0,0 +1,4 @@
+log_line,log_part
+0,<NULL>
+1,middle
+2,middle
diff --git a/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.err b/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.err
diff --git a/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.out b/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.out
new file mode 100644
index 0000000..adef6fa
--- /dev/null
+++ b/test/expected/test_sessions.sh_6d87ff483d5785c58fb271a405ff1c35e4f83cd9.out
@@ -0,0 +1,36 @@
+#!lnav -Nf
+# This file is an export of an lnav session. You can type
+# '|/path/to/this/file' in lnav to execute this file and
+# restore the state of the session.
+
+;SELECT raise_error('This session export was made with a newer version of lnav, please upgrade to ' || '0.11.1' || ' or later')
+ WHERE lnav_version() < '0.11.1' COLLATE naturalcase
+
+# The files loaded into the session were:
+
+
+# Set this environment variable to override this value or edit this script.
+;INSERT OR IGNORE INTO environ (name, value) VALUES ('LOG_DIR_0', '{test_dir}')
+:open $LOG_DIR_0/support-dump/logfile_access_log.0
+:open $LOG_DIR_0/support-dump/logfile_access_log.1
+
+:rebuild
+
+
+# The following SQL statements will restore the bookmarks,
+# comments, and tags that were added in the session.
+
+;SELECT total_changes() AS before_mark_changes
+;UPDATE all_logs SET log_mark = 1, log_comment = NULL, log_tags = NULL WHERE log_time_msecs = 1248130769000 AND log_format = 'access_log' AND log_line_hash = 'v1:b05c1bdfe75cde41e151c89087e31951'
+
+;SELECT 1 - (total_changes() - $before_mark_changes) AS failed_mark_changes
+;SELECT echoln(printf('%sERROR%s: failed to restore %d bookmarks',
+ $ansi_red, $ansi_norm, $failed_mark_changes))
+ WHERE $failed_mark_changes != 0
+
+
+# The following commands will restore the state of the LOG view.
+
+:switch-to-view log
+:hide-file */support-dump/logfile_access_log.1
+:goto 1
diff --git a/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err b/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.err
diff --git a/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out b/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out
new file mode 100644
index 0000000..ba6bfe9
--- /dev/null
+++ b/test/expected/test_sessions.sh_858fd0081ed9c46dd81e2f81f1090756f2463558.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [01/Jan/2010:00:00:00 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [01/Jan/2010:00:00:03 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [01/Jan/2010:00:00:03 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.err b/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.err
diff --git a/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.out b/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.out
new file mode 100644
index 0000000..a1e2e6f
--- /dev/null
+++ b/test/expected/test_sessions.sh_8732dad5481be991ca7f291d9c5451c7b016cea7.out
@@ -0,0 +1,33 @@
+#!lnav -Nf
+# This file is an export of an lnav session. You can type
+# '|/path/to/this/file' in lnav to execute this file and
+# restore the state of the session.
+
+;SELECT raise_error('This session export was made with a newer version of lnav, please upgrade to ' || '0.11.0' || ' or later')
+ WHERE lnav_version() < '0.11.0' COLLATE naturalcase
+
+# The files loaded into the session were:
+
+
+;INSERT OR IGNORE INTO environ (name, value) VALUES ('LOG_DIR_0', '{top_srcdir_parent}')
+:open $LOG_DIR_0/lnav/test/logfile_access_log.0
+
+:rebuild
+
+
+# The following SQL statements will restore the bookmarks,
+# comments, and tags that were added in the session.
+
+;SELECT total_changes() AS before_mark_changes
+;UPDATE all_logs SET log_mark = 1, log_comment = NULL, log_tags = NULL WHERE log_time_msecs = 1248130769000 AND log_format = 'access_log' AND log_line_hash = 'v1:b05c1bdfe75cde41e151c89087e31951'
+
+;SELECT 1 - (total_changes() - $before_mark_changes) AS failed_mark_changes
+;SELECT echoln(printf('%sERROR%s: failed to restore %d bookmarks',
+ $ansi_red, $ansi_norm, $failed_mark_changes))
+ WHERE $failed_mark_changes != 0
+
+
+# The following commands will restore the state of the LOG view.
+
+:switch-to-view log
+:goto 1
diff --git a/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err b/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.err
diff --git a/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out b/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_903b41c950f5f90d7786d7a09bb6e2f217654b15.out
diff --git a/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err b/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.err
diff --git a/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.out b/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.out
new file mode 100644
index 0000000..a9dd3d0
--- /dev/null
+++ b/test/expected/test_sessions.sh_92a98a3e4e3a10bf1f2371d21a8282c5d3d4baa5.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.err b/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.err
diff --git a/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.out b/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.out
new file mode 100644
index 0000000..3c84ede
--- /dev/null
+++ b/test/expected/test_sessions.sh_9978aaa475513f9981840e612f853a7707ffcf90.out
@@ -0,0 +1,11 @@
+view_name filter_id enabled type language pattern
+log 1 1 out regex blah
+ name search
+log foobar
+text
+help
+histogram
+db
+schema
+pretty
+spectro
diff --git a/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.err b/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.err
diff --git a/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out b/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_a92822d121a836140a401fd71535dc4a7a8d5b48.out
diff --git a/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err b/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.err
diff --git a/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out b/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_b3d71a87fcb4e3487f71ccad8c6ce681db220572.out
diff --git a/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err b/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.err
diff --git a/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out b/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out
new file mode 100644
index 0000000..ad2b37e
--- /dev/null
+++ b/test/expected/test_sessions.sh_b932b33dd087b94d4306dd179c5d4f9ddd394960.out
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err b/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.err
diff --git a/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out b/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out
new file mode 100644
index 0000000..ad2b37e
--- /dev/null
+++ b/test/expected/test_sessions.sh_ddf45811e9906de9f3930fe802ac7b2cc6e48106.out
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.err b/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.err
diff --git a/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.out b/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.out
new file mode 100644
index 0000000..0473e9d
--- /dev/null
+++ b/test/expected/test_sessions.sh_e39648f425c3f291c9d1c0d14595a019abd0cb48.out
@@ -0,0 +1,33 @@
+#!lnav -Nf
+# This file is an export of an lnav session. You can type
+# '|/path/to/this/file' in lnav to execute this file and
+# restore the state of the session.
+
+;SELECT raise_error('This session export was made with a newer version of lnav, please upgrade to ' || '0.11.0' || ' or later')
+ WHERE lnav_version() < '0.11.0' COLLATE naturalcase
+
+# The files loaded into the session were:
+
+
+;INSERT OR IGNORE INTO environ (name, value) VALUES ('LOG_DIR_0', '{test_dir}')
+:open $LOG_DIR_0/support-dump/logfile_access_log.0
+
+:rebuild
+
+
+# The following SQL statements will restore the bookmarks,
+# comments, and tags that were added in the session.
+
+;SELECT total_changes() AS before_mark_changes
+;UPDATE all_logs SET log_mark = 1, log_comment = NULL, log_tags = NULL WHERE log_time_msecs = 1248130769000 AND log_format = 'access_log' AND log_line_hash = 'v1:b05c1bdfe75cde41e151c89087e31951'
+
+;SELECT 1 - (total_changes() - $before_mark_changes) AS failed_mark_changes
+;SELECT echoln(printf('%sERROR%s: failed to restore %d bookmarks',
+ $ansi_red, $ansi_norm, $failed_mark_changes))
+ WHERE $failed_mark_changes != 0
+
+
+# The following commands will restore the state of the LOG view.
+
+:switch-to-view log
+:goto 1
diff --git a/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err b/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.err
diff --git a/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out b/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out
new file mode 100644
index 0000000..fd072bc
--- /dev/null
+++ b/test/expected/test_shlexer.sh_14dd967cb2af90899c9e5e45d00b676b5a3163aa.out
@@ -0,0 +1,7 @@
+ ~ foo
+til ^
+wsp ^
+eval -- ../test foo
+split:
+ 0 -- ../test
+ 1 -- foo
diff --git a/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err b/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.err
diff --git a/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.out b/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.out
new file mode 100644
index 0000000..b7ba9e8
--- /dev/null
+++ b/test/expected/test_shlexer.sh_2781f5dd570580cbe746ad91b58a28b8371283b3.out
@@ -0,0 +1,7 @@
+ ~nonexistent/bar baz
+til ^----------^
+wsp ^
+eval -- ~nonexistent/bar baz
+split:
+ 0 -- ~nonexistent/bar
+ 1 -- baz
diff --git a/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.err b/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.err
diff --git a/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.out b/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.out
new file mode 100644
index 0000000..85cca78
--- /dev/null
+++ b/test/expected/test_shlexer.sh_2af44d06fc137a77bc230be86376ccad23a2806b.out
@@ -0,0 +1,2 @@
+ \
+err ^
diff --git a/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.err b/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.err
diff --git a/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.out b/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.out
new file mode 100644
index 0000000..f677b17
--- /dev/null
+++ b/test/expected/test_shlexer.sh_6858e530a8ecb77cbaec1a7507768dd5a1942ac9.out
@@ -0,0 +1,5 @@
+ ${FOO}
+qrf ^----^
+eval -- bar
+split:
+ 0 -- bar
diff --git a/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.err b/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.err
diff --git a/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.out b/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.out
new file mode 100644
index 0000000..630eb1c
--- /dev/null
+++ b/test/expected/test_shlexer.sh_7f31e16ea2469da7a4328c93c7bcc8e109f84d2f.out
@@ -0,0 +1,7 @@
+ "abc ${DEF} 123"
+dst ^
+qrf ^----^
+den ^
+eval -- "abc xyz 123"
+split:
+ 0 -- abc xyz 123
diff --git a/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.err b/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.err
diff --git a/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.out b/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.out
new file mode 100644
index 0000000..759e75b
--- /dev/null
+++ b/test/expected/test_shlexer.sh_8aeebcdef56edd783579eaaddaff7c5cc127bb86.out
@@ -0,0 +1,6 @@
+ 'abc $DEF 123'
+sst ^
+sen ^
+eval -- 'abc $DEF 123'
+split:
+ 0 -- abc $DEF 123
diff --git a/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.err b/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.err
diff --git a/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.out b/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.out
new file mode 100644
index 0000000..2cbee1a
--- /dev/null
+++ b/test/expected/test_shlexer.sh_8e9addb0e5b6f4254d81dd89ecf12783109644bb.out
@@ -0,0 +1,7 @@
+ "abc $DEF 123"
+dst ^
+ref ^--^
+den ^
+eval -- "abc xyz 123"
+split:
+ 0 -- abc xyz 123
diff --git a/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.err b/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.err
diff --git a/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.out b/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.out
new file mode 100644
index 0000000..9a2b2a7
--- /dev/null
+++ b/test/expected/test_shlexer.sh_90961e6728e96d0a44535a6c9907cc990c10316c.out
@@ -0,0 +1,6 @@
+ "def"
+dst ^
+den ^
+eval -- "def"
+split:
+ 0 -- def
diff --git a/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.err b/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.err
diff --git a/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.out b/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.out
new file mode 100644
index 0000000..30a7791
--- /dev/null
+++ b/test/expected/test_shlexer.sh_95c4e861804a5434900fdb4d67b149d1baa2edf4.out
@@ -0,0 +1,5 @@
+ $FOO
+ref ^--^
+eval -- bar
+split:
+ 0 -- bar
diff --git a/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.err b/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.err
diff --git a/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.out b/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.out
new file mode 100644
index 0000000..a2ae7ff
--- /dev/null
+++ b/test/expected/test_shlexer.sh_d7fe5f6b8fc9ba00539fad0fa0bfb08319d8b04b.out
@@ -0,0 +1,6 @@
+ 'abc'
+sst ^
+sen ^
+eval -- 'abc'
+split:
+ 0 -- abc
diff --git a/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.err b/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.err
diff --git a/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.out b/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.out
new file mode 100644
index 0000000..def9d5c
--- /dev/null
+++ b/test/expected/test_shlexer.sh_d9d46422a913e3a06ddbd262933ef5352c30e68f.out
@@ -0,0 +1,9 @@
+ abc $DEF 123
+wsp ^
+ref ^--^
+wsp ^^
+eval -- abc xyz 123
+split:
+ 0 -- abc
+ 1 -- xyz
+ 2 -- 123
diff --git a/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.err b/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.err
diff --git a/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out b/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out
new file mode 100644
index 0000000..9b84999
--- /dev/null
+++ b/test/expected/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out
@@ -0,0 +1,6 @@
+ '"'
+sst ^
+sen ^
+eval -- '"'
+split:
+ 0 -- "
diff --git a/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err b/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err
diff --git a/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out b/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out
new file mode 100644
index 0000000..a668d4d
--- /dev/null
+++ b/test/expected/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out
@@ -0,0 +1,6 @@
+ "'"
+dst ^
+den ^
+eval -- "'"
+split:
+ 0 -- '
diff --git a/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.err b/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.err
new file mode 100644
index 0000000..8b97c72
--- /dev/null
+++ b/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: no such table: nonexistent_table
+ --> command-option:1
+ | select * from nonexistent_table 
diff --git a/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.out b/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_02def66745b063518473df862987747909f56ccc.out
diff --git a/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err b/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err
diff --git a/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.out b/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.out
new file mode 100644
index 0000000..386f1e3
--- /dev/null
+++ b/test/expected/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.out
@@ -0,0 +1,2 @@
+ lnav_top_file() 
+{test_dir}/logfile_access_log.0
diff --git a/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.err b/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.err
new file mode 100644
index 0000000..0b7649a
--- /dev/null
+++ b/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: the stop parameter is required
+ --> command-option:1
+ | SELECT * FROM generate_series(1) 
diff --git a/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.out b/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_0d46ee142f80f262c8c14a22751571cc567df525.out
diff --git a/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.err b/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.err
diff --git a/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.out b/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.out
new file mode 100644
index 0000000..4acb940
--- /dev/null
+++ b/test/expected/test_sql.sh_13429aed81d7edfd47b57e9cdb8a25c43aff35c4.out
@@ -0,0 +1,2 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters  c_ip cs_bytes cs_method cs_uri_query  cs_uri_stem cs_username cs_vars cs_version s_app s_core s_pid s_req s_runtime s_switches s_worker_reqs sc_bytes sc_header_bytes sc_headers sc_status 
+ 0  <NULL> 2016-03-13 22:49:12.000  0 info   0  <NULL>  <NULL>  <NULL> 127.0.0.1  696 POST   <NULL> /update_metrics     38 HTTP/1.1  0   3  88185  1  0.129  1  1  47  378  9    200 
diff --git a/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.err b/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.err
diff --git a/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.out b/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.out
new file mode 100644
index 0000000..df0e6d7
--- /dev/null
+++ b/test/expected/test_sql.sh_1cbb81cfe40ee16332c5c775a74d06b945aa65c2.out
@@ -0,0 +1,3 @@
+id first_name last_name age 
+ 0 Phil  Myman   30 
+ 1 Lem  Hewitt   35
diff --git a/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.err b/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.err
new file mode 100644
index 0000000..b57e6bc
--- /dev/null
+++ b/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.err
@@ -0,0 +1,10 @@
+✘ error: “bad(” is not a valid regular expression
+ reason: missing closing parenthesis
+ --> pattern
+ | bad( 
+ |  ^ missing closing parenthesis 
+ --> command-option:1
+ | :create-search-table search_test1 bad( 
+ = help: :create-search-table table-name [pattern]
+ ══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
diff --git a/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.out b/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_2532083f215ed44630621f18df3dd7b77c06ae10.out
diff --git a/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.err b/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.err
new file mode 100644
index 0000000..b5fba56
--- /dev/null
+++ b/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.err
@@ -0,0 +1,6 @@
+✘ error: Cannot generate spectrogram for database results
+ reason: No “log_time” column found in the result set
+ --> command-option:2
+ | :spectrogram sc_bytes 
+ = note: An ascending “log_time” column is needed to render a spectrogram
+ = help: Include a “log_time” column in your statement. Use an AS directive to alias a computed timestamp
diff --git a/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.out b/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_26c0d94d7837792144f2d0f866fb3c12a0bd410d.out
diff --git a/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.err b/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.err
new file mode 100644
index 0000000..cf33b67
--- /dev/null
+++ b/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: not authorized
+ --> command-option:1
+ | attach database '/tmp/memdb' as 'db' 
diff --git a/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.out b/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_2959f0c70fca61a07c6c772f193e73022f7794f1.out
diff --git a/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err
new file mode 100644
index 0000000..bc74c2d
--- /dev/null
+++ b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.err
@@ -0,0 +1,4 @@
+✘ error: call to raise_error(msg) failed
+ reason: oops!
+ --> command-option:1
+ | ;SELECT raise_error('oops!') 
diff --git a/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.out b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_2a16a6fd0ff235a7877e1ea93b22d873a3609402.out
diff --git a/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.err b/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.err
new file mode 100644
index 0000000..f68fcf0
--- /dev/null
+++ b/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: not authorized
+ --> command-option:1
+ | attach database 'simple-db.db' as 'db' 
diff --git a/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.out b/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_2cc8a92c6eb73741080b187a2670d309b8171c90.out
diff --git a/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.err b/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.err
diff --git a/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.out b/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.out
new file mode 100644
index 0000000..df0e6d7
--- /dev/null
+++ b/test/expected/test_sql.sh_2f15b8a38673ac4db45dc6ed2eafe609c332575b.out
@@ -0,0 +1,3 @@
+id first_name last_name age 
+ 0 Phil  Myman   30 
+ 1 Lem  Hewitt   35
diff --git a/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.err b/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.err
diff --git a/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.out b/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.out
new file mode 100644
index 0000000..5118721
--- /dev/null
+++ b/test/expected/test_sql.sh_31df37f254255115611fc321b63374a2fa4a1cd5.out
@@ -0,0 +1,2 @@
+ replicate('foobar', 120) 
+foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar⋯oobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar
diff --git a/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.err b/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.err
new file mode 100644
index 0000000..73441f1
--- /dev/null
+++ b/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: not authorized
+ --> command-option:1
+ | attach database ':memdb:' as 'db' 
diff --git a/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.out b/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_3d77a2092192caf98e141a6039e886ede836f044.out
diff --git a/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.err b/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.err
new file mode 100644
index 0000000..57d160d
--- /dev/null
+++ b/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.err
@@ -0,0 +1,5 @@
+✘ error: Cannot generate spectrogram for database results
+ reason: unknown column -- “sc_byes”
+ --> command-option:2
+ | :spectrogram sc_byes 
+ = help: Expecting a numeric column to visualize
diff --git a/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.out b/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_4090f96ea11a344c1e2939211da778992dab47d8.out
diff --git a/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err
new file mode 100644
index 0000000..0c1c059
--- /dev/null
+++ b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: A non-empty name and value must be provided when inserting an environment variable
+ --> command-option:1
+ | ;INSERT INTO environ (name) VALUES (null)
diff --git a/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.out b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_4629b626c65a85d7a5595571e195b67afca272ba.out
diff --git a/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err
new file mode 100644
index 0000000..89f156f
--- /dev/null
+++ b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: An environment variable with the name 'SQL_ENV_VALUE' already exists
+ --> command-option:1
+ | ;INSERT INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar")
diff --git a/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.out b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_50c0b2c93b646b848a017764bde8a4282c556e2d.out
diff --git a/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err
new file mode 100644
index 0000000..b15f6ce
--- /dev/null
+++ b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Environment variable names cannot contain an equals sign (=)
+ --> command-option:1
+ | ;INSERT INTO environ (name, value) VALUES ("foo=bar", "bar")
diff --git a/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.out b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_528e48a03cdfa7cfbe263a6e22a65606247a8a95.out
diff --git a/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.err b/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.err
diff --git a/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.out b/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.out
new file mode 100644
index 0000000..dbb2a2f
--- /dev/null
+++ b/test/expected/test_sql.sh_5532c7a21e3f6b7df3aad10d7bdfbb7a812ae6c7.out
@@ -0,0 +1,2 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,log_hostname,log_msgid,log_pid,log_pri,log_procname,log_struct,log_syslog_tag,syslog_version,col_0,TTY,PWD,USER,COMMAND
+0,<NULL>,2007-11-03 09:47:02.000,0,info,0,<NULL>,<NULL>,[1],veridian,<NULL>,<NULL>,<NULL>,sudo,<NULL>,sudo,<NULL>,timstack,pts/6,/auto/wstimstack/rpms/lbuild/test,root,/usr/bin/tail /var/log/messages
diff --git a/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.err b/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.err
diff --git a/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.out b/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.out
new file mode 100644
index 0000000..fdb6294
--- /dev/null
+++ b/test/expected/test_sql.sh_56047c9470e515bc3e3709354c01e5d50462cde7.out
@@ -0,0 +1,2 @@
+log_top_line() 
+ <NULL>
diff --git a/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.err b/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.err
new file mode 100644
index 0000000..7c11869
--- /dev/null
+++ b/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.err
@@ -0,0 +1,5 @@
+✘ error: Cannot generate spectrogram for database results
+ reason: “c_ip” is not a numeric column
+ --> command-option:2
+ | :spectrogram c_ip 
+ = help: Only numeric columns can be visualized
diff --git a/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.out b/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_57427f3c4b4ec785ffff7c5802c10db0d3e547cf.out
diff --git a/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err
new file mode 100644
index 0000000..600e19d
--- /dev/null
+++ b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.err
@@ -0,0 +1,7 @@
+✘ error: call to raise_error(msg) failed
+ reason: no data was redirected to lnav's standard-input
+ --> command-option:1
+ | |rename-stdin foo 
+ --> ../test/.lnav/formats/default/rename-stdin.lnav:7
+ | ;SELECT raise_error('no data was redirected to lnav''s standard-input') 
+ |  WHERE (SELECT count(1) FROM lnav_file WHERE filepath='stdin') = 0
diff --git a/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.out b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_57edc93426e6767aa44ab2356c55327553dcdc8d.out
diff --git a/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err
new file mode 100644
index 0000000..3ced6be
--- /dev/null
+++ b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: A non-empty name and value must be provided when inserting an environment variable
+ --> command-option:1
+ | ;INSERT INTO environ (name, value) VALUES (null, null)
diff --git a/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.out b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_5801770f3e0ecc1d62c7a97116d6da1981bbc7bd.out
diff --git a/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.err b/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.err
new file mode 100644
index 0000000..dfe4674
--- /dev/null
+++ b/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.err
@@ -0,0 +1,5 @@
+✘ error: invalid SQL statement
+ reason: using a question-mark (?) for bound variables is not supported, only named bound parameters are supported
+ --> command-option:1
+ | ;SELECT 1 = ? 
+ = help: named parameters start with a dollar-sign ($) or colon (:) followed by the variable name
diff --git a/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.out b/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_5fe26fe4fc22f23f8dbe3a6aab394602886f2971.out
diff --git a/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.err b/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.err
diff --git a/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.out b/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.out
new file mode 100644
index 0000000..898c9a8
--- /dev/null
+++ b/test/expected/test_sql.sh_62eb85c9569e71a630d72065238559528a16114c.out
@@ -0,0 +1,2 @@
+filepath 
+foo
diff --git a/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err
new file mode 100644
index 0000000..cdb2140
--- /dev/null
+++ b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.err
@@ -0,0 +1,6 @@
+✘ error: unable to read script file: nonexistent-file -- No such file or directory
+ --> command-option:1
+ | ;.read nonexistent-file 
+ = help: ;.read path
+ ══════════════════════════════════════════════════════════════════════
+ Execute the SQLite statements in the given file
diff --git a/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.out b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_6ad9d0adf85c36363f6b24f49950dcdc13dd34ab.out
diff --git a/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.err b/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.err
new file mode 100644
index 0000000..f031c59
--- /dev/null
+++ b/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.err
@@ -0,0 +1,6 @@
+✘ error: unknown search table -- search_test1
+ --> command-option:1
+ | :delete-search-table search_test1 
+ = help: :delete-search-table table-name
+ ══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
diff --git a/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.out b/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_6edb0c8d5323d1b962d90dd6ecdd7eee9008d7b5.out
diff --git a/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.err b/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.err
diff --git a/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.out b/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.out
new file mode 100644
index 0000000..801a9af
--- /dev/null
+++ b/test/expected/test_sql.sh_753c343a256d1286750314957d1b4e155464e03e.out
@@ -0,0 +1,2 @@
+log_top_datetime() 
+ <NULL>
diff --git a/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.err b/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.err
diff --git a/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.out b/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.out
new file mode 100644
index 0000000..fabc853
--- /dev/null
+++ b/test/expected/test_sql.sh_764306f0e5f610ba71f521ba3d19fe158ece0ba5.out
@@ -0,0 +1,2 @@
+ col_0 
+eth0.IPv4
diff --git a/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err
new file mode 100644
index 0000000..1a0c2b0
--- /dev/null
+++ b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.err
@@ -0,0 +1,6 @@
+✘ error: call to raise_error(msg) failed
+ reason: expecting the new name for stdin as the first argument
+ --> command-option:1
+ | |rename-stdin 
+ --> ../test/.lnav/formats/default/rename-stdin.lnav:6
+ | ;SELECT raise_error('expecting the new name for stdin as the first argument') WHERE $1 IS NULL
diff --git a/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.out b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_7f664c9cda0ae1c48333e21051b5e0eeafd5b4bc.out
diff --git a/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.err b/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.err
diff --git a/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.out b/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.out
new file mode 100644
index 0000000..97b8dcc
--- /dev/null
+++ b/test/expected/test_sql.sh_85fe3b9803254ea54b864d4865d7bd4d7a7f86c6.out
@@ -0,0 +1,4 @@
+192.168.202.254 - - [20/Jul/2009:23:00:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:23:00:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:23:00:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+10.112.81.15 - - [15/Feb/2013:06:01:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.err b/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.err
diff --git a/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.out b/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.out
new file mode 100644
index 0000000..b21f574
--- /dev/null
+++ b/test/expected/test_sql.sh_8ee288f1508eaab0367e465e9f382e848f3282aa.out
@@ -0,0 +1,4 @@
+ log_time 
+2009-07-20 22:59:26.000
+2009-07-20 22:59:29.000
+2009-07-20 22:59:29.000
diff --git a/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.err b/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.err
new file mode 100644
index 0000000..d291abe
--- /dev/null
+++ b/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.err
@@ -0,0 +1,6 @@
+✘ error: unknown search table -- search_test1
+ --> command-option:2
+ | :delete-search-table search_test1 
+ = help: :delete-search-table table-name
+ ══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
diff --git a/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.out b/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_9a209f3ee1b1f543ca2587b695d2eb0e63e74c51.out
diff --git a/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.err b/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.err
diff --git a/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.out b/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.out
new file mode 100644
index 0000000..f648fc6
--- /dev/null
+++ b/test/expected/test_sql.sh_9b03e9f7a1bc35e408b3a17ee90cfdadea164df6.out
@@ -0,0 +1,4 @@
+Min: 0   1-23   24-48   49+ Max: 291690
+ Thu Nov 03 00:15:00               
+▲ 70 values in the range 0.00-3788.18
+ Thu Nov 03 00:20:00
diff --git a/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.err b/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.err
new file mode 100644
index 0000000..3129cfa
--- /dev/null
+++ b/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.err
@@ -0,0 +1,6 @@
+✘ error: Cannot generate spectrogram for database results
+ reason: The “log_time” column is not in ascending order between rows 1 and 2
+ --> command-option:2
+ | :spectrogram sc_bytes 
+ = note: An ascending “log_time” column is needed to render a spectrogram
+ = help: Add an “ORDER BY log_time ASC” clause to your SELECT statement
diff --git a/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out b/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out
diff --git a/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err
new file mode 100644
index 0000000..d3d1a0a
--- /dev/null
+++ b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: real file paths cannot be updated, only symbolic ones
+ --> command-option:1
+ | ;UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0')
diff --git a/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out
diff --git a/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err
new file mode 100644
index 0000000..8dd63fa
--- /dev/null
+++ b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: attempt to write a readonly database
+ --> command-option:1
+ | ;delete from access_log 
diff --git a/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out
diff --git a/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.err b/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.err
diff --git a/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.out b/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.out
new file mode 100644
index 0000000..c012bd8
--- /dev/null
+++ b/test/expected/test_sql.sh_ae7b1f1684e14bf9c16e0d789257b6ef57cfb2b1.out
@@ -0,0 +1,2 @@
+ log_time 
+2009-07-20 22:59:26.000
diff --git a/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.err b/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.err
diff --git a/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.out b/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.out
new file mode 100644
index 0000000..4382802
--- /dev/null
+++ b/test/expected/test_sql.sh_afe9cdc4898df5c4e112c13dfe3db6dc089c0d7c.out
@@ -0,0 +1,4 @@
+ log_body 
+lookup(file): lookup for foobar failed
+attempting to mount entry /auto/opt
+lookup(file): lookup for opt failed
diff --git a/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.err b/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.err
diff --git a/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.out b/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.out
new file mode 100644
index 0000000..b21f574
--- /dev/null
+++ b/test/expected/test_sql.sh_b085d26043f9661d70f82cb90ecb3c5245d25eac.out
@@ -0,0 +1,4 @@
+ log_time 
+2009-07-20 22:59:26.000
+2009-07-20 22:59:29.000
+2009-07-20 22:59:29.000
diff --git a/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.err b/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.err
new file mode 100644
index 0000000..fe7b342
--- /dev/null
+++ b/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: the start parameter is required
+ --> command-option:1
+ | SELECT * FROM generate_series() 
diff --git a/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.out b/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_b2694e4fbecdd128798af25ee0d069e7e35fb499.out
diff --git a/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.err b/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.err
diff --git a/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.out b/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.out
new file mode 100644
index 0000000..c2c44ad
--- /dev/null
+++ b/test/expected/test_sql.sh_b5aa0561a65de7e8e22085db184c72a94b1a89a9.out
@@ -0,0 +1,2 @@
+ log_body 
+timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.err b/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.err
diff --git a/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.out b/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.out
new file mode 100644
index 0000000..85a1303
--- /dev/null
+++ b/test/expected/test_sql.sh_bad03a996c0750733ab99c592b9011851f521a69.out
@@ -0,0 +1,5 @@
+match_index  content  case match_index when 2 then replicate('abc', 1000) else '' end 
+  0 {"col_0":10}  
+ 1 {"col_0":50}  
+ 2 {"col_0":50} abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc⋯bcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc 
+ 3 {"col_0":50}  
diff --git a/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.err b/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.err
diff --git a/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.out b/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.out
new file mode 100644
index 0000000..7041f45
--- /dev/null
+++ b/test/expected/test_sql.sh_bd46ca4560f8be6307a914e39539bbac0368080a.out
@@ -0,0 +1,2 @@
+lnav_top_file() 
+ <NULL>
diff --git a/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err
new file mode 100644
index 0000000..da8dff5
--- /dev/null
+++ b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: A non-empty name and value must be provided when inserting an environment variable
+ --> command-option:1
+ | ;INSERT INTO environ (name, value) VALUES ("", null)
diff --git a/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.out b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_c20b0320096342c180146a5d18a6de82319d70b2.out
diff --git a/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.err b/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.err
diff --git a/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.out b/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.out
new file mode 100644
index 0000000..b21f574
--- /dev/null
+++ b/test/expected/test_sql.sh_c353ef036c505b75996252138fbd4c8d22e8149c.out
@@ -0,0 +1,4 @@
+ log_time 
+2009-07-20 22:59:26.000
+2009-07-20 22:59:29.000
+2009-07-20 22:59:29.000
diff --git a/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.err b/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.err
diff --git a/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.out b/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.out
new file mode 100644
index 0000000..86a4d5a
--- /dev/null
+++ b/test/expected/test_sql.sh_c5b8da04734fadf3b9eea80e0af997e38e0fb811.out
@@ -0,0 +1,3 @@
+log_line  col_0 
+ 0 eth0.IPv4 
+ 7 eth0.IPv4
diff --git a/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.err b/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.err
new file mode 100644
index 0000000..8ab7471
--- /dev/null
+++ b/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.err
@@ -0,0 +1,4 @@
+✘ error: failed to compile SQL statement
+ reason: not authorized
+ --> command-option:1
+ | attach database 'file:memdb?cache=shared' as 'db'
diff --git a/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.out b/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_c73dec2706fc0b9a124f5da3a83f40d8d3255beb.out
diff --git a/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.err b/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.err
diff --git a/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.out b/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.out
new file mode 100644
index 0000000..762b09c
--- /dev/null
+++ b/test/expected/test_sql.sh_c7e1dbf4605914720b55787785abfafdf2c4178a.out
@@ -0,0 +1,2 @@
+ log_top_datetime() 
+2016-03-13 22:49:15.000
diff --git a/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.err b/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.err
diff --git a/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.out b/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.out
new file mode 100644
index 0000000..b13e5f0
--- /dev/null
+++ b/test/expected/test_sql.sh_cc77a633a66d1778705a34e3657737547b3fb08d.out
@@ -0,0 +1,2 @@
+log_top_line() 
+ 2
diff --git a/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.err b/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.err
new file mode 100644
index 0000000..c7ee159
--- /dev/null
+++ b/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.err
@@ -0,0 +1,10 @@
+✘ error: call to raise_error(msg) failed
+ reason: oops!
+ --> command-option:2
+ | ;SELECT $inum, $nul, $fnum, $str, raise_error('oops!')
+ = note: the bound parameters are set as follows:
+ $fnum:FLOAT = “2”
+ $inum:INTEGER = “1”
+ $nul:NULL = “<NULL>”
+ $str:TEXT = “abc”
+
diff --git a/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.out b/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_dd540973a0dc86320d84706845a15608196ae5be.out
diff --git a/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.err b/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.err
diff --git a/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.out b/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.out
new file mode 100644
index 0000000..889aced
--- /dev/null
+++ b/test/expected/test_sql.sh_e70dc7d2b686c7f91c2b41b10f3920c50f3ea405.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.err b/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.err
diff --git a/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.out b/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.out
new file mode 100644
index 0000000..a4a70f3
--- /dev/null
+++ b/test/expected/test_sql.sh_ff8a978fc0de0fed675a3cd1454cf435a6856fd5.out
@@ -0,0 +1,3 @@
+134
+46210
+78929
diff --git a/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.err b/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.err
diff --git a/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.out b/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.out
new file mode 100644
index 0000000..8adbd5c
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_028d5d5af2f3519b59d349d41cb7ecf385253b51.out
@@ -0,0 +1,5 @@
+ SELECT * FROM FOO
+ sql_keyword ------
+ sql_oper -
+ sql_keyword ----
+ sql_ident ---
diff --git a/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.err b/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.err
diff --git a/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.out b/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.out
new file mode 100644
index 0000000..0e8b3dd
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_0a37c43350ddd7a2d0d75695be32fac083ad04a4.out
@@ -0,0 +1,4 @@
+ CREATE
+ sql_keyword ------
+CREATE: Assign a name to a SELECT statement
+CREATE: Create a table
diff --git a/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.err b/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.err
diff --git a/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.out b/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.out
new file mode 100644
index 0000000..d8f654e
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_1151e5b727f6b57070bf2c8f047f1d7e02b803a6.out
@@ -0,0 +1,6 @@
+ SELECT lower(abc
+ sql_keyword ------
+ sql_func ---------
+ sql_ident -----
+ sql_ident ---
+lower: Returns a copy of the given string with all ASCII characters converted to lower case.
diff --git a/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.err b/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.err
diff --git a/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out b/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out
new file mode 100644
index 0000000..c9237a8
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_1b29488b949c294479aa6054f80a35bc106b454b.out
@@ -0,0 +1,2 @@
+ TABLE
+ sql_keyword -----
diff --git a/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err b/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.err
diff --git a/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out b/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out
new file mode 100644
index 0000000..b7bee8a
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_331a152080d2e278b7cc0a37728eca1ded36ed72.out
@@ -0,0 +1,5 @@
+ SELECT 'hello, world!' FROM "my table"
+ sql_keyword ------
+ sql_string ---------------
+ sql_keyword ----
+ sql_ident ----------
diff --git a/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.err
diff --git a/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out
new file mode 100644
index 0000000..9498d4b
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_4ca92f0da538c2f9d524211a021b306af0d2740d.out
@@ -0,0 +1,7 @@
+ SELECT * FROM foo.bar
+ sql_keyword ------
+ sql_oper -
+ sql_keyword ----
+ sql_ident ---
+ sql_garbage -
+ sql_ident ---
diff --git a/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err b/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.err
diff --git a/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out b/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out
new file mode 100644
index 0000000..8433625
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_73814eca259e469b57bf7469787b91e8e8569b17.out
@@ -0,0 +1,7 @@
+ SELECT (1 + 2) AS three
+ sql_keyword ------
+ sql_number -
+ sql_oper -
+ sql_number -
+ sql_keyword --
+ sql_ident -----
diff --git a/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err b/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.err
diff --git a/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.out b/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.out
new file mode 100644
index 0000000..00a2e8a
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_74bc5fb90a0c94a1a37d30a8e9254ea02c192a75.out
@@ -0,0 +1,6 @@
+ SELECT lower(abc)
+ sql_keyword ------
+ sql_func ---------
+ sql_ident -----
+ sql_ident ---
+SELECT: Query the database and return zero or more rows of data.
diff --git a/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.err b/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.err
diff --git a/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.out b/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.out
new file mode 100644
index 0000000..7c92ed1
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_7b183037479528581e1eacace7b9acae41c5aa8e.out
@@ -0,0 +1,12 @@
+ SELECT instr(lower(abc), '123') FROM bar
+ sql_keyword ------
+ sql_func -----------------------
+ sql_ident -----
+ sql_func ---------
+ sql_ident -----
+ sql_ident ---
+ sql_comma -
+ sql_string -----
+ sql_keyword ----
+ sql_ident ---
+SELECT: Query the database and return zero or more rows of data.
diff --git a/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.err b/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.err
diff --git a/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.out b/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.out
new file mode 100644
index 0000000..dc88535
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_96ebdc277ae760e1b6efae3195ff678654b04e52.out
@@ -0,0 +1,7 @@
+ SELECT foo(bar())
+ sql_keyword ------
+ sql_func ---------
+ sql_ident ---
+ sql_func ----
+ sql_ident ---
+SELECT: Query the database and return zero or more rows of data.
diff --git a/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.err b/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.err
diff --git a/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.out b/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.out
new file mode 100644
index 0000000..5fa2f87
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_99da5994c8c90536dbdb1b8ad7dbfb41698a5e8c.out
@@ -0,0 +1,10 @@
+ SELECT instr(lower(abc), '123')
+ sql_keyword ------
+ sql_func -----------------------
+ sql_ident -----
+ sql_func ---------
+ sql_ident -----
+ sql_ident ---
+ sql_comma -
+ sql_string -----
+lower: Returns a copy of the given string with all ASCII characters converted to lower case.
diff --git a/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.err b/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.err
diff --git a/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.out b/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.out
new file mode 100644
index 0000000..fc6d386
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_b1a2ddce48beb3e4b1e3ca4b4229a7c21b83b7c4.out
@@ -0,0 +1,6 @@
+ SELECT lower( abc )
+ sql_keyword ------
+ sql_func ----------------
+ sql_ident -----
+ sql_ident ---
+lower: Returns a copy of the given string with all ASCII characters converted to lower case.
diff --git a/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.err b/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.err
diff --git a/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.out b/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.out
new file mode 100644
index 0000000..902a1db
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_be6839712d088fc7b31618ed90f8ce706c35a9c0.out
@@ -0,0 +1,7 @@
+ SELECT (1.5 + 2.2) AS decim
+ sql_keyword ------
+ sql_number ---
+ sql_oper -
+ sql_number ---
+ sql_keyword --
+ sql_ident -----
diff --git a/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.err b/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.err
diff --git a/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.out b/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.out
new file mode 100644
index 0000000..c09afc3
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_c879ba94fdc1a099cf56bd33e5b3e9be65310036.out
@@ -0,0 +1,10 @@
+ SELECT instr(lower(abc), '123')
+ sql_keyword ------
+ sql_func -----------------------
+ sql_ident -----
+ sql_func ---------
+ sql_ident -----
+ sql_ident ---
+ sql_comma -
+ sql_string -----
+instr: Finds the first occurrence of the needle within the haystack and returns the number of prior characters plus 1, or 0 if the needle was not found
diff --git a/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.err b/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.err
diff --git a/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.out b/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.out
new file mode 100644
index 0000000..304d8dc
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_c909647ed0e585002074f55c946f3033df1815b2.out
@@ -0,0 +1,6 @@
+ SELECT foo(bar())
+ sql_keyword ------
+ sql_func ---------
+ sql_ident ---
+ sql_func ----
+ sql_ident ---
diff --git a/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.err b/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.err
diff --git a/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.out b/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.out
new file mode 100644
index 0000000..654e434
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_ce0506ee7a12eb0f7b970522cc6a79180ecb20cc.out
@@ -0,0 +1,11 @@
+ SELECT * from vmw_log, regexp_capture(log_body, '--> /SessionStats/SessionPool/Session/(?<line>[abc]+)')
+ sql_keyword ------
+ sql_oper -
+ sql_keyword ----
+ sql_ident -------
+ sql_comma -
+ sql_func --------------------------------------------------------------------------------
+ sql_ident --------------
+ sql_ident --------
+ sql_comma -
+ sql_string -------------------------------------------------------
diff --git a/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.err b/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.err
diff --git a/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.out b/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.out
new file mode 100644
index 0000000..2ee5ee2
--- /dev/null
+++ b/test/expected/test_sql_anno.sh_f3c64191d6016767a5857fbb1bad26548586bb96.out
@@ -0,0 +1,10 @@
+ SELECT * FROM (SELECT foo, bar FROM baz)
+ sql_keyword ------
+ sql_oper -
+ sql_keyword ----
+ sql_keyword ------
+ sql_ident ---
+ sql_comma -
+ sql_ident ---
+ sql_keyword ----
+ sql_ident ---
diff --git a/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.err b/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.err
diff --git a/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.out b/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.out
new file mode 100644
index 0000000..36b0c2b
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_077cab6e271c914daf5b221cc512853077891f35.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'fe80::a85f:80b4:5cbe:8691' = 'fe80:0000:0000:0000:a85f:80b4:5cbe:8691' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.err b/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.err
diff --git a/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.out b/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.out
new file mode 100644
index 0000000..cf84c47
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_0ce56741d3c34af274c8ddb4b90c4e5749d05971.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'info' collate loglevel between 'trace' and 'fatal': 1
diff --git a/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.err b/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.err
diff --git a/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.out b/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.out
new file mode 100644
index 0000000..187dc99
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_180ad44fe073cc9642da642af1f442adfd98ec62.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'file10.txt' < 'file2.txt' collate naturalcase: 0
diff --git a/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.err b/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.err
diff --git a/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.out b/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.out
new file mode 100644
index 0000000..4ecbd26
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_2230714a0b2ab6aca9ddfe686734f313cef5a96b.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '::ffff:192.168.1.10' = '192.168.1.10' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.err b/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.err
diff --git a/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.out b/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.out
new file mode 100644
index 0000000..4bac183
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_68515cfd0a50880f6dfc8f9810c9e761493ebb12.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '192.168.1.10' < '192.168.1.2' collate ipaddress: 0
diff --git a/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.err b/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.err
diff --git a/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.out b/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.out
new file mode 100644
index 0000000..90b4acb
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_6de2a86c53883ec4430b98edd06b0c0cdf23e741.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '192.168.1.10' < '192.168.1.2': 1
diff --git a/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.err b/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.err
diff --git a/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.out b/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.out
new file mode 100644
index 0000000..2f6aec0
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_918178c6dd9d70d0432ededfde5af5e53c094385.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '192.168.1.10' < '192.168.1.12' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.err b/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.err
diff --git a/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.out b/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.out
new file mode 100644
index 0000000..913c6b3
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_c76a24a209987e4c668c87588c12b8f34294b144.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '' < '192.168.1.2' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.err b/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.err
diff --git a/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.out b/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.out
new file mode 100644
index 0000000..2718d82
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_cacb045d2bce6dc298c4da3d96bdc34dab2404df.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'file10.txt' < 'file2.txt': 1
diff --git a/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.err b/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.err
diff --git a/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.out b/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.out
new file mode 100644
index 0000000..5b48b4e
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_cae4bc239c924bbc05a0b099b63f0e3af7560976.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'w' < 'e' collate loglevel: 1
diff --git a/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.err b/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.err
diff --git a/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.out b/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.out
new file mode 100644
index 0000000..bcfa7cb
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_d4e3c9f7a38458726900731d2b71c104d591ef14.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'h9.example.com' < 'h10.example.com' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.err b/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.err
diff --git a/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.out b/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.out
new file mode 100644
index 0000000..945e0ee
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_d5c8f7ab91c3dbe46add7e08f532b17797d9975c.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '192.168.1.2' > '' collate ipaddress: 1
diff --git a/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.err b/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.err
diff --git a/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.out b/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.out
new file mode 100644
index 0000000..d6a7338
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_eb2c424733ce978d1b6d1dcb93d6e45af7c8fa96.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column 'e' < 'w' collate loglevel: 0
diff --git a/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.err b/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.err
diff --git a/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.out b/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.out
new file mode 100644
index 0000000..fc31b19
--- /dev/null
+++ b/test/expected/test_sql_coll_func.sh_f045e94d921bfcfbded83ee681bf11445a99ff6d.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column '192.168.1.2' < 'fe80::a85f:80b4:5cbe:8691' collate ipaddress: 1
diff --git a/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.err b/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.err
diff --git a/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.out b/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.out
new file mode 100644
index 0000000..b95b567
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_109ff42de817b56a9082f605f63af71c0db8c9d7.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column joinpath(): (null)
diff --git a/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.err b/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.err
diff --git a/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.out b/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.out
new file mode 100644
index 0000000..cf84c59
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_17b09f79bfcac1762153ec9650fb1e545a24d8a3.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('/'): /
diff --git a/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.err b/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.err
diff --git a/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.out b/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.out
new file mode 100644
index 0000000..7271fd2
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_18ddc138b263dd06f3fe81fec05bc4330caffef7.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('/foo'): foo
diff --git a/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.err b/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.err
diff --git a/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.out b/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.out
new file mode 100644
index 0000000..bace683
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_20a76db446a0a558dcbdf41033f97d4a22ca1bfa.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('foo'): .
diff --git a/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.err b/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.err
diff --git a/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.out b/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.out
new file mode 100644
index 0000000..983fcf5
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_2c3f66e78deb8721b1d1fe5a787e9958895401d7.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('/foo//'): /
diff --git a/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.err b/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.err
diff --git a/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.out b/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.out
new file mode 100644
index 0000000..77491a9
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_3ed11101a413e47c3dfe219557b7a6df04a64253.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('foo//'): .
diff --git a/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.err b/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.err
diff --git a/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.out b/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.out
new file mode 100644
index 0000000..6e4accc
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_469380561dccd79c7249562067107c330838eaad.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname(''): .
diff --git a/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.err b/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.err
diff --git a/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.out b/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.out
new file mode 100644
index 0000000..a2f9057
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_54b004f301907860d360434b37fd6c81fcc12f99.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('foo'): foo
diff --git a/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.err b/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.err
diff --git a/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.out b/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.out
new file mode 100644
index 0000000..49e73dc
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_73df81c6889d1f06fb3f3b6bf30c6046b3f52c8b.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column joinpath('foo', 'bar', 'baz', '/root'): /root
diff --git a/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.err b/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.err
diff --git a/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.out b/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.out
new file mode 100644
index 0000000..8a5ccfc
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_74ca242a126316bcb82ccefd9369f9e43b7fd2e1.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column joinpath('foo'): foo
diff --git a/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.err b/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.err
diff --git a/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.out b/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.out
new file mode 100644
index 0000000..b6bb6f9
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_7b116cb0ab7a28b866e0d2b80fe8ef0cd25f2aa3.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('/'): /
diff --git a/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.err b/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.err
diff --git a/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.out b/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.out
new file mode 100644
index 0000000..fcf9b4c
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_7b5d7dd8d0003ab83e3e5cb0a5ce802fe9a0e3b3.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column joinpath('foo', 'bar', 'baz'): foo/bar/baz
diff --git a/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.err b/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.err
diff --git a/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.out b/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.out
new file mode 100644
index 0000000..864b02c
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_917ffde411c1425e8a6addae0170900dcd553986.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('/foo'): /
diff --git a/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.err b/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.err
new file mode 100644
index 0000000..b1d8939
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to readlink(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":46},{"start":17,"end":21,"type":"role","value":45},{"start":8,"end":22,"type":"role","value":59}]},"reason":{"str":"unable to stat path: non-existent-link -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.out b/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_9e2c0a90ce333365ff7354375f2c609bc27135c8.out
diff --git a/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.err b/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.err
diff --git a/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.out b/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.out
new file mode 100644
index 0000000..2f75397
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_a247b137e71124e496f1beab56c7fe85717c4199.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename(''): .
diff --git a/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.err b/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.err
diff --git a/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.out b/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.out
new file mode 100644
index 0000000..71c2d31
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_b66242975fd6ecb7260cd96ac29accaf4f4af6ae.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('foo///'): .
diff --git a/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.err b/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.err
diff --git a/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.out b/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.out
new file mode 100644
index 0000000..cfb2e26
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_c5d78cfbf5594cc27590277353c08a92e2497622.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('/foo/'): foo
diff --git a/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.err b/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.err
diff --git a/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.out b/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.out
new file mode 100644
index 0000000..46a1c9c
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cc402803bf14ee3673089c575f1af87220cb6a72.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('foo/bar'): bar
diff --git a/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.err b/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.err
diff --git a/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.out b/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.out
new file mode 100644
index 0000000..01ff27e
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cf307d87104e99a1858bb7c4f28ea3068340f188.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('/foo///'): foo
diff --git a/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.err b/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.err
new file mode 100644
index 0000000..0316795
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to realpath(path) failed","attrs":[{"start":8,"end":16,"type":"role","value":46},{"start":17,"end":21,"type":"role","value":45},{"start":8,"end":22,"type":"role","value":59}]},"reason":{"str":"Could not get real path for non-existent-path -- No such file or directory","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.out b/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_cf670dfa1ae7ac5a074baa642068c6d26ac8e096.out
diff --git a/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.err b/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.err
diff --git a/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.out b/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.out
new file mode 100644
index 0000000..0d744ab
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_d51ad77cd67a2a691838c9d95142638df1c07360.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column dirname('/foo/bar'): /foo
diff --git a/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.err b/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.err
diff --git a/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.out b/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.out
new file mode 100644
index 0000000..6306be6
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_e24cf3f35643f945392e7d7a4ca82fea98b4519e.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column basename('//'): /
diff --git a/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.err b/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.err
diff --git a/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.out b/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.out
new file mode 100644
index 0000000..00c5d02
--- /dev/null
+++ b/test/expected/test_sql_fs_func.sh_f31f240313ddec806aa6f353ceed707dfd9aaf16.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column readlink('sql_fs_readlink_test.lnk'): sql_fs_readlink_test
diff --git a/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.err b/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.err
diff --git a/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.out b/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_026dd9752b6101e0791689d3a2026f7e517e36f5.out
diff --git a/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.err b/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.err
diff --git a/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.out b/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.out
new file mode 100644
index 0000000..7179021
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_1614ebb5e2e83bab11023354dea8a0885ddf64b4.out
@@ -0,0 +1,3 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters log_msg_format 
+  1  <NULL> 2009-07-20 22:59:29.000  3000 error   0  <NULL>  <NULL>  <NULL>  
+ 3  <NULL> 2013-02-15 06:00:31.000  112777262000 error   0  <NULL>  <NULL>  <NULL>  
diff --git a/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.err b/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.err
diff --git a/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.out b/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.out
new file mode 100644
index 0000000..5467779
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_541a8e35f34a206e340a3880128b6ce137847872.out
@@ -0,0 +1,5 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters  c_ip cs_method cs_referer cs_uri_query  cs_uri_stem cs_user_agent cs_username cs_version sc_bytes sc_status cs_host  log_unique_path 
+  0  <NULL> 2009-07-20 22:59:26.000  0 info   0  <NULL>  <NULL>  <NULL> 192.168.202.254 GET  -   <NULL> /vmw/cgi/tramp  gPXE/0.9.7  -  HTTP/1.0   134  200  <NULL> logfile_access_log.0 
+   1 <NULL> 2009-07-20 22:59:29.000 3000 error 0 <NULL> <NULL> <NULL> 192.168.202.254 GET - <NULL> /vmw/vSphere/default/vmkboot.gz gPXE/0.9.7 - HTTP/1.0 46210 404 <NULL> logfile_access_log.0
+  2  <NULL> 2009-07-20 22:59:29.000  0 info   0  <NULL>  <NULL>  <NULL> 192.168.202.254 GET  -   <NULL> /vmw/vSphere/default/vmkernel.gz gPXE/0.9.7  -  HTTP/1.0   78929  200  <NULL> logfile_access_log.0 
+ 3  <NULL> 2013-02-15 06:00:31.000  112777262000 error   0  <NULL>  <NULL>  <NULL> 10.112.81.15  <NULL>  -   <NULL> <NULL>  -  -  <NULL>   0  400  <NULL> logfile_access_log.1
diff --git a/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.err b/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.err
diff --git a/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.out b/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.out
new file mode 100644
index 0000000..823c4d0
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_59a1497c13a5e09bc8f95ef02552b2835ebea6e5.out
@@ -0,0 +1,2 @@
+$id $parent $notused  replace($detail, 'SCAN TABLE', 'SCAN') 
+ 2  0  0 SCAN all_logs VIRTUAL TABLE INDEX 1:SEARCH all_logs USING log_level < ? 
diff --git a/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.err b/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.err
diff --git a/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.out b/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.out
new file mode 100644
index 0000000..cb2aac6
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_69fd19d56a8cd1fc9c7eb9351270eabb491f8233.out
@@ -0,0 +1,5 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters log_msg_format log_format 
+ 0  <NULL> 2009-07-20 22:59:26.000  0 info   0  <NULL>  <NULL>  <NULL>   access_log 
+  1 <NULL> 2009-07-20 22:59:29.000 3000 error 0 <NULL> <NULL> <NULL> access_log
+ 2  <NULL> 2009-07-20 22:59:29.000  0 info   0  <NULL>  <NULL>  <NULL>   access_log 
+ 3  <NULL> 2013-02-15 06:00:31.000  112777262000 error   0  <NULL>  <NULL>  <NULL>   access_log
diff --git a/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.err b/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.err
diff --git a/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.out b/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.out
new file mode 100644
index 0000000..ee48805
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_6f707b6e856dbaab6f95e7e89b98dc3652021f85.out
@@ -0,0 +1,3 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters log_msg_format 
+ 0  <NULL> 2009-07-20 22:59:26.000  0 info   0  <NULL>  <NULL>  <NULL>  
+ 2 <NULL> 2009-07-20 22:59:29.000 0 info 0 <NULL> <NULL> <NULL>
diff --git a/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.err b/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.err
diff --git a/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.out b/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.out
new file mode 100644
index 0000000..2a91985
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_b615b6737b1e0d383c8ce4a1db56332f11dbc158.out
@@ -0,0 +1,2 @@
+$id $parent $notused  replace($detail, 'SCAN TABLE', 'SCAN') 
+ 2  0  0 SCAN all_logs VIRTUAL TABLE INDEX 1:SEARCH all_logs USING log_format = ? 
diff --git a/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.err b/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.err
diff --git a/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.out b/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.out
new file mode 100644
index 0000000..82958af
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_dab07d8de7728752ae938a174468d75e85f3ae7e.out
@@ -0,0 +1,2 @@
+$id $parent $notused  replace($detail, 'SCAN TABLE', 'SCAN') 
+ 2  0  0 SCAN access_log VIRTUAL TABLE INDEX 1:SEARCH access_log USING log_path GLOB ? 
diff --git a/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.err b/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.err
diff --git a/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.out b/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.out
new file mode 100644
index 0000000..16c7c37
--- /dev/null
+++ b/test/expected/test_sql_indexes.sh_f7681c234d4f60df16c997a05163aeb058c52870.out
@@ -0,0 +1,5 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters log_msg_format 
+ 0  <NULL> 2009-07-20 22:59:26.000  0 info   0  <NULL>  <NULL>  <NULL>  
+  1 <NULL> 2009-07-20 22:59:29.000 3000 error 0 <NULL> <NULL> <NULL>
+ 2  <NULL> 2009-07-20 22:59:29.000  0 info   0  <NULL>  <NULL>  <NULL>  
+ 3  <NULL> 2013-02-15 06:00:31.000  112777262000 error   0  <NULL>  <NULL>  <NULL>  
diff --git a/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.err b/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.err
diff --git a/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.out b/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.out
new file mode 100644
index 0000000..451a2fa
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_017d24148f3e28f719429b709f4aa5478f458443.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40]', '/0'): (null)
diff --git a/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.err b/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.err
new file mode 100644
index 0000000..9654daa
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.err
@@ -0,0 +1,4 @@
+error: sqlite3_exec failed -- parse error: premature EOF
+ [123, true
+ (right here) ------^
+
diff --git a/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.out b/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_026077f4d573ee034467065b7e4f1878bdd4e2f2.out
diff --git a/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.err b/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.err
diff --git a/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.out b/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.out
new file mode 100644
index 0000000..531034e
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_191436b38db80b1dd9e7e0814c31c5fa7239dc51.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column id: 1
+ Column stack: {"key1":10,"key2":20,"key3":30}
diff --git a/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.err b/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.err
diff --git a/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.out b/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.out
new file mode 100644
index 0000000..449f615
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_1a74914cbf12fcd5c06935b992f6355acdbcf2d8.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 4.0]', '/4'): 4.0
diff --git a/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.err b/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.err
diff --git a/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.out b/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.out
new file mode 100644
index 0000000..fb37801
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_1c1a2d438d2bde95abd9a859d113c3661e650a36.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40]', '/0/foo'): (null)
diff --git a/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.err b/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.err
diff --git a/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.out b/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.out
new file mode 100644
index 0000000..4b8f538
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_238417283b8e5db23c992f966e3f106bd178f7d0.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40, {"msg": "Hello"}]', ''): [null,true,20,30,40,{"msg":"Hello"}]
diff --git a/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.err b/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.err
diff --git a/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.out b/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.out
new file mode 100644
index 0000000..dd75a1d
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_32459ba8e8bb9a1d9e63b6c67059d7f065cf4301.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40]', '/abc', 1): 1
diff --git a/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.err b/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.err
diff --git a/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.out b/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.out
new file mode 100644
index 0000000..3d09bd6
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_39c13797278d765c027d3581a0b6e0574f5c56eb.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('4', 4): 1
diff --git a/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.err b/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.err
diff --git a/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.out b/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.out
new file mode 100644
index 0000000..0973745
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_3cf4b66d40c4b1979ff14a9eccad8bd5ac48151c.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column res: 0
diff --git a/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.err b/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.err
diff --git a/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.out b/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.out
new file mode 100644
index 0000000..14f3b8e
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_4192f378e320cb3f2c3c228b63ec65de92044704.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('4', 2): 0
diff --git a/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.err b/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.err
new file mode 100644
index 0000000..73b5594
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Uneven number of arguments to json_group_object(), expecting key and value pairs
diff --git a/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.out b/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_57c3aecdced547b837177ab02d3776361363e48d.out
diff --git a/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.err b/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.err
diff --git a/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.out b/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.out
new file mode 100644
index 0000000..414df03
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_5b4a95677a1fc7d11f4b87d92165f56a60a65828.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_concat(NULL, json('{"abc": 1}')): [{"abc":1}]
diff --git a/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.err b/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.err
new file mode 100644
index 0000000..8bf9a3d
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to json_contains(json, value) failed","attrs":[{"start":8,"end":21,"type":"role","value":46},{"start":22,"end":26,"type":"role","value":45},{"start":28,"end":33,"type":"role","value":45},{"start":8,"end":34,"type":"role","value":59}]},"reason":{"str":"parse error: premature EOF\n [\"hi\", \"bye\", \"solong]\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.out b/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_5f2feef079a51410e1f8661bfe92da1c3277f665.out
diff --git a/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.err b/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.err
diff --git a/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.out b/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.out
new file mode 100644
index 0000000..69e1a5e
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_61417198a652aab93e9495b6e8cf3a634af175c6.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('', 4): 0
diff --git a/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.err b/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.err
diff --git a/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.out b/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.out
new file mode 100644
index 0000000..9a729a8
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_79ab816ac01c9902ddbb0f6f20392ab2f2cd6172.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column id: 1
+ Column stack: {"1":10,"2":[1,2,3],"3":30.5}
diff --git a/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.err b/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.err
diff --git a/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.out b/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.out
new file mode 100644
index 0000000..c70a186
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_7c01aaf09078aaa3f23d127f9e03a317dca066de.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('"hi"', 'hi'): 1
diff --git a/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.err b/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.err
diff --git a/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.out b/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.out
new file mode 100644
index 0000000..57ecd1c
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_80c97b22084a06fd765ad22c935616c578968d07.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40]', '/abc'): (null)
diff --git a/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.err b/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.err
diff --git a/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.out b/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.out
new file mode 100644
index 0000000..375f86a
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_83d8615c9ce5dfab5e4373570c1b68b8608155f5.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('"hi"', 'hi there'): 0
diff --git a/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.err b/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.err
diff --git a/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.out b/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.out
new file mode 100644
index 0000000..3a26b62
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8cae9740ddfd6ba4c865fca0117b7bea3bb556e5.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_concat(json('[null, true, 0]'), 1.0, 2.0): [null,true,0,1.0,2.0]
diff --git a/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.err b/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.err
diff --git a/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.out b/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.out
new file mode 100644
index 0000000..72ded4f
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8e229f1b5fa3d3803e9db2f295a8d1a490e1b3db.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40, {"msg": "Hello"}]', '/5/msg'): Hello
diff --git a/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.err b/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.err
new file mode 100644
index 0000000..da16df8
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- expecting JSON value and pointer
diff --git a/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.out b/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_8e3724c90bf96dff5d8ba3cfaf4b7e2eaa9e5f66.out
diff --git a/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.err b/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.err
diff --git a/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.out b/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.out
new file mode 100644
index 0000000..67ca681
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_93ba3ba52b0dd2d5a3ba43bcb7c3638c05ecfe75.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40]', '/3'): 30
diff --git a/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.err b/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.err
diff --git a/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.out b/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.out
new file mode 100644
index 0000000..df74174
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_97aa53b581838f5875fe2beda8d1cb245a24f3d6.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_concat(NULL, NULL): [null]
diff --git a/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.err b/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.err
diff --git a/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.out b/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.out
new file mode 100644
index 0000000..6f7f8d0
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_98a83bc899a78c04d1fdb390b2c1e403c35428c7.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column res: 1
diff --git a/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.err b/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.err
diff --git a/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.out b/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.out
new file mode 100644
index 0000000..f6f983c
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_98ce02dff32d955466524bb167fa45fdf8591788.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains(NULL, 4): 0
diff --git a/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.err b/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.err
diff --git a/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.out b/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.out
new file mode 100644
index 0000000..7019ce5
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9ab4f51486d7cc99c584721bf0e50c223dac4f18.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column typeof(jget('[null, true, 20, 30, 40]', '/3')): integer
diff --git a/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.err b/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.err
diff --git a/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.out b/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.out
new file mode 100644
index 0000000..1c9c316
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9d260ed24b28579ef1dbed25b10c42741e52b023.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_group_array(column1): []
diff --git a/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.err b/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.err
diff --git a/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.out b/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.out
new file mode 100644
index 0000000..776dfd6
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_9fbfe3c93467666c45b643f3b8ba990a294c17ff.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('4', null): 4
diff --git a/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.err b/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.err
diff --git a/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.out b/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.out
new file mode 100644
index 0000000..931d5dc
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_a4ffc64f89cf9917fbc918227fd3c05e54d9e8b5.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('[[0]]', 0): 0
diff --git a/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.err b/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.err
diff --git a/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.out b/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.out
new file mode 100644
index 0000000..f150fde
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_a5e179607645aefce14b9fd12ddef34107afe337.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column stack: [10,null,"hello"]
diff --git a/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.err b/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.err
diff --git a/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.out b/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.out
new file mode 100644
index 0000000..68ffe43
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_b2fc37822e29f7f59497a02a8968c680b545ee1d.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_concat(json('["tag0"]'), 'tag1', 'tag2'): ["tag0","tag1","tag2"]
diff --git a/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.err b/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.err
diff --git a/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.out b/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.out
new file mode 100644
index 0000000..e2c7330
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_bbd979ed74b46ae1696ed7312a48a436bcf99ec0.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('[null, true, 20, 30, 40, {"msg": "Hello"}]', '/5'): {"msg":"Hello"}
diff --git a/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.err b/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.err
diff --git a/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.out b/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.out
new file mode 100644
index 0000000..ae0858b
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_c1ae603d969a5b106328287523c0ddfed07146ad.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column json_contains('null', NULL): 1
diff --git a/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.err b/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.err
new file mode 100644
index 0000000..f8e3d64
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to json_concat(json, value, ...) failed","attrs":[{"start":8,"end":19,"type":"role","value":46},{"start":20,"end":24,"type":"role","value":45},{"start":26,"end":31,"type":"role","value":45},{"start":8,"end":37,"type":"role","value":59}]},"reason":{"str":"Invalid JSON: parse error: premature EOF\n [null,\n (right here) ------^","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.out b/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_e0ab80f50fb008700ab6cfb90694ed014d40e44b.out
diff --git a/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.err b/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.err
diff --git a/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.out b/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.out
new file mode 100644
index 0000000..e187559
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_ebafb98307f307ae8d8ab6921c32929aab3a1a16.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column typeof(jget('[null, true, 20, 30, 4.0]', '/4')): real
diff --git a/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.err b/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.err
diff --git a/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.out b/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.out
new file mode 100644
index 0000000..4cdd719
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_ee36fbea10a33ca106a211feb05d61ecf8e74634.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column jget('4', ''): 4
diff --git a/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.err b/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.err
diff --git a/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.out b/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.out
new file mode 100644
index 0000000..5e3bd8b
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f1cbc70771cc75520f807261eac3a88dc2d8fe6b.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column stack: [10,100,20,200,30,300]
diff --git a/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.err b/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.err
diff --git a/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.out b/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.out
new file mode 100644
index 0000000..95c2d9b
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f34205b59e04f261897ad89f659595c743a18ca9.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column id: 1
+ Column stack: {"1":10,"2":null,"3":30.5}
diff --git a/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.err b/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.err
new file mode 100644
index 0000000..e8eef68
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.err
@@ -0,0 +1,4 @@
+error: sqlite3_exec failed -- parse error: premature EOF
+ [null, true, 20, 30, 40
+ (right here) ------^
+
diff --git a/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out b/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_json_func.sh_f34f5dfa938a1ac7721f924beb16bbceec127a1b.out
diff --git a/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err b/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.err
diff --git a/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out b/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out
new file mode 100644
index 0000000..19aa1c4
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_03257c56e85558aa0cc925b68d3af962afc25125.out
@@ -0,0 +1,4 @@
+match_index capture_index capture_name capture_count range_start range_stop content 
+ 0  0  <NULL>  3  1  9 abc=def; 
+ 0 1 <NULL> 3 1 4 abc
+ 0  2  <NULL>  3  5  8 def 
diff --git a/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err b/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.err
diff --git a/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out b/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out
new file mode 100644
index 0000000..4917183
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_51293df041b6969ccecc60204dce3676d0fb006d.out
@@ -0,0 +1,2 @@
+match_index  content 
+ 0 {"key":"foo","value":4670} 
diff --git a/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err b/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.err
diff --git a/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out b/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out
new file mode 100644
index 0000000..78f05ff
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_b841a0c09601e2419eeb99e85f7e286c889e4801.out
@@ -0,0 +1,27 @@
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,log_hostname,log_msgid,log_pid,log_pri,log_procname,log_struct,log_syslog_tag,syslog_version,match_index,content
+2,<NULL>,2022-08-16 00:32:15.000,199000,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,0,"{""value"":""com.apple.cdscheduler""}"
+2,<NULL>,2022-08-16 00:32:15.000,199000,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,1,"{""value"":"" claims selected messages.\n\tThose messages may not appear in standard system log files or in the ASL database.""}"
+5,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,0,"{""value"":""com.apple.install""}"
+5,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,1,"{""value"":"" claims selected messages.\n\tThose messages may not appear in standard system log files or in the ASL database.""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,0,"{""value"":""com.apple.authd""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,1,"{""value"":"" sharing output destination ""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,2,"{""value"":""/var/log/asl""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,3,"{""value"":"" with ASL Module ""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,4,"{""value"":""com.apple.asl""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,5,"{""value"":"".\n\tOutput parameters from ASL Module ""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,6,"{""value"":""com.apple.asl""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,7,"{""value"":"" override any specified in ASL Module ""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,8,"{""value"":""com.apple.authd""}"
+8,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,9,"{""value"":"".""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,0,"{""value"":""com.apple.authd""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,1,"{""value"":"" sharing output destination ""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,2,"{""value"":""/var/log/system.log""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,3,"{""value"":"" with ASL Module ""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,4,"{""value"":""com.apple.asl""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,5,"{""value"":"".\n\tOutput parameters from ASL Module ""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,6,"{""value"":""com.apple.asl""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,7,"{""value"":"" override any specified in ASL Module ""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,8,"{""value"":""com.apple.authd""}"
+11,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,9,"{""value"":"".""}"
+14,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,0,"{""value"":""com.apple.authd""}"
+14,<NULL>,2022-08-16 00:32:15.000,0,info,0,<NULL>,<NULL>,<NULL>,Tims-Air,<NULL>,314,<NULL>,syslogd,<NULL>,syslogd[314],<NULL>,1,"{""value"":"" claims selected messages.\n\tThose messages may not appear in standard system log files or in the ASL database.""}"
diff --git a/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err b/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.err
diff --git a/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.out b/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.out
new file mode 100644
index 0000000..655ce13
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_bbd1128cf61a9af8f9dc937b46217443f42e1a7a.out
@@ -0,0 +1,2 @@
+match_index  content 
+ 0 {"key":"foo","value":"123e"} 
diff --git a/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.err b/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.err
new file mode 100644
index 0000000..79d28a5
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.err
@@ -0,0 +1,9 @@
+✘ error: unable to parse flags
+ reason: invalid JSON
+ |  reason: lexical error: invalid char in json text.
+ |   |  {abc
+ |   |  (right here) ------^
+ |   --> flags:1
+ |   | {abc
+ --> command-option:1
+ | ;SELECT * from regexp_capture_into_json('foo=0x123e;', '(?<key>\w+)=(?<value>[^;]+)', '{abc')
diff --git a/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.out b/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_d42e1fcfe6d42394f79da84be2d37e62c4c0ea63.out
diff --git a/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.err b/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.err
diff --git a/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.out b/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.out
new file mode 100644
index 0000000..6e952fb
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_d61af17ff19d640ddfc879460910991825eedd05.out
@@ -0,0 +1,2 @@
+match_index  content 
+ 0 {"col_0":"abc","col_1":"def"} 
diff --git a/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.err b/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.err
diff --git a/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.out b/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.out
new file mode 100644
index 0000000..fef8e26
--- /dev/null
+++ b/test/expected/test_sql_regexp.sh_ed6e9f13f178def009ee58c2aeea8c3c70fdb580.out
@@ -0,0 +1,2 @@
+match_index  content 
+ 0 {"key":"foo","value":"0x123e"} 
diff --git a/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.err b/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.err
diff --git a/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.out b/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.out
new file mode 100644
index 0000000..d56bc20
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_1a0d872ebc492fcecb2e79a0993170d5fc771a5b.out
@@ -0,0 +1,2 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters  comp  opid  tid  user  item prc reason  req  sid  src  sub vpxa_update  line  file match_index  lro_id  entity  operation  SessionId  SessionSubId 
+ 2  <NULL> 2022-06-02 11:58:12.376  182 info   0  <NULL>  <NULL>  <NULL> <NULL> e3979f6 45709 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846064 SessionManager vim.SessionManager.sessionIsActive 52626140-422b-6287-b4e4-344192c6a01d 523e0a4b-6e83-6bcd-9342-22502dd89866 
diff --git a/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.err b/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.err
diff --git a/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.out b/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.out
new file mode 100644
index 0000000..c92cf49
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_3f5f74863d065418bca5a000e6ad3d9344635164.out
@@ -0,0 +1,12 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters match_index  name 
+ 2  <NULL> 2022-08-16 00:32:15.000  199000 info   0  <NULL>  <NULL>  <NULL>  0 com.apple.cdscheduler 
+ 5 <NULL> 2022-08-16 00:32:15.000 0 info 0 <NULL> <NULL> <NULL> 0 com.apple.install
+ 8  <NULL> 2022-08-16 00:32:15.000  0 info   0  <NULL>  <NULL>  <NULL>  0 com.apple.authd 
+ 8 <NULL> 2022-08-16 00:32:15.000 0 info 0 <NULL> <NULL> <NULL> 1 com.apple.asl
+ 8  <NULL> 2022-08-16 00:32:15.000  0 info   0  <NULL>  <NULL>  <NULL>  2 com.apple.asl 
+ 8 <NULL> 2022-08-16 00:32:15.000 0 info 0 <NULL> <NULL> <NULL> 3 com.apple.authd
+ 11  <NULL> 2022-08-16 00:32:15.000  0 info   0  <NULL>  <NULL>  <NULL>  0 com.apple.authd 
+ 11 <NULL> 2022-08-16 00:32:15.000 0 info 0 <NULL> <NULL> <NULL> 1 com.apple.asl
+ 11  <NULL> 2022-08-16 00:32:15.000  0 info   0  <NULL>  <NULL>  <NULL>  2 com.apple.asl 
+ 11 <NULL> 2022-08-16 00:32:15.000 0 info 0 <NULL> <NULL> <NULL> 3 com.apple.authd
+ 14  <NULL> 2022-08-16 00:32:15.000  0 info   0  <NULL>  <NULL>  <NULL>  0 com.apple.authd 
diff --git a/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.err b/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.err
diff --git a/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.out b/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.out
new file mode 100644
index 0000000..738eab3
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_5aaae556ecb1661602f176215e28f661d3404032.out
@@ -0,0 +1,4 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters match_index user pid cpu_pct mem_pct vsz rss tty stat start_time cpu_time  cmd  cmd_name cmd_args 
+ 0  <NULL> 2022-06-02 00:01:01.000  0 info   0  <NULL>  <NULL>  <NULL>  1 root  2  0  0  0  0 ?  S  Jun01  0:00  [kthreadd] [kthreadd]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  1 root  2  0  0  0  0 ?  S  Jun01  0:00  [kthreadd] [kthreadd]  <NULL>
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  1 root  2  0  0  0  0 ?  S  Jun01  0:00  [kthreadd] [kthreadd]  <NULL> 
diff --git a/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.err b/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.err
diff --git a/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.out b/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.out
new file mode 100644
index 0000000..326fcbd
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_df0fd242f57a96d40f466493938cda0789a094fa.out
@@ -0,0 +1,24 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters match_index user pid cpu_pct mem_pct  vsz rss tty stat start_time cpu_time  cmd  cmd_name  cmd_args 
+ 0  <NULL> 2022-06-02 00:01:01.000  0 info   0  <NULL>  <NULL>  <NULL>  0 root  1  0  0 158392 7792 ?  Ss  Jun01  0:14  /lib/systemd/systemd --switched-root --system --deserialize 16 /lib/systemd/systemd  --switched-root --system --deserialize 16 
+ 0 <NULL> 2022-06-02 00:01:01.000 0 info 0 <NULL> <NULL> <NULL> 1 root 2 0 0 0 0 ? S Jun01 0:00 [kthreadd] [kthreadd] <NULL>
+ 0  <NULL> 2022-06-02 00:01:01.000  0 info   0  <NULL>  <NULL>  <NULL>  2 root  3  0  0  0  0 ?  I<  Jun01  0:00  [rcu_gp]  [rcu_gp]  <NULL> 
+ 0 <NULL> 2022-06-02 00:01:01.000 0 info 0 <NULL> <NULL> <NULL> 3 root 4 0 0 0 0 ? I< Jun01 0:00 [rcu_par_gp] [rcu_par_gp] <NULL>
+ 0  <NULL> 2022-06-02 00:01:01.000  0 info   0  <NULL>  <NULL>  <NULL>  4 root  6  0  0  0  0 ?  I<  Jun01  0:00  [kworker/0:0H-kblockd]  [kworker/0:0H-kblockd] <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  0 root  1  0  0 158392 7792 ?  Ss  Jun01  0:14  /lib/systemd/systemd --switched-root --system --deserialize 16 /lib/systemd/systemd  --switched-root --system --deserialize 16
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  1 root  2  0  0  0  0 ?  S  Jun01  0:00  [kthreadd]  [kthreadd]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL> <NULL> <NULL> 2 root 3 0 0 0 0 ? I< Jun01 0:00 [rcu_gp] [rcu_gp] <NULL>
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  3 root  4  0  0  0  0 ?  I<  Jun01  0:00  [rcu_par_gp]  [rcu_par_gp]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL> <NULL> <NULL> 4 root 6 0 0 0 0 ? I< Jun01 0:00 [kworker/0:0H-kblockd] [kworker/0:0H-kblockd] <NULL>
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  5 root  8  0  0  0  0 ?  I<  Jun01  0:00  [mm_percpu_wq]  [mm_percpu_wq]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL> <NULL> <NULL> 6 root 9 0 0 0 0 ? S Jun01 0:00 [ksoftirqd/0] [ksoftirqd/0] <NULL>
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  7 root  10  0  0  0  0 ?  I  Jun01  0:23  [rcu_sched]  [rcu_sched]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL> <NULL> <NULL> 8 root 11 0 0 0 0 ? I Jun01 0:00 [rcu_bh] [rcu_bh] <NULL>
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  9 root  12  0  0  0  0 ?  S  Jun01  0:00  [migration/0]  [migration/0]  <NULL> 
+ 12  <NULL> 2022-06-02 00:02:01.000  60000 info   0  <NULL> <NULL> <NULL> 10 root 14 0 0 0 0 ? S Jun01 0:00 [cpuhp/0] [cpuhp/0] <NULL>
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  0 root  1  0  0 158392 7792 ?  Ss  Jun01  0:14  /lib/systemd/systemd --switched-root --system --deserialize 16 /lib/systemd/systemd  --switched-root --system --deserialize 16 
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL> <NULL> <NULL> 1 root 2 0 0 0 0 ? S Jun01 0:00 [kthreadd] [kthreadd] <NULL>
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  2 root  3  0  0  0  0 ?  I<  Jun01  0:00  [rcu_gp]  [rcu_gp]  <NULL> 
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL> <NULL> <NULL> 3 root 4 0 0 0 0 ? I< Jun01 0:00 [rcu_par_gp] [rcu_par_gp] <NULL>
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  4 root  6  0  0  0  0 ?  I<  Jun01  0:00  [kworker/0:0H-kblockd]  [kworker/0:0H-kblockd] <NULL> 
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL> <NULL> <NULL> 5 root 8 0 0 0 0 ? I< Jun01 0:00 [mm_percpu_wq] [mm_percpu_wq] <NULL>
+ 30  <NULL> 2022-06-02 00:03:01.000  60000 info   0  <NULL>  <NULL>  <NULL>  6 root  9  0  0  0  0 ?  S  Jun01  0:00  [ksoftirqd/0]  [ksoftirqd/0]  <NULL> 
diff --git a/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.err b/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.err
diff --git a/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.out b/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.out
new file mode 100644
index 0000000..767d785
--- /dev/null
+++ b/test/expected/test_sql_search_table.sh_ef9373a76853f345d06234f6e0fe11b5d40da27b.out
@@ -0,0 +1,6 @@
+log_line log_part  log_time log_idle_msecs log_level log_mark log_comment log_tags log_filters  comp  opid  tid  user  item prc reason  req  sid  src  sub vpxa_update  line  file match_index  lro_id  entity  operation  SessionId  SessionSubId  log_body 
+ 0  <NULL> 2022-06-02 11:58:12.193  0 info   0  <NULL>  <NULL>  <NULL> <NULL> 7e1280cf  45715 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846063 SessionManager  vim.SessionManager.sessionIsActive  528e6e0c-246d-58b5-3234-278c6e0c5d0d 52c289ac-2563-48d5-8a8e-f178da022c0d [VpxLRO] -- BEGIN lro-846063 -- SessionManager -- vim.Sessio⋯8b5-3234-278c6e0c5d0d(52c289ac-2563-48d5-8a8e-f178da022c0d) 
+ 2  <NULL> 2022-06-02 11:58:12.376  182 info   0  <NULL>  <NULL>  <NULL> <NULL> e3979f6  45709 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846064 SessionManager  vim.SessionManager.sessionIsActive  52626140-422b-6287-b4e4-344192c6a01d 523e0a4b-6e83-6bcd-9342-22502dd89866 [VpxLRO] -- BEGIN lro-846064 -- SessionManager -- vim.Sessio⋯287-b4e4-344192c6a01d(523e0a4b-6e83-6bcd-9342-22502dd89866)
+ 4  <NULL> 2022-06-02 11:58:12.623  246 info   0  <NULL>  <NULL>  <NULL> <NULL> l3wrhr4o-cbf-h5:70001034-60 47524 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846066 ChangeLogCollector vim.cdc.ChangeLogCollector.waitForChanges 526861fc-0c28-1930-ae5e-d8c2772bf8c2 52a7a308-9646-c054-f1e7-16131c1a7db6 [VpxLRO] -- BEGIN lro-846066 -- ChangeLogCollector -- vim.c⋯1930-ae5e-d8c2772bf8c2(52a7a308-9646-c054-f1e7-16131c1a7db6) 
+ 6  <NULL> 2022-06-02 11:58:12.736  113 info   0  <NULL>  <NULL>  <NULL> <NULL> 499b440  48432 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846067 SessionManager vim.SessionManager.sessionIsActive 521fe9f6-d061-11a2-ac86-badb3c071373 524cba9b-2cc4-9b70-32e4-421452a404d7 [VpxLRO] -- BEGIN lro-846067 -- SessionManager -- vim.Sessio⋯1a2-ac86-badb3c071373(524cba9b-2cc4-9b70-32e4-421452a404d7)
+ 8  <NULL> 2022-06-02 11:58:12.740  4 info   0  <NULL>  <NULL>  <NULL> <NULL> 55a419df  48035 <NULL> <NULL> vpxd <NULL> <NULL> <NULL> Originator@6876 vpxLro  <NULL> <NULL> <NULL>  0 lro-846068 SessionManager  vim.SessionManager.sessionIsActive  52585600-b0bc-76b1-c4d5-4d7708671c5e 523b68ba-e312-9909-a3ca-39cc86aaf206 [VpxLRO] -- BEGIN lro-846068 -- SessionManager -- vim.Sessio⋯6b1-c4d5-4d7708671c5e(523b68ba-e312-9909-a3ca-39cc86aaf206) 
diff --git a/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.err b/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.err
diff --git a/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.out b/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.out
new file mode 100644
index 0000000..2c908c0
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_005b9365ac99596e539f47c9fe432668c209b21f.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column repl: abc=def
diff --git a/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.err b/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.err
diff --git a/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out b/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out
new file mode 100644
index 0000000..1d3dddd
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_04712488fe50554eb36d3ced80f9a033602f3daa.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"col_0":1}
diff --git a/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.err b/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.err
diff --git a/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.out b/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.out
new file mode 100644
index 0000000..e144653
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_0947bfe7ec626eaa0409a45b10fcbb634fb12eb7.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com/'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/","query":null,"parameters":null,"fragment":null}
diff --git a/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err b/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.err
diff --git a/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out b/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out
new file mode 100644
index 0000000..efa08d6
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_11bcc5d32eabbedb6974f160dace9ef1ef0009e9.out
@@ -0,0 +1,64 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 1
+ Column range_stop: 2
+ Column content: 1
+Row 1:
+ Column match_index: 0
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 1
+ Column range_stop: 2
+ Column content: 1
+Row 2:
+ Column match_index: 1
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 3
+ Column range_stop: 4
+ Column content: 2
+Row 3:
+ Column match_index: 1
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 3
+ Column range_stop: 4
+ Column content: 2
+Row 4:
+ Column match_index: 2
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 5
+ Column range_stop: 6
+ Column content: 3
+Row 5:
+ Column match_index: 2
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 5
+ Column range_stop: 6
+ Column content: 3
+Row 6:
+ Column match_index: 3
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 7
+ Column range_stop: 9
+ Column content: 45
+Row 7:
+ Column match_index: 3
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 7
+ Column range_stop: 9
+ Column content: 45
diff --git a/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err b/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.err
diff --git a/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out b/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out
new file mode 100644
index 0000000..eea58f2
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_11d458fdadd00df1239a0eeaac049abb49ed212d.out
@@ -0,0 +1,198 @@
+anonymize(bro_id_resp_h)
+10.0.0.1
+10.0.0.2
+10.0.0.2
+10.0.0.2
+10.0.0.2
+10.0.0.2
+10.0.0.2
+10.0.0.3
+10.0.0.4
+10.0.0.1
+10.0.0.4
+10.0.0.4
+10.0.0.5
+10.0.0.4
+10.0.0.4
+10.0.0.1
+10.0.0.6
+10.0.0.4
+10.0.0.7
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.8
+10.0.0.9
+10.0.0.10
+10.0.0.5
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.5
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.5
+10.0.0.10
+10.0.0.6
+10.0.0.12
+10.0.0.1
+10.0.0.1
+10.0.0.6
+10.0.0.11
+10.0.0.11
+10.0.0.13
+10.0.0.6
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.13
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.6
+10.0.0.14
+10.0.0.6
+10.0.0.14
+10.0.0.15
+10.0.0.16
+10.0.0.6
+10.0.0.16
+10.0.0.17
+10.0.0.5
+10.0.0.1
+10.0.0.17
+10.0.0.15
+10.0.0.17
+10.0.0.18
+10.0.0.18
+10.0.0.10
+10.0.0.5
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.18
+10.0.0.11
+10.0.0.11
+10.0.0.11
+10.0.0.18
+10.0.0.18
+10.0.0.18
+10.0.0.19
+10.0.0.18
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.19
+10.0.0.20
+10.0.0.20
+10.0.0.21
+10.0.0.18
+10.0.0.18
+10.0.0.22
+10.0.0.6
+10.0.0.5
+10.0.0.5
+10.0.0.5
+10.0.0.5
+10.0.0.6
+10.0.0.23
+10.0.0.24
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.24
+10.0.0.24
+10.0.0.24
+10.0.0.24
+10.0.0.25
+10.0.0.26
+10.0.0.27
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.25
+10.0.0.26
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.23
+10.0.0.25
+10.0.0.26
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.25
+10.0.0.26
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.28
+10.0.0.23
+10.0.0.25
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.26
+10.0.0.23
+10.0.0.25
+10.0.0.26
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.23
+10.0.0.27
+10.0.0.23
+10.0.0.25
+10.0.0.24
+10.0.0.24
+10.0.0.27
+10.0.0.26
diff --git a/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err b/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.err
diff --git a/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out b/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out
new file mode 100644
index 0000000..c474fab
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_129e58679e72f3cc5864812026e49a7917baf3d0.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column gunzip(gzip(1)): 1
diff --git a/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err b/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.err
diff --git a/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.out b/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.out
new file mode 100644
index 0000000..3b8aad8
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_151a0fd71ef6837c8cbd8a67e315019b5812b079.out
@@ -0,0 +1,8 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 1
+ Column range_start: 1
+ Column range_stop: 4
+ Column content: foo
diff --git a/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.err b/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.err
new file mode 100644
index 0000000..9b9cb88
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- wrong number of arguments to function humanize_file_size()
diff --git a/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.out b/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_1e7362ac3d9690b1b2cfbd320b6129c46ecfbb8a.out
diff --git a/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.err b/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.err
diff --git a/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.out b/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.out
new file mode 100644
index 0000000..13d2b61
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_211c5428db0590795072c31cb116ef35281e02b5.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column endswith('foo.', '.'): 1
diff --git a/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.err b/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.err
diff --git a/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.out b/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.out
new file mode 100644
index 0000000..7942a4a
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_2f189f0785bb81a1298db35e9e166983b633c73f.out
@@ -0,0 +1,8 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 1
+ Column range_start: 1
+ Column range_stop: 8
+ Column content: foo bar
diff --git a/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.err b/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.err
diff --git a/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.out b/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.out
new file mode 100644
index 0000000..76ba63e
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_30f65162174b886130b94a5dd1f094e7f09debed.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column unparse_url(parse_url('https://example.com/search?flag&flag2&=def#frag1%20space')): https://example.com/search?flag&flag2&=def#frag1%20space
diff --git a/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.err b/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.err
diff --git a/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.out b/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.out
new file mode 100644
index 0000000..8cb1716
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_352434d199f7b493668c9f2774472eb69ef0d9f0.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp('bc', 'abcd'): 1
diff --git a/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.err b/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.err
diff --git a/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.out b/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.out
new file mode 100644
index 0000000..52f6a45
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_36fc9005464f1106f969559e640d9fa36d5fadad.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp_replace('test 1 2 3', '\d+', 'N'): test N N N
diff --git a/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.err b/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.err
new file mode 100644
index 0000000..e3d40ab
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"invalid URL: “https://bad@[fe::”","attrs":[]},"reason":{"str":"Port number was not a decimal number between 0 and 65535","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.out b/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_3855d2cc0ab29171cae8e722f130adec25eae36e.out
diff --git a/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.err b/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.err
diff --git a/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.out b/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.out
new file mode 100644
index 0000000..e139659
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_3de72fe5c1751dd212a1cd45cf2caa7f3b52bced.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"foo":1,"bar":2,"baz":20.0,"msg":"hello"}
diff --git a/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.err b/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.err
diff --git a/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.out b/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.out
new file mode 100644
index 0000000..cf88bf4
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_4b402274da152135c6c99456b693e1ecabca0256.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column startswith('foo', '.'): 0
diff --git a/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.err b/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.err
diff --git a/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.out b/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.out
new file mode 100644
index 0000000..a8efc56
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_51055e40d709332ee772ba5719039314bbf5e411.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column endswith('foo', '.'): 0
diff --git a/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.err b/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.err
diff --git a/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.out b/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.out
new file mode 100644
index 0000000..061b9ed
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_51766b600fd158a9e0677f6b0fa31b83537b2e5b.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com/search?flag&flag2&=def'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/search","query":"flag&flag2&=def","parameters":{"flag":null,"flag2":null,"":"def"},"fragment":null}
diff --git a/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.err b/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.err
diff --git a/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.out b/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.out
new file mode 100644
index 0000000..e062d63
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5203db1a4a81e43a693f339fd26e1ed635da9d5a.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"foo":1,"bar":2}
diff --git a/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.err b/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.err
diff --git a/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.out b/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.out
new file mode 100644
index 0000000..aed4105
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5abe3717393fba14ec510a37b4b94fedc67aae8e.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column endswith('foo.txt', '.txt'): 1
diff --git a/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.err b/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.err
diff --git a/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.out b/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.out
new file mode 100644
index 0000000..22d58c4
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5e436fbd4efb140600999c5208886a5a57b8a30e.out
@@ -0,0 +1,24 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 3
+ Column range_start: 1
+ Column range_stop: 8
+ Column content: foo bar
+Row 1:
+ Column match_index: 0
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 3
+ Column range_start: 0
+ Column range_stop: 0
+ Column content: (null)
+Row 2:
+ Column match_index: 0
+ Column capture_index: 2
+ Column capture_name: word
+ Column capture_count: 3
+ Column range_start: 5
+ Column range_stop: 8
+ Column content: bar
diff --git a/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.err b/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.err
diff --git a/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.out b/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.out
new file mode 100644
index 0000000..3268219
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_5f9979fa5ce7b76efe714bb27ffbe9f5927ae941.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp('[e-z]+', 'ea'): 1
diff --git a/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.err b/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.err
diff --git a/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.out b/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.out
new file mode 100644
index 0000000..4645bc6
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_60a005a9f0d44ad022b5554415319933d5743c51.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column typeof(result): text
+ Column result: {"col_0":"","col_1":""}
diff --git a/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.err b/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.err
diff --git a/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.out b/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.out
new file mode 100644
index 0000000..0a2022e
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_660288b48d9b30244621d873944938f7ef043976.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column value: foo
diff --git a/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.err b/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.err
diff --git a/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.out b/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.out
new file mode 100644
index 0000000..b86c36b
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_6607c0dd8baff16930eb3e0daf6354af5b50052b.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column endswith('a', '.txt'): 0
diff --git a/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.err b/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.err
diff --git a/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.out b/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.out
new file mode 100644
index 0000000..913b8ce
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_69f5d49e62da48e188bd9d6af4bd3adeb21eb7d1.out
@@ -0,0 +1,6 @@
+Row 0:
+ Column match_index: 0
+ Column content: {"col_0":1,"col_1":2}
+Row 1:
+ Column match_index: 1
+ Column content: {"col_0":3,"col_1":4}
diff --git a/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.err b/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.err
diff --git a/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.out b/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.out
new file mode 100644
index 0000000..d1dcc93
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_6ff984d8ed3e5099376d19f0dd20d5fd1ed42494.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com/sea%26rch?flag&flag2&=def#frag1%20space'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/sea&rch","query":"flag&flag2&=def","parameters":{"flag":null,"flag2":null,"":"def"},"fragment":"frag1 space"}
diff --git a/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.err b/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.err
diff --git a/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.out b/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.out
new file mode 100644
index 0000000..3718bc2
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_71f37db33504b2c08a7a3323c482556f53d88100.out
@@ -0,0 +1,16 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 1
+ Column range_stop: 8
+ Column content: foo bar
+Row 1:
+ Column match_index: 0
+ Column capture_index: 1
+ Column capture_name: word
+ Column capture_count: 2
+ Column range_start: 5
+ Column range_stop: 8
+ Column content: bar
diff --git a/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.err b/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.err
diff --git a/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.out b/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.out
new file mode 100644
index 0000000..bf73241
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_77fc174faeec1eda687a9373dbdbdd1aaef56e20.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column typeof(result): text
+ Column result:
diff --git a/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.err b/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.err
new file mode 100644
index 0000000..4f2a2e8
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Expecting an integer for argument number 0
diff --git a/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.out b/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_790da4aab5af901feeff5426790876eb91b967cb.out
diff --git a/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.err b/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.err
diff --git a/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.out b/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.out
new file mode 100644
index 0000000..ec11590
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7a544cd702579c1fab35870428788ad763cf1143.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: (null)
diff --git a/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.err b/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.err
diff --git a/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.out b/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.out
new file mode 100644
index 0000000..c3b7854
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7b6e7c26e8a80459fef55d56156d6ff93c00bd49.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column unparse_url(parse_url('https://example.com/search?flag&flag2&=def')): https://example.com/search?flag&flag2&=def
diff --git a/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.err b/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.err
diff --git a/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.out b/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.out
new file mode 100644
index 0000000..6233470
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7c1e7604ac050e7047201638dca0a6b0fcfd8bdf.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column unparse_url(parse_url('https://example.com/search?flag&flag2')): https://example.com/search?flag&flag2
diff --git a/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.err b/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.err
diff --git a/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.out b/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.out
new file mode 100644
index 0000000..b012761
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_7f751009d0db15fc97f9113c5c84db05ff1de9c3.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column length(gzip(1)): 21
diff --git a/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.err b/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.err
diff --git a/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.out b/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.out
new file mode 100644
index 0000000..84c7397
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_805ca5e97fbf1ed56f2e920befd963255ba190b6.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com/search?flag&flag2'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/search","query":"flag&flag2","parameters":{"flag":null,"flag2":null},"fragment":null}
diff --git a/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.err b/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.err
new file mode 100644
index 0000000..2d0c060
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to regexp_match(re, str) failed","attrs":[{"start":8,"end":20,"type":"role","value":46},{"start":21,"end":23,"type":"role","value":45},{"start":25,"end":28,"type":"role","value":45},{"start":8,"end":29,"type":"role","value":59}]},"reason":{"str":"regular expression does not have any captures","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.out b/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_80c1fb9affbfac609ebf1cc5556aafb1ecd223c1.out
diff --git a/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.err b/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.err
diff --git a/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.out b/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.out
new file mode 100644
index 0000000..c803da8
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_836e3f721a0f945ad27e7aa241121ba739aab618.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column encode('foo', null): (null)
diff --git a/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.err b/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.err
diff --git a/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.out b/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.out
new file mode 100644
index 0000000..34bf1a0
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_838e9bc7873b2b238157ba0358e0dfd6a01d837d.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"foo":"abc","col_0":123}
diff --git a/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.err b/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.err
diff --git a/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.out b/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.out
new file mode 100644
index 0000000..ec11590
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_84e77dedec887c5e2433dbc5b130000cd88963bd.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: (null)
diff --git a/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.err b/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.err
new file mode 100644
index 0000000..511fbab
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Expecting an value of 'base64', 'hex', or 'uri' for argument number 1
diff --git a/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.out b/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_887afe94962d958aca2e03f7873d58ca93e190b5.out
diff --git a/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.err b/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.err
diff --git a/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.out b/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.out
new file mode 100644
index 0000000..724853b
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8c9ef83431ea75050fd16824075bf72056cf5f53.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column humanize_file_size(10 * 1000 * 1000): 9.5MB
diff --git a/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.err b/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.err
diff --git a/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.out b/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.out
new file mode 100644
index 0000000..233afd3
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8cef54f0617960320b5d3615068eb27333dcf6a3.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp('abcd', 'abcd'): 1
diff --git a/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.err b/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.err
diff --git a/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.out b/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.out
new file mode 100644
index 0000000..90f0972
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_8f4f0ed74c4dc6b821e02a44552b694614cd9353.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp_match(null, 'abc'): (null)
diff --git a/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.err b/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.err
diff --git a/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.out b/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.out
new file mode 100644
index 0000000..f93d348
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_949ffd5b2ef9fbcbe17f2e61ef7750f7038f6fd6.out
@@ -0,0 +1,2 @@
+regexp_match('^(\w+)=([^;]+);', 'abc=def;ghi=jkl;')
+{"col_0":"abc","col_1":"def"}
diff --git a/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.err b/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.err
diff --git a/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.out b/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.out
new file mode 100644
index 0000000..067e846
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a4d84a0082a7df34c95c2e6e070bbf6effaa5594.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column repl: test{ }1{ }2{ }3
diff --git a/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.err b/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.err
new file mode 100644
index 0000000..475a9b2
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"invalid URL: “https://example.com:100000”","attrs":[]},"reason":{"str":"Port number was not a decimal number between 0 and 65535","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.out b/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a515ba81cc3655c602da28cd0fa1a186d5e9a6e1.out
diff --git a/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.err b/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.err
diff --git a/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.out b/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.out
new file mode 100644
index 0000000..bf3f522
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_a65d2fb2f841578619528ca10168ca4d650218e9.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column typeof(result): real
+ Column result: 123.456
diff --git a/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.err b/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.err
diff --git a/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.out b/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.out
new file mode 100644
index 0000000..0652eef
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ac7ecdda0fcc4279a4694291edaa2f1411f5262e.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column repl: <\3><\3> <\3><\3>
diff --git a/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.err b/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.err
diff --git a/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.out b/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.out
new file mode 100644
index 0000000..e93f55d
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b088735cf46f23ca3d5fb3da41f07a6a3b1cba35.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/","query":null,"parameters":null,"fragment":null}
diff --git a/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.err b/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.err
diff --git a/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.out b/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.out
new file mode 100644
index 0000000..f94307e
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b0e5bf23bbbc0defa8bb26817782c9d46a778ad8.out
@@ -0,0 +1,16 @@
+Row 0:
+ Column match_index: 0
+ Column capture_index: 0
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 1
+ Column range_stop: 8
+ Column content: foo bar
+Row 1:
+ Column match_index: 0
+ Column capture_index: 1
+ Column capture_name: (null)
+ Column capture_count: 2
+ Column range_start: 5
+ Column range_stop: 8
+ Column content: bar
diff --git a/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.err b/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.err
diff --git a/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.out b/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.out
new file mode 100644
index 0000000..3e3281a
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b2aafbcaa7befe426d3f9df71c24f16fdc9d2856.out
@@ -0,0 +1,3 @@
+Row 0:
+ Column typeof(result): integer
+ Column result: 123
diff --git a/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.err b/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.err
diff --git a/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.out b/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.out
new file mode 100644
index 0000000..70e423e
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_b81b27abfafbd357d41c407428d41ae0f4bb75e2.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column unparse_url(parse_url('https://example.com/search?flag')): https://example.com/search?flag
diff --git a/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.err b/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.err
diff --git a/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.out b/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.out
new file mode 100644
index 0000000..daf8e0a
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bac7f6531a2adf70cd1871fb13eab26dff133b7c.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column parse_url('https://example.com/search?flag'): {"scheme":"https","user":null,"password":null,"host":"example.com","port":null,"path":"/search","query":"flag","parameters":{"flag":null},"fragment":null}
diff --git a/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.err b/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.err
diff --git a/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.out b/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.out
new file mode 100644
index 0000000..8a4e63d
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bfb7088916412360f77683009058b0747784630a.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column repl: <\><\> <\><\>
diff --git a/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.err b/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.err
new file mode 100644
index 0000000..9b9cb88
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- wrong number of arguments to function humanize_file_size()
diff --git a/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.out b/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_bfe8b09e23389af0ef14359b66d68228d0285185.out
diff --git a/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.err b/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.err
diff --git a/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.out b/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.out
new file mode 100644
index 0000000..f4fd280
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_c26269b10b9b9e8485aa97c2be2afb2cc3ee910d.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column gunzip(decode(encode(gzip('Hello, World!'), 'base64'), 'base64')): Hello, World!
diff --git a/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.err b/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.err
diff --git a/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.out b/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.out
new file mode 100644
index 0000000..366c195
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_c9e2f41431bef879364dc37a472ab01f64d89f89.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column regexp('[e-z]+', 'abcd'): 0
diff --git a/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.err b/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.err
diff --git a/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.out b/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.out
new file mode 100644
index 0000000..548d900
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_cc53348c585ee71a7456157ad6b125689813bafe.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column encode(null, 'base64'): (null)
diff --git a/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.err b/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.err
diff --git a/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.out b/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.out
new file mode 100644
index 0000000..3b62dec
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ce9db1dbc2e5fee87247135d17787ff3af014d77.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"foo":1}
diff --git a/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.err b/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.err
diff --git a/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.out b/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d3367527118052081a541a660b091f6f495b1c0d.out
diff --git a/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.err b/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.err
new file mode 100644
index 0000000..f4c8399
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Invalid regular expression: missing closing parenthesis
diff --git a/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.out b/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d4bc869850f5b7e53353fc2506fea0c8e96f29c5.out
diff --git a/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.err b/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.err
diff --git a/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.out b/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.out
new file mode 100644
index 0000000..fb41ca4
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d4e805ff08d4ccf62865dbf8db8d526f7ce02f37.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column result: {"foo":"abc","col_0":123.456}
diff --git a/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.err b/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.err
diff --git a/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.out b/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.out
new file mode 100644
index 0000000..659abf7
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d54a759f5683a22ad289129b2096b80652b1cc0c.out
@@ -0,0 +1,47 @@
+[
+ {
+ "log_body": "[VpxLRO] -- BEGIN lro-846063 -- SessionManager -- vim.SessionManager.sessionIsActive -- 528e6e0c-246d-58b5-3234-278c6e0c5d0d(52c289ac-2563-48d5-8a8e-f178da022c0d)",
+ "extract(log_body)": {
+ "col_0": [
+ "VpxLRO"
+ ],
+ "col_1": "--",
+ "col_2": "BEGIN",
+ "col_3": "lro-846063",
+ "col_4": "--",
+ "col_5": "SessionManager",
+ "col_6": "--",
+ "col_7": "vim.SessionManager.sessionIsActive",
+ "col_8": "--",
+ "col_9": "528e6e0c-246d-58b5-3234-278c6e0c5d0d",
+ "col_10": [
+ "52c289ac-2563-48d5-8a8e-f178da022c0d"
+ ]
+ }
+ },
+ {
+ "log_body": "[VpxLRO] -- FINISH lro-846063",
+ "extract(log_body)": {
+ "col_0": [
+ "VpxLRO"
+ ],
+ "col_1": "--",
+ "col_2": "FINISH",
+ "col_3": "lro-846063"
+ }
+ },
+ {
+ "log_body": "Exception was thrown when call vsan-performance-manager for cluster [vim.ClusterComputeResource:domain-c109,Cluster-52] perf metrics: N3Vim5Fault8NotFound9ExceptionE(Fault cause: vim.fault.NotFound\n--> )",
+ "extract(log_body)": {
+ "Exception was thrown when call vsan-performance-manager for cluster [vim.ClusterComputeResource:domain-c109,Cluster-52] perf metrics": {
+ "N3Vim5Fault8NotFound9ExceptionE": [
+ "Fault cause",
+ "vim.fault.NotFound",
+ "\n",
+ "--",
+ ">"
+ ]
+ }
+ }
+ }
+]
diff --git a/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.err b/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.err
diff --git a/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.out b/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.out
new file mode 100644
index 0000000..0c22818
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_d8d4cde8bbc98175069be579ff5634de43880b8c.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column startswith('.foo', '.'): 1
diff --git a/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.err b/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.err
diff --git a/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.out b/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_e68167bf5edc7a7b1defd06bdfb694ffa8b00df2.out
diff --git a/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.err b/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.err
diff --git a/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.out b/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.out
new file mode 100644
index 0000000..1fd3a79
--- /dev/null
+++ b/test/expected/test_sql_str_func.sh_ec939e82da809965c61f1c00f68d7afaa4a88382.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column repl: {test}{} {1}{} {2}{} {3}{}
diff --git a/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.err b/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.err
diff --git a/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.out b/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.out
new file mode 100644
index 0000000..1cbda8c
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_028e99419eb1ac80b03b36148ef1d4ae1c38c44c.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timediff('today', 'yesterday'): 86400.0
diff --git a/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.err b/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.err
diff --git a/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.out b/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.out
new file mode 100644
index 0000000..f209496
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_123c85ff1178743f5cb78efeaf98b637bcbe55ff.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice(null, null): (null)
diff --git a/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.err b/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.err
diff --git a/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.out b/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.out
new file mode 100644
index 0000000..8566fb2
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_14737ee9597b7d22519d23fbe34c0eb7d6c09ff2.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 11:59:00', 'before 12pm'): 2015-08-07 00:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.err b/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.err
diff --git a/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.out b/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.out
new file mode 100644
index 0000000..1a4cb45
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_1fbeb1ba69a95284eb1d4d052f5068ede7968704.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 11:59:00', 'fri'): 2015-08-07 00:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.err b/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.err
diff --git a/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.out b/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.out
new file mode 100644
index 0000000..ba1b6f3
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_20477acc218c96f1385dc97e4d28c80a05c93709.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 11:59:00', 'after fri'): (null)
diff --git a/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.err b/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.err
diff --git a/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.out b/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.out
new file mode 100644
index 0000000..7c5c9a3
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_243454526f6b5e19485db771b4932ddffd6f83a4.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice(1616300753.333, '100ms'): 2021-03-21 04:25:53.300
diff --git a/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.err b/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.err
diff --git a/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.out b/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.out
new file mode 100644
index 0000000..46dac6c
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_28638a132caae65fd89a68459d1b4af0000b8aef.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 08:01:33', '8 am'): (null)
diff --git a/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.err b/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.err
diff --git a/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.out b/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.out
new file mode 100644
index 0000000..e029e45
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_3b551281347a8144c84f00ade2664db9ac4aacab.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timediff('2017-01-02T05:00:00.100', '2017-01-02T05:00:00.000'): 0.1
diff --git a/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.err b/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.err
diff --git a/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.out b/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.out
new file mode 100644
index 0000000..f575185
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_4035ee76938269e9247f9a696927a9ac18cce80a.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', '5m'): 2015-08-07 12:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.err b/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.err
new file mode 100644
index 0000000..fa2cecd
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":46},{"start":18,"end":22,"type":"role","value":45},{"start":24,"end":29,"type":"role","value":45},{"start":8,"end":30,"type":"role","value":59}]},"reason":{"str":"unable to parse time slice value: blah -- Unrecognized input","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.out b/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_42f0fc1a154b0d79b4f6e846f283426be498040f.out
diff --git a/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.err b/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.err
diff --git a/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.out b/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.out
new file mode 100644
index 0000000..088f537
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_4b96fe71bc2d18955e3625b765a6095ab1f7a75d.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', 'after 12pm'): 2015-08-07 12:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.err b/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.err
diff --git a/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.out b/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.out
new file mode 100644
index 0000000..b5d1a46
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_53b76b094e47691b5bca106142ee470e82e8e420.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', '1 month'): 2015-08-03 00:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.err b/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.err
diff --git a/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.out b/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.out
new file mode 100644
index 0000000..e1e9cb6
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_6288a9e690d381602b2be5665cc1cd3552733bc2.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', 'before 12pm'): (null)
diff --git a/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.err b/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.err
diff --git a/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.out b/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.out
new file mode 100644
index 0000000..f09bc3f
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_652bbd00b5159e22d94970ab1e882997d14b5777.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 11:59:00', 'after 12pm'): (null)
diff --git a/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.err b/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.err
new file mode 100644
index 0000000..f8b9601
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- timeslice() expects between 1 and 2 arguments
diff --git a/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.out b/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_6832a58259168622af8b3370b0c89534f98f3f9f.out
diff --git a/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.err b/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.err
new file mode 100644
index 0000000..c789e93
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- lnav-error:{"level":"error","message":{"str":"call to timeslice(time, slice) failed","attrs":[{"start":8,"end":17,"type":"role","value":46},{"start":18,"end":22,"type":"role","value":45},{"start":24,"end":29,"type":"role","value":45},{"start":8,"end":30,"type":"role","value":59}]},"reason":{"str":"no time slice value given","attrs":[]},"snippets":[],"help":{"str":"","attrs":[]}}
diff --git a/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.out b/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_72862ec9c8f261a8507d237eb673c7ddfaafd898.out
diff --git a/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.err b/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.err
diff --git a/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.out b/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.out
new file mode 100644
index 0000000..1f9d1e1
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_7797302b63d73234c9ec9f0405c7c0a748daf8e9.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timediff('foo', 'yesterday'): (null)
diff --git a/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.err b/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.err
diff --git a/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.out b/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.out
new file mode 100644
index 0000000..de734a9
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_9569ab40cb2e51c60f818a6c2729c60d86565e7e.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-02-01T05:10:00'): 2015-02-01 05:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.err b/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.err
diff --git a/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.out b/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.out
new file mode 100644
index 0000000..74ec041
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_9e649c4bc10f4d178519983358f7092e9c5dfe71.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', '1d'): 2015-08-07 00:00:00.000
diff --git a/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.err b/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.err
diff --git a/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.out b/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.out
new file mode 100644
index 0000000..e913429
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_b0257ced663fc444801a5e6cba89c3053acca11e.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', 'before fri'): (null)
diff --git a/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.err b/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.err
diff --git a/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.out b/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.out
new file mode 100644
index 0000000..f18a8b8
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_b5f9ec3ea8b4551fd40017398d74c524fb54ebc9.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice(null): (null)
diff --git a/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.err b/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.err
diff --git a/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.out b/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.out
new file mode 100644
index 0000000..2729e3c
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_dbe786c096d5a7a5e1d05311b929f1427d8bac79.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 12:01:00', '8 am'): (null)
diff --git a/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.err b/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.err
diff --git a/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.out b/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.out
new file mode 100644
index 0000000..8687c5d
--- /dev/null
+++ b/test/expected/test_sql_time_func.sh_f3b1ea49779117bf45f85ad5615fdc5e89193db6.out
@@ -0,0 +1,2 @@
+Row 0:
+ Column timeslice('2015-08-07 08:00:33', '8 am'): 2015-08-07 08:00:00.000
diff --git a/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err b/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err
new file mode 100644
index 0000000..6568331
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Only the top view in the stack can be deleted
+ --> command-option:2
+ | ;DELETE FROM lnav_view_stack WHERE name = 'log'
diff --git a/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.out b/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_28e23f4e98b1acd6478e39844fd9306b444550c3.out
diff --git a/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.err b/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.err
diff --git a/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.out b/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.out
new file mode 100644
index 0000000..710f668
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_32acc1a8bb5028636fdbf08f077f9a835ab51bec.out
@@ -0,0 +1,19 @@
+Build
+
+Lnav follows the usual GNU style for configuring and installing
+software:
+
+Run  ./autogen.sh  if compiling from a cloned repository.
+
+ ▌$ ./configure 
+ ▌$ make 
+ ▌$ sudo make install 
+
+See Also
+
+Angle-grinder[1] is a tool to slice and dice log files on the
+command-line. If you're familiar with the SumoLogic query language,
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.err b/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.err
diff --git a/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.out b/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.out
new file mode 100644
index 0000000..bfe5f1e
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_485a6ac7c69bd4b5d34d3399a9c17f6a2dc89ad3.out
@@ -0,0 +1 @@
+2014-10-08 16:56:38,344:WARN:foo bar baz
diff --git a/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.err b/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.err
new file mode 100644
index 0000000..0c9a2b7
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: filter already exists -- :filter-in vmk
+ --> command-option:3
+ | ;UPDATE lnav_view_filters SET pattern = 'vmk'
diff --git a/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.out b/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.out
new file mode 100644
index 0000000..48f52f3
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_62d15cb9d5a9259f198aa01ca8ed200d6da38d68.out
@@ -0,0 +1,3 @@
+view_name filter_id enabled type language pattern 
+log   1  1 in  regex  vmk 
+log   2    1 in regex vmk1
diff --git a/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.err b/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.err
diff --git a/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.out b/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.out
new file mode 100644
index 0000000..2678e6c
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_662b5f9b17aa69a8e3aa9a18acb30d9acf6e2837.out
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.err b/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.err
diff --git a/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.out b/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.out
new file mode 100644
index 0000000..1ad5fbf
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_6ffd89498b9a7758ded6717148fc2ce77a12621b.out
@@ -0,0 +1,2 @@
+search 
+warn
diff --git a/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err b/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err
new file mode 100644
index 0000000..482241e
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Expecting a non-empty pattern value
+ --> command-option:1
+ | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', '')
diff --git a/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.out b/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_764ea85863d4f0ea3b7cb40850ac7c8fde682d57.out
diff --git a/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.err b/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.err
new file mode 100644
index 0000000..6787d65
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: A SQL expression filter already exists
+ --> command-option:2
+ | ;INSERT INTO lnav_view_filters (view_name, language, pattern) VALUES ('log', 'sql', '1')
diff --git a/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.out b/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.out
new file mode 100644
index 0000000..c99c751
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_81dc3eb51ec4dc3066a2365524001242c423a9cf.out
@@ -0,0 +1,2 @@
+view_name filter_id enabled type language pattern 
+log   0  1 out  sql  1  
diff --git a/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.err b/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.err
diff --git a/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.out b/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_81ffd4ed3f62228494a966512791202cea7e3b57.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err b/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err
new file mode 100644
index 0000000..609aacb
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Expecting an lnav view name for column number 0
+ --> command-option:1
+ | ;INSERT INTO lnav_view_filters VALUES ('bad', 0, 1, 'out', 'regex', 'abc')
diff --git a/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.out b/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_87f53d441e22c1d27c27eaa6003c83da1207c063.out
diff --git a/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.err b/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.err
diff --git a/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.out b/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.out
new file mode 100644
index 0000000..d51a68c
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_977cdf5d396522194d6b9e945169ff8073b4296b.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.err b/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.err
diff --git a/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.out b/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.out
new file mode 100644
index 0000000..8ee2f08
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_9a5be90921256e90428c77753eca5ea0d31bd910.out
@@ -0,0 +1,2 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err b/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err
new file mode 100644
index 0000000..a0853fd
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: filter already exists -- :filter-in vmk
+ --> command-option:2
+ | ;INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk', 'in')
diff --git a/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out b/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out
new file mode 100644
index 0000000..38afb7c
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_a2c0f0e51b3f85ea2a05ecdcacaad962b4fe5d4f.out
@@ -0,0 +1,2 @@
+view_name filter_id enabled type language pattern 
+log   1  1 in  regex  vmk 
diff --git a/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err b/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err
new file mode 100644
index 0000000..66b8e6a
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: The lnav_view_stack table cannot be updated
+ --> command-option:1
+ | ;UPDATE lnav_view_stack SET name = 'foo'
diff --git a/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out b/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ac1f6e9a88608ef8939f9c2f7061a25a86742d46.out
diff --git a/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err b/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err
new file mode 100644
index 0000000..dd46516
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Invalid regular expression for pattern: missing closing parenthesis at offset 4
+ --> command-option:1
+ | ;INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', 'abc(')
diff --git a/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.out b/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ade121f29bedea0d1a54452cc994b2302ad9dabb.out
diff --git a/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err b/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err
new file mode 100644
index 0000000..4276af6
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Invalid time: bad-time
+ --> command-option:1
+ | ;UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log'
diff --git a/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.out b/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_c851bdf3ba2f56fac5a216457b2d11a109e77f03.out
diff --git a/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.err b/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.err
diff --git a/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.out b/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.out
new file mode 100644
index 0000000..bc35132
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_d99d884ba6668b66e3ca9ea4ed2d0e236497c35d.out
@@ -0,0 +1 @@
+2014-10-08 16:56:38,344:WARN:foo bar baz
diff --git a/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.err b/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.err
diff --git a/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.out b/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.out
new file mode 100644
index 0000000..493283c
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_e036fabdc6c15f65a374b95c9922212670d494ee.out
@@ -0,0 +1 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.err b/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.err
diff --git a/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.out b/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.out
new file mode 100644
index 0000000..0dd4cb7
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_ec4623bd63ff353f50db44da1231e46a1a4f1824.out
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err b/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err
new file mode 100644
index 0000000..aab37c6
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Expecting an lnav view name for column number 0
+ --> command-option:1
+ | ;INSERT INTO lnav_view_filters VALUES (NULL, 0, 1, 'out', 'regex', 'abc')
diff --git a/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.out b/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_f7476c76ea51cf479a6a79b037e0cb59871b629c.out
diff --git a/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err b/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err
new file mode 100644
index 0000000..8a477fc
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.err
@@ -0,0 +1,4 @@
+✘ error: SQL statement failed
+ reason: Expecting an value of 'in' or 'out' for column number 3
+ --> command-option:1
+ | ;INSERT INTO lnav_view_filters VALUES ('log', 0 , 1, 'bad', 'regex', 'abc')
diff --git a/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.out b/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_views_vtab.sh_f8340cb4c62aabd839ea09235b6ebe41b2bb48f4.out
diff --git a/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.err b/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.err
diff --git a/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.out b/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_46dfa23e2effabf3fa150c4b871fd8d22b1c834d.out
diff --git a/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.err b/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.err
diff --git a/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.out b/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.out
new file mode 100644
index 0000000..a4c5713
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_4effabf11b59580e5f0727199eb74fba049c0cda.out
@@ -0,0 +1,6 @@
+Row 0:
+ Column result: <def>Hello &gt;</def>
+
+ Column node_path: /abc/def
+ Column node_attr: {}
+ Column node_text: Hello >
diff --git a/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.err b/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.err
diff --git a/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.out b/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.out
new file mode 100644
index 0000000..2800fc5
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_8912b59d5b515ab1373a3d9bc635ebabacd01dfd.out
@@ -0,0 +1,6 @@
+Row 0:
+ Column result: <def a="b">ghi</def>
+
+ Column node_path: /abc/def[2]
+ Column node_attr: {"a":"b"}
+ Column node_text: ghi
diff --git a/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.err b/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.err
new file mode 100644
index 0000000..6ac0f80
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Invalid XPATH expression at offset 5: Unrecognized node test
diff --git a/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out b/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out
diff --git a/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err b/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err
new file mode 100644
index 0000000..a97d7cd
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err
@@ -0,0 +1 @@
+error: sqlite3_exec failed -- Invalid XML document at offset 3: Error parsing start element tag
diff --git a/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out b/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out
diff --git a/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.err b/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.err
new file mode 100644
index 0000000..b7f3a79
--- /dev/null
+++ b/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.err
@@ -0,0 +1,4 @@
+✘ error: failed to parse YAML content
+ reason: closing ] not found
+ --> command-option:1
+ | ;SELECT yaml_to_json('[abc') 
diff --git a/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.out b/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_yaml_func.sh_41c6abde708a69e74f5b7fde865d88fa75f91e0a.out
diff --git a/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.err b/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.err
new file mode 100644
index 0000000..b7f3a79
--- /dev/null
+++ b/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.err
@@ -0,0 +1,4 @@
+✘ error: failed to parse YAML content
+ reason: closing ] not found
+ --> command-option:1
+ | ;SELECT yaml_to_json('[abc') 
diff --git a/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.out b/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_sql_yaml_func.sh_dc189d02e8979b7ed245d5d750f68b9965984699.out
diff --git a/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err b/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err
new file mode 100644
index 0000000..b77acd0
--- /dev/null
+++ b/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err
@@ -0,0 +1,3 @@
+tailer stderr:
+info: load preview request -- 1234
+info: exiting...
diff --git a/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out b/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out
new file mode 100644
index 0000000..cd58305
--- /dev/null
+++ b/test/expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out
@@ -0,0 +1,8 @@
+preview of file: {test_dir}/remote-log-dir/*
+{test_dir}/remote-log-dir/logfile_access_log.0
+{test_dir}/remote-log-dir/logfile_access_log.1
+
+all done!
+tailer stderr:
+info: load preview request -- 1234
+info: exiting...
diff --git a/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.err b/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.err
new file mode 100644
index 0000000..08a372f
--- /dev/null
+++ b/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.err
@@ -0,0 +1,2 @@
+✘ error: unable to open file: non-existent:
+ reason: failed to ssh to host: ssh: Could not resolve hostname non-existent: nodename nor servname provided, or not known
diff --git a/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.out b/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_2e69c22dcfa37b5c3e8490a6026eacb7ca953998.out
diff --git a/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err b/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err
diff --git a/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out b/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out
new file mode 100644
index 0000000..a39be1e
--- /dev/null
+++ b/test/expected/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out
@@ -0,0 +1,178 @@
+Build[1][2] Docs[3][4] Coverage Status[5][6] lnav[7][8]
+
+ ▌[1] - https://github.com/tstack/lnav/workflows/ci-build/badge.svg
+ ▌[2] - https://github.com/tstack/lnav/actions?query=workflow%3Aci-build
+ ▌[3] - https://readthedocs.org/projects/lnav/badge/?version=latest&style=plastic
+ ▌[4] - https://docs.lnav.org
+ ▌[5] - https://coveralls.io/repos/github/tstack/lnav/badge.svg?branch=master
+ ▌[6] - https://coveralls.io/github/tstack/lnav?branch=master
+ ▌[7] - https://snapcraft.io/lnav/badge.svg
+ ▌[8] - https://snapcraft.io/lnav
+
+<img
+src="https://assets-global.website-files.com/6257adef93867e50d84d30e2/62594fddd654fc29fcc07359_cb48d2a8d4991281d7a6a95d2f58195e.svg"
+height="20"/>[1]
+
+ ▌[1] - https://discord.gg/erBPnKwz7R
+
+This is the source repository for lnav, visit https://lnav.org[1] for
+a high level overview.
+
+ ▌[1] - https://lnav.org
+
+LNAV – The Logfile Navigator
+
+The Log File Navigator, lnav for short, is an advanced log file viewer
+for the small-scale. It is a terminal application that can understand
+your log files and make it easy for you to find problems with little
+to no setup.
+
+Screenshot
+
+The following screenshot shows a syslog file. Log lines are displayed
+with highlights. Errors are red and warnings are yellow.
+
+Screenshot[1][2]
+
+ ▌[1] - file://{top_srcdir}/docs/assets/images/lnav-syslog-thumb.png
+ ▌[2] - file://{top_srcdir}/docs/assets/images/lnav-syslog.png
+
+Features
+
+ • Log messages from different files are collated together
+ into a single view
+ • Automatic detection of log format
+ • Automatic decompression of GZip and BZip2 files
+ • Filter log messages based on regular expressions
+ • Use SQL to analyze your logs
+ • And more...
+
+Installation
+
+Download a statically-linked binary for Linux/MacOS from the release
+page[1]
+
+ ▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
+
+Usage
+
+The only file installed is the executable,  lnav . You can execute it
+with no arguments to view the default set of files:
+
+ ▌$ lnav 
+
+You can view all the syslog messages by running:
+
+ ▌$ lnav /var/log/messages* 
+
+Usage with  systemd-journald 
+
+On systems running  systemd-journald , you can use  lnav  as the
+pager:
+
+ ▌$ journalctl | lnav 
+
+or in follow mode:
+
+ ▌$ journalctl -f | lnav 
+
+Since  journalctl 's default output format omits the year, if you are
+viewing logs which span multiple years you will need to change the
+output format to include the year, otherwise  lnav  gets confused:
+
+ ▌$ journalctl -o short-iso | lnav 
+
+It is also possible to use  journalctl 's json output format and  lnav
+will make use of additional fields such as PRIORITY and _SYSTEMD_UNIT:
+
+ ▌$ journalctl -o json | lnav 
+
+In case some MESSAGE fields contain special characters such as ANSI
+color codes which are considered as unprintable by journalctl,
+specifying  journalctl 's  -a  option might be preferable in order to
+output those messages still in a non-binary representation:
+
+ ▌$ journalctl -a -o json | lnav 
+
+If using systemd v236 or newer, the output fields can be limited to
+the ones actually recognized by  lnav  for increased efficiency:
+
+ ▌$ journalctl -o json --output-fields=MESSAGE,PRIORITY,_PID,SYSLOG_IDENTIFIER,_SYSTEMD_UNIT | lnav 
+
+If your system has been running for a long time, for increased
+efficiency you may want to limit the number of log lines fed into  lnav
+, e.g. via  journalctl 's  -n  or  --since=...  options.
+
+In case of a persistent journal, you may want to limit the number of
+log lines fed into  lnav  via  journalctl 's  -b  option.
+
+Support
+
+Please file issues on this repository or use the discussions section.
+The following alternatives are also available:
+
+ • support@lnav.org[1]
+ • Discord[2]
+ • Google Groups[3]
+
+ ▌[1] - mailto:support@lnav.org
+ ▌[2] - https://discord.gg/erBPnKwz7R
+ ▌[3] - https://groups.google.com/g/lnav
+
+Links
+
+ • Main Site[1]
+ • Documentation[2] on Read the Docs
+ • Internal Architecture[3]
+
+ ▌[1] - https://lnav.org
+ ▌[2] - https://docs.lnav.org
+ ▌[3] - file://{top_srcdir}/ARCHITECTURE.md
+
+Contributing
+
+ • Become a Sponsor on GitHub[1]
+
+ ▌[1] - https://github.com/sponsors/tstack
+
+Building From Source
+
+Prerequisites
+
+The following software packages are required to build lnav:
+
+ • gcc/clang - A C++14-compatible compiler.
+ • libpcre2 - The Perl Compatible Regular Expression v2
+ (PCRE2) library.
+ • sqlite - The SQLite database engine. Version 3.9.0
+ or higher is required.
+ • ncurses - The ncurses text UI library.
+ • readline - The readline line editing library.
+ • zlib - The zlib compression library.
+ • bz2 - The bzip2 compression library.
+ • libcurl - The cURL library for downloading files
+ from URLs. Version 7.23.0 or higher is required.
+ • libarchive - The libarchive library for opening archive
+ files, like zip/tgz.
+ • wireshark - The 'tshark' program is used to interpret
+ pcap files.
+
+Build
+
+Lnav follows the usual GNU style for configuring and installing
+software:
+
+Run  ./autogen.sh  if compiling from a cloned repository.
+
+ ▌$ ./configure 
+ ▌$ make 
+ ▌$ sudo make install 
+
+See Also
+
+Angle-grinder[1] is a tool to slice and dice log files on the
+command-line. If you're familiar with the SumoLogic query language,
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.err b/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.err
diff --git a/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out b/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out
new file mode 100644
index 0000000..accb1c3
--- /dev/null
+++ b/test/expected/test_text_file.sh_6a24078983cf1b7a80b6fb65d5186cd125498136.out
@@ -0,0 +1,149 @@
+Screenshot
+
+The following screenshot shows a syslog file. Log lines are displayed
+with highlights. Errors are red and warnings are yellow.
+
+Screenshot[1][2]
+
+ ▌[1] - file://{top_srcdir}/docs/assets/images/lnav-syslog-thumb.png
+ ▌[2] - file://{top_srcdir}/docs/assets/images/lnav-syslog.png
+
+Features
+
+ • Log messages from different files are collated together
+ into a single view
+ • Automatic detection of log format
+ • Automatic decompression of GZip and BZip2 files
+ • Filter log messages based on regular expressions
+ • Use SQL to analyze your logs
+ • And more...
+
+Installation
+
+Download a statically-linked binary for Linux/MacOS from the release
+page[1]
+
+ ▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
+
+Usage
+
+The only file installed is the executable,  lnav . You can execute it
+with no arguments to view the default set of files:
+
+ ▌$ lnav 
+
+You can view all the syslog messages by running:
+
+ ▌$ lnav /var/log/messages* 
+
+Usage with  systemd-journald 
+
+On systems running  systemd-journald , you can use  lnav  as the
+pager:
+
+ ▌$ journalctl | lnav 
+
+or in follow mode:
+
+ ▌$ journalctl -f | lnav 
+
+Since  journalctl 's default output format omits the year, if you are
+viewing logs which span multiple years you will need to change the
+output format to include the year, otherwise  lnav  gets confused:
+
+ ▌$ journalctl -o short-iso | lnav 
+
+It is also possible to use  journalctl 's json output format and  lnav
+will make use of additional fields such as PRIORITY and _SYSTEMD_UNIT:
+
+ ▌$ journalctl -o json | lnav 
+
+In case some MESSAGE fields contain special characters such as ANSI
+color codes which are considered as unprintable by journalctl,
+specifying  journalctl 's  -a  option might be preferable in order to
+output those messages still in a non-binary representation:
+
+ ▌$ journalctl -a -o json | lnav 
+
+If using systemd v236 or newer, the output fields can be limited to
+the ones actually recognized by  lnav  for increased efficiency:
+
+ ▌$ journalctl -o json --output-fields=MESSAGE,PRIORITY,_PID,SYSLOG_IDENTIFIER,_SYSTEMD_UNIT | lnav 
+
+If your system has been running for a long time, for increased
+efficiency you may want to limit the number of log lines fed into  lnav
+, e.g. via  journalctl 's  -n  or  --since=...  options.
+
+In case of a persistent journal, you may want to limit the number of
+log lines fed into  lnav  via  journalctl 's  -b  option.
+
+Support
+
+Please file issues on this repository or use the discussions section.
+The following alternatives are also available:
+
+ • support@lnav.org[1]
+ • Discord[2]
+ • Google Groups[3]
+
+ ▌[1] - mailto:support@lnav.org
+ ▌[2] - https://discord.gg/erBPnKwz7R
+ ▌[3] - https://groups.google.com/g/lnav
+
+Links
+
+ • Main Site[1]
+ • Documentation[2] on Read the Docs
+ • Internal Architecture[3]
+
+ ▌[1] - https://lnav.org
+ ▌[2] - https://docs.lnav.org
+ ▌[3] - file://{top_srcdir}/ARCHITECTURE.md
+
+Contributing
+
+ • Become a Sponsor on GitHub[1]
+
+ ▌[1] - https://github.com/sponsors/tstack
+
+Building From Source
+
+Prerequisites
+
+The following software packages are required to build lnav:
+
+ • gcc/clang - A C++14-compatible compiler.
+ • libpcre2 - The Perl Compatible Regular Expression v2
+ (PCRE2) library.
+ • sqlite - The SQLite database engine. Version 3.9.0
+ or higher is required.
+ • ncurses - The ncurses text UI library.
+ • readline - The readline line editing library.
+ • zlib - The zlib compression library.
+ • bz2 - The bzip2 compression library.
+ • libcurl - The cURL library for downloading files
+ from URLs. Version 7.23.0 or higher is required.
+ • libarchive - The libarchive library for opening archive
+ files, like zip/tgz.
+ • wireshark - The 'tshark' program is used to interpret
+ pcap files.
+
+Build
+
+Lnav follows the usual GNU style for configuring and installing
+software:
+
+Run  ./autogen.sh  if compiling from a cloned repository.
+
+ ▌$ ./configure 
+ ▌$ make 
+ ▌$ sudo make install 
+
+See Also
+
+Angle-grinder[1] is a tool to slice and dice log files on the
+command-line. If you're familiar with the SumoLogic query language,
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.err b/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.err
diff --git a/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.out b/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.out
new file mode 100644
index 0000000..a7ed740
--- /dev/null
+++ b/test/expected/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.out
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2018, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log_level.hh"
+
+#include <ctype.h>
+
+#include "config.h"
+
+const char* level_names[LEVEL__MAX + 1] = {
+ "unknown",
+ "trace",
+ "debug5",
+ "debug4",
+ "debug3",
+ "debug2",
+ "debug",
+ "info",
+ "stats",
+ "notice",
+ "warning",
+ "error",
+ "critical",
+ "fatal",
+ "invalid",
+
+ nullptr,
+};
+
+log_level_t
+abbrev2level(const char* levelstr, ssize_t len)
+{
+ if (len == 0 || levelstr[0] == '\0') {
+ return LEVEL_UNKNOWN;
+ }
+
+ switch (toupper(levelstr[0])) {
+ case 'T':
+ return LEVEL_TRACE;
+ case 'D':
+ case 'V':
+ if (len > 1) {
+ switch (levelstr[len - 1]) {
+ case '2':
+ return LEVEL_DEBUG2;
+ case '3':
+ return LEVEL_DEBUG3;
+ case '4':
+ return LEVEL_DEBUG4;
+ case '5':
+ return LEVEL_DEBUG5;
+ }
+ }
+ return LEVEL_DEBUG;
+ case 'I':
+ if (len == 7 && toupper(levelstr[1]) == 'N'
+ && toupper(levelstr[2]) == 'V' && toupper(levelstr[3]) == 'A'
+ && toupper(levelstr[4]) == 'L' && toupper(levelstr[5]) == 'I'
+ && toupper(levelstr[6]) == 'D')
+ {
+ return LEVEL_INVALID;
+ }
+ return LEVEL_INFO;
+ case 'S':
+ return LEVEL_STATS;
+ case 'N':
+ return LEVEL_NOTICE;
+ case 'W':
+ return LEVEL_WARNING;
+ case 'E':
+ return LEVEL_ERROR;
+ case 'C':
+ return LEVEL_CRITICAL;
+ case 'F':
+ return LEVEL_FATAL;
+ default:
+ return LEVEL_UNKNOWN;
+ }
+}
+
+int
+levelcmp(const char* l1, ssize_t l1_len, const char* l2, ssize_t l2_len)
+{
+ return abbrev2level(l1, l1_len) - abbrev2level(l2, l2_len);
+}
diff --git a/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err b/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err
diff --git a/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out b/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out
new file mode 100644
index 0000000..ae06214
--- /dev/null
+++ b/test/expected/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2018, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log_level.hh"
+
+#include <ctype.h>
+
+#include "config.h"
+
+const char* level_names[LEVEL__MAX + 1] = {
+ "unknown",
+ "trace",
+ "debug5",
+ "debug4",
+ "debug3",
+ "debug2",
+ "debug",
+ "info",
+ "stats",
+ "notice",
+ "warning",
+ "error",
+ "critical",
+ "fatal",
+ "invalid",
+
+ nullptr,
+};
+
+log_level_t
+abbrev2level(const char* levelstr, ssize_t len)
+{
+ if (len == 0 || levelstr[0] == '\0') {
+ return LEVEL_UNKNOWN;
+ }
+
+ switch (toupper(levelstr[0])) {
+ case 'T':
+ return LEVEL_TRACE;
+ case 'D':
+ case 'V':
+ if (len > 1) {
+ switch (levelstr[len - 1]) {
+ case '2':
+ return LEVEL_DEBUG2;
+ case '3':
+ return LEVEL_DEBUG3;
+ case '4':
+ return LEVEL_DEBUG4;
+ case '5':
+ return LEVEL_DEBUG5;
+ }
+ }
+ return LEVEL_DEBUG;
+ case 'I':
+ if (len == 7 && toupper(levelstr[1]) == 'N'
+ && toupper(levelstr[2]) == 'V' && toupper(levelstr[3]) == 'A'
+ && toupper(levelstr[4]) == 'L' && toupper(levelstr[5]) == 'I'
+ && toupper(levelstr[6]) == 'D')
+ {
+ return LEVEL_INVALID;
+ }
+ return LEVEL_INFO;
+ case 'S':
+ return LEVEL_STATS;
+ case 'N':
+ return LEVEL_NOTICE;
+ case 'W':
+ return LEVEL_WARNING;
+ case 'E':
+ return LEVEL_ERROR;
+ case 'C':
+ return LEVEL_CRITICAL;
+ case 'F':
+ return LEVEL_FATAL;
+ default:
+ return LEVEL_UNKNOWN;
+ }
+}
+
+int
+levelcmp(const char* l1, ssize_t l1_len, const char* l2, ssize_t l2_len)
+{
+ return abbrev2level(l1, l1_len) - abbrev2level(l2, l2_len);
+}
diff --git a/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.err b/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.err
diff --git a/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.out b/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.out
new file mode 100644
index 0000000..c8719bb
--- /dev/null
+++ b/test/expected/test_text_file.sh_8b2cd055e6a1db2ed9b2af2a917f8556395fa653.out
@@ -0,0 +1,2 @@
+ filepath  descriptor  mimetype  content 
+{test_dir}/textfile_0.md net.daringfireball.markdown.frontmatter application/json {␊ "comment": "This is JSON front-matter"␊} 
diff --git a/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.err b/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.err
diff --git a/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.out b/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.out
new file mode 100644
index 0000000..5a1b89a
--- /dev/null
+++ b/test/expected/test_text_file.sh_ac486314c4e02e480d829ea2f077b86c49fedcec.out
@@ -0,0 +1,4 @@
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err b/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.err
diff --git a/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out b/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out
new file mode 100644
index 0000000..6c9b5ae
--- /dev/null
+++ b/test/expected/test_text_file.sh_ac872aadda29b9a824361a2c711d62ec1c75d40f.out
@@ -0,0 +1,74 @@
+✘ error: unable to parse markdown file
+ reason: file has invalid UTF-8 at offset 4461: Expecting bytes in the following ranges: 00..7F C2..F4.
+
+UTF-8 decoder capability and stress test
+----------------------------------------
+
+Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> - 2015-08-28 - CC BY 4.0
+
+This test file can help you examine, how your UTF-8 decoder handles
+various types of correct, malformed, or otherwise interesting UTF-8
+sequences. This file is not meant to be a conformance test. It does
+not prescribe any particular outcome. Therefore, there is no way to
+"pass" or "fail" this test file, even though the text does suggest a
+preferable decoder behaviour at some places. Its aim is, instead, to
+help you think about, and test, the behaviour of your UTF-8 decoder on a
+systematic collection of unusual inputs. Experience so far suggests
+that most first-time authors of UTF-8 decoders find at least one
+serious problem in their decoder using this file.
+
+The test lines below cover boundary conditions, malformed UTF-8
+sequences, as well as correctly encoded UTF-8 sequences of Unicode code
+points that should never occur in a correct UTF-8 file.
+
+According to ISO 10646-1:2000, sections D.7 and 2.3c, a device
+receiving UTF-8 shall interpret a "malformed sequence in the same way
+that it interprets a character that is outside the adopted subset" and
+"characters that are not within the adopted subset shall be indicated
+to the user" by a receiving device. One commonly used approach in
+UTF-8 decoders is to replace any malformed UTF-8 sequence by a
+replacement character (U+FFFD), which looks a bit like an inverted
+question mark, or a similar symbol. It might be a good idea to
+visually distinguish a malformed UTF-8 sequence from a correctly
+encoded Unicode character that is just not available in the current
+font but otherwise fully legal, even though ISO 10646-1 doesn't
+mandate this. In any case, just ignoring malformed sequences or
+unavailable characters does not conform to ISO 10646, will make
+debugging more difficult, and can lead to user confusion.
+
+Please check, whether a malformed UTF-8 sequence is (1) represented at
+all, (2) represented by exactly one single replacement character (or
+equivalent signal), and (3) the following quotation mark after an
+illegal UTF-8 sequence is correctly displayed, i.e. proper
+resynchronization takes place immediately after any malformed
+sequence. This file says "THE END" in the last line, so if you don't
+see that, your decoder crashed somehow before, which should always be
+cause for concern.
+
+All lines in this file are exactly 79 characters long (plus the line
+feed). In addition, all lines end with "|", except for the two test
+lines 2.1.1 and 2.2.1, which contain non-printable ASCII controls
+U+0000 and U+007F. If you display this file with a fixed-width font,
+these "|" characters should all line up in column 79 (right margin).
+This allows you to test quickly, whether your UTF-8 decoder finds the
+correct number of characters in every line, that is whether each
+malformed sequences is replaced by a single replacement character.
+
+Note that, as an alternative to the notion of malformed sequence used
+here, it is also a perfectly acceptable (and in some situations even
+preferable) solution to represent each individual byte of a malformed
+sequence with a replacement character. If you follow this strategy in
+your decoder, then please ignore the "|" column.
+
+
+Here come the tests: |
+ |
+1 Some correct UTF-8 text |
+ |
+You should see the Greek word 'kosme': "κόσμε" |
+ |
+2 Boundary condition test cases |
+ |
+2.1 First possible sequence of a certain length |
+ |
+2.1.1 1 byte (U-00000000): "
diff --git a/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.err b/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.err
diff --git a/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.out b/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.out
new file mode 100644
index 0000000..59a0aa9
--- /dev/null
+++ b/test/expected/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.out
@@ -0,0 +1,159 @@
+Build[1][2] Docs[3][4] Coverage Status[5][6] lnav[7][8]
+
+ ▌[1] - https://github.com/tstack/lnav/workflows/ci-build/badge.svg
+ ▌[2] - https://github.com/tstack/lnav/actions?query=workflow%3Aci-build
+ ▌[3] - https://readthedocs.org/projects/lnav/badge/?version=latest&style=plastic
+ ▌[4] - https://docs.lnav.org
+ ▌[5] - https://coveralls.io/repos/github/tstack/lnav/badge.svg?branch=master
+ ▌[6] - https://coveralls.io/github/tstack/lnav?branch=master
+ ▌[7] - https://snapcraft.io//lnav/badge.svg
+ ▌[8] - https://snapcraft.io/lnav
+
+This is the source repository for lnav, visit https://lnav.org[1] for
+a high level overview.
+
+ ▌[1] - https://lnav.org
+
+LNAV – The Logfile Navigator
+
+The Log File Navigator, lnav for short, is an advanced log file viewer
+for the small-scale. It is a terminal application that can understand
+your log files and make it easy for you to find problems with little
+to no setup.
+
+Screenshot
+
+The following screenshot shows a syslog file. Log lines are displayed
+with highlights. Errors are red and warnings are yellow.
+
+Screenshot[1][2]
+
+ ▌[1] - file://{top_srcdir}/docs/assets/images/lnav-syslog-thumb.png
+ ▌[2] - file://{top_srcdir}/docs/assets/images/lnav-syslog.png
+
+Features
+
+ • Log messages from different files are collated together
+ into a single view
+ • Automatic detection of log format
+ • Automatic decompression of GZip and BZip2 files
+ • Filter log messages based on regular expressions
+ • Use SQL to analyze your logs
+ • And more...
+
+Installation
+
+Download a statically-linked binary for Linux/MacOS from the release
+page[1]
+
+ ▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
+
+Usage
+
+The only file installed is the executable,  lnav . You can execute it
+with no arguments to view the default set of files:
+
+ ▌$ lnav 
+
+You can view all the syslog messages by running:
+
+ ▌$ lnav /var/log/messages* 
+
+Usage with  systemd-journald 
+
+On systems running  systemd-journald , you can use  lnav  as the
+pager:
+
+ ▌$ journalctl | lnav 
+
+or in follow mode:
+
+ ▌$ journalctl -f | lnav 
+
+Since  journalctl 's default output format omits the year, if you are
+viewing logs which span multiple years you will need to change the
+output format to include the year, otherwise  lnav  gets confused:
+
+ ▌$ journalctl -o short-iso | lnav 
+
+It is also possible to use  journalctl 's json output format and  lnav
+will make use of additional fields such as PRIORITY and _SYSTEMD_UNIT:
+
+ ▌$ journalctl -o json | lnav 
+
+In case some MESSAGE fields contain special characters such as ANSI
+color codes which are considered as unprintable by journalctl,
+specifying  journalctl 's  -a  option might be preferable in order to
+output those messages still in a non binary representation:
+
+ ▌$ journalctl -a -o json | lnav 
+
+If using systemd v236 or newer, the output fields can be limited to
+the ones actually recognized by  lnav  for increased efficiency:
+
+ ▌$ journalctl -o json --output-fields=MESSAGE,PRIORITY,_PID,SYSLOG_IDENTIFIER,_SYSTEMD_UNIT | lnav 
+
+If your system has been running for a long time, for increased
+efficiency you may want to limit the number of log lines fed into  lnav
+, e.g. via  journalctl 's  -n  or  --since=...  options.
+
+In case of a persistent journal, you may want to limit the number of
+log lines fed into  lnav  via  journalctl 's  -b  option.
+
+Links
+
+ • Main Site[1]
+ • Documentation[2] on Read the Docs
+ • Internal Architecture[3]
+
+ ▌[1] - https://lnav.org
+ ▌[2] - https://docs.lnav.org
+ ▌[3] - file://{top_srcdir}/ARCHITECTURE.md
+
+Contributing
+
+ • Become a Sponsor on GitHub[1]
+
+ ▌[1] - https://github.com/sponsors/tstack
+
+Building From Source
+
+Prerequisites
+
+The following software packages are required to build lnav:
+
+ • gcc/clang - A C++14-compatible compiler.
+ • libpcre - The Perl Compatible Regular Expression
+ (PCRE) library.
+ • sqlite - The SQLite database engine. Version 3.9.0
+ or higher is required.
+ • ncurses - The ncurses text UI library.
+ • readline - The readline line editing library.
+ • zlib - The zlib compression library.
+ • bz2 - The bzip2 compression library.
+ • libcurl - The cURL library for downloading files
+ from URLs. Version 7.23.0 or higher is required.
+ • libarchive - The libarchive library for opening archive
+ files, like zip/tgz.
+ • wireshark - The 'tshark' program is used to interpret
+ pcap files.
+
+Build
+
+Lnav follows the usual GNU style for configuring and installing
+software:
+
+Run  ./autogen.sh  if compiling from a cloned repository.
+
+ ▌$ ./configure 
+ ▌$ make 
+ ▌$ sudo make install 
+
+See Also
+
+Angle-grinder[1] is a tool to slice and dice log files on the
+command-line. If you're familiar with the SumoLogic query language,
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err b/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.err
diff --git a/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out b/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out
new file mode 100644
index 0000000..1efd1ba
--- /dev/null
+++ b/test/expected/test_text_file.sh_c2a346ca1da2da4346f1d310212e166767993ce9.out
@@ -0,0 +1,58 @@
+[
+ {
+ "top_meta": {
+ "file": "{top_srcdir}/README.md",
+ "anchor": "#support",
+ "breadcrumbs": [
+ {
+ "display_value": "README.md",
+ "search_placeholder": "",
+ "possibilities": [
+ {
+ "display_value": "README.md"
+ }
+ ]
+ },
+ {
+ "display_value": "LNAV – The Logfile Navigator",
+ "search_placeholder": "",
+ "possibilities": [
+ {
+ "display_value": "LNAV – The Logfile Navigator"
+ }
+ ]
+ },
+ {
+ "display_value": "Support",
+ "search_placeholder": "",
+ "possibilities": [
+ {
+ "display_value": "Contributing"
+ },
+ {
+ "display_value": "Features"
+ },
+ {
+ "display_value": "Installation"
+ },
+ {
+ "display_value": "Links"
+ },
+ {
+ "display_value": "Screenshot"
+ },
+ {
+ "display_value": "See Also"
+ },
+ {
+ "display_value": "Support"
+ },
+ {
+ "display_value": "Usage"
+ }
+ ]
+ }
+ ]
+ }
+ }
+]
diff --git a/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.err b/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.err
diff --git a/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.out b/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.out
new file mode 100644
index 0000000..accb1c3
--- /dev/null
+++ b/test/expected/test_text_file.sh_e088ea61a5382458cc48a2607e2639e52b0be1da.out
@@ -0,0 +1,149 @@
+Screenshot
+
+The following screenshot shows a syslog file. Log lines are displayed
+with highlights. Errors are red and warnings are yellow.
+
+Screenshot[1][2]
+
+ ▌[1] - file://{top_srcdir}/docs/assets/images/lnav-syslog-thumb.png
+ ▌[2] - file://{top_srcdir}/docs/assets/images/lnav-syslog.png
+
+Features
+
+ • Log messages from different files are collated together
+ into a single view
+ • Automatic detection of log format
+ • Automatic decompression of GZip and BZip2 files
+ • Filter log messages based on regular expressions
+ • Use SQL to analyze your logs
+ • And more...
+
+Installation
+
+Download a statically-linked binary for Linux/MacOS from the release
+page[1]
+
+ ▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
+
+Usage
+
+The only file installed is the executable,  lnav . You can execute it
+with no arguments to view the default set of files:
+
+ ▌$ lnav 
+
+You can view all the syslog messages by running:
+
+ ▌$ lnav /var/log/messages* 
+
+Usage with  systemd-journald 
+
+On systems running  systemd-journald , you can use  lnav  as the
+pager:
+
+ ▌$ journalctl | lnav 
+
+or in follow mode:
+
+ ▌$ journalctl -f | lnav 
+
+Since  journalctl 's default output format omits the year, if you are
+viewing logs which span multiple years you will need to change the
+output format to include the year, otherwise  lnav  gets confused:
+
+ ▌$ journalctl -o short-iso | lnav 
+
+It is also possible to use  journalctl 's json output format and  lnav
+will make use of additional fields such as PRIORITY and _SYSTEMD_UNIT:
+
+ ▌$ journalctl -o json | lnav 
+
+In case some MESSAGE fields contain special characters such as ANSI
+color codes which are considered as unprintable by journalctl,
+specifying  journalctl 's  -a  option might be preferable in order to
+output those messages still in a non-binary representation:
+
+ ▌$ journalctl -a -o json | lnav 
+
+If using systemd v236 or newer, the output fields can be limited to
+the ones actually recognized by  lnav  for increased efficiency:
+
+ ▌$ journalctl -o json --output-fields=MESSAGE,PRIORITY,_PID,SYSLOG_IDENTIFIER,_SYSTEMD_UNIT | lnav 
+
+If your system has been running for a long time, for increased
+efficiency you may want to limit the number of log lines fed into  lnav
+, e.g. via  journalctl 's  -n  or  --since=...  options.
+
+In case of a persistent journal, you may want to limit the number of
+log lines fed into  lnav  via  journalctl 's  -b  option.
+
+Support
+
+Please file issues on this repository or use the discussions section.
+The following alternatives are also available:
+
+ • support@lnav.org[1]
+ • Discord[2]
+ • Google Groups[3]
+
+ ▌[1] - mailto:support@lnav.org
+ ▌[2] - https://discord.gg/erBPnKwz7R
+ ▌[3] - https://groups.google.com/g/lnav
+
+Links
+
+ • Main Site[1]
+ • Documentation[2] on Read the Docs
+ • Internal Architecture[3]
+
+ ▌[1] - https://lnav.org
+ ▌[2] - https://docs.lnav.org
+ ▌[3] - file://{top_srcdir}/ARCHITECTURE.md
+
+Contributing
+
+ • Become a Sponsor on GitHub[1]
+
+ ▌[1] - https://github.com/sponsors/tstack
+
+Building From Source
+
+Prerequisites
+
+The following software packages are required to build lnav:
+
+ • gcc/clang - A C++14-compatible compiler.
+ • libpcre2 - The Perl Compatible Regular Expression v2
+ (PCRE2) library.
+ • sqlite - The SQLite database engine. Version 3.9.0
+ or higher is required.
+ • ncurses - The ncurses text UI library.
+ • readline - The readline line editing library.
+ • zlib - The zlib compression library.
+ • bz2 - The bzip2 compression library.
+ • libcurl - The cURL library for downloading files
+ from URLs. Version 7.23.0 or higher is required.
+ • libarchive - The libarchive library for opening archive
+ files, like zip/tgz.
+ • wireshark - The 'tshark' program is used to interpret
+ pcap files.
+
+Build
+
+Lnav follows the usual GNU style for configuring and installing
+software:
+
+Run  ./autogen.sh  if compiling from a cloned repository.
+
+ ▌$ ./configure 
+ ▌$ make 
+ ▌$ sudo make install 
+
+See Also
+
+Angle-grinder[1] is a tool to slice and dice log files on the
+command-line. If you're familiar with the SumoLogic query language,
+you might find this tool more comfortable to work with.
+
+ ▌[1] - https://github.com/rcoh/angle-grinder
+
diff --git a/test/expected_help.txt b/test/expected_help.txt
new file mode 100644
index 0000000..d741fd2
--- /dev/null
+++ b/test/expected_help.txt
@@ -0,0 +1,4013 @@
+
+lnav
+
+A fancy log file viewer for the terminal.
+
+Overview
+
+The Logfile Navigator, lnav, is an enhanced log file viewer that takes
+advantage of any semantic information that can be gleaned from the
+files being viewed, such as timestamps and log levels. Using this
+extra semantic information, lnav can do things like interleaving
+messages from different files, generate histograms of messages over
+time, and providing hotkeys for navigating through the file. It is
+hoped that these features will allow the user to quickly and
+efficiently zero in on problems.
+
+Opening Paths/URLs
+
+The main arguments to lnav are the files, directories, glob patterns,
+or URLs to be viewed. If no arguments are given, the default syslog
+file for your system will be opened. These arguments will be polled
+periodically so that any new data or files will be automatically
+loaded. If a previously loaded file is removed or replaced, it will be
+closed and the replacement opened.
+
+Note: When opening SFTP URLs, if the password is not provided for the
+host, the SSH agent can be used to do authentication.
+
+Options
+
+Lnav takes a list of files to view and/or you can use the flag
+arguments to load well-known log files, such as the syslog log files.
+The flag arguments are:
+
+ • -a Load all of the most recent log file types.
+ • -r Recursively load files from the given directory
+ hierarchies.
+ • -R Load older rotated log files as well.
+
+When using the flag arguments, lnav will look for the files relative
+to the current directory and its parent directories. In other words,
+if you are working within a directory that has the well-known log
+files, those will be preferred over any others.
+
+If you do not want the default syslog file to be loaded when no files
+are specified, you can pass the -N flag.
+
+Any files given on the command-line are scanned to determine their log
+file format and to create an index for each line in the file. You do
+not have to manually specify the log file format. The currently
+supported formats are: syslog, apache, strace, tcsh history, and
+generic log files with timestamps.
+
+Lnav will also display data piped in on the standard input. The
+following options are available when doing so:
+
+ • -t Prepend timestamps to the lines of data being read
+ in on the standard input.
+ • -w file Write the contents of the standard input to
+ this file.
+
+To automatically execute queries or lnav commands after the files have
+been loaded, you can use the following options:
+
+ • -c cmd A command, query, or file to execute. The
+ first character determines the type of operation: a colon
+ ( : ) is used for the built-in commands; a semi-colon ( ;
+ ) for SQL queries; and a pipe symbol ( | ) for executing
+ a file containing other commands. For example, to open
+ the file "foo.log" and go to the tenth line in the file,
+ you can do:
+
+ ┃lnav -c ':goto 10' foo.log
+
+ This option can be given multiple times to execute
+ multiple operations in sequence.
+ • -f file A file that contains commands, queries, or
+ files to execute. This option is a shortcut for -c '|file'
+ . You can use a dash ( - ) to execute commands from the
+ standard input.
+
+To execute commands/queries without the opening the interactive text
+UI, you can pass the -n option. This combination of options allows
+you to write scripts for processing logs with lnav. For example, to
+get a list of IP addresses that dhclient has bound to in CSV format:
+
+ ┃#! /usr/bin/lnav -nf
+ ┃
+ ┃# Usage: dhcp_ip.lnav /var/log/messages
+ ┃# Only include lines that look like:
+ ┃# Apr 29 00:31:56 example-centos5 dhclient: bound to 10.1.10.103 -- renewal in 9938 seconds.
+ ┃
+ ┃:filter-in dhclient: bound to
+ ┃
+ ┃# The log message parser will extract the IP address
+ ┃# as col_0, so we select that and alias it to "dhcp_ip".
+ ┃;select distinct col_0 as dhcp_ip from logline;
+ ┃
+ ┃# Finally, write the results of the query to stdout.
+ ┃:write-csv-to -
+
+Display
+
+The main part of the display shows the log lines from the files
+interleaved based on time-of-day. New lines are automatically loaded
+as they are appended to the files and, if you are viewing the bottom
+of the files, lnav will scroll down to display the new lines, much
+like tail -f .
+
+On color displays, the lines will be highlighted as follows:
+
+ • Errors will be colored in red;
+ • warnings will be yellow;
+ • boundaries between days will be underlined; and
+ • various color highlights will be applied to: IP
+ addresses, SQL keywords, XML tags, file and line numbers
+ in Java backtraces, and quoted strings.
+
+To give you an idea of where you are spatially, the right side of the
+display has a proportionally sized 'scroll bar' that indicates your
+current position in the files. The scroll bar will also show areas of
+the file where warnings or errors are detected by coloring the bar
+yellow or red, respectively. Tick marks will also be added to the left
+and right hand side of the bar, for search hits and bookmarks.
+
+A bar on the left side is color coded and broken up to indicate which
+messages are from the same file. Pressing the left-arrow or h will
+reveal the source file names for each message and pressing again will
+show the full paths.
+
+Above and below the main body are status lines that display:
+
+ • the current time;
+ • the name of the file the top line was pulled from;
+ • the log format for the top line;
+ • the current view;
+ • the line number for the top line in the display;
+ • the current search hit, the total number of hits, and
+ the search term;
+
+If the view supports filtering, there will be a status line showing
+the following:
+
+ • the number of enabled filters and the total number of
+ filters;
+ • the number of lines not displayed because of filtering.
+
+To edit the filters, you can press TAB to change the focus from the
+main view to the filter editor. The editor allows you to create,
+enable/disable, and delete filters easily.
+
+Finally, the last line on the display is where you can enter search
+patterns and execute internal commands, such as converting a unix-
+timestamp into a human-readable date. The command-line is implemented
+using the readline library, so the usual set of keyboard shortcuts are
+available. Most commands and searches also support tab-completion.
+
+The body of the display is also used to display other content, such
+as: the help file, histograms of the log messages over time, and SQL
+results. The views are organized into a stack so that any time you
+activate a new view with a key press or command, the new view is
+pushed onto the stack. Pressing the same key again will pop the view
+off of the stack and return you to the previous view. Note that you
+can always use q to pop the top view off of the stack.
+
+Default Key Bindings
+
+Views
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ ? View/leave this help message.
+ q Leave the current view or quit the program when in
+ the log file view.
+ Q Similar to q , except it will try to sync the top
+ time between the current and former views. For
+ example, when leaving the spectrogram view with Q
+ , the top time in that view will be matched to the
+ top time in the log view.
+ TAB Toggle focusing on the filter editor or the main
+ view.
+ a/A Restore the view that was previously popped with q
+ / Q . The A hotkey will try to match the top
+ times between the two views.
+ X Close the current text file or log file.
+
+Spatial Navigation
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════════
+ g/Home Move to the top of the file.
+ G/End Move to the end of the file. If the view is
+ already at the end, it will move to the last line.
+ SPACE/PgDn Move down a page.
+ b/PgUp Move up a page.
+ j/↓ Move down a line.
+ k/↑ Move up a line.
+ h/← Move to the left. In the log view, moving left
+ will reveal the source log file names for each
+ line. Pressing again will reveal the full path.
+ l/→ Move to the right.
+ H/Shift ← Move to the left by a smaller increment.
+ L/Shift → Move to the right by a smaller increment.
+ e/E Move to the next/previous error.
+ w/W Move to the next/previous warning.
+ n/N Move to the next/previous search hit. When pressed
+ repeatedly within a short time, the view will move
+ at least a full page at a time instead of moving
+ to the next hit.
+ f/F Move to the next/previous file. In the log view,
+ this moves to the next line from a different file.
+ In the text view, this rotates the view to the
+ next file.
+ >/< Move horizontally to the next/previous search hit.
+ o/O Move forward/backward to the log message with a
+ matching 'operation ID' (opid) field.
+ u/U Move forward/backward through any user bookmarks
+ you have added using the 'm' key. This hotkey will
+ also jump to the start of any log partitions that
+ have been created with the 'partition-name'
+ command.
+ s/S Move to the next/previous "slow down" in the log
+ message rate. A slow down is detected by measuring
+ how quickly the message rate has changed over the
+ previous several messages. For example, if one
+ message is logged every second for five seconds
+ and then the last message arrives five seconds
+ later, the last message will be highlighted as a
+ slow down.
+ {/} Move to the previous/next location in history.
+ Whenever you jump to a new location in the view,
+ the location will be added to the history. The
+ history is not updated when using only the arrow
+ keys.
+
+Chronological Navigation
+
+ Key(s) Action
+══════════════════════════════════════════════════════════════════
+ d/D Move forward/backward 24 hours from the current
+ position in the log file.
+ 1-6/Shift 1-6 Move to the next/previous n'th ten minute of the
+ hour. For example, '4' would move to the first log
+ line in the fortieth minute of the current hour in
+ the log. And, '6' would move to the next hour
+ boundary.
+ 7/8 Move to the previous/next minute.
+ 0/Shift 0 Move to the next/previous day boundary.
+ r/R Move forward/backward based on the relative time
+ that was last used with the 'goto' command. For
+ example, executing ':goto a minute later' will
+ move the log view forward a minute and then
+ pressing 'r' will move it forward a minute again.
+ Pressing 'R' will then move the view in the
+ opposite direction, so backwards a minute.
+
+Bookmarks
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ m Mark/unmark the line at the top of the display.
+ The line will be highlighted with reverse video to
+ indicate that it is a user bookmark. You can use
+ the u hotkey to iterate through marks you have
+ added.
+ M Mark/unmark all the lines between the top of the
+ display and the last line marked/unmarked.
+ J Mark/unmark the next line after the previously
+ marked line.
+ K Like J except it toggles the mark on the
+ previous line.
+ c Copy the marked text to the X11 selection buffer
+ or OS X clipboard.
+ C Clear all marked lines.
+
+Display options
+
+ Key(s) Action
+══════════════════════════════════════════════════════════════════
+ P Switch to/from the pretty-printed view of the log
+ or text files currently displayed. In this view,
+ structured data, such as XML, will be reformatted
+ to make it easier to read.
+ t Switch to/from the text file view. The text file
+ view is for any files that are not recognized as
+ log files.
+ = Pause/unpause loading of new file data.
+ Ctrl-L (Lo-fi mode) Exit screen-mode and write the
+ displayed log lines in plain text to the terminal
+ until a key is pressed. Useful for copying long
+ lines from the terminal without picking up any of
+ the extra decorations.
+ T Toggle the display of the "elapsed time" column
+ that shows the time elapsed since the beginning of
+ the logs or the offset from the previous bookmark.
+ Sharp changes in the message rate are highlighted
+ by coloring the separator between the time column
+ and the log message. A red highlight means the
+ message rate has slowed down and green means it
+ has sped up. You can use the "s/S" hotkeys to scan
+ through the slow downs.
+ i View/leave a histogram of the log messages over
+ time. The histogram counts the number of displayed
+ log lines for each bucket of time. The bars are
+ layed out horizontally with colored segments
+ representing the different log levels. You can use
+ the z hotkey to change the size of the time
+ buckets (e.g. ten minutes, one hour, one day).
+ I Switch between the log and histogram views while
+ keeping the time displayed at the top of each view
+ in sync. For example, if the top line in the log
+ view is "11:40", hitting I will switch to the
+ histogram view and scrolled to display "11:00" at
+ the top (if the zoom level is hours).
+ z/Shift Z Zoom in or out one step in the histogram view.
+ v Switch to/from the SQL result view.
+ V Switch between the log and SQL result views while
+ keeping the top line number in the log view in
+ sync with the log_line column in the SQL view. For
+ example, doing a query that selects for "
+ log_idle_msecs" and "log_line", you can move the
+ top of the SQL view to a line and hit 'V' to
+ switch to the log view and move to the line number
+ that was selected in the "log_line" column. If
+ there is no "log_line" column, lnav will find the
+ first column with a timestamp and move to
+ corresponding time in the log view.
+ TAB/Shift TAB In the SQL result view, cycle through the columns
+ that are graphed. Initially, all number values are
+ displayed in a stacked graph. Pressing TAB will
+ change the display to only graph the first column.
+ Repeatedly pressing TAB will cycle through the
+ columns until they are all graphed again.
+ p In the log view: enable or disable the display of
+ the fields that the log message parser knows about
+ or has discovered. This overlay is temporarily
+ enabled when the semicolon key (;) is pressed so
+ that it is easier to write queries.
+ In the DB view: enable or disable the display of
+ values in columns containing JSON-encoded values
+ in the top row. The overlay will display the JSON-
+ Pointer reference and value for all fields in the
+ JSON data.
+ CTRL-W Toggle word-wrapping.
+ CTRL-P Show/hide the data preview panel that may be
+ opened when entering commands or SQL queries.
+ CTRL-F Toggle the enabled/disabled state of all filters
+ in the current view.
+ x Toggle the hiding of log message fields. The
+ hidden fields will be replaced with three bullets
+ and highlighted in yellow.
+ F2 Toggle mouse support.
+
+Query
+
+ Key(s) Action
+═════════════════════════════════════════════════════════════════════════════
+ /regexp Start a search for the given regular expression.
+ The search is live, so when there is a pause in
+ typing, the currently running search will be
+ canceled and a new one started. The first ten
+ lines that match the search will be displayed in
+ the preview window at the bottom of the view.
+ History is maintained for your searches so you can
+ rerun them easily. Words that are currently
+ displayed are also available for tab-completion,
+ so you can easily search for values without
+ needing to copy-and-paste the string. If there is
+ an error encountered while trying to interpret the
+ expression, the error will be displayed in red on
+ the status line. While the search is active, the '
+ hits' field in the status line will be green, when
+ finished it will turn back to black.
+ :<command> Execute an internal command. The commands are
+ listed below. History is also supported in this
+ context as well as tab-completion for commands and
+ some arguments. The result of the command replaces
+ the command you typed.
+ ;<sql> Execute an SQL query. Most supported log file
+ formats provide a sqlite virtual table backend
+ that can be used in queries. See the SQL section
+ below for more information.
+ |<script> [arg1 .. argN] Execute an lnav script contained in a format
+ directory (e.g. ~/.lnav/formats/default). The
+ script can contain lines starting with : , ; ,
+ or | to execute commands, SQL queries or execute
+ other files in lnav. Any values after the script
+ name are treated as arguments can be referenced in
+ the script using $1 , $2 , and so on, like in a
+ shell script.
+ CTRL+], ESCAPE Abort command-line entry started with / , :
+, ;
+ , or | .
+
+ ┃ Note: The regular expression format used by is PCRE
+ ┃ (Perl-Compatible Regular Expressions). For example,
+ ┃ if you wanted to search for ethernet device names,
+ ┃ regardless of their ID number, you can type:
+ ┃
+ ┃ eth\d+
+ ┃
+ ┃ You can find more information about Perl regular
+ ┃ expressions at:
+ ┃
+ ┃ http://perldoc.perl.org/perlre.html
+ ┃
+ ┃ If the search string is not valid PCRE, a search
+ ┃ is done for the exact string instead of doing a
+ ┃ regex search.
+
+Session
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ CTRL-R Reset the session state. This will save the
+ current session state (filters, highlights) and
+ then reset the state to the factory default.
+
+Filter Editor
+
+The following hotkeys are only available when the focus is on the
+filter editor. You can change the focus by pressing TAB.
+
+ Key(s) Action
+═══════════════════════════════════════════════════════════
+ q Switch the focus back to the main view.
+ j/↓ Select the next filter.
+ k/↑ Select the previous filter.
+ o Create a new "out" filter.
+ i Create a new "in" filter .
+ SPACE Toggle the enabled/disabled state of the currently
+ selected filter.
+ t Toggle the type of filter between "in" and "out".
+ ENTER Edit the selected filter.
+ D Delete the selected filter.
+
+Mouse Support (experimental)
+
+If you are using Xterm, or a compatible terminal, you can use the
+mouse to mark lines of text and move the view by grabbing the
+scrollbar.
+
+NOTE: You need to manually enable this feature by setting the LNAV_EXP
+environment variable to "mouse". F2 toggles mouse support.
+
+SQL Queries (experimental)
+
+Lnav has support for performing SQL queries on log files using the
+Sqlite3 "virtual" table feature. For all supported log file types,
+lnav will create tables that can be queried using the subset of SQL
+that is supported by Sqlite3. For example, to get the top ten URLs
+being accessed in any loaded Apache log files, you can execute:
+
+ ┃;select cs_uri_stem, count(*) as total from access_log
+ ┃ group by cs_uri_stem order by total desc limit 10;
+
+The query result view shows the results and graphs any numeric values
+found in the result, much like the histogram view.
+
+The builtin set of log tables are listed below. Note that only the log
+messages that match a particular format can be queried by a particular
+table. You can find the file format and table name for the top log
+message by looking in the upper right hand corner of the log file
+view.
+
+Some commonly used format tables are:
+
+ Name Description
+════════════════════════════════════════════════════════════════
+ access_log Apache common access log format
+ syslog_log Syslog format
+ strace_log Strace log format
+ generic_log 'Generic' log format. This table contains messages
+ from files that have a very simple format with a
+ leading timestamp followed by the message.
+
+NOTE: You can get a dump of the schema for the internal tables, and
+any attached databases, by running the .schema SQL command.
+
+The columns available for the top log line in the view will
+automatically be displayed after pressing the semicolon ( ; ) key. All
+log tables contain at least the following columns:
+
+ Column Description
+═══════════════════════════════════════════════════════════════════
+ log_line The line number in the file, starting at zero.
+ log_part The name of the partition. You can change this
+ column using an UPDATE SQL statement or with the '
+ partition-name' command. After a value is set,
+ the following log messages will have the same
+ partition name up until another name is set.
+ log_time The time of the log entry.
+ log_idle_msecs The amount of time, in milliseconds, between the
+ current log message and the previous one.
+ log_level The log level (e.g. info, error, etc...).
+ log_mark The bookmark status for the line. This column can
+ be written to using an UPDATE query.
+ log_path The full path to the file.
+ log_text The raw line of text. Note that this column is
+ not included in the result of a 'select *', but it
+ does exist.
+
+The following tables include the basic columns as listed above and
+include a few more columns since the log file format is more
+structured.
+
+ • syslog_log
+
+ Column Description
+ ═════════════════════════════════════════════════════════════════
+ log_hostname The hostname the message was received from.
+ log_procname The name of the process that sent the message.
+ log_pid The process ID of the process that sent the
+ message.
+ • access_log (The column names are the same as those in
+ the Microsoft LogParser tool.)
+
+ Column Description
+ ══════════════════════════════════════════════════════════
+ c_ip The client IP address.
+ cs_username The client user name.
+ cs_method The HTTP method.
+ cs_uri_stem The stem portion of the URI.
+ cs_uri_query The query portion of the URI.
+ cs_version The HTTP version string.
+ sc_status The status number returned to the client.
+ sc_bytes The number of bytes sent to the client.
+ cs_referrer The URL of the referring page.
+ cs_user_agent The user agent string.
+ • strace_log (Currently, you need to run strace with
+ the -tt -T options so there are timestamps for each
+ function call.)
+
+ Column Description
+ ═══════════════════════════════════════════════════════
+ funcname The name of the syscall.
+ result The result code.
+ duration The amount of time spent in the syscall.
+ arg0 - arg9 The arguments passed to the syscall.
+
+These tables are created dynamically and not stored in memory or on
+disk. If you would like to persist some information from the tables,
+you can attach another database and create tables in that database.
+For example, if you wanted to save the results from the earlier
+example of a top ten query into the "/tmp/topten.db" file, you can do:
+
+ ┃;attach database "/tmp/topten.db" as topten;
+ ┃;create table topten.foo as select cs_uri_stem, count(*) as total
+ ┃ from access_log group by cs_uri_stem order by total desc
+ ┃ limit 10;
+
+Dynamic logline Table (experimental)
+
+(NOTE: This feature is still very new and not completely reliable yet,
+use with care.)
+
+For log formats that lack message structure, lnav can parse the log
+message and attempt to extract any data fields that it finds. This
+feature is available through the logline log table. This table is
+dynamically created and defined based on the message at the top of the
+log view. For example, given the following log message from "sudo",
+lnav will create the "logline" table with columns for "TTY", "PWD", "
+USER", and "COMMAND":
+
+ ┃May 24 06:48:38 Tim-Stacks-iMac.local sudo[76387]: stack : TTY=ttys003 ; PWD=/Users/stack/github/lbuild ; USER=root ; COMMAND=/bin/echo Hello, World!
+
+Queries executed against this table will then only return results for
+other log messages that have the same format. So, if you were to
+execute the following query while viewing the above line, you might
+get the following results:
+
+ ┃;select USER,COMMAND from logline;
+
+ USER COMMAND
+═════════════════════════════════
+ root /bin/echo Hello, World!
+ mal /bin/echo Goodbye, World!
+
+The log parser works by examining each message for key/value pairs
+separated by an equal sign (=) or a colon (:). For example, in the
+previous example of a "sudo" message, the parser sees the "USER=root"
+string as a pair where the key is "USER" and the value is "root". If
+no pairs can be found, then anything that looks like a value is
+extracted and assigned a numbered column. For example, the following
+line is from "dhcpd":
+
+ ┃Sep 16 22:35:57 drill dhcpd: DHCPDISCOVER from 00:16:ce:54:4e:f3 via hme3
+
+In this case, the lnav parser recognizes that "DHCPDISCOVER", the MAC
+address and the "hme3" device name are values and not normal words.
+So, it builds a table with three columns for each of these values. The
+regular words in the message, like "from" and "via", are then used to
+find other messages with a similar format.
+
+If you would like to execute queries against log messages of different
+formats at the same time, you can use the 'create-logline-table'
+command to permanently create a table using the top line of the log
+view as a template.
+
+Other SQL Features
+
+Environment variables can be used in SQL statements by prefixing the
+variable name with a dollar-sign ($). For example, to read the value
+of the HOME variable, you can do:
+
+ ┃;SELECT $HOME;
+
+To select the syslog messages that have a hostname field that is equal
+to the HOSTNAME variable:
+
+ ┃;SELECT * FROM syslog_log WHERE log_hostname = $HOSTNAME;
+
+NOTE: Variable substitution is done for fields in the query and is not
+a plain text substitution. For example, the following statement WILL
+NOT WORK:
+
+ ┃;SELECT * FROM $TABLE_NAME; -- Syntax error
+
+Access to lnav's environment variables is also available via the "
+environ" table. The table has two columns (name, value) and can be
+read and written to using SQL SELECT, INSERT, UPDATE, and DELETE
+statements. For example, to set the "FOO" variable to the value "BAR":
+
+ ┃;INSERT INTO environ SELECT 'FOO', 'BAR';
+
+As a more complex example, you can set the variable "LAST" to the last
+syslog line number by doing:
+
+ ┃;INSERT INTO environ SELECT 'LAST', (SELECT max(log_line) FROM syslog_log);
+
+A delete will unset the environment variable:
+
+ ┃;DELETE FROM environ WHERE name='LAST';
+
+The table allows you to easily use the results of a SQL query in lnav
+commands, which is especially useful when scripting lnav.
+
+Contact
+
+For more information, visit the lnav website at:
+
+http://lnav.org[1]
+
+ ┃[1] - http://lnav.org
+
+For support questions, email:
+
+lnav@googlegroups.com[1] support@lnav.org[2]
+
+ ┃[1] - mailto:lnav@googlegroups.com
+ ┃[2] - mailto:support@lnav.org
+
+Command Reference
+
+:adjust-log-time timestamp
+══════════════════════════════════════════════════════════════════════
+ Change the timestamps of the top file to be relative to the given
+ date
+Parameter
+ timestamp The new timestamp for the top line in the view
+
+Examples
+#1 To set the top timestamp to a given date:
+ :adjust-log-time 2017-01-02T05:33:00
+
+
+#2 To set the top timestamp back an hour:
+ :adjust-log-time -1h
+
+
+
+:alt-msg msg
+══════════════════════════════════════════════════════════════════════
+ Display a message in the alternate command position
+Parameter
+ msg The message to display
+See Also
+ :echo, :eval, :redirect-to, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-to, :write-view-to
+Example
+#1 To display 'Press t to switch to the text view' on the bottom right:
+ :alt-msg Press t to switch to the text view
+
+
+
+:append-to path
+══════════════════════════════════════════════════════════════════════
+ Append marked lines in the current view to the given file
+Parameter
+ path The path to the file to append to
+See Also
+ :echo, :pipe-line-to, :pipe-to, :redirect-to, :write-csv-to,
+ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to,
+ :write-table-to, :write-to, :write-view-to
+Example
+#1 To append marked lines to the file /tmp/interesting-lines.txt:
+ :append-to /tmp/interesting-lines.txt
+
+
+
+:clear-comment
+══════════════════════════════════════════════════════════════════════
+ Clear the comment attached to the top log line
+See Also
+ :comment, :tag
+
+:clear-filter-expr
+══════════════════════════════════════════════════════════════════════
+ Clear the filter expression
+See Also
+ :filter-expr, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+
+:clear-highlight pattern
+══════════════════════════════════════════════════════════════════════
+ Remove a previously set highlight regular expression
+Parameter
+ pattern The regular expression previously used with :highlight
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+Example
+#1 To clear the highlight with the pattern 'foobar':
+ :clear-highlight foobar
+
+
+
+:clear-mark-expr
+══════════════════════════════════════════════════════════════════════
+ Clear the mark expression
+See Also
+ :hide-unmarked-lines, :mark, :mark-expr, :next-mark, :prev-mark
+
+:clear-partition
+══════════════════════════════════════════════════════════════════════
+ Clear the partition the top line is a part of
+
+
+:close
+══════════════════════════════════════════════════════════════════════
+ Close the top file in the view
+
+
+:comment text
+══════════════════════════════════════════════════════════════════════
+ Attach a comment to the top log line
+Parameter
+ text The comment text
+See Also
+ :clear-comment, :tag
+Example
+#1 To add the comment 'This is where it all went wrong' to the top line:
+ :comment This is where it all went wrong
+
+
+
+:config option [value]
+══════════════════════════════════════════════════════════════════════
+ Read or write a configuration option
+Parameters
+ option The path to the option to read or write
+ value The value to write. If not given, the current value is
+ returned
+See Also
+ :reset-config
+Examples
+#1 To read the configuration of the '/ui/clock-format' option:
+ :config /ui/clock-format
+
+
+#2 To set the '/ui/dim-text' option to 'false':
+ :config /ui/dim-text false
+
+
+
+:create-logline-table table-name
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table using the top line of the log view as a template
+
+Parameter
+ table-name The name for the new table
+See Also
+ :create-search-table, :create-search-table, :write-csv-to,
+ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to,
+ :write-table-to, :write-view-to
+Example
+#1 To create a logline-style table named 'task_durations':
+ :create-logline-table task_durations
+
+
+
+:create-search-table table-name [pattern]
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
+Parameters
+ table-name The name of the table to create
+ pattern The regular expression used to capture the table
+ columns. If not given, the current search pattern is
+ used.
+See Also
+ :create-logline-table, :create-logline-table, :delete-search-table,
+ :delete-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To create a table named 'task_durations' that matches log messages with the pattern '
+ duration=(?<duration>\d+)':
+ :create-search-table task_durations duration=(?<duration>\d+)
+
+
+
+:current-time
+══════════════════════════════════════════════════════════════════════
+ Print the current time in human-readable form and seconds since the
+ epoch
+
+
+:delete-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Delete the filter created with :filter-in or :filter-out
+Parameter
+ pattern The regular expression to match
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To delete the filter with the pattern 'last message repeated':
+ :delete-filter last message repeated
+
+
+
+:delete-logline-table table-name
+══════════════════════════════════════════════════════════════════════
+ Delete a table created with create-logline-table
+Parameter
+ table-name The name of the table to delete
+See Also
+ :create-logline-table, :create-logline-table, :create-search-table,
+ :create-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To delete the logline-style table named 'task_durations':
+ :delete-logline-table task_durations
+
+
+
+:delete-search-table table-name
+══════════════════════════════════════════════════════════════════════
+ Create an SQL table based on a regex search
+Parameter
+ table-name The name of the table to create
+See Also
+ :create-logline-table, :create-logline-table, :create-search-table,
+ :create-search-table, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-view-to
+Example
+#1 To delete the search table named 'task_durations':
+ :delete-search-table task_durations
+
+
+
+:delete-tags tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Remove the given tags from all log lines
+Parameter
+ tag The tags to delete
+See Also
+ :comment, :tag
+Example
+#1 To remove the tags '#BUG123' and '#needs-review' from all log lines:
+ :delete-tags #BUG123 #needs-review
+
+
+
+:disable-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Disable a filter created with filter-in/filter-out
+Parameter
+ pattern The regular expression used in the filter command
+See Also
+ :enable-filter, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To disable the filter with the pattern 'last message repeated':
+ :disable-filter last message repeated
+
+
+
+:disable-word-wrap
+══════════════════════════════════════════════════════════════════════
+ Disable word-wrapping for the current view
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+
+:echo msg
+══════════════════════════════════════════════════════════════════════
+ Echo the given message to the screen or, if :redirect-to has been
+ called, to output file specified in the redirect. Variable
+ substitution is performed on the message. Use a backslash to escape
+ any special characters, like '$'
+Parameter
+ msg The message to display
+See Also
+ :alt-msg, :append-to, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-json-to,
+ :write-json-to, :write-jsonlines-to, :write-jsonlines-to,
+ :write-raw-to, :write-raw-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-to, :write-to, :write-view-to,
+ :write-view-to
+Example
+#1 To output 'Hello, World!':
+ :echo Hello, World!
+
+
+
+:enable-filter pattern
+══════════════════════════════════════════════════════════════════════
+ Enable a previously created and disabled filter
+Parameter
+ pattern The regular expression used in the filter command
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To enable the disabled filter with the pattern 'last message repeated':
+ :enable-filter last message repeated
+
+
+
+:enable-word-wrap
+══════════════════════════════════════════════════════════════════════
+ Enable word-wrapping for the current view
+See Also
+ :disable-word-wrap, :hide-fields, :highlight
+
+:eval command
+══════════════════════════════════════════════════════════════════════
+ Evaluate the given command/query after doing environment variable
+ substitution
+Parameter
+ command The command or query to perform substitution on.
+See Also
+ :alt-msg, :echo, :redirect-to, :write-csv-to, :write-json-to,
+ :write-jsonlines-to, :write-raw-to, :write-screen-to, :write-table-to,
+ :write-to, :write-view-to
+Example
+#1 To substitute the table name from a variable:
+ :eval ;SELECT * FROM ${table}
+
+
+
+:filter-expr expr
+══════════════════════════════════════════════════════════════════════
+ Set the filter expression
+Parameter
+ expr The SQL expression to evaluate for each log message. The
+ message values can be accessed using column names prefixed
+ with a colon
+See Also
+ :clear-filter-expr, :filter-in, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Examples
+#1 To set a filter expression that matched syslog messages from 'syslogd':
+ :filter-expr :log_procname = 'syslogd'
+
+
+#2 To set a filter expression that matches log messages where 'id' is followed by a number
+ and contains the string 'foo':
+ :filter-expr :log_body REGEXP 'id\d+' AND :log_body REGEXP 'foo'
+
+
+
+:filter-in pattern
+══════════════════════════════════════════════════════════════════════
+ Only show lines that match the given regular expression in the
+ current view
+Parameter
+ pattern The regular expression to match
+See Also
+ :delete-filter, :disable-filter, :filter-out, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To filter out log messages that do not have the string 'dhclient':
+ :filter-in dhclient
+
+
+
+:filter-out pattern
+══════════════════════════════════════════════════════════════════════
+ Remove lines that match the given regular expression in the current
+ view
+Parameter
+ pattern The regular expression to match
+See Also
+ :delete-filter, :disable-filter, :filter-in, :hide-lines-after,
+ :hide-lines-before, :hide-unmarked-lines, :toggle-filtering
+Example
+#1 To filter out log messages that contain the string 'last message repeated':
+ :filter-out last message repeated
+
+
+
+:goto line#|N%|date
+══════════════════════════════════════════════════════════════════════
+ Go to the given location in the top view
+Parameter
+ line#|N%|date A line number, percent into the file, or a timestamp
+
+See Also
+ :next-location, :next-mark, :prev-location, :prev-mark, :relative-goto
+Examples
+#1 To go to line 22:
+ :goto 22
+
+
+#2 To go to the line 75% of the way into the view:
+ :goto 75%
+
+
+#3 To go to the first message on the first day of 2017:
+ :goto 2017-01-01
+
+
+
+:help
+══════════════════════════════════════════════════════════════════════
+ Open the help text view
+
+
+:hide-fields field-name1 [... field-nameN]
+══════════════════════════════════════════════════════════════════════
+ Hide log message fields by replacing them with an ellipsis
+Parameter
+ field-name The name of the field to hide in the format for the top
+ log line. A qualified name can be used where the field
+ name is prefixed by the format name and a dot to hide
+ any field.
+See Also
+ :enable-word-wrap, :highlight, :show-fields
+Examples
+#1 To hide the log_procname fields in all formats:
+ :hide-fields log_procname
+
+
+#2 To hide only the log_procname field in the syslog format:
+ :hide-fields syslog_log.log_procname
+
+
+
+:hide-file path
+══════════════════════════════════════════════════════════════════════
+ Hide the given file(s) and skip indexing until it is shown again.
+ If no path is given, the current file in the view is hidden
+Parameter
+ path A path or glob pattern that specifies the files to hide
+
+
+:hide-lines-after date
+══════════════════════════════════════════════════════════════════════
+ Hide lines that come after the given date
+Parameter
+ date An absolute or relative date
+See Also
+ :filter-in, :filter-out, :hide-lines-before, :hide-unmarked-lines,
+ :show-lines-before-and-after, :toggle-filtering
+Examples
+#1 To hide the lines after the top line in the view:
+ :hide-lines-after here
+
+
+#2 To hide the lines after 6 AM today:
+ :hide-lines-after 6am
+
+
+
+:hide-lines-before date
+══════════════════════════════════════════════════════════════════════
+ Hide lines that come before the given date
+Parameter
+ date An absolute or relative date
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-unmarked-lines,
+ :show-lines-before-and-after, :toggle-filtering
+Examples
+#1 To hide the lines before the top line in the view:
+ :hide-lines-before here
+
+
+#2 To hide the log messages before 6 AM today:
+ :hide-lines-before 6am
+
+
+
+:hide-unmarked-lines
+══════════════════════════════════════════════════════════════════════
+ Hide lines that have not been bookmarked
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before, :mark,
+ :next-mark, :prev-mark, :toggle-filtering
+
+:highlight pattern
+══════════════════════════════════════════════════════════════════════
+ Add coloring to log messages fragments that match the given regular
+ expression
+Parameter
+ pattern The regular expression to match
+See Also
+ :clear-highlight, :enable-word-wrap, :hide-fields
+Example
+#1 To highlight numbers with three or more digits:
+ :highlight \d{3,}
+
+
+
+:load-session
+══════════════════════════════════════════════════════════════════════
+ Load the latest session state
+
+
+:mark
+══════════════════════════════════════════════════════════════════════
+ Toggle the bookmark state for the top line in the current view
+See Also
+ :hide-unmarked-lines, :next-mark, :prev-mark
+
+:mark-expr expr
+══════════════════════════════════════════════════════════════════════
+ Set the bookmark expression
+Parameter
+ expr The SQL expression to evaluate for each log message. The
+ message values can be accessed using column names prefixed
+ with a colon
+See Also
+ :clear-mark-expr, :hide-unmarked-lines, :mark, :next-mark, :prev-mark
+Example
+#1 To mark lines from 'dhclient' that mention 'eth0':
+ :mark-expr :log_procname = 'dhclient' AND :log_body LIKE '%eth0%'
+
+
+
+:next-location
+══════════════════════════════════════════════════════════════════════
+ Move to the next position in the location history
+See Also
+ :goto, :next-mark, :prev-location, :prev-mark, :relative-goto
+
+:next-mark type1 [... typeN]
+══════════════════════════════════════════════════════════════════════
+ Move to the next bookmark of the given type in the current view
+Parameter
+ type The type of bookmark -- error, warning, search, user, file,
+ meta
+See Also
+ :goto, :hide-unmarked-lines, :mark, :next-location, :prev-location,
+ :prev-mark, :prev-mark, :relative-goto
+Example
+#1 To go to the next error:
+ :next-mark error
+
+
+
+:open path1 [... pathN]
+══════════════════════════════════════════════════════════════════════
+ Open the given file(s) in lnav. Opening files on machines
+ accessible via SSH can be done using the syntax: [user@]host:/path/
+ to/logs
+Parameter
+ path The path to the file to open
+
+Examples
+#1 To open the file '/path/to/file':
+ :open /path/to/file
+
+
+#2 To open the remote file '/var/log/syslog.log':
+ :open dean@host1.example.com:/var/log/syslog.log
+
+
+
+:partition-name name
+══════════════════════════════════════════════════════════════════════
+ Mark the top line in the log view as the start of a new partition
+ with the given name
+Parameter
+ name The name for the new partition
+
+Example
+#1 To mark the top line as the start of the partition named 'boot #1':
+ :partition-name boot #1
+
+
+
+:pipe-line-to shell-cmd
+══════════════════════════════════════════════════════════════════════
+ Pipe the top line to the given shell command
+Parameter
+ shell-cmd The shell command-line to execute
+See Also
+ :append-to, :echo, :pipe-to, :redirect-to, :write-csv-to,
+ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to,
+ :write-table-to, :write-to, :write-view-to
+Example
+#1 To write the top line to 'sed' for processing:
+ :pipe-line-to sed -e 's/foo/bar/g'
+
+
+
+:pipe-to shell-cmd
+══════════════════════════════════════════════════════════════════════
+ Pipe the marked lines to the given shell command
+Parameter
+ shell-cmd The shell command-line to execute
+See Also
+ :append-to, :echo, :pipe-line-to, :redirect-to, :write-csv-to,
+ :write-json-to, :write-jsonlines-to, :write-raw-to, :write-screen-to,
+ :write-table-to, :write-to, :write-view-to
+Example
+#1 To write marked lines to 'sed' for processing:
+ :pipe-to sed -e s/foo/bar/g
+
+
+
+:prev-location
+══════════════════════════════════════════════════════════════════════
+ Move to the previous position in the location history
+See Also
+ :goto, :next-location, :next-mark, :prev-mark, :relative-goto
+
+:prev-mark type1 [... typeN]
+══════════════════════════════════════════════════════════════════════
+ Move to the previous bookmark of the given type in the current view
+Parameter
+ type The type of bookmark -- error, warning, search, user, file,
+ meta
+See Also
+ :goto, :hide-unmarked-lines, :mark, :next-location, :next-mark,
+ :next-mark, :prev-location, :relative-goto
+Example
+#1 To go to the previous error:
+ :prev-mark error
+
+
+
+:prompt type [--alt] [prompt] [initial-value]
+══════════════════════════════════════════════════════════════════════
+ Open the given prompt
+Parameters
+ type The type of prompt -- command, script, search, sql,
+ user
+ --alt Perform the alternate action for this prompt by
+ default
+ prompt The prompt to display
+ initial-value The initial value to fill in for the prompt
+
+Examples
+#1 To open the command prompt with 'filter-in' already filled in:
+ :prompt command : 'filter-in '
+
+
+#2 To ask the user a question:
+ :prompt user 'Are you sure? '
+
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:quit
+══════════════════════════════════════════════════════════════════════
+ Quit lnav
+
+
+:redirect-to [path]
+══════════════════════════════════════════════════════════════════════
+ Redirect the output of commands that write to stdout to the given
+ file
+Parameter
+ path The path to the file to write. If not specified, the current
+ redirect will be cleared
+See Also
+ :alt-msg, :append-to, :echo, :echo, :eval, :pipe-line-to, :pipe-to,
+ :write-csv-to, :write-csv-to, :write-json-to, :write-json-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-to, :write-to, :write-view-to, :write-view-to
+Example
+#1 To write the output of lnav commands to the file /tmp/script-output.txt:
+ :redirect-to /tmp/script-output.txt
+
+
+
+:redraw
+══════════════════════════════════════════════════════════════════════
+ Do a full redraw of the screen
+
+
+:relative-goto line-count|N%
+══════════════════════════════════════════════════════════════════════
+ Move the current view up or down by the given amount
+Parameter
+ line-count|N% The amount to move the view by.
+See Also
+ :goto, :next-location, :next-mark, :prev-location, :prev-mark
+Examples
+#1 To move 22 lines down in the view:
+ :relative-goto +22
+
+
+#2 To move 10 percent back in the view:
+ :relative-goto -10%
+
+
+
+:reset-config option
+══════════════════════════════════════════════════════════════════════
+ Reset the configuration option to its default value
+Parameter
+ option The path to the option to reset
+See Also
+ :config
+Example
+#1 To reset the '/ui/clock-format' option back to the builtin default:
+ :reset-config /ui/clock-format
+
+
+
+:reset-session
+══════════════════════════════════════════════════════════════════════
+ Reset the session state, clearing all filters, highlights, and
+ bookmarks
+
+
+:save-session
+══════════════════════════════════════════════════════════════════════
+ Save the current state as a session
+
+
+:session lnav-command
+══════════════════════════════════════════════════════════════════════
+ Add the given command to the session file (~/.lnav/session)
+Parameter
+ lnav-command The lnav command to save.
+
+Example
+#1 To add the command ':highlight foobar' to the session file:
+ :session :highlight foobar
+
+
+
+:set-min-log-level log-level
+══════════════════════════════════════════════════════════════════════
+ Set the minimum log level to display in the log view
+Parameter
+ log-level The new minimum log level
+
+Example
+#1 To set the minimum log level displayed to error:
+ :set-min-log-level error
+
+
+
+:show-fields field-name1 [... field-nameN]
+══════════════════════════════════════════════════════════════════════
+ Show log message fields that were previously hidden
+Parameter
+ field-name The name of the field to show
+See Also
+ :enable-word-wrap, :hide-fields, :highlight
+Example
+#1 To show all the log_procname fields in all formats:
+ :show-fields log_procname
+
+
+
+:show-file path
+══════════════════════════════════════════════════════════════════════
+ Show the given file(s) and resume indexing.
+Parameter
+ path The path or glob pattern that specifies the files to show
+
+
+:show-lines-before-and-after
+══════════════════════════════════════════════════════════════════════
+ Show lines that were hidden by the 'hide-lines' commands
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :toggle-filtering
+
+:show-only-this-file
+══════════════════════════════════════════════════════════════════════
+ Show only the file for the top line in the view
+
+
+:show-unmarked-lines
+══════════════════════════════════════════════════════════════════════
+ Show lines that have not been bookmarked
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines, :hide-unmarked-lines, :mark, :next-mark,
+ :prev-mark, :toggle-filtering
+
+:spectrogram field-name
+══════════════════════════════════════════════════════════════════════
+ Visualize the given message field using a spectrogram
+Parameter
+ field-name The name of the numeric field to visualize.
+
+Example
+#1 To visualize the sc_bytes field in the access_log format:
+ :spectrogram sc_bytes
+
+
+
+:summarize column-name
+══════════════════════════════════════════════════════════════════════
+ Execute a SQL query that computes the characteristics of the values
+ in the given column
+Parameter
+ column-name The name of the column to analyze.
+
+Example
+#1 To get a summary of the sc_bytes column in the access_log table:
+ :summarize sc_bytes
+
+
+
+:switch-to-view view-name
+══════════════════════════════════════════════════════════════════════
+ Switch to the given view
+Parameter
+ view-name The name of the view to switch to.
+
+Example
+#1 To switch to the 'schema' view:
+ :switch-to-view schema
+
+
+
+:tag tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Attach tags to the top log line
+Parameter
+ tag The tags to attach
+See Also
+ :comment, :delete-tags, :untag
+Example
+#1 To add the tags '#BUG123' and '#needs-review' to the top line:
+ :tag #BUG123 #needs-review
+
+
+
+:toggle-filtering
+══════════════════════════════════════════════════════════════════════
+ Toggle the filtering flag for the current view
+See Also
+ :filter-in, :filter-out, :hide-lines-after, :hide-lines-before,
+ :hide-unmarked-lines
+
+:toggle-view view-name
+══════════════════════════════════════════════════════════════════════
+ Switch to the given view or, if it is already displayed, switch to
+ the previous view
+Parameter
+ view-name The name of the view to toggle the display of.
+
+Example
+#1 To switch to the 'schema' view if it is not displayed or switch back to the previous
+ view:
+ :toggle-view schema
+
+
+
+:unix-time seconds
+══════════════════════════════════════════════════════════════════════
+ Convert epoch time to a human-readable form
+Parameter
+ seconds The epoch timestamp to convert
+
+Example
+#1 To convert the epoch time 1490191111:
+ :unix-time 1490191111
+
+
+
+:untag tag1 [... tagN]
+══════════════════════════════════════════════════════════════════════
+ Detach tags from the top log line
+Parameter
+ tag The tags to detach
+See Also
+ :comment, :tag
+Example
+#1 To remove the tags '#BUG123' and '#needs-review' from the top line:
+ :untag #BUG123 #needs-review
+
+
+
+:write-table-to path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in a tabular format
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to
+Example
+#1 To write SQL results as text to /tmp/table.txt:
+ :write-table-to /tmp/table.txt
+
+
+
+:write-csv-to path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in CSV format
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-json-to, :write-json-to, :write-json-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-jsonlines-to,
+ :write-raw-to, :write-raw-to, :write-raw-to, :write-screen-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-table-to, :write-to, :write-to, :write-view-to, :write-view-to,
+ :write-view-to
+Example
+#1 To write SQL results as CSV to /tmp/table.csv:
+ :write-csv-to /tmp/table.csv
+
+
+
+:write-json-to path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in JSON format
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-jsonlines-to,
+ :write-raw-to, :write-raw-to, :write-raw-to, :write-screen-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-table-to, :write-to, :write-to, :write-view-to, :write-view-to,
+ :write-view-to
+Example
+#1 To write SQL results as JSON to /tmp/table.json:
+ :write-json-to /tmp/table.json
+
+
+
+:write-jsonlines-to path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in JSON Lines format
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-raw-to,
+ :write-raw-to, :write-raw-to, :write-screen-to, :write-screen-to,
+ :write-screen-to, :write-table-to, :write-table-to, :write-table-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to
+Example
+#1 To write SQL results as JSON Lines to /tmp/table.json:
+ :write-jsonlines-to /tmp/table.json
+
+
+
+:write-raw-to [--view={log,db}] path
+══════════════════════════════════════════════════════════════════════
+ In the log view, write the original log file content of the marked
+ messages to the file. In the DB view, the contents of the cells are
+ written to the output file.
+Parameters
+ --view={log,db} The view to use as the source of data
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-screen-to,
+ :write-screen-to, :write-screen-to, :write-table-to, :write-table-to,
+ :write-table-to, :write-to, :write-to, :write-view-to, :write-view-to,
+ :write-view-to
+Example
+#1 To write the marked lines in the log view to /tmp/table.txt:
+ :write-raw-to /tmp/table.txt
+
+
+
+:write-screen-to path
+══════════════════════════════════════════════════════════════════════
+ Write the displayed text or SQL results to the given file without
+ any formatting
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-table-to, :write-table-to, :write-table-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to
+Example
+#1 To write only the displayed text to /tmp/table.txt:
+ :write-screen-to /tmp/table.txt
+
+
+
+:write-table-to path
+══════════════════════════════════════════════════════════════════════
+ Write SQL results to the given file in a tabular format
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-to, :write-to, :write-view-to, :write-view-to, :write-view-to
+Example
+#1 To write SQL results as text to /tmp/table.txt:
+ :write-table-to /tmp/table.txt
+
+
+
+:write-to path
+══════════════════════════════════════════════════════════════════════
+ Overwrite the given file with any marked lines in the current view
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :echo, :echo, :eval, :pipe-line-to, :pipe-to,
+ :redirect-to, :redirect-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-raw-to, :write-raw-to, :write-screen-to,
+ :write-screen-to, :write-table-to, :write-table-to, :write-view-to,
+ :write-view-to
+Example
+#1 To write marked lines to the file /tmp/interesting-lines.txt:
+ :write-to /tmp/interesting-lines.txt
+
+
+
+:write-view-to path
+══════════════════════════════════════════════════════════════════════
+ Write the text in the top view to the given file without any
+ formatting
+Parameter
+ path The path to the file to write
+See Also
+ :alt-msg, :append-to, :create-logline-table, :create-search-table,
+ :echo, :echo, :eval, :pipe-line-to, :pipe-to, :redirect-to,
+ :redirect-to, :write-csv-to, :write-csv-to, :write-csv-to,
+ :write-json-to, :write-json-to, :write-json-to, :write-jsonlines-to,
+ :write-jsonlines-to, :write-jsonlines-to, :write-raw-to, :write-raw-to,
+ :write-raw-to, :write-screen-to, :write-screen-to, :write-screen-to,
+ :write-table-to, :write-table-to, :write-table-to, :write-to,
+ :write-to
+Example
+#1 To write the top view to /tmp/table.txt:
+ :write-view-to /tmp/table.txt
+
+
+
+:zoom-to zoom-level
+══════════════════════════════════════════════════════════════════════
+ Zoom the histogram view to the given level
+Parameter
+ zoom-level The zoom level
+
+Example
+#1 To set the zoom level to '1-week':
+ :zoom-to 1-week
+
+
+SQL Reference
+
+CAST(expr AS type-name)
+══════════════════════════════════════════════════════════════════════
+ Convert the value of the given expression to a different storage
+ class specified by type-name.
+Parameters
+ expr The value to convert.
+ type-name The name of the type to convert to.
+
+Example
+#1 To cast the value 1.23 as an integer:
+ ;SELECT CAST(1.23 AS INTEGER)
+
+
+
+OVER([base-window-name] PARTITION BY expr, ... ORDER BY expr, ...,
+ [frame-spec])
+══════════════════════════════════════════════════════════════════════
+ Executes the preceding function over a window
+Parameters
+ base-window-name The name of the window definition
+ expr The values to use for partitioning
+ expr The values used to order the rows in the window
+ frame-spec Determines which output rows are read by an
+ aggregate window function
+
+
+abs(x)
+══════════════════════════════════════════════════════════════════════
+ Return the absolute value of the argument
+Parameter
+ x The number to convert
+See Also
+ acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the absolute value of -1:
+ ;SELECT abs(-1)
+
+
+
+acos(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arccosine of a number, in radians
+Parameter
+ num A cosine value that is between -1 and 1
+See Also
+ abs(), acosh(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arccosine of 0.2:
+ ;SELECT acos(0.2)
+
+
+
+acosh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arccosine of a number
+Parameter
+ num A number that is one or more
+See Also
+ abs(), acos(), asin(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arccosine of 1.2:
+ ;SELECT acosh(1.2)
+
+
+
+asin(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arcsine of a number, in radians
+Parameter
+ num A sine value that is between -1 and 1
+See Also
+ abs(), acos(), acosh(), asinh(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arcsine of 0.2:
+ ;SELECT asin(0.2)
+
+
+
+asinh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arcsine of a number
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), atan(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arcsine of 0.2:
+ ;SELECT asinh(0.2)
+
+
+
+atan(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the arctangent of a number, in radians
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan2(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the arctangent of 0.2:
+ ;SELECT atan(0.2)
+
+
+
+atan2(y, x)
+══════════════════════════════════════════════════════════════════════
+ Returns the angle in the plane between the positive X axis and the
+ ray from (0, 0) to the point (x, y)
+Parameters
+ y The y coordinate of the point
+ x The x coordinate of the point
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atanh(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the angle, in degrees, for the point at (5, 5):
+ ;SELECT degrees(atan2(5, 5))
+
+
+
+atanh(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the hyperbolic arctangent of a number
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atn2(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the hyperbolic arctangent of 0.2:
+ ;SELECT atanh(0.2)
+
+
+
+atn2(y, x)
+══════════════════════════════════════════════════════════════════════
+ Returns the angle in the plane between the positive X axis and the
+ ray from (0, 0) to the point (x, y)
+Parameters
+ y The y coordinate of the point
+ x The x coordinate of the point
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ avg(), ceil(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the angle, in degrees, for the point at (5, 5):
+ ;SELECT degrees(atn2(5, 5))
+
+
+
+avg(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the average value of all non-NULL numbers within a group.
+Parameter
+ X The value to compute the average of.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), ceil(), degrees(), exp(), floor(), log(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the average of the column 'ex_duration' from the table 'lnav_example_log':
+ ;SELECT avg(ex_duration) FROM lnav_example_log
+
+
+#2 To get the average of the column 'ex_duration' from the table 'lnav_example_log' when
+ grouped by 'ex_procname':
+ ;SELECT ex_procname, avg(ex_duration) FROM lnav_example_log GROUP BY ex_procname
+
+
+
+basename(path)
+══════════════════════════════════════════════════════════════════════
+ Extract the base portion of a pathname.
+Parameter
+ path The path
+See Also
+ dirname(), joinpath(), readlink(), realpath()
+Examples
+#1 To get the base of a plain file name:
+ ;SELECT basename('foobar')
+
+
+#2 To get the base of a path:
+ ;SELECT basename('foo/bar')
+
+
+#3 To get the base of a directory:
+ ;SELECT basename('foo/bar/')
+
+
+#4 To get the base of an empty string:
+ ;SELECT basename('')
+
+
+#5 To get the base of a Windows path:
+ ;SELECT basename('foo\bar')
+
+
+#6 To get the base of the root directory:
+ ;SELECT basename('/')
+
+
+
+ceil(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the smallest integer that is not less than the argument
+Parameter
+ num The number to raise to the ceiling
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), degrees(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the ceiling of 1.23:
+ ;SELECT ceil(1.23)
+
+
+
+changes()
+══════════════════════════════════════════════════════════════════════
+ The number of database rows that were changed, inserted, or deleted
+ by the most recent statement.
+
+
+char(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns a string composed of characters having the given unicode
+ code point values
+Parameter
+ X The unicode code point values
+See Also
+ charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), upper(), xpath()
+Example
+#1 To get a string with the code points 0x48 and 0x49:
+ ;SELECT char(0x48, 0x49)
+
+
+
+charindex(needle, haystack, [start])
+══════════════════════════════════════════════════════════════════════
+ Finds the first occurrence of the needle within the haystack and
+ returns the number of prior characters plus 1, or 0 if Y is nowhere
+ found within X
+Parameters
+ needle The string to look for in the haystack
+ haystack The string to search within
+ start The one-based index within the haystack to start the
+ search
+See Also
+ char(), endswith(), extract(), group_concat(), group_spooky_hash(),
+ gunzip(), gzip(), humanize_file_size(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To search for the string 'abc' within 'abcabc' and starting at position 2:
+ ;SELECT charindex('abc', 'abcabc', 2)
+
+
+#2 To search for the string 'abc' within 'abcdef' and starting at position 2:
+ ;SELECT charindex('abc', 'abcdef', 2)
+
+
+
+coalesce(X, Y, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of its first non-NULL argument, or NULL if all
+ arguments are NULL
+Parameters
+ X A value to check for NULL-ness
+ Y A value to check for NULL-ness
+
+Example
+#1 To get the first non-null value from three parameters:
+ ;SELECT coalesce(null, 0, null)
+
+
+
+count(X)
+══════════════════════════════════════════════════════════════════════
+ If the argument is '*', the total number of rows in the group is
+ returned. Otherwise, the number of times the argument is non-NULL.
+Parameter
+ X The value to count.
+
+Examples
+#1 To get the count of the non-NULL rows of 'lnav_example_log':
+ ;SELECT count(*) FROM lnav_example_log
+
+
+#2 To get the count of the non-NULL values of 'log_part' from 'lnav_example_log':
+ ;SELECT count(log_part) FROM lnav_example_log
+
+
+
+cume_dist()
+══════════════════════════════════════════════════════════════════════
+ Returns the cumulative distribution
+See Also
+ dense_rank(), first_value(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+date(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date in this format: YYYY-MM-DD.
+Parameters
+ timestring The string to convert to a date.
+ modifier A transformation that is applied to the value to the
+ left.
+See Also
+ datetime(), julianday(), strftime(), time(), timediff(), timeslice()
+Examples
+#1 To get the date portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT date('2017-01-02T03:04:05')
+
+
+#2 To get the date portion of the timestamp '2017-01-02T03:04:05' plus one day:
+ ;SELECT date('2017-01-02T03:04:05', '+1 day')
+
+
+#3 To get the date portion of the epoch timestamp 1491341842:
+ ;SELECT date(1491341842, 'unixepoch')
+
+
+
+datetime(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date and time in this format: YYYY-MM-DD HH:MM:SS.
+Parameters
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the value to the
+ left.
+See Also
+ date(), julianday(), strftime(), time(), timediff(), timeslice()
+Examples
+#1 To get the date and time portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT datetime('2017-01-02T03:04:05')
+
+
+#2 To get the date and time portion of the timestamp '2017-01-02T03:04:05' plus one minute
+ :
+ ;SELECT datetime('2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To get the date and time portion of the epoch timestamp 1491341842:
+ ;SELECT datetime(1491341842, 'unixepoch')
+
+
+
+degrees(radians)
+══════════════════════════════════════════════════════════════════════
+ Converts radians to degrees
+Parameter
+ radians The radians value to convert to degrees
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), exp(), floor(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To convert PI to degrees:
+ ;SELECT degrees(pi())
+
+
+
+dense_rank()
+══════════════════════════════════════════════════════════════════════
+ Returns the row_number() of the first peer in each group without
+ gaps
+See Also
+ cume_dist(), first_value(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+dirname(path)
+══════════════════════════════════════════════════════════════════════
+ Extract the directory portion of a pathname.
+Parameter
+ path The path
+See Also
+ basename(), joinpath(), readlink(), realpath()
+Examples
+#1 To get the directory of a relative file path:
+ ;SELECT dirname('foo/bar')
+
+
+#2 To get the directory of an absolute file path:
+ ;SELECT dirname('/foo/bar')
+
+
+#3 To get the directory of a file in the root directory:
+ ;SELECT dirname('/bar')
+
+
+#4 To get the directory of a Windows path:
+ ;SELECT dirname('foo\bar')
+
+
+#5 To get the directory of an empty path:
+ ;SELECT dirname('')
+
+
+
+endswith(str, suffix)
+══════════════════════════════════════════════════════════════════════
+ Test if a string ends with the given suffix
+Parameters
+ str The string to test
+ suffix The suffix to check in the string
+See Also
+ char(), charindex(), extract(), group_concat(), group_spooky_hash(),
+ gunzip(), gzip(), humanize_file_size(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To test if the string 'notbad.jpg' ends with '.jpg':
+ ;SELECT endswith('notbad.jpg', '.jpg')
+
+
+#2 To test if the string 'notbad.png' starts with '.jpg':
+ ;SELECT endswith('notbad.png', '.jpg')
+
+
+
+exp(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the value of e raised to the power of x
+Parameter
+ x The exponent
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), floor(), log(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To raise e to 2:
+ ;SELECT exp(2)
+
+
+
+extract(str)
+══════════════════════════════════════════════════════════════════════
+ Automatically Parse and extract data from a string
+Parameter
+ str The string to parse
+See Also
+ char(), charindex(), endswith(), group_concat(), group_spooky_hash(),
+ gunzip(), gzip(), humanize_file_size(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To extract key/value pairs from a string:
+ ;SELECT extract('foo=1 bar=2 name="Rolo Tomassi"')
+
+
+#2 To extract columnar data from a string:
+ ;SELECT extract('1.0 abc 2.0')
+
+
+
+first_value(expr)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the first
+ row in the window frame.
+Parameter
+ expr The expression to execute over the first row
+See Also
+ cume_dist(), dense_rank(), lag(), last_value(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+floor(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the largest integer that is not greater than the argument
+Parameter
+ num The number to lower to the floor
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), log(), log10(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the floor of 1.23:
+ ;SELECT floor(1.23)
+
+
+
+generate_series(start, stop, [step])
+══════════════════════════════════════════════════════════════════════
+ A table-valued-function that returns the whole numbers between a
+ lower and upper bound, inclusive
+Parameters
+ start The starting point of the series
+ stop The stopping point of the series
+ step The increment between each value
+Result
+ value The number in the series
+
+Examples
+#1 To generate the numbers in the range [10, 14]:
+ ;SELECT value FROM generate_series(10, 14)
+
+
+#2 To generate every other number in the range [10, 14]:
+ ;SELECT value FROM generate_series(10, 14, 2)
+
+
+#3 To count down from five to 1:
+ ;SELECT value FROM generate_series(1, 5, -1)
+
+
+
+gethostbyaddr(hostname)
+══════════════════════════════════════════════════════════════════════
+ Get the hostname for the given IP address
+Parameter
+ hostname The IP address to lookup.
+See Also
+ gethostbyname()
+Example
+#1 To get the hostname for the IP '127.0.0.1':
+ ;SELECT gethostbyaddr('127.0.0.1')
+
+
+
+gethostbyname(hostname)
+══════════════════════════════════════════════════════════════════════
+ Get the IP address for the given hostname
+Parameter
+ hostname The DNS hostname to lookup.
+See Also
+ gethostbyaddr()
+Example
+#1 To get the IP address for 'localhost':
+ ;SELECT gethostbyname('localhost')
+
+
+
+glob(pattern, str)
+══════════════════════════════════════════════════════════════════════
+ Match a string against Unix glob pattern
+Parameters
+ pattern The glob pattern
+ str The string to match
+
+Example
+#1 To test if the string 'abc' matches the glob 'a*':
+ ;SELECT glob('a*', 'abc')
+
+
+
+group_concat(X, [sep])
+══════════════════════════════════════════════════════════════════════
+ Returns a string which is the concatenation of all non-NULL values
+ of X separated by a comma or the given separator.
+Parameters
+ X The value to concatenate.
+ sep The separator to place between the values.
+See Also
+ char(), charindex(), endswith(), extract(), group_spooky_hash(),
+ gunzip(), gzip(), humanize_file_size(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To concatenate the values of the column 'ex_procname' from the table 'lnav_example_log'
+ :
+ ;SELECT group_concat(ex_procname) FROM lnav_example_log
+
+
+#2 To join the values of the column 'ex_procname' using the string ', ':
+ ;SELECT group_concat(ex_procname, ', ') FROM lnav_example_log
+
+
+#3 To concatenate the distinct values of the column 'ex_procname' from the table '
+ lnav_example_log':
+ ;SELECT group_concat(DISTINCT ex_procname) FROM lnav_example_log
+
+
+
+group_spooky_hash(str, ...)
+══════════════════════════════════════════════════════════════════════
+ Compute the hash value for the given arguments
+Parameter
+ str The string to hash
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(), gunzip(),
+ gzip(), humanize_file_size(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To produce a hash of all of the values of 'column1':
+ ;SELECT group_spooky_hash(column1) FROM (VALUES ('abc'), ('123'))
+
+
+
+gunzip(b, ...)
+══════════════════════════════════════════════════════════════════════
+ Decompress a gzip file
+Parameter
+ b The blob to decompress
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gzip(), humanize_file_size(), instr(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+
+gzip(value, ...)
+══════════════════════════════════════════════════════════════════════
+ Compress a string into a gzip file
+Parameter
+ value The value to compress
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), upper(), xpath()
+
+hex(X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string which is the upper-case hexadecimal rendering of
+ the content of its argument.
+Parameter
+ X The blob to convert to hexadecimal
+
+Example
+#1 To get the hexadecimal rendering of the string 'abc':
+ ;SELECT hex('abc')
+
+
+
+humanize_file_size(value)
+══════════════════════════════════════════════════════════════════════
+ Format the given file size as a human-friendly string
+Parameter
+ value The file size to format
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), instr(), leftstr(), length(),
+ logfmt2json(), lower(), ltrim(), padc(), padl(), padr(), printf(),
+ proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To format an amount:
+ ;SELECT humanize_file_size(10 * 1024 * 1024)
+
+
+
+ifnull(X, Y)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of its first non-NULL argument, or NULL if both
+ arguments are NULL
+Parameters
+ X A value to check for NULL-ness
+ Y A value to check for NULL-ness
+
+Example
+#1 To get the first non-null value between null and zero:
+ ;SELECT ifnull(null, 0)
+
+
+
+instr(haystack, needle)
+══════════════════════════════════════════════════════════════════════
+ Finds the first occurrence of the needle within the haystack and
+ returns the number of prior characters plus 1, or 0 if the needle
+ was not found
+Parameters
+ haystack The string to search within
+ needle The string to look for in the haystack
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), leftstr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To test get the position of 'b' in the string 'abc':
+ ;SELECT instr('abc', 'b')
+
+
+
+jget(json, ptr, [default])
+══════════════════════════════════════════════════════════════════════
+ Get the value from a JSON object using a JSON-Pointer.
+Parameters
+ json The JSON object to query.
+ ptr The JSON-Pointer to lookup in the object.
+ default The default value if the value was not found
+See Also
+ json_concat(), json_contains(), json_group_array(),
+ json_group_object()
+Examples
+#1 To get the root of a JSON value:
+ ;SELECT jget('1', '')
+
+
+#2 To get the property named 'b' in a JSON object:
+ ;SELECT jget('{ "a": 1, "b": 2 }', '/b')
+
+
+#3 To get the 'msg' property and return a default if it does not exist:
+ ;SELECT jget(null, '/msg', 'Hello')
+
+
+
+joinpath(path, ...)
+══════════════════════════════════════════════════════════════════════
+ Join components of a path together.
+Parameter
+ path One or more path components to join together. If an argument
+ starts with a forward or backward slash, it will be
+ considered an absolute path and any preceding elements will
+ be ignored.
+See Also
+ basename(), dirname(), readlink(), realpath()
+Examples
+#1 To join a directory and file name into a relative path:
+ ;SELECT joinpath('foo', 'bar')
+
+
+#2 To join an empty component with other names into a relative path:
+ ;SELECT joinpath('', 'foo', 'bar')
+
+
+#3 To create an absolute path with two path components:
+ ;SELECT joinpath('/', 'foo', 'bar')
+
+
+#4 To create an absolute path from a path component that starts with a forward slash:
+ ;SELECT joinpath('/', 'foo', '/bar')
+
+
+
+json_concat(json, value, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns an array with the given values concatenated onto the end.
+ If the initial value is null, the result will be an array with the
+ given elements. If the initial value is an array, the result will
+ be an array with the given values at the end. If the initial value
+ is not null or an array, the result will be an array with two
+ elements: the initial value and the given value.
+Parameters
+ json The initial JSON value.
+ value The value(s) to add to the end of the array.
+See Also
+ jget(), json_contains(), json_group_array(), json_group_object()
+Examples
+#1 To append the number 4 to null:
+ ;SELECT json_concat(NULL, 4)
+
+
+#2 To append 4 and 5 to the array [1, 2, 3]:
+ ;SELECT json_concat('[1, 2, 3]', 4, 5)
+
+
+#3 To concatenate two arrays together:
+ ;SELECT json_concat('[1, 2, 3]', json('[4, 5]'))
+
+
+
+json_contains(json, value)
+══════════════════════════════════════════════════════════════════════
+ Check if a JSON value contains the given element.
+Parameters
+ json The JSON value to query.
+ value The value to look for in the first argument
+See Also
+ jget(), json_concat(), json_group_array(), json_group_object()
+Examples
+#1 To test if a JSON array contains the number 4:
+ ;SELECT json_contains('[1, 2, 3]', 4)
+
+
+#2 To test if a JSON array contains the string 'def':
+ ;SELECT json_contains('["abc", "def"]', 'def')
+
+
+
+json_group_array(value, ...)
+══════════════════════════════════════════════════════════════════════
+ Collect the given values from a query into a JSON array
+Parameter
+ value The values to append to the array
+See Also
+ jget(), json_concat(), json_contains(), json_group_object()
+Examples
+#1 To create an array from arguments:
+ ;SELECT json_group_array('one', 2, 3.4)
+
+
+#2 To create an array from a column of values:
+ ;SELECT json_group_array(column1) FROM (VALUES (1), (2), (3))
+
+
+
+json_group_object(name, value, ...)
+══════════════════════════════════════════════════════════════════════
+ Collect the given values from a query into a JSON object
+Parameters
+ name The property name for the value
+ value The value to add to the object
+See Also
+ jget(), json_concat(), json_contains(), json_group_array()
+Examples
+#1 To create an object from arguments:
+ ;SELECT json_group_object('a', 1, 'b', 2)
+
+
+#2 To create an object from a pair of columns:
+ ;SELECT json_group_object(column1, column2) FROM (VALUES ('a', 1), ('b', 2))
+
+
+
+julianday(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of days since noon in Greenwich on November 24,
+ 4714 B.C.
+Parameters
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the value to the
+ left.
+See Also
+ date(), datetime(), strftime(), time(), timediff(), timeslice()
+Examples
+#1 To get the julian day from the timestamp '2017-01-02T03:04:05':
+ ;SELECT julianday('2017-01-02T03:04:05')
+
+
+#2 To get the julian day from the timestamp '2017-01-02T03:04:05' plus one minute:
+ ;SELECT julianday('2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To get the julian day from the timestamp 1491341842:
+ ;SELECT julianday(1491341842, 'unixepoch')
+
+
+
+lag(expr, [offset], [default])
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the previous
+ row in the partition.
+Parameters
+ expr The expression to execute over the previous row
+ offset The offset from the current row in the partition
+ default The default value if the previous row does not exist
+ instead of NULL
+See Also
+ cume_dist(), dense_rank(), first_value(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), rank(), row_number()
+
+last_insert_rowid()
+══════════════════════════════════════════════════════════════════════
+ Returns the ROWID of the last row insert from the database
+ connection which invoked the function
+
+
+last_value(expr)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the last row
+ in the window frame.
+Parameter
+ expr The expression to execute over the last row
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), lead(), nth_value(),
+ ntile(), percent_rank(), rank(), row_number()
+
+lead(expr, [offset], [default])
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the next row
+ in the partition.
+Parameters
+ expr The expression to execute over the next row
+ offset The offset from the current row in the partition
+ default The default value if the next row does not exist instead
+ of NULL
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(),
+ nth_value(), ntile(), percent_rank(), rank(), row_number()
+
+leftstr(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N leftmost (UTF-8) characters in the given string.
+Parameters
+ str The string to return subset.
+ N The number of characters from the left side of the string to
+ return.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ length(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To get the first character of the string 'abc':
+ ;SELECT leftstr('abc', 1)
+
+
+#2 To get the first ten characters of a string, regardless of size:
+ ;SELECT leftstr('abc', 10)
+
+
+
+length(str)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of characters (not bytes) in the given string
+ prior to the first NUL character
+Parameter
+ str The string to determine the length of
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), logfmt2json(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To get the length of the string 'abc':
+ ;SELECT length('abc')
+
+
+
+like(pattern, str, [escape])
+══════════════════════════════════════════════════════════════════════
+ Match a string against a pattern
+Parameters
+ pattern The pattern to match. A percent symbol (%) will match
+ zero or more characters and an underscore (_) will match a
+ single character.
+ str The string to match
+ escape The escape character that can be used to prefix a literal
+ percent or underscore in the pattern.
+
+Examples
+#1 To test if the string 'aabcc' contains the letter 'b':
+ ;SELECT like('%b%', 'aabcc')
+
+
+#2 To test if the string 'aab%' ends with 'b%':
+ ;SELECT like('%b:%', 'aab%', ':')
+
+
+
+likelihood(value, probability)
+══════════════════════════════════════════════════════════════════════
+ Provides a hint to the query planner that the first argument is a
+ boolean that is true with the given probability
+Parameters
+ value The boolean value to return
+ probability A floating point constant between 0.0 and 1.0
+
+
+likely(value)
+══════════════════════════════════════════════════════════════════════
+ Short-hand for likelihood(X,0.9375)
+Parameter
+ value The boolean value to return
+
+
+lnav_top_file()
+══════════════════════════════════════════════════════════════════════
+ Return the name of the file that the top line in the current view
+ came from.
+
+
+lnav_version()
+══════════════════════════════════════════════════════════════════════
+ Return the current version of lnav
+
+
+load_extension(path, [entry-point])
+══════════════════════════════════════════════════════════════════════
+ Loads SQLite extensions out of the given shared library file using
+ the given entry point.
+Parameters
+ path The path to the shared library containing the
+ extension.
+ entry-point
+
+
+log(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the natural logarithm of x
+Parameter
+ x The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log10(), max(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To get the natual logarithm of 8:
+ ;SELECT log(8)
+
+
+
+log10(x)
+══════════════════════════════════════════════════════════════════════
+ Returns the base-10 logarithm of X
+Parameter
+ x The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), max(), min(),
+ pi(), power(), radians(), round(), sign(), square(), sum(), total()
+Example
+#1 To get the logarithm of 100:
+ ;SELECT log10(100)
+
+
+
+log_top_datetime()
+══════════════════════════════════════════════════════════════════════
+ Return the timestamp of the line at the top of the log view.
+
+
+log_top_line()
+══════════════════════════════════════════════════════════════════════
+ Return the line number at the top of the log view.
+
+
+logfmt2json(str)
+══════════════════════════════════════════════════════════════════════
+ Convert a logfmt-encoded string into JSON
+Parameter
+ str The logfmt message to parse
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), lower(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To extract key/value pairs from a log message:
+ ;SELECT logfmt2json('foo=1 bar=2 name="Rolo Tomassi"')
+
+
+
+lower(str)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of the given string with all ASCII characters
+ converted to lower case.
+Parameter
+ str The string to convert.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), ltrim(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To lowercase the string 'AbC':
+ ;SELECT lower('AbC')
+
+
+
+ltrim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the left side of the first.
+Parameters
+ str The string to trim characters from the left side
+ chars The characters to trim. Defaults to spaces.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), padc(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To trim the leading whitespace from the string ' abc':
+ ;SELECT ltrim(' abc')
+
+
+#2 To trim the characters 'a' or 'b' from the left side of the string 'aaaabbbc':
+ ;SELECT ltrim('aaaabbbc', 'ab')
+
+
+
+max(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the argument with the maximum value, or return NULL if any
+ argument is NULL.
+Parameter
+ X The numbers to find the maximum of. If only one argument is
+ given, this function operates as an aggregate.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ min(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the largest value from the parameters:
+ ;SELECT max(2, 1, 3)
+
+
+#2 To get the largest value from an aggregate:
+ ;SELECT max(status) FROM http_status_codes
+
+
+
+min(X, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the argument with the minimum value, or return NULL if any
+ argument is NULL.
+Parameter
+ X The numbers to find the minimum of. If only one argument is
+ given, this function operates as an aggregate.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), pi(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Examples
+#1 To get the smallest value from the parameters:
+ ;SELECT min(2, 1, 3)
+
+
+#2 To get the smallest value from an aggregate:
+ ;SELECT min(status) FROM http_status_codes
+
+
+
+nth_value(expr, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the result of evaluating the expression against the nth row
+ in the window frame.
+Parameters
+ expr The expression to execute over the nth row
+ N The row number
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ ntile(), percent_rank(), rank(), row_number()
+
+ntile(groups)
+══════════════════════════════════════════════════════════════════════
+ Returns the number of the group that the current row is a part of
+Parameter
+ groups The number of groups
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), percent_rank(), rank(), row_number()
+
+nullif(X, Y)
+══════════════════════════════════════════════════════════════════════
+ Returns its first argument if the arguments are different and NULL
+ if the arguments are the same.
+Parameters
+ X The first argument to compare.
+ Y The argument to compare against the first.
+
+Examples
+#1 To test if 1 is different from 1:
+ ;SELECT nullif(1, 1)
+
+
+#2 To test if 1 is different from 2:
+ ;SELECT nullif(1, 2)
+
+
+
+padc(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with enough spaces to make it centered within
+ the given length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padl(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padc('abc', 6) || 'def'
+
+
+#2 To pad the string 'abcdef' to a length of eight characters:
+ ;SELECT padc('abcdef', 8) || 'ghi'
+
+
+
+padl(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with leading spaces until it reaches the
+ desired length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padr(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padl('abc', 6)
+
+
+#2 To pad the string 'abcdef' to a length of four characters:
+ ;SELECT padl('abcdef', 4)
+
+
+
+padr(str, len)
+══════════════════════════════════════════════════════════════════════
+ Pad the given string with trailing spaces until it reaches the
+ desired length
+Parameters
+ str The string to pad
+ len The minimum desired length of the output string
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ printf(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To pad the string 'abc' to a length of six characters:
+ ;SELECT padr('abc', 6) || 'def'
+
+
+#2 To pad the string 'abcdef' to a length of four characters:
+ ;SELECT padr('abcdef', 4) || 'ghi'
+
+
+
+percent_rank()
+══════════════════════════════════════════════════════════════════════
+ Returns (rank - 1) / (partition-rows - 1)
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), rank(), row_number()
+
+pi()
+══════════════════════════════════════════════════════════════════════
+ Returns the value of PI
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), power(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To get the value of PI:
+ ;SELECT pi()
+
+
+
+power(base, exp)
+══════════════════════════════════════════════════════════════════════
+ Returns the base to the given exponent
+Parameters
+ base The base number
+ exp The exponent
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), radians(), round(), sign(), square(), sum(),
+ total()
+Example
+#1 To raise two to the power of three:
+ ;SELECT power(2, 3)
+
+
+
+printf(format, X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string with this functions arguments substituted into the
+ given format. Substitution points are specified using percent (%)
+ options, much like the standard C printf() function.
+Parameters
+ format The format of the string to return.
+ X The argument to substitute at a given position in the
+ format.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), proper(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Examples
+#1 To substitute 'World' into the string 'Hello, %s!':
+ ;SELECT printf('Hello, %s!', 'World')
+
+
+#2 To right-align 'small' in the string 'align:' with a column width of 10:
+ ;SELECT printf('align: % 10s', 'small')
+
+
+#3 To format 11 with a width of five characters and leading zeroes:
+ ;SELECT printf('value: %05d', 11)
+
+
+
+proper(str)
+══════════════════════════════════════════════════════════════════════
+ Capitalize the first character of words in the given string
+Parameter
+ str The string to capitalize.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), regexp_capture(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To capitalize the words in the string 'hello, world!':
+ ;SELECT proper('hello, world!')
+
+
+
+quote(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the text of an SQL literal which is the value of its
+ argument suitable for inclusion into an SQL statement.
+Parameter
+ X The string to quote.
+
+Examples
+#1 To quote the string 'abc':
+ ;SELECT quote('abc')
+
+
+#2 To quote the string 'abc'123':
+ ;SELECT quote('abc''123')
+
+
+
+radians(degrees)
+══════════════════════════════════════════════════════════════════════
+ Converts degrees to radians
+Parameter
+ degrees The degrees value to convert to radians
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), round(), sign(), square(), sum(), total()
+Example
+#1 To convert 180 degrees to radians:
+ ;SELECT radians(180)
+
+
+
+raise_error(msg)
+══════════════════════════════════════════════════════════════════════
+ Raises an error with the given message when executed
+Parameter
+ msg The error message
+
+
+random()
+══════════════════════════════════════════════════════════════════════
+ Returns a pseudo-random integer between -9223372036854775808 and +
+ 9223372036854775807.
+
+
+randomblob(N)
+══════════════════════════════════════════════════════════════════════
+ Return an N-byte blob containing pseudo-random bytes.
+Parameter
+ N The size of the blob in bytes.
+
+
+rank()
+══════════════════════════════════════════════════════════════════════
+ Returns the row_number() of the first peer in each group with gaps
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), row_number()
+
+readlink(path)
+══════════════════════════════════════════════════════════════════════
+ Read the target of a symbolic link.
+Parameter
+ path The path to the symbolic link.
+See Also
+ basename(), dirname(), joinpath(), realpath()
+
+realpath(path)
+══════════════════════════════════════════════════════════════════════
+ Returns the resolved version of the given path, expanding symbolic
+ links and resolving '.' and '..' references.
+Parameter
+ path The path to resolve.
+See Also
+ basename(), dirname(), joinpath(), readlink()
+
+regexp(re, str)
+══════════════════════════════════════════════════════════════════════
+ Test if a string matches a regular expression
+Parameters
+ re The regular expression to use
+ str The string to test against the regular expression
+
+
+regexp_capture(string, pattern)
+══════════════════════════════════════════════════════════════════════
+ A table-valued function that executes a regular-expression over a
+ string and returns the captured values. If the regex only matches a
+ subset of the input string, it will be rerun on the remaining parts
+ of the string until no more matches are found.
+Parameters
+ string The string to match against the given pattern.
+ pattern The regular expression to match.
+Results
+ match_index The match iteration. This value will increase each
+ time a new match is found in the input string.
+ capture_index The index of the capture in the regex.
+ capture_name The name of the capture in the regex.
+ capture_count The total number of captures in the regex.
+ range_start The start of the capture in the input string.
+ range_stop The stop of the capture in the input string.
+ content The captured value from the string.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_match(), regexp_replace(),
+ replace(), replicate(), reverse(), rightstr(), rtrim(), sparkline(),
+ spooky_hash(), startswith(), strfilter(), substr(), trim(), unicode(),
+ upper(), xpath()
+Example
+#1 To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2':
+ ;SELECT * FROM regexp_capture('a=1; b=2', '(\w+)=(\d+)')
+
+
+
+regexp_match(re, str)
+══════════════════════════════════════════════════════════════════════
+ Match a string against a regular expression and return the capture
+ groups as JSON.
+Parameters
+ re The regular expression to use
+ str The string to test against the regular expression
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_replace(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), upper(), xpath()
+Examples
+#1 To capture the digits from the string '123':
+ ;SELECT regexp_match('(\d+)', '123')
+
+
+#2 To capture a number and word into a JSON object with the properties 'col_0' and 'col_1'
+ :
+ ;SELECT regexp_match('(\d+) (\w+)', '123 four')
+
+
+#3 To capture a number and word into a JSON object with the named properties 'num' and '
+ str':
+ ;SELECT regexp_match('(?<num>\d+) (?<str>\w+)', '123 four')
+
+
+
+regexp_replace(str, re, repl)
+══════════════════════════════════════════════════════════════════════
+ Replace the parts of a string that match a regular expression.
+Parameters
+ str The string to perform replacements on
+ re The regular expression to match
+ repl The replacement string. You can reference capture groups
+ with a backslash followed by the number of the group,
+ starting with 1.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_match(), replace(), replicate(), reverse(), rightstr(), rtrim(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Examples
+#1 To replace the word at the start of the string 'Hello, World!' with 'Goodbye':
+ ;SELECT regexp_replace('Hello, World!', '^(\w+)', 'Goodbye')
+
+
+#2 To wrap alphanumeric words with angle brackets:
+ ;SELECT regexp_replace('123 abc', '(\w+)', '<\1>')
+
+
+
+replace(str, old, replacement)
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by substituting the replacement string for
+ every occurrence of the old string in the given string.
+Parameters
+ str The string to perform substitutions on.
+ old The string to be replaced.
+ replacement The string to replace any occurrences of the old
+ string with.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replicate(), reverse(), rightstr(), rtrim(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Examples
+#1 To replace the string 'x' with 'z' in 'abc':
+ ;SELECT replace('abc', 'x', 'z')
+
+
+#2 To replace the string 'a' with 'z' in 'abc':
+ ;SELECT replace('abc', 'a', 'z')
+
+
+
+replicate(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the given string concatenated N times.
+Parameters
+ str The string to replicate.
+ N The number of times to replicate the string.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), reverse(), rightstr(), rtrim(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Example
+#1 To repeat the string 'abc' three times:
+ ;SELECT replicate('abc', 3)
+
+
+
+reverse(str)
+══════════════════════════════════════════════════════════════════════
+ Returns the reverse of the given string.
+Parameter
+ str The string to reverse.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), rightstr(), rtrim(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Example
+#1 To reverse the string 'abc':
+ ;SELECT reverse('abc')
+
+
+
+rightstr(str, N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N rightmost (UTF-8) characters in the given string.
+Parameters
+ str The string to return subset.
+ N The number of characters from the right side of the string to
+ return.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rtrim(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Examples
+#1 To get the last character of the string 'abc':
+ ;SELECT rightstr('abc', 1)
+
+
+#2 To get the last ten characters of a string, regardless of size:
+ ;SELECT rightstr('abc', 10)
+
+
+
+round(num, [digits])
+══════════════════════════════════════════════════════════════════════
+ Returns a floating-point value rounded to the given number of digits
+ to the right of the decimal point.
+Parameters
+ num The value to round.
+ digits The number of digits to the right of the decimal to round
+ to.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), sign(), square(), sum(),
+ total()
+Examples
+#1 To round the number 123.456 to an integer:
+ ;SELECT round(123.456)
+
+
+#2 To round the number 123.456 to a precision of 1:
+ ;SELECT round(123.456, 1)
+
+
+#3 To round the number 123.456 to a precision of 5:
+ ;SELECT round(123.456, 5)
+
+
+
+row_number()
+══════════════════════════════════════════════════════════════════════
+ Returns the number of the row within the current partition, starting
+ from 1.
+See Also
+ cume_dist(), dense_rank(), first_value(), lag(), last_value(), lead(),
+ nth_value(), ntile(), percent_rank(), rank()
+Example
+#1 To number messages from a process:
+ ;SELECT row_number() OVER (PARTITION BY ex_procname ORDER BY log_line) AS msg_num,
+ ex_procname, log_body FROM lnav_example_log
+
+
+
+rtrim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the right side of the first.
+Parameters
+ str The string to trim characters from the right side
+ chars The characters to trim. Defaults to spaces.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ sparkline(), spooky_hash(), startswith(), strfilter(), substr(),
+ trim(), unicode(), upper(), xpath()
+Examples
+#1 To trim the whitespace from the end of the string 'abc ':
+ ;SELECT rtrim('abc ')
+
+
+#2 To trim the characters 'b' and 'c' from the string 'abbbbcccc':
+ ;SELECT rtrim('abbbbcccc', 'bc')
+
+
+
+sign(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the sign of the given number as -1, 0, or 1
+Parameter
+ num The number
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), square(), sum(),
+ total()
+Examples
+#1 To get the sign of 10:
+ ;SELECT sign(10)
+
+
+#2 To get the sign of 0:
+ ;SELECT sign(0)
+
+
+#3 To get the sign of -10:
+ ;SELECT sign(-10)
+
+
+
+sparkline(value, [upper])
+══════════════════════════════════════════════════════════════════════
+ Function used to generate a sparkline bar chart. The non-aggregate
+ version converts a single numeric value on a range to a bar chart
+ character. The aggregate version returns a string with a bar
+ character for every numeric input
+Parameters
+ value The numeric value to convert
+ upper The upper bound of the numeric range. The non-aggregate
+ version defaults to 100. The aggregate version uses the
+ largest value in the inputs.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), spooky_hash(), startswith(), strfilter(), substr(), trim(),
+ unicode(), upper(), xpath()
+Examples
+#1 To get the unicode block element for the value 32 in the range of 0-128:
+ ;SELECT sparkline(32, 128)
+
+
+#2 To chart the values in a JSON array:
+ ;SELECT sparkline(value) FROM json_each('[0, 1, 2, 3, 4, 5, 6, 7, 8]')
+
+
+
+spooky_hash(str, ...)
+══════════════════════════════════════════════════════════════════════
+ Compute the hash value for the given arguments.
+Parameter
+ str The string to hash
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), startswith(), strfilter(), substr(), trim(),
+ unicode(), upper(), xpath()
+Examples
+#1 To produce a hash for the string 'Hello, World!':
+ ;SELECT spooky_hash('Hello, World!')
+
+
+#2 To produce a hash for the parameters where one is NULL:
+ ;SELECT spooky_hash('Hello, World!', NULL)
+
+
+#3 To produce a hash for the parameters where one is an empty string:
+ ;SELECT spooky_hash('Hello, World!', '')
+
+
+#4 To produce a hash for the parameters where one is a number:
+ ;SELECT spooky_hash('Hello, World!', 123)
+
+
+
+sqlite_compileoption_get(N)
+══════════════════════════════════════════════════════════════════════
+ Returns the N-th compile-time option used to build SQLite or NULL if
+ N is out of range.
+Parameter
+ N The option number to get
+
+
+sqlite_compileoption_used(option)
+══════════════════════════════════════════════════════════════════════
+ Returns true (1) or false (0) depending on whether or not that
+ compile-time option was used during the build.
+Parameter
+ option The name of the compile-time option.
+
+Example
+#1 To check if the SQLite library was compiled with ENABLE_FTS3:
+ ;SELECT sqlite_compileoption_used('ENABLE_FTS3')
+
+
+
+sqlite_source_id()
+══════════════════════════════════════════════════════════════════════
+ Returns a string that identifies the specific version of the source
+ code that was used to build the SQLite library.
+
+
+sqlite_version()
+══════════════════════════════════════════════════════════════════════
+ Returns the version string for the SQLite library that is running.
+
+
+square(num)
+══════════════════════════════════════════════════════════════════════
+ Returns the square of the argument
+Parameter
+ num The number to square
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), sum(),
+ total()
+Example
+#1 To get the square of two:
+ ;SELECT square(2)
+
+
+
+startswith(str, prefix)
+══════════════════════════════════════════════════════════════════════
+ Test if a string begins with the given prefix
+Parameters
+ str The string to test
+ prefix The prefix to check in the string
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), strfilter(), substr(), trim(),
+ unicode(), upper(), xpath()
+Examples
+#1 To test if the string 'foobar' starts with 'foo':
+ ;SELECT startswith('foobar', 'foo')
+
+
+#2 To test if the string 'foobar' starts with 'bar':
+ ;SELECT startswith('foobar', 'bar')
+
+
+
+strfilter(source, include)
+══════════════════════════════════════════════════════════════════════
+ Returns the source string with only the characters given in the
+ second parameter
+Parameters
+ source The string to filter
+ include The characters to include in the result
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), substr(), trim(),
+ unicode(), upper(), xpath()
+Example
+#1 To get the 'b', 'c', and 'd' characters from the string 'abcabc':
+ ;SELECT strfilter('abcabc', 'bcd')
+
+
+
+strftime(format, timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the date formatted according to the format string specified
+ as the first argument.
+Parameters
+ format A format string with substitutions similar to those
+ found in the strftime() standard C library.
+ timestring The string to convert to a date with time.
+ modifier A transformation that is applied to the value to the
+ left.
+See Also
+ date(), datetime(), julianday(), time(), timediff(), timeslice()
+Examples
+#1 To get the year from the timestamp '2017-01-02T03:04:05':
+ ;SELECT strftime('%Y', '2017-01-02T03:04:05')
+
+
+#2 To create a string with the time from the timestamp '2017-01-02T03:04:05' plus one
+ minute:
+ ;SELECT strftime('The time is: %H:%M:%S', '2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To create a string with the Julian day from the epoch timestamp 1491341842:
+ ;SELECT strftime('Julian day: %J', 1491341842, 'unixepoch')
+
+
+
+substr(str, start, [size])
+══════════════════════════════════════════════════════════════════════
+ Returns a substring of input string X that begins with the Y-th
+ character and which is Z characters long.
+Parameters
+ str The string to extract a substring from.
+ start The index within 'str' that is the start of the substring.
+ Indexes begin at 1. A negative value means that the
+ substring is found by counting from the right rather than
+ the left.
+ size The size of the substring. If not given, then all
+ characters through the end of the string are returned. If
+ the value is negative, then the characters before the start
+ are returned.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(), trim(),
+ unicode(), upper(), xpath()
+Examples
+#1 To get the substring starting at the second character until the end of the string 'abc'
+ :
+ ;SELECT substr('abc', 2)
+
+
+#2 To get the substring of size one starting at the second character of the string 'abc':
+ ;SELECT substr('abc', 2, 1)
+
+
+#3 To get the substring starting at the last character until the end of the string 'abc':
+ ;SELECT substr('abc', -1)
+
+
+#4 To get the substring starting at the last character and going backwards one step of the
+ string 'abc':
+ ;SELECT substr('abc', -1, -1)
+
+
+
+sum(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the sum of the values in the group as an integer.
+Parameter
+ X The values to add.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), square(),
+ total()
+Example
+#1 To sum all of the values in the column 'ex_duration' from the table 'lnav_example_log':
+ ;SELECT sum(ex_duration) FROM lnav_example_log
+
+
+
+time(timestring, modifier, ...)
+══════════════════════════════════════════════════════════════════════
+ Returns the time in this format: HH:MM:SS.
+Parameters
+ timestring The string to convert to a time.
+ modifier A transformation that is applied to the value to the
+ left.
+See Also
+ date(), datetime(), julianday(), strftime(), timediff(), timeslice()
+Examples
+#1 To get the time portion of the timestamp '2017-01-02T03:04:05':
+ ;SELECT time('2017-01-02T03:04:05')
+
+
+#2 To get the time portion of the timestamp '2017-01-02T03:04:05' plus one minute:
+ ;SELECT time('2017-01-02T03:04:05', '+1 minute')
+
+
+#3 To get the time portion of the epoch timestamp 1491341842:
+ ;SELECT time(1491341842, 'unixepoch')
+
+
+
+timediff(time1, time2)
+══════════════════════════════════════════════════════════════════════
+ Compute the difference between two timestamps in seconds
+Parameters
+ time1 The first timestamp
+ time2 The timestamp to subtract from the first
+See Also
+ date(), datetime(), julianday(), strftime(), time(), timeslice()
+Examples
+#1 To get the difference between two timestamps:
+ ;SELECT timediff('2017-02-03T04:05:06', '2017-02-03T04:05:00')
+
+
+#2 To get the difference between relative timestamps:
+ ;SELECT timediff('today', 'yesterday')
+
+
+
+timeslice(time, slice)
+══════════════════════════════════════════════════════════════════════
+ Return the start of the slice of time that the given timestamp falls
+ in. If the time falls outside of the slice, NULL is returned.
+Parameters
+ time The timestamp to get the time slice for.
+ slice The size of the time slices
+See Also
+ date(), datetime(), julianday(), strftime(), time(), timediff()
+Examples
+#1 To get the timestamp rounded down to the start of the ten minute slice:
+ ;SELECT timeslice('2017-01-01T05:05:00', '10m')
+
+
+#2 To group log messages into five minute buckets and count them:
+ ;SELECT timeslice(log_time_msecs, '5m') AS slice, count(1)
+ FROM lnav_example_log GROUP BY slice
+
+
+#3 To group log messages by those before 4:30am and after:
+ ;SELECT timeslice(log_time_msecs, 'before 4:30am') AS slice, count(1) FROM
+ lnav_example_log GROUP BY slice
+
+
+
+total(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the sum of the values in the group as a floating-point.
+Parameter
+ X The values to add.
+See Also
+ abs(), acos(), acosh(), asin(), asinh(), atan(), atan2(), atanh(),
+ atn2(), avg(), ceil(), degrees(), exp(), floor(), log(), log10(),
+ max(), min(), pi(), power(), radians(), round(), sign(), square(),
+ sum()
+Example
+#1 To total all of the values in the column 'ex_duration' from the table 'lnav_example_log
+ ':
+ ;SELECT total(ex_duration) FROM lnav_example_log
+
+
+
+total_changes()
+══════════════════════════════════════════════════════════════════════
+ Returns the number of row changes caused by INSERT, UPDATE or DELETE
+ statements since the current database connection was opened.
+
+
+trim(str, [chars])
+══════════════════════════════════════════════════════════════════════
+ Returns a string formed by removing any and all characters that
+ appear in the second argument from the left and right sides of the
+ first.
+Parameters
+ str The string to trim characters from the left and right sides.
+
+ chars The characters to trim. Defaults to spaces.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), unicode(), upper(), xpath()
+Examples
+#1 To trim whitespace from the start and end of the string ' abc ':
+ ;SELECT trim(' abc ')
+
+
+#2 To trim the characters '-' and '+' from the string '-+abc+-':
+ ;SELECT trim('-+abc+-', '-+')
+
+
+
+typeof(X)
+══════════════════════════════════════════════════════════════════════
+ Returns a string that indicates the datatype of the expression X: "
+ null", "integer", "real", "text", or "blob".
+Parameter
+ X The expression to check.
+
+Examples
+#1 To get the type of the number 1:
+ ;SELECT typeof(1)
+
+
+#2 To get the type of the string 'abc':
+ ;SELECT typeof('abc')
+
+
+
+unicode(X)
+══════════════════════════════════════════════════════════════════════
+ Returns the numeric unicode code point corresponding to the first
+ character of the string X.
+Parameter
+ X The string to examine.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), upper(), xpath()
+Example
+#1 To get the unicode code point for the first character of 'abc':
+ ;SELECT unicode('abc')
+
+
+
+unlikely(value)
+══════════════════════════════════════════════════════════════════════
+ Short-hand for likelihood(X, 0.0625)
+Parameter
+ value The boolean value to return
+
+
+upper(str)
+══════════════════════════════════════════════════════════════════════
+ Returns a copy of the given string with all ASCII characters
+ converted to upper case.
+Parameter
+ str The string to convert.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), xpath()
+Example
+#1 To uppercase the string 'aBc':
+ ;SELECT upper('aBc')
+
+
+
+xpath(xpath, xmldoc)
+══════════════════════════════════════════════════════════════════════
+ A table-valued function that executes an xpath expression over an
+ XML string and returns the selected values.
+Parameters
+ xpath The XPATH expression to evaluate over the XML document.
+ xmldoc The XML document as a string.
+Results
+ result The result of the XPATH expression.
+ node_path The absolute path to the node containing the result.
+ node_attr The node's attributes stored in JSON object.
+ node_text The node's text value.
+See Also
+ char(), charindex(), endswith(), extract(), group_concat(),
+ group_spooky_hash(), gunzip(), gzip(), humanize_file_size(), instr(),
+ leftstr(), length(), logfmt2json(), lower(), ltrim(), padc(), padl(),
+ padr(), printf(), proper(), regexp_capture(), regexp_match(),
+ regexp_replace(), replace(), replicate(), reverse(), rightstr(),
+ rtrim(), sparkline(), spooky_hash(), startswith(), strfilter(),
+ substr(), trim(), unicode(), upper()
+Examples
+#1 To select the XML nodes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
+
+
+#2 To select all 'a' attributes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def/@a', '<abc><def a="b">Hello</def><def>Bye</def></abc>')
+
+
+#3 To select the text nodes on the path '/abc/def':
+ ;SELECT * FROM xpath('/abc/def/text()', '<abc><def a="b">Hello &#x2605;</def></abc>')
+
+
+
+zeroblob(N)
+══════════════════════════════════════════════════════════════════════
+ Returns a BLOB consisting of N bytes of 0x00.
+Parameter
+ N The size of the BLOB.
+
+
+ATTACH DATABASE filename AS schema-name
+══════════════════════════════════════════════════════════════════════
+ Attach a database file to the current connection.
+Parameters
+ filename The path to the database file.
+ schema-name The prefix for tables in this database.
+
+Example
+#1 To attach the database file '/tmp/customers.db' with the name customers:
+ ;ATTACH DATABASE '/tmp/customers.db' AS customers
+
+
+
+CASE [base-expr] WHEN cmp-expr1 THEN then-expr1 [... WHEN cmp-exprN THEN then-exprN] [ELSE else-expr] END
+══════════════════════════════════════════════════════════════════════
+ Evaluate a series of expressions in order until one evaluates to
+ true and then return it's result. Similar to an IF-THEN-ELSE
+ construct in other languages.
+Parameters
+ base-expr The base expression that is used for comparison in the
+ branches
+ cmp-expr The expression to test if this branch should be taken
+ else-expr The result of this CASE if no branches matched.
+
+Example
+#1 To evaluate the number one and return the string 'one':
+ ;SELECT CASE 1 WHEN 0 THEN 'zero' WHEN 1 THEN 'one' END
+
+
+
+CREATE [TEMP] VIEW [IF NOT EXISTS] [schema-name.] view-name AS select-stmt
+══════════════════════════════════════════════════════════════════════
+ Assign a name to a SELECT statement
+Parameters
+ IF NOT EXISTS Do not create the view if it already exists
+ schema-name. The database to create the view in
+ view-name The name of the view
+ select-stmt The SELECT statement the view represents
+
+
+DELETE FROM table-name [WHERE cond]
+══════════════════════════════════════════════════════════════════════
+ Delete rows from a table
+Parameters
+ table-name The name of the table
+ cond The conditions used to delete the rows.
+
+
+DETACH DATABASE schema-name
+══════════════════════════════════════════════════════════════════════
+ Detach a database from the current connection.
+Parameter
+ schema-name The prefix for tables in this database.
+
+Example
+#1 To detach the database named 'customers':
+ ;DETACH DATABASE customers
+
+
+
+DROP VIEW [IF EXISTS] [schema-name.] view-name
+══════════════════════════════════════════════════════════════════════
+ Drop a view
+Parameters
+
+
+INSERT INTO [schema-name.] table-name [( column-name1 [, ... column-nameN] )] VALUES ( expr1 [, ... exprN] )
+══════════════════════════════════════════════════════════════════════
+ Insert rows into a table
+Parameters
+
+Example
+#1 To insert the pair containing 'MSG' and 'HELLO, WORLD!' into the 'environ'
+ table:
+ ;INSERT INTO environ VALUES ('MSG', 'HELLO, WORLD!')
+
+
+
+OVER window-name
+══════════════════════════════════════════════════════════════════════
+ Executes the preceding function over a window
+Parameter
+ window-name The name of the window definition
+
+
+SELECT result-column1 [, ... result-columnN] [FROM table1 [, ... tableN]] [WHERE cond] [GROUP BY grouping-expr1 [, ... grouping-exprN]] [ORDER BY ordering-term1 [, ... ordering-termN]] [LIMIT limit-expr1 [, ... limit-exprN]]
+══════════════════════════════════════════════════════════════════════
+ Query the database and return zero or more rows of data.
+Parameters
+ result-column The expression used to generate a result for this
+ column.
+ table The table(s) to query for data
+ cond The conditions used to select the rows to return.
+ grouping-expr The expression to use when grouping rows.
+ ordering-term The values to use when ordering the result set.
+ limit-expr The maximum number of rows to return.
+
+Example
+#1 To select all of the columns from the table 'syslog_log':
+ ;SELECT * FROM syslog_log
+
+
+
+UPDATE table SET column-name1 = expr1 [, ... column-nameN = exprN] [WHERE cond]
+══════════════════════════════════════════════════════════════════════
+ Modify a subset of values in zero or more rows of the given table
+Parameters
+ table The table to update
+ column-name The columns in the table to update.
+ cond The condition used to determine whether a row should
+ be updated.
+
+Example
+#1 To mark the syslog message at line 40:
+ ;UPDATE syslog_log SET log_mark = 1 WHERE log_line = 40
+
+
+
+WITH [RECURSIVE] cte-table-name AS select-stmt
+══════════════════════════════════════════════════════════════════════
+ Create a temporary view that exists only for the duration of a SQL
+ statement.
+Parameters
+ cte-table-name The name for the temporary table.
+ select-stmt The SELECT statement used to populate the temporary
+ table.
+
diff --git a/test/file_for_dot_read.sql b/test/file_for_dot_read.sql
new file mode 100644
index 0000000..fca253c
--- /dev/null
+++ b/test/file_for_dot_read.sql
@@ -0,0 +1,4 @@
+
+INSERT INTO environ VALUES ('SEARCH_TERM', '%mount%');
+
+SELECT log_line, log_body FROM syslog_log WHERE log_body LIKE $SEARCH_TERM
diff --git a/test/formats/collision/format.json b/test/formats/collision/format.json
new file mode 100644
index 0000000..35c25c0
--- /dev/null
+++ b/test/formats/collision/format.json
@@ -0,0 +1,48 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "zblued_log": {
+ "title": "blued",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\w{3}\\s+\\d{1,2} \\d{2}:\\d{2}:\\d{2})(?: (?<log_hostname>[a-zA-Z0-9:][^ ]+[a-zA-Z0-9]))? blued(?:\\[(?<log_pid>\\d+)])?:(?<body>(?:.|\\n)*)$"
+ }
+ },
+ "level-field": "body",
+ "level": {
+ "error": "(?:failed|failure|error)",
+ "warning" : "(?:warn|not responding|init: cannot execute)"
+ },
+ "value" : {
+ "log_hostname" : {
+ "kind" : "string",
+ "collate" : "ipaddress",
+ "identifier" : true
+ }
+ },
+ "sample" : [
+ {
+ "line" : "Apr 4 20:02:32 Tim-Stacks-iMac.local blued[59]: Release the WiFi lock"
+ }
+ ]
+ },
+ "xerror_log" : {
+ "title" : "Common Error Log",
+ "description" : "The default web error log format for servers like Apache.",
+ "regex" : {
+ "cups" : {
+ "pattern" : "^(?<level>\\w) \\[(?<timestamp>[^\\]]+)\\] (?<body>.*)"
+ }
+ },
+ "level-field": "level",
+ "level" : {
+ "error" : "E",
+ "warning" : "W",
+ "info" : "I"
+ },
+ "sample" : [
+ {
+ "line" : "E [08/Jun/2013:11:28:58 -0700] Unknown directive BrowseOrder on line 22 of /private/etc/cups/cupsd.conf."
+ }
+ ]
+ }
+}
diff --git a/test/formats/customlevel/format.json b/test/formats/customlevel/format.json
new file mode 100644
index 0000000..dde41fe
--- /dev/null
+++ b/test/formats/customlevel/format.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "leveltest_log": {
+ "description": "Log format used for testing levels",
+ "regex": {
+ "line": {
+ "pattern": "^(?<timestamp>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) (?<level>[^ ]+) (?<body>.*)$"
+ }
+ },
+ "level": {
+ "trace": "trace",
+ "debug": "debug",
+ "debug2": "debug2",
+ "debug3": "debug3",
+ "info": "info",
+ "warning": "warn",
+ "fatal": "fatal"
+ },
+ "sample": [
+ {
+ "line": "2016-06-30 12:00:01 trace tracemessage"
+ }
+ ]
+ }
+}
diff --git a/test/formats/jsontest-subsec/format.json b/test/formats/jsontest-subsec/format.json
new file mode 100644
index 0000000..8469c7f
--- /dev/null
+++ b/test/formats/jsontest-subsec/format.json
@@ -0,0 +1,27 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "subsec_json_log": {
+ "title": "JSON Log with subsecond field",
+ "json": true,
+ "file-pattern": "logfile_json_subsec\\.json",
+ "line-format": [
+ {
+ "field": "__timestamp__"
+ },
+ " ",
+ {
+ "field": "msg"
+ }
+ ],
+ "timestamp-field": "instant/epochSecond",
+ "subsecond-field": "instant/nanoOfSecond",
+ "subsecond-units": "nano",
+ "body-field": "msg",
+ "value": {
+ "instant": {
+ "kind": "json",
+ "hidden": true
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/formats/jsontest/format.json b/test/formats/jsontest/format.json
new file mode 100644
index 0000000..78300e9
--- /dev/null
+++ b/test/formats/jsontest/format.json
@@ -0,0 +1,36 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "test_log" : {
+ "title" : "Test JSON Log",
+ "json" : true,
+ "file-pattern" : "logfile_json\\.json",
+ "description" : "Test config",
+ "line-format" : [
+ "\n[",
+ { "field" : "ts" },
+ "] ",
+ { "field" : "lvl" },
+ " ",
+ { "field" : "msg" }
+ ],
+ "level-field" : "lvl",
+ "timestamp-field": "ts",
+ "body-field" : "msg",
+ "value" : {
+ "msg" : {
+ "rewriter" : ";SELECT :msg || 'bork bork bork'"
+ },
+ "arr" : {
+ "kind" : "json"
+ },
+ "obj" : {
+ "kind" : "json"
+ },
+ "user" : {
+ "kind" : "string",
+ "identifier" : true,
+ "rewriter" : "|rewrite-user"
+ }
+ }
+ }
+}
diff --git a/test/formats/jsontest/lnav-logstash.json b/test/formats/jsontest/lnav-logstash.json
new file mode 100644
index 0000000..27f9239
--- /dev/null
+++ b/test/formats/jsontest/lnav-logstash.json
@@ -0,0 +1,47 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "logstash_dam": {
+ "title": "Logstash Java JSON",
+ "url": "https://github.com/logstash/logstash-logback-encoder",
+ "description": "Log format for DAM Logstash JSON",
+ "json": true,
+ "hide-extra": false,
+ "file-pattern": "\\.clog.*",
+ "multiline": false,
+ "line-format": [
+ { "field" : "@timestamp" },
+ " ",
+ { "field" : "ipaddress" },
+ " ",
+ { "field" : "message" },
+ " ",
+ { "field" : "stack_trace", "default-value" : "" }
+ ],
+ "timestamp-field" : "@timestamp",
+ "body-field" : "message",
+ "level-field" : "level",
+ "level" : {
+ "trace" : "TRACE",
+ "debug" : "DEBUG",
+ "info" : "INFO",
+ "error" : "ERROR",
+ "warning" : "WARN"
+ },
+ "value" : {
+ "logger_name" : {
+ "kind" : "string",
+ "identifier" : true
+ },
+ "ipaddress" : {
+ "kind" : "string",
+ "identifier" : true
+ },
+ "level_value" : {
+ "hidden": true
+ },
+ "stack_trace" : {
+ "kind" : "string"
+ }
+ }
+ }
+}
diff --git a/test/formats/jsontest/rewrite-user.lnav b/test/formats/jsontest/rewrite-user.lnav
new file mode 100644
index 0000000..e34aa78
--- /dev/null
+++ b/test/formats/jsontest/rewrite-user.lnav
@@ -0,0 +1,2 @@
+
+;SELECT 'mailto:' || :user
diff --git a/test/formats/jsontest2/format.json b/test/formats/jsontest2/format.json
new file mode 100644
index 0000000..167aa0f
--- /dev/null
+++ b/test/formats/jsontest2/format.json
@@ -0,0 +1,49 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "json_log2": {
+ "title": "Test JSON Log with integer levels",
+ "json": true,
+ "file-pattern": "logfile_.*json2\\.json",
+ "description": "Test config",
+ "line-format": [
+ {
+ "field": "ts"
+ },
+ " ",
+ {
+ "field": "ts",
+ "timestamp-format": "abc %S def"
+ },
+ " ",
+ {
+ "field": "lvl",
+ "min-width": 5
+ },
+ " ",
+ {
+ "field": "cl",
+ "max-width": 5
+ },
+ " ",
+ {
+ "field": "msg"
+ }
+ ],
+ "level-field": "lvl",
+ "level": {
+ "info": 0,
+ "error": 10
+ },
+ "timestamp-field": "ts",
+ "body-field": "msg",
+ "value": {
+ "user": {
+ "kind": "string",
+ "identifier": true
+ },
+ "cl": {
+ "kind": "string"
+ }
+ }
+ }
+}
diff --git a/test/formats/jsontest3/format.json b/test/formats/jsontest3/format.json
new file mode 100644
index 0000000..63cc2a6
--- /dev/null
+++ b/test/formats/jsontest3/format.json
@@ -0,0 +1,75 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "json_log3": {
+ "title": "Test JSON Log Format",
+ "description": "Test JSON Log Format",
+ "file-pattern": "logfile_.*json3\\.json",
+ "json": true,
+ "hide-extra": true,
+ "convert-to-local-time": true,
+ "line-format": [
+ {
+ "field": "__timestamp__"
+ },
+ " ",
+ {
+ "field": "client_ip"
+ },
+ " ",
+ {
+ "field": "request/method"
+ },
+ " ",
+ {
+ "field": "response/status"
+ },
+ " ",
+ {
+ "field": "request/uri"
+ }
+ ],
+ "value": {
+ "started_at": {
+ "kind": "integer",
+ "identifier": true
+ },
+ "client_ip": {
+ "kind": "string",
+ "identifier": true
+ },
+ "request/method": {
+ "kind": "string",
+ "identifier": true
+ },
+ "request/uri": {
+ "kind": "string",
+ "identifier": true
+ },
+ "request/size": {
+ "kind": "integer",
+ "identifier": false,
+ "hidden": true
+ },
+ "response/status": {
+ "kind": "string"
+ },
+ "details1": {
+ "hidden": true
+ },
+ "details2": {
+ "hidden": true
+ },
+ "details3": {
+ "hidden": true
+ }
+ },
+ "timestamp-field": "started_at",
+ "timestamp-divisor": 1000,
+ "level-field": "response/status",
+ "level": {
+ "info": "2\\d+",
+ "warning": "4\\d+",
+ "critical": "5\\d+"
+ }
+ }
+}
diff --git a/test/formats/nestedjson/format.json b/test/formats/nestedjson/format.json
new file mode 100644
index 0000000..afa6b08
--- /dev/null
+++ b/test/formats/nestedjson/format.json
@@ -0,0 +1,32 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "ntest_log": {
+ "title": "Test JSON Log",
+ "json": true,
+ "file-pattern": "logfile_(nested|invalid)_json\\d*\\.json",
+ "description": "Test config",
+ "line-format": [
+ {
+ "field": "ts"
+ },
+ " ",
+ {
+ "field": "/@fields/lvl"
+ },
+ " ",
+ { "field" : "@fields/msg" }
+ ],
+ "level-field" : "/@fields/lvl",
+ "timestamp-field": "ts",
+ "body-field" : "@fields/msg",
+ "value" : {
+ "@fields/user" : {
+ "kind" : "string",
+ "identifier" : true
+ },
+ "@fields/trace#" : {
+ "kind" : "string"
+ }
+ }
+ }
+}
diff --git a/test/formats/scripts/multiline-echo.lnav b/test/formats/scripts/multiline-echo.lnav
new file mode 100644
index 0000000..6913088
--- /dev/null
+++ b/test/formats/scripts/multiline-echo.lnav
@@ -0,0 +1,3 @@
+;SELECT 'World' as name
+:echo Hello, ${name}!
+Goodbye, ${name}!
diff --git a/test/formats/scripts/nested-redirecting.lnav b/test/formats/scripts/nested-redirecting.lnav
new file mode 100644
index 0000000..785c605
--- /dev/null
+++ b/test/formats/scripts/nested-redirecting.lnav
@@ -0,0 +1,5 @@
+:echo HOWDY!
+:redirect-to hw2.txt
+:echo HELLO, WORLD!
+:redirect-to
+:echo GOODBYE, WORLD!
diff --git a/test/formats/scripts/redirecting.lnav b/test/formats/scripts/redirecting.lnav
new file mode 100644
index 0000000..84b42c2
--- /dev/null
+++ b/test/formats/scripts/redirecting.lnav
@@ -0,0 +1,6 @@
+:echo Howdy!
+:redirect-to hw.txt
+:echo Hello, World!
+|nested-redirecting
+:redirect-to
+:echo Goodbye, World!
diff --git a/test/formats/sqldir/init.sql b/test/formats/sqldir/init.sql
new file mode 100644
index 0000000..4e17034
--- /dev/null
+++ b/test/formats/sqldir/init.sql
@@ -0,0 +1,5 @@
+
+CREATE VIEW web_status AS
+ SELECT group_concat(cs_uri_stem), sc_status FROM access_log group by sc_status;
+
+INSERT into lnav_view_filters VALUES ("log", 5, 0, "in", "regex", "credential status");
diff --git a/test/formats/timestamp/format.json b/test/formats/timestamp/format.json
new file mode 100644
index 0000000..2a3740a
--- /dev/null
+++ b/test/formats/timestamp/format.json
@@ -0,0 +1,26 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "epoch_log": {
+ "title": "epoch timestamp test",
+ "regex": {
+ "std": {
+ "pattern": "^(?<timestamp>\\d+) (?<body>.*)$"
+ },
+ "non_epoch": {
+ "pattern": "^(?<timestamp>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d+) (?<body>.*)$"
+ }
+ },
+ "timestamp-format": [
+ "%i",
+ "%Y-%m-%d %H:%M:%S.%f"
+ ],
+ "sample": [
+ {
+ "line": "1428634687123 Hello, World!"
+ },
+ {
+ "line": "2022-09-10 19:57:36.123456 Hello, World"
+ }
+ ]
+ }
+}
diff --git a/test/formats/xmlmsg/format.json b/test/formats/xmlmsg/format.json
new file mode 100644
index 0000000..efd6f42
--- /dev/null
+++ b/test/formats/xmlmsg/format.json
@@ -0,0 +1,73 @@
+{
+ "$schema": "https://lnav.org/schemas/format-v1.schema.json",
+ "xml_msg_log": {
+ "title": "",
+ "description": "",
+ "regex": {
+ "std": {
+ "pattern": "^\\[(?<timestamp>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3})\\]\\s+(?<level>\\w+)\\s+\\[(?<module>[^:]*):(?<line>\\d+)\\]\\s*(?<body>[^\\n]*)\\n?(?<msg_data>.*)"
+ }
+ },
+ "level": {
+ "critical": "CRITICAL",
+ "error": "ERROR",
+ "warning": "WARNING",
+ "info": "INFO",
+ "debug": "DEBUG"
+ },
+ "value": {
+ "module": {
+ "kind": "string",
+ "identifier": true,
+ "description": "Python source module which emitted log entry",
+ "rewriter": ";SELECT ''"
+ },
+ "line": {
+ "kind": "integer",
+ "description": "Line number – in the module – where log entry was emitted"
+ },
+ "msg_data": {
+ "kind": "xml",
+ "rewriter": ";SELECT node_path FROM xpath('//*', :msg_data)"
+ }
+ },
+ "highlights": {
+ "client_id": {
+ "pattern": "(?<=>)\\d+(?=<\/client>)",
+ "color": "Orange1",
+ "underline": true
+ },
+ "reply_error": {
+ "pattern": "(?<=<result>)ERROR(?=</result>)",
+ "color": "Red1"
+ },
+ "request": {
+ "pattern": "<request[^>]*>",
+ "color": "Green"
+ },
+ "reply": {
+ "pattern": "<head[^>]*>",
+ "color": "Gold1"
+ }
+ },
+ "tags": {
+ "xml-req": {
+ "pattern": "Full request text:"
+ }
+ },
+ "sample": [
+ {
+ "line": "[2020-12-10 06:56:41,477] INFO [m:108] Calling 'x' with params:",
+ "level": "info"
+ },
+ {
+ "line": "[2020-12-10 06:56:41,092] DEBUG [m:69] Full request text:\n<?xml version='1.0' encoding='iso-8859-2'?>\n<a-request>\n <head>\n x\n </head>\n <source>\n x\n </source>\n <request>\n <name>\n x\n </name>\n </request>\n</a-request>\n",
+ "level": "debug"
+ },
+ {
+ "line": "[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text:\n<?xml version='1.0' encoding='iso-8859-2'?>\n<a-reply>\n <head>\n x\n </head>\n <reply>\n <status>\n <result>OK</result>\n </status>\n <name>\n x\n </name>\n </reply>\n <technical-track>\n x\n </technical-track>\n</a-reply>\n",
+ "level": "debug"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/test/gp_test.cc b/test/gp_test.cc
new file mode 100644
index 0000000..ba2700b
--- /dev/null
+++ b/test/gp_test.cc
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "grep_proc.hh"
+#include "line_buffer.hh"
+#include "logfile.hh"
+
+class my_source : public grep_proc_source {
+public:
+ logfile* ms_lf;
+
+ my_source(logfile* lf) : ms_lf(lf){};
+
+ size_t grep_lines(void)
+ {
+ return this->ms_lf->size();
+ };
+
+ void grep_value_for_line(int line, std::string& value_out, int pass)
+ {
+ value_out = this->ms_lf->read_line(this->ms_lf->begin() + line);
+ };
+};
+
+class my_sink : public grep_proc_sink {
+public:
+ void grep_match(grep_line_t line, int start, int end)
+ {
+ printf("%d - %d:%d\n", (int) line, start, end);
+ };
+};
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_fd fd;
+
+ fd = open("/tmp/gp.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ fprintf(stderr, "startup\n");
+
+ if (argc < 2) {
+ fprintf(stderr, "error: no file given\n");
+ } else {
+ logfile lf(argv[1]);
+ lf.rebuild_index();
+ my_source ms(&lf);
+ my_sink msink;
+ grep_proc gp("pnp", ms);
+
+ gp.start();
+ gp.set_sink(&msink);
+
+ fd_set read_fds;
+
+ int maxfd = gp.update_fd_set(read_fds);
+
+ while (1) {
+ fd_set rfds = read_fds;
+ select(maxfd + 1, &rfds, NULL, NULL, NULL);
+
+ gp.check_fd_set(rfds);
+ if (!FD_ISSET(maxfd, &read_fds))
+ break;
+ }
+ }
+
+ return retval;
+}
diff --git a/test/lb_test.cc b/test/lb_test.cc
new file mode 100644
index 0000000..d82ad3c
--- /dev/null
+++ b/test/lb_test.cc
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "line_buffer.hh"
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_fd fd;
+
+ fd = open("/tmp/lb.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ fprintf(stderr, "startup\n");
+
+ if (argc < 2) {
+ fprintf(stderr, "error: no file given\n");
+ } else if ((fd = open(argv[1], O_RDONLY)) == -1) {
+ perror("open");
+ } else {
+ const char* line;
+ line_buffer lb;
+ size_t len;
+
+ lb.set_fd(fd);
+ while ((line = lb.read_line(len)) != NULL) {
+ printf("%s\n", line);
+ }
+ }
+
+ return retval;
+}
diff --git a/test/listview_output.0 b/test/listview_output.0
new file mode 100644
index 0000000..3d82d0d
--- /dev/null
+++ b/test/listview_output.0
@@ -0,0 +1,70 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 1 ┋Hello x┋
+A └┛ alt
+S 2 ┋World! x┋
+A └┛ alt
+S 3 ┋ x┋
+A └┛ alt
+S 4 ┋ x┋
+A └┛ alt
+S 5 ┋ x┋
+A └┛ alt
+S 6 ┋ x┋
+A └┛ alt
+S 7 ┋ x┋
+A └┛ alt
+S 8 ┋ x┋
+A └┛ alt
+S 9 ┋ x┋
+A └┛ alt
+S 10 ┋ x┋
+A └┛ alt
+S 11 ┋ x┋
+A └┛ alt
+S 12 ┋ x┋
+A └┛ alt
+S 13 ┋ x┋
+A └┛ alt
+S 14 ┋ x┋
+A └┛ alt
+S 15 ┋ x┋
+A └┛ alt
+S 16 ┋ x┋
+A └┛ alt
+S 17 ┋ x┋
+A └┛ alt
+S 18 ┋ x┋
+A └┛ alt
+S 19 ┋ x┋
+A └┛ alt
+S 20 ┋ x┋
+A └┛ alt
+S 21 ┋ x┋
+A └┛ alt
+S 22 ┋ x┋
+A └┛ alt
+S 23 ┋ x┋
+A └┛ alt
+S 24 ┋ x ┋
+A ···············································································└ backspace
+A └┛ alt
+A ···············································································└ backspace
+CSI Set Replace mode
+S 24 ┋ ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.1 b/test/listview_output.1
new file mode 100644
index 0000000..17f7202
--- /dev/null
+++ b/test/listview_output.1
@@ -0,0 +1,70 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 1 ┋World! x┋
+A └┛ alt
+S 2 ┋ x┋
+A └┛ alt
+S 3 ┋ x┋
+A └┛ alt
+S 4 ┋ x┋
+A └┛ alt
+S 5 ┋ x┋
+A └┛ alt
+S 6 ┋ x┋
+A └┛ alt
+S 7 ┋ x┋
+A └┛ alt
+S 8 ┋ x┋
+A └┛ alt
+S 9 ┋ x┋
+A └┛ alt
+S 10 ┋ x┋
+A └┛ alt
+S 11 ┋ x┋
+A └┛ alt
+S 12 ┋ x┋
+A └┛ alt
+S 13 ┋ x┋
+A └┛ alt
+S 14 ┋ x┋
+A └┛ alt
+S 15 ┋ x┋
+A └┛ alt
+S 16 ┋ x┋
+A └┛ alt
+S 17 ┋ x┋
+A └┛ alt
+S 18 ┋ x┋
+A └┛ alt
+S 19 ┋ x┋
+A └┛ alt
+S 20 ┋ x┋
+A └┛ alt
+S 21 ┋ x┋
+A └┛ alt
+S 22 ┋ x┋
+A └┛ alt
+S 23 ┋ x┋
+A └┛ alt
+S 24 ┋ x ┋
+A ···············································································└ backspace
+A └┛ alt
+A ···············································································└ backspace
+CSI Set Replace mode
+S 24 ┋ ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.2 b/test/listview_output.2
new file mode 100644
index 0000000..a028d66
--- /dev/null
+++ b/test/listview_output.2
@@ -0,0 +1,70 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 1 ┋ello x┋
+A └┛ alt
+S 2 ┋orld! x┋
+A └┛ alt
+S 3 ┋ x┋
+A └┛ alt
+S 4 ┋ x┋
+A └┛ alt
+S 5 ┋ x┋
+A └┛ alt
+S 6 ┋ x┋
+A └┛ alt
+S 7 ┋ x┋
+A └┛ alt
+S 8 ┋ x┋
+A └┛ alt
+S 9 ┋ x┋
+A └┛ alt
+S 10 ┋ x┋
+A └┛ alt
+S 11 ┋ x┋
+A └┛ alt
+S 12 ┋ x┋
+A └┛ alt
+S 13 ┋ x┋
+A └┛ alt
+S 14 ┋ x┋
+A └┛ alt
+S 15 ┋ x┋
+A └┛ alt
+S 16 ┋ x┋
+A └┛ alt
+S 17 ┋ x┋
+A └┛ alt
+S 18 ┋ x┋
+A └┛ alt
+S 19 ┋ x┋
+A └┛ alt
+S 20 ┋ x┋
+A └┛ alt
+S 21 ┋ x┋
+A └┛ alt
+S 22 ┋ x┋
+A └┛ alt
+S 23 ┋ x┋
+A └┛ alt
+S 24 ┋ x ┋
+A ···············································································└ backspace
+A └┛ alt
+A ···············································································└ backspace
+CSI Set Replace mode
+S 24 ┋ ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.3 b/test/listview_output.3
new file mode 100644
index 0000000..b29ea7d
--- /dev/null
+++ b/test/listview_output.3
@@ -0,0 +1,70 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 1 ┋orld! x┋
+A └┛ alt
+S 2 ┋ x┋
+A └┛ alt
+S 3 ┋ x┋
+A └┛ alt
+S 4 ┋ x┋
+A └┛ alt
+S 5 ┋ x┋
+A └┛ alt
+S 6 ┋ x┋
+A └┛ alt
+S 7 ┋ x┋
+A └┛ alt
+S 8 ┋ x┋
+A └┛ alt
+S 9 ┋ x┋
+A └┛ alt
+S 10 ┋ x┋
+A └┛ alt
+S 11 ┋ x┋
+A └┛ alt
+S 12 ┋ x┋
+A └┛ alt
+S 13 ┋ x┋
+A └┛ alt
+S 14 ┋ x┋
+A └┛ alt
+S 15 ┋ x┋
+A └┛ alt
+S 16 ┋ x┋
+A └┛ alt
+S 17 ┋ x┋
+A └┛ alt
+S 18 ┋ x┋
+A └┛ alt
+S 19 ┋ x┋
+A └┛ alt
+S 20 ┋ x┋
+A └┛ alt
+S 21 ┋ x┋
+A └┛ alt
+S 22 ┋ x┋
+A └┛ alt
+S 23 ┋ x┋
+A └┛ alt
+S 24 ┋ x ┋
+A ···············································································└ backspace
+A └┛ alt
+A ···············································································└ backspace
+CSI Set Replace mode
+S 24 ┋ ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.4 b/test/listview_output.4
new file mode 100644
index 0000000..8f6c5e7
--- /dev/null
+++ b/test/listview_output.4
@@ -0,0 +1,68 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 2 ┋Hello x┋
+A └┛ alt
+S 3 ┋World! x┋
+A └┛ alt
+S 4 ┋2 x┋
+A └┛ alt
+S 5 ┋3 x┋
+A └┛ alt
+S 6 ┋4 x┋
+A └┛ alt
+S 7 ┋5 x┋
+A └┛ alt
+S 8 ┋6 x┋
+A └┛ alt
+S 9 ┋7 x┋
+A └┛ alt
+S 10 ┋8 x┋
+A └┛ alt
+S 11 ┋9 x┋
+A └┛ alt
+S 12 ┋10 x┋
+A └┛ alt
+S 13 ┋11 x┋
+A └┛ alt
+S 14 ┋12 x┋
+A └┛ alt
+S 15 ┋13 x┋
+A └┛ alt
+S 16 ┋14 x┋
+A └┛ alt
+S 17 ┋15 x┋
+A └┛ alt
+S 18 ┋16 x┋
+A └┛ alt
+S 19 ┋17 x┋
+A └┛ alt
+S 20 ┋18 x┋
+A └┛ alt
+S 21 ┋19 x┋
+A └┛ alt
+S 22 ┋20 x┋
+A └┛ alt
+S 23 ┋21 x┋
+A └┛ alt
+S 24 ┋22 x ┋
+A ···············································································└ backspace
+A └┛ alt
+A ···············································································└ backspace
+CSI Set Replace mode
+S 24 ┋ ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.5 b/test/listview_output.5
new file mode 100644
index 0000000..021b8d7
--- /dev/null
+++ b/test/listview_output.5
@@ -0,0 +1,59 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 2 ┋Hello x┋
+A └┛ alt
+S 3 ┋World! x┋
+A └┛ alt
+S 4 ┋2 x┋
+A └┛ alt
+S 5 ┋3 x┋
+A └┛ alt
+S 6 ┋4 x┋
+A └┛ alt
+S 7 ┋5 x┋
+A └┛ alt
+S 8 ┋6 x┋
+A └┛ alt
+S 9 ┋7 x┋
+A └┛ alt
+S 10 ┋8 x┋
+A └┛ alt
+S 11 ┋9 x┋
+A └┛ alt
+S 12 ┋10 x┋
+A └┛ alt
+S 13 ┋11 x┋
+A └┛ alt
+S 14 ┋12 x┋
+A └┛ alt
+S 15 ┋13 x┋
+A └┛ alt
+S 16 ┋14 x┋
+A └┛ alt
+S 17 ┋15 x┋
+A └┛ alt
+S 18 ┋16 x┋
+A └┛ alt
+S 19 ┋17 x┋
+A └┛ alt
+S 20 ┋18 x┋
+A └┛ alt
+S 21 ┋19 x┋
+A └┛ alt
+S 22 ┋20 x┋
+A └┛ alt
+S 23 ┋21 x┋
+A └┛ alt
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/listview_output.6 b/test/listview_output.6
new file mode 100644
index 0000000..f5765d5
--- /dev/null
+++ b/test/listview_output.6
@@ -0,0 +1,59 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 2 ┋World! x┋
+A └┛ alt
+S 3 ┋2 x┋
+A └┛ alt
+S 4 ┋3 x┋
+A └┛ alt
+S 5 ┋4 x┋
+A └┛ alt
+S 6 ┋5 x┋
+A └┛ alt
+S 7 ┋6 x┋
+A └┛ alt
+S 8 ┋7 x┋
+A └┛ alt
+S 9 ┋8 x┋
+A └┛ alt
+S 10 ┋9 x┋
+A └┛ alt
+S 11 ┋10 x┋
+A └┛ alt
+S 12 ┋11 x┋
+A └┛ alt
+S 13 ┋12 x┋
+A └┛ alt
+S 14 ┋13 x┋
+A └┛ alt
+S 15 ┋14 x┋
+A └┛ alt
+S 16 ┋15 x┋
+A └┛ alt
+S 17 ┋16 x┋
+A └┛ alt
+S 18 ┋17 x┋
+A └┛ alt
+S 19 ┋18 x┋
+A └┛ alt
+S 20 ┋19 x┋
+A └┛ alt
+S 21 ┋20 x┋
+A └┛ alt
+S 22 ┋21 x┋
+A └┛ alt
+S 23 ┋22 x┋
+A └┛ alt
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/lnav_doctests.cc b/test/lnav_doctests.cc
new file mode 100644
index 0000000..423f807
--- /dev/null
+++ b/test/lnav_doctests.cc
@@ -0,0 +1,231 @@
+/**
+ * Copyright (c) 2017, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "byte_array.hh"
+#include "data_scanner.hh"
+#include "doctest/doctest.h"
+#include "lnav_config.hh"
+#include "lnav_util.hh"
+#include "relative_time.hh"
+#include "unique_path.hh"
+
+using namespace std;
+
+#if 0
+TEST_CASE("overwritten-logfile") {
+ string fname = "reload_test.0";
+
+ ofstream(fname) << "test 1\n";
+
+ logfile_open_options loo;
+ logfile lf(fname, loo);
+ auto build_result = lf.rebuild_index();
+ CHECK(build_result == logfile::RR_NEW_LINES);
+ CHECK(lf.size() == 1);
+
+ sleep(1);
+ ofstream(fname) << "test 2\n";
+ auto rebuild_result = lf.rebuild_index();
+ CHECK(rebuild_result == logfile::RR_NO_NEW_LINES);
+ CHECK(lf.is_closed());
+}
+#endif
+
+TEST_CASE("byte_array")
+{
+ using my_array_t = byte_array<8>;
+
+ my_array_t ba1;
+
+ memcpy(ba1.out(), "abcd1234", my_array_t::BYTE_COUNT);
+ CHECK(ba1.to_string() == "6162636431323334");
+ auto ba2 = ba1;
+ CHECK(ba1 == ba2);
+ CHECK_FALSE(ba1 != ba2);
+ CHECK_FALSE(ba1 < ba2);
+
+ my_array_t ba3;
+
+ memcpy(ba3.out(), "abcd1235", my_array_t::BYTE_COUNT);
+ CHECK(ba1 < ba3);
+ CHECK_FALSE(ba3 < ba1);
+
+ ba1.clear();
+ CHECK(ba1.to_string() == "0000000000000000");
+ CHECK(ba2.to_string() == "6162636431323334");
+
+ auto outbuf = auto_buffer::alloc(my_array_t::STRING_SIZE);
+ ba2.to_string(std::back_inserter(outbuf));
+ CHECK(std::string(outbuf.in(), outbuf.size()) == "6162636431323334");
+}
+
+TEST_CASE("ptime_fmt")
+{
+ const char* date_str = "2018-05-16 18:16:42";
+ struct exttm tm;
+ off_t off = 0;
+
+ bool rc
+ = ptime_fmt("%Y-%d-%m\t%H:%M:%S", &tm, date_str, off, strlen(date_str));
+ CHECK(!rc);
+ CHECK(off == 8);
+}
+
+TEST_CASE("rgb_color from string")
+{
+ string name = "SkyBlue1";
+ auto color = rgb_color::from_str(name).unwrap();
+ CHECK(color.rc_r == 135);
+ CHECK(color.rc_g == 215);
+ CHECK(color.rc_b == 255);
+}
+
+TEST_CASE("ptime_roundtrip")
+{
+ const char* fmts[] = {
+ "%Y-%m-%d %l:%M:%S %p",
+ "%Y-%m-%d %I:%M:%S %p",
+ };
+ time_t now = time(nullptr);
+
+ for (const auto* fmt : fmts) {
+ for (time_t sec = now; sec < (now + (24 * 60 * 60)); sec++) {
+ char ftime_result[128];
+ char strftime_result[128];
+ struct exttm etm;
+
+ memset(&etm, 0, sizeof(etm));
+ gmtime_r(&sec, &etm.et_tm);
+ etm.et_flags = ETF_YEAR_SET | ETF_MONTH_SET | ETF_DAY_SET;
+ size_t ftime_size
+ = ftime_fmt(ftime_result, sizeof(ftime_result), fmt, etm);
+ size_t strftime_size = strftime(
+ strftime_result, sizeof(strftime_result), fmt, &etm.et_tm);
+
+ CHECK(string(ftime_result, ftime_size)
+ == string(strftime_result, strftime_size));
+
+ struct exttm etm2;
+ off_t off = 0;
+
+ memset(&etm2, 0, sizeof(etm2));
+ bool rc = ptime_fmt(fmt, &etm2, ftime_result, off, ftime_size);
+ CHECK(rc);
+ CHECK(sec == tm2sec(&etm2.et_tm));
+ }
+ }
+}
+
+class my_path_source : public unique_path_source {
+public:
+ explicit my_path_source(ghc::filesystem::path p) : mps_path(std::move(p)) {}
+
+ ghc::filesystem::path get_path() const override { return this->mps_path; }
+
+ ghc::filesystem::path mps_path;
+};
+
+TEST_CASE("unique_path")
+{
+ unique_path_generator upg;
+
+ auto bar = make_shared<my_path_source>("/foo/bar");
+ auto bar_dupe = make_shared<my_path_source>("/foo/bar");
+ auto baz = make_shared<my_path_source>("/foo/baz");
+ auto baz2 = make_shared<my_path_source>("/foo2/bar");
+ auto log1 = make_shared<my_path_source>(
+ "/home/bob/downloads/machine1/var/log/syslog.log");
+ auto log2 = make_shared<my_path_source>(
+ "/home/bob/downloads/machine2/var/log/syslog.log");
+
+ upg.add_source(bar);
+ upg.add_source(bar_dupe);
+ upg.add_source(baz);
+ upg.add_source(baz2);
+ upg.add_source(log1);
+ upg.add_source(log2);
+
+ upg.generate();
+
+ CHECK(bar->get_unique_path() == "[foo]/bar");
+ CHECK(bar_dupe->get_unique_path() == "[foo]/bar");
+ CHECK(baz->get_unique_path() == "baz");
+ CHECK(baz2->get_unique_path() == "[foo2]/bar");
+ CHECK(log1->get_unique_path() == "[machine1]/syslog.log");
+ CHECK(log2->get_unique_path() == "[machine2]/syslog.log");
+}
+
+TEST_CASE("attr_line to json")
+{
+ attr_line_t al;
+
+ al.append("Hello, ").append(lnav::roles::symbol("World")).append("!");
+
+ auto json = lnav::to_json(al);
+ auto al2 = lnav::from_json<attr_line_t>(json).unwrap();
+ auto json2 = lnav::to_json(al2);
+
+ CHECK(json == json2);
+}
+
+TEST_CASE("user_message to json")
+{
+ auto um = lnav::console::user_message::error("testing")
+ .with_reason("because")
+ .with_snippet(lnav::console::snippet::from(
+ intern_string::lookup("hello.c"), "printf(")
+ .with_line(1))
+ .with_help("close it");
+
+ auto json = lnav::to_json(um);
+ auto um2 = lnav::from_json<lnav::console::user_message>(json).unwrap();
+ auto json2 = lnav::to_json(um2);
+
+ CHECK(json == json2);
+}
+
+TEST_CASE("data_scanner CSI")
+{
+ static const char INPUT[] = "\x1b[32mHello\x1b[0m";
+
+ data_scanner ds(string_fragment::from_const(INPUT));
+
+ auto tok_res = ds.tokenize2();
+ CHECK(tok_res->tr_token == DT_CSI);
+ CHECK(tok_res->to_string() == "\x1b[32m");
+ tok_res = ds.tokenize2();
+ CHECK(tok_res->tr_token == DT_SYMBOL);
+ CHECK(tok_res->to_string() == "Hello");
+ tok_res = ds.tokenize2();
+ CHECK(tok_res->tr_token == DT_CSI);
+ CHECK(tok_res->to_string() == "\x1b[0m");
+}
diff --git a/test/log-samples/sample-057d6c669632ef9d07b6adec605f6bdeae19af27.txt b/test/log-samples/sample-057d6c669632ef9d07b6adec605f6bdeae19af27.txt
new file mode 100644
index 0000000..c1d9b88
--- /dev/null
+++ b/test/log-samples/sample-057d6c669632ef9d07b6adec605f6bdeae19af27.txt
@@ -0,0 +1,13 @@
+ 2013-02-11 06:42:34,310:INFO:com.twisted:Site starting on 8099
+ key 29:29 ^
+ key 29:40 ^---------^ com.twisted
+pair 29:40 ^---------^ com.twisted
+ key 58:58 ^
+ num 58:62 ^--^ 8099
+pair 58:62 ^--^ 8099
+msg ::com.twisted:Site starting on 8099
+format ::#:Site starting on #
+{
+ "col_0": "com.twisted",
+ "col_1": 8099
+}
diff --git a/test/log-samples/sample-06aaa6f48a801f592558575d886864d6c3ab9ed4.txt b/test/log-samples/sample-06aaa6f48a801f592558575d886864d6c3ab9ed4.txt
new file mode 100644
index 0000000..aafb46d
--- /dev/null
+++ b/test/log-samples/sample-06aaa6f48a801f592558575d886864d6c3ab9ed4.txt
@@ -0,0 +1,40 @@
+ Apr 11 16:43:25 localhost smartd[2532]: Device: /dev/sda [SAT], VBOX HARDDISK, S/N:VBc8882b62-a0263a39, FW:1.0, 17.1 GB
+ key 40:46 ^----^ Device
+path 48:56 ^------^ /dev/sda
+wspc 56:57 ^
+ sym 58:61 ^-^ SAT
+ val 58:61 ^-^ SAT
+ grp 58:61 ^-^ SAT
+ val 48:61 ^-----------^ /dev/sda [SAT
+pair 40:61 ^-------------------^ Device: /dev/sda [SAT
+ key 64:64 ^
+ sym 64:68 ^--^ VBOX
+wspc 68:69 ^
+ sym 69:77 ^------^ HARDDISK
+ val 64:77 ^-----------^ VBOX HARDDISK
+pair 64:77 ^-----------^ VBOX HARDDISK
+ key 79:79 ^
+ sym 79:82 ^-^ S/N
+coln 82:83 ^ :
+ sym 83:102 ^-----------------^ VBc8882b62-a0263a39
+ val 79:102 ^---------------------^ S/N:VBc8882b62-a0263a39
+pair 79:102 ^---------------------^ S/N:VBc8882b62-a0263a39
+ key 104:106 ^^ FW
+ num 107:110 ^-^ 1.0
+ val 107:110 ^-^ 1.0
+pair 104:110 ^----^ FW:1.0
+ key 112:112 ^
+ num 112:116 ^--^ 17.1
+wspc 116:117 ^
+ sym 117:119 ^^ GB
+ val 112:119 ^-----^ 17.1 GB
+pair 112:119 ^-----^ 17.1 GB
+msg :Device: /dev/sda [SAT], VBOX HARDDISK, S/N:VBc8882b62-a0263a39, FW:1.0, 17.1 GB
+format :Device: #], #, #, FW:#, #
+{
+ "Device": "/dev/sda [SAT",
+ "col_0": "VBOX HARDDISK",
+ "col_1": "S/N:VBc8882b62-a0263a39",
+ "FW": 1.0,
+ "col_2": "17.1 GB"
+}
diff --git a/test/log-samples/sample-1aeb47c0a97d19bb7418f0172480e05e49c6e53e.txt b/test/log-samples/sample-1aeb47c0a97d19bb7418f0172480e05e49c6e53e.txt
new file mode 100644
index 0000000..289780a
--- /dev/null
+++ b/test/log-samples/sample-1aeb47c0a97d19bb7418f0172480e05e49c6e53e.txt
@@ -0,0 +1,17 @@
+ Apr 29 22:32:27 tstack-centos5 dhclient: bound to 10.1.10.62 -- renewal in 55327 seconds
+ key 50:50 ^
+ipv4 50:60 ^--------^ 10.1.10.62
+pair 50:60 ^--------^ 10.1.10.62
+ key 61:61 ^
+ sym 61:63 ^^ --
+pair 61:63 ^^ --
+ key 75:75 ^
+ num 75:80 ^---^ 55327
+pair 75:80 ^---^ 55327
+msg :bound to 10.1.10.62 -- renewal in 55327 seconds
+format :bound to # # renewal in # seconds
+{
+ "col_0": "10.1.10.62",
+ "col_1": "--",
+ "col_2": 55327
+}
diff --git a/test/log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt b/test/log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt
new file mode 100644
index 0000000..3a7277b
--- /dev/null
+++ b/test/log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt
@@ -0,0 +1,4 @@
+ Jun 3 07:00:23 Tim-Stacks-iMac.local sudo[2326]: stack : TTY=ttys002 ; PWD=/ ; USER=root ; COMMAND=/bin/ls
+msg :
+format :
+null
diff --git a/test/log-samples/sample-3856ad0f551a04fde41a020158d6b33ef97c870a.txt b/test/log-samples/sample-3856ad0f551a04fde41a020158d6b33ef97c870a.txt
new file mode 100644
index 0000000..5d5d347
--- /dev/null
+++ b/test/log-samples/sample-3856ad0f551a04fde41a020158d6b33ef97c870a.txt
@@ -0,0 +1,17 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: Leaving mDNS multicast group on interface eth0.IPv4 with address 10.1.10.62
+ key 59:59 ^
+ sym 59:63 ^--^ mDNS
+pair 59:63 ^--^ mDNS
+ key 93:93 ^
+ sym 93:102 ^-------^ eth0.IPv4
+pair 93:102 ^-------^ eth0.IPv4
+ key 116:116 ^
+ipv4 116:126 ^--------^ 10.1.10.62
+pair 116:126 ^--------^ 10.1.10.62
+msg :Leaving mDNS multicast group on interface eth0.IPv4 with address 10.1.10.62
+format :Leaving # multicast group on interface # with address #
+{
+ "col_0": "mDNS",
+ "col_1": "eth0.IPv4",
+ "col_2": "10.1.10.62"
+}
diff --git a/test/log-samples/sample-45364b3fd51af92a4ad8a309b5f4fd88.txt b/test/log-samples/sample-45364b3fd51af92a4ad8a309b5f4fd88.txt
new file mode 100644
index 0000000..e6799b7
--- /dev/null
+++ b/test/log-samples/sample-45364b3fd51af92a4ad8a309b5f4fd88.txt
@@ -0,0 +1,40 @@
+ Aug 20 06:36:07 Tim-Stacks-iMac kernel[0]: hibernate_teardown: wired_pages 518290, free_pages 5699523, active_pages 40010, inactive_pages 0, speculative_pages 0, cleaned_pages 0, compressor_pages 144
+ key 63:74 ^---------^ wired_pages
+ num 75:81 ^----^ 518290
+ val 75:81 ^----^ 518290
+pair 63:81 ^----------------^ wired_pages 518290
+ key 83:93 ^--------^ free_pages
+ num 94:101 ^-----^ 5699523
+ val 94:101 ^-----^ 5699523
+pair 83:101 ^----------------^ free_pages 5699523
+ key 103:115 ^----------^ active_pages
+ num 116:121 ^---^ 40010
+ val 116:121 ^---^ 40010
+pair 103:121 ^----------------^ active_pages 40010
+ key 123:137 ^------------^ inactive_pages
+ num 138:139 ^ 0
+ val 138:139 ^ 0
+pair 123:139 ^--------------^ inactive_pages 0
+ key 141:158 ^---------------^ speculative_pages
+ num 159:160 ^ 0
+ val 159:160 ^ 0
+pair 141:160 ^-----------------^ speculative_pages 0
+ key 162:175 ^-----------^ cleaned_pages
+ num 176:177 ^ 0
+ val 176:177 ^ 0
+pair 162:177 ^-------------^ cleaned_pages 0
+ key 179:195 ^--------------^ compressor_pages
+ num 196:199 ^-^ 144
+ val 196:199 ^-^ 144
+pair 179:199 ^------------------^ compressor_pages 144
+msg :hibernate_teardown: wired_pages 518290, free_pages 5699523, active_pages 40010, inactive_pages 0, speculative_pages 0, cleaned_pages 0, compressor_pages 144
+format :hibernate_teardown: wired_pages #, free_pages #, active_pages #, inactive_pages #, speculative_pages #, cleaned_pages #, compressor_pages #
+{
+ "wired_pages": 518290,
+ "free_pages": 5699523,
+ "active_pages": 40010,
+ "inactive_pages": 0,
+ "speculative_pages": 0,
+ "cleaned_pages": 0,
+ "compressor_pages": 144
+}
diff --git a/test/log-samples/sample-500c9e492e04f5f58862c8086ca301de0dd976ce.txt b/test/log-samples/sample-500c9e492e04f5f58862c8086ca301de0dd976ce.txt
new file mode 100644
index 0000000..ed7fa8e
--- /dev/null
+++ b/test/log-samples/sample-500c9e492e04f5f58862c8086ca301de0dd976ce.txt
@@ -0,0 +1,13 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: New relevant interface eth0.IPv4 for mDNS
+ key 74:74 ^
+ sym 74:83 ^-------^ eth0.IPv4
+pair 74:83 ^-------^ eth0.IPv4
+ key 88:88 ^
+ sym 88:92 ^--^ mDNS
+pair 88:92 ^--^ mDNS
+msg :New relevant interface eth0.IPv4 for mDNS
+format :New relevant interface # for #
+{
+ "col_0": "eth0.IPv4",
+ "col_1": "mDNS"
+}
diff --git a/test/log-samples/sample-55ac97afae4b0650ccb62e2dbc8d89bb.txt b/test/log-samples/sample-55ac97afae4b0650ccb62e2dbc8d89bb.txt
new file mode 100644
index 0000000..baee2e9
--- /dev/null
+++ b/test/log-samples/sample-55ac97afae4b0650ccb62e2dbc8d89bb.txt
@@ -0,0 +1,15 @@
+ Aug 25 00:30:32 Tim-Stacks-iMac.local iTunes[558]: Entered:__thr_AMMuxedDeviceDisconnected, mux-device:509
+ key 51:58 ^-----^ Entered
+ sym 59:90 ^-----------------------------^ __thr_AMMuxedDeviceDisconnected
+ val 59:90 ^-----------------------------^ __thr_AMMuxedDeviceDisconnected
+pair 51:90 ^-------------------------------------^ Entered:__thr_AMMuxedDeviceDisconnected
+ key 92:102 ^--------^ mux-device
+ num 103:106 ^-^ 509
+ val 103:106 ^-^ 509
+pair 92:106 ^------------^ mux-device:509
+msg :Entered:__thr_AMMuxedDeviceDisconnected, mux-device:509
+format :Entered:#, mux-device:#
+{
+ "Entered": "__thr_AMMuxedDeviceDisconnected",
+ "mux-device": 509
+}
diff --git a/test/log-samples/sample-6049d4309f26eefb1a3406d937a9ba8a0df592a7.txt b/test/log-samples/sample-6049d4309f26eefb1a3406d937a9ba8a0df592a7.txt
new file mode 100644
index 0000000..f424a86
--- /dev/null
+++ b/test/log-samples/sample-6049d4309f26eefb1a3406d937a9ba8a0df592a7.txt
@@ -0,0 +1,13 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: Withdrawing address record for 10.1.10.62 on eth0
+ key 82:82 ^
+ipv4 82:92 ^--------^ 10.1.10.62
+pair 82:92 ^--------^ 10.1.10.62
+ key 96:96 ^
+ sym 96:100 ^--^ eth0
+pair 96:100 ^--^ eth0
+msg :Withdrawing address record for 10.1.10.62 on eth0
+format :Withdrawing address record for # on #
+{
+ "col_0": "10.1.10.62",
+ "col_1": "eth0"
+}
diff --git a/test/log-samples/sample-62315d884afdc4155b35f905415c74bfcfd39fc2.txt b/test/log-samples/sample-62315d884afdc4155b35f905415c74bfcfd39fc2.txt
new file mode 100644
index 0000000..5a30cbc
--- /dev/null
+++ b/test/log-samples/sample-62315d884afdc4155b35f905415c74bfcfd39fc2.txt
@@ -0,0 +1,17 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: Joining mDNS multicast group on interface eth0.IPv4 with address 10.1.10.62
+ key 59:59 ^
+ sym 59:63 ^--^ mDNS
+pair 59:63 ^--^ mDNS
+ key 93:93 ^
+ sym 93:102 ^-------^ eth0.IPv4
+pair 93:102 ^-------^ eth0.IPv4
+ key 116:116 ^
+ipv4 116:126 ^--------^ 10.1.10.62
+pair 116:126 ^--------^ 10.1.10.62
+msg :Joining mDNS multicast group on interface eth0.IPv4 with address 10.1.10.62
+format :Joining # multicast group on interface # with address #
+{
+ "col_0": "mDNS",
+ "col_1": "eth0.IPv4",
+ "col_2": "10.1.10.62"
+}
diff --git a/test/log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt b/test/log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt
new file mode 100644
index 0000000..9d80bf9
--- /dev/null
+++ b/test/log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt
@@ -0,0 +1,4 @@
+ Jun 3 07:02:37 Tim-Stacks-iMac.local sudo[2717]: stack : TTY=ttys002 ; PWD=/ ; USER=root ; COMMAND=/usr/bin/env VAR1=foo ls
+msg :
+format :
+null
diff --git a/test/log-samples/sample-9cf7fbb3546c676c686fac0ed096d026f46c875f.txt b/test/log-samples/sample-9cf7fbb3546c676c686fac0ed096d026f46c875f.txt
new file mode 100644
index 0000000..d1bf5d4
--- /dev/null
+++ b/test/log-samples/sample-9cf7fbb3546c676c686fac0ed096d026f46c875f.txt
@@ -0,0 +1,13 @@
+ 2013-06-05T14:20:24 DEBUG cc2.main CC - 4672610200547811617359537811896212984085567168.114723023 Json_Reader - Doing prepare for resource name "Json_Reader", component "com.json.components.JSONReader"
+ key 144:144 ^
+quot 144:155 ^---------^ Json_Reader
+pair 144:155 ^---------^ Json_Reader
+ key 169:169 ^
+quot 169:199 ^----------------------------^ com.json.components.JSONReader
+pair 169:199 ^----------------------------^ com.json.components.JSONReader
+msg : Doing prepare for resource name "Json_Reader", component "com.json.components.JSONReader"
+format : Doing prepare for resource name #, component #
+{
+ "col_0": "Json_Reader",
+ "col_1": "com.json.components.JSONReader"
+}
diff --git a/test/log-samples/sample-a74570613c082c7fe283672031e18e54e8887ffb.txt b/test/log-samples/sample-a74570613c082c7fe283672031e18e54e8887ffb.txt
new file mode 100644
index 0000000..b2e0426
--- /dev/null
+++ b/test/log-samples/sample-a74570613c082c7fe283672031e18e54e8887ffb.txt
@@ -0,0 +1,13 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: Interface eth0.IPv4 no longer relevant for mDNS
+ key 61:61 ^
+ sym 61:70 ^-------^ eth0.IPv4
+pair 61:70 ^-------^ eth0.IPv4
+ key 94:94 ^
+ sym 94:98 ^--^ mDNS
+pair 94:98 ^--^ mDNS
+msg :Interface eth0.IPv4 no longer relevant for mDNS
+format :Interface # no longer relevant for #
+{
+ "col_0": "eth0.IPv4",
+ "col_1": "mDNS"
+}
diff --git a/test/log-samples/sample-aca2878a2e50779c6697c0747ab1f60e4b368dcb.txt b/test/log-samples/sample-aca2878a2e50779c6697c0747ab1f60e4b368dcb.txt
new file mode 100644
index 0000000..f5c31f2
--- /dev/null
+++ b/test/log-samples/sample-aca2878a2e50779c6697c0747ab1f60e4b368dcb.txt
@@ -0,0 +1,15 @@
+ Apr 29 08:13:43 tstack-centos5 NET[13682]: /sbin/dhclient-script : updated /etc/resolv.conf
+ key 43:43 ^
+path 43:64 ^-------------------^ /sbin/dhclient-script
+ val 43:64 ^-------------------^ /sbin/dhclient-script
+pair 43:64 ^-------------------^ /sbin/dhclient-script
+ key 67:74 ^-----^ updated
+path 75:91 ^--------------^ /etc/resolv.conf
+ val 75:91 ^--------------^ /etc/resolv.conf
+pair 67:91 ^----------------------^ updated /etc/resolv.conf
+msg :/sbin/dhclient-script : updated /etc/resolv.conf
+format :# : updated #
+{
+ "col_0": "/sbin/dhclient-script",
+ "updated": "/etc/resolv.conf"
+}
diff --git a/test/log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt b/test/log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt
new file mode 100644
index 0000000..63c22cc
--- /dev/null
+++ b/test/log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt
@@ -0,0 +1,21 @@
+ Jun 2 00:34:32 Tim-Stacks-iMac kernel[0]: vmnet: VNetUserIf_Create: created userIf at 0xffffff802644f400
+ key 43:48 ^---^ vmnet
+quot 49:49 ^
+ val 49:49 ^
+pair 43:49 ^----^ vmnet:
+ key 50:67 ^---------------^ VNetUserIf_Create
+word 69:76 ^-----^ created
+wspc 76:77 ^
+ sym 77:83 ^----^ userIf
+wspc 83:84 ^
+word 84:86 ^^ at
+wspc 86:87 ^
+ hex 87:105 ^----------------^ 0xffffff802644f400
+ val 69:105 ^----------------------------------^ created userIf at 0xffffff802644f400
+pair 50:105 ^-----------------------------------------------------^ VNetUserIf_Create: created userIf at 0xffffff802644f400
+msg :vmnet: VNetUserIf_Create: created userIf at 0xffffff802644f400
+format :vmnet:# VNetUserIf_Create: #
+{
+ "vmnet": "",
+ "VNetUserIf_Create": "created userIf at 0xffffff802644f400"
+}
diff --git a/test/log-samples/sample-bc6f6cf689fa5455616b4d9fbe121a48d3c9de59.txt b/test/log-samples/sample-bc6f6cf689fa5455616b4d9fbe121a48d3c9de59.txt
new file mode 100644
index 0000000..32d86d0
--- /dev/null
+++ b/test/log-samples/sample-bc6f6cf689fa5455616b4d9fbe121a48d3c9de59.txt
@@ -0,0 +1,25 @@
+ Apr 29 08:13:42 tstack-centos5 dhclient: DHCPNAK from 10.1.10.1 (xid=0x4e17f141)
+ key 41:41 ^
+ sym 41:48 ^-----^ DHCPNAK
+pair 41:48 ^-----^ DHCPNAK
+ key 54:54 ^
+ipv4 54:63 ^-------^ 10.1.10.1
+pair 54:63 ^-------^ 10.1.10.1
+ key 65:65 ^
+ key 65:68 ^-^ xid
+ hex 69:79 ^--------^ 0x4e17f141
+ val 69:79 ^--------^ 0x4e17f141
+pair 65:79 ^------------^ xid=0x4e17f141
+ grp 65:79 ^------------^ xid=0x4e17f141
+pair 65:79 ^------------^ xid=0x4e17f141
+msg :DHCPNAK from 10.1.10.1 (xid=0x4e17f141)
+format :# from # (#)
+{
+ "col_0": "DHCPNAK",
+ "col_1": "10.1.10.1",
+ "col_2": [
+ {
+ "xid": "0x4e17f141"
+ }
+ ]
+}
diff --git a/test/log-samples/sample-c15acd32844669d23d0cbc88ec548129ed2c592e.txt b/test/log-samples/sample-c15acd32844669d23d0cbc88ec548129ed2c592e.txt
new file mode 100644
index 0000000..a68d490
--- /dev/null
+++ b/test/log-samples/sample-c15acd32844669d23d0cbc88ec548129ed2c592e.txt
@@ -0,0 +1,87 @@
+ Jul 14 14:31:06 linjenkins3 kernel: [31809412.513897] [UFW BLOCK] IN=eth0 OUT= MAC=40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00 SRC=69.60.116.202 DST=173.203.237.224 LEN=44 TOS=0x00 PREC=0x00 TTL=29 ID=15852 PROTO=TCP SPT=43998 DPT=3389 WINDOW=3072 RES=0x00 SYN URGP=0
+ key 37:68 ^-----------------------------^ 31809412.513897] [UFW BLOCK] IN
+ sym 69:73 ^--^ eth0
+ val 69:73 ^--^ eth0
+pair 37:73 ^----------------------------------^ 31809412.513897] [UFW BLOCK] IN=eth0
+ key 74:77 ^-^ OUT
+quot 78:78 ^
+ val 78:78 ^
+pair 74:78 ^--^ OUT=
+ key 79:82 ^-^ MAC
+hexd 83:124 ^---------------------------------------^ 40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00
+ val 83:124 ^---------------------------------------^ 40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00
+pair 79:124 ^-------------------------------------------^ MAC=40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00
+ key 125:128 ^-^ SRC
+ipv4 129:142 ^-----------^ 69.60.116.202
+ val 129:142 ^-----------^ 69.60.116.202
+pair 125:142 ^---------------^ SRC=69.60.116.202
+ key 143:146 ^-^ DST
+ipv4 147:162 ^-------------^ 173.203.237.224
+ val 147:162 ^-------------^ 173.203.237.224
+pair 143:162 ^-----------------^ DST=173.203.237.224
+ key 163:166 ^-^ LEN
+ num 167:169 ^^ 44
+ val 167:169 ^^ 44
+pair 163:169 ^----^ LEN=44
+ key 170:173 ^-^ TOS
+ hex 174:178 ^--^ 0x00
+ val 174:178 ^--^ 0x00
+pair 170:178 ^------^ TOS=0x00
+ key 179:183 ^--^ PREC
+ hex 184:188 ^--^ 0x00
+ val 184:188 ^--^ 0x00
+pair 179:188 ^-------^ PREC=0x00
+ key 189:192 ^-^ TTL
+ num 193:195 ^^ 29
+ val 193:195 ^^ 29
+pair 189:195 ^----^ TTL=29
+ key 196:198 ^^ ID
+ num 199:204 ^---^ 15852
+ val 199:204 ^---^ 15852
+pair 196:204 ^------^ ID=15852
+ key 205:210 ^---^ PROTO
+ sym 211:214 ^-^ TCP
+ val 211:214 ^-^ TCP
+pair 205:214 ^-------^ PROTO=TCP
+ key 215:218 ^-^ SPT
+ num 219:224 ^---^ 43998
+ val 219:224 ^---^ 43998
+pair 215:224 ^-------^ SPT=43998
+ key 225:228 ^-^ DPT
+ num 229:233 ^--^ 3389
+ val 229:233 ^--^ 3389
+pair 225:233 ^------^ DPT=3389
+ key 234:240 ^----^ WINDOW
+ num 241:245 ^--^ 3072
+ val 241:245 ^--^ 3072
+pair 234:245 ^---------^ WINDOW=3072
+ key 246:249 ^-^ RES
+ hex 250:254 ^--^ 0x00
+wspc 254:255 ^
+ sym 255:258 ^-^ SYN
+ val 250:258 ^------^ 0x00 SYN
+pair 246:258 ^----------^ RES=0x00 SYN
+ key 259:263 ^--^ URGP
+ num 264:265 ^ 0
+ val 264:265 ^ 0
+pair 259:265 ^----^ URGP=0
+msg :[31809412.513897] [UFW BLOCK] IN=eth0 OUT= MAC=40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00 SRC=69.60.116.202 DST=173.203.237.224 LEN=44 TOS=0x00 PREC=0x00 TTL=29 ID=15852 PROTO=TCP SPT=43998 DPT=3389 WINDOW=3072 RES=0x00 SYN URGP=0
+format :[31809412.513897] [UFW BLOCK] IN=# OUT=# MAC=# SRC=# DST=# LEN=# TOS=# PREC=# TTL=# ID=# PROTO=# SPT=# DPT=# WINDOW=# RES=# URGP=#
+{
+ "31809412.513897] [UFW BLOCK] IN": "eth0",
+ "OUT": "",
+ "MAC": "40:40:2e:9a:ad:92:c4:71:fe:f1:b9:7f:08:00",
+ "SRC": "69.60.116.202",
+ "DST": "173.203.237.224",
+ "LEN": 44,
+ "TOS": "0x00",
+ "PREC": "0x00",
+ "TTL": 29,
+ "ID": 15852,
+ "PROTO": "TCP",
+ "SPT": 43998,
+ "DPT": 3389,
+ "WINDOW": 3072,
+ "RES": "0x00 SYN",
+ "URGP": 0
+}
diff --git a/test/log-samples/sample-c23f22c1b932b904203e018f78dead95fb89b15d.txt b/test/log-samples/sample-c23f22c1b932b904203e018f78dead95fb89b15d.txt
new file mode 100644
index 0000000..376752b
--- /dev/null
+++ b/test/log-samples/sample-c23f22c1b932b904203e018f78dead95fb89b15d.txt
@@ -0,0 +1,37 @@
+ Apr 29 08:13:42 tstack-centos5 dhclient: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5 (xid=0xd16b79d)
+ key 41:41 ^
+ sym 41:53 ^----------^ DHCPDISCOVER
+pair 41:53 ^----------^ DHCPDISCOVER
+ key 57:57 ^
+ sym 57:61 ^--^ eth0
+pair 57:61 ^--^ eth0
+ key 65:65 ^
+ipv4 65:80 ^-------------^ 255.255.255.255
+pair 65:80 ^-------------^ 255.255.255.255
+ key 86:86 ^
+ num 86:88 ^^ 67
+pair 86:88 ^^ 67
+ key 98:98 ^
+ num 98:99 ^ 5
+pair 98:99 ^ 5
+ key 101:101 ^
+ key 101:104 ^-^ xid
+ hex 105:114 ^-------^ 0xd16b79d
+ val 105:114 ^-------^ 0xd16b79d
+pair 101:114 ^-----------^ xid=0xd16b79d
+ grp 101:114 ^-----------^ xid=0xd16b79d
+pair 101:114 ^-----------^ xid=0xd16b79d
+msg :DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5 (xid=0xd16b79d)
+format :# on # to # port # interval # (#)
+{
+ "col_0": "DHCPDISCOVER",
+ "col_1": "eth0",
+ "col_2": "255.255.255.255",
+ "col_3": 67,
+ "col_4": 5,
+ "col_5": [
+ {
+ "xid": "0xd16b79d"
+ }
+ ]
+}
diff --git a/test/log-samples/sample-d0d6b3fc6766caac5ac3fac4a3754ceaab785eb8.txt b/test/log-samples/sample-d0d6b3fc6766caac5ac3fac4a3754ceaab785eb8.txt
new file mode 100644
index 0000000..b7aad42
--- /dev/null
+++ b/test/log-samples/sample-d0d6b3fc6766caac5ac3fac4a3754ceaab785eb8.txt
@@ -0,0 +1,33 @@
+ Apr 29 22:32:26 tstack-centos5 dhclient: DHCPREQUEST on eth0 to 10.1.10.1 port 67 (xid=0xd16b79d)
+ key 41:41 ^
+ sym 41:52 ^---------^ DHCPREQUEST
+pair 41:52 ^---------^ DHCPREQUEST
+ key 56:56 ^
+ sym 56:60 ^--^ eth0
+pair 56:60 ^--^ eth0
+ key 64:64 ^
+ipv4 64:73 ^-------^ 10.1.10.1
+pair 64:73 ^-------^ 10.1.10.1
+ key 79:79 ^
+ num 79:81 ^^ 67
+pair 79:81 ^^ 67
+ key 83:83 ^
+ key 83:86 ^-^ xid
+ hex 87:96 ^-------^ 0xd16b79d
+ val 87:96 ^-------^ 0xd16b79d
+pair 83:96 ^-----------^ xid=0xd16b79d
+ grp 83:96 ^-----------^ xid=0xd16b79d
+pair 83:96 ^-----------^ xid=0xd16b79d
+msg :DHCPREQUEST on eth0 to 10.1.10.1 port 67 (xid=0xd16b79d)
+format :# on # to # port # (#)
+{
+ "col_0": "DHCPREQUEST",
+ "col_1": "eth0",
+ "col_2": "10.1.10.1",
+ "col_3": 67,
+ "col_4": [
+ {
+ "xid": "0xd16b79d"
+ }
+ ]
+}
diff --git a/test/log-samples/sample-d4a0aedc8350f64b22403eeef4eca71fbf749d2b.txt b/test/log-samples/sample-d4a0aedc8350f64b22403eeef4eca71fbf749d2b.txt
new file mode 100644
index 0000000..91a456a
--- /dev/null
+++ b/test/log-samples/sample-d4a0aedc8350f64b22403eeef4eca71fbf749d2b.txt
@@ -0,0 +1,9 @@
+ Apr 29 23:02:45 tstack-centos5 avahi-daemon[2467]: Invalid response packet from host fe80::22c9:d0ff:fe15:1b7c
+ key 85:85 ^
+ipv6 85:110 ^-----------------------^ fe80::22c9:d0ff:fe15:1b7c
+pair 85:110 ^-----------------------^ fe80::22c9:d0ff:fe15:1b7c
+msg :Invalid response packet from host fe80::22c9:d0ff:fe15:1b7c
+format :Invalid response packet from host #
+{
+ "col_0": "fe80::22c9:d0ff:fe15:1b7c"
+}
diff --git a/test/log-samples/sample-d714b5e8cd354321f376ed1c0a70ec9a2f58076d.txt b/test/log-samples/sample-d714b5e8cd354321f376ed1c0a70ec9a2f58076d.txt
new file mode 100644
index 0000000..d7367ab
--- /dev/null
+++ b/test/log-samples/sample-d714b5e8cd354321f376ed1c0a70ec9a2f58076d.txt
@@ -0,0 +1,9 @@
+ Apr 29 23:02:45 tstack-centos5 avahi-daemon[2467]: Invalid response packet from host 10.1.10.10
+ key 85:85 ^
+ipv4 85:95 ^--------^ 10.1.10.10
+pair 85:95 ^--------^ 10.1.10.10
+msg :Invalid response packet from host 10.1.10.10
+format :Invalid response packet from host #
+{
+ "col_0": "10.1.10.10"
+}
diff --git a/test/log-samples/sample-dd7d406352ec6a11d966b6f015a9482b060f2b29.txt b/test/log-samples/sample-dd7d406352ec6a11d966b6f015a9482b060f2b29.txt
new file mode 100644
index 0000000..bcf3908
--- /dev/null
+++ b/test/log-samples/sample-dd7d406352ec6a11d966b6f015a9482b060f2b29.txt
@@ -0,0 +1,23 @@
+ 2013-02-11 06:42:34,311:INFO:com.twisted:Starting factory <twisted.web.server.Site instance at 0x1de9290>
+ key 29:29 ^
+ key 29:40 ^---------^ com.twisted
+pair 29:40 ^---------^ com.twisted
+ key 59:59 ^
+ sym 59:82 ^---------------------^ twisted.web.server.Site
+wspc 82:83 ^
+word 83:91 ^------^ instance
+wspc 91:92 ^
+word 92:94 ^^ at
+wspc 94:95 ^
+ hex 95:104 ^-------^ 0x1de9290
+ val 59:104 ^-------------------------------------------^ twisted.web.server.Site instance at 0x1de9290
+ grp 59:104 ^-------------------------------------------^ twisted.web.server.Site instance at 0x1de9290
+pair 59:104 ^-------------------------------------------^ twisted.web.server.Site instance at 0x1de9290
+msg ::com.twisted:Starting factory <twisted.web.server.Site instance at 0x1de9290>
+format ::#:Starting factory <#>
+{
+ "col_0": "com.twisted",
+ "col_1": [
+ "twisted.web.server.Site instance at 0x1de9290"
+ ]
+}
diff --git a/test/log-samples/sample-e779d1771e34f5203ae73e85802e78002be63db6.txt b/test/log-samples/sample-e779d1771e34f5203ae73e85802e78002be63db6.txt
new file mode 100644
index 0000000..d527217
--- /dev/null
+++ b/test/log-samples/sample-e779d1771e34f5203ae73e85802e78002be63db6.txt
@@ -0,0 +1,25 @@
+ Apr 29 22:32:27 tstack-centos5 dhclient: DHCPACK from 10.1.10.1 (xid=0xd16b79d)
+ key 41:41 ^
+ sym 41:48 ^-----^ DHCPACK
+pair 41:48 ^-----^ DHCPACK
+ key 54:54 ^
+ipv4 54:63 ^-------^ 10.1.10.1
+pair 54:63 ^-------^ 10.1.10.1
+ key 65:65 ^
+ key 65:68 ^-^ xid
+ hex 69:78 ^-------^ 0xd16b79d
+ val 69:78 ^-------^ 0xd16b79d
+pair 65:78 ^-----------^ xid=0xd16b79d
+ grp 65:78 ^-----------^ xid=0xd16b79d
+pair 65:78 ^-----------^ xid=0xd16b79d
+msg :DHCPACK from 10.1.10.1 (xid=0xd16b79d)
+format :# from # (#)
+{
+ "col_0": "DHCPACK",
+ "col_1": "10.1.10.1",
+ "col_2": [
+ {
+ "xid": "0xd16b79d"
+ }
+ ]
+}
diff --git a/test/log-samples/sample-f5afbee90a8c054061c4e9ffe673293cce7761de.txt b/test/log-samples/sample-f5afbee90a8c054061c4e9ffe673293cce7761de.txt
new file mode 100644
index 0000000..1eafdc7
--- /dev/null
+++ b/test/log-samples/sample-f5afbee90a8c054061c4e9ffe673293cce7761de.txt
@@ -0,0 +1,13 @@
+ Apr 29 08:13:43 tstack-centos5 dhclient: DHCPOFFER from 10.1.10.1
+ key 41:41 ^
+ sym 41:50 ^-------^ DHCPOFFER
+pair 41:50 ^-------^ DHCPOFFER
+ key 56:56 ^
+ipv4 56:65 ^-------^ 10.1.10.1
+pair 56:65 ^-------^ 10.1.10.1
+msg :DHCPOFFER from 10.1.10.1
+format :# from #
+{
+ "col_0": "DHCPOFFER",
+ "col_1": "10.1.10.1"
+}
diff --git a/test/log-samples/sample-fc8923633e57bacd641d80dde3ff878212230552.txt b/test/log-samples/sample-fc8923633e57bacd641d80dde3ff878212230552.txt
new file mode 100644
index 0000000..f0f3afe
--- /dev/null
+++ b/test/log-samples/sample-fc8923633e57bacd641d80dde3ff878212230552.txt
@@ -0,0 +1,13 @@
+ Apr 29 08:13:43 tstack-centos5 avahi-daemon[2467]: Registering new address record for 10.1.10.62 on eth0
+ key 86:86 ^
+ipv4 86:96 ^--------^ 10.1.10.62
+pair 86:96 ^--------^ 10.1.10.62
+ key 100:100 ^
+ sym 100:104 ^--^ eth0
+pair 100:104 ^--^ eth0
+msg :Registering new address record for 10.1.10.62 on eth0
+format :Registering new address record for # on #
+{
+ "col_0": "10.1.10.62",
+ "col_1": "eth0"
+}
diff --git a/test/log.clog b/test/log.clog
new file mode 100644
index 0000000..14e4ed9
--- /dev/null
+++ b/test/log.clog
@@ -0,0 +1,2 @@
+{"@timestamp":"2016-08-03T12:06:31.009-0500","@version":1,"message":";Exception initializing page context;","logger_name":"org.apache.jasper.runtime.JspFactoryImpl","thread_name":"http-bio-0.0.0.0-8081-exec-198","level":"ERROR","level_value":40000,"stack_trace":"java.lang.NoClassDefFoundError: javax/el/StaticFieldELResolver\n\tat org.apache.jasper.runtime.JspFactoryImpl.internalGetPageContext(JspFactoryImpl.java:172)\n\tat org.apache.jasper.runtime.JspFactoryImpl.getPageContext(JspFactoryImpl.java:123)\n\tat org.apache.jsp.errors._404_002dnot_002dfound_jsp._jspService(_404_002dnot_002dfound_jsp.java:38)\n\tat org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:731)\n\tat org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)\n\tat org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)\n\tat org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:731)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat collective.config.startup.DamFilter.doFilter(DamFilter.java:270)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)\n\tat org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)\n\tat org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)\n\tat org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)\n\tat org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)\n\tat org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:476)\n\tat org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:345)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:210)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)\n\tat org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)\n\tat org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)\n\tat org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)\n\tat org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)\n\tat org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:744)\nCaused by: java.lang.ClassNotFoundException: javax.el.StaticFieldELResolver\n\tat org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)\n\tat org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)\n\t... 33 common frames omitted\n","customer":"foobaz"}
+{"@timestamp":"2016-08-03T12:06:31.009-0500","@version":1,"message":";Exception initializing page context;","logger_name":"org.apache.jasper.runtime.JspFactoryImpl","thread_name":"http-bio-0.0.0.0-8081-exec-198","level":"ERROR","level_value":40000,"customer":"foobaz"}
diff --git a/test/logfile_access_log.0 b/test/logfile_access_log.0
new file mode 100644
index 0000000..a90f29f
--- /dev/null
+++ b/test/logfile_access_log.0
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/logfile_access_log.1 b/test/logfile_access_log.1
new file mode 100644
index 0000000..ad2b37e
--- /dev/null
+++ b/test/logfile_access_log.1
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/logfile_ansi.0 b/test/logfile_ansi.0
new file mode 100644
index 0000000..d9c9499
--- /dev/null
+++ b/test/logfile_ansi.0
@@ -0,0 +1 @@
+2022-06-22T10:20:33 Example foo
diff --git a/test/logfile_ansi.1 b/test/logfile_ansi.1
new file mode 100644
index 0000000..51fc1bf
--- /dev/null
+++ b/test/logfile_ansi.1
@@ -0,0 +1,10 @@
+Sep 19 09:24:04 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Mux ID not found in mapping dictionary
+Sep 19 09:24:04 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Can't handle disconnect with invalid ecid
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: Entered:_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: Entered:_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: Entered:__thr_AMMuxedDeviceDisconnected, mux-device:1003
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: tid:191f - Mux ID not found in mapping dictionary
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Mux ID not found in mapping dictionary
+Sep 19 09:24:20 Tims-MacBook-Air MobileDeviceUpdater[17530]: tid:191f - Can't handle disconnect with invalid ecid
+Sep 19 09:24:20 Tims-MacBook-Air AMPDeviceDiscoveryAgent[17600]: tid:1d1f - Can't handle disconnect with invalid ecid
diff --git a/test/logfile_bad_access_log.0 b/test/logfile_bad_access_log.0
new file mode 100644
index 0000000..d48df45
--- /dev/null
+++ b/test/logfile_bad_access_log.0
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/logfile_bad_syslog.0 b/test/logfile_bad_syslog.0
new file mode 100644
index 0000000..af65a10
--- /dev/null
+++ b/test/logfile_bad_syslog.0
@@ -0,0 +1,4 @@
+Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Nov 3 09:23:38 veridian lookup for opt failed
+Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/logfile_block.1 b/test/logfile_block.1
new file mode 100644
index 0000000..681ec73
--- /dev/null
+++ b/test/logfile_block.1
@@ -0,0 +1,4 @@
+Wed May 19 08:00:01 EST 2021 line 1
+/abc/def
+Wed May 19 08:00:03 EST 2021 line 3
+/ghi/jkl
diff --git a/test/logfile_block.2 b/test/logfile_block.2
new file mode 100644
index 0000000..3d21dd3
--- /dev/null
+++ b/test/logfile_block.2
@@ -0,0 +1,2 @@
+Wed May 19 12:00:02 UTC 2021 line 2
+Wed May 19 12:00:04 UTC 2021 line 4
diff --git a/test/logfile_blued.0 b/test/logfile_blued.0
new file mode 100644
index 0000000..1422615
--- /dev/null
+++ b/test/logfile_blued.0
@@ -0,0 +1,6 @@
+Apr 4 20:02:32 Tim-Stacks-iMac.local blued[59]: Release the WiFi lock
+Apr 4 20:02:32 Tim-Stacks-iMac.local blued[59]: Acquiring the wifi lock
+Apr 4 20:02:32 Tim-Stacks-iMac.local blued[59]: Acquired the wifi lock
+Apr 4 20:02:42 Tim-Stacks-iMac.local blued[59]: Release the WiFi lock
+Apr 4 20:02:42 Tim-Stacks-iMac.local blued[59]: Acquiring the wifi lock
+Apr 4 20:02:42 Tim-Stacks-iMac.local blued[59]: Acquired the wifi lock
diff --git a/test/logfile_bro_conn.log.0 b/test/logfile_bro_conn.log.0
new file mode 100644
index 0000000..305e368
--- /dev/null
+++ b/test/logfile_bro_conn.log.0
@@ -0,0 +1,101 @@
+#separator \x09
+#set_separator ,
+#empty_field (empty)
+#unset_field -
+#path conn
+#open 2017-04-16-21-36-10
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents
+#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string]
+1320279554.496300 Cg9xqq3JAcZusspA86 192.168.2.76 52025 208.85.42.28 80 tcp - 2.125850 0 1092421 SF - - 0 ^dAfFa 400 20800 756 1131733 (empty)
+1320279567.181431 CdysLK1XpcrXOpVDuh 192.168.2.76 52034 174.129.249.33 80 tcp http 0.082899 389 1495 SF - - 0 ShADdfFa 5 613 4 1667 (empty)
+1320279567.452735 C6nSoj1Qco9PGyslz6 192.168.2.76 52035 184.72.234.3 80 tcp http 2.561940 905 731 SF - - 0 ShADadfF 9 1289 8 1063 (empty)
+1320279567.181050 CtgxRAqDLvrRUQdqe 192.168.2.76 52033 184.72.234.3 80 tcp http 3.345539 1856 1445 SF - - 0 ShADadfF 15 2480 13 1969 (empty)
+1320279572.537165 Cg66JO6sKx3fvUkQa 192.168.2.76 52014 132.235.215.117 80 tcp - 0.005881 0 0 SF - - 0 FfA 2 104 1 52 (empty)
+1320279578.886650 CIJIDL1ULo4HpT24Gl 192.168.2.76 52052 63.241.108.124 80 tcp http 0.498720 1566 2543 SF - - 0 ShADadfF 6 1830 5 2747 (empty)
+1320279577.453637 CEh6Ka2HInkNSH01L2 192.168.2.76 52044 216.34.181.48 80 tcp http 5.077548 596 576 SF - - 0 ShADadfF 6 920 5 848 (empty)
+1320279581.284239 CSvRlm1gGNFXUOrtRj 192.168.2.76 52059 207.171.163.23 80 tcp - 5.056486 0 0 SF - - 0 ShAFf 4 184 2 92 (empty)
+1320279577.507914 CjPGiy13ncXKxU765j 192.168.2.76 52045 216.34.181.45 80 tcp http 11.654832 2603 181933 SF - - 0 ShADadfF 80 6775 134 188913 (empty)
+1320279590.558878 CKeb0i4BZy3XEHQGvb 192.168.2.76 52077 74.125.225.78 80 tcp - 5.048744 0 0 SF - - 0 ShAFf 4 220 2 112 (empty)
+1320279601.552309 CK957ERTz8lBycly4 192.168.2.76 52085 199.59.148.201 80 tcp http 0.237418 883 1071 SF - - 0 ShADadfF 6 1207 5 1339 (empty)
+1320279600.826685 CaPClb1Bf0RrRGtyWi 192.168.2.76 52083 192.150.187.43 80 tcp http 5.233472 442 31353 SF - - 0 ShADadfF 20 1494 26 32713 (empty)
+1320279600.826441 CmWpSw3VtjiAceBCwf 192.168.2.76 52081 192.150.187.43 80 tcp http 5.233763 446 24258 SF - - 0 ShADadfF 14 1186 21 25358 (empty)
+1320279600.826004 CBeaXe4Iyj1gXd2Iq 192.168.2.76 52080 192.150.187.43 80 tcp http 5.404390 886 16577 SF - - 0 ShADadfF 14 1626 17 17469 (empty)
+1320279600.825492 Cd8s2R3OGDgkhnvSu9 192.168.2.76 52079 192.150.187.43 80 tcp http 5.496459 1309 17849 SF - - 0 ShADadfF 16 2153 18 18793 (empty)
+1320279600.826607 CX1GjC4vn52UY1uDv6 192.168.2.76 52082 192.150.187.43 80 tcp http 5.515177 1746 14412 SF - - 0 ShADadfF 14 2486 16 15252 (empty)
+1320279600.581672 CbQAWi3GX2bCmX5L56 192.168.2.76 52078 192.150.187.43 80 tcp http 5.825503 1599 80801 SF - - 0 ShADadfF 37 3535 63 84085 (empty)
+1320279607.998777 CKskol4qPFKjkV6273 192.168.2.76 52022 74.125.225.68 80 tcp - 0.021505 0 0 SF - - 0 FfA 2 104 1 52 (empty)
+1320279607.998577 CtBtCj3jZ4UVo657Dc 192.168.2.76 52023 209.85.145.101 80 tcp - 0.031533 0 0 SF - - 0 FfA 2 104 1 52 (empty)
+1320279611.527848 CurHpb1TGZOktTRNP1 192.168.2.76 52092 199.59.148.201 80 tcp http 0.349795 902 1070 SF - - 0 ShADadfF 6 1226 5 1338 (empty)
+1320279612.495344 CuUKOQ1R3CqKBgeTdf 192.168.2.76 52093 199.59.148.201 80 tcp http 0.279806 907 1070 SF - - 0 ShADadfF 6 1231 5 1338 (empty)
+1320279613.968096 C3xkHgJnzZszVSTpi 192.168.2.76 52094 199.59.148.201 80 tcp http 0.486591 902 1070 SF - - 0 ShADadfF 6 1226 5 1338 (empty)
+1320279611.171273 CINVx040XRWPWdQIOd 192.168.2.76 52091 192.150.187.43 80 tcp - 5.081864 0 0 SF - - 0 ShAFf 5 272 3 172 (empty)
+1320279601.552622 C3TZMB4CrUwYfkGJy1 192.168.2.76 52086 199.59.148.20 80 tcp http 15.200059 4078 9556 SF - - 0 ShADadfF 12 4714 13 10240 (empty)
+1320279610.744212 CO5QKYQkcSdxQFA35 192.168.2.76 52090 192.150.187.43 80 tcp http 6.499438 1669 37688 SF - - 0 ShADadFf 26 3033 31 39308 (empty)
+1320279616.742259 CMrjgF2XLmRh9C9TR4 192.168.2.76 52095 208.85.41.42 80 tcp http 0.604819 546 59445 SF - - 0 ShADadfF 29 2066 45 61793 (empty)
+1320279630.486420 CD69521bDXIAb4IkW 192.168.2.76 52097 199.59.148.201 80 tcp http 0.166288 903 1070 SF - - 0 ShADadfF 6 1227 5 1338 (empty)
+1320279630.021607 C2vQ8sVgyADHjtEda 192.168.2.76 52096 192.150.187.43 80 tcp http 5.199366 421 15397 SF - - 0 ShADadfF 13 1109 15 16185 (empty)
+1320279637.215536 CmxyBl2c8XAMTuHEk4 192.168.2.76 52100 199.59.148.201 80 tcp http 0.264911 905 1068 SF - - 0 ShADadFf 7 1281 5 1336 (empty)
+1320279577.687091 CAUlC249svUfE6q0g3 192.168.2.76 52051 184.29.211.172 80 tcp http 61.298320 1465 22567 SF - - 0 ShADadfF 19 2465 21 23667 (empty)
+1320279639.698701 CBX0254QJoklXNbvv2 192.168.2.76 52110 199.59.148.201 80 tcp http 0.283987 901 1067 SF - - 0 ShADadfF 6 1225 5 1335 (empty)
+1320279638.450681 CSvs6v26bQqFylkk6l 192.168.2.76 52101 192.150.187.43 80 tcp http 5.709781 758 19809 SF - - 0 ShADadFf 16 1602 20 20857 (empty)
+1320279638.954157 C4pHul1H3OeWYz7o7i 192.168.2.76 52102 192.150.187.43 80 tcp http 5.228420 371 498 SF - - 0 ShADadFf 7 747 5 766 (empty)
+1320279638.957224 C7Lcvr4vsTf6eYpBva 192.168.2.76 52104 192.150.187.43 80 tcp http 5.231185 340 1443 SF - - 0 ShADadFf 7 716 5 1711 (empty)
+1320279638.955996 CV8faD4L1sLL5kDwN9 192.168.2.76 52103 192.150.187.43 80 tcp http 5.243925 338 24829 SF - - 0 ShADadFf 18 1286 22 25981 (empty)
+1320279639.349306 CvfUrT2DgYXXoZw9Ah 192.168.2.76 52109 192.150.187.43 80 tcp http 4.862785 400 7004 SF - - 0 ShADadFf 9 880 8 7428 (empty)
+1320279639.147746 C6MrHk2C7rLuJqhjsg 192.168.2.76 52107 192.150.187.43 80 tcp http 5.066841 404 491 SF - - 0 ShADadFf 6 728 4 707 (empty)
+1320279639.205080 Ccc26E2f7mpxWWj5L2 192.168.2.76 52108 192.150.187.43 80 tcp - 5.009511 0 0 SF - - 0 ShAFf 5 272 3 172 (empty)
+1320279639.052091 CyiluB4nGodFLEMnX5 192.168.2.76 52105 192.150.187.43 80 tcp - 5.162501 0 0 SF - - 0 ShAFf 5 272 3 172 (empty)
+1320279639.147610 CxyAKs10ppnHFP6O8i 192.168.2.76 52106 192.150.187.43 80 tcp http 5.066984 404 491 SF - - 0 ShADadFf 6 728 4 707 (empty)
+1320279636.698841 C7Krri4g9tZfHniGXh 192.168.2.76 52099 192.150.187.43 80 tcp http 7.515757 1219 28929 SF - - 0 ShADadFf 23 2427 24 30185 (empty)
+1320279630.486859 CC3vUI3gFB04zLvWRa 192.168.2.76 52098 199.59.148.20 80 tcp http 15.198762 2050 4776 SF - - 0 ShADadfF 8 2478 9 5252 (empty)
+1320279673.118128 CRNn9f1zKNlzHSM5pa 192.168.2.76 52112 199.59.148.201 80 tcp http 0.351267 902 1068 SF - - 0 ShADadfF 6 1226 5 1336 (empty)
+1320279672.273571 C6Ym6jvMgikT0xTTc 192.168.2.76 52111 192.150.187.43 80 tcp http 5.564817 419 48038 SF - - 0 ShADadfF 23 1627 38 50022 (empty)
+1320279579.393218 CLsqp41RLUd83arUQb 192.168.2.76 52053 132.235.215.119 80 tcp http 0.045584 2503 21124 S1 - - 0 ShADad 13 3191 18 22068 (empty)
+1320279567.515293 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 tcp http 23.090143 6335 4537 S1 - - 0 ShADad 18 7283 11 5117 (empty)
+1320279581.817559 CGv2Tp4Ngt8MmKmVRd 192.168.2.76 52062 132.235.215.119 80 tcp http 0.007172 600 248 S1 - - 0 ShADad 4 820 3 412 (empty)
+1320279571.543053 CsBgiE1WmGP4Yo749h 192.168.2.76 52039 69.171.228.39 80 tcp http 0.308956 417 10451 S1 - - 0 ShADd 9 897 9 10931 (empty)
+1320279587.101825 C96j2X1DixgLTj2Oi8 192.168.2.76 52072 74.125.225.64 80 tcp http 0.614423 2544 2981 S1 - - 0 ShADad 6 2868 6 3301 (empty)
+1320279577.686971 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 tcp http 6.945222 2240 31147 S1 - - 0 ShADad 21 3344 26 32507 (empty)
+1320279589.315281 CBHHuR1xFnm5C5CQBc 192.168.2.76 52074 74.125.225.76 80 tcp http 0.059880 373 1158 S1 - - 0 ShADad 4 593 3 1322 (empty)
+1320279590.557604 C0K9DaoPFkfnzwlZa 192.168.2.76 52076 74.125.225.78 80 tcp http 0.048630 717 342 S1 - - 0 ShADad 4 937 3 506 (empty)
+1320279581.472457 CiIjAe1n5MnPOVpQ9f 192.168.2.76 52061 74.125.225.90 80 tcp http 0.704763 4835 51573 S1 - - 0 ShADad 30 6407 46 53973 (empty)
+1320279585.726876 CRgW2I2zo3SInm6iT8 192.168.2.76 52066 204.246.169.217 80 tcp http 1.386549 1233 8739 S1 - - 0 ShADad 10 1765 10 9267 (empty)
+1320279566.795729 CdrfXZ1NOFPEawF218 192.168.2.76 52028 72.21.211.173 80 tcp http 115.121914 380 2260 SF - - 0 ShADdFf 6 644 4 2432 (empty)
+1320279584.599525 Cs5yEZ3ELZTeuTOsP4 192.168.2.76 52064 204.246.169.252 80 tcp http 0.391939 370 64350 S1 - - 0 ShADad 28 1838 47 66802 (empty)
+1320279601.555241 CTRXSR3blXJE5ZE7Ij 192.168.2.76 52089 74.125.225.83 80 tcp http 71.619232 4280 704 S1 - - 0 ShADad 10 4812 6 1024 (empty)
+1320279580.303255 CNbPns4mOMGgjI8Ele 192.168.2.76 52057 204.246.169.3 80 tcp http 0.118609 844 1440 S1 - - 0 ShADad 6 1168 4 1656 (empty)
+1320279600.900056 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 tcp http 72.274459 8979 8637 S1 - - 0 ShADad 23 10187 16 9477 (empty)
+1320279571.880419 CtANmVrHYMtkWqPE5 192.168.2.76 52041 132.235.215.117 80 tcp http 0.013122 374 1813 S1 - - 0 ShADad 4 594 4 2029 (empty)
+1320279577.686764 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 tcp http 6.975476 1916 71870 S1 - - 0 ShADad 37 3852 55 74738 (empty)
+1320279581.287819 C185u7u9Q4qhJPhzl 192.168.2.76 52060 74.125.225.92 80 tcp http 0.686395 1601 40796 S1 - - 0 ShADad 21 2705 33 42520 (empty)
+1320279586.006470 CbUCgw1DrIGcXzONB7 192.168.2.76 52071 204.246.169.217 80 tcp http 0.092010 381 1322 S1 - - 0 ShADad 4 601 3 1486 (empty)
+1320279566.795779 CJwUi9bdB9c1lLW44 192.168.2.76 52029 72.21.211.173 80 tcp http 115.121339 380 2658 SF - - 0 ShADdFf 6 644 4 2830 (empty)
+1320279571.880174 CYfHyC28tAhkLYkXB7 192.168.2.76 52040 132.235.215.117 80 tcp http 0.673383 1507 12558 S1 - - 0 ShADad 13 2195 14 13302 (empty)
+1320279581.284163 CKzjfhsJ8vrn2rrfg 192.168.2.76 52058 207.171.163.23 80 tcp http 0.335801 736 1674 S1 - - 0 ShADad 6 1000 5 1886 (empty)
+1320279577.686914 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 tcp http 6.967534 2207 28633 S1 - - 0 ShADad 22 3363 24 29889 (empty)
+1320279586.001630 CWJhMU2cTLEnseTmCb 192.168.2.76 52067 204.246.169.217 80 tcp http 0.136158 381 5225 S1 - - 0 ShADad 5 653 6 5545 (empty)
+1320279567.684168 CdZUPH2DKOE7zzCLE3 192.168.2.76 52038 132.235.215.119 80 tcp http 115.202498 449 9019 SF - - 0 ShADadFf 9 929 10 9547 (empty)
+1320279579.442948 CbCciH11995WKkobR1 192.168.2.76 52054 74.121.134.156 80 tcp http 0.274905 1028 1071 S1 - - 0 ShADd 6 1292 3 1195 (empty)
+1320279579.803083 CaP2LpLGvsmX7yJO 192.168.2.76 52056 74.125.225.91 80 tcp http 0.046347 400 360 S1 - - 0 ShADad 4 620 3 524 (empty)
+1320279586.002799 CejI402rKGtdBXij4f 192.168.2.76 52068 204.246.169.217 80 tcp http 0.120253 762 3509 S1 - - 0 ShADad 6 1086 6 3829 (empty)
+1320279567.667107 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 tcp http 32.451792 6668 13531 S1 - - 0 ShADad 29 8188 29 15047 (empty)
+1320279566.795888 CT0JIh479jXIGt0Po1 192.168.2.76 52031 72.21.211.173 80 tcp http 115.121506 380 1981 SF - - 0 ShADdFf 6 644 4 2153 (empty)
+1320279566.447996 CwFs1P2UcUdlSxD2La 192.168.2.76 52026 132.235.215.119 80 tcp http 116.438679 2063 18235 SF - - 0 ShADadFf 15 2855 18 19179 (empty)
+1320279577.686850 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 tcp http 6.973070 1921 280972 S1 - - 0 ShADadt 144 11093 199 291328 (empty)
+1320279566.795830 CJxSUgkInyKSHiju1 192.168.2.76 52030 72.21.211.173 80 tcp http 115.121810 380 2686 SF - - 0 ShADdFf 6 644 4 2858 (empty)
+1320279601.554581 CibfNy1QQW4ImDWRq5 192.168.2.76 52088 74.125.225.83 80 tcp http 35.738404 4220 704 S1 - - 0 ShADad 10 4752 7 1076 (empty)
+1320279566.795628 CoX7zA3OJKGUOSCBY2 192.168.2.76 52027 72.21.211.173 80 tcp http 115.121837 380 2948 SF - - 0 ShADdFf 6 644 5 3160 (empty)
+1320279577.687031 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 tcp http 6.947920 2582 34114 S1 - - 0 ShADad 26 3946 30 35682 (empty)
+1320279584.610492 Cu4gIx1BDNtGOl7Ht2 192.168.2.76 52065 204.246.169.252 80 tcp http 4.847647 1218 131460 S1 - - 0 ShADad 55 4090 94 136356 (empty)
+1320279588.157960 CYYyja3FFNEnftw3K6 192.168.2.76 52073 74.125.225.72 80 tcp http 0.346895 378 174833 S1 - - 0 ShADadt 77 4718 127 181445 (empty)
+1320279571.880844 C4uDKU5tpeRU9Su19 192.168.2.76 52043 132.235.215.117 80 tcp http 0.027676 389 803 S1 - - 0 ShADad 4 609 3 967 (empty)
+1320279571.880785 CSTH8n1O1nv0ztxNQd 192.168.2.76 52042 132.235.215.117 80 tcp http 0.698402 813 45320 S1 - - 0 ShADad 22 1969 34 47096 (empty)
+1320279586.004044 C2KnU34GcVV6amo8va 192.168.2.76 52069 204.246.169.217 80 tcp http 0.094285 381 1903 S1 - - 0 ShADad 4 601 4 2119 (empty)
+1320279582.210392 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 tcp http 7.278092 1971 508090 S1 - - 0 ShADadt 225 15495 355 526558 (empty)
+1320279590.556280 CD1jfU3p9abEm77mzf 192.168.2.76 52075 74.125.225.78 80 tcp http 0.047887 714 342 S1 - - 0 ShADad 4 934 3 506 (empty)
+1320279586.005337 C5vx4911iSMAJuShFd 192.168.2.76 52070 204.246.169.217 80 tcp http 0.093133 381 2493 S1 - - 0 ShADad 4 601 4 2709 (empty)
+1320279673.118549 CJLgi92kpp2gLgGTE5 192.168.2.76 52113 199.59.148.20 80 tcp http 10.247819 1023 2388 SF - - 0 ShADadfF 6 1347 6 2708 (empty)
+1320279579.731320 ClcvKE1dqsEFQu46m9 192.168.2.76 52055 74.125.225.91 80 tcp http 0.522914 1493 54251 S1 - - 0 ShADad 30 3065 46 56651 (empty)
+1320279601.553361 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 tcp http 71.658218 3168 19975 S1 - - 0 ShADadt 23 4388 29 21491 (empty)
+1320279566.796068 C6Q4Vm14ZJIlZhsXqk 192.168.2.76 52032 72.21.211.173 80 tcp http 115.119217 380 2628 SF - - 0 ShADadFf 6 644 5 2840 (empty)
+#close 2017-04-16-21-36-10
diff --git a/test/logfile_bro_http.log.0 b/test/logfile_bro_http.log.0
new file mode 100644
index 0000000..8f69bec
--- /dev/null
+++ b/test/logfile_bro_http.log.0
@@ -0,0 +1,206 @@
+#separator \x09
+#set_separator ,
+#empty_field (empty)
+#unset_field -
+#path http
+#open 2017-04-16-21-36-10
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer version user_agent request_body_len response_body_len status_code status_msg info_code info_msg tags username password proxied orig_fuids orig_filenames orig_mime_types resp_fuids resp_filenames resp_mime_types
+#types time string addr port addr port count string string string string string string count count count string count string set[enum] string string set[string] vector[string] vector[string] vector[string] vector[string] vector[string] vector[string]
+1320279566.452687 CwFs1P2UcUdlSxD2La 192.168.2.76 52026 132.235.215.119 80 1 GET www.reddit.com / - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 109978 200 OK - - (empty) - - - - - - Ftw3fJ2JJF3ntMTL2 - text/html
+1320279566.831619 CJxSUgkInyKSHiju1 192.168.2.76 52030 72.21.211.173 80 1 GET e.thumbs.redditmedia.com /E-pbDbmiBclPkDaX.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2300 200 OK - - (empty) - - - - - - FFTf9Zdgk3YkfCKo3 - image/jpeg
+1320279566.831563 CJwUi9bdB9c1lLW44 192.168.2.76 52029 72.21.211.173 80 1 GET f.thumbs.redditmedia.com /BP5bQfy4o-C7cF6A.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2272 200 OK - - (empty) - - - - - - FfXtOj3o7aub4vbs2j - image/jpeg
+1320279566.831473 CoX7zA3OJKGUOSCBY2 192.168.2.76 52027 72.21.211.173 80 1 GET e.thumbs.redditmedia.com /SVUtep3Rhg5FTRn4.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2562 200 OK - - (empty) - - - - - - F21Ybs3PTqS6O4Q2Zh - image/jpeg
+1320279566.831643 CT0JIh479jXIGt0Po1 192.168.2.76 52031 72.21.211.173 80 1 GET f.thumbs.redditmedia.com /uuy31444rLSyKdHS.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1595 200 OK - - (empty) - - - - - - Fdk0MZ1wQmKWAJ4WH4 - image/jpeg
+1320279566.831666 C6Q4Vm14ZJIlZhsXqk 192.168.2.76 52032 72.21.211.173 80 1 GET a.thumbs.redditmedia.com /BoVp7eG0DUodTIfr.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2242 200 OK - - (empty) - - - - - - FwCCcC3lGkQAwhCDX3 - image/jpeg
+1320279566.831535 CdrfXZ1NOFPEawF218 192.168.2.76 52028 72.21.211.173 80 1 GET c.thumbs.redditmedia.com /IEeSI3Q47xHE0UEz.jpg http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1874 200 OK - - (empty) - - - - - - FHK4nO28ZC5rrBZPqa - image/jpeg
+1320279567.211407 CdysLK1XpcrXOpVDuh 192.168.2.76 52034 174.129.249.33 80 1 GET www.redditmedia.com /ads/ http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3258 200 OK - - (empty) - - - - - - Fv5xxZ7iP0eQKziM2 - text/html
+1320279567.211031 CtgxRAqDLvrRUQdqe 192.168.2.76 52033 184.72.234.3 80 1 GET pixel.redditmedia.com /pixel/of_destiny.png?v=32tb6zakMbpImUZWtz+pksVc/8wYRc822cfKz091HT0oAKWHwZGxGpDcvvwUpyjwU8nJsyGc4cw=&r=296143927 http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 105 200 OK - - (empty) - - - - - - F5EJmr1cvlMkJFqSSk - image/png
+1320279567.296908 CwFs1P2UcUdlSxD2La 192.168.2.76 52026 132.235.215.119 80 2 GET www.reddit.com /static/bg-button-positive-unpressed.png http://www.reddit.com/static/reddit.RZTLMiZ4gTk.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279567.451885 CtgxRAqDLvrRUQdqe 192.168.2.76 52033 184.72.234.3 80 2 GET pixel.redditmedia.com /fetch-trackers?callback=jQuery16107779853632052074_1320279566998&ids[]=t5_6&ids[]=t3_lsfmb&ids[]=t3_lsejk&_=1320279567192 http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 206 200 OK - - (empty) - - - - - - FGxLzB2hPvGVceWXuf - text/plain
+1320279567.482546 C6nSoj1Qco9PGyslz6 192.168.2.76 52035 184.72.234.3 80 1 GET pixel.redditmedia.com /fetch-trackers?callback=jQuery16107779853632052074_1320279566999&ids[]=t5_6&ids[]=t3_lsfmb&ids[]=t3_lsejk&_=1320279567197 http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 206 200 OK - - (empty) - - - - - - FJ5XTZ1P1mJV2IhFth - text/plain
+1320279567.536586 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 1 GET www.google-analytics.com /__utm.gif?utmwv=5.2.0&utms=1&utmn=872724630&utmhn=www.reddit.com&utme=8(site*srpath*usertype*uitype)9( reddit.com* reddit.com-GET_listing*guest*web)11(3!2)&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=reddit: the front page of the internet&utmhid=1425264550&utmr=-&utmp=/&utmac=UA-12131688-1&utmcc=__utma=55650728.1984705726.1319611466.1320276256.1320279567.22;+__utmz=55650728.1319747429.7.7.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=appengine%20python%20mobile%20analytics;&utmu=qQ~ http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FilkiN33J86y8uYEF7 - image/gif
+1320279567.689996 CdZUPH2DKOE7zzCLE3 192.168.2.76 52038 132.235.215.119 80 1 GET feeds.bbci.co.uk /news/rss.xml?edition=int - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 44841 200 OK - - (empty) - - - - - - FscOrx3YnSFtKUa9uh - text/atom
+1320279567.680708 CtgxRAqDLvrRUQdqe 192.168.2.76 52033 184.72.234.3 80 3 GET pixel.redditmedia.com /pixel/of_doom.png?id=t5_6&hash=e962d119a7ff69901bb4ceaa7f3ba1224fd704b7&r=741109704 http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 105 200 OK - - (empty) - - - - - - F6kKwQdgasTZr1aL3 - image/png
+1320279567.683031 C6nSoj1Qco9PGyslz6 192.168.2.76 52035 184.72.234.3 80 2 GET pixel.redditmedia.com /pixel/of_doom.png?id=t3_lsfmb&hash=1c635ac04668546a1c33c2faf3c4814cd6c4f96a&r=1492956402 http://www.reddit.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 105 200 OK - - (empty) - - - - - - FmHLsN1LHERYFmp4e2 - image/png
+1320279567.690049 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 1 GET ad.doubleclick.net /adj/reddit.dart/reddit.com;kw=reddit.com;tile=1;sz=300x250;ord=5117434431991380? http://www.redditmedia.com/ads/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 491 200 OK - - (empty) - - - - - - Fabf7l1EL26N2KoFX6 - application/javascript
+1320279568.281910 CtgxRAqDLvrRUQdqe 192.168.2.76 52033 184.72.234.3 80 4 GET pixel.redditmedia.com /pixel/of_defenestration.png?hash=a8ababd2e4912c8b21d72252ad18ebb5d8e27ea3&id=dart_reddit.com&random=5012335803517919 http://www.redditmedia.com/ads/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 105 200 OK - - (empty) - - - - - - FcDkzJ3PNtrAn4aZu6 - image/png
+1320279571.625521 CsBgiE1WmGP4Yo749h 192.168.2.76 52039 69.171.228.39 80 1 GET www.facebook.com / - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 31379 200 OK - - (empty) - - - - - - FSRE0d2Zg3eeFyEBhf - text/html
+1320279571.883692 CYfHyC28tAhkLYkXB7 192.168.2.76 52040 132.235.215.117 80 1 GET static.ak.fbcdn.net /rsrc.php/v1/yt/r/svonORc8tTu.css http://www.facebook.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 20200 200 OK - - (empty) - - - - - - F2U3Y12HmvdWxdclQ1 - text/plain
+1320279571.883724 CtANmVrHYMtkWqPE5 192.168.2.76 52041 132.235.215.117 80 1 GET static.ak.fbcdn.net /rsrc.php/v1/yZ/r/ejLIIb8vBQK.css http://www.facebook.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6968 200 OK - - (empty) - - - - - - FRGXkT2UUJEXviZzgf - text/plain
+1320279571.884016 CSTH8n1O1nv0ztxNQd 192.168.2.76 52042 132.235.215.117 80 1 GET static.ak.fbcdn.net /rsrc.php/v1/yp/r/kk8dc2UJYJ4.png http://www.facebook.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2209 200 OK - - (empty) - - - - - - FJroqp2fMBIRhSjj6j - image/png
+1320279571.884052 C4uDKU5tpeRU9Su19 192.168.2.76 52043 132.235.215.117 80 1 GET static.ak.fbcdn.net /rsrc.php/v1/yb/r/GsNJNwuI-UM.gif http://www.facebook.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 522 200 OK - - (empty) - - - - - - FkTSSMSu95IbbWyPk - image/gif
+1320279571.930335 CYfHyC28tAhkLYkXB7 192.168.2.76 52040 132.235.215.117 80 2 GET static.ak.fbcdn.net /rsrc.php/yi/r/q9U99v3_saj.ico - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 152 200 OK - - (empty) - - - - - - FA4O2QKRGwGeMhyWg - image/png
+1320279572.530622 CYfHyC28tAhkLYkXB7 192.168.2.76 52040 132.235.215.117 80 3 GET static.ak.fbcdn.net /rsrc.php/v1/yB/r/TwAHgQi2ZPB.png http://static.ak.fbcdn.net/rsrc.php/v1/yt/r/svonORc8tTu.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1203 200 OK - - (empty) - - - - - - FIp9Ei7407PZotrLf - image/png
+1320279572.541605 CYfHyC28tAhkLYkXB7 192.168.2.76 52040 132.235.215.117 80 4 GET static.ak.fbcdn.net /rsrc.php/v1/yu/r/O03OuHGGSjF.js http://www.facebook.com/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 14481 200 OK - - (empty) - - - - - - FXCacf3k0I8Jmv40V6 - text/plain
+1320279572.531333 CSTH8n1O1nv0ztxNQd 192.168.2.76 52042 132.235.215.117 80 2 GET static.ak.fbcdn.net /rsrc.php/v1/yi/r/OBaVg52wtTZ.png http://static.ak.fbcdn.net/rsrc.php/v1/yt/r/svonORc8tTu.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 42565 200 OK - - (empty) - - - - - - FKd4ju2Q2pBLbL2g5j - image/png
+1320279577.475501 CEh6Ka2HInkNSH01L2 192.168.2.76 52044 216.34.181.48 80 1 GET www.slashdot.org / - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 297 301 Moved Permanently - - (empty) - - - - - - FlEa1o4YEPG5x7R5mh - text/html
+1320279577.662818 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 2 GET www.google-analytics.com /siteopt.js?v=1&utmxkey=2467390112&utmx=9273847.00017148082467390112:2:4&utmxx=9273847.00017148082467390112:1320193640:2592000&utmxtime=1320279577646 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3968 200 OK - - (empty) - - - - - - Fe6QOa3PksIXzVHTE4 - text/plain
+1320279577.706621 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 1 GET a.fsdn.com /sd/topics/nasa_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3599 200 OK - - (empty) - - - - - - FS2GsS2N4xpsInXkc5 - image/png
+1320279577.706671 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 1 GET a.fsdn.com /sd/topics/redhat_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1708 200 OK - - (empty) - - - - - - FbrtkF2Bsf8qono1hl - image/png
+1320279577.727833 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 3 GET www.google-analytics.com /__utm.gif?utmwv=5.2.0&utms=1&utmn=2075689467&utmhn=slashdot.org&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/2467390112/test&utmac=UA-32013-38&utmcc=__utma=9273847.1625321166.1320279578.1320279578.1320279578.1;+__utmz=9273847.1320279578.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);+__utmx=9273847.00017148082467390112:2:4;&utmu=qACg~ http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FMI1K94zPiqlNScu2b - image/gif
+1320279577.526624 CjPGiy13ncXKxU765j 192.168.2.76 52045 216.34.181.45 80 1 GET slashdot.org / - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 92235 200 OK - - (empty) - - - - - - FC6fny4bS2LdWArKCd - text/html
+1320279577.706646 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 1 GET a.fsdn.com /sd/topics/apple_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5316 200 OK - - (empty) - - - - - - FrzGSm1jOZoVQ2Hx9k - image/png
+1320279577.746860 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 2 GET a.fsdn.com /sd/topics/news_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4791 200 OK - - (empty) - - - - - - FFzyL22N09AR4kpGqj - image/png
+1320279577.744727 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 2 GET a.fsdn.com /sd/topics/windows_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6070 200 OK - - (empty) - - - - - - FSY7De4YLIkMbdkgub - image/png
+1320279577.792926 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 3 GET a.fsdn.com /sd/topics/microsoft_64100.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4684 200 OK - - (empty) - - - - - - F1ZWL920coZQCa5hB6 - image/png
+1320279577.786697 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 2 GET a.fsdn.com /sd/topics/bug_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 7200 200 OK - - (empty) - - - - - - FkTxkx1LuAiF22kjQ5 - image/png
+1320279577.706695 CAUlC249svUfE6q0g3 192.168.2.76 52051 184.29.211.172 80 1 GET a.fsdn.com /sd/topics/science_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6820 200 OK - - (empty) - - - - - - FqSWHi2S4omFxuoqE8 - image/png
+1320279577.796082 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 3 GET a.fsdn.com /sd/topics/privacy_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5372 200 OK - - (empty) - - - - - - FEDr4Q1KVBpZpYyCvf - image/png
+1320279577.831213 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 4 GET a.fsdn.com /sd/topics/games_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4858 200 OK - - (empty) - - - - - - Fsf46e3M0rnbBBosjb - image/png
+1320279577.855921 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 3 GET a.fsdn.com /sd/topics/java_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5985 200 OK - - (empty) - - - - - - FzE9vp3dywOexb5lOj - image/png
+1320279577.706506 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 1 GET a.fsdn.com /sd/classic.css?release_20111101.01 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 102898 200 OK - - (empty) - - - - - - FeeI2T3XazYNxR2Aff - text/plain
+1320279577.885356 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 4 GET a.fsdn.com /sd/topics/facebook_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 935 200 OK - - (empty) - - - - - - F0pvzI2hxCu7CPDES4 - image/png
+1320279577.874879 CAUlC249svUfE6q0g3 192.168.2.76 52051 184.29.211.172 80 2 GET a.fsdn.com /sd/topics/topickde.gif http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3503 200 OK - - (empty) - - - - - - FaZ03A6N9Jr41XtA9 - image/gif
+1320279577.898479 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 5 GET a.fsdn.com /sd/topics/technology_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 7000 200 OK - - (empty) - - - - - - Ft1wSRxSA94TeB9vk - image/png
+1320279577.706532 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 1 GET a.fsdn.com /sd/all-minified.js?release_20111101.01 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 265231 200 OK - - (empty) - - - - - - FV4WlAnhOGEzG8yNf - text/plain
+1320279578.786070 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 4 GET www.google-analytics.com /__utm.gif?utmwv=5.2.0&utms=1&utmn=1576123726&utmhn=slashdot.org&utme=8(User Type*Page)9(Anon*index2)&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/&utmac=UA-32013-5&utmcc=__utma=57409013.1111154037.1320279579.1320279579.1320279579.1;+__utmz=57409013.1320279579.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);&utmu=qRCg~ http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FPFdR81eU5ibximh1c - image/gif
+1320279578.786348 CjPGiy13ncXKxU765j 192.168.2.76 52045 216.34.181.45 80 2 GET slashdot.org /favicon.ico - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 318 200 OK - - (empty) - - - - - - FNUo213hZ5nZPeveCg - image/x-icon
+1320279578.786168 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 2 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_p1_leader;pg=index2;logged_in=0;tile=1;sz=728x90;u=;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1102 200 OK - - (empty) - - - - - - FX5LMT3stFxRIOJTy6 - application/javascript
+1320279578.927905 CIJIDL1ULo4HpT24Gl 192.168.2.76 52052 63.241.108.124 80 1 GET bs.serving-sys.com /BurstingPipe/adServer.bs?cn=rsb&c=28&pli=3258172&PluID=0&w=728&h=90&ord=5919911&ucm=true&ncu=$$http://ad.doubleclick.net/click;h=v8/3bb4/3/0/*/i;246771152;0-0;0;47077322;3454-728/90;44177745/44195532/1;u=;~okv=;pg=index2;logged_in=0;tile=1;sz=728x90;u=;bsg=100834;bsg=100849;bsg=100972;bsg=100974;bsg=109739;~sscs=?$$ http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2445 200 OK - - (empty) - - - - - - F1gfQ01LTJYKrGF5f6 - text/plain
+1320279579.395786 CLsqp41RLUd83arUQb 192.168.2.76 52053 132.235.215.119 80 1 GET ds.serving-sys.com /BurstingCachedScripts//SBTemplates_2_4_11/StdBanner.js?ai=6818549 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 25789 200 OK - - (empty) - - - - - - FsP7B41SP02n8qy4Q4 - text/plain
+1320279579.411954 CLsqp41RLUd83arUQb 192.168.2.76 52053 132.235.215.119 80 2 GET ds.serving-sys.com /BurstingRes///Site-16990/Type-0/0c04460f-7d5c-47c7-bb52-d55a6cb9dfcc.gif http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 13402 200 OK - - (empty) - - - - - - Fwc35U3WIVMb3eEMih - image/gif
+1320279579.414248 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 3 GET ad.doubleclick.net /adj/ostg.slashdot/mainpage_p33_powerswitch;pg=index2;logged_in=0;tile=2;sz=980x66;u=;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 350 200 OK - - (empty) - - - - - - FHYUQHQwRCXF6z6m1 - application/javascript
+1320279579.446304 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 2 GET a.fsdn.com /sd/logo_w_l.png http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 916 200 OK - - (empty) - - - - - - Fq8jKs4ZEeQ86XLwHb - image/png
+1320279579.446541 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 2 GET a.fsdn.com /sd/classic/img/glyphish-icons-16.png http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 34897 200 OK - - (empty) - - - - - - Fp4mTFtTxLfj1aZ0k - image/png
+1320279579.494380 CbCciH11995WKkobR1 192.168.2.76 52054 74.121.134.156 80 1 GET data.cmcore.com /imp?tid=17&ci=90378805&vn1=4.1.1&vn2=imp&ec=UTF-8&cm_mmc=CL11Display-_-Geeknet-_-728x90-_-SimpleQ4 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 302 Found - - (empty) - - - - - - - - -
+1320279579.635947 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 3 GET a.fsdn.com /sd/classic/img/facebook_24.png http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1145 200 OK - - (empty) - - - - - - FrO4DB3JrPQuySFXqb - image/png
+1320279579.635700 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 3 GET a.fsdn.com /sd/classic/img/twitter_24.png http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1131 200 OK - - (empty) - - - - - - FwOft14FasgQFevesf - image/png
+1320279579.636241 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 4 GET a.fsdn.com /sd/classic/img/rss_24.png http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1394 200 OK - - (empty) - - - - - - Fg51Vl4RyzuxqyZong - image/png
+1320279579.660927 CbCciH11995WKkobR1 192.168.2.76 52054 74.121.134.156 80 2 GET data.cmcore.com /imp?tid=17&ci=90378805&vn1=4.1.1&vn2=imp&ec=UTF-8&cm_mmc=CL11Display-_-Geeknet-_-728x90-_-SimpleQ4&cvdone=s http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 43 200 OK - - (empty) - - - - - - FsfXhn4B6h8Cjd8sS8 - image/gif
+1320279579.605985 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 4 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_p83_medrec;pg=index2;logged_in=0;tile=3;sz=300x250,300x600;u=;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 37631 200 OK - - (empty) - - - - - - FKjsb32g87yJd7WC59 - application/javascript
+1320279579.754251 ClcvKE1dqsEFQu46m9 192.168.2.76 52055 74.125.225.91 80 1 GET s0.2mdn.net /1251057/plcr_44606913_1318531591501.js http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 16859 200 OK - - (empty) - - - - - - F8zvi64uyBZnSFW7X9 - text/plain
+1320279579.731050 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 5 GET ad.doubleclick.net /ad/N815.slashdot/B5855285.36;sz=1x1 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 302 Moved Temporarily - - (empty) - - - - - - - - -
+1320279579.788781 ClcvKE1dqsEFQu46m9 192.168.2.76 52055 74.125.225.91 80 2 GET s0.2mdn.net /879366/inpageGlobalTemplate_v2_62_06.js http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 47618 200 OK - - (empty) - - - - - - F1x0AK2HfI8zKiGCpc - text/plain
+1320279579.826149 CaP2LpLGvsmX7yJO 192.168.2.76 52056 74.125.225.91 80 1 GET s0.2mdn.net /viewad/3000209/14-1x1.gif http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 43 200 OK - - (empty) - - - - - - FwHSAt162BDr8cAtJc - image/gif
+1320279580.110519 ClcvKE1dqsEFQu46m9 192.168.2.76 52055 74.125.225.91 80 3 GET s0.2mdn.net /1251057/PID_1778428_MABQrgjDNeiVz7Kj.swf http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 30158 200 OK - - (empty) - - - - - - FiWyYW1UE23Xn9Du4c - application/x-shockwave-flash
+1320279580.134281 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 6 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_p31_lower_poll_spons;pg=index;logged_in=0;tile=4;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 481 200 OK - - (empty) - - - - - - FHGSmj2OR6IRPOR1Rg - application/javascript
+1320279580.212196 ClcvKE1dqsEFQu46m9 192.168.2.76 52055 74.125.225.91 80 4 GET s0.2mdn.net /viewad/1251080/peelUp2.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 9700 200 OK - - (empty) - - - - - - FDXrgk2emoeMrxUO52 - image/png
+1320279580.212311 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 7 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_CPL_medrec;pg=index;logged_in=0;tile=5;sz=300x250;ord=6795061899455057;? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 346 200 OK - - (empty) - - - - - - FcCddr4x0GnKCSZ8q1 - application/javascript
+1320279580.339065 CNbPns4mOMGgjI8Ele 192.168.2.76 52057 204.246.169.3 80 1 GET d1clfvuu2240eh.cloudfront.net /crossdomain.xml - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 76 200 OK - - (empty) - - - - - - FkbZHZVBBE3Z1ZgDh - text/x-cross-domain-policy
+1320279580.382077 CNbPns4mOMGgjI8Ele 192.168.2.76 52057 204.246.169.3 80 2 GET d1clfvuu2240eh.cloudfront.net /t.gif?m=a:W5Tk9EhlHtS1pyYL+RycSdDuNycgbdBawaGo+otmkKetUyhIY6Wu7kA=&m=b:JnQ9aW1wcmVzc2lvbiZyPTc2 - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 43 200 OK - - (empty) - - - - - - FMHtHn3vMLs8pHW5O4 - image/gif
+1320279580.341750 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 8 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_p85_medrec;pg=index2;logged_in=0;tile=6;sz=300x250,300x600;u=;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 857 200 OK - - (empty) - - - - - - FcmK3c38gruwiDs6xe - application/javascript
+1320279581.309602 C185u7u9Q4qhJPhzl 192.168.2.76 52060 74.125.225.92 80 1 GET pagead2.googlesyndication.com /pagead/show_ads.js http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279581.313348 CKzjfhsJ8vrn2rrfg 192.168.2.76 52058 207.171.163.23 80 1 GET farm.sproutbuilder.com /crossdomain.xml - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 75 200 OK - - (empty) - - - - - - FRmk7R24HzVNTD5jM5 - text/x-cross-domain-policy
+1320279581.510471 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 5 GET www.google-analytics.com /__utm.gif?utmwv=5.2.0&utms=2&utmn=949132929&utmhn=slashdot.org&utmt=event&utme=5(Firehose*FirehoseMore*10)8(User Type*Page)9(Anon*index2)&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/&utmac=UA-32013-5&utmcc=__utma=57409013.1111154037.1320279579.1320279579.1320279579.1;+__utmz=57409013.1320279579.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);&utmu=6RCgAAAAAAAAAAAAQ~ http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FFCJkh2igAZa2JEKsg - image/gif
+1320279581.442967 CKzjfhsJ8vrn2rrfg 192.168.2.76 52058 207.171.163.23 80 2 GET farm.sproutbuilder.com /runtime.xml - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 853 200 OK - - (empty) - - - - - - FM2Cma4R3x8nKUayJ1 - application/xml
+1320279581.425927 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 9 GET ad.doubleclick.net /adj/ostg.slashdot/pg_index_google_medrec;pg=index2;logged_in=0;tile=7;sz=300x250,300x600;u=;ord=6795061899455057? http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 862 200 OK - - (empty) - - - - - - FVjOxU23aI5BNmJX2h - application/javascript
+1320279581.494295 CiIjAe1n5MnPOVpQ9f 192.168.2.76 52061 74.125.225.90 80 1 GET googleads.g.doubleclick.net /pagead/ads?client=ca-ostg_js&format=300x250_pas_abgnc&output=html&h=250&w=300&lmt=1320279577&channel=books_sd_pages&region=default&ad_type=text,image,flash,html&adtest=off&alt_color=ffffff&color_bg=cccccc&color_border=bababa&color_line=c8c8c8&color_link=002f2f&color_text=000000&oe=utf8&flash=10.1.102&url=http://slashdot.org/&adsafe=high&dt=1320279581339&bpp=3&shv=r20111026&jsv=r20110914&correlator=1320279581423&frm=4&adk=3033987521&ga_vid=473684895.1320279581&ga_sid=1320279581&ga_hid=756102172&ga_fc=0&ga_wpids=UA-32013-5&u_tz=-240&u_his=3&u_java=0&u_h=800&u_w=1280&u_ah=726&u_aw=1280&u_cd=24&u_nplug=4&u_nmime=64&dff=arial&dfs=13&adx=939&ady=1333&biw=1265&bih=617&fu=0&ifi=1&dtd=128&xpc=ZMG9awPxwx&p=http://slashdot.org http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4365 200 OK - - (empty) - - - - - - F3NRgf4pxU4hVreqGi - text/html
+1320279581.820179 CGv2Tp4Ngt8MmKmVRd 192.168.2.76 52062 132.235.215.119 80 1 GET b.scorecardresearch.com /b?c1=2&c2=6035546&rn=0.8987666179077362&c7=http://slashdot.org/&c3=&c4=&c5=&c6=&c10=&c15=&c16=&c8=Slashdot: News for nerds, stuff that matters&c9=&cv=1.7 http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 204 No Content - - (empty) - - - - - - - - -
+1320279581.866795 C185u7u9Q4qhJPhzl 192.168.2.76 52060 74.125.225.92 80 2 GET pagead2.googlesyndication.com /pagead/imgad?id=CICAgMDOnZWCUxCsAhj6ATIICPPzdVZiN_g http://googleads.g.doubleclick.net/pagead/ads?client=ca-ostg_js&format=300x250_pas_abgnc&output=html&h=250&w=300&lmt=1320279577&channel=books_sd_pages&region=default&ad_type=text%2Cimage%2Cflash%2Chtml&adtest=off&alt_color=ffffff&color_bg=cccccc&color_border=bababa&color_line=c8c8c8&color_link=002f2f&color_text=000000&oe=utf8&flash=10.1.102&url=http%3A%2F%2Fslashdot.org%2F&adsafe=high&dt=1320279581339&bpp=3&shv=r20111026&jsv=r20110914&correlator=1320279581423&frm=4&adk=3033987521&ga_vid=473684895.1320279581&ga_sid=1320279581&ga_hid=756102172&ga_fc=0&ga_wpids=UA-32013-5&u_tz=-240&u_his=3&u_java=0&u_h=800&u_w=1280&u_ah=726&u_aw=1280&u_cd=24&u_nplug=4&u_nmime=64&dff=arial&dfs=13&adx=939&ady=1333&biw=1265&bih=617&fu=0&ifi=1&dtd=128&xpc=ZMG9awPxwx&p=http%3A//slashdot.org 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 40252 200 OK - - (empty) - - - - - - FpH8io1fXFSErb0719 - application/x-shockwave-flash
+1320279581.833299 CiIjAe1n5MnPOVpQ9f 192.168.2.76 52061 74.125.225.90 80 2 GET googleads.g.doubleclick.net /pagead/ads?client=ca-ostg_js&format=300x250_pas_abgnc&output=html&h=250&w=300&lmt=1320279577&channel=slashdot_imu_geo_us&region=default&ad_type=text,image,flash,html&adtest=off&alt_color=ffffff&color_bg=cccccc&color_border=bababa&color_line=c8c8c8&color_link=002f2f&color_text=000000&oe=utf8&flash=10.1.102&url=http://slashdot.org/&adsafe=high&dt=1320279581648&bpp=3&shv=r20111026&jsv=r20110914&prev_fmts=300x250_pas_abgnc&correlator=1320279581423&frm=4&adk=2897144109&ga_vid=473684895.1320279581&ga_sid=1320279581&ga_hid=756102172&ga_fc=0&u_tz=-240&u_his=3&u_java=0&u_h=800&u_w=1280&u_ah=726&u_aw=1280&u_cd=24&u_nplug=4&u_nmime=64&dff=arial&dfs=13&adx=939&ady=3468&biw=1265&bih=617&fu=0&ifi=2&dtd=172&xpc=8j2egD1P4r&p=http://slashdot.org http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2878 200 OK - - (empty) - - - - - - FNIXjx45CYFKs7kZF5 - text/html
+1320279582.056477 CiIjAe1n5MnPOVpQ9f 192.168.2.76 52061 74.125.225.90 80 3 GET googleads.g.doubleclick.net /pagead/imgad?id=CLK48PnasdKuNxCsAhj6ATII1hcxUl9z8x8 http://googleads.g.doubleclick.net/pagead/ads?client=ca-ostg_js&format=300x250_pas_abgnc&output=html&h=250&w=300&lmt=1320279577&channel=slashdot_imu_geo_us&region=default&ad_type=text%2Cimage%2Cflash%2Chtml&adtest=off&alt_color=ffffff&color_bg=cccccc&color_border=bababa&color_line=c8c8c8&color_link=002f2f&color_text=000000&oe=utf8&flash=10.1.102&url=http%3A%2F%2Fslashdot.org%2F&adsafe=high&dt=1320279581648&bpp=3&shv=r20111026&jsv=r20110914&prev_fmts=300x250_pas_abgnc&correlator=1320279581423&frm=4&adk=2897144109&ga_vid=473684895.1320279581&ga_sid=1320279581&ga_hid=756102172&ga_fc=0&u_tz=-240&u_his=3&u_java=0&u_h=800&u_w=1280&u_ah=726&u_aw=1280&u_cd=24&u_nplug=4&u_nmime=64&dff=arial&dfs=13&adx=939&ady=3468&biw=1265&bih=617&fu=0&ifi=2&dtd=172&xpc=8j2egD1P4r&p=http%3A//slashdot.org 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 47034 200 OK - - (empty) - - - - - - FsE8Xf1Is5TGXnetD5 - image/gif
+1320279582.246333 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 1 GET edge.sproutbuilder.com /crossdomain.xml - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 75 200 OK - - (empty) - - - - - - FVXCaI2T2NHgtAv0tb - text/x-cross-domain-policy
+1320279582.411626 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 4 GET a.fsdn.com /sd/spinner_ffffff_on_004242.gif http://a.fsdn.com/sd/classic.css?release_20111101.01 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1849 200 OK - - (empty) - - - - - - FlloV02bcrqQfmom13 - image/gif
+1320279582.409055 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 6 GET www.google-analytics.com /__utm.gif?utmwv=5.2.0&utms=3&utmn=246596971&utmhn=slashdot.org&utmt=event&utme=5(Firehose*FirehoseMore*20)8(User Type*Page)9(Anon*index2)&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/&utmac=UA-32013-5&utmcc=__utma=57409013.1111154037.1320279579.1320279579.1320279579.1;+__utmz=57409013.1320279579.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);&utmu=6RCgAAAAAAAAAAAAQ~ http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - F0yeUn1hZB9Y7yejMj - image/gif
+1320279582.288447 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 2 GET edge.sproutbuilder.com /code/1319516275/player.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 291690 200 OK - - (empty) - - - - - - FA1xCj2DTlHjcsG0H7 - application/x-shockwave-flash
+1320279582.366695 CjPGiy13ncXKxU765j 192.168.2.76 52045 216.34.181.45 80 3 POST slashdot.org /ajax.pl http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 584 88073 200 OK - - (empty) - - - FCo92D1aKZZwcho8T3 - text/plain FzIP4GoO5f5PVho8l - text/json
+1320279584.545928 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 5 GET a.fsdn.com /sd/topics/medicine_64.png?refresh=now http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2377 200 OK - - (empty) - - - - - - F8qktS1RoJMLjjMYX - image/png
+1320279584.546009 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 6 GET a.fsdn.com /sd/topics/government_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4069 200 OK - - (empty) - - - - - - FTA0804fE7gZIXNT9b - image/png
+1320279584.546848 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 5 GET a.fsdn.com /sd/topics/censorship_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4975 200 OK - - (empty) - - - - - - FbZkOe38GSLykHirIa - image/png
+1320279584.544804 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 4 GET a.fsdn.com /sd/topics/business_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6221 200 OK - - (empty) - - - - - - FboOO11NKqIFhA2jAi - image/png
+1320279584.546073 CAUlC249svUfE6q0g3 192.168.2.76 52051 184.29.211.172 80 3 GET a.fsdn.com /sd/topics/power_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4293 200 OK - - (empty) - - - - - - FnNo9O1IVWySYiWof3 - image/png
+1320279584.582221 CjinlH2fzDtvzI9637 192.168.2.76 52049 184.29.211.172 80 6 GET a.fsdn.com /sd/topics/hp_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6772 200 OK - - (empty) - - - - - - F52lFL2Slu0Yj1b9h3 - image/png
+1320279584.591410 Cedw7H3ddE2yLiLoXc 192.168.2.76 52050 184.29.211.172 80 7 GET a.fsdn.com /sd/topics/security_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4562 200 OK - - (empty) - - - - - - FiL1v32LLpGAfCoxGj - image/png
+1320279584.595893 CaEFHq2HVQ5iGJQiD9 192.168.2.76 52048 184.29.211.172 80 6 GET a.fsdn.com /sd/topics/court_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5591 200 OK - - (empty) - - - - - - FvuG3B1pRIwIYLWXb8 - image/png
+1320279584.544227 Ct6ixh35y9AEr7J7o9 192.168.2.76 52047 184.29.211.172 80 5 GET a.fsdn.com /sd/topics/china_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 10079 200 OK - - (empty) - - - - - - FEjKFT1N7SHLlgUDie - image/png
+1320279584.602215 CPoz7NUpXISemlNSd 192.168.2.76 52046 184.29.211.172 80 5 GET a.fsdn.com /sd/topics/money_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5459 200 OK - - (empty) - - - - - - FwxTAhFrD0SefH1Sj - image/png
+1320279584.624590 CAUlC249svUfE6q0g3 192.168.2.76 52051 184.29.211.172 80 4 GET a.fsdn.com /sd/topics/idle_64.png http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6556 200 OK - - (empty) - - - - - - Fs2vnI3rv9Lzrna8m - image/png
+1320279584.594900 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 3 GET edge.sproutbuilder.com /font/Tahoma.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 60686 200 OK - - (empty) - - - - - - FM0cqy3Sr1FMqQu4R4 - application/x-shockwave-flash
+1320279584.635813 Cs5yEZ3ELZTeuTOsP4 192.168.2.76 52064 204.246.169.252 80 1 GET edge.sproutbuilder.com /font/Futura.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 63675 200 OK - - (empty) - - - - - - FgA7fUcDv9ymIxGik - application/x-shockwave-flash
+1320279584.651727 Cu4gIx1BDNtGOl7Ht2 192.168.2.76 52065 204.246.169.252 80 1 GET edge.sproutbuilder.com /font/Archer.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 77236 200 OK - - (empty) - - - - - - FraIcD2n6aVym9cqsc - application/x-shockwave-flash
+1320279585.764353 CRgW2I2zo3SInm6iT8 192.168.2.76 52066 204.246.169.217 80 1 GET edgy.sproutbuilder.com /crossdomain.xml - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 75 200 OK - - (empty) - - - - - - FZiisa2oO1yLpfxavf - text/x-cross-domain-policy
+1320279585.653934 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 4 GET edge.sproutbuilder.com /code/1319516275/com.sproutbuilder.components.video.VideoComponent.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 100368 200 OK - - (empty) - - - - - - FzRX504YyLGx2Mqk8b - application/x-shockwave-flash
+1320279585.839709 Cu4gIx1BDNtGOl7Ht2 192.168.2.76 52065 204.246.169.252 80 2 GET edge.sproutbuilder.com /code/1319516275/com.sproutbuilder.components.button.ButtonComponent.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 27471 200 OK - - (empty) - - - - - - FZR5pf1Sn9SSiYJF37 - application/x-shockwave-flash
+1320279586.039240 CejI402rKGtdBXij4f 192.168.2.76 52068 204.246.169.217 80 1 GET edgy.sproutbuilder.com /asset/aADeSoj6NM7TVgD-.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1170 200 OK - - (empty) - - - - - - F0NexnjX9pfFNWVmk - image/png
+1320279586.039757 C2KnU34GcVV6amo8va 192.168.2.76 52069 204.246.169.217 80 1 GET edgy.sproutbuilder.com /asset/wwCdFIihNP2BVYdd.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1248 200 OK - - (empty) - - - - - - Fmjv7q4q8sYJInU3C - image/png
+1320279586.041164 C5vx4911iSMAJuShFd 192.168.2.76 52070 204.246.169.217 80 1 GET edgy.sproutbuilder.com /asset/3ADTPIg3NBsgWP5u.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1838 200 OK - - (empty) - - - - - - FtXp4r2NHB0rsNJVZ9 - image/png
+1320279586.052831 CbUCgw1DrIGcXzONB7 192.168.2.76 52071 204.246.169.217 80 1 GET edgy.sproutbuilder.com /asset/qABVt4hSNIK2WmTu.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 668 200 OK - - (empty) - - - - - - FuM3Px3V9iLL9UWuR6 - image/png
+1320279586.081611 CejI402rKGtdBXij4f 192.168.2.76 52068 204.246.169.217 80 2 GET edgy.sproutbuilder.com /asset/UgDmFIiWNOMoVJD_.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1031 200 OK - - (empty) - - - - - - FzSLhC1MkvDzSRPqMh - image/png
+1320279586.037832 CWJhMU2cTLEnseTmCb 192.168.2.76 52067 204.246.169.217 80 1 GET edgy.sproutbuilder.com /asset/dQA7E4gKNDB1UJoP.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 4570 200 OK - - (empty) - - - - - - FZL5uJ1ZdfYUKShkVb - image/png
+1320279586.000195 CRgW2I2zo3SInm6iT8 192.168.2.76 52066 204.246.169.217 80 2 GET edgy.sproutbuilder.com /asset/vgBY54hjNDESTf27.jpg - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6921 200 OK - - (empty) - - - - - - FGB1Ugi2qN3KCeA3j - image/jpeg
+1320279587.052749 CRgW2I2zo3SInm6iT8 192.168.2.76 52066 204.246.169.217 80 3 GET edgy.sproutbuilder.com /asset/qABVt4hSNIK2WmTu.png - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279587.124669 C96j2X1DixgLTj2Oi8 192.168.2.76 52072 74.125.225.64 80 1 GET www.youtube.com /crossdomain.xml - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 306 200 OK - - (empty) - - - - - - FAyeVc3FzNroUbHvdi - text/x-cross-domain-policy
+1320279587.627640 C96j2X1DixgLTj2Oi8 192.168.2.76 52072 74.125.225.64 80 2 GET www.youtube.com /apiplayer?version=3 - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2177 200 OK - - (empty) - - - - - - FvuQ063vjYp4OXZCkj - application/x-shockwave-flash
+1320279588.180462 CYYyja3FFNEnftw3K6 192.168.2.76 52073 74.125.225.72 80 1 GET s.ytimg.com /yt/swfbin/apiplayer3-vflmM-6Dr.swf - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 174499 200 OK - - (empty) - - - - - - FSARBI7PBlWKampzk - application/x-shockwave-flash
+1320279589.337053 CBHHuR1xFnm5C5CQBc 192.168.2.76 52074 74.125.225.76 80 1 GET i4.ytimg.com /vi/gDbg_GeuiSY/hqdefault.jpg - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 893 404 Not Found - - (empty) - - - - - - F2GiAw3j1m22R2yIg2 - image/jpeg
+1320279589.319143 Cu4gIx1BDNtGOl7Ht2 192.168.2.76 52065 204.246.169.252 80 3 GET edge.sproutbuilder.com /code/1319516275/com.sproutbuilder.platforms.DoubleClickPlatform.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 24725 200 OK - - (empty) - - - - - - FkCpou1t1Vt0YinJq6 - application/x-shockwave-flash
+1320279589.317863 C5DisEMFU77Wk9Kae 192.168.2.76 52063 204.246.169.252 80 5 GET edge.sproutbuilder.com /code/1319516275/com.sproutbuilder.platforms.GoogleAnalyticsPlatform.swf - 1.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 51897 200 OK - - (empty) - - - - - - FiBTwJ2zXXVZZ3aI0d - application/x-shockwave-flash
+1320279590.080406 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 10 GET ad.doubleclick.net /activity;src=1251057;met=1;v=1;pid=47077323;aid=247206211;ko=11;cid=44589125;rid=44606913;rv=1;&timestamp=1320279590078;eid1=2;ecn1=1;etm1=8; http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 42 200 OK - - (empty) - - - - - - Fa4s1w3OIKrgQOmn1c - image/gif
+1320279590.554429 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 7 GET www.google-analytics.com /__utm.gif?utmwv=4.3as&utmn=1977361745&utmhn=s0.2mdn.net&utmt=event&utme=5(cachedCodeMiss*MABQrgjDNeiVz7Kj* )(0)&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/&utmac=UA-5905822-1&utmcc=__utma=83256788.1532070249585310700.1304822985.1320193646.1320279590.297; - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FoZQYe34dgjuHgb1Sd - image/gif
+1320279590.579330 CD1jfU3p9abEm77mzf 192.168.2.76 52075 74.125.225.78 80 1 GET www.google-analytics.com /__utm.gif?utmwv=4.3as&utmn=754945709&utmhn=s0.2mdn.net&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/sprout/MABQrgjDNeiVz7Kj/view&utmac=UA-5905822-1&utmcc=__utma=83256788.1532070249585310700.1304822985.1320193646.1320279590.297; - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - Fyq8F21bTZJAyHUxIb - image/gif
+1320279590.581157 CN5hnY3x51j6Hr1v4 192.168.2.76 52036 74.125.225.78 80 8 GET www.google-analytics.com /__utm.gif?utmwv=4.3as&utmn=1428329940&utmhn=s0.2mdn.net&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/MABQrgjDNeiVz7Kj&utmac=UA-32013-47&utmcc=__utma=83256788.1532070249585310700.1304822985.1320279590.1320279590.298; - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - FHnvsV2OYtFTWZGPM9 - image/gif
+1320279590.581430 C0K9DaoPFkfnzwlZa 192.168.2.76 52076 74.125.225.78 80 1 GET www.google-analytics.com /__utm.gif?utmwv=4.3as&utmn=223025521&utmhn=s0.2mdn.net&utmcs=UTF-8&utmsr=1280x800&utmsc=24-bit&utmul=en-us&utmje=0&utmfl=10.1 r102&utmdt=Slashdot: News for nerds, stuff that matters&utmhid=756102172&utmr=-&utmp=/MABQrgjDNeiVz7Kj/Untitled Page&utmac=UA-32013-47&utmcc=__utma=83256788.1532070249585310700.1304822985.1320279590.1320279590.298; - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 35 200 OK - - (empty) - - - - - - Feqm4J3iuQBtNnTEre - image/gif
+1320279600.078941 CmWpC33jXuKpXNLcie 192.168.2.76 52037 74.125.225.91 80 11 GET ad.doubleclick.net /activity;src=1251057;met=1;v=1;pid=47077323;aid=247206211;ko=11;cid=44589125;rid=44606913;rv=1;&timestamp=1320279600077;eid1=2;ecn1=0;etm1=10; http://slashdot.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 42 200 OK - - (empty) - - - - - - FC2TUu4ohZGmou4as - image/gif
+1320279600.921844 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 1 GET www.google.com /jsapi http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 23184 200 OK - - (empty) - - - - - - Fhm2NC27oehfBrVKsd - text/plain
+1320279600.688672 CbQAWi3GX2bCmX5L56 192.168.2.76 52078 192.150.187.43 80 1 GET www.bro-ids.org / - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 14258 200 OK - - (empty) - - - - - - FY05u72qZWO5o7Z2a - text/html
+1320279600.921091 Cd8s2R3OGDgkhnvSu9 192.168.2.76 52079 192.150.187.43 80 1 GET www.bro-ids.org /css/pygments.css http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2957 200 OK - - (empty) - - - - - - FR5Qvt1sx1p8pzmdtj - text/plain
+1320279600.924479 CX1GjC4vn52UY1uDv6 192.168.2.76 52082 192.150.187.43 80 1 GET www.bro-ids.org /css/print.css http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 334 200 OK - - (empty) - - - - - - FgV8RW27C5HTHOolrk - text/plain
+1320279600.921641 CBeaXe4Iyj1gXd2Iq 192.168.2.76 52080 192.150.187.43 80 1 GET www.bro-ids.org /css/960.css http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5600 200 OK - - (empty) - - - - - - FcT6ak3zlX7zUFMefh - text/plain
+1320279601.025685 CX1GjC4vn52UY1uDv6 192.168.2.76 52082 192.150.187.43 80 2 GET www.bro-ids.org /js/jquery.zrssfeed.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3324 200 OK - - (empty) - - - - - - FhKTDH1mwUptcDlgU9 - text/plain
+1320279600.995522 CbQAWi3GX2bCmX5L56 192.168.2.76 52078 192.150.187.43 80 2 GET www.bro-ids.org /js/jquery.fancybox-1.3.4.pack.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 15669 200 OK - - (empty) - - - - - - FqFURH1MR5BhnnvfZh - text/plain
+1320279601.021907 Cd8s2R3OGDgkhnvSu9 192.168.2.76 52079 192.150.187.43 80 2 GET www.bro-ids.org /js/jquery.tweet.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 8894 200 OK - - (empty) - - - - - - FeFVLI3Awcp2Tgpdxj - text/plain
+1320279601.130463 CX1GjC4vn52UY1uDv6 192.168.2.76 52082 192.150.187.43 80 3 GET www.bro-ids.org /js/superfish.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3833 200 OK - - (empty) - - - - - - FoAMYj4is1GDyS2dZi - text/plain
+1320279601.201354 CbQAWi3GX2bCmX5L56 192.168.2.76 52078 192.150.187.43 80 3 GET www.bro-ids.org /js/hoverIntent.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3257 200 OK - - (empty) - - - - - - FO8dv4OWQKKWRq0M7 - text/plain
+1320279601.219818 Cd8s2R3OGDgkhnvSu9 192.168.2.76 52079 192.150.187.43 80 3 GET www.bro-ids.org /js/general.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5108 200 OK - - (empty) - - - - - - FJQxkp6TVhaNdhg6f - text/plain
+1320279601.127352 CBeaXe4Iyj1gXd2Iq 192.168.2.76 52080 192.150.187.43 80 2 GET www.bro-ids.org /js/jquery.tableofcontents.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 10384 200 OK - - (empty) - - - - - - FYKJ0y2gwKzVqIPOu5 - text/plain
+1320279600.921817 CmWpSw3VtjiAceBCwf 192.168.2.76 52081 192.150.187.43 80 1 GET www.bro-ids.org /css/bro-ids.css http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 23964 200 OK - - (empty) - - - - - - FtYub54s8HXI8r2JT1 - text/plain
+1320279601.239924 CX1GjC4vn52UY1uDv6 192.168.2.76 52082 192.150.187.43 80 4 GET www.bro-ids.org /js/jquery.collapse.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 5735 200 OK - - (empty) - - - - - - F0xM1j3wDeCr0UqNS1 - text/plain
+1320279600.925084 CaPClb1Bf0RrRGtyWi 192.168.2.76 52083 192.150.187.43 80 1 GET www.bro-ids.org /js/jquery.cycle.all.min.js http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 31052 200 OK - - (empty) - - - - - - FSQQ8nplvGBhBLgz8 - text/plain
+1320279601.385890 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 2 GET www.google.com /uds/?file=search&v=1&hl=en http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 615 200 OK - - (empty) - - - - - - FDwylw2NdwC19wGS77 - text/plain
+1320279601.554052 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 3 GET www.google.com /uds/?file=ads&v=3&packages=search&async=2 http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 441 200 OK - - (empty) - - - - - - FietVd1NOjUCHJiqpa - text/plain
+1320279601.305092 CbQAWi3GX2bCmX5L56 192.168.2.76 52078 192.150.187.43 80 4 GET www.bro-ids.org /images/bro-eyes.png http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 46415 200 OK - - (empty) - - - - - - FxO0Mzcsll6F6W5If - image/png
+1320279601.576535 CibfNy1QQW4ImDWRq5 192.168.2.76 52088 74.125.225.83 80 1 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279601.576629 CTRXSR3blXJE5ZE7Ij 192.168.2.76 52089 74.125.225.83 80 1 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279601.585473 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 1 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279601362&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - F1zJJe3NVHAaTYoSB2 - text/plain
+1320279601.636171 CK957ERTz8lBycly4 192.168.2.76 52085 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279601360 http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Fu8xI43gbfnTmSOEh - text/plain
+1320279601.631059 C3TZMB4CrUwYfkGJy1 192.168.2.76 52086 199.59.148.20 80 1 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279601361 http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - F6HZ0A3TyUou56RR2i - text/plain
+1320279610.842497 CO5QKYQkcSdxQFA35 192.168.2.76 52090 192.150.187.43 80 1 GET www.bro-ids.org /download/index.html http://www.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 18981 200 OK - - (empty) - - - - - - FQ5FRM2xyT1BwXV8d2 - text/html
+1320279611.147279 CO5QKYQkcSdxQFA35 192.168.2.76 52090 192.150.187.43 80 2 GET www.bro-ids.org /js/breadcrumbs.js http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 2021 200 OK - - (empty) - - - - - - FatmzL3v37tIyHwqBd - text/plain
+1320279611.248377 CO5QKYQkcSdxQFA35 192.168.2.76 52090 192.150.187.43 80 3 GET www.bro-ids.org /images/icons/download.png http://www.bro-ids.org/css/bro-ids.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 716 200 OK - - (empty) - - - - - - FdcBQFJQuOKnBUiN7 - image/png
+1320279611.530084 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 4 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279611.530359 CibfNy1QQW4ImDWRq5 192.168.2.76 52088 74.125.225.83 80 2 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279611.527729 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 2 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279611010&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FJ1t1Z2EpTTMw2Rrdk - text/plain
+1320279611.527499 C3TZMB4CrUwYfkGJy1 192.168.2.76 52086 199.59.148.20 80 2 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279611009 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FWPC0B25vmDQsn5Uid - text/plain
+1320279611.615559 CurHpb1TGZOktTRNP1 192.168.2.76 52092 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279611008 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - F1zPyq3ZCdx2Przg4d - text/plain
+1320279612.151517 CO5QKYQkcSdxQFA35 192.168.2.76 52090 192.150.187.43 80 4 GET www.bro-ids.org /documentation/index.html http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 14762 200 OK - - (empty) - - - - - - FAhpvZ1Au5PG4I7Aah - text/html
+1320279612.497234 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 5 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/documentation/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279612.497348 CTRXSR3blXJE5ZE7Ij 192.168.2.76 52089 74.125.225.83 80 2 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279612.495602 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 3 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279612311&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/documentation/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FUcAdl1oIIu09uHxQh - text/plain
+1320279612.495458 C3TZMB4CrUwYfkGJy1 192.168.2.76 52086 199.59.148.20 80 3 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279612310 http://www.bro-ids.org/documentation/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - Fk2gkj3kfAL1hYWbG5 - text/plain
+1320279612.574308 CuUKOQ1R3CqKBgeTdf 192.168.2.76 52093 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279612309 http://www.bro-ids.org/documentation/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - FpSSeZ2ZRioppjrZji - text/plain
+1320279613.969241 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 6 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279613.970081 CibfNy1QQW4ImDWRq5 192.168.2.76 52088 74.125.225.83 80 3 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279613.968918 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 4 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279613813&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FraFOz3DFPTGZNaJC6 - text/plain
+1320279613.968841 C3TZMB4CrUwYfkGJy1 192.168.2.76 52086 199.59.148.20 80 4 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279613812 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FmB8iY3WlgS5hBY7Wf - text/plain
+1320279614.052578 C3xkHgJnzZszVSTpi 192.168.2.76 52094 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279613811 http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - F762sm4bW4MkAIJJGe - text/plain
+1320279616.824058 CMrjgF2XLmRh9C9TR4 192.168.2.76 52095 208.85.41.42 80 1 GET cont-sjl-1.pandora.com /images/public/amz/0/9/0/0/842694020090_500W_433H.jpg app:/desktop.swf 1.1 Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/531.9 (KHTML, like Gecko) AdobeAIR/2.6 0 59209 200 OK - - (empty) - - - - - - FipMsu3eD5AnIRq2N - image/jpeg
+1320279630.119515 C2vQ8sVgyADHjtEda 192.168.2.76 52096 192.150.187.43 80 1 GET www.bro-ids.org /community/index.html http://www.bro-ids.org/download/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 15087 200 OK - - (empty) - - - - - - FeyKb7qKmO9eR5OKi - text/html
+1320279630.488327 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 7 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/community/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279630.488443 CTRXSR3blXJE5ZE7Ij 192.168.2.76 52089 74.125.225.83 80 3 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279630.486761 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 5 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279630306&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/community/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - F9xd37OdlAikt5No5 - text/plain
+1320279630.565603 CD69521bDXIAb4IkW 192.168.2.76 52097 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279630304 http://www.bro-ids.org/community/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - FQPsz94ybCmQu6Xiq4 - text/plain
+1320279630.566430 CC3vUI3gFB04zLvWRa 192.168.2.76 52098 199.59.148.20 80 1 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279630305 http://www.bro-ids.org/community/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FgGEuUcNVvhufCFR3 - text/plain
+1320279636.797267 C7Krri4g9tZfHniGXh 192.168.2.76 52099 192.150.187.43 80 1 GET www.bro-ids.org /development/index.html http://www.bro-ids.org/community/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 18428 200 OK - - (empty) - - - - - - FNbqYH3mmO41rlz20h - text/html
+1320279637.219103 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 8 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/development/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279637.219249 CibfNy1QQW4ImDWRq5 192.168.2.76 52088 74.125.225.83 80 4 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279637.215608 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 6 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279636956&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/development/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FAnyyncILgPoNLSa - text/plain
+1320279637.303129 CmxyBl2c8XAMTuHEk4 192.168.2.76 52100 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279636954 http://www.bro-ids.org/development/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - F7JE7E2W4ihR5mCZhe - text/plain
+1320279637.215272 CC3vUI3gFB04zLvWRa 192.168.2.76 52098 199.59.148.20 80 2 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279636955 http://www.bro-ids.org/development/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - F3SK3Te5UYn22w7ji - text/plain
+1320279638.548436 CSvs6v26bQqFylkk6l 192.168.2.76 52101 192.150.187.43 80 1 GET git.bro-ids.org / http://www.bro-ids.org/development/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 10073 200 OK - - (empty) - - - - - - F4qJsD4pKcjLtpeXEa - text/html
+1320279639.050631 C4pHul1H3OeWYz7o7i 192.168.2.76 52102 192.150.187.43 80 1 GET git.bro-ids.org /static/git-logo.png http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 207 200 OK - - (empty) - - - - - - F5il8p3yYIq690qvNc - image/png
+1320279639.053683 C7Lcvr4vsTf6eYpBva 192.168.2.76 52104 192.150.187.43 80 1 GET git.bro-ids.org /static/git-favicon.png - 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1150 200 OK - - (empty) - - - - - - FBCz8D1BQ3SiYOv7m9 - image/x-icon
+1320279639.047586 CSvs6v26bQqFylkk6l 192.168.2.76 52101 192.150.187.43 80 2 GET git.bro-ids.org /static/gitweb.css http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 9186 200 OK - - (empty) - - - - - - FyTRixVp6ulaxUUq2 - text/plain
+1320279639.244415 CxyAKs10ppnHFP6O8i 192.168.2.76 52106 192.150.187.43 80 1 GET www-new.bro-ids.org /frames/header.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 225 302 Found - - (empty) - - - - - - FrucKB2amhlamv0ivb - text/html
+1320279639.244463 C6MrHk2C7rLuJqhjsg 192.168.2.76 52107 192.150.187.43 80 1 GET www-new.bro-ids.org /frames/footer.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 225 302 Found - - (empty) - - - - - - FpddCQ3BDmmGcuG9C3 - text/html
+1320279639.348046 C7Krri4g9tZfHniGXh 192.168.2.76 52099 192.150.187.43 80 2 GET www.bro-ids.org /frames/header.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 3516 200 OK - - (empty) - - - - - - Fzea5XNhn9eNRMvx7 - text/html
+1320279639.053730 CV8faD4L1sLL5kDwN9 192.168.2.76 52103 192.150.187.43 80 1 GET git.bro-ids.org /static/gitweb.js http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 24528 200 OK - - (empty) - - - - - - F983UxQF0o4kjJjuf - text/plain
+1320279639.463465 C7Krri4g9tZfHniGXh 192.168.2.76 52099 192.150.187.43 80 3 GET www.bro-ids.org /images/logo-bro-small.png http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6075 200 OK - - (empty) - - - - - - Fw6FlF4WtotJFNXmHb - image/png
+1320279639.448670 CvfUrT2DgYXXoZw9Ah 192.168.2.76 52109 192.150.187.43 80 1 GET www.bro-ids.org /frames/footer.html http://git.bro-ids.org/ 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6695 200 OK - - (empty) - - - - - - FkCp6k4tqksK3tiSy7 - text/html
+1320279639.786857 CBX0254QJoklXNbvv2 192.168.2.76 52110 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279639636 http://www.bro-ids.org/frames/footer.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Feut0t346XEHsQ0OC7 - text/plain
+1320279672.372857 C6Ym6jvMgikT0xTTc 192.168.2.76 52111 192.150.187.43 80 1 GET www.bro-ids.org /research/index.html http://www.bro-ids.org/frames/header.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 47728 200 OK - - (empty) - - - - - - FOze0l2aT79uPyMiv7 - text/html
+1320279673.123842 CTRXSR3blXJE5ZE7Ij 192.168.2.76 52089 74.125.225.83 80 4 GET www.google.com /uds/css/clear.gif http://www.google.com/uds/api/search/1.0/473bb688d0c0dd605119ad983f5a4386/default+en.css 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279673.123121 CbNCgO1MzloHRNeY4f 192.168.2.76 52084 74.125.225.83 80 9 GET www.google.com /uds/css/small-logo.png http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 0 304 Not Modified - - (empty) - - - - - - - - -
+1320279673.121725 CnGze54kQWWpKqrrZ4 192.168.2.76 52087 209.85.145.95 80 7 GET ajax.googleapis.com /ajax/services/feed/load?v=1.0&callback=jsonp1320279672539&q=http://blog.bro-ids.org/feeds/posts/default&num=5 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6584 200 OK - - (empty) - - - - - - FXEXQEMH8DrEuAdg8 - text/plain
+1320279673.204466 CJLgi92kpp2gLgGTE5 192.168.2.76 52113 199.59.148.20 80 1 GET api.twitter.com /1/statuses/user_timeline.json?screen_name=Bro_IDS&count=2&include_rts=1&callback=jsonp1320279672538 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 6095 200 OK - - (empty) - - - - - - FAVIuu2XZQyVznfnq8 - text/plain
+1320279673.198815 CRNn9f1zKNlzHSM5pa 192.168.2.76 52112 199.59.148.201 80 1 GET search.twitter.com /search.json?&q=#BroIDS&rpp=2&callback=jsonp1320279672537 http://www.bro-ids.org/research/index.html 1.1 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 0 1543 200 OK - - (empty) - - - - - - Fzjgwn8xXem3Esvk - text/plain
+#close 2017-04-16-21-36-10
diff --git a/test/logfile_crlf.0 b/test/logfile_crlf.0
new file mode 100644
index 0000000..501ee63
--- /dev/null
+++ b/test/logfile_crlf.0
@@ -0,0 +1,2 @@
+2012-07-02 10:22:40,672:DEBUG:foo bar baz
+2014-10-08 16:56:38,344:WARN:foo bar baz
diff --git a/test/logfile_cxx.0 b/test/logfile_cxx.0
new file mode 100644
index 0000000..f8de8cf
--- /dev/null
+++ b/test/logfile_cxx.0
@@ -0,0 +1 @@
+Mar 24 15:17:38.999 000000000264F I shmem.res 262144 262144 1 chassis_msg_svc/osenv::req_blocking<osenv::req_lambda<tcp_messaging_impl::register_app(svc::messaging_port, defs::atom*, defs::borrowed<svc::messaging_session>, defs::owned<svc::connection_eviction_strategy>&&, svc::messaging::connection_type, svc::messaging::app_param)::{lambda()#1}>, osenv::aloc_dynamic_named<tcp_messaging_impl::register_app(svc::messaging_port, defs::atom*, defs::borrowed<svc::messaging_session>, defs::owned<svc::connection_eviction_strategy>&&, svc::messaginconnection_type, svc::messaging::app_param)::{lambda()#1}, osenv::temporal, tcp_messaging_impl::register_app(svc::messaging_port, defs::atom*, defs::borrowed<svc::messaging_session>, des::owned<svc::connection_eviction_strategy>&&, svc::messaging::connection_type, svc::messaging::app_param)::{lambda()#1}>, osenv::req>->fiber stacks
diff --git a/test/logfile_empty.0 b/test/logfile_empty.0
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/logfile_empty.0
diff --git a/test/logfile_epoch.0 b/test/logfile_epoch.0
new file mode 100644
index 0000000..2e0197f
--- /dev/null
+++ b/test/logfile_epoch.0
@@ -0,0 +1,2 @@
+1428634687123 Hello, World!
+1428634687456 Goodbye, World!
diff --git a/test/logfile_epoch.1 b/test/logfile_epoch.1
new file mode 100644
index 0000000..645f051
--- /dev/null
+++ b/test/logfile_epoch.1
@@ -0,0 +1,2 @@
+2015-04-09 19:58:07.123000 Hello, World!
+2015-04-09 19:58:07.456000 Goodbye, World!
diff --git a/test/logfile_filter.0 b/test/logfile_filter.0
new file mode 100644
index 0000000..6a5ac12
--- /dev/null
+++ b/test/logfile_filter.0
@@ -0,0 +1,13 @@
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: Joining mDNS multicast group on interface virbr0.IPv4 with address 192.168.122.1.
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: New relevant interface virbr0.IPv4 for mDNS.
+Dec 6 13:01:34 ubu-mac avahi-daemon[786]: Registering new address record for 192.168.122.1 on virbr0.IPv4.
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: started, version 2.68 cachesize 150
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: DHCP, IP range 192.168.122.2 -- 192.168.122.254, lease time 1h
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: DHCP, sockets bound exclusively to interface virbr0
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: reading /etc/resolv.conf
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: using nameserver 192.168.1.1#53
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: read /etc/hosts - 5 addresses
+Dec 6 13:01:34 ubu-mac dnsmasq[1840]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
+Dec 6 13:01:34 ubu-mac dnsmasq-dhcp[1840]: read /var/lib/libvirt/dnsmasq/default.hostsfile
+Dec 6 13:05:01 ubu-mac CRON[3883]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)
diff --git a/test/logfile_for_join.0 b/test/logfile_for_join.0
new file mode 100644
index 0000000..b811ae9
--- /dev/null
+++ b/test/logfile_for_join.0
@@ -0,0 +1,10 @@
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: New relevant interface eth0.IPv4 for mDNS.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Joining mDNS multicast group on interface eth0.IPv4 with address 10.1.10.103.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Registering new address record for 10.1.10.103 on eth0.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Withdrawing address record for 10.1.10.103 on eth0.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Leaving mDNS multicast group on interface eth0.IPv4 with address 10.1.10.103.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: iface.c: interface_mdns_mcast_join() called but no local address available.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Interface eth0.IPv4 no longer relevant for mDNS.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: New relevant interface eth0.IPv4 for mDNS.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Joining mDNS multicast group on interface eth0.IPv4 with address 10.1.10.103.
+Apr 28 06:53:55 tstack-centos5 avahi-daemon[2467]: Registering new address record for 10.1.10.103 on eth0.
diff --git a/test/logfile_generic.0 b/test/logfile_generic.0
new file mode 100644
index 0000000..944fe50
--- /dev/null
+++ b/test/logfile_generic.0
@@ -0,0 +1,2 @@
+2012-07-02 10:22:40,672:DEBUG:foo bar baz
+2014-10-08 16:56:38,344:WARN:foo bar baz \ No newline at end of file
diff --git a/test/logfile_generic.1 b/test/logfile_generic.1
new file mode 100644
index 0000000..173c027
--- /dev/null
+++ b/test/logfile_generic.1
@@ -0,0 +1,2 @@
+2015-04-24T21:09:29.296 25376]INFO:somemodule:Something very INFOrmative.
+2015-04-24T21:09:39.296 25376]ERROR:somemodule:Something very INFOrmative.
diff --git a/test/logfile_generic.2 b/test/logfile_generic.2
new file mode 100644
index 0000000..71cc21a
--- /dev/null
+++ b/test/logfile_generic.2
@@ -0,0 +1,2 @@
+2015-04-24T21:08:10.313913+00:00 err rbd [22968]lotuscreds:ERROR:Could not retrieve lotus account information from db
+2015-04-24T21:08:58.430632+00:00 err rbd [24206]networkutil:ERROR:The configured address sg01-1-vc1.oc.vmware.com was invalid
diff --git a/test/logfile_generic.3 b/test/logfile_generic.3
new file mode 100644
index 0000000..a883793
--- /dev/null
+++ b/test/logfile_generic.3
@@ -0,0 +1,2 @@
+20120702.102240,672:DEBUG:foo bar baz
+20141008.165638,344:WARN:foo bar baz
diff --git a/test/logfile_generic_with_header.0 b/test/logfile_generic_with_header.0
new file mode 100644
index 0000000..bea5673
--- /dev/null
+++ b/test/logfile_generic_with_header.0
@@ -0,0 +1,4 @@
+Header1: abc
+Header2: def
+2012-07-02 10:22:40,672:DEBUG:foo bar baz
+2014-10-08 16:56:38,344:WARN:foo bar baz \ No newline at end of file
diff --git a/test/logfile_glog.0 b/test/logfile_glog.0
new file mode 100644
index 0000000..ba6eb9b
--- /dev/null
+++ b/test/logfile_glog.0
@@ -0,0 +1,7 @@
+E0517 15:04:22.619632 1952452992 logging_unittest.cc:253] Log every 3, iteration 19
+I0517 15:04:22.619642 952452992 logging_unittest.cc:259] Log if every 1, iteration 19
+I0517 15:04:22.619740 52452992 logging_unittest.cc:259] Log if every 1, iteration 20
+W0517 15:04:22.619751 2452992 logging_unittest.cc:263] log_if this
+I0517 15:04:22.619760 452992 logging_unittest.cc:267] array
+I0517 15:04:22.619768 52992 logging_unittest.cc:269] const array
+E0517 15:04:22.619776 2992 logging_unittest.cc:271] foo 1000 0000001000 3e8
diff --git a/test/logfile_haproxy.0 b/test/logfile_haproxy.0
new file mode 100644
index 0000000..a9ee9e6
--- /dev/null
+++ b/test/logfile_haproxy.0
@@ -0,0 +1,17 @@
+Feb 25 16:19:38 192.168.4.2 haproxy[1]: Proxy prod_http_in started.
+Feb 25 16:19:38 192.168.4.2 haproxy[1]: Proxy tools_http_frnt started.
+Feb 25 16:19:38 192.168.4.2 haproxy[1]: Proxy git_inio_ssh_frnt started.
+Feb 25 16:19:49 192.168.4.2 haproxy[7]: 141.35.244.171:53332 [25/Feb/2019:16:19:48.143] prod_http_in~ bk_admin/nginx_sonst 0/0/7/1457/1487 200 11394 - - ---- 2/1/0/0/0 0/0 {Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /admin/colt/administration?survey=130&input_stats=1&ajax=1&&ajax=1&refresh=1&ihandle=1 HTTP/1.1"
+Feb 25 16:19:49 192.168.4.2 haproxy[7]: 92.193.212.151:59841 [25/Feb/2019:16:19:49.851] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/0/62/62 200 306 - - ---- 3/2/0/0/0 0/0 {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36} {} "POST /portal/?Script=934&onlinetest=speichereKorrektur&anm=10347 HTTP/1.1"
+Feb 25 16:19:57 192.168.4.2 haproxy[7]: 92.193.212.151:59842 [25/Feb/2019:16:19:57.515] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/1/37/38 200 306 - - ---- 2/1/0/0/0 0/0 {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36} {} "POST /portal/?Script=934&onlinetest=speichereKorrektur&anm=10347 HTTP/1.1"
+Feb 25 16:20:02 192.168.4.2 haproxy[7]: 79.246.138.36:7891 [25/Feb/2019:16:20:02.367] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/1/327/328 200 306 - - ---- 1/1/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "POST /portal/?Script=934&onlinetest=speichereKorrektur&anm=13531 HTTP/1.1"
+Feb 25 16:20:04 192.168.4.2 haproxy[7]: 141.35.244.171:53337 [25/Feb/2019:16:20:03.208] prod_http_in~ bk_admin/nginx_sonst 0/0/1/1031/1039 200 11394 - - ---- 3/2/0/0/0 0/0 {Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /admin/colt/administration?survey=130&input_stats=1&ajax=1&&ajax=1&refresh=1&ihandle=1 HTTP/1.1"
+Feb 25 16:20:09 192.168.4.2 haproxy[7]: 89.247.124.65:15564 [25/Feb/2019:16:20:06.321] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/1/43/2707 200 26170 - - ---- 3/3/1/1/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /portal/?Script=934&onlinetest=korrektur&anm=13915&currentPage=0 HTTP/1.1"
+Feb 25 16:20:11 192.168.4.2 haproxy[7]: 89.247.124.65:15565 [25/Feb/2019:16:20:08.872] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/1/26/2442 200 26170 - - ---- 3/2/1/1/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /portal/?Script=934&onlinetest=korrektur&anm=13915&currentPage=0 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50186 [25/Feb/2019:16:20:11.910] prod_http_in~ bk_ktest_kt/nginx_sonst 0/0/0/236/236 200 4586 - - ---- 4/4/3/3/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /portal/?Script=934&lehrer=77798 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50186 [25/Feb/2019:16:20:12.234] prod_http_in~ bk_ktest_sonst/nginx_sonst 0/0/1/0/1 200 16416 - - ---- 4/4/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /media/core/bootstrap_3.3.7/css/bootstrap.css?1550939643 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50186 [25/Feb/2019:16:20:12.317] prod_http_in~ bk_ktest_sonst/nginx_sonst 0/0/0/1/1 200 11065 - - ---- 9/9/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /media/core/jquery/jquery-ui-1.12.1.js?1550939557 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 95.216.197.33:56224 [25/Feb/2019:16:20:10.111] prod_http_in/sktst2: SSL handshake failure
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50188 [25/Feb/2019:16:20:12.321] prod_http_in~ bk_ktest_sonst/nginx_sonst 0/0/1/0/1 200 5959 - - ---- 9/9/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /media/pi_fontawesome/css/font-awesome.css?1550939694 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50187 [25/Feb/2019:16:20:12.325] prod_http_in~ bk_ktest_sonst/nginx_sonst 0/0/1/0/1 200 1859 - - ---- 9/9/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /media/pi_popup/1.1.0/magnific-popup.css?1550939704 HTTP/1.1"
+Feb 25 16:20:12 192.168.4.2 haproxy[7]: 87.183.41.77:50189 [25/Feb/2019:16:20:12.331] prod_http_in~ bk_ktest_sonst/nginx_sonst 0/0/1/0/1 200 2496 - - ---- 9/9/0/0/0 0/0 {Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0} {} "GET /media/core/core.css?1550939640 HTTP/1.1"
diff --git a/test/logfile_invalid_json.json b/test/logfile_invalid_json.json
new file mode 100644
index 0000000..f95af65
--- /dev/null
+++ b/test/logfile_invalid_json.json
@@ -0,0 +1,5 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "@fields": { "lvl": "TRACE", "msg": "trace test"}}
+{"ts": "2013-09-06T20:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Starting up service"}}
+{"ts": "2013-09-06T22:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Shutting down service\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG5", "msg": "Details..."}}
+{"ts": "2013-09-06T22:00:59.222222Z", "@fields": { "lvl": "DEBUG4", "msg": "Details..."}}
diff --git a/test/logfile_invalid_json2.json b/test/logfile_invalid_json2.json
new file mode 100644
index 0000000..ed97989
--- /dev/null
+++ b/test/logfile_invalid_json2.json
@@ -0,0 +1,3 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "@fields": { "lvl": "TRACE", "msg": "trace test"}}
+{"ts": "2013-09-06T20:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Starting up service"}}
+{"ts": "2013-09-06T22:00:49.124817Z", "@fields": { "lvl": "INFO", "msg":
diff --git a/test/logfile_journald.json b/test/logfile_journald.json
new file mode 100644
index 0000000..5654ae7
--- /dev/null
+++ b/test/logfile_journald.json
@@ -0,0 +1,2 @@
+{ "__CURSOR" : "s=e991dd5775894620914f2f7126aae6c1;i=372a;b=0dc874d3fbd44bdbb6fbcfaa27481492;m=24ea327;t=573f280a663fd;x=9ceeb77ef4331563", "__REALTIME_TIMESTAMP" : "1534860261221373", "__MONOTONIC_TIMESTAMP" : "38708007", "_BOOT_ID" : "0dc874d3fbd44bdbb6fbcfaa27481492", "PRIORITY" : "1", "_MACHINE_ID" : "1234567890abcdef1234567890abcdef", "_HOSTNAME" : "imx6ul-medusa", "SYSLOG_FACILITY" : "3", "_UID" : "0", "_GID" : "0", "_SYSTEMD_SLICE" : "system.slice", "_CAP_EFFECTIVE" : "3fffffffff", "_TRANSPORT" : "stdout", "_STREAM_ID" : "d6422e98dfb24d128e274f917f04362f", "SYSLOG_IDENTIFIER" : "python", "_PID" : "184", "_COMM" : "python", "_EXE" : "/usr/bin/python2.7", "_CMDLINE" : "/usr/bin/python -u /usr/bin/medusa/GpsLocator/GpsLocator.py", "_SYSTEMD_CGROUP" : "/system.slice/medusa-GpsLocator.service", "_SYSTEMD_UNIT" : "medusa-GpsLocator.service", "_SYSTEMD_INVOCATION_ID" : "e8fb03c1b8bf47b8ac2fc82f9870fd57", "MESSAGE" : "GPS Reference longitude: 7.358143333" }
+{ "__CURSOR" : "s=e991dd5775894620914f2f7126aae6c1;i=372b;b=0dc874d3fbd44bdbb6fbcfaa27481492;m=24ea327;t=573f280a663fd;x=26df66509c108970", "__REALTIME_TIMESTAMP" : "1534860261221373", "__MONOTONIC_TIMESTAMP" : "38708007", "_BOOT_ID" : "0dc874d3fbd44bdbb6fbcfaa27481492", "PRIORITY" : "6", "_MACHINE_ID" : "1234567890abcdef1234567890abcdef", "_HOSTNAME" : "imx6ul-medusa", "SYSLOG_FACILITY" : "3", "_UID" : "0", "_GID" : "0", "_SYSTEMD_SLICE" : "system.slice", "_CAP_EFFECTIVE" : "3fffffffff", "_TRANSPORT" : "stdout", "_STREAM_ID" : "d6422e98dfb24d128e274f917f04362f", "SYSLOG_IDENTIFIER" : "python", "_PID" : "184", "_COMM" : "python", "_EXE" : "/usr/bin/python2.7", "_CMDLINE" : "/usr/bin/python -u /usr/bin/medusa/GpsLocator/GpsLocator.py", "_SYSTEMD_CGROUP" : "/system.slice/medusa-GpsLocator.service", "_SYSTEMD_UNIT" : "medusa-GpsLocator.service", "_SYSTEMD_INVOCATION_ID" : "e8fb03c1b8bf47b8ac2fc82f9870fd57", "MESSAGE" : "GPS Reference latitude: 46.908706667" }
diff --git a/test/logfile_json.json b/test/logfile_json.json
new file mode 100644
index 0000000..ef750df
--- /dev/null
+++ b/test/logfile_json.json
@@ -0,0 +1,13 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "lvl": "TRACE", "msg": "trace test"}
+{"ts": "2013-09-06T20:00:49.124817Z", "lvl": "INFO", "msg": "Starting up service"}
+{"ts": "2013-09-06T22:00:49.124817Z", "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG5", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG4", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG3", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG2", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG", "msg": "Details..."}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "STATS", "msg": "1 beat per second"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "WARNING", "msg": "not looking good"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "ERROR", "msg": "looking bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "CRITICAL", "msg": "sooo bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "FATAL", "msg": "shoot", "obj": { "field1" : "hi", "field2": 2 }, "arr" : ["hi", {"sub1": true}]}
diff --git a/test/logfile_json2.json b/test/logfile_json2.json
new file mode 100644
index 0000000..9a3921e
--- /dev/null
+++ b/test/logfile_json2.json
@@ -0,0 +1,3 @@
+{"ts": "2013-09-06T20:00:49.124817Z", "lvl": 0, "msg": "Starting up service", "cl": "com.exmaple.foo"}
+{"ts": "2013-09-06T22:00:49.124817Z", "lvl": 0, "msg": "Shutting down service", "user": "steve@example.com", "cl": "com.exmaple.foo"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": 10, "msg": "looking bad", "cl": "com.exmaple.foo"}
diff --git a/test/logfile_json3.json b/test/logfile_json3.json
new file mode 100644
index 0000000..5d23279
--- /dev/null
+++ b/test/logfile_json3.json
@@ -0,0 +1,3 @@
+{ "started_at": 1490385986240, "response": { "status": 200, "size": "443", "headers": { "server": "nginx\/1.11.10", "content-type": "application\/json", "connection": "close", "cache-control": "max-age=0, must-revalidate, no-cache, no-store, private" } }, "request": { "method": "GET", "uri": "\/example\/uri\/5", "size": "166", "querystring": {}, "headers": { "host": "example.com" } }, "client_ip": "1.1.1.1" }
+{ "started_at": 1490386367764.0, "response": { "status": 500, "size": "443", "headers": { "server": "nginx\/1.11.10", "content-type": "application\/json", "connection": "close", "cache-control": "max-age=0, must-revalidate, no-cache, no-store, private" } }, "request": { "method": "GET", "uri": "\/example\/uri\/5", "size": "166", "querystring": {}, "headers": { "host": "example.com" } }, "client_ip": "1.1.1.1" }
+{ "started_at": 1490386531694, "response": { "status": 400, "size": "443", "headers": { "server": "nginx\/1.11.10", "content-type": "application\/json", "connection": "close", "cache-control": "max-age=0, must-revalidate, no-cache, no-store, private" } }, "request": { "method": "GET", "uri": "\/example\/uri\/5", "size": "166", "querystring": {}, "headers": { "host": "example.com" } }, "client_ip": "1.1.1.1", "details1": {"foo": "bar"}, "details2": {"foo": "bar"}, "details3": {"foo": "bar"} }
diff --git a/test/logfile_json_subsec.json b/test/logfile_json_subsec.json
new file mode 100644
index 0000000..3ddc190
--- /dev/null
+++ b/test/logfile_json_subsec.json
@@ -0,0 +1,2 @@
+{"instant":{"epochSecond": 1663977609,"nanoOfSecond": 484000000}, "msg": "Hello, World!"}
+{"instant":{"epochSecond": 1663977619,"nanoOfSecond": 222000000}, "msg": "Goodbye, World!"}
diff --git a/test/logfile_leveltest.0 b/test/logfile_leveltest.0
new file mode 100644
index 0000000..9105fb4
--- /dev/null
+++ b/test/logfile_leveltest.0
@@ -0,0 +1,8 @@
+2016-06-30 12:00:01 trace tracemessage
+2016-06-30 12:00:02 debug debugmessage
+2016-06-30 12:00:03 debug2 debug2message
+2016-06-30 12:00:04 debug3 debug3message
+2016-06-30 12:00:05 info infomessage
+2016-06-30 12:00:06 warn warnmessage
+2016-06-30 12:00:07 fatal fatalmessage
+2016-06-30 12:00:08 invalid invalidmessage
diff --git a/test/logfile_logfmt.0 b/test/logfile_logfmt.0
new file mode 100644
index 0000000..c453b35
--- /dev/null
+++ b/test/logfile_logfmt.0
@@ -0,0 +1,5 @@
+time="2021-09-15T21:17:10.220731Z" level=error msg="error retrieving pod status: pod inc-1-enh-domain-c14-ns-2/hello-inc-1-enh-domain-c14-ns-2-3-d8f465685-k75gp is not found: PodNotFound" namespace=inc-1-enh-domain-c14-ns-2 pod=hello-inc-1-enh-domain-c14-ns-2-3-d8f465685-k75gp reason= status=Pending
+time="2021-09-15T21:17:11.674149Z" level=warning msg="Failed to DeletePod in the provider" error="pod inc-1-domain-c14-ns-6/fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b is not found: PodNotFound" namespace=inc-1-domain-c14-ns-6 pod=fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b uid=be2def59-3a08-42fd-8f84-6f64cfcefa93
+time="2021-09-15T21:17:11.678991Z" level=info msg="DeletionGracePeriodSeconds set to 0" namespace=inc-1-domain-c14-ns-6 pod=fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b uid=be2def59-3a08-42fd-8f84-6f64cfcefa93
+time="2021-09-15T21:17:11.679036Z" level=info msg="Pod deleted" namespace=inc-1-domain-c14-ns-6 pod=fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b uid=be2def59-3a08-42fd-8f84-6f64cfcefa93
+time="2021-09-15T21:18:20.335825Z" level=error msg="error retrieving pod status: pod inc-1-enh-domain-c14-ns-2/hello-inc-1-enh-domain-c14-ns-2-7-5ddd6bcd69-6rqct is not found: PodNotFound" namespace=inc-1-enh-domain-c14-ns-2 pod=hello-inc-1-enh-domain-c14-ns-2-7-5ddd6bcd69-6rqct reason= status=Pending
diff --git a/test/logfile_mixed_json2.json b/test/logfile_mixed_json2.json
new file mode 100644
index 0000000..6ddcb81
--- /dev/null
+++ b/test/logfile_mixed_json2.json
@@ -0,0 +1,18 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "lvl": "TRACE", "msg": "trace test"}
+{"ts": "2013-09-06T20:00:49.124817Z", "lvl": "INFO", "msg": "Starting up service"}
+{"ts": "2013-09-06T22:00:49.124817Z", "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}
+timestamp="2013-09-06T22:00:50.123000Z" level="INFO" msg="Hello, World"
+panic: foo bar failed baz
+ level1.py:10034
+ level2.py:100
+ level3.py:42
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG5", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG4", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG3", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG2", "msg": "Details..."}
+{"ts": "2013-09-06T22:00:59.124817Z", "lvl": "DEBUG", "msg": "Details..."}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "STATS", "msg": "1 beat per second"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "WARNING", "msg": "not looking good"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "ERROR", "msg": "looking bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "CRITICAL", "msg": "sooo bad"}
+{"ts": "2013-09-06T22:01:49.124817Z", "lvl": "FATAL", "msg": "shoot", "obj": { "field1" : "hi", "field2": 2 }, "arr" : ["hi", {"sub1": true}]}
diff --git a/test/logfile_multiline.0 b/test/logfile_multiline.0
new file mode 100644
index 0000000..b1c7de0
--- /dev/null
+++ b/test/logfile_multiline.0
@@ -0,0 +1,3 @@
+2009-07-20 22:59:27,672:DEBUG:Hello, World!
+ How are you today?
+2009-07-20 22:59:30,221:ERROR:Goodbye, World!
diff --git a/test/logfile_nested_json.json b/test/logfile_nested_json.json
new file mode 100644
index 0000000..6cc8072
--- /dev/null
+++ b/test/logfile_nested_json.json
@@ -0,0 +1,13 @@
+{"ts": "2013-09-06T20:00:48.124817Z", "@fields": { "lvl": "TRACE", "msg": "trace test"}}
+{"ts": "2013-09-06T20:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Starting up service"}}
+{"ts": "2013-09-06T22:00:49.124817Z", "@fields": { "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"}}
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG5", "msg": "Details..."}}
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG4", "msg": "Details..."}}
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG3", "msg": "Details..."}}
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG2", "msg": "Details..."}}
+{"ts": "2013-09-06T22:00:59.124817Z", "@fields": { "lvl": "DEBUG", "msg": "Details..."}}
+{"ts": "2013-09-06T22:01:49.124817Z", "@fields": { "lvl": "STATS", "msg": "1 beat per second"}}
+{"ts": "2013-09-06T22:01:49.124817Z", "@fields": { "lvl": "WARNING", "msg": "not looking good"}}
+{"ts": "2013-09-06T22:01:49.124817Z", "@fields": { "lvl": "ERROR", "msg": "looking bad"}}
+{"ts": "2013-09-06T22:01:49.124817Z", "@fields": { "lvl": "CRITICAL", "msg": "sooo bad"}}
+{"ts": "2013-09-06T22:01:49.124817Z", "@fields": { "lvl": "FATAL", "msg": "shoot", "trace": ["line:1", "line:2"]}}
diff --git a/test/logfile_openam.0 b/test/logfile_openam.0
new file mode 100644
index 0000000..6268cdd
--- /dev/null
+++ b/test/logfile_openam.0
@@ -0,0 +1,2 @@
+"2014-06-15 01:04:52" "http://localhost:8086|/|<samlp:Response xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol"" ID=""s2daac0735bf476f4560aab81104b623bedfb0cbc0"" InResponseTo=""84cbf2be33f6410bbe55877545a93f02"" Version=""2.0"" IssueInstant=""2014-06-15T01:04:52Z"" Destination=""http://localhost:8086/api/1/rest/admin/org/530e42ccd6f45fd16d0d0717/saml/consume""><saml:Issuer xmlns:saml=""urn:oasis:names:tc:SAML:2.0:assertion"">http://openam.vagrant.dev/openam</saml:Issuer><samlp:Status xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol"">\\n<samlp:StatusCode xmlns:samlp=""urn:oasis:names:tc:SAML:2.0:protocol""\\nValue=""urn:oasis:names:tc:SAML:2.0:status:Success"">\\n</samlp:StatusCode>\\n</samlp:Status><saml:Assertion xmlns:saml=""urn:oasis:names:tc:SAML:2.0:assertion"" ID=""s2a0bee0da937e236167e99b209802056033816ac2"" IssueInstant=""2014-06-15T01:04:52Z"" Version=""2.0"">\\n<saml:Issuer>http://openam.vagrant.dev/openam</saml:Issuer><ds:Signature xmlns:ds=""http://www.w3.org/2000/09/xmldsig#"">\\n<ds:SignedInfo>\\n<ds:CanonicalizationMethod Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#""/>\\n<ds:SignatureMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#rsa-sha1""/>\\n<ds:Reference URI=""#s2a0bee0da937e236167e99b209802056033816ac2"">\\n<ds:Transforms>\\n<ds:Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>\\n<ds:Transform Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#""/>\\n</ds:Transforms>\\n<ds:DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1""/>\\n<ds:DigestValue>4uSmVzjovUdQd3px/RcnoxQBsqE=</ds:DigestValue>\\n</ds:Reference>\\n</ds:SignedInfo>\\n<ds:SignatureValue>\\nhm/grge36uA6j1OWif2bTcvVTwESjmuJa27NxepW0AiV5YlcsHDl7RAIk6k/CjsSero3bxGbm56m\\nYncOEi9F1Tu7dS0bfx+vhm/kKTPgwZctf4GWn4qQwP+KeoZywbNj9ShsYJ+zPKzXwN4xBSuPjMxP\\nNf5szzjEWpOndQO/uDs=\\n</ds:SignatureValue>\\n<ds:KeyInfo>\\n<ds:X509Data>\\n<ds:X509Certificate>\\nMIICQDCCAakCBEeNB0swDQYJKoZIhvcNAQEEBQAwZzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh\\nbGlmb3JuaWExFDASBgNVBAcTC1NhbnRhIENsYXJhMQwwCgYDVQQKEwNTdW4xEDAOBgNVBAsTB09w\\nZW5TU08xDTALBgNVBAMTBHRlc3QwHhcNMDgwMTE1MTkxOTM5WhcNMTgwMTEyMTkxOTM5WjBnMQsw\\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExDDAK\\nBgNVBAoTA1N1bjEQMA4GA1UECxMHT3BlblNTTzENMAsGA1UEAxMEdGVzdDCBnzANBgkqhkiG9w0B\\nAQEFAAOBjQAwgYkCgYEArSQc/U75GB2AtKhbGS5piiLkmJzqEsp64rDxbMJ+xDrye0EN/q1U5Of+\\nRkDsaN/igkAvV1cuXEgTL6RlafFPcUX7QxDhZBhsYF9pbwtMzi4A4su9hnxIhURebGEmxKW9qJNY\\nJs0Vo5+IgjxuEWnjnnVgHTs1+mq5QYTA7E6ZyL8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQB3Pw/U\\nQzPKTPTYi9upbFXlrAKMwtFf2OW4yvGWWvlcwcNSZJmTJ8ARvVYOMEVNbsT4OFcfu2/PeYoAdiDA\\ncGy/F2Zuj8XJJpuQRSE6PtQqBuDEHjjmOQJ0rV/r8mO1ZCtHRhpZ5zYRjhRC9eCbjx9VrFax0JDC\\n/FfwWigmrW0Y0Q==\\n</ds:X509Certificate>\\n</ds:X509Data>\\n</ds:KeyInfo>\\n</ds:Signature><saml:Subject>\\n<saml:NameID Format=""urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"" NameQualifier=""http://openam.vagrant.dev/openam"">user@example.com</saml:NameID><saml:SubjectConfirmation Method=""urn:oasis:names:tc:SAML:2.0:cm:bearer"">\\n<saml:SubjectConfirmationData InResponseTo=""84cbf2be33f6410bbe55877545a93f02"" NotOnOrAfter=""2014-06-15T01:14:52Z"" Recipient=""http://localhost:8086/api/1/rest/admin/org/530e42ccd6f45fd16d0d0717/saml/consume""/></saml:SubjectConfirmation>\\n</saml:Subject><saml:Conditions NotBefore=""2014-06-15T00:54:52Z"" NotOnOrAfter=""2014-06-15T01:14:52Z"">\\n<saml:AudienceRestriction>\\n<saml:Audience>http://localhost:8086</saml:Audience>\\n</saml:AudienceRestriction>\\n</saml:Conditions>\\n<saml:AuthnStatement AuthnInstant=""2014-06-15T01:00:25Z"" SessionIndex=""s2f9b4d4b453d12b40ef3905cc959cdb40579c2301""><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>" id=openamuser,ou=user,dc=openam 82e87195d704585501 "Not Available" INFO dc=openam "cn=dsameuser,ou=DSAME Users,dc=openam" SAML2-37 SAML2.access user@example.com 192.168.33.1
+"2014-06-15 01:04:52" vagrant|/ "cn=dsameuser,ou=DSAME Users,dc=openam" ec5708a7f199678a01 "Not Available" FINE dc=openam "cn=dsameuser,ou=DSAME Users,dc=openam" COT-22 COT.access "Not Available" 127.0.1.1
diff --git a/test/logfile_plain.0 b/test/logfile_plain.0
new file mode 100644
index 0000000..13bc727
--- /dev/null
+++ b/test/logfile_plain.0
@@ -0,0 +1,3 @@
+Hello, World!
+How are you?
+Goodbye, World!
diff --git a/test/logfile_pretty.0 b/test/logfile_pretty.0
new file mode 100644
index 0000000..f91b054
--- /dev/null
+++ b/test/logfile_pretty.0
@@ -0,0 +1,23 @@
+Apr 7 00:49:42 Tim-Stacks-iMac kernel[0]: Ethernet [AppleBCM5701Ethernet]: Link up on en0, 1-Gigabit, Full-duplex, Symmetric flow-control, Debug [796d,2301,0de1,0300,cde1,3800]
+Apr 7 05:49:53 Tim-Stacks-iMac.local GoogleSoftwareUpdateDaemon[17212]: -[KSUpdateCheckAction performAction] KSUpdateCheckAction running KSServerUpdateRequest: <KSOmahaServerUpdateRequest:0x511f30
+ server=<KSOmahaServer:0x510d80>
+ url="https://tools.google.com/service/update2"
+ runningFetchers=0
+ tickets=1
+ activeTickets=1
+ rollCallTickets=1
+ body=
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <o:gupdate xmlns:o="http://www.google.com/update2/request" protocol="2.0" version="KeystoneDaemon-1.2.0.7709" ismachine="1" requestid="{0DFDBCD1-5E29-4DFC-BD99-31A2397198FE}">
+ <o:os platform="mac" version="MacOSX" sp="10.10.2_x86_64h"></o:os>
+ <o:app appid="com.google.Keystone" version="1.2.0.7709" lang="en-us" installage="180" brand="GGLG">
+ <o:ping r="1" a="1"></o:ping>
+ <o:updatecheck></o:updatecheck>
+ </o:app>
+ </o:gupdate>
+ >
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: WARNING: The Gestalt selector gestaltSystemVersion is returning 10.9.2 instead of 10.10.2. Use NSProcessInfo's operatingSystemVersion property to get correct system version number.
+ Call location:
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: 0 CarbonCore 0x00007fff8a9b3d9b ___Gestalt_SystemVersion_block_invoke + 113
+Apr 7 07:31:56 Tim-Stacks-iMac.local VirtualBox[36403]: 1 libdispatch.dylib 0x00007fff8bc84c13 _dispatch_client_callout + 8
+Apr 7 07:32:56 Tim-Stacks-iMac.local logger[234]: Bad data { abc, 123, 456 )}]
diff --git a/test/logfile_procstate.0 b/test/logfile_procstate.0
new file mode 100644
index 0000000..43878aa
--- /dev/null
+++ b/test/logfile_procstate.0
@@ -0,0 +1,43 @@
+========== Start of system state dump at Thu Jun 2 00:01:01 UTC 2022 ==========
+
+/bin/ps auxww
+USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+root 1 0.0 0.0 158392 7792 ? Ss Jun01 0:14 /lib/systemd/systemd --switched-root --system --deserialize 16
+root 2 0.0 0.0 0 0 ? S Jun01 0:00 [kthreadd]
+root 3 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_gp]
+root 4 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_par_gp]
+root 6 0.0 0.0 0 0 ? I< Jun01 0:00 [kworker/0:0H-kblockd]
+========== End of system state dump ==========
+
+
+========== Start of system state dump at Thu Jun 2 00:02:01 UTC 2022 ==========
+
+/bin/ps auxww
+USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+root 1 0.0 0.0 158392 7792 ? Ss Jun01 0:14 /lib/systemd/systemd --switched-root --system --deserialize 16
+root 2 0.0 0.0 0 0 ? S Jun01 0:00 [kthreadd]
+root 3 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_gp]
+root 4 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_par_gp]
+root 6 0.0 0.0 0 0 ? I< Jun01 0:00 [kworker/0:0H-kblockd]
+root 8 0.0 0.0 0 0 ? I< Jun01 0:00 [mm_percpu_wq]
+root 9 0.0 0.0 0 0 ? S Jun01 0:00 [ksoftirqd/0]
+root 10 0.0 0.0 0 0 ? I Jun01 0:23 [rcu_sched]
+root 11 0.0 0.0 0 0 ? I Jun01 0:00 [rcu_bh]
+root 12 0.0 0.0 0 0 ? S Jun01 0:00 [migration/0]
+root 14 0.0 0.0 0 0 ? S Jun01 0:00 [cpuhp/0]
+========== End of system state dump ==========
+
+
+========== Start of system state dump at Thu Jun 2 00:03:01 UTC 2022 ==========
+
+/bin/ps auxww
+USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+root 1 0.0 0.0 158392 7792 ? Ss Jun01 0:14 /lib/systemd/systemd --switched-root --system --deserialize 16
+root 2 0.0 0.0 0 0 ? S Jun01 0:00 [kthreadd]
+root 3 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_gp]
+root 4 0.0 0.0 0 0 ? I< Jun01 0:00 [rcu_par_gp]
+root 6 0.0 0.0 0 0 ? I< Jun01 0:00 [kworker/0:0H-kblockd]
+root 8 0.0 0.0 0 0 ? I< Jun01 0:00 [mm_percpu_wq]
+root 9 0.0 0.0 0 0 ? S Jun01 0:00 [ksoftirqd/0]
+========== End of system state dump ==========
+
diff --git a/test/logfile_rollover.0 b/test/logfile_rollover.0
new file mode 100644
index 0000000..f37fbab
--- /dev/null
+++ b/test/logfile_rollover.0
@@ -0,0 +1,6 @@
+00:00:00.000 foo DEBUG some super duper message
+01:00:00.000 foo DEBUG some super duper message
+02:00:00.000 foo DEBUG some super duper message
+03:00:00.000 foo DEBUG some super duper message
+00:00:00.000 bar DEBUG some super duper message next day (only one hour)
+00:01:00.000 bar DEBUG some super duper message next day (only one hour)
diff --git a/test/logfile_rollover.1 b/test/logfile_rollover.1
new file mode 100644
index 0000000..2a54342
--- /dev/null
+++ b/test/logfile_rollover.1
@@ -0,0 +1,5 @@
+Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Nov 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
+Feb 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
diff --git a/test/logfile_strace_log.0 b/test/logfile_strace_log.0
new file mode 100644
index 0000000..cc74c00
--- /dev/null
+++ b/test/logfile_strace_log.0
@@ -0,0 +1,9 @@
+08:09:33.814936 execve("/bin/ls", ["ls"], [/* 38 vars */]) = 0 <0.000264>
+08:09:33.815688 brk(0) = 0x1513000 <0.000016>
+08:09:33.815801 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9100b05000 <0.000019>
+08:09:33.815943 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000019>
+08:09:33.816083 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9100b03000 <0.000018>
+08:09:33.816206 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000019>
+08:09:33.816326 open("/etc/ld.so.cache", O_RDONLY) = 3 <0.000023>
+08:09:33.816428 fstat(3, {st_mode=S_IFREG|0644, st_size=102143, ...}) = 0 <0.000015>
+08:09:33.816577 mmap(NULL, 102143, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9100aea000 <0.000019>
diff --git a/test/logfile_syslog.0 b/test/logfile_syslog.0
new file mode 100644
index 0000000..312fa69
--- /dev/null
+++ b/test/logfile_syslog.0
@@ -0,0 +1,4 @@
+Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Nov 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/logfile_syslog.1 b/test/logfile_syslog.1
new file mode 100644
index 0000000..0794a4d
--- /dev/null
+++ b/test/logfile_syslog.1
@@ -0,0 +1,4 @@
+Dec 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Dec 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Dec 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Jan 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/logfile_syslog.2 b/test/logfile_syslog.2
new file mode 100644
index 0000000..5f43947
--- /dev/null
+++ b/test/logfile_syslog.2
@@ -0,0 +1,3 @@
+Nov 3 09:23:38 veridian foo[7998]: eth0 is up
+Nov 3 09:23:38 veridian foo[16442]: eth1 is up
+Nov 3 09:23:38 veridian foo[7999]: eth0 is down
diff --git a/test/logfile_syslog.3 b/test/logfile_syslog.3
new file mode 100644
index 0000000..05d1a0b
--- /dev/null
+++ b/test/logfile_syslog.3
@@ -0,0 +1,17 @@
+Aug 16 00:10:45 Tims-Air syslogd[314]: ASL Sender Statistics
+Aug 16 00:28:56 Tims-Air syslogd[314]: ASL Sender Statistics
+Aug 16 00:32:15 Tims-Air syslogd[314]: Configuration Notice:
+ ASL Module "com.apple.cdscheduler" claims selected messages.
+ Those messages may not appear in standard system log files or in the ASL database.
+Aug 16 00:32:15 Tims-Air syslogd[314]: Configuration Notice:
+ ASL Module "com.apple.install" claims selected messages.
+ Those messages may not appear in standard system log files or in the ASL database.
+Aug 16 00:32:15 Tims-Air syslogd[314]: Configuration Notice:
+ ASL Module "com.apple.authd" sharing output destination "/var/log/asl" with ASL Module "com.apple.asl".
+ Output parameters from ASL Module "com.apple.asl" override any specified in ASL Module "com.apple.authd".
+Aug 16 00:32:15 Tims-Air syslogd[314]: Configuration Notice:
+ ASL Module "com.apple.authd" sharing output destination "/var/log/system.log" with ASL Module "com.apple.asl".
+ Output parameters from ASL Module "com.apple.asl" override any specified in ASL Module "com.apple.authd".
+Aug 16 00:32:15 Tims-Air syslogd[314]: Configuration Notice:
+ ASL Module "com.apple.authd" claims selected messages.
+ Those messages may not appear in standard system log files or in the ASL database.
diff --git a/test/logfile_syslog_fr.0 b/test/logfile_syslog_fr.0
new file mode 100644
index 0000000..8b93e0c
--- /dev/null
+++ b/test/logfile_syslog_fr.0
@@ -0,0 +1 @@
+août 19 11:08:37 nlaptop symphorien[4961]: test
diff --git a/test/logfile_syslog_with_access_log.0 b/test/logfile_syslog_with_access_log.0
new file mode 100644
index 0000000..2ec28da
--- /dev/null
+++ b/test/logfile_syslog_with_access_log.0
@@ -0,0 +1,5 @@
+Jan 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
+Mar 24 14:02:50 bigproduct-web1 tomcat.log: 127.0.0.1 - - "GET /includes/js/combined-javascript.js HTTP/1.1" 200 65508 4.386
+Mar 24 14:02:50 bigproduct-web1 tomcat.log: 127.0.0.1 - - "GET /bad.foo HTTP/1.1" 404 65508 4.386
+Mar 24 14:02:51 bigproduct-web1 automount[7999]: lookup(file): lookup for opt failed
+Mar 24 14:26:01 --- last message repeated 2 times ---
diff --git a/test/logfile_syslog_with_header.0 b/test/logfile_syslog_with_header.0
new file mode 100644
index 0000000..8f22c16
--- /dev/null
+++ b/test/logfile_syslog_with_header.0
@@ -0,0 +1,6 @@
+Header1: abc
+Header2: def
+Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Nov 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
diff --git a/test/logfile_syslog_with_mixed_times.0 b/test/logfile_syslog_with_mixed_times.0
new file mode 100644
index 0000000..f2314ae
--- /dev/null
+++ b/test/logfile_syslog_with_mixed_times.0
@@ -0,0 +1,13 @@
+Sep 13 00:58:45 Tim-Stacks-iMac kernel[0]: AirParrot device perform power state change 0 -> 1
+Sep 13 00:59:30 Tim-Stacks-iMac.local airportd[59]: _configureScanOffloadParameters: Unable to configure scan offloading on en1 (Device power is off)
+Sep 13 01:23:54 Tim-Stacks-iMac kernel[0]: RTC: PowerByCalendarDate setting ignored
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: vm_compressor_record_warmup (9478314 - 9492476)
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: AppleBCM5701Ethernet [en0]: 0 0 memWrInd fBJP_Wakeup_Timer
+Sep 13 01:25:39 Tim-Stacks-iMac kernel[0]: AppleThunderboltNHIType2::waitForOk2Go2Sx - retries = 60000
+Sep 13 03:12:04 Tim-Stacks-iMac kernel[0]: hibernate_page_list_setall(preflight 0) start 0xffffff8428276000, 0xffffff8428336000
+Sep 13 03:12:58 Tim-Stacks-iMac kernel[0]: *** kernel exceeded 500 log message per second limit - remaining messages this second discarded ***
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: IOThunderboltSwitch<0xffffff803f4b3000>(0x0)::listenerCallback - Thunderbolt HPD packet for route = 0x0 port = 11 unplug = 0
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: vm_compressor_flush - starting
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: AppleBCM5701Ethernet [en0]: 0 0 memWrInd fBJP_Wakeup_Timer
+Sep 13 03:13:16 Tim-Stacks-iMac kernel[0]: AppleThunderboltNHIType2::waitForOk2Go2Sx - retries = 60000
+Sep 13 03:46:03 Tim-Stacks-iMac kernel[0]: hibernate_page_list_setall(preflight 0) start 0xffffff838f1fc000, 0xffffff838f2bc000
diff --git a/test/logfile_tai64n.0 b/test/logfile_tai64n.0
new file mode 100644
index 0000000..0e195bc
--- /dev/null
+++ b/test/logfile_tai64n.0
@@ -0,0 +1,10 @@
+@40000000433225833b6e1a8c tcpserver: status: 5/30
+@40000000433225833b6e2644 tcpserver: pid 26162 from 194.206.24.40
+@40000000433225840c85ba04 tcpserver: ok 26162 a.mx.jms1.net:209.114.200.128:25 :194.206.24.40::1521
+@40000000433225840c8f0cbc rblsmtpd: 194.206.24.40 pid 26162: 451 We do not accept mail from IP addresses without reverse DNS.
+@40000000433225852a9ada4c tcpserver: status: 6/30
+@40000000433225852a9ae604 tcpserver: pid 26163 from 193.123.2.227
+@40000000433225852aa997bc tcpserver: ok 26163 a.mx.jms1.net:209.114.200.128:25 pixelwww.pixelpower.com:193.123.2.227::4232
+@40000000433225852aa9a374 rblsmtpd: 193.123.2.227 pid 26163: 553 Sent mail to honeypot qmmycemglyiuq@delete.net on 2005-01-04
+@400000004332258538eae27c tcpserver: end 26163 status 0
+@400000004332258538eaea4c tcpserver: status: 5/30
diff --git a/test/logfile_tcf.0 b/test/logfile_tcf.0
new file mode 100644
index 0000000..b6034b4
--- /dev/null
+++ b/test/logfile_tcf.0
@@ -0,0 +1,30 @@
+TCF 29:47.191: Server-Properties: {"Name":"TCF Protocol Logger","OSName":"Linux 3.2.0-60-generic","UserName":"xavier","AgentID":"1fde3dd1-d4be-4f79-8090-6f8d212f03bf","TransportName":"TCP","Proxy":"","ValueAdd":"1","Port":"1534"}
+TCF 30:04.735: channel server connecting
+TCF 30:04.735: channel server connected
+TCF 30:11.474: 0: ---> C 2 RunControl getChildren null <eom>
+TCF 30:11.475: 0: <--- R 2 ["P1"] <eom>
+TCF 30:11.475: 0: ---> C 3 RunControl getContext "P1" <eom>
+TCF 30:11.475: 0: <--- R 3 {"ID":"P1","ProcessID":"P1","Name":"VxWorks","CanSuspend":true,"CanResume":1,"IsContainer":true,"WordSize":4,"CanTerminate":true,"CanDetach":true,"RCGroup":"P1","SymbolsGroup":"P1","CPUGroup":"P1","DiagnosticTestProcess":true} <eom>
+TCF 30:11.475: 0: ---> C 4 RunControl getChildren "P1" <eom>
+TCF 30:11.475: 0: <--- R 4 ["P2"] <eom>
+TCF 30:11.475: 0: ---> C 5 RunControl getContext "P2" <eom>
+TCF 30:11.476: 0: <--- R 5 {"ID":"P2","ParentID":"P1","ProcessID":"P2","Name":"Kernel","CanSuspend":true,"CanResume":1,"IsContainer":true,"WordSize":4,"CanTerminate":true,"CanDetach":true,"RCGroup":"P2","BPGroup":"P2","SymbolsGroup":"P2","CPUGroup":"P2","DiagnosticTestProcess":true} <eom>
+TCF 30:11.476: 0: ---> C 6 RunControl getChildren "P2" <eom>
+TCF 30:11.476: 0: <--- R 6 [] <eom>
+TCF 30:11.523: 0: ---> C RR4 RunControl getChildren null <eom>
+TCF 30:11.524: 0: <--- R RR4 ["P1"] <eom>
+TCF 30:11.525: 0: ---> C RR6 RunControl getContext "P1" <eom>
+TCF 30:11.526: 0: <--- R RR6 {"ID":"P1","ProcessID":"P1","Name":"VxWorks","CanSuspend":true,"CanResume":1,"IsContainer":true,"WordSize":4,"CanTerminate":true,"CanDetach":true,"RCGroup":"P1","SymbolsGroup":"P1","CPUGroup":"P1","DiagnosticTestProcess":true} <eom>
+TCF 30:11.530: 0: ---> C RR7 RunControl getChildren "P1" <eom>
+TCF 30:11.530: 0: <--- R RR7 ["P2"] <eom>
+TCF 30:11.531: 0: ---> C RR8 RunControl getContext "P2" <eom>
+TCF 30:11.531: 0: <--- R RR8 {"ID":"P2","ParentID":"P1","ProcessID":"P2","Name":"Kernel","CanSuspend":true,"CanResume":1,"IsContainer":true,"WordSize":4,"CanTerminate":true,"CanDetach":true,"RCGroup":"P2","BPGroup":"P2","SymbolsGroup":"P2","CPUGroup":"P2","DiagnosticTestProcess":true} <eom>
+TCF 30:11.533: 0: ---> C RR9 RunControl getChildren "P2" <eom>
+TCF 30:11.533: 0: <--- R RR9 [] <eom>
+TCF 30:11.536: 0: ---> C RR10 Locator getAgentID <eom>
+TCF 30:11.536: 0: <--- R RR10 "00000000-0000-4daa-8665-a704d3dc0000" <eom>
+TCF 30:21.573: 0: ---> C RR11 ProcessesV1 getChildren null false <eom>
+TCF 30:21.573: 0: <--- R RR11 ["P1"] <eom>
+TCF 30:21.577: 0: ---> C RR12 ProcessesV1 getContext "P1" <eom>
+TCF 30:21.577: 0: <--- R RR12 {"Name":"VxWorks","CanTerminate":false,"CanAttach":true,"IsProcess":false,"ID":"P1"} <eom>
+TCF 30:21.756: 0: <--- E RunControl contextAdded [{"ID":"P2.1623333904","ParentID":"P2","ProcessID":"P2","Name":"ipcom_syslogd","CanSuspend":true,"CanResume":12351,"HasState":true,"WordSize":4,"CanTerminate":true,"CanDetach":true,"RCGroup":"P2.1623333904","BPGroup":"P2","SymbolsGroup":"P2","CPUGroup":"P2","DiagnosticTestProcess":true}] <eom>
diff --git a/test/logfile_tcf.1 b/test/logfile_tcf.1
new file mode 100644
index 0000000..c7c2699
--- /dev/null
+++ b/test/logfile_tcf.1
@@ -0,0 +1,3 @@
+TCF 59:47.191: Server-Properties: {"Name":"TCF Protocol Logger","OSName":"Linux 3.2.0-60-generic","UserName":"xavier","AgentID":"1fde3dd1-d4be-4f79-8090-6f8d212f03bf","TransportName":"TCP","Proxy":"","ValueAdd":"1","Port":"1534"}
+TCF 30:11.474: 0: ---> C 2 RunControl getChildren null <eom>
+TCF 01:11.475: 0: <--- R 2 ["P1"] <eom>
diff --git a/test/logfile_tcsh_history.0 b/test/logfile_tcsh_history.0
new file mode 100644
index 0000000..465d851
--- /dev/null
+++ b/test/logfile_tcsh_history.0
@@ -0,0 +1,4 @@
+#+1162490366
+./drive_vt52_curses
+#+1162490385
+exit
diff --git a/test/logfile_uwsgi.0 b/test/logfile_uwsgi.0
new file mode 100644
index 0000000..df31323
--- /dev/null
+++ b/test/logfile_uwsgi.0
@@ -0,0 +1,19 @@
+[pid: 88185|app: 0|req: 1/1] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:49:12 2016] POST /update_metrics => generated 47 bytes in 129 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 3)
+[pid: 88185|app: 0|req: 3/2] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:49:15 2016] POST /update_metrics => generated 47 bytes in 35 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 30)
+[pid: 88185|app: 0|req: 3/3] 127.0.0.1 () {34 vars in 617 bytes} [Sun Mar 13 22:49:15 2016] POST /endpoint2 => generated 215 bytes in 68 micros (HTTP/1.1 200) 9 headers in 373 bytes (1 switches on core 8)
+[pid: 88185|app: 0|req: 4/4] 127.0.0.1 () {34 vars in 617 bytes} [Sun Mar 13 22:49:15 2016] POST /endpoint2 => generated 215 bytes in 16 msecs (HTTP/1.1 200) 9 headers in 373 bytes (1 switches on core 22)
+[pid: 88185|app: 0|req: 5/5] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:50:12 2016] POST /update_metrics => generated 47 bytes in 10 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 0)
+[pid: 88186|app: 0|req: 1/6] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:50:15 2016] POST /update_metrics => generated 47 bytes in 65 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 16)
+[pid: 88186|app: 0|req: 2/7] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:51:12 2016] POST /update_metrics => generated 47 bytes in 11 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 30)
+[pid: 88188|app: 0|req: 1/8] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:51:15 2016] POST /update_metrics => generated 47 bytes in 66 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 31)
+[pid: 88186|app: 0|req: 3/9] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:52:12 2016] POST /update_metrics => generated 47 bytes in 11 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 81)
+[pid: 88188|app: 0|req: 2/10] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:52:15 2016] POST /update_metrics => generated 47 bytes in 18 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 38)
+[pid: 88187|app: 0|req: 1/11] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:53:12 2016] POST /update_metrics => generated 47 bytes in 107 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 7)
+[pid: 88187|app: 0|req: 2/12] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:53:15 2016] POST /update_metrics => generated 47 bytes in 17 msecs (HTTP/1.1 200) 9 headers in 378 bytes (2 switches on core 8)
+[pid: 88187|app: 0|req: 3/13] 127.0.0.1 () {38 vars in 695 bytes} [Sun Mar 13 22:54:12 2016] POST /update_metrics => generated 47 bytes in 16 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 9)
+[pid: 88188|app: 0|req: 3/14] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:54:15 2016] POST /update_metrics => generated 47 bytes in 52 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 1)
+[pid: 88186|app: 0|req: 4/15] 127.0.0.1 () {34 vars in 617 bytes} [Sun Mar 13 22:54:15 2016] POST /endpoint2 => generated 215 bytes in 35 msecs (HTTP/1.1 200) 9 headers in 373 bytes (1 switches on core 43)
+[pid: 88187|app: 0|req: 4/16] 127.0.0.1 () {38 vars in 695 bytes} [Sun Mar 13 22:55:12 2016] POST /update_metrics => generated 47 bytes in 11 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 14)
+[pid: 88188|app: 0|req: 4/17] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:55:15 2016] POST /update_metrics => generated 47 bytes in 14 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 57)
+[pid: 88187|app: 0|req: 5/18] 127.0.0.1 () {38 vars in 695 bytes} [Sun Mar 13 22:56:12 2016] POST /update_metrics => generated 47 bytes in 11 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 35)
+[pid: 88186|app: 0|req: 5/19] 127.0.0.1 () {38 vars in 696 bytes} [Sun Mar 13 22:56:15 2016] POST /update_metrics => generated 47 bytes in 40 msecs (HTTP/1.1 200) 9 headers in 378 bytes (1 switches on core 60)
diff --git a/test/logfile_vami.0 b/test/logfile_vami.0
new file mode 100644
index 0000000..23b7b31
--- /dev/null
+++ b/test/logfile_vami.0
@@ -0,0 +1,4 @@
+2015-03-12T23:16:52.071:INFO:com.root:Response :
+ <?xml version="1.0"?>
+<response><locale>en-US</locale><requestid>ipInfo</requestid><value id="ipv4Gateway" actions="enabled">198.51.100.253</value><value id="ipv6Gateway" actions="enabled"/><value id="ipv6Enabled" actions="enabled">true</value><value id="ipv4Enabled" actions="enabled">true</value><value id="name" actions="enabled">nic1</value><value id="v4config" actions="enabled"><value id="defaultGateway" actions="enabled">0.0.0.0</value><value id="updateable" actions="enabled">True</value><value id="prefix" actions="enabled">22</value><value id="mode" actions="enabled">dhcp</value><value id="address" actions="enabled">198.51.100.110</value><value id="interface" actions="enabled">nic1</value></value><value id="v6config" actions="enabled"><value id="defaultGateway" actions="enabled">fe80::214:f609:19f7:6bf1</value><value id="updateable" actions="enabled">True</value><value id="interface" actions="enabled">nic1</value><value id="dhcp" actions="enabled">False</value><value id="autoconf" actions="enabled">False</value><value id="addresses" actions="enabled"><value id="origin" actions="enabled">other</value><value id="status" actions="enabled">preferred</value><value id="prefix" actions="enabled">64</value><value id="address" actions="enabled">fe80::250:56ff:feaa:5abf</value></value></value><value id="interfaceInfo" actions="enabled"><value id="status" actions="enabled">up</value><value id="mac" actions="enabled">00:50:56:aa:5a:bf</value><value id="name" actions="enabled">nic1</value></value></response>
+
diff --git a/test/logfile_vdsm.0 b/test/logfile_vdsm.0
new file mode 100644
index 0000000..e36910e
--- /dev/null
+++ b/test/logfile_vdsm.0
@@ -0,0 +1,16 @@
+MainThread::INFO::2011-12-05 07:04:56,101::vdsm::71::vds::(run) I am the actual vdsm 4.9-0
+MainThread::ERROR::2011-12-05 07:04:56,300::vdsm::74::vds::(run) Traceback (most recent call last):
+File "/usr/share/vdsm/vdsm", line 72, in run
+ serve_clients(log)
+File "/usr/share/vdsm/vdsm", line 40, in serve_clients
+ cif = clientIF.clientIF(log)
+File "/usr/share/vdsm/clientIF.py", line 111, in init
+ self._libvirt = libvirtconnection.get()
+File "/usr/share/vdsm/libvirtconnection.py", line 111, in get
+ conn = libvirt.openAuth('qemu:///system', auth, 0)
+File "/usr/lib64/python2.6/site-packages/libvirt.py", line 102, in openAuth
+ if ret is None:raise libvirtError('virConnectOpenAuth() failed')
+libvirtError: Failed to connect socket to '/var/run/libvirt/libvirt-sock': No such file or directory
+Thread-15::DEBUG::2011-12-07 11:44:17,737::clientIF::54::vds::(wrapper) [10.35.17.240]::call getVdsCapabilities with () {}
+Thread-16::DEBUG::2011-06-23 19:03:11,607::clientIF::225::Storage.Dispatcher.Protect::(wrapper) [10.35.16.71]
+Thread-1950::INFO::2011-12-07 12:14:15,018::dispatcher::94::Storage.Dispatcher.Protect::(run) Run and protect: getDeviceList, args: ( storageType=2)
diff --git a/test/logfile_vmw_log.0 b/test/logfile_vmw_log.0
new file mode 100644
index 0000000..99e1c91
--- /dev/null
+++ b/test/logfile_vmw_log.0
@@ -0,0 +1,4 @@
+2022-06-02T11:58:12.193Z info vpxd[45715] [Originator@6876 sub=vpxLro opID=7e1280cf] [VpxLRO] -- BEGIN lro-846063 -- SessionManager -- vim.SessionManager.sessionIsActive -- 528e6e0c-246d-58b5-3234-278c6e0c5d0d(52c289ac-2563-48d5-8a8e-f178da022c0d)
+2022-06-02T11:58:12.194Z info vpxd[45715] [Originator@6876 sub=vpxLro opID=7e1280cf] [VpxLRO] -- FINISH lro-846063
+2022-06-02T11:59:41.498Z warning vpxd[47756] [Originator@6876 sub=drmLogger opID=SWI-66b629ff] Exception was thrown when call vsan-performance-manager for cluster [vim.ClusterComputeResource:domain-c109,Cluster-52] perf metrics: N3Vim5Fault8NotFound9ExceptionE(Fault cause: vim.fault.NotFound
+--> )
diff --git a/test/logfile_vpxd.0 b/test/logfile_vpxd.0
new file mode 100644
index 0000000..224ca7b
--- /dev/null
+++ b/test/logfile_vpxd.0
@@ -0,0 +1,12 @@
+2022-06-02T11:58:12.193Z info vpxd[45715] [Originator@6876 sub=vpxLro opID=7e1280cf] [VpxLRO] -- BEGIN lro-846063 -- SessionManager -- vim.SessionManager.sessionIsActive -- 528e6e0c-246d-58b5-3234-278c6e0c5d0d(52c289ac-2563-48d5-8a8e-f178da022c0d)
+2022-06-02T11:58:12.194Z info vpxd[45715] [Originator@6876 sub=vpxLro opID=7e1280cf] [VpxLRO] -- FINISH lro-846063
+2022-06-02T11:58:12.376Z info vpxd[45709] [Originator@6876 sub=vpxLro opID=e3979f6] [VpxLRO] -- BEGIN lro-846064 -- SessionManager -- vim.SessionManager.sessionIsActive -- 52626140-422b-6287-b4e4-344192c6a01d(523e0a4b-6e83-6bcd-9342-22502dd89866)
+2022-06-02T11:58:12.377Z info vpxd[45709] [Originator@6876 sub=vpxLro opID=e3979f6] [VpxLRO] -- FINISH lro-846064
+2022-06-02T11:58:12.623Z info vpxd[47524] [Originator@6876 sub=vpxLro opID=l3wrhr4o-cbf-h5:70001034-60] [VpxLRO] -- BEGIN lro-846066 -- ChangeLogCollector -- vim.cdc.ChangeLogCollector.waitForChanges -- 526861fc-0c28-1930-ae5e-d8c2772bf8c2(52a7a308-9646-c054-f1e7-16131c1a7db6)
+2022-06-02T11:58:12.623Z info vpxd[47524] [Originator@6876 sub=vpxLro opID=l3wrhr4o-cbf-h5:70001034-60] [VpxLRO] -- FINISH lro-846066
+2022-06-02T11:58:12.736Z info vpxd[48432] [Originator@6876 sub=vpxLro opID=499b440] [VpxLRO] -- BEGIN lro-846067 -- SessionManager -- vim.SessionManager.sessionIsActive -- 521fe9f6-d061-11a2-ac86-badb3c071373(524cba9b-2cc4-9b70-32e4-421452a404d7)
+2022-06-02T11:58:12.736Z info vpxd[48432] [Originator@6876 sub=vpxLro opID=499b440] [VpxLRO] -- FINISH lro-846067
+2022-06-02T11:58:12.740Z info vpxd[48035] [Originator@6876 sub=vpxLro opID=55a419df] [VpxLRO] -- BEGIN lro-846068 -- SessionManager -- vim.SessionManager.sessionIsActive -- 52585600-b0bc-76b1-c4d5-4d7708671c5e(523b68ba-e312-9909-a3ca-39cc86aaf206)
+2022-06-02T11:58:12.740Z info vpxd[48035] [Originator@6876 sub=vpxLro opID=55a419df] [VpxLRO] -- FINISH lro-846068
+2022-06-02T11:58:12.796Z info vpxd[47240] [Originator@6876 sub=MoCluster opID=HB-host-363@2022-389ab9b1] Host [vim.HostSystem:host-363,esx-2-121.vlcm.com] has 1 HDCS resources
+2022-06-02T11:58:12.914Z info vpxd[47370] [Originator@6876 sub=MoCluster opID=HB-host-493@2000-2922fd96] Host [vim.HostSystem:host-493,esx-2-192.vlcm.com] has 1 HDCS resources
diff --git a/test/logfile_w3c.0 b/test/logfile_w3c.0
new file mode 100644
index 0000000..c6177e7
--- /dev/null
+++ b/test/logfile_w3c.0
@@ -0,0 +1,5 @@
+#Software: Microsoft HTTP Server API 2.0
+#Version: 1.0 // the log file version as it's described by "https://www.w3.org/TR/WD-logfile".
+#Date: 2002-05-02 17:42:15 // when the first log file entry was recorded, which is when the entire log file was created.
+#Fields: date time c-ip cs-username s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status cs(User-Agent)
+2002-05-02 17:42:15 172.22.255.255 - 172.30.255.255 80 GET /images/picture.jpg - 200 Mozilla/4.0+(compatible;MSIE+5.5;+Windows+2000+Server)
diff --git a/test/logfile_w3c.1 b/test/logfile_w3c.1
new file mode 100644
index 0000000..7e8a4f1
--- /dev/null
+++ b/test/logfile_w3c.1
@@ -0,0 +1,7 @@
+#Version: 1.0
+#GMT-Offset: -0800
+#Software: Oracle9iAS Web Cache/2.0.0.2.0
+#Start-Date: 2001-10-31 00:00:18
+#Fields: c-ip c-dns c-auth-id date time cs-method cs-uri sc-status bytes cs(Cookie) cs(Referrer) time-taken cs(User-Agent)
+#Date: 2001-10-31 00:00:18
+64.103.37.2 client_joaz7 DMS.user 2001-10-31 00:00:18 GET /admin/images/oc_bottomleft.gif 200 350 "BIGipServerwww_webcache_pool=1443321748.19460.0000;ORA_UCM_AGID=%2fMP%2f8M7%3etSHPV%40%2fS%3f%3fDh3VHO" "http://www.oracle.com/nl/partner/content.html" 370879 "Mozilla/4.5 [en] (WinNT; I)"
diff --git a/test/logfile_w3c.2 b/test/logfile_w3c.2
new file mode 100644
index 0000000..c15f08b
--- /dev/null
+++ b/test/logfile_w3c.2
@@ -0,0 +1,22 @@
+#Software: Microsoft Internet Information Server 4.0
+#Version: 1.0
+#Date: 2000-10-09 16:44:49
+#Fields: time c-ip cs-method cs-uri-stem sc-status
+16:44:49 1.1.1.1 [2]USER anonymous 331
+16:44:49 1.1.1.1 [2]PASS - 230
+16:48:05 1.1.1.1 [2]QUIT - 226
+16:48:17 1.1.1.1 [3]USER anonymous 331
+16:48:24 1.1.1.1 [3]PASS user@domain.com 230
+16:48:35 1.1.1.1 [3]sent /user/test.c 226
+16:48:41 1.1.1.1 [3]created readme.txt 226
+16:48:41 1.1.1.1 [3]created fileid.diz 226
+16:48:41 1.1.1.1 [3]created names.dll 226
+16:48:41 1.1.1.1 [3]created TEST.EXE 226
+16:48:44 1.1.1.1 [3]QUIT - 226
+#Software: Microsoft Internet Information Server 4.0
+#Version: 1.0
+#Date: 2000-10-10 16:44:49
+#Fields: time c-ip cs-method cs-uri-stem sc-status
+16:44:49 1.1.1.1 [2]USER anonymous 331
+16:44:49 1.1.1.1 [2]PASS - 230
+16:48:05 1.1.1.1 [2]QUIT - 226
diff --git a/test/logfile_w3c.3 b/test/logfile_w3c.3
new file mode 100644
index 0000000..2f3d190
--- /dev/null
+++ b/test/logfile_w3c.3
@@ -0,0 +1,10 @@
+#Software: IIS Advanced Logging Module
+
+#Version: 1.0
+
+#Start-Date: 2014-11-18 00:00:00.128
+
+#Fields: date-local time-local s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) cs(Host) sc-status sc-substatus sc-win32-status TimeTakenMS
+2012-08-15 17:00:00.363 1.2.3.4 GET /Products/theProduct - 80 - "70.95.0.0" "Mozilla/5.0 (Linux; Android 4.4.4; SM-G900V Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36" "http://example.com/Search/SearchResults.pg?informationRecipient.languageCode.c=en" "xzy.example.com" 200 0 0 109
+2012-08-15 17:00:00.660 10.10.28.140 GET /Topic/hw43061 - 80 - - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36" - "example.hello.com" 301 0 0 0
+2012-08-15 17:00:00.675 10.10.28.140 GET /hello/world/6,681965 - 80 - "173.5.0.0" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36" - "hello.example.com" 404 " ""garbage"" w/ spaces " 0 359
diff --git a/test/logfile_w3c.4 b/test/logfile_w3c.4
new file mode 100644
index 0000000..76d978b
--- /dev/null
+++ b/test/logfile_w3c.4
@@ -0,0 +1,6 @@
+#Software: Incapsula LOGS API
+#Version: 1.1
+#Date: 28/Jun/2017 07:28:59
+#Fields: date time cs-vid cs-clapp cs-browsertype cs-js-support cs-co-support c-ip s-caip cs-clappsig s-capsupport s-suid cs(User-Agent) cs-sessionid s-siteid cs-countrycode s-tag cs-cicode s-computername cs-lat cs-long s-accountname cs-uri cs-postbody cs-version sc-action s-externalid cs(Referrer) s-ip s-port cs-method cs-uri-query sc-status s-xff cs-bytes cs-start cs-rule cs-severity cs-attacktype cs-attackid s-ruleName
+"2017-06-28" "07:26:35" "a1f36498-c34a-45b9-b3a5-ee0bd00f91b6" "Chrome" "Browser" "false" "true" "123.123.123.123" "" "62a660e57ba257275cf7ccf699919eae18e07e84cb11c1075e99b1be98456059d3064ec14d3932ba6e89f5393a158b8b8c2572ad7ad7dadb0fe02a34ae4c3d504c035017bf9a6a7802bb898226378938" "NA" "774502" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" "452000660051880893" "44850949" "SE" "LS" "Stockholm" "www.example.com" "32.0000" "32.0000" "Customer" "www.example.com/page.php" "" "HTTP" "REQ_PASSED" "118866685985031205" "" "124.124.124.124" "80" "GET" "variable=test" "200" "123.123.123.123" "10117" "1498634795555" "" "" "" "" ""
+"2017-06-26" "18:21:17" "daf5e234-24fc-4a69-985c-ab923529b393" "Firefox" "Browser" "false" "true" "125.125.125.125" "" "030404c9ac184e57a6c956e6bfad11dc23186ea6cf166908c6bc7db81aab7170e33740ea4d2972210f96e3365d25eb25a222f316a4f9221f39e56035fa9a49c80f9eedd9b846bb0491abe72a4b988e7cd3e7117283cee9f556726334972b7ce9" "NA" "774502" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 Lightning/4.7.8" "000000830000750000" "85437078" "SE" "XX" "Town" "www.example.com" "66.3333" "66.3333" "Company" "www.example.com/rss/news" "" "HTTP" "REQ_BAD_SERVER_CLOSED_CONNECTION" "3004162128217401" "" "125.125.125.125" "80" "GET" "" "" "125.125.125.125" "" "1498501277430" "" "" "" "" ""
diff --git a/test/logfile_w3c.5 b/test/logfile_w3c.5
new file mode 100644
index 0000000..b05bc48
--- /dev/null
+++ b/test/logfile_w3c.5
@@ -0,0 +1,2 @@
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 283
diff --git a/test/logfile_w3c.6 b/test/logfile_w3c.6
new file mode 100644
index 0000000..0a8f3e2
--- /dev/null
+++ b/test/logfile_w3c.6
@@ -0,0 +1,5 @@
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 00:32:17
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 ÄÖÜäöü\ßßßMözillä/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 283
diff --git a/test/logfile_w3c_big.0 b/test/logfile_w3c_big.0
new file mode 100644
index 0000000..866b8bc
--- /dev/null
+++ b/test/logfile_w3c_big.0
@@ -0,0 +1,254 @@
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 00:32:17
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 283
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 157
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 152
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 149
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 137
+2015-01-13 00:32:26 100.79.192.81 GET /p/eToken1.png - 80 - 207.46.13.64 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 245 157
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 02:05:40
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 02:05:40 100.79.192.81 GET /48672181611.html - 80 - 180.111.242.129 Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+5.1;+Trident/4.0) - 404 0 2 1405 141 2411
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 08:22:18
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 08:22:18 100.79.192.81 GET /robots.txt - 80 - 66.249.78.6 Mozilla/5.0+(compatible;+Googlebot/2.1;++http://www.google.com/bot.html) - 404 0 2 1405 250 156
+2015-01-13 08:22:18 100.79.192.81 GET /contact/ - 80 - 66.249.64.36 Mozilla/5.0+AppleWebKit/537.36+(KHTML,+like+Gecko;+Google+Web+Preview+Analytics)+Chrome/27.0.1453+Safari/537.36+(compatible;+Googlebot/2.1;++http://www.google.com/bot.html) - 404 0 2 1405 331 376
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 09:49:46
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 09:49:46 100.79.192.81 GET / - 80 - 188.120.253.124 Mozilla/5.0+(Windows;+U;+Windows+NT+5.1;+en-US)+AppleWebKit/533.4+(KHTML,+like+Gecko)+Chrome/5.0.375.99+Safari/533.4 http://example.com 200 0 0 960 205 468
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 10:16:10
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 10:16:10 100.79.192.81 GET /robots.txt - 80 - 37.59.20.217 Mozilla/5.0+(compatible;+MJ12bot/v1.4.5;+http://www.majestic12.co.uk/bot.php?+) - 404 0 2 1424 170 156
+2015-01-13 10:16:15 100.79.192.81 GET / - 80 - 37.59.20.217 Mozilla/5.0+(compatible;+MJ12bot/v1.4.5;+http://www.majestic12.co.uk/bot.php?+) - 200 0 0 979 313 265
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 10:46:33
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 10:46:33 100.79.192.81 GET / - 80 - 188.163.80.167 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.1;+WOW64;+Trident/7.0;+SLCC2;+.NET+CLR+2.0.50727;+.NET+CLR+3.5.30729;+.NET+CLR+3.0.30729;+Media+Center+PC+6.0;+.NET4.0C;+.NET4.0E) - 200 0 0 960 327 499
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 12:30:24
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 12:30:24 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 261 283
+2015-01-13 12:30:30 100.79.192.81 GET / - 80 - 157.55.39.146 Mozilla/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 200 0 0 960 264 418
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 13:00:56
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 13:00:56 100.79.192.81 GET / - 80 - 192.99.149.88 Mozilla/5.0+(Windows+NT+6.1;+WOW64;+Trident/7.0;+rv:11.0)+like+Gecko - 200 0 64 0 212 504
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 16:35:13
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 16:35:13 100.79.192.81 GET / - 80 - 130.211.190.46 NerdyBot - 200 0 0 984 94 503
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 22:29:42
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 22:29:42 100.79.192.81 GET / - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 200 0 0 960 238 807
+2015-01-13 22:29:42 100.79.192.81 GET /fckeditor/fckconfig.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 260 376
+2015-01-13 22:29:42 100.79.192.81 GET /fckeditor/license.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 259 392
+2015-01-13 22:29:43 100.79.192.81 GET /fckeditor/editor/js/fckeditorcode_ie.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 277 399
+2015-01-13 22:29:43 100.79.192.81 GET /fckeditor/fckeditor.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 260 392
+2015-01-13 22:29:43 100.79.192.81 GET /FCK/editor/js/fckeditorcode_ie.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 271 393
+2015-01-13 22:29:44 100.79.192.81 GET /FCK/fckeditor.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 254 392
+2015-01-13 22:29:44 100.79.192.81 GET /fckeditor.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 250 377
+2015-01-13 22:29:44 100.79.192.81 GET /editor/js/fckeditorcode_ie.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 267 361
+2015-01-13 22:29:45 100.79.192.81 GET /fckeditor/editor/js/fckeditorcode_ie.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 277 352
+2015-01-13 22:29:45 100.79.192.81 GET /ckeditor/ckeditor.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 258 355
+2015-01-13 22:29:45 100.79.192.81 GET / c=4e5e5d7364f443e28fbf0d3ae744a59a 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 200 0 0 960 273 361
+2015-01-13 22:29:46 100.79.192.81 GET /wp-cron.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 345
+2015-01-13 22:29:46 100.79.192.81 GET /wp-content - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 354
+2015-01-13 22:29:46 100.79.192.81 GET /wp-login.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 250 338
+2015-01-13 22:29:47 100.79.192.81 GET /license.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 345
+2015-01-13 22:29:47 100.79.192.81 GET /readme.html - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 346
+2015-01-13 22:29:47 100.79.192.81 GET /robots.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 345
+2015-01-13 22:29:48 100.79.192.81 GET /favicon.ico - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 330
+2015-01-13 22:29:48 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 335
+2015-01-13 22:29:48 100.79.192.81 GET /weblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 325
+2015-01-13 22:29:48 100.79.192.81 GET /wordpress/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 330
+2015-01-13 22:29:50 100.79.192.81 GET /wp/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 241 345
+2015-01-13 22:29:50 100.79.192.81 GET /log/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 330
+2015-01-13 22:29:50 100.79.192.81 GET /archiver - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 345
+2015-01-13 22:29:51 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 330
+2015-01-13 22:29:51 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 329
+2015-01-13 22:29:51 100.79.192.81 GET /discuz/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 346
+2015-01-13 22:29:52 100.79.192.81 GET /docs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 330
+2015-01-13 22:29:52 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 345
+2015-01-13 22:29:52 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 346
+2015-01-13 22:29:53 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 345
+2015-01-13 22:29:53 100.79.192.81 GET /cart/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 345
+2015-01-13 22:29:53 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 346
+2015-01-13 22:29:54 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 345
+2015-01-13 22:29:54 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 361
+2015-01-13 22:29:54 100.79.192.81 GET /shopex/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 344
+2015-01-13 22:29:55 100.79.192.81 GET /administrator/manifests/files/joomla.xml - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 278 363
+2015-01-13 22:29:55 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 361
+2015-01-13 22:29:55 100.79.192.81 GET /joomla/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 361
+2015-01-13 22:29:56 100.79.192.81 GET /public/js/ips.board.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 260 361
+2015-01-13 22:29:56 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 385
+2015-01-13 22:29:56 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 369
+2015-01-13 22:29:57 100.79.192.81 GET /ipboard/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 377
+2015-01-13 22:29:57 100.79.192.81 GET /board/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 377
+2015-01-13 22:29:57 100.79.192.81 GET /data/admin/ver.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 256 393
+2015-01-13 22:29:58 100.79.192.81 GET /digg.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 377
+2015-01-13 22:29:58 100.79.192.81 GET /plus/sitemap.html - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 255 361
+2015-01-13 22:29:58 100.79.192.81 GET /plus/rssmap.html - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 254 377
+2015-01-13 22:29:59 100.79.192.81 GET /plus/heightsearch.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 259 377
+2015-01-13 22:29:59 100.79.192.81 GET /data - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 377
+2015-01-13 22:29:59 100.79.192.81 GET /member/space/company/info.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 267 376
+2015-01-13 22:30:00 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 378
+2015-01-13 22:30:00 100.79.192.81 GET /dedecms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 393
+2015-01-13 22:30:00 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 393
+2015-01-13 22:30:02 100.79.192.81 GET /empirecms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 393
+2015-01-13 22:30:02 100.79.192.81 GET /CHANGELOG.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 251 377
+2015-01-13 22:30:02 100.79.192.81 GET /changelog.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 251 393
+2015-01-13 22:30:03 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 377
+2015-01-13 22:30:03 100.79.192.81 GET /drupal/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 393
+2015-01-13 22:30:03 100.79.192.81 GET /admin - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 378
+2015-01-13 22:30:04 100.79.192.81 GET /list.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 376
+2015-01-13 22:30:04 100.79.192.81 GET /admin/template/article_more/config.htm - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 276 377
+2015-01-13 22:30:04 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 377
+2015-01-13 22:30:05 100.79.192.81 GET /docs.css - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 393
+2015-01-13 22:30:05 100.79.192.81 GET /phpmyadmin/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 408
+2015-01-13 22:30:05 100.79.192.81 GET /rss.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 393
+2015-01-13 22:30:06 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 410
+2015-01-13 22:30:06 100.79.192.81 GET /inc/rsd.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 391
+2015-01-13 22:30:06 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 409
+2015-01-13 22:30:08 100.79.192.81 GET /weblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 408
+2015-01-13 22:30:08 100.79.192.81 GET /log/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 408
+2015-01-13 22:30:08 100.79.192.81 GET /robots.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 424
+2015-01-13 22:30:09 100.79.192.81 GET /tools/rss.aspx - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 0 2127 252 472
+2015-01-13 22:30:09 100.79.192.81 GET /help.aspx - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 0 2122 247 408
+2015-01-13 22:30:09 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 424
+2015-01-13 22:30:10 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 408
+2015-01-13 22:30:10 100.79.192.81 GET /discuz/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 422
+2015-01-13 22:30:10 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 395
+2015-01-13 22:30:11 100.79.192.81 GET /foosun/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 393
+2015-01-13 22:30:11 100.79.192.81 GET /index.php m=search 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 256 345
+2015-01-13 22:30:11 100.79.192.81 GET /index.php m=wap 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 253 315
+2015-01-13 22:30:11 100.79.192.81 GET /index.php m=admin 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 255 314
+2015-01-13 22:30:13 100.79.192.81 GET /index.php m=admin&c=index&a=login&pc_hash= 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 280 314
+2015-01-13 22:30:13 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 313
+2015-01-13 22:30:13 100.79.192.81 GET /phpcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 315
+2015-01-13 22:30:13 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:14 100.79.192.81 GET /aspcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 313
+2015-01-13 22:30:14 100.79.192.81 GET /admin/inc/xml.xslt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 256 315
+2015-01-13 22:30:14 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:14 100.79.192.81 GET /feed.asp - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 314
+2015-01-13 22:30:15 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 314
+2015-01-13 22:30:15 100.79.192.81 GET /weblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 315
+2015-01-13 22:30:15 100.79.192.81 GET /log/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:15 100.79.192.81 GET /zblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 314
+2015-01-13 22:30:16 100.79.192.81 GET /mail/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 315
+2015-01-13 22:30:16 100.79.192.81 GET /webmail/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 314
+2015-01-13 22:30:16 100.79.192.81 GET /archive/archive.css - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 257 314
+2015-01-13 22:30:16 100.79.192.81 GET /clientscript/vbulletin_ajax_htmlloader.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 279 314
+2015-01-13 22:30:18 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 330
+2015-01-13 22:30:18 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 361
+2015-01-13 22:30:18 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 392
+2015-01-13 22:30:19 100.79.192.81 GET /phpbb/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 424
+2015-01-13 22:30:19 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 420
+2015-01-13 22:30:19 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 398
+2015-01-13 22:30:20 100.79.192.81 GET /leadbbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 408
+2015-01-13 22:30:20 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 408
+2015-01-13 22:30:20 100.79.192.81 GET /cmseasy/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 392
+2015-01-13 22:30:21 100.79.192.81 GET /history.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 408
+2015-01-13 22:30:21 100.79.192.81 GET /common/common.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 254 378
+2015-01-13 22:30:21 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 361
+2015-01-13 22:30:22 100.79.192.81 GET /weblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 381
+2015-01-13 22:30:22 100.79.192.81 GET /log/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 357
+2015-01-13 22:30:22 100.79.192.81 GET /blog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 361
+2015-01-13 22:30:23 100.79.192.81 GET /log/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 361
+2015-01-13 22:30:23 100.79.192.81 GET /weblog/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 362
+2015-01-13 22:30:23 100.79.192.81 GET /typecho/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 377
+2015-01-13 22:30:25 100.79.192.81 GET /extern.php action=feed&type=atom 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 270 361
+2015-01-13 22:30:25 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 377
+2015-01-13 22:30:25 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 377
+2015-01-13 22:30:26 100.79.192.81 GET /fluxbb/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 377
+2015-01-13 22:30:26 100.79.192.81 GET /inc/Templates/rss.xslt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 260 362
+2015-01-13 22:30:26 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 392
+2015-01-13 22:30:27 100.79.192.81 GET /dvbbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 377
+2015-01-13 22:30:27 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 376
+2015-01-13 22:30:27 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 394
+2015-01-13 22:30:28 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 377
+2015-01-13 22:30:28 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 372
+2015-01-13 22:30:28 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 399
+2015-01-13 22:30:29 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 376
+2015-01-13 22:30:29 100.79.192.81 GET /opencart/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 247 393
+2015-01-13 22:30:29 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 393
+2015-01-13 22:30:30 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 411
+2015-01-13 22:30:30 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 401
+2015-01-13 22:30:30 100.79.192.81 GET /iwebshop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 247 397
+2015-01-13 22:30:31 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 408
+2015-01-13 22:30:31 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 407
+2015-01-13 22:30:31 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 394
+2015-01-13 22:30:33 100.79.192.81 GET /ecshop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 408
+2015-01-13 22:30:33 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 393
+2015-01-13 22:30:33 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 414
+2015-01-13 22:30:34 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 402
+2015-01-13 22:30:34 100.79.192.81 GET /shop7z/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 394
+2015-01-13 22:30:34 100.79.192.81 GET /skin/frontend/default/modern/css/styles.css - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 281 384
+2015-01-13 22:30:35 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 338
+2015-01-13 22:30:35 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 315
+2015-01-13 22:30:35 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 314
+2015-01-13 22:30:35 100.79.192.81 GET /magento/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 314
+2015-01-13 22:30:36 100.79.192.81 GET /api/api_user.xml - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 254 330
+2015-01-13 22:30:36 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:36 100.79.192.81 GET /kesion/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 314
+2015-01-13 22:30:36 100.79.192.81 GET /archiver - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 314
+2015-01-13 22:30:38 100.79.192.81 GET /robots.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 314
+2015-01-13 22:30:38 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:38 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 314
+2015-01-13 22:30:38 100.79.192.81 GET /bbsmax/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 313
+2015-01-13 22:30:39 100.79.192.81 GET /inc/playerKinds.xml - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 257 316
+2015-01-13 22:30:39 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:39 100.79.192.81 GET /maxcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 314
+2015-01-13 22:30:39 100.79.192.81 GET /install - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 315
+2015-01-13 22:30:40 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:40 100.79.192.81 GET /oecms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 314
+2015-01-13 22:30:40 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 314
+2015-01-13 22:30:40 100.79.192.81 GET /lazycms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 313
+2015-01-13 22:30:41 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 315
+2015-01-13 22:30:41 100.79.192.81 GET /verycms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 314
+2015-01-13 22:30:41 100.79.192.81 GET /template/home.htm - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 255 315
+2015-01-13 22:30:41 100.79.192.81 GET /system/skins/default/system.login.htm - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 275 314
+2015-01-13 22:30:43 100.79.192.81 GET /system/language/zh-cn.xml - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 263 314
+2015-01-13 22:30:43 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 330
+2015-01-13 22:30:43 100.79.192.81 GET /kingcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 345
+2015-01-13 22:30:44 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 331
+2015-01-13 22:30:44 100.79.192.81 GET /metinfo/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 345
+2015-01-13 22:30:44 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 361
+2015-01-13 22:30:45 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 340
+2015-01-13 22:30:45 100.79.192.81 GET /6kbb/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 335
+2015-01-13 22:30:45 100.79.192.81 GET /stylesheet.css - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 252 383
+2015-01-13 22:30:46 100.79.192.81 GET /includes/general.js - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 257 393
+2015-01-13 22:30:46 100.79.192.81 GET /shop/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 424
+2015-01-13 22:30:46 100.79.192.81 GET /store/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 408
+2015-01-13 22:30:47 100.79.192.81 GET /mall/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 417
+2015-01-13 22:30:47 100.79.192.81 GET /oscommerce/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 416
+2015-01-13 22:30:47 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 361
+2015-01-13 22:30:48 100.79.192.81 GET /jxcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 317
+2015-01-13 22:30:48 100.79.192.81 GET /cms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 311
+2015-01-13 22:30:48 100.79.192.81 GET /zcms/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 243 313
+2015-01-13 22:30:48 100.79.192.81 GET /robots.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 248 319
+2015-01-13 22:30:49 100.79.192.81 GET /licence.txt - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 249 310
+2015-01-13 22:30:49 100.79.192.81 GET /rss.php - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 245 317
+2015-01-13 22:30:49 100.79.192.81 GET /bbs/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 242 315
+2015-01-13 22:30:49 100.79.192.81 GET /forum/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 244 314
+2015-01-13 22:30:51 100.79.192.81 GET /phpwind/ - 80 - 183.60.244.30 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_9_4)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/36.0.1985.125+Safari/537.36 - 404 0 2 1405 246 341
+#Software: Microsoft Internet Information Services 8.5
+#Version: 1.0
+#Date: 2015-01-13 23:15:41
+#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken
+2015-01-13 23:15:41 100.79.192.81 GET /robots.txt - 80 - 188.165.15.50 Mozilla/5.0+(compatible;+AhrefsBot/5.0;++http://ahrefs.com/robot/) - 404 0 2 1405 170 141
diff --git a/test/logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0 b/test/logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0
new file mode 100644
index 0000000..8ab686e
--- /dev/null
+++ b/test/logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0
@@ -0,0 +1 @@
+Hello, World!
diff --git a/test/logfile_xml_msg.0 b/test/logfile_xml_msg.0
new file mode 100644
index 0000000..010dac6
--- /dev/null
+++ b/test/logfile_xml_msg.0
@@ -0,0 +1,36 @@
+[2020-12-10 06:56:41,061] INFO [m:108] Calling 'x' with params:
+
+[2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text:
+<?xml version='1.0' encoding='iso-8859-2'?>
+<a-request>
+ <head>
+ x
+ </head>
+ <source>
+ x
+ </source>
+ <request id="1">
+ <name>
+ x
+ </name>
+ </request>
+</a-request>
+
+[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text:
+<?xml version='1.0' encoding='iso-8859-2'?>
+<a-reply>
+ <head>
+ x
+ </head>
+ <reply id="2">
+ <status>
+ <result>OK</result>
+ </status>
+ <name>
+ x
+ </name>
+ </reply>
+ <technical-track>
+ x
+ </technical-track>
+</a-reply>
diff --git a/test/multiline.lnav b/test/multiline.lnav
new file mode 100644
index 0000000..3ee2135
--- /dev/null
+++ b/test/multiline.lnav
@@ -0,0 +1,14 @@
+#! /usr/bin/env lnav -f
+
+;CREATE TABLE foobar (
+ mykey integer primary key,
+ name text
+);
+
+;INSERT INTO foobar VALUES (1, 'Jules');
+
+;INSERT INTO environ
+ SELECT "msg", "Hello: " || group_concat(name, ", ") FROM foobar;
+
+:pipe-line-to
+ echo $msg
diff --git a/test/mvwattrline_output.0 b/test/mvwattrline_output.0
new file mode 100644
index 0000000..608ba64
--- /dev/null
+++ b/test/mvwattrline_output.0
@@ -0,0 +1,49 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+S -1 ┋ ┋
+A └ normal, normal, normal
+CSI Erase all
+S 1 ┋Plain text ┋
+A ··········└ carriage-return
+S 2 ┋ Leading tab ┋
+A └ inverse │
+A ········└ normal │
+A ···················└ carriage-return
+S 3 ┋Tab with text ┋
+A ·└ inverse │
+A ········└ normal │
+A ·················└ carriage-return
+S 4 ┋Tab with text #2 ┋
+A ···└ inverse │
+A ········└ normal │
+A ····················└ carriage-return
+S 5 ┋Two tabs with text ┋
+A ········└ inverse │ │
+A ··········└ normal │ │
+A ················└ inverse│
+A ····················└ normal
+A ·························└ carriage-return
+S 6 ┋Text with mixed attributes. ┋
+A ·····└ fg(#800000) │
+A ·······└ inverse │
+A ·········└ normal │
+A ············└ normal │
+A ···························└ carriage-return
+S 7 ┋Text with unicode ▶ characters ┋
+A ····················└ inverse │
+A ························└ normal
+A ······························└ carriage-return
+S 8 ┋ ┋
+A └ normal
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/nested.lnav b/test/nested.lnav
new file mode 100644
index 0000000..836e030
--- /dev/null
+++ b/test/nested.lnav
@@ -0,0 +1,2 @@
+
+:echo nested here $0 $1 $2
diff --git a/test/parser_debugger.py b/test/parser_debugger.py
new file mode 100755
index 0000000..d2818f5
--- /dev/null
+++ b/test/parser_debugger.py
@@ -0,0 +1,249 @@
+#! /usr/bin/env python
+
+# Copyright (c) 2013, Timothy Stack
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Timothy Stack nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import string
+import readline
+import itertools
+import collections
+
+TEST_DIR = os.path.dirname(__file__)
+ROOT_DIR = os.path.dirname(TEST_DIR)
+SRC_DIR = os.path.join(ROOT_DIR, "src")
+
+addr_to_name = {}
+name_to_addr = {}
+element_lists = collections.defaultdict(list)
+list_depth = {}
+list_format = {}
+breakpoints = set()
+
+def completer(text, state):
+ options = [x for x in itertools.chain(name_to_addr,
+ element_lists,
+ breakpoints)
+ if x.startswith(text)]
+ try:
+ return options[state]
+ except IndexError:
+ return None
+
+readline.set_completer(completer)
+
+if 'libedit' in readline.__doc__:
+ readline.parse_and_bind('bind ^I rl_complete')
+else:
+ readline.parse_and_bind('tab: complete')
+
+input_line = ''
+ops = []
+for line in open("scanned.dpt"):
+ if line.startswith("input "):
+ input_line = line[6:-1]
+ else:
+ ops.append(map(string.strip, line.split()))
+
+def getstr(capture):
+ start, end = capture.split(':')
+ return input_line[int(start):int(end)]
+
+def printlist(name_or_addr):
+ if name_or_addr in name_to_addr:
+ addr = name_to_addr[name_or_addr]
+ print "% 3d (%s:%s) %s" % (list_depth.get(addr, -1), name_or_addr, addr, element_lists[addr])
+ elif name_or_addr in element_lists:
+ addr = name_or_addr
+ print "% 3d (%s:%s) %s" % (list_depth.get(name_or_addr, -1),
+ addr_to_name.get(name_or_addr, name_or_addr),
+ name_or_addr,
+ element_lists[name_or_addr])
+ else:
+ print "error: unknown list --", name_or_addr
+
+ if addr in list_format:
+ print " format -- appender(%s) term(%s) qual(%s) sep(%s) prefix_term(%s)" % tuple(list_format[addr])
+
+def handleop(fields):
+ addr = fields[0]
+ loc = fields[1].split(':')
+ method_name = fields[2]
+ method_args = fields[3:]
+
+ if addr == '0x0':
+ el = None
+ else:
+ el = element_lists[addr]
+
+ if method_name == 'element_list_t':
+ addr_to_name[addr] = method_args[0]
+ name_to_addr[method_args[0]] = addr
+ list_depth[addr] = int(method_args[1])
+ elif method_name == '~element_list_t':
+ del element_lists[addr]
+ elif method_name == 'format':
+ list_depth[addr] = int(method_args[0])
+ list_format[addr] = method_args[1:]
+ elif method_name == 'consumed':
+ list_depth[addr] = -1
+ elif method_name == 'push_back':
+ el.append((method_args[0], getstr(method_args[1])))
+ elif method_name == 'pop_front':
+ el.pop(0)
+ elif method_name == 'pop_back':
+ el.pop()
+ elif method_name == 'clear2':
+ el[::] = []
+ elif method_name == 'splice':
+ pos = int(method_args[0])
+ other = element_lists[method_args[1]]
+ start, from_end = map(int, method_args[2].split(':'))
+ end = len(other) - from_end
+ sub_list = other[start:end]
+ del other[start:end]
+ el[pos:pos] = sub_list
+ elif method_name == 'swap':
+ other = element_lists[method_args[0]]
+ element_lists[method_args[0]] = el
+ element_lists[addr] = other
+ elif method_name == 'point':
+ breakpoints.add(method_args[0])
+ else:
+ print "Unhandled method: ", method_name
+
+def playupto(length):
+ addr_to_name.clear()
+ name_to_addr.clear()
+ element_lists.clear()
+ list_depth.clear()
+ for index in range(length):
+ handleop(ops[index])
+
+def find_prev_point(start, name):
+ orig_start = start
+ while start > 0:
+ start -= 1;
+ fields = ops[start]
+ if fields[2] != 'point':
+ continue
+ if not name or fields[3] == name:
+ return start + 1
+ return orig_start + 1
+
+def find_next_point(start, name):
+ orig_start = start
+ while start < len(ops):
+ start += 1;
+ fields = ops[start]
+ if fields[2] != 'point':
+ continue
+ if not name or fields[3] == name:
+ return start + 1
+ return orig_start + 1
+
+def printall():
+ print input_line
+ sorted_lists = [(list_depth.get(addr, -1), addr) for addr in element_lists]
+ sorted_lists.sort()
+ for _depth, addr in sorted_lists:
+ printlist(addr)
+
+index = len(ops)
+last_cmd = ['']
+watch_list = set()
+while True:
+ playupto(index)
+
+ if index == 0:
+ print "init"
+ else:
+ op = ops[index - 1]
+ print "#%s %s" % (index -1, op)
+ if op[2] == 'push_back':
+ print getstr(op[4])
+
+ for list_name in watch_list:
+ printlist(list_name)
+
+ try:
+ cmd = raw_input("> ").split()
+ except EOFError:
+ print
+ break
+
+ if not cmd or cmd[0] == '':
+ cmd = last_cmd
+
+ if not cmd or cmd[0] == '':
+ pass
+ elif cmd[0] == 'h':
+ print 'Help:'
+ print ' q - quit'
+ print ' s - Start over'
+ print ' n - Next step'
+ print ' r - Previous step'
+ print ' b - Previous breakpoint'
+ print ' c - Next breakpoint'
+ print ' p - Print state'
+ print ' w <var> - Add a variable to the watch list'
+ print ' u <var> - Remove a variable from the watch list'
+ elif cmd[0] == 'q':
+ break
+ elif cmd[0] == 's':
+ index = 0
+ elif cmd[0] == 'n':
+ if index < len(ops):
+ index += 1
+ elif cmd[0] == 'r':
+ if index > 0:
+ index -= 1
+ elif cmd[0] == 'b':
+ if len(cmd) == 1:
+ cmd.append('')
+
+ index = find_prev_point(index - 1, cmd[1])
+ elif cmd[0] == 'c':
+ if len(cmd) == 1:
+ cmd.append('')
+ index = find_next_point(index - 1, cmd[1])
+ elif cmd[0] == 'p':
+ if len(cmd) > 1:
+ printlist(cmd[1])
+ else:
+ printall()
+ elif cmd[0] == 'w':
+ watch_list.add(cmd[1])
+ elif cmd[0] == 'u':
+ if watch_list:
+ watch_list.remove(cmd[1])
+ else:
+ print "error: unknown command --", cmd
+
+ printall()
+
+ last_cmd = cmd
diff --git a/test/remote-log-dir/logfile_access_log.0 b/test/remote-log-dir/logfile_access_log.0
new file mode 100644
index 0000000..a90f29f
--- /dev/null
+++ b/test/remote-log-dir/logfile_access_log.0
@@ -0,0 +1,3 @@
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
diff --git a/test/remote-log-dir/logfile_access_log.1 b/test/remote-log-dir/logfile_access_log.1
new file mode 100644
index 0000000..ad2b37e
--- /dev/null
+++ b/test/remote-log-dir/logfile_access_log.1
@@ -0,0 +1 @@
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
diff --git a/test/rltest.cc b/test/rltest.cc
new file mode 100644
index 0000000..81606eb
--- /dev/null
+++ b/test/rltest.cc
@@ -0,0 +1,216 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <readline/readline.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "vt52_curses.hh"
+
+static const int KEY_TIMEOUT = 500 * 1000;
+
+static int got_line = 0;
+static int got_timeout = 0;
+
+static void
+sigalrm(int sig)
+{
+ got_timeout = 1;
+}
+
+static void
+line_ready(char* line)
+{
+ fprintf(stderr, "got line: %s\n", line);
+ add_history(line);
+ got_line = 1;
+}
+
+static void
+child_readline(void)
+{
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+
+ rl_callback_handler_install("/", (void (*)()) line_ready);
+ while (1) {
+ fd_set ready_rfds = rfds;
+ int rc;
+
+ rc = select(STDIN_FILENO + 1, &ready_rfds, NULL, NULL, NULL);
+ if (rc < 0) {
+ switch (errno) {
+ case EINTR:
+ break;
+ }
+ } else {
+ if (FD_ISSET(STDIN_FILENO, &ready_rfds)) {
+ struct itimerval itv;
+
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = KEY_TIMEOUT;
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &itv, NULL);
+
+ rl_callback_read_char();
+ }
+ }
+
+ if (got_timeout) {
+ fprintf(stderr, "got timeout\n");
+ got_timeout = 0;
+ }
+ if (got_line) {
+ rl_callback_handler_remove();
+ got_line = 0;
+ rl_callback_handler_install("/", (void (*)()) line_ready);
+ }
+ }
+}
+
+static void
+finish(int sig)
+{
+ endwin();
+ exit(0);
+}
+
+int
+main(int argc, char* argv[])
+{
+ int fd, retval = EXIT_SUCCESS;
+ signal(SIGALRM, sigalrm);
+
+ fd = open("/tmp/rltest.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ fprintf(stderr, "startup\n");
+
+ if (0) {
+ while (1) {
+ char* ret = readline("/");
+
+ add_history(ret);
+ }
+ }
+
+ (void) signal(SIGINT, finish); /* arrange interrupts to terminate */
+
+ WINDOW* mainwin = initscr(); /* initialize the curses library */
+ keypad(stdscr, TRUE); /* enable keyboard mapping */
+ (void) nonl(); /* tell curses not to do NL->CR/NL on output */
+ (void) cbreak(); /* take input chars one at a time, no wait for \n */
+ (void) noecho(); /* don't echo input */
+
+ if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0)
+ perror("fcntl");
+
+ {
+ int master, slave;
+ pid_t rl;
+
+ if (openpty(&master, &slave, NULL, NULL, NULL) < 0) {
+ perror("openpty");
+ } else if ((rl = fork()) < 0) {
+ perror("fork");
+ } else if (rl == 0) {
+ close(master);
+ master = -1;
+
+ dup2(slave, STDIN_FILENO);
+ dup2(slave, STDOUT_FILENO);
+
+ setenv("TERM", "vt52", 1);
+
+ child_readline();
+ } else {
+ vt52_curses vc(mainwin);
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+ FD_SET(master, &rfds);
+
+ while (1) {
+ fd_set ready_rfds = rfds;
+ int rc;
+
+ rc = select(master + 1, &ready_rfds, NULL, NULL, NULL);
+ if (rc < 0) {
+ break;
+ } else {
+ char buffer[1024];
+
+ if (FD_ISSET(STDIN_FILENO, &ready_rfds)) {
+ int ch;
+
+ if ((ch = getch()) != ERR) {
+ const char* bch;
+ int len;
+
+ bch = vc.map_input(ch, len);
+
+ if (len > 0) {
+ fprintf(stderr, "stdin: %x\n", ch);
+ if (write(master, bch, len) < 0)
+ perror("write");
+ }
+ }
+ }
+ if (FD_ISSET(master, &ready_rfds)) {
+ int lpc;
+
+ rc = read(master, buffer, sizeof(buffer));
+
+ fprintf(stderr, "child: ");
+ for (lpc = 0; lpc < rc; lpc++) {
+ fprintf(stderr, "%x ", buffer[lpc]);
+ }
+ fprintf(stderr, "\n");
+
+ vc.map_output(buffer, rc);
+ }
+ }
+ refresh();
+ }
+ }
+ }
+
+ finish(0);
+
+ return retval;
+}
diff --git a/test/scripty.cc b/test/scripty.cc
new file mode 100644
index 0000000..2f7bb94
--- /dev/null
+++ b/test/scripty.cc
@@ -0,0 +1,1153 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#if defined HAVE_NCURSESW_CURSES_H
+# include <ncursesw/curses.h>
+#elif defined HAVE_NCURSESW_H
+# include <ncursesw.h>
+#elif defined HAVE_NCURSES_CURSES_H
+# include <ncurses/curses.h>
+#elif defined HAVE_NCURSES_H
+# include <ncurses.h>
+#elif defined HAVE_CURSES_H
+# include <curses.h>
+#else
+# error "SysV or X/Open-compatible Curses header file required"
+#endif
+
+#ifdef HAVE_PTY_H
+# include <pty.h>
+#endif
+
+#ifdef HAVE_UTIL_H
+# include <util.h>
+#endif
+
+#ifdef HAVE_LIBUTIL_H
+# include <libutil.h>
+#endif
+
+#include <algorithm>
+#include <map>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "base/auto_fd.hh"
+#include "base/auto_mem.hh"
+#include "base/string_util.hh"
+#include "fmt/format.h"
+#include "ghc/filesystem.hpp"
+#include "styling.hh"
+#include "termios_guard.hh"
+#include "ww898/cp_utf8.hpp"
+
+using namespace std;
+
+/**
+ * An RAII class for opening a PTY and forking a child process.
+ */
+class child_term {
+public:
+ class error : public std::exception {
+ public:
+ error(int err) : e_err(err){};
+
+ int e_err;
+ };
+
+ explicit child_term(bool passin)
+ {
+ struct winsize ws;
+ auto_fd slave;
+
+ memset(&ws, 0, sizeof(ws));
+
+ if (isatty(STDIN_FILENO)
+ && tcgetattr(STDIN_FILENO, &this->ct_termios) == -1) {
+ throw error(errno);
+ }
+
+ if (isatty(STDOUT_FILENO)
+ && ioctl(STDOUT_FILENO, TIOCGWINSZ, &this->ct_winsize) == -1)
+ {
+ throw error(errno);
+ }
+
+ ws.ws_col = 80;
+ ws.ws_row = 24;
+
+ if (openpty(this->ct_master.out(), slave.out(), nullptr, nullptr, &ws)
+ < 0) {
+ throw error(errno);
+ }
+
+ if ((this->ct_child = fork()) == -1)
+ throw error(errno);
+
+ if (this->ct_child == 0) {
+ this->ct_master.reset();
+
+ if (!passin) {
+ dup2(slave, STDIN_FILENO);
+ }
+ dup2(slave, STDOUT_FILENO);
+
+ setenv("TERM", "xterm-color", 1);
+ } else {
+ slave.reset();
+ }
+ };
+
+ virtual ~child_term()
+ {
+ (void) this->wait_for_child();
+
+ if (isatty(STDIN_FILENO)
+ && tcsetattr(STDIN_FILENO, TCSANOW, &this->ct_termios) == -1)
+ {
+ perror("tcsetattr");
+ }
+ if (isatty(STDOUT_FILENO)
+ && ioctl(STDOUT_FILENO, TIOCSWINSZ, &this->ct_winsize) == -1)
+ {
+ perror("ioctl");
+ }
+ };
+
+ int wait_for_child()
+ {
+ int retval = -1;
+
+ if (this->ct_child > 0) {
+ kill(this->ct_child, SIGTERM);
+ this->ct_child = -1;
+
+ while (wait(&retval) < 0 && (errno == EINTR))
+ ;
+ }
+
+ return retval;
+ };
+
+ bool is_child() const
+ {
+ return this->ct_child == 0;
+ };
+
+ pid_t get_child_pid() const
+ {
+ return this->ct_child;
+ };
+
+ int get_fd() const
+ {
+ return this->ct_master;
+ };
+
+protected:
+ pid_t ct_child;
+ auto_fd ct_master;
+ struct termios ct_termios;
+ struct winsize ct_winsize;
+};
+
+/**
+ * @param fd The file descriptor to switch to raw mode.
+ * @return Zero on success, -1 on error.
+ */
+static int
+tty_raw(int fd)
+{
+ struct termios attr[1];
+
+ assert(fd >= 0);
+
+ if (tcgetattr(fd, attr) == -1)
+ return -1;
+
+ attr->c_lflag &= ~(ECHO | ICANON | IEXTEN);
+ attr->c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
+ attr->c_cflag &= ~(CSIZE | PARENB);
+ attr->c_cflag |= (CS8);
+ attr->c_oflag &= ~(OPOST);
+ attr->c_cc[VMIN] = 1;
+ attr->c_cc[VTIME] = 0;
+
+ return tcsetattr(fd, TCSANOW, attr);
+}
+
+static void
+dump_memory(FILE* dst, const char* src, int len)
+{
+ int lpc;
+
+ for (lpc = 0; lpc < len; lpc++) {
+ fprintf(dst, "%02x", src[lpc] & 0xff);
+ }
+}
+
+static std::vector<char>
+hex2bits(const char* src)
+{
+ std::vector<char> retval;
+
+ for (size_t lpc = 0; src[lpc] && isdigit(src[lpc]); lpc += 2) {
+ int val;
+
+ sscanf(&src[lpc], "%2x", &val);
+ retval.push_back((char) val);
+ }
+
+ return retval;
+}
+
+static const char*
+tstamp()
+{
+ static char buf[64];
+
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
+ strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.", localtime(&tv.tv_sec));
+ auto dlen = strlen(buf);
+ snprintf(&buf[dlen], sizeof(buf) - dlen, "%.06d", tv.tv_usec);
+
+ return buf;
+}
+
+typedef enum {
+ CT_WRITE,
+} command_type_t;
+
+struct command {
+ command_type_t c_type;
+ vector<char> c_arg;
+};
+
+static struct {
+ const char* sd_program_name{nullptr};
+ sig_atomic_t sd_looping{true};
+
+ pid_t sd_child_pid{-1};
+
+ ghc::filesystem::path sd_actual_name;
+ auto_mem<FILE> sd_from_child{fclose};
+ ghc::filesystem::path sd_expected_name;
+
+ deque<struct command> sd_replay;
+} scripty_data;
+
+static const std::map<std::string, std::string> CSI_TO_DESC = {
+ {")0", "Use alt charset"},
+
+ {"[?1000l", "Don't Send Mouse X & Y"},
+ {"[?1002l", "Don’t Use Cell Motion Mouse Tracking"},
+ {"[?1006l", "Don't ..."},
+ {"[?1h", "Application cursor keys"},
+ {"[?1l", "Normal cursor keys"},
+ {"[?47h", "Use alternate screen buffer"},
+ {"[?47l", "Use normal screen buffer"},
+ {"[2h", "Set Keyboard Action mode"},
+ {"[4h", "Set Replace mode"},
+ {"[12h", "Set Send/Receive mode"},
+ {"[20h", "Set Normal Linefeed mode"},
+ {"[2l", "Reset Keyboard Action mode"},
+ {"[4l", "Reset Replace mode"},
+ {"[12l", "Reset Send/Receive mode"},
+ {"[20l", "Reset Normal Linefeed mode"},
+ {"[2J", "Erase all"},
+};
+
+struct term_machine {
+ enum class state {
+ NORMAL,
+ ESCAPE_START,
+ ESCAPE_FIXED_LENGTH,
+ ESCAPE_VARIABLE_LENGTH,
+ ESCAPE_OSC,
+ };
+
+ struct term_attr {
+ term_attr(size_t pos, const std::string& desc)
+ : ta_pos(pos), ta_end(pos), ta_desc({desc})
+ {
+ }
+
+ term_attr(size_t pos, size_t end, const std::string& desc)
+ : ta_pos(pos), ta_end(end), ta_desc({desc})
+ {
+ }
+
+ size_t ta_pos;
+ size_t ta_end;
+ std::vector<std::string> ta_desc;
+ };
+
+ term_machine(child_term& ct) : tm_child_term(ct)
+ {
+ this->clear();
+ }
+
+ ~term_machine()
+ {
+ this->flush_line();
+ }
+
+ void clear()
+ {
+ std::fill(begin(this->tm_line), end(this->tm_line), ' ');
+ this->tm_line_attrs.clear();
+ this->tm_new_data = false;
+ }
+
+ void add_line_attr(const std::string& desc)
+ {
+ if (!this->tm_line_attrs.empty()
+ && this->tm_line_attrs.back().ta_pos == this->tm_cursor_x)
+ {
+ this->tm_line_attrs.back().ta_desc.emplace_back(desc);
+ } else {
+ this->tm_line_attrs.emplace_back(this->tm_cursor_x, desc);
+ }
+ }
+
+ void write_char(char ch)
+ {
+ if (isprint(ch)) {
+ require(ch);
+
+ this->tm_new_data = true;
+ this->tm_line[this->tm_cursor_x++] = (unsigned char) ch;
+ } else {
+ switch (ch) {
+ case '\a':
+ this->flush_line();
+ fprintf(scripty_data.sd_from_child, "CTRL bell\n");
+ break;
+ case '\x08':
+ this->add_line_attr("backspace");
+ if (this->tm_cursor_x > 0) {
+ this->tm_cursor_x -= 1;
+ }
+ break;
+ case '\r':
+ this->add_line_attr("carriage-return");
+ this->tm_cursor_x = 0;
+ break;
+ case '\n':
+ this->flush_line();
+ if (this->tm_cursor_y >= 0) {
+ this->tm_cursor_y += 1;
+ }
+ this->tm_cursor_x = 0;
+ break;
+ case '\x0e':
+ this->tm_shift_start = this->tm_cursor_x;
+ break;
+ case '\x0f':
+ if (this->tm_shift_start != this->tm_cursor_x) {
+ this->tm_line_attrs.emplace_back(
+ this->tm_shift_start, this->tm_cursor_x, "alt");
+ }
+ break;
+ default:
+ require(ch);
+ this->tm_new_data = true;
+ this->tm_line[this->tm_cursor_x++] = (unsigned char) ch;
+ break;
+ }
+ }
+ }
+
+ void flush_line()
+ {
+ if (std::exchange(this->tm_waiting_on_input, false)
+ && !this->tm_user_input.empty())
+ {
+ fprintf(stderr, "%s:flush keys\n", tstamp());
+ fprintf(scripty_data.sd_from_child, "K ");
+ dump_memory(
+ scripty_data.sd_from_child, this->tm_user_input.data(), 1);
+ fprintf(scripty_data.sd_from_child, "\n");
+ this->tm_user_input.erase(this->tm_user_input.begin());
+ }
+ if (this->tm_new_data || !this->tm_line_attrs.empty()) {
+ // fprintf(scripty_data.sd_from_child, "flush %d\n",
+ // this->tm_flush_count);
+ fprintf(stderr, "%s:flush %zu\n", tstamp(), this->tm_flush_count++);
+ fprintf(
+ scripty_data.sd_from_child, "S % 3d \u250B", this->tm_cursor_y);
+ for (auto uch : this->tm_line) {
+ ww898::utf::utf8::write(uch, [](auto ch) {
+ fputc(ch, scripty_data.sd_from_child);
+ });
+ }
+ fprintf(scripty_data.sd_from_child, "\u250B\n");
+ for (size_t lpc = 0; lpc < this->tm_line_attrs.size(); lpc++) {
+ const auto& ta = this->tm_line_attrs[lpc];
+ auto full_desc = fmt::format(
+ "{}",
+ fmt::join(ta.ta_desc.begin(), ta.ta_desc.end(), ", "));
+ int line_len;
+
+ if (ta.ta_pos == ta.ta_end) {
+ line_len = fprintf(
+ scripty_data.sd_from_child,
+ "A %s%s %s",
+ repeat("\u00B7", ta.ta_pos).c_str(),
+ ((lpc + 1 < this->tm_line_attrs.size())
+ && (ta.ta_pos == this->tm_line_attrs[lpc + 1].ta_pos))
+ ? "\u251C"
+ : "\u2514",
+ full_desc.c_str());
+ line_len -= 2 + ta.ta_pos;
+ } else {
+ line_len = fprintf(
+ scripty_data.sd_from_child,
+ "A %s%s%s\u251b %s",
+ std::string(ta.ta_pos, ' ').c_str(),
+ ((lpc + 1 < this->tm_line_attrs.size())
+ && (ta.ta_pos == this->tm_line_attrs[lpc + 1].ta_pos))
+ ? "\u2518"
+ : "\u2514",
+ std::string(ta.ta_end - ta.ta_pos - 1, '-').c_str(),
+ full_desc.c_str());
+ line_len -= 4;
+ }
+ for (size_t lpc2 = lpc + 1; lpc2 < this->tm_line_attrs.size();
+ lpc2++) {
+ auto bar_pos = 7 + this->tm_line_attrs[lpc2].ta_pos;
+
+ if (bar_pos < line_len) {
+ continue;
+ }
+ line_len += fprintf(
+ scripty_data.sd_from_child,
+ "%s\u2502",
+ std::string(bar_pos - line_len, ' ').c_str());
+ line_len -= 2;
+ }
+ fprintf(scripty_data.sd_from_child, "\n");
+ }
+ this->clear();
+ }
+ fflush(scripty_data.sd_from_child);
+ }
+
+ std::vector<int> get_m_params()
+ {
+ std::vector<int> retval;
+ size_t index = 1;
+
+ while (index < this->tm_escape_buffer.size()) {
+ int val, last;
+
+ if (sscanf(&this->tm_escape_buffer[index], "%d%n", &val, &last)
+ == 1) {
+ retval.push_back(val);
+ index += last;
+ if (this->tm_escape_buffer[index] != ';') {
+ break;
+ }
+ index += 1;
+ } else {
+ break;
+ }
+ }
+
+ return retval;
+ }
+
+ void new_user_input(char ch)
+ {
+ this->tm_user_input.push_back(ch);
+ }
+
+ void new_input(char ch)
+ {
+ if (this->tm_unicode_remaining > 0) {
+ this->tm_unicode_buffer.push_back(ch);
+ this->tm_unicode_remaining -= 1;
+ if (this->tm_unicode_remaining == 0) {
+ this->tm_new_data = true;
+ this->tm_line[this->tm_cursor_x++]
+ = ww898::utf::utf8::read([this]() {
+ auto retval = this->tm_unicode_buffer.front();
+
+ this->tm_unicode_buffer.pop_front();
+ return retval;
+ });
+ }
+ return;
+ } else {
+ auto utfsize = ww898::utf::utf8::char_size(
+ [ch]() { return std::make_pair(ch, 16); });
+
+ if (utfsize.unwrap() > 1) {
+ this->tm_unicode_remaining = utfsize.unwrap() - 1;
+ this->tm_unicode_buffer.push_back(ch);
+ return;
+ }
+ }
+
+ switch (this->tm_state) {
+ case state::NORMAL: {
+ switch (ch) {
+ case '\x1b': {
+ this->tm_escape_buffer.clear();
+ this->tm_state = state::ESCAPE_START;
+ break;
+ }
+ default: {
+ this->write_char(ch);
+ break;
+ }
+ }
+ break;
+ }
+ case state::ESCAPE_START: {
+ switch (ch) {
+ case '[': {
+ this->tm_escape_buffer.push_back(ch);
+ this->tm_state = state::ESCAPE_VARIABLE_LENGTH;
+ break;
+ }
+ case ']': {
+ this->tm_escape_buffer.push_back(ch);
+ this->tm_state = state::ESCAPE_OSC;
+ break;
+ }
+ case '(':
+ case ')':
+ case '*':
+ case '+': {
+ this->tm_state = state::ESCAPE_FIXED_LENGTH;
+ this->tm_escape_buffer.push_back(ch);
+ this->tm_escape_expected_size = 2;
+ break;
+ }
+ default: {
+ this->flush_line();
+ switch (ch) {
+ case '7':
+ fprintf(scripty_data.sd_from_child,
+ "CTRL save cursor\n");
+ break;
+ case '8':
+ fprintf(scripty_data.sd_from_child,
+ "CTRL restore cursor\n");
+ break;
+ case '>':
+ fprintf(scripty_data.sd_from_child,
+ "CTRL Normal keypad\n");
+ break;
+ default: {
+ fprintf(scripty_data.sd_from_child,
+ "CTRL %c\n",
+ ch);
+ break;
+ }
+ }
+ this->tm_state = state::NORMAL;
+ break;
+ }
+ }
+ break;
+ }
+ case state::ESCAPE_FIXED_LENGTH: {
+ this->tm_escape_buffer.push_back(ch);
+ if (this->tm_escape_buffer.size()
+ == this->tm_escape_expected_size) {
+ auto iter = CSI_TO_DESC.find(
+ std::string(this->tm_escape_buffer.data(),
+ this->tm_escape_buffer.size()));
+ this->flush_line();
+ if (iter == CSI_TO_DESC.end()) {
+ fprintf(scripty_data.sd_from_child,
+ "CTRL %.*s\n",
+ (int) this->tm_escape_buffer.size(),
+ this->tm_escape_buffer.data());
+ } else {
+ fprintf(scripty_data.sd_from_child,
+ "CTRL %s\n",
+ iter->second.c_str());
+ }
+ this->tm_state = state::NORMAL;
+ }
+ break;
+ }
+ case state::ESCAPE_VARIABLE_LENGTH: {
+ this->tm_escape_buffer.push_back(ch);
+ if (isalpha(ch)) {
+ auto iter = CSI_TO_DESC.find(
+ std::string(this->tm_escape_buffer.data(),
+ this->tm_escape_buffer.size()));
+ if (iter == CSI_TO_DESC.end()) {
+ this->tm_escape_buffer.push_back('\0');
+ switch (ch) {
+ case 'A': {
+ auto amount = this->get_m_params();
+ int count = 1;
+
+ if (!amount.empty()) {
+ count = amount[0];
+ }
+ this->flush_line();
+ this->tm_cursor_y -= count;
+ if (this->tm_cursor_y < 0) {
+ this->tm_cursor_y = 0;
+ }
+ break;
+ }
+ case 'B': {
+ auto amount = this->get_m_params();
+ int count = 1;
+
+ if (!amount.empty()) {
+ count = amount[0];
+ }
+ this->flush_line();
+ this->tm_cursor_y += count;
+ break;
+ }
+ case 'C': {
+ auto amount = this->get_m_params();
+ int count = 1;
+
+ if (!amount.empty()) {
+ count = amount[0];
+ }
+ this->tm_cursor_x += count;
+ break;
+ }
+ case 'J': {
+ auto param = this->get_m_params();
+
+ this->flush_line();
+
+ auto region = param.empty() ? 0 : param[0];
+ switch (region) {
+ case 0:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase Below\n");
+ break;
+ case 1:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase Above\n");
+ break;
+ case 2:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase All\n");
+ break;
+ case 3:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase Saved Lines\n");
+ break;
+ }
+ break;
+ }
+ case 'K': {
+ auto param = this->get_m_params();
+
+ this->flush_line();
+
+ auto region = param.empty() ? 0 : param[0];
+ switch (region) {
+ case 0:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase to Right\n");
+ break;
+ case 1:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase to Left\n");
+ break;
+ case 2:
+ fprintf(scripty_data.sd_from_child,
+ "CSI Erase All\n");
+ break;
+ }
+ break;
+ }
+ case 'H': {
+ auto coords = this->get_m_params();
+
+ if (coords.empty()) {
+ coords = {1, 1};
+ }
+ this->flush_line();
+ this->tm_cursor_y = coords[0];
+ this->tm_cursor_x = coords[1] - 1;
+ break;
+ }
+ case 'r': {
+ auto region = this->get_m_params();
+
+ this->flush_line();
+ fprintf(scripty_data.sd_from_child,
+ "CSI set scrolling region %d-%d\n",
+ region[0],
+ region[1]);
+ break;
+ }
+ case 'm': {
+ auto attrs = this->get_m_params();
+
+ if (attrs.empty()) {
+ this->add_line_attr("normal");
+ } else if ((30 <= attrs[0]) && (attrs[0] <= 37))
+ {
+ auto xt = xterm_colors();
+
+ this->add_line_attr(fmt::format(
+ "fg({})",
+ xt->tc_palette[attrs[0] - 30].xc_hex));
+ } else if (attrs[0] == 38) {
+ auto xt = xterm_colors();
+
+ require(attrs[1] == 5);
+ this->add_line_attr(fmt::format(
+ "fg({})",
+ xt->tc_palette[attrs[2]].xc_hex));
+ } else if ((40 <= attrs[0]) && (attrs[0] <= 47))
+ {
+ auto xt = xterm_colors();
+
+ this->add_line_attr(fmt::format(
+ "bg({})",
+ xt->tc_palette[attrs[0] - 40].xc_hex));
+ } else if (attrs[0] == 48) {
+ auto xt = xterm_colors();
+
+ require(attrs[1] == 5);
+ this->add_line_attr(fmt::format(
+ "bg({})",
+ xt->tc_palette[attrs[2]].xc_hex));
+ } else {
+ switch (attrs[0]) {
+ case 1:
+ this->add_line_attr("bold");
+ break;
+ case 4:
+ this->add_line_attr("underline");
+ break;
+ case 5:
+ this->add_line_attr("blink");
+ break;
+ case 7:
+ this->add_line_attr("inverse");
+ break;
+ default:
+ this->add_line_attr(
+ this->tm_escape_buffer.data());
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "%s:missed %c\n", tstamp(), ch);
+ this->add_line_attr(
+ this->tm_escape_buffer.data());
+ break;
+ }
+ } else {
+ this->flush_line();
+ fprintf(scripty_data.sd_from_child,
+ "CSI %s\n",
+ iter->second.c_str());
+ }
+ this->tm_state = state::NORMAL;
+ } else {
+ }
+ break;
+ }
+ case state::ESCAPE_OSC: {
+ if (ch == '\a') {
+ this->tm_escape_buffer.push_back('\0');
+
+ auto num = this->get_m_params();
+ auto semi_index
+ = strchr(this->tm_escape_buffer.data(), ';');
+
+ switch (num[0]) {
+ case 0: {
+ this->flush_line();
+ fprintf(scripty_data.sd_from_child,
+ "OSC Set window title: %s\n",
+ semi_index + 1);
+ break;
+ }
+ case 999: {
+ this->flush_line();
+ this->tm_waiting_on_input = true;
+ if (!scripty_data.sd_replay.empty()) {
+ const auto& cmd
+ = scripty_data.sd_replay.front();
+
+ this->tm_user_input = cmd.c_arg;
+ write(this->tm_child_term.get_fd(),
+ this->tm_user_input.data(),
+ this->tm_user_input.size());
+
+ scripty_data.sd_replay.pop_front();
+ }
+ break;
+ }
+ }
+
+ this->tm_state = state::NORMAL;
+ } else {
+ this->tm_escape_buffer.push_back(ch);
+ }
+ break;
+ }
+ }
+ }
+
+ child_term& tm_child_term;
+ bool tm_waiting_on_input{false};
+ state tm_state{state::NORMAL};
+ std::vector<char> tm_escape_buffer;
+ std::deque<uint8_t> tm_unicode_buffer;
+ size_t tm_unicode_remaining{0};
+ size_t tm_escape_expected_size{0};
+ uint32_t tm_line[80];
+ bool tm_new_data{false};
+ size_t tm_cursor_x{0};
+ int tm_cursor_y{-1};
+ size_t tm_shift_start{0};
+ std::vector<term_attr> tm_line_attrs;
+
+ std::vector<char> tm_user_input;
+
+ size_t tm_flush_count{0};
+};
+
+static void
+sigchld(int sig)
+{
+}
+
+static void
+sigpass(int sig)
+{
+ kill(scripty_data.sd_child_pid, sig);
+}
+
+static void
+usage()
+{
+ const char* usage_msg
+ = "usage: %s [-h] [-t to_child] [-f from_child] -- <cmd>\n"
+ "\n"
+ "Recorder for TTY I/O from a child process."
+ "\n"
+ "Options:\n"
+ " -h Print this message, then exit.\n"
+ " -n Do not pass the output to the console.\n"
+ " -i Pass stdin to the child process instead of connecting\n"
+ " the child to the tty.\n"
+ " -a <file> The file where the actual I/O from/to the child "
+ "process\n"
+ " should be stored.\n"
+ " -e <file> The file containing the expected I/O from/to the "
+ "child\n"
+ " process.\n"
+ "\n"
+ "Examples:\n"
+ " To record a session for playback later:\n"
+ " $ scripty -a output.0 -- myCursesApp\n"
+ "\n"
+ " To replay the recorded session:\n"
+ " $ scripty -e input.0 -- myCursesApp\n";
+
+ fprintf(stderr, usage_msg, scripty_data.sd_program_name);
+}
+
+int
+main(int argc, char* argv[])
+{
+ int c, fd, retval = EXIT_SUCCESS;
+ bool passout = true, passin = false, prompt = false;
+ auto_mem<FILE> file(fclose);
+
+ scripty_data.sd_program_name = argv[0];
+ scripty_data.sd_looping = true;
+
+ while ((c = getopt(argc, argv, "ha:e:nip")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+ exit(retval);
+ break;
+ case 'a':
+ scripty_data.sd_actual_name = optarg;
+ break;
+ case 'e':
+ scripty_data.sd_expected_name = optarg;
+ if ((file = fopen(optarg, "r")) == nullptr) {
+ fprintf(
+ stderr, "%s:error: cannot open %s\n", tstamp(), optarg);
+ retval = EXIT_FAILURE;
+ } else {
+ char line[32 * 1024];
+
+ while (fgets(line, sizeof(line), file)) {
+ if (line[0] == 'K') {
+ struct command cmd;
+
+ cmd.c_type = CT_WRITE;
+ cmd.c_arg = hex2bits(&line[2]);
+ scripty_data.sd_replay.push_back(cmd);
+ }
+ }
+ }
+ break;
+ case 'n':
+ passout = false;
+ break;
+ case 'i':
+ passin = true;
+ break;
+ case 'p':
+ prompt = true;
+ break;
+ default:
+ fprintf(stderr, "%s:error: unknown flag -- %c\n", tstamp(), c);
+ retval = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!scripty_data.sd_expected_name.empty()
+ && scripty_data.sd_actual_name.empty())
+ {
+ scripty_data.sd_actual_name = scripty_data.sd_expected_name.filename();
+ scripty_data.sd_actual_name += ".tmp";
+ }
+
+ if (!scripty_data.sd_actual_name.empty()) {
+ if ((scripty_data.sd_from_child
+ = fopen(scripty_data.sd_actual_name.c_str(), "w"))
+ == nullptr)
+ {
+ fprintf(stderr,
+ "error: unable to open %s -- %s\n",
+ scripty_data.sd_actual_name.c_str(),
+ strerror(errno));
+ retval = EXIT_FAILURE;
+ }
+ }
+
+ if (scripty_data.sd_from_child != nullptr) {
+ fcntl(fileno(scripty_data.sd_from_child), F_SETFD, 1);
+ }
+
+ if (retval != EXIT_FAILURE) {
+ guard_termios gt(STDOUT_FILENO);
+ fd = open("/tmp/scripty.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+ fprintf(stderr, "%s:startup\n", tstamp());
+
+ child_term ct(passin);
+
+ if (ct.is_child()) {
+ execvp(argv[0], argv);
+ perror("execvp");
+ exit(-1);
+ } else {
+ int maxfd;
+ struct timeval last, now;
+ fd_set read_fds;
+ term_machine tm(ct);
+ size_t last_replay_size = scripty_data.sd_replay.size();
+
+ scripty_data.sd_child_pid = ct.get_child_pid();
+ signal(SIGINT, sigpass);
+ signal(SIGTERM, sigpass);
+
+ signal(SIGCHLD, sigchld);
+
+ gettimeofday(&now, nullptr);
+ last = now;
+
+ FD_ZERO(&read_fds);
+ FD_SET(STDIN_FILENO, &read_fds);
+ FD_SET(ct.get_fd(), &read_fds);
+
+ fprintf(stderr, "%s:goin in the loop\n", tstamp());
+
+ tty_raw(STDIN_FILENO);
+
+ maxfd = max(STDIN_FILENO, ct.get_fd());
+ while (scripty_data.sd_looping) {
+ fd_set ready_rfds = read_fds;
+ struct timeval diff, to;
+ int rc;
+
+ to.tv_sec = 0;
+ to.tv_usec = 10000;
+ rc = select(maxfd + 1, &ready_rfds, nullptr, nullptr, &to);
+ gettimeofday(&now, nullptr);
+ timersub(&now, &last, &diff);
+ if (diff.tv_sec > 10) {
+ fprintf(stderr, "%s:replay timed out!\n", tstamp());
+ scripty_data.sd_looping = false;
+ kill(ct.get_child_pid(), SIGKILL);
+ retval = EXIT_FAILURE;
+ break;
+ }
+ if (rc == 0) {
+ } else if (rc < 0) {
+ switch (errno) {
+ case EINTR:
+ break;
+ default:
+ fprintf(stderr,
+ "%s:select %s\n",
+ tstamp(),
+ strerror(errno));
+ kill(ct.get_child_pid(), SIGKILL);
+ scripty_data.sd_looping = false;
+ break;
+ }
+ } else {
+ char buffer[1024];
+
+ fprintf(stderr, "%s:fds ready %d\n", tstamp(), rc);
+ if (FD_ISSET(STDIN_FILENO, &ready_rfds)) {
+ rc = read(STDIN_FILENO, buffer, sizeof(buffer));
+ if (rc < 0) {
+ scripty_data.sd_looping = false;
+ } else if (rc == 0) {
+ FD_CLR(STDIN_FILENO, &read_fds);
+ } else {
+ log_perror(write(ct.get_fd(), buffer, rc));
+
+ for (ssize_t lpc = 0; lpc < rc; lpc++) {
+ fprintf(stderr,
+ "%s:to-child %02x\n",
+ tstamp(),
+ buffer[lpc] & 0xff);
+ tm.new_user_input(buffer[lpc]);
+ }
+ }
+ last = now;
+ }
+ if (FD_ISSET(ct.get_fd(), &ready_rfds)) {
+ rc = read(ct.get_fd(), buffer, sizeof(buffer));
+ fprintf(stderr, "%s:read rc %d\n", tstamp(), rc);
+ if (rc <= 0) {
+ scripty_data.sd_looping = false;
+ } else {
+ if (passout) {
+ log_perror(write(STDOUT_FILENO, buffer, rc));
+ }
+ if (scripty_data.sd_from_child != nullptr) {
+ for (size_t lpc = 0; lpc < rc; lpc++) {
+#if 0
+ fprintf(stderr, "%s:from-child %02x\n",
+ tstamp(),
+ buffer[lpc] & 0xff);
+#endif
+ tm.new_input(buffer[lpc]);
+ if (scripty_data.sd_replay.size()
+ != last_replay_size) {
+ last = now;
+ last_replay_size
+ = scripty_data.sd_replay.size();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ retval = ct.wait_for_child() || retval;
+ }
+
+ if (retval == EXIT_SUCCESS && !scripty_data.sd_expected_name.empty()) {
+ auto cmd = fmt::format("diff -ua {} {}",
+ scripty_data.sd_expected_name.string(),
+ scripty_data.sd_actual_name.string());
+ auto rc = system(cmd.c_str());
+ if (rc != 0) {
+ if (prompt) {
+ char resp[4];
+
+ printf("Would you like to update the original file? (y/N) ");
+ fflush(stdout);
+ log_perror(scanf("%3s", resp));
+ if (strcasecmp(resp, "y") == 0) {
+ printf("Updating: %s -> %s\n",
+ scripty_data.sd_actual_name.c_str(),
+ scripty_data.sd_expected_name.c_str());
+
+ auto options
+ = ghc::filesystem::copy_options::overwrite_existing;
+ ghc::filesystem::copy_file(scripty_data.sd_actual_name,
+ scripty_data.sd_expected_name,
+ options);
+ } else {
+ retval = EXIT_FAILURE;
+ }
+ } else {
+ fprintf(stderr, "%s:error: mismatch\n", tstamp());
+ retval = EXIT_FAILURE;
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/test/si_test.cc b/test/si_test.cc
new file mode 100644
index 0000000..f6b89b3
--- /dev/null
+++ b/test/si_test.cc
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "strong_int.hh"
+
+class __dsi1_distinct;
+typedef strong_int<int, __dsi1_distinct> dsi1_t;
+class __dsi2_distinct;
+typedef strong_int<int, __dsi2_distinct> dsi2_t;
+
+STRONG_INT_TYPE(int, dsi3);
+
+int
+main(int argc, char* argv[])
+{
+ dsi1_t dsi1(0);
+ dsi2_t dsi2(1);
+ dsi3_t dsi3(2);
+
+ printf("%d\n", sizeof(dsi1));
+}
diff --git a/test/slicer.cc b/test/slicer.cc
new file mode 100644
index 0000000..a44c5bf
--- /dev/null
+++ b/test/slicer.cc
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+#include <vector>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "line_buffer.hh"
+
+using namespace std;
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ vector<file_range> index;
+ auto_fd fd;
+
+ if (argc < 2) {
+ fprintf(stderr, "error: expecting file argument\n");
+ retval = EXIT_FAILURE;
+ } else if ((fd = open(argv[1], O_RDONLY)) == -1) {
+ perror("open");
+ retval = EXIT_FAILURE;
+ } else {
+ int line_number, start, end;
+ line_buffer lb;
+ file_range range;
+
+ lb.set_fd(fd);
+ while (true) {
+ auto load_result = lb.load_next_line(range);
+
+ if (load_result.isErr()) {
+ return EXIT_FAILURE;
+ }
+
+ auto li = load_result.unwrap();
+
+ if (li.li_file_range.empty()) {
+ break;
+ }
+
+ index.emplace_back(li.li_file_range);
+
+ range = li.li_file_range;
+ }
+
+ try {
+ while (scanf("%d:%d:%d", &line_number, &start, &end) == 3) {
+ range = index[line_number];
+ auto read_result = lb.read_range(range);
+
+ if (read_result.isErr()) {
+ return EXIT_FAILURE;
+ }
+
+ auto str = to_string(read_result.unwrap());
+
+ str = str.substr(start, end - start);
+ printf("%s\n", str.c_str());
+ }
+ } catch (line_buffer::error& e) {
+ fprintf(stderr, "error: line buffer %s\n", strerror(e.e_err));
+ }
+ }
+ return retval;
+}
diff --git a/test/sql.0.in b/test/sql.0.in
new file mode 100644
index 0000000..e72339b
--- /dev/null
+++ b/test/sql.0.in
@@ -0,0 +1,6 @@
+sleep 0.913123
+write 3b
+sleep 0.822303
+write 73656c656374202a2066726f6d20706572736f6e206f726465722062792061676520646573633b0d
+sleep 9.068423
+write 71
diff --git a/test/sql.0.out b/test/sql.0.out
new file mode 100644
index 0000000..c0f0bbb
--- /dev/null
+++ b/test/sql.0.out
@@ -0,0 +1,7 @@
+read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b3f313030306c1b5b3f313030326c1b5b3f31681b3d1b5b6d1b5b6d1b5b33376d1b5b34306d1b5b313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32343b3148202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200820081b5b3468651b5b346c1b5b481b5b33306d1b5b34376d20546875204a756e2030362031323a31333a32302050445420202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32333b31482020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b33316d1b5b34376d202020201b5b33306d1b5b34376d3f3a566965772048656c702020201b5b316d201b5b6d1b5b33306d1b5b34376d202020202020202020202020202020201b5b32343b3332481b5b6d1b5b6d1b5b33376d1b5b34306d652f453a204d6f766520666f72776172642f6261636b77617264207468726f756768206572726f72206d6573736167650873081b5b3468651b5b346c0d1b5b411b5b431b5b33306d1b5b34376d4c301b5b32333b31354830251b5b32333b34334830570d1b5b31421b5b6d1b5b6d1b5b33376d1b5b34306d
+# write 3b
+read 1b5b32343b3332482020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200820081b5b3468201b5b346c0d1b5b373943081b5b6d1b5b33376d1b5b34306d1b5b376d20081b5b34681b5b6d1b5b6d1b5b33376d1b5b34306d201b5b346c0d3b
+# write 73656c656374202a2066726f6d20706572736f6e206f726465722062792061676520646573633b0d
+read 73656c656374202a2066726f6d20706572736f6e206f726465722062792061676520646573630d1b5b3232411b5b4d1b5b323242202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200820081b5b3468201b5b346c1b5b32333b3430483b1b5b333943201b5b32343b383048081b5b6d1b5b33376d1b5b34306d1b5b376d20081b5b34681b5b6d1b5b6d1b5b33376d1b5b34306d201b5b346c0d1b5b411b5b3231411b5b6d1b5b33376d1b5b34306d1b5b346d69642066697273745f6e616d65206c6173745f6e616d65201b5b33346d1b5b34306d616765201b5b6d1b5b33376d1b5b34306d1b5b316d2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b333b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b343b31481b5b33346d1b5b34376d20311b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33346d1b5b34376d1b5b376d4c656d202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33346d1b5b34376d1b5b376d4865776974742020201b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33346d1b5b34376d1b5b376d203335202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b33376d1b5b34306d201b5b353b31481b5b33346d1b5b34376d201b5b6d1b5b33376d1b5b34306d301b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33376d1b5b34306d5068696c2020202020201b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33376d1b5b34306d4d796d616e202020201b5b6d1b5b6d1b5b33376d1b5b34306d0e780f1b5b33376d1b5b34306d203330202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b363b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b373b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b383b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b393b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b31303b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b31313b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b31323b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b31333b31481b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b6d1b5b33376d1b5b34306d1b5b376d201b5b31343b383048201b5b31353b383048201b5b31363b383048201b5b31373b383048201b5b31383b383048201b5b31393b383048201b5b32303b383048201b5b32313b383048201b5b32323b31481b5b6d1b5b6d1b5b33376d1b5b34306d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b6d1b5b33376d1b5b34306d1b5b376d201b5b32333b31481b5b6d1b5b33306d1b5b34376d204c302020202020202020203130302520202020202020202020202020202020202020202020202020202020201b5b33316d1b5b34376d202020201b5b33306d1b5b34376d3f3a566965772048656c702020201b5b316d201b5b6d1b5b33306d1b5b34376d202020202020202020202020202020201b5b32343b31481b5b6d1b5b6d1b5b33376d1b5b34306d3220726f77287329206d6174636865641b5b3633430820081b5b3468201b5b346c0d
+# write 71
+read 1b5b3f313030306c1b5b3f313030326c1b5b6d1b5b4b1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e
diff --git a/test/test_abbrev.cc b/test/test_abbrev.cc
new file mode 100644
index 0000000..81f62f9
--- /dev/null
+++ b/test/test_abbrev.cc
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2016, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+
+#include "base/string_util.hh"
+#include "config.h"
+
+static struct test_data {
+ const char* str{nullptr};
+ const char* abbrev_str{nullptr};
+ size_t max_len{0};
+} TEST_DATA[] = {
+ {"abc", "abc", 5},
+ {"com.example.foo.bar", "c.e.f.bar", 5},
+ {"com.example.foo.bar", "c.e.foo.bar", 15},
+ {"no dots in here", "no dots in here", 5},
+};
+
+int
+main(int argc, char* argv[])
+{
+ for (const auto& td : TEST_DATA) {
+ char buffer[1024];
+
+ strcpy(buffer, td.str);
+ size_t actual = abbreviate_str(buffer, strlen(td.str), td.max_len);
+ buffer[actual] = '\0';
+
+ printf("orig: %s\n", td.str);
+ printf(" act: %s\n", buffer);
+ assert(strcmp(buffer, td.abbrev_str) == 0);
+ }
+}
diff --git a/test/test_ansi_scrubber.cc b/test/test_ansi_scrubber.cc
new file mode 100644
index 0000000..5371a31
--- /dev/null
+++ b/test/test_ansi_scrubber.cc
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2013, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @file test_ansi_scrubber.cc
+ *
+ * Test for the scrub_ansi_string function.
+ *
+ * TODO: Add a test for the ansi-colors.0.in file. It has a matrix of all the
+ * color/style combinations.
+ */
+
+#include <assert.h>
+
+#include "base/ansi_scrubber.hh"
+#include "config.h"
+#include "view_curses.hh"
+
+using namespace std;
+
+int
+main(int argc, char* argv[])
+{
+ {
+ char input[] = "Hello, \x1b[33;mWorld\x1b[0;m!";
+
+ auto new_len = erase_ansi_escapes(string_fragment::from_const(input));
+
+ printf("result '%s'\n", input);
+
+ assert(new_len == 13);
+ }
+
+ {
+ std::string boldish
+ = "\u2022\b\u2022\u2023\b\u2023 h\bhe\bel\blo\bo _\ba_\bb_\bc a\b_ "
+ "b";
+ auto boldish2 = boldish;
+ string_attrs_t sa;
+
+ sa.clear();
+ scrub_ansi_string(boldish, &sa);
+ printf("boldish %s\n", boldish.c_str());
+ assert(boldish == "\u2022\u2023 helo abc a b");
+
+ auto new_len = erase_ansi_escapes(boldish2);
+ boldish2.resize(new_len);
+ printf("boldish2 %s\n", boldish2.c_str());
+ assert(boldish2 == "\u2022\u2023 helo abc a b");
+
+ for (const auto& attr : sa) {
+ printf("attr %d:%d %s\n",
+ attr.sa_range.lr_start,
+ attr.sa_range.lr_end,
+ attr.sa_type->sat_name);
+ if (attr.sa_type == &SA_ORIGIN_OFFSET) {
+ printf(" value: %d\n", attr.sa_value.get<int64_t>());
+ }
+ }
+ }
+
+ string_attrs_t sa;
+ string str_cp;
+
+ str_cp = "Hello, World!";
+ scrub_ansi_string(str_cp, &sa);
+
+ assert(str_cp == "Hello, World!");
+ assert(sa.empty());
+
+ str_cp = "Hello\x1b[44;m, \x1b[33;mWorld\x1b[0;m!";
+ scrub_ansi_string(str_cp, &sa);
+ assert(str_cp == "Hello, World!");
+}
diff --git a/test/test_auto_fd.cc b/test/test_auto_fd.cc
new file mode 100644
index 0000000..ab45490
--- /dev/null
+++ b/test/test_auto_fd.cc
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "base/auto_fd.hh"
+#include "config.h"
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_fd fd1, fd2;
+ int tmp;
+
+ assert(fd1 == -1);
+ tmp = open("/dev/null", O_RDONLY);
+ assert(tmp != -1);
+ fd1 = tmp;
+ fd1 = tmp;
+ assert(fcntl(tmp, F_GETFL) >= 0);
+ fd1 = std::move(fd2);
+ assert(fcntl(tmp, F_GETFL) == -1);
+ assert(errno == EBADF);
+ assert(fd1 == -1);
+
+ tmp = open("/dev/null", O_RDONLY);
+ assert(tmp != -1);
+ fd1 = tmp;
+ *fd1.out() = STDOUT_FILENO;
+ assert(fcntl(tmp, F_GETFL) == -1);
+ assert(errno == EBADF);
+
+ {
+ auto_fd fd_cp(fd1.dup());
+
+ assert(fd1 == STDOUT_FILENO);
+ assert(fd_cp != STDOUT_FILENO);
+ assert(fd_cp != -1);
+
+ tmp = (int) fd_cp;
+ }
+ {
+ auto_fd fd_cp(fd1.dup());
+
+ assert(fd_cp == tmp);
+ }
+ assert(fd1.release() == STDOUT_FILENO);
+ assert(fd1 == -1);
+
+ return retval;
+}
diff --git a/test/test_auto_mem.cc b/test/test_auto_mem.cc
new file mode 100644
index 0000000..d6f0b55
--- /dev/null
+++ b/test/test_auto_mem.cc
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "base/auto_mem.hh"
+#include "config.h"
+
+struct my_data {
+ int dummy1;
+ int dummy2;
+};
+
+int free_count;
+void* last_free;
+
+void
+my_free(void* mem)
+{
+ free_count += 1;
+ last_free = mem;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+ auto_mem<struct my_data, my_free> md1, md2;
+ struct my_data md1_val, md2_val;
+
+ md1 = &md1_val;
+ assert(free_count == 0);
+ md1 = std::move(md2);
+ assert(free_count == 1);
+ assert(last_free == &md1_val);
+ assert(md1 == NULL);
+
+ md1 = &md2_val;
+ assert(free_count == 1);
+ assert(last_free == &md1_val);
+ *md1.out() = &md1_val;
+ assert(free_count == 2);
+ assert(last_free == &md2_val);
+ assert(md1.in() == &md1_val);
+
+ {
+ auto_mem<struct my_data, my_free> md_cp(std::move(md1));
+
+ assert(md1 == NULL);
+ assert(free_count == 2);
+ assert(md_cp == &md1_val);
+ }
+
+ assert(free_count == 3);
+ assert(last_free == &md1_val);
+
+ {
+ static const char* msg = "Hello, World!\nGoodbye, World!\nTest";
+
+ auto buf = auto_buffer::from(msg, strlen(msg));
+ auto first_lf = std::find(buf.begin(), buf.end(), '\n');
+ auto last_lf = std::find(buf.rbegin(), buf.rend(), '\n');
+
+ assert(std::distance(buf.begin(), first_lf) == 13);
+ assert(*first_lf == '\n');
+ assert(*last_lf == '\n');
+ auto last_lf_index = std::distance(last_lf, buf.rend()) - 1;
+ auto* last_lf_rchr = strrchr(msg, '\n');
+ assert(last_lf_index == (last_lf_rchr - msg));
+ }
+
+ {
+ auto bitmap = auto_buffer::alloc_bitmap(15);
+
+ assert(bitmap.capacity() == 2);
+ bitmap.resize_bitmap(15);
+ assert(bitmap.size() == 2);
+
+ memset(bitmap.in(), 0, bitmap.size());
+ for (size_t lpc = 0; lpc < 15; lpc++) {
+ assert(!bitmap.is_bit_set(lpc));
+ }
+ }
+
+ return retval;
+}
diff --git a/test/test_bookmarks.cc b/test/test_bookmarks.cc
new file mode 100644
index 0000000..37ae86e
--- /dev/null
+++ b/test/test_bookmarks.cc
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bookmarks.hh"
+#include "config.h"
+#include "textview_curses.hh"
+
+int
+main(int argc, char* argv[])
+{
+ int lpc, retval = EXIT_SUCCESS;
+ bookmark_vector<vis_line_t> bv, bv_cp;
+
+ bv.insert_once(vis_line_t(2));
+ bv.insert_once(vis_line_t(2));
+ assert(bv.size() == 1);
+
+ bv.insert_once(vis_line_t(4));
+ bv.insert_once(vis_line_t(3));
+ assert(bv[0] == 2);
+ assert(bv[1] == 3);
+ assert(bv[2] == 4);
+
+ {
+ auto range = bv.equal_range(0_vl, 5_vl);
+
+ assert(range.first != range.second);
+ assert(*range.first == 2_vl);
+ ++range.first;
+ assert(range.first != range.second);
+ assert(*range.first == 3_vl);
+ ++range.first;
+ assert(range.first != range.second);
+ assert(*range.first == 4_vl);
+ ++range.first;
+ assert(range.first == range.second);
+ }
+
+ {
+ auto range = bv.equal_range(0_vl, 1_vl);
+
+ assert(range.first == range.second);
+ }
+
+ {
+ auto range = bv.equal_range(10_vl, 10_vl);
+
+ assert(range.first == range.second);
+ }
+
+ bv.clear();
+ assert(!bv.next(vis_line_t(0)));
+ assert(!bv.prev(vis_line_t(0)));
+ assert(!bv.next(vis_line_t(100)));
+ assert(!bv.prev(vis_line_t(100)));
+
+ bv.insert_once(vis_line_t(2));
+
+ assert(bv.next(vis_line_t(0)).value() == 2);
+ assert(!bv.next(vis_line_t(2)));
+ assert(!bv.next(vis_line_t(3)));
+
+ assert(bv.prev(vis_line_t(3)).value() == 2);
+ assert(!bv.prev(vis_line_t(2)));
+
+ bv.insert_once(vis_line_t(4));
+
+ assert(bv.next(vis_line_t(0)).value() == 2);
+ assert(bv.next(vis_line_t(2)).value() == 4);
+ assert(bv.next(vis_line_t(3)).value() == 4);
+ assert(!bv.next(vis_line_t(4)));
+
+ assert(bv.prev(vis_line_t(10)).value() == 4);
+ assert(bv.prev(vis_line_t(5)).value() == 4);
+ assert(bv.prev(vis_line_t(4)).value() == 2);
+ assert(!bv.prev(vis_line_t(2)));
+
+ bv.clear();
+
+ const int LINE_COUNT = 10000;
+
+ for (lpc = 0; lpc < 1000; lpc++) {
+ bv.insert_once(vis_line_t(random() % LINE_COUNT));
+ }
+ bv_cp = bv;
+ sort(bv_cp.begin(), bv_cp.end());
+ assert(equal(bv.begin(), bv.end(), bv_cp.begin()));
+ unique(bv_cp.begin(), bv_cp.end());
+ assert(equal(bv.begin(), bv.end(), bv_cp.begin()));
+
+ {
+ vis_line_t last_line(-1);
+
+ for (lpc = 0; lpc != -1; lpc = bv.next(vis_line_t(lpc)).value_or(-1_vl))
+ {
+ assert(lpc >= 0);
+ assert(lpc < LINE_COUNT);
+ assert(last_line < lpc);
+
+ last_line = vis_line_t(lpc);
+ }
+
+ last_line = vis_line_t(10000);
+ for (lpc = LINE_COUNT - 1; lpc != -1;
+ lpc = bv.prev(vis_line_t(lpc)).value_or(-1_vl))
+ {
+ assert(lpc >= 0);
+ assert(lpc < LINE_COUNT);
+ assert(last_line > lpc);
+
+ last_line = vis_line_t(lpc);
+ }
+ }
+
+ return retval;
+}
diff --git a/test/test_cli.sh b/test/test_cli.sh
new file mode 100644
index 0000000..be773f5
--- /dev/null
+++ b/test/test_cli.sh
@@ -0,0 +1,31 @@
+#! /bin/bash
+
+export TZ="UTC"
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n -c 'foo'
+
+run_cap_test ${lnav_test} -d /tmp/lnav.err -t -n <<EOF
+Hello, World!
+Goodbye, World!
+EOF
+
+mkdir -p nested/sub1/sub2
+echo "2021-07-03T21:49:29 Test" > nested/sub1/sub2/test.log
+
+run_cap_test ${lnav_test} -nr nested
+
+printf "a\ba _\ba a\b_" | run_cap_test env TEST_COMMENT="overstrike bold" \
+ ${lnav_test} -n
+
+{
+ echo "This is the start of a file with long lines"
+ ${lnav_test} -nN \
+ -c ";select replicate('abcd', 2 * 1024 * 1024)" -c ':write-raw-to -'
+ echo "abcd"
+ echo "Goodbye"
+} > textfile_long_lines.0
+
+grep abcd textfile_long_lines.0 | run_cap_test \
+ ${lnav_test} -n -d /tmp/lnav.err \
+ -c ';SELECT filepath, lines FROM lnav_file'
diff --git a/test/test_cmds.sh b/test/test_cmds.sh
new file mode 100644
index 0000000..1bcbc00
--- /dev/null
+++ b/test/test_cmds.sh
@@ -0,0 +1,515 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view help" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -c ":goto 2011-11-03 00:19:39" \
+ -c ";SELECT log_top_line()" \
+ ${test_dir}/logfile_bro_http.log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":mark" \
+ -c ":hide-unmarked-lines" \
+ -c ":goto 0" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":unix-time" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n \
+ -c ":unix-time abc" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -c ":unix-time 1612072409" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -c ":current-time" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":write-to" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ";SELECT 1 AS c1, 'Hello ' || char(10) || 'World!' AS c2" \
+ -c ":write-csv-to -" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ";SELECT 1 AS c1, 'Hello, World!' AS c2" \
+ -c ":write-table-to -" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ";SELECT 1 AS c1, 'Hello, World!' AS c2" \
+ -c ":write-raw-to -" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":write-view-to -" \
+ "${test_dir}/logfile_access_log.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":write-view-to --anonymize -" \
+ "${test_dir}/logfile_access_log.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":write-view-to --anonymize -" \
+ "${test_dir}/logfile_pretty.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-expr timeslice(:log_time_msecs, 'bad') is not null" \
+ "${test_dir}/logfile_multiline.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-expr :log_text LIKE '%How are%'" \
+ "${test_dir}/logfile_multiline.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-expr not json_contains(:log_tags, '#bad')" \
+ -c ":goto 0" \
+ -c ":tag #bad" \
+ "${test_dir}/logfile_access_log.0"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-expr :sc_bytes > 2000" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-expr :sc_bytes # ff" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":goto 0" \
+ -c ":close" \
+ -c ":goto 0" \
+ "${test_dir}/logfile_access_log.*"
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":goto 0" \
+ -c ":hide-file" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":goto 0" \
+ -c ":next-mark error" \
+ -c ":prev-location" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":goto 0" \
+ -c ":next-mark error" \
+ -c ":prev-location" \
+ -c ":next-location" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-in vmk" \
+ -c ":disable-filter vmk" \
+ -c ":goto 0" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":filter-in vmk" \
+ -c ":rebuild" \
+ -c ":reset-session" \
+ -c ":rebuild" \
+ -c ":goto 0" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":goto 0" \
+ -c ":filter-out vmk" \
+ -c ":toggle-filtering" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-fields foobar" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-fields cs_uri_stem" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-fields access_log.c_ip access_log.cs_uri_stem" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -f- -n < ${test_dir}/formats/scripts/multiline-echo.lnav
+
+run_cap_test ${lnav_test} -n \
+ -c ":config /bad/option" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -nvq \
+ -c ":config /ui/clock-format" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -nv \
+ -c ":config /ui/clock-format" \
+ -c ":config /ui/clock-format abc" \
+ -c ":config /ui/clock-format" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -nv \
+ -c ":config /ui/clock-format abc" \
+ -c ":reset-config /ui/clock-format" \
+ -c ":config /ui/clock-format" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c "|${test_dir}/toplevel.lnav 123 456 789" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -f "nonexistent.lnav" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":adjust-log-time 2010-01-01T00:00:00" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":adjust-log-time -1h" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ':goto 2022-06-16Tabc' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto -1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":goto 2 hours later" \
+ ${test_dir}/logfile_syslog_with_mixed_times.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":goto 3:45" \
+ ${test_dir}/logfile_syslog_with_mixed_times.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto invalid" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":relative-goto -1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":next-mark error" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto -1" \
+ -c ":prev-mark error" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":next-mark foobar" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-in vmk" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-in vmk" \
+ -c ":reset-session" \
+ -c ":filter-in cgi" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-in today" \
+ ${test_dir}/logfile_multiline.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-out vmk" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-out today" \
+ ${test_dir}/logfile_multiline.0
+
+cp ${test_dir}/logfile_multiline.0 logfile_append.0
+chmod ug+w logfile_append.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";update generic_log set log_mark=1" \
+ -c ":filter-in Goodbye" \
+ -c ":append-to logfile_append.0" \
+ -c ":rebuild" \
+ logfile_append.0
+
+cp ${test_dir}/logfile_multiline.0 logfile_append.0
+chmod ug+w logfile_append.0
+
+run_cap_test ${lnav_test} -n -d /tmp/lnav-search.err \
+ -c "/goodbye" \
+ -c ";update generic_log set log_mark=1" \
+ -c ":filter-in Goodbye" \
+ -c ":append-to logfile_append.0" \
+ -c ":rebuild" \
+ -c ":next-mark search" \
+ logfile_append.0
+
+cp ${test_dir}/logfile_multiline.0 logfile_append.0
+chmod ug+w logfile_append.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-out Goodbye" \
+ -c ":shexec echo '2009-07-20 22:59:30,221:ERROR:Goodbye, World!' >> logfile_append.0" \
+ -c ":rebuild" \
+ logfile_append.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-in avahi" \
+ -c ":delete-filter avahi" \
+ -c ":filter-in avahi" \
+ -c ":filter-in dnsmasq" \
+ ${test_dir}/logfile_filter.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view text" \
+ -c ":filter-in World" \
+ ${test_dir}/logfile_plain.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view text" \
+ -c ":filter-out World" \
+ ${test_dir}/logfile_plain.0
+
+TOO_MANY_FILTERS=""
+for i in `seq 1 32`; do
+ TOO_MANY_FILTERS="$TOO_MANY_FILTERS -c ':filter-out $i'"
+done
+run_cap_test eval ${lnav_test} -d /tmp/lnav.err -n \
+ $TOO_MANY_FILTERS \
+ ${test_dir}/logfile_filter.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":close" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":close" \
+ -c ":close" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":open" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":close" \
+ -c ":open ${test_dir}/logfile_multiline.0" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":close" \
+ -c ":open /non-existent" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":write-screen-to -" \
+ "${test_dir}/logfile_access_log.0"
+
+run_cap_test ${lnav_test} -n \
+ -c ";select * from access_log" \
+ -c ':write-json-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";select * from access_log" \
+ -c ':write-jsonlines-to -' \
+ ${test_dir}/logfile_access_log.0
+
+# By setting the LNAVSECURE mode before executing the command, we will disable
+# the access to the write-json-to command and the output would just be the
+# actual display of select query rather than json output.
+export LNAVSECURE=1
+run_cap_test env TEST_COMMENT="secure mode write test" ${lnav_test} -n \
+ -c ";select * from access_log" \
+ -c ':write-json-to /tmp/bad' \
+ ${test_dir}/logfile_access_log.0
+
+unset LNAVSECURE
+
+run_cap_test ${lnav_test} -n \
+ -c ";update generic_log set log_mark=1" \
+ -c ":pipe-to sed -e 's/World!/Bork!/g' -e 's/2009//g'" \
+ ${test_dir}/logfile_multiline.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":echo Hello, World!" \
+ -c ":goto 2" \
+ -c ":pipe-line-to sed -e 's/World!/Bork!/g' -e 's/2009//g'" \
+ ${test_dir}/logfile_multiline.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":pipe-line-to echo \$cs_uri_stem \$sc_status" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/textfile_json_one_line.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/textfile_json_one_line.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/textfile_quoted_json.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/logfile_vami.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/logfile_pretty.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":set-min-log-level error" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":highlight foobar" \
+ -c ":clear-highlight foobar" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":clear-highlight foobar" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":zoom-to 4-hour" \
+ ${test_dir}/textfile_json_indented.0
+
+cp ${test_dir}/logfile_rollover.1 logfile_rollover.1.live
+chmod ug+w logfile_rollover.1.live
+touch -t 200711030923 logfile_rollover.1.live
+
+run_cap_test ${lnav_test} -n \
+ -c ":shexec echo 'Jan 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt' >> logfile_rollover.1.live" \
+ -c ":rebuild" \
+ -c ":switch-to-view histogram" \
+ -c ":goto 0" \
+ logfile_rollover.1.live
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":goto next year" \
+ logfile_rollover.1.live
+
+touch -t 200711030923 ${srcdir}/logfile_syslog.0
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view histogram" \
+ -c ":zoom-to 4-hour" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view histogram" \
+ -c ":zoom-to 1-day" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-in sudo" \
+ -c ":switch-to-view histogram" \
+ -c ":zoom-to 4-hour" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":mark-expr" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":mark-expr :log_procname lik" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":mark-expr :cs_uri_stem LIKE '%vmk%'" \
+ -c ":write-to -" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 0" \
+ -c ":mark" \
+ -c ":switch-to-view histogram" \
+ ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":zoom-to bad" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -f ${test_dir}/multiline.lnav \
+ ${test_dir}/logfile_access_log.0
+
+printf "Hello, World!" | run_cap_test env TEST_COMMENT="text view" ${lnav_test} -n \
+ -c ":switch-to-view text"
+
+run_cap_test ${lnav_test} -Nnv \
+ -c ":hide-lines-before 2009-07-20T22:59:29" \
+ -c ":hide-lines-before"
+
+run_cap_test ${lnav_test} -Nnv \
+ -c ":hide-lines-after 2009-07-20T22:59:29" \
+ -c ":hide-lines-after"
+
+run_cap_test ${lnav_test} -Nnv \
+ -c ":hide-lines-before 2009-07-20T22:00:29" \
+ -c ":hide-lines-after 2009-07-20T22:59:29" \
+ -c ":hide-lines-before"
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-lines-before 2009-07-20T22:59:29" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-lines-after 2009-07-20T22:59:26" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":hide-lines-after 2009-07-20T22:59:26" \
+ -c ":show-lines-before-and-after" \
+ ${test_dir}/logfile_access_log.0
+
+export XYZ="World"
+
+run_cap_test ${lnav_test} -n \
+ -c ':echo Hello, \$XYZ!' \
+ ${test_dir}/logfile_access_log.0
+
+export XYZ="World"
+
+run_cap_test ${lnav_test} -n \
+ -c ':echo -n Hello, ' \
+ -c ':echo World!' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ':echo Hello, $XYZ!' \
+ ${test_dir}/logfile_access_log.0
diff --git a/test/test_column_namer.cc b/test/test_column_namer.cc
new file mode 100644
index 0000000..7eaece7
--- /dev/null
+++ b/test/test_column_namer.cc
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2022, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+
+#include "config.h"
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "column_namer.hh"
+#include "doctest/doctest.h"
+
+TEST_CASE("column_namer::default")
+{
+ column_namer cn{column_namer::language::SQL};
+
+ auto def_name0 = cn.add_column(string_fragment{});
+ CHECK(def_name0 == "col_0");
+ auto def_name1 = cn.add_column(string_fragment{});
+ CHECK(def_name1 == "col_1");
+}
+
+TEST_CASE("column_namer::no-collision")
+{
+ column_namer cn{column_namer::language::SQL};
+
+ auto name0 = cn.add_column(string_fragment{"abc"});
+ CHECK(name0 == "abc");
+ auto name1 = cn.add_column(string_fragment{"def"});
+ CHECK(name1 == "def");
+}
+
+TEST_CASE("column_namer::collisions")
+{
+ column_namer cn{column_namer::language::SQL};
+
+ auto name0 = cn.add_column(string_fragment{"abc"});
+ CHECK(name0 == "abc");
+ auto name1 = cn.add_column(string_fragment{"abc"});
+ CHECK(name1 == "abc_0");
+ auto name2 = cn.add_column(string_fragment{"abc"});
+ CHECK(name2 == "abc_1");
+}
diff --git a/test/test_config.sh b/test/test_config.sh
new file mode 100755
index 0000000..4722abb
--- /dev/null
+++ b/test/test_config.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+export YES_COLOR=1
+
+export HOME="./test-config"
+export XDG_CONFIG_HOME="./test-config/.config"
+rm -rf ./test-config
+mkdir -p $HOME/.config
+
+# config write global var
+run_cap_test ${lnav_test} -nN \
+ -c ":config /global/foo bar"
+
+# config read global var
+run_cap_test ${lnav_test} -nN \
+ -c ":config /global/foo"
+
+# config bad color
+run_cap_test ${lnav_test} -n \
+ -c ":config /ui/theme-defs/default/styles/text/color #f" \
+ ${test_dir}/logfile_access_log.0
+
+# invalid min-free-space allowed?
+run_cap_test env TMPDIR=tmp ${lnav_test} -n \
+ -c ':config /tuning/archive-manager/min-free-space abc' \
+ ${srcdir}/logfile_syslog.0
+
+# config bad theme
+run_cap_test ${lnav_test} -n \
+ -c ":config /ui/theme baddy" \
+ ${test_dir}/logfile_access_log.0
+
+# config bad theme
+run_cap_test ${lnav_test} -W -n \
+ -I ${test_dir}/bad-config2 \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -nN \
+ -c ":reset-config /bad/path"
diff --git a/test/test_curl.sh b/test/test_curl.sh
new file mode 100644
index 0000000..be3d1cd
--- /dev/null
+++ b/test/test_curl.sh
@@ -0,0 +1,48 @@
+#! /bin/bash
+
+if test x"$SFTP_TEST_URL" == x""; then
+ exit 0
+fi
+
+run_test ${lnav_test} -n \
+ file://${test_dir}/logfile_access_log.0
+
+check_output "file URL is not working" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+EOF
+
+cp ${test_dir}/logfile_access_log.0 curl_access_log.0
+
+run_test ${lnav_test} -n \
+ $SFTP_TEST_URL/`pwd`/curl_access_log.0
+
+check_output "sftp URL is not working" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":poll-now" \
+ -c ":shexec echo foo >> curl_access_log.0" \
+ $SFTP_TEST_URL/`pwd`/curl_access_log.0
+
+check_output "sftp URL is not working" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+foo
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":open $SFTP_TEST_URL/`pwd`/curl_access_log.0" \
+ ${test_dir}/logfile_empty.0
+
+check_output "sftp URL is not working" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+foo
+EOF
diff --git a/test/test_data_parser.sh b/test/test_data_parser.sh
new file mode 100644
index 0000000..26f8163
--- /dev/null
+++ b/test/test_data_parser.sh
@@ -0,0 +1,16 @@
+#! /bin/bash
+
+for fn in ${top_srcdir}/test/datafile_simple.*; do
+ run_test ./drive_data_scanner $fn
+ on_error_fail_with "$fn does not match"
+done
+
+for fn in ${top_srcdir}/test/datafile_xml.*; do
+ run_test ./drive_data_scanner -P $fn
+ on_error_fail_with "$fn does not match"
+done
+
+for fn in ${top_srcdir}/test/log-samples/*.txt; do
+ run_test ./drive_data_scanner -l $fn
+ on_error_fail_with "$fn does not match"
+done
diff --git a/test/test_date_time_scanner.cc b/test/test_date_time_scanner.cc
new file mode 100644
index 0000000..8a85993
--- /dev/null
+++ b/test/test_date_time_scanner.cc
@@ -0,0 +1,192 @@
+/**
+ * Copyright (c) 2014, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <locale.h>
+
+#include "../src/lnav_util.hh"
+#include "base/date_time_scanner.hh"
+#include "config.h"
+
+static const char* GOOD_TIMES[] = {
+ "2017 May 08 Mon 18:57:57.578",
+ "May 01 00:00:01",
+ "May 10 12:00:01",
+ "2014-02-11 16:12:34",
+ "2014-02-11 16:12:34.123",
+ "05/18/2018 12:00:53 PM",
+ "05/18/2018 12:00:53 AM",
+};
+
+static const char* BAD_TIMES[] = {
+ "1-2-3 1:2:3",
+
+ "2013-22-01 12:01:22",
+ "2013-00-01 12:01:22",
+
+ "@4000000043",
+};
+
+int
+main(int argc, char* argv[])
+{
+ setenv("TZ", "UTC", 1);
+
+ for (const auto* good_time : GOOD_TIMES) {
+ date_time_scanner dts;
+ struct timeval tv;
+ struct exttm tm;
+ const char* rc;
+
+ rc = dts.scan(good_time, strlen(good_time), nullptr, &tm, tv);
+ printf("ret %s %p\n", good_time, rc);
+ assert(rc != nullptr);
+
+ char ts[64];
+
+ gmtime_r(&tv.tv_sec, &tm.et_tm);
+ dts.ftime(ts, sizeof(ts), nullptr, tm);
+ printf("orig %s\n", good_time);
+ printf("loop %s\n", ts);
+ assert(strcmp(ts, good_time) == 0);
+ }
+
+ {
+ static const char* OLD_TIME = "05/18/1960 12:00:53 AM";
+ date_time_scanner dts;
+ struct timeval tv;
+ struct exttm tm;
+
+ auto rc = dts.scan(OLD_TIME, strlen(OLD_TIME), nullptr, &tm, tv);
+ assert(rc != nullptr);
+ char ts[64];
+ dts.ftime(ts, sizeof(ts), nullptr, tm);
+ assert(strcmp(ts, "05/18/1980 12:00:53 AM") == 0);
+ }
+
+ {
+ date_time_scanner dts;
+ struct timeval tv;
+
+ dts.convert_to_timeval("@40000000433225833b6e1a8c", -1, nullptr, tv);
+ assert(tv.tv_sec == 1127359865);
+ assert(tv.tv_usec == 997071);
+
+ memset(&tv, 0, sizeof(tv));
+ dts.convert_to_timeval("@4000000043322583", -1, nullptr, tv);
+ assert(tv.tv_sec == 1127359865);
+ assert(tv.tv_usec == 0);
+ }
+
+ for (const auto* bad_time : BAD_TIMES) {
+ date_time_scanner dts;
+ struct timeval tv;
+ struct exttm tm;
+
+ printf("Checking bad time: %s\n", bad_time);
+ assert(dts.scan(bad_time, strlen(bad_time), nullptr, &tm, tv)
+ == nullptr);
+ }
+
+ {
+ const char* en_date = "Jan 1 12:00:00";
+ const char* es_date = " 1/Ene/2014:12:00:00 +0000";
+ struct timeval en_tv, es_tv;
+ struct exttm en_tm, es_tm;
+ date_time_scanner dts;
+
+ if (setlocale(LC_TIME, "es_ES.UTF-8") != nullptr) {
+ assert(dts.scan(en_date, strlen(en_date), nullptr, &en_tm, en_tv)
+ != nullptr);
+ dts.clear();
+ assert(dts.scan(es_date, strlen(es_date), nullptr, &es_tm, es_tv)
+ != nullptr);
+ }
+ }
+
+ {
+ const char* en_date = "Jan 1 12:00:00";
+ const char* fr_date = "août 19 11:08:37";
+ struct timeval en_tv, fr_tv;
+ struct exttm en_tm, fr_tm;
+ date_time_scanner dts;
+
+ if (setlocale(LC_TIME, "fr_FR.UTF-8") != nullptr) {
+ assert(dts.scan(en_date, strlen(en_date), nullptr, &en_tm, en_tv)
+ != nullptr);
+ dts.clear();
+ assert(dts.scan(fr_date, strlen(fr_date), nullptr, &fr_tm, fr_tv)
+ != nullptr);
+ }
+ }
+
+ {
+ const char* ts = "22:46:03.471";
+ const char* fmt[] = {
+ "%H:%M:%S.%L",
+ nullptr,
+ };
+ char buf[64];
+ date_time_scanner dts;
+ struct exttm tm;
+ struct timeval tv;
+
+ const auto* ts_end = dts.scan(ts, strlen(ts), fmt, &tm, tv);
+ assert(ts_end - ts == 12);
+ auto rc = dts.ftime(buf, sizeof(buf), fmt, tm);
+ assert(rc == 12);
+ assert(strcmp(ts, buf) == 0);
+ }
+
+ {
+ const char* epoch_str = "ts 1428721664 ]";
+ struct exttm tm;
+ off_t off = 0;
+
+ memset(&tm, 0, sizeof(tm));
+ bool rc = ptime_fmt("ts %s ]", &tm, epoch_str, off, strlen(epoch_str));
+ assert(rc);
+ assert(tm2sec(&tm.et_tm) == 1428721664);
+ }
+
+ {
+ const char* epoch_str = "ts 60150c93 ]";
+ struct exttm tm;
+ off_t off = 0;
+
+ memset(&tm, 0, sizeof(tm));
+ bool rc = ptime_fmt("ts %q ]", &tm, epoch_str, off, strlen(epoch_str));
+ assert(rc);
+ assert(tm2sec(&tm.et_tm) == 1611992211);
+
+ char buf[32];
+ ftime_fmt(buf, sizeof(buf), "ts %q ]", tm);
+ assert(strcmp(buf, epoch_str) == 0);
+ }
+}
diff --git a/test/test_events.sh b/test/test_events.sh
new file mode 100644
index 0000000..2266c4b
--- /dev/null
+++ b/test/test_events.sh
@@ -0,0 +1,31 @@
+#! /bin/bash
+
+rm -rf events-home
+mkdir -p events-home
+export HOME=events-home
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT json(content) as content FROM lnav_events' \
+ -c ':write-jsonlines-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -nN \
+ -c ':config /log/watch-expressions/http-errors/expr sc_status >= 400 AND bad'
+
+run_cap_test ${lnav_test} -nN \
+ -c ':config /log/watch-expressions/http-errors/expr :sc_status >= 400'
+
+run_cap_test env TEST_COMMENT="watch expression generate detect event" ${lnav_test} -n \
+ -c ';SELECT json(content) as content FROM lnav_events' \
+ -c ':write-jsonlines-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test env TEST_COMMENT="show the configuration" ${lnav_test} -nN \
+ -c ':config /log/watch-expressions'
+
+run_cap_test env TEST_COMMENT="delete the configuration" ${lnav_test} -nN \
+ -c ':reset-config /log/watch-expressions/http-errors/'
+
+run_cap_test env TEST_COMMENT="config should be gone now" ${lnav_test} -nN \
+ -c ':config /log/watch-expressions'
diff --git a/test/test_format_installer.sh b/test/test_format_installer.sh
new file mode 100644
index 0000000..2b94d3d
--- /dev/null
+++ b/test/test_format_installer.sh
@@ -0,0 +1,34 @@
+#! /bin/bash
+
+CONFIG_DIR="${top_builddir}/installer-test-home"
+
+mkdir -p "${CONFIG_DIR}"
+rm -rf "${CONFIG_DIR}/.lnav/formats"
+
+HOME=${CONFIG_DIR}
+unset XDG_CONFIG_HOME
+export HOME
+
+${lnav_test} -i ${srcdir}/formats/jsontest/format.json
+
+if ! test -f ${CONFIG_DIR}/.lnav/formats/installed/test_log.json; then
+ echo "Format not installed correctly?"
+ exit 1
+fi
+
+if test x"${TEST_GIT_INSTALL}" = x""; then
+ # Hitting the git repos frequently is slow/noisy
+ exit 0
+fi
+
+${lnav_test} -i extra
+
+if ! test -f ${CONFIG_DIR}/.lnav/remote-config/remote-config.json; then
+ echo "Remote config not downloaded?"
+ exit 1
+fi
+
+if ! test -d ${CONFIG_DIR}/.lnav/formats/https___github_com_PaulWay_lnav_formats_git; then
+ echo "Third-party repo not downloaded?"
+ exit 1
+fi
diff --git a/test/test_format_loader.sh b/test/test_format_loader.sh
new file mode 100644
index 0000000..e5bb422
--- /dev/null
+++ b/test/test_format_loader.sh
@@ -0,0 +1,17 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -W -C \
+ -I ${test_dir}/bad-config-json
+
+if test x"$HAVE_SQLITE3_ERROR_OFFSET" != x""; then
+ run_cap_test env LC_ALL=C ${lnav_test} -W -C \
+ -I ${test_dir}/bad-config
+fi
+
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ";select * from leveltest_log" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_leveltest.0
diff --git a/test/test_grep_proc.sh b/test/test_grep_proc.sh
new file mode 100644
index 0000000..70b19ba
--- /dev/null
+++ b/test/test_grep_proc.sh
@@ -0,0 +1,57 @@
+#! /bin/bash
+
+cat > gp.dat <<EOF
+Hello, World!
+Goodbye, World?
+EOF
+
+grep_slice() {
+ ./drive_grep_proc "$1" "$2" | ./slicer "$2"
+}
+
+grep_capture() {
+ ./drive_grep_proc "$1" "$2" 1>/dev/null
+}
+
+run_test grep_slice 'Hello' gp.dat
+
+check_output "grep_proc didn't find the right match?" <<EOF
+Hello
+EOF
+
+run_test grep_slice '.*' gp.dat
+
+check_output "grep_proc didn't find all lines?" <<EOF
+Hello, World!
+
+
+Goodbye, World?
+
+
+EOF
+
+run_test grep_slice '\w+,' gp.dat
+
+check_output "grep_proc didn't find the right matches?" <<EOF
+Hello,
+Goodbye,
+EOF
+
+run_test grep_slice '\w+.' gp.dat
+
+check_output "grep_proc didn't find multiple matches?" <<EOF
+Hello,
+World!
+Goodbye,
+World?
+EOF
+
+run_test grep_capture '(\w+), World' gp.dat
+
+check_error_output "grep_proc didn't capture matches?" <<EOF
+0(0:5)Hello
+1(0:7)Goodbye
+EOF
+
+check_output "grep_proc didn't capture matches?" <<EOF
+EOF
diff --git a/test/test_grep_proc2.cc b/test/test_grep_proc2.cc
new file mode 100644
index 0000000..11e9d1c
--- /dev/null
+++ b/test/test_grep_proc2.cc
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "config.h"
+#include "grep_proc.hh"
+#include "vis_line.hh"
+
+using namespace std;
+
+static struct {
+ int l_number;
+ const char* l_value;
+} MS_LINES[] = {
+ {10, ""},
+ {11, ""},
+ {12, ""},
+ {13, ""},
+ {0, ""},
+ {1, ""},
+ {2, ""},
+};
+
+class my_source : public grep_proc_source<vis_line_t> {
+public:
+ my_source() : ms_current_line(0){};
+
+ bool grep_value_for_line(vis_line_t line_number, string& value_out)
+ {
+ bool retval = true;
+
+ assert(line_number == MS_LINES[this->ms_current_line].l_number);
+ value_out = MS_LINES[this->ms_current_line].l_value;
+
+ this->ms_current_line += 1;
+
+ return retval;
+ };
+
+ int ms_current_line;
+};
+
+class my_sleeper_source : public grep_proc_source<vis_line_t> {
+ bool grep_value_for_line(vis_line_t line_number, string& value_out)
+ {
+ sleep(1000);
+ return true;
+ };
+};
+
+class my_sink : public grep_proc_sink<vis_line_t> {
+public:
+ my_sink() : ms_finished(false){};
+
+ void grep_match(grep_proc<vis_line_t>& gp,
+ vis_line_t line,
+ int start,
+ int end){};
+
+ void grep_end(grep_proc<vis_line_t>& gp) { this->ms_finished = true; };
+
+ bool ms_finished;
+};
+
+static void
+looper(grep_proc<vis_line_t>& gp)
+{
+ my_sink msink;
+
+ gp.set_sink(&msink);
+
+ while (!msink.ms_finished) {
+ vector<struct pollfd> pollfds;
+
+ gp.update_poll_set(pollfds);
+ poll(&pollfds[0], pollfds.size(), -1);
+
+ gp.check_poll_set(pollfds);
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+
+ auto code
+ = lnav::pcre2pp::code::from_const("foobar", PCRE2_CASELESS).to_shared();
+
+ auto psuperv = std::make_shared<pollable_supervisor>();
+ {
+ my_source ms;
+ grep_proc<vis_line_t> gp(code, ms, psuperv);
+
+ gp.queue_request(10_vl, 14_vl);
+ gp.queue_request(0_vl, 3_vl);
+ gp.start();
+ looper(gp);
+ }
+
+ {
+ my_sleeper_source mss;
+ grep_proc<vis_line_t>* gp
+ = new grep_proc<vis_line_t>(code, mss, psuperv);
+ int status;
+
+ gp->queue_request();
+ gp->start();
+
+ assert(wait3(&status, WNOHANG, NULL) == 0);
+
+ delete gp;
+
+ assert(wait(&status) == -1);
+ assert(errno == ECHILD);
+ }
+
+ return retval;
+}
diff --git a/test/test_json_format.sh b/test/test_json_format.sh
new file mode 100644
index 0000000..0387387
--- /dev/null
+++ b/test/test_json_format.sh
@@ -0,0 +1,141 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+# journald json log format is not working"
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_journald.json
+
+# json log format is not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_json.json
+
+# json log format is not working"
+run_cap_test ${lnav_test} -n -I ${test_dir} \
+ -c ':switch-to-view pretty' \
+ -c ':switch-to-view log' \
+ -c ':switch-to-view pretty' \
+ ${test_dir}/logfile_json.json
+
+# multi-line-format json log format is not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/log.clog
+
+# log levels not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select * from test_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_json.json
+
+# log levels not working" < ${test_dir}/logfile_jso
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select log_raw_text from test_log' \
+ -c ':write-raw-to -' \
+ ${test_dir}/logfile_json.json
+
+# write-raw-to with json is not working" <
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ':goto 0' \
+ -c ':mark' \
+ -c ':goto 1' \
+ -c ':mark' \
+ -c ':goto 2' \
+ -c ':mark' \
+ -c ':write-raw-to -' \
+ ${test_dir}/log.clog
+
+# json output not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select * from test_log' \
+ -c ':write-json-to -' \
+ ${test_dir}/logfile_json.json
+
+# timestamp-format not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_json2.json
+
+# log levels not working"
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -I ${test_dir} \
+ -c ';select * from json_log2' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_json2.json
+
+# pipe-line-to is not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ":goto 4" \
+ -c ":pipe-line-to sed -e 's/2013//g'" \
+ -c ":switch-to-view text" \
+ ${test_dir}/logfile_json.json
+
+# json log format is not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_nested_json.json
+
+# log levels not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select * from ntest_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_nested_json.json
+
+# pipe-line-to is not working"
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ":goto 4" \
+ -c ":pipe-line-to sed -e 's/2013//g'" \
+ -c ":switch-to-view text" \
+ ${test_dir}/logfile_nested_json.json
+
+# json log3 format is not working"
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_json3.json
+
+# json log3 format is not working"
+run_cap_test env TZ=UTC ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select * from json_log3' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_json3.json
+
+run_cap_test env TZ=America/New_York ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_json3.json
+
+# json log3 format is not working"
+run_cap_test env TZ=America/New_York ${lnav_test} -n \
+ -I ${test_dir} \
+ -c ';select * from json_log3' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_json3.json
+
+# json log format is not working"
+run_cap_test ${lnav_test} -n \
+ -d /tmp/lnav.err \
+ -I ${test_dir} \
+ ${test_dir}/logfile_invalid_json.json
+
+# json log format is not working"
+run_cap_test ${lnav_test} -n \
+ -d /tmp/lnav.err \
+ -I ${test_dir} \
+ ${test_dir}/logfile_invalid_json2.json
+
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_mixed_json2.json
+
+run_cap_test ${lnav_test} -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_json_subsec.json
diff --git a/test/test_line_buffer.sh b/test/test_line_buffer.sh
new file mode 100644
index 0000000..43a2580
--- /dev/null
+++ b/test/test_line_buffer.sh
@@ -0,0 +1,78 @@
+#! /bin/bash
+
+cp ${test_dir}/logfile_access_log.1 logfile_changed.0
+chmod u+w logfile_changed.0
+run_test ${lnav_test} -n \
+ -c ":rebuild" \
+ -c ":shexec head -1 ${test_dir}/logfile_access_log.0 > logfile_changed.0" \
+ -c ":rebuild" \
+ logfile_changed.0
+
+check_error_output "line buffer cache flush" <<EOF
+EOF
+
+check_output "line buffer cache flush is not working" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+EOF
+
+run_test ./drive_line_buffer "${top_srcdir}/src/line_buffer.hh"
+
+check_output "Line buffer output doesn't match input?" < \
+ "${top_srcdir}/src/line_buffer.hh"
+
+run_test ./drive_line_buffer < ${top_srcdir}/src/line_buffer.hh
+
+check_output "Line buffer output doesn't match input from pipe?" < \
+ "${top_srcdir}/src/line_buffer.hh"
+
+cat > lb.dat <<EOF
+1
+2
+3
+4
+5
+EOF
+
+LINE_OFF=`grep -b '4' lb.dat | cut -f 1 -d :`
+
+run_test ./drive_line_buffer -o $LINE_OFF lb.dat
+
+check_output "Seeking in the line buffer doesn't work?" <<EOF
+4
+5
+EOF
+
+run_test ./drive_line_buffer -o 4424 -c 1 ${srcdir}/UTF-8-test.txt
+
+check_output "Invalid UTF is not scrubbed?" <<EOF
+2.1.5 5 bytes (U-00200000): "?????" |
+EOF
+
+cat "${top_srcdir}/src/"*.hh "${top_srcdir}/src/"*.cc > lb-2.dat
+grep -b '$' lb-2.dat | cut -f 1 -d : > lb.index
+
+run_test ./drive_line_buffer -i lb.index -n 10 lb-2.dat
+
+check_output "Random reads don't match input?" <<EOF
+All done
+EOF
+
+gzip -c ${test_dir}/logfile_access_log.1 > lb-double.gz
+gzip -c ${test_dir}/logfile_access_log.1 >> lb-double.gz
+run_test ${lnav_test} -n lb-double.gz
+
+gzip -dc lb-double.gz | \
+ check_output "concatenated gzip files don't parse correctly"
+
+> lb-3.gz
+while test $(wc -c < lb-3.gz) -le 5000000 ; do
+ cat lb-2.dat
+done | gzip -c -1 > lb-3.gz
+gzip -dc lb-3.gz > lb-3.dat
+grep -b '$' lb-3.dat | cut -f 1 -d : > lb-3.index
+
+run_test ./drive_line_buffer -i lb-3.index -n 10 lb-3.gz lb-3.dat
+
+check_output "Random gzipped reads don't match input" <<EOF
+All done
+EOF \ No newline at end of file
diff --git a/test/test_line_buffer2.cc b/test/test_line_buffer2.cc
new file mode 100644
index 0000000..07b9765
--- /dev/null
+++ b/test/test_line_buffer2.cc
@@ -0,0 +1,157 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/auto_fd.hh"
+#include "config.h"
+#include "line_buffer.hh"
+
+using namespace std;
+
+static const char* TEST_DATA
+ = "Hello, World!\n"
+ "Goodbye, World!\n";
+
+static void
+single_line(const char* data)
+{
+ line_buffer lb;
+ auto_fd pi[2];
+ off_t off = 0;
+
+ assert(auto_fd::pipe(pi) == 0);
+ log_perror(write(pi[1], data, strlen(data)));
+ pi[1].reset();
+
+ lb.set_fd(pi[0]);
+ auto load_result = lb.load_next_line({off});
+ auto li = load_result.unwrap();
+ assert(data[strlen(data) - 1] == '\n' || li.li_partial);
+ assert(li.li_file_range.next_offset() == (off_t) strlen(data));
+ assert(li.li_file_range.fr_size == strlen(data));
+
+ auto next_load_result = lb.load_next_line(li.li_file_range);
+ assert(next_load_result.isOk());
+ assert(next_load_result.unwrap().li_file_range.empty());
+ assert(lb.get_file_size() != -1);
+}
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+
+ single_line("Dexter Morgan");
+ single_line("Rudy Morgan\n");
+
+ {
+ char fn_template[] = "test_line_buffer.XXXXXX";
+
+ auto fd = auto_fd(mkstemp(fn_template));
+ remove(fn_template);
+ line_buffer lb;
+
+ write(fd, TEST_DATA, strlen(TEST_DATA));
+ lseek(fd, SEEK_SET, 0);
+
+ lb.set_fd(fd);
+
+ shared_buffer_ref sbr;
+
+ auto result = lb.read_range({0, 1024});
+
+ assert(result.isErr());
+ }
+
+ {
+ static string first = "Hello";
+ static string second = ", World!";
+ static string third = "Goodbye, World!";
+ static string last = "\n";
+
+ line_buffer lb;
+ auto_fd pi[2];
+ off_t off = 0;
+
+ assert(auto_fd::pipe(pi) == 0);
+ log_perror(write(pi[1], first.c_str(), first.size()));
+ fcntl(pi[0], F_SETFL, O_NONBLOCK);
+
+ lb.set_fd(pi[0]);
+ auto load_result = lb.load_next_line({off});
+ auto li = load_result.unwrap();
+ assert(li.li_partial);
+ assert(li.li_file_range.fr_size == 5);
+ log_perror(write(pi[1], second.c_str(), second.size()));
+ auto load_result2 = lb.load_next_line({off});
+ li = load_result2.unwrap();
+ assert(li.li_partial);
+ assert(li.li_file_range.fr_size == 13);
+ log_perror(write(pi[1], last.c_str(), last.size()));
+ auto load_result3 = lb.load_next_line({off});
+ li = load_result3.unwrap();
+ assert(!li.li_partial);
+ assert(li.li_file_range.fr_size == 14);
+ auto load_result4 = lb.load_next_line(li.li_file_range);
+ li = load_result4.unwrap();
+ auto last_range = li.li_file_range;
+ assert(li.li_partial);
+ assert(li.li_file_range.empty());
+ log_perror(write(pi[1], third.c_str(), third.size()));
+ auto load_result5 = lb.load_next_line(last_range);
+ li = load_result5.unwrap();
+ assert(li.li_partial);
+ assert(li.li_file_range.fr_size == 15);
+ log_perror(write(pi[1], last.c_str(), last.size()));
+ auto load_result6 = lb.load_next_line(last_range);
+ li = load_result6.unwrap();
+ assert(!li.li_partial);
+ assert(li.li_file_range.fr_size == 16);
+
+ auto load_result7 = lb.load_next_line(li.li_file_range);
+ li = load_result7.unwrap();
+ assert(li.li_partial);
+ assert(li.li_file_range.empty());
+ assert(!lb.is_pipe_closed());
+
+ pi[1].reset();
+
+ auto load_result8 = lb.load_next_line(li.li_file_range);
+ li = load_result8.unwrap();
+ assert(!li.li_partial);
+ assert(li.li_file_range.empty());
+ assert(lb.is_pipe_closed());
+ }
+
+ return retval;
+}
diff --git a/test/test_listview.sh b/test/test_listview.sh
new file mode 100644
index 0000000..38634da
--- /dev/null
+++ b/test/test_listview.sh
@@ -0,0 +1,36 @@
+#! /bin/bash
+
+run_test ./scripty -n -e ${srcdir}/listview_output.0 -- \
+ ./drive_listview < /dev/null
+
+on_error_fail_with "listview output does not match?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.1 -- \
+ ./drive_listview -t 1 < /dev/null
+
+on_error_fail_with "listview didn't move down?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.2 -- \
+ ./drive_listview -l 1 < /dev/null
+
+on_error_fail_with "Listview didn't move right?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.3 -- \
+ ./drive_listview -t 1 -l 1 < /dev/null
+
+on_error_fail_with "Listview didn't move left and right?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.4 -- \
+ ./drive_listview -y 1 -r 50 < /dev/null
+
+on_error_fail_with "Listview doesn't start down one line?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.5 -- \
+ ./drive_listview -y 1 -r 50 -h -1 < /dev/null
+
+on_error_fail_with "Listview isn't shorter?"
+
+run_test ./scripty -n -e ${srcdir}/listview_output.6 -- \
+ ./drive_listview -y 1 -r 50 -h -1 -t 1 < /dev/null
+
+on_error_fail_with "Listview didn't move down (2)?"
diff --git a/test/test_log_accel.cc b/test/test_log_accel.cc
new file mode 100644
index 0000000..df5625f
--- /dev/null
+++ b/test/test_log_accel.cc
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2014, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+
+#include "config.h"
+#include "log_accel.hh"
+
+static int64_t SIMPLE_TEST_POINTS[] = {90,
+ 80,
+ 40,
+ 30,
+ 20,
+ 10,
+
+ -1};
+
+static log_accel::direction_t SIMPLE_TEST_DIRS[] = {
+ log_accel::A_STEADY,
+ log_accel::A_DECEL,
+ log_accel::A_STEADY,
+ log_accel::A_STEADY,
+ log_accel::A_STEADY,
+ log_accel::A_STEADY,
+ log_accel::A_STEADY,
+};
+
+int
+main(int argc, char* argv[])
+{
+ for (int point = 0; SIMPLE_TEST_POINTS[point] != -1; point++) {
+ log_accel la;
+
+ for (int lpc = point; SIMPLE_TEST_POINTS[lpc] != -1; lpc++) {
+ if (!la.add_point(SIMPLE_TEST_POINTS[lpc])) {
+ break;
+ }
+ }
+
+ assert(SIMPLE_TEST_DIRS[point] == la.get_direction());
+ }
+
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/test/test_logfile.sh b/test/test_logfile.sh
new file mode 100644
index 0000000..16d061b
--- /dev/null
+++ b/test/test_logfile.sh
@@ -0,0 +1,701 @@
+#! /bin/bash
+
+echo ${top_srcdir}
+echo ${top_builddir}
+
+printf '#Date:\t20\x800-2-02\n0\n' | run_cap_test \
+ env TEST_COMMENT="short timestamp" ${lnav_test} -n
+
+printf '000\n000\n#Fields: 0\n0\n#Fields: 0\n0' | run_cap_test \
+ env TEST_COMMENT="invalid w3c log" ${lnav_test} -n
+
+cat > rollover_in.0 <<EOF
+2600/2 0 00:00:00 0:
+00:2 0 00:00:00 0:
+00:2 0 00:00:00 0:
+EOF
+touch -t 200711030923 rollover_in.0
+
+run_cap_test env TEST_COMMENT="invalid date rollover" ${lnav_test} -n rollover_in.0
+
+printf '#Fields: 0\tcs-bytes\n#Fields: 0\n\t0 #\n0' | run_cap_test \
+ env TEST_COMMENT="w3c with dupe #Fields" ${lnav_test} -n
+
+printf '#Fields: \xf9\t)\n0\n' | run_cap_test \
+ env TEST_COMMENT="garbage w3c fields #1" ${lnav_test} -n
+
+run_cap_test env TEST_COMMENT="w3c with bad header" ${lnav_test} -n <<EOF
+#Fields: 0 time
+ 00:00
+#Date:
+EOF
+
+printf '\x2b0\x1b[a' | run_cap_test \
+ env TEST_COMMENT="log line with an ansi escape" ${lnav_test} -n
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT * FROM logline' \
+ ${test_dir}/logfile_block.1
+
+run_test ${lnav_test} -d /tmp/lnav.err -n -w logfile_stdin.0.log \
+ -c ':shexec sleep 1 && touch -t 200711030923 logfile_stdin.0.log' <<EOF
+2013-06-06T19:13:20.123 Hi
+EOF
+
+check_output "piping to stdin is not working?" <<EOF
+2013-06-06T19:13:20.123 Hi
+EOF
+
+if test x"${TSHARK_CMD}" != x""; then
+ run_test env TZ=UTC ${lnav_test} -n ${test_dir}/dhcp.pcapng
+
+ check_output "pcap file is not recognized" <<EOF
+2004-12-05T19:16:24.317 0.0.0.0 → 255.255.255.255 DHCP 314 DHCP Discover - Transaction ID 0x3d1d
+2004-12-05T19:16:24.317 192.168.0.1 → 192.168.0.10 DHCP 342 DHCP Offer - Transaction ID 0x3d1d
+2004-12-05T19:16:24.387 0.0.0.0 → 255.255.255.255 DHCP 314 DHCP Request - Transaction ID 0x3d1e
+2004-12-05T19:16:24.387 192.168.0.1 → 192.168.0.10 DHCP 342 DHCP ACK - Transaction ID 0x3d1e
+EOF
+
+ run_test ${lnav_test} -n ${test_dir}/dhcp-trunc.pcapng
+
+ check_error_output "truncated pcap file is not recognized" <<EOF
+error: unable to open file: {test_dir}/dhcp-trunc.pcapng -- tshark: The file "{test_dir}/dhcp-trunc.pcapng" appears to have been cut short in the middle of a packet.
+EOF
+fi
+
+
+cp ${srcdir}/logfile_syslog.0 truncfile.0
+chmod u+w truncfile.0
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ -c ";update syslog_log set log_mark = 1 where log_line = 1" \
+ -c ":write-to truncfile.0" \
+ -c ":goto 1" \
+ truncfile.0
+
+check_output "truncated log file not detected" <<EOF
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+EOF
+
+
+if locale -a | grep fr_FR; then
+ cp ${srcdir}/logfile_syslog_fr.0 logfile_syslog_fr_test.0
+ touch -t 200711030923 logfile_syslog_fr_test.0
+ run_test env LC_ALL=fr_FR.UTF-8 ${lnav_test} -n \
+ -c ";SELECT log_time FROM syslog_log" \
+ -c ":write-csv-to -" \
+ logfile_syslog_fr_test.0
+
+ check_output "french locale is not recognized" <<EOF
+log_time
+2007-08-19 11:08:37.000
+EOF
+fi
+
+if test x"${LIBARCHIVE_LIBS}" != x""; then
+ run_test env TMPDIR=tmp ${lnav_test} -n \
+ -c ':config /tuning/archive-manager/min-free-space -1' \
+ ${srcdir}/logfile_syslog.0
+
+ check_error_output "invalid min-free-space allowed?" <<EOF
+✘ error: “-1” is not a valid value for option “/tuning/archive-manager/min-free-space”
+ reason: value must be greater than or equal to 0
+ --> input:1
+ = help: Property Synopsis
+ /tuning/archive-manager/min-free-space <bytes>
+ Description
+ The minimum free space, in bytes, to maintain when unpacking archives
+EOF
+
+ rm -rf tmp/lnav-*
+ if test x"${XZ_CMD}" != x""; then
+ ${XZ_CMD} -z -c ${srcdir}/logfile_syslog.1 > logfile_syslog.1.xz
+
+ run_test env TMPDIR=tmp ${lnav_test} -n \
+ -c ':config /tuning/archive-manager/min-free-space 1125899906842624' \
+ -c ':config /tuning/archive-manager/cache-ttl 1d' \
+ ${srcdir}/logfile_syslog.0
+
+ run_test env TMPDIR=tmp ${lnav_test} -d /tmp/lnav.err -n \
+ logfile_syslog.1.xz
+
+ sed -e "s|lnav-user-[0-9]*-work|lnav-user-NNN-work|g" \
+ -e "s|arc-[0-9a-z]*-logfile|arc-NNN-logfile|g" \
+ -e "s|space on disk \(.*\) is|space on disk (NNN) is|g" \
+ -e "s|${builddir}||g" \
+ `test_err_filename` > test_logfile.big.out
+ mv test_logfile.big.out `test_err_filename`
+ check_error_output "decompression worked?" <<EOF
+✘ error: unable to open file: /logfile_syslog.1.xz
+ reason: available space on disk (NNN) is below the minimum-free threshold (1.0PB). Unable to unpack 'logfile_syslog.1.xz' to 'tmp/lnav-user-NNN-work/archives/arc-NNN-logfile_syslog.1.xz'
+EOF
+
+ run_test env TMPDIR=tmp ${lnav_test} -n \
+ -c ':config /tuning/archive-manager/min-free-space 33554432' \
+ ${srcdir}/logfile_syslog.0
+
+ run_test env TMPDIR=tmp ${lnav_test} -n \
+ logfile_syslog.1.xz
+
+ check_output "decompression not working" <<EOF
+Dec 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Dec 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Dec 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Jan 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
+EOF
+ fi
+
+ tar cfz ${builddir}/test-logs.tgz -C ${top_srcdir} test/logfile_access_log.0 test/logfile_access_log.1 test/logfile_empty.0 -C ${builddir}/.. src/lnav
+
+ dd if=test-logs.tgz of=test-logs-trunc.tgz bs=4096 count=20
+
+ mkdir -p tmp
+ run_test env TMPDIR=tmp ${lnav_test} \
+ -c ':config /tuning/archive-manager/cache-ttl 1d' \
+ -n test-logs.tgz
+
+ check_output "archive not unpacked" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
+EOF
+
+ if ! test -f tmp/*/archives/*-test-logs.tgz/test/logfile_access_log.0; then
+ echo "archived file not unpacked"
+ exit 1
+ fi
+
+ if test -w tmp/*/archives/*-test-logs.tgz/test/logfile_access_log.0; then
+ echo "archived file is writable"
+ exit 1
+ fi
+
+ env TMPDIR=tmp ${lnav_test} -d /tmp/lnav.err \
+ -c ':config /tuning/archive-manager/cache-ttl 0d' \
+ -n -q ${srcdir}/logfile_syslog.0
+
+ if test -f tmp/lnav*/archives/*-test-logs.tgz/test/logfile_access_log.0; then
+ echo "archive cache not deleted?"
+ exit 1
+ fi
+
+ run_test env TMPDIR=tmp ${lnav_test} -n\
+ -c ';SELECT view_name, basename(filepath), visible FROM lnav_view_files' \
+ test-logs.tgz
+
+ check_output "archive files not loaded correctly" <<EOF
+view_name basename(filepath) visible
+log logfile_access_log.0 1
+log logfile_access_log.1 1
+EOF
+
+ run_test env TMPDIR=tmp ${lnav_test} -n \
+ test-logs-trunc.tgz
+
+ sed -e "s|${builddir}||g" `test_err_filename` | head -2 \
+ > test_logfile.trunc.out
+ mv test_logfile.trunc.out `test_err_filename`
+ check_error_output "truncated tgz not reported correctly" <<EOF
+✘ error: unable to open file: /test-logs-trunc.tgz
+ reason: failed to extract 'src/lnav' from archive '/test-logs-trunc.tgz' -- truncated gzip input
+EOF
+
+ mkdir -p rotmp
+ chmod ugo-w rotmp
+ run_test env TMPDIR=rotmp ${lnav_test} -n test-logs.tgz
+
+ sed -e "s|lnav-user-[0-9]*-work|lnav-user-NNN-work|g" \
+ -e 's|log\.0 -- .*|log\.0 -- ...|g' \
+ -e "s|arc-[0-9a-z]*-test|arc-NNN-test|g" \
+ -e "s|${builddir}||g" \
+ `test_err_filename` | head -2 \
+ > test_logfile.rotmp.out
+ cp test_logfile.rotmp.out `test_err_filename`
+ check_error_output "archive not unpacked" <<EOF
+✘ error: unable to open file: /test-logs.tgz
+ reason: unable to create directory: rotmp/lnav-user-NNN-work/archives -- Permission denied
+EOF
+fi
+
+touch unreadable.log
+chmod ugo-r unreadable.log
+
+run_test ${lnav_test} -n unreadable.log
+
+sed -e "s|/.*/unreadable.log|unreadable.log|g" `test_err_filename` | head -3 \
+ > test_logfile.unreadable.out
+
+mv test_logfile.unreadable.out `test_err_filename`
+check_error_output "able to read an unreadable log file?" <<EOF
+✘ error: file exists, but is not readable: unreadable.log
+ reason: Permission denied
+EOF
+
+run_test ${lnav_test} -n 'unreadable.*'
+
+check_output "unreadable file was not skipped" <<EOF
+EOF
+
+run_test ./drive_logfile -f syslog_log ${srcdir}/logfile_syslog.0
+
+on_error_fail_with "Didn't infer syslog log format?"
+
+run_test ./drive_logfile -f tcsh_history ${srcdir}/logfile_tcsh_history.0
+
+on_error_fail_with "Didn't infer tcsh-history log format?"
+
+run_test ./drive_logfile -f access_log ${srcdir}/logfile_access_log.0
+
+on_error_fail_with "Didn't infer access_log log format?"
+
+run_test ./drive_logfile -f strace_log ${srcdir}/logfile_strace_log.0
+
+on_error_fail_with "Didn't infer strace_log log format?"
+
+run_test ./drive_logfile -f zblued_log ${srcdir}/logfile_blued.0
+
+on_error_fail_with "Didn't infer blued_log that collides with syslog?"
+
+run_test ./drive_logfile -f bro_http_log ${srcdir}/logfile_bro_http.log.0
+
+on_error_fail_with "Didn't infer bro_http_log log format?"
+
+run_test ./drive_logfile -f bro_conn_log ${srcdir}/logfile_bro_conn.log.0
+
+on_error_fail_with "Didn't infer bro_conn_log log format?"
+
+run_test ./drive_logfile -f w3c_log ${srcdir}/logfile_w3c.0
+
+on_error_fail_with "Didn't infer w3c_log log format?"
+
+
+run_test ./drive_logfile ${srcdir}/logfile_empty.0
+
+on_error_fail_with "Didn't handle empty log?"
+
+
+run_test ./drive_logfile -t -f w3c_log ${srcdir}/logfile_w3c.2
+
+check_output "w3c timestamp interpreted incorrectly?" <<EOF
+Oct 09 16:44:49 2000 -- 000
+Oct 09 16:44:49 2000 -- 000
+Oct 09 16:48:05 2000 -- 000
+Oct 09 16:48:17 2000 -- 000
+Oct 09 16:48:24 2000 -- 000
+Oct 09 16:48:35 2000 -- 000
+Oct 09 16:48:41 2000 -- 000
+Oct 09 16:48:41 2000 -- 000
+Oct 09 16:48:41 2000 -- 000
+Oct 09 16:48:41 2000 -- 000
+Oct 09 16:48:44 2000 -- 000
+Oct 10 16:44:49 2000 -- 000
+Oct 10 16:44:49 2000 -- 000
+Oct 10 16:48:05 2000 -- 000
+EOF
+
+run_test ./drive_logfile -t -f w3c_log ${srcdir}/logfile_w3c.4
+
+check_output "quoted w3c timestamp interpreted incorrectly?" <<EOF
+Jun 28 07:26:35 2017 -- 000
+Jun 26 18:21:17 2017 -- 000
+EOF
+
+cp ${srcdir}/logfile_syslog.0 logfile_syslog_test.0
+touch -t 200711030923 logfile_syslog_test.0
+run_test ./drive_logfile -t -f syslog_log logfile_syslog_test.0
+
+check_output "Syslog timestamp interpreted incorrectly?" <<EOF
+Nov 03 09:23:38 2007 -- 000
+Nov 03 09:23:38 2007 -- 000
+Nov 03 09:23:38 2007 -- 000
+Nov 03 09:47:02 2007 -- 000
+EOF
+
+env TZ=UTC touch -t 200711030923 ${srcdir}/logfile_syslog.1
+run_test ./drive_logfile -t -f syslog_log ${srcdir}/logfile_syslog.1
+
+check_output "Syslog timestamp interpreted incorrectly for year end?" <<EOF
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Jan 03 09:47:02 2007 -- 000
+EOF
+
+touch -t 200711030000 ${srcdir}/logfile_rollover.0
+run_test ./drive_logfile -t -f generic_log ${srcdir}/logfile_rollover.0
+
+check_output "Generic timestamp interpreted incorrectly for day rollover?" <<EOF
+Nov 02 00:00:00 2007 -- 000
+Nov 02 01:00:00 2007 -- 000
+Nov 02 02:00:00 2007 -- 000
+Nov 02 03:00:00 2007 -- 000
+Nov 03 00:00:00 2007 -- 000
+Nov 03 00:01:00 2007 -- 000
+EOF
+
+gzip -c ${srcdir}/logfile_syslog.1 > logfile_syslog.1.gz
+
+run_test ./drive_logfile -t -f syslog_log logfile_syslog.1.gz
+
+check_output "Syslog timestamp incorrect for gzipped file?" <<EOF
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Jan 03 09:47:02 2007 -- 000
+EOF
+
+if [ "$BZIP2_SUPPORT" -eq 1 ] && [ x"$BZIP2_CMD" != x"" ] ; then
+ $BZIP2_CMD -z -c "${srcdir}/logfile_syslog.1" > logfile_syslog.1.bz2
+
+ touch -t 200711030923 logfile_syslog.1.bz2
+ run_test ./drive_logfile -t -f syslog_log logfile_syslog.1.bz2
+
+ check_output "bzip2 file not loaded?" <<EOF
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Dec 03 09:23:38 2006 -- 000
+Jan 03 09:47:02 2007 -- 000
+EOF
+fi
+
+touch -t 201404061109 ${srcdir}/logfile_tcf.1
+run_test ./drive_logfile -t -f tcf_log ${srcdir}/logfile_tcf.1
+
+check_output "TCF timestamp interpreted incorrectly for hour wrap?" <<EOF
+Apr 06 09:59:47 2014 -- 191
+Apr 06 10:30:11 2014 -- 474
+Apr 06 11:01:11 2014 -- 475
+EOF
+
+run_test ${lnav_test} -n ${srcdir}/logfile_tcf.1
+
+check_output "timestamps with no dates are not rewritten?" <<EOF
+TCF 2014-04-06 09:59:47.191000: Server-Properties: {"Name":"TCF Protocol Logger","OSName":"Linux 3.2.0-60-generic","UserName":"xavier","AgentID":"1fde3dd1-d4be-4f79-8090-6f8d212f03bf","TransportName":"TCP","Proxy":"","ValueAdd":"1","Port":"1534"}
+TCF 2014-04-06 10:30:11.474000: 0: ---> C 2 RunControl getChildren null <eom>
+TCF 2014-04-06 11:01:11.475000: 0: <--- R 2 ["P1"] <eom>
+EOF
+
+
+# The TCSH format converts to local time, so we need to specify a TZ
+export TZ="UTC"
+run_test ./drive_logfile -t -f tcsh_history ${srcdir}/logfile_tcsh_history.0
+
+check_output "TCSH timestamp interpreted incorrectly?" <<EOF
+Nov 02 17:59:26 2006 -- 000
+Nov 02 17:59:26 2006 -- 000
+Nov 02 17:59:45 2006 -- 000
+Nov 02 17:59:45 2006 -- 000
+EOF
+
+run_test ./drive_logfile -t -f access_log ${srcdir}/logfile_access_log.0
+
+check_output "access_log timestamp interpreted incorrectly?" <<EOF
+Jul 20 22:59:26 2009 -- 000
+Jul 20 22:59:29 2009 -- 000
+Jul 20 22:59:29 2009 -- 000
+EOF
+
+run_test ./drive_logfile -t -f generic_log ${srcdir}/logfile_tai64n.0
+
+check_output "tai64n timestamps interpreted incorrectly?" <<EOF
+Sep 22 03:31:05 2005 -- 997
+Sep 22 03:31:05 2005 -- 997
+Sep 22 03:31:06 2005 -- 210
+Sep 22 03:31:06 2005 -- 210
+Sep 22 03:31:07 2005 -- 714
+Sep 22 03:31:07 2005 -- 714
+Sep 22 03:31:07 2005 -- 715
+Sep 22 03:31:07 2005 -- 715
+Sep 22 03:31:07 2005 -- 954
+Sep 22 03:31:07 2005 -- 954
+EOF
+
+touch -t 200711030923 ${srcdir}/logfile_strace_log.0
+run_test ./drive_logfile -t -f strace_log ${srcdir}/logfile_strace_log.0
+
+check_output "strace_log timestamp interpreted incorrectly?" <<EOF
+Nov 03 08:09:33 2007 -- 814
+Nov 03 08:09:33 2007 -- 815
+Nov 03 08:09:33 2007 -- 815
+Nov 03 08:09:33 2007 -- 815
+Nov 03 08:09:33 2007 -- 816
+Nov 03 08:09:33 2007 -- 816
+Nov 03 08:09:33 2007 -- 816
+Nov 03 08:09:33 2007 -- 816
+Nov 03 08:09:33 2007 -- 816
+EOF
+
+
+run_test ./drive_logfile -t -f epoch_log ${srcdir}/logfile_epoch.0
+
+check_output "epoch_log timestamp interpreted incorrectly?" <<EOF
+Apr 10 02:58:07 2015 -- 123
+Apr 10 02:58:07 2015 -- 456
+EOF
+
+
+run_test ./drive_logfile -t -f epoch_log ${srcdir}/logfile_epoch.1
+
+check_error_output "epoch" <<EOF
+EOF
+
+check_output "epoch_log timestamp interpreted incorrectly?" <<EOF
+Apr 09 19:58:07 2015 -- 123
+Apr 09 19:58:07 2015 -- 456
+EOF
+
+
+touch -t 201509130923 ${srcdir}/logfile_syslog_with_mixed_times.0
+run_test ./drive_logfile -t -f syslog_log ${srcdir}/logfile_syslog_with_mixed_times.0
+
+check_output "syslog_log with mixed times interpreted incorrectly?" <<EOF
+Sep 13 00:58:45 2015 -- 000
+Sep 13 00:59:30 2015 -- 000
+Sep 13 01:23:54 2015 -- 000
+Sep 13 03:12:04 2015 -- 000
+Sep 13 03:12:04 2015 -- 000
+Sep 13 03:12:04 2015 -- 000
+Sep 13 03:12:04 2015 -- 000
+Sep 13 03:12:58 2015 -- 000
+Sep 13 03:46:03 2015 -- 000
+Sep 13 03:46:03 2015 -- 000
+Sep 13 03:46:03 2015 -- 000
+Sep 13 03:46:03 2015 -- 000
+Sep 13 03:46:03 2015 -- 000
+EOF
+
+
+##
+
+run_test ./drive_logfile -v -f syslog_log ${srcdir}/logfile_syslog.0
+
+check_output "Syslog level interpreted incorrectly?" <<EOF
+error 0x0
+info 0x0
+error 0x0
+info 0x0
+EOF
+
+run_test ./drive_logfile -v -f tcsh_history ${srcdir}/logfile_tcsh_history.0
+
+check_output "TCSH level interpreted incorrectly?" <<EOF
+info 0x0
+info 0x80
+info 0x0
+info 0x80
+EOF
+
+run_test ./drive_logfile -v -f access_log ${srcdir}/logfile_access_log.0
+
+check_output "access_log level interpreted incorrectly?" <<EOF
+info 0x0
+error 0x0
+info 0x0
+EOF
+
+run_test ./drive_logfile -v -f strace_log ${srcdir}/logfile_strace_log.0
+
+check_output "strace_log level interpreted incorrectly?" <<EOF
+info 0x0
+info 0x0
+info 0x0
+error 0x0
+info 0x0
+error 0x0
+info 0x0
+info 0x0
+info 0x0
+EOF
+
+run_test ./drive_logfile -t -f generic_log ${srcdir}/logfile_generic.0
+
+check_output "generic_log timestamp interpreted incorrectly?" <<EOF
+Jul 02 10:22:40 2012 -- 672
+Oct 08 16:56:38 2014 -- 344
+EOF
+
+run_test ./drive_logfile -t -f generic_log ${srcdir}/logfile_generic.3
+
+check_output "generic_log timestamp interpreted incorrectly?" <<EOF
+Jul 02 10:22:40 2012 -- 672
+Oct 08 16:56:38 2014 -- 344
+EOF
+
+run_test ./drive_logfile -v -f generic_log ${srcdir}/logfile_generic.0
+
+check_output "generic_log level interpreted incorrectly?" <<EOF
+debug 0x0
+warning 0x0
+EOF
+
+run_test ./drive_logfile -v -f generic_log ${srcdir}/logfile_generic.1
+
+check_output "generic_log (1) level interpreted incorrectly?" <<EOF
+info 0x0
+error 0x0
+EOF
+
+run_test ./drive_logfile -v -f generic_log ${srcdir}/logfile_generic.2
+
+check_output "generic_log (2) level interpreted incorrectly?" <<EOF
+error 0x0
+error 0x0
+EOF
+
+touch -t 200711030923 ${srcdir}/logfile_glog.0
+run_test ./drive_logfile -t -f glog_log ${srcdir}/logfile_glog.0
+
+check_output "glog_log timestamp interpreted incorrectly?" <<EOF
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+May 17 15:04:22 2007 -- 619
+EOF
+
+run_test ./drive_logfile -v -f glog_log ${srcdir}/logfile_glog.0
+
+check_output "glog_log level interpreted incorrectly?" <<EOF
+error 0x0
+info 0x0
+info 0x0
+warning 0x0
+info 0x0
+info 0x0
+error 0x0
+EOF
+
+run_test ./drive_logfile -t -f logfmt_log ${srcdir}/logfile_logfmt.0
+
+check_output "logfmt_log time interpreted incorrectly?" <<EOF
+Sep 15 21:17:10 2021 -- 220
+Sep 15 21:17:11 2021 -- 674
+Sep 15 21:17:11 2021 -- 678
+Sep 15 21:17:11 2021 -- 679
+Sep 15 21:18:20 2021 -- 335
+EOF
+
+run_test ./drive_logfile -v -f logfmt_log ${srcdir}/logfile_logfmt.0
+
+check_output "logfmt_log level interpreted incorrectly?" <<EOF
+error 0x0
+warning 0x0
+info 0x0
+info 0x0
+error 0x0
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -nt -w logfile_stdin.log <<EOF
+Hi
+EOF
+
+check_output "piping to stdin is not working?" <<EOF
+2013-06-06T19:13:20.123 Hi
+2013-06-06T19:13:20.123 ---- END-OF-STDIN ----
+EOF
+
+run_test ${lnav_test} -C ${test_dir}/logfile_bad_access_log.0
+
+sed -ibak -e "s|/.*/logfile_bad_access_log.0|logfile_bad_access_log.0|g" `test_err_filename`
+
+check_error_output "bad access_log line not found?" <<EOF
+error:logfile_bad_access_log.0:1:line did not match format /access_log/regex/std
+error:logfile_bad_access_log.0:1: line -- 192.168.202.254 [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+error:logfile_bad_access_log.0:1:partial match -- 192.168.202.254
+EOF
+
+run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_w3c.2
+
+check_output "metadata lines not ignored?" <<EOF
+16:44:49 1.1.1.1 [2]USER anonymous 331
+16:44:49 1.1.1.1 [2]PASS - 230
+16:48:05 1.1.1.1 [2]QUIT - 226
+16:48:17 1.1.1.1 [3]USER anonymous 331
+16:48:24 1.1.1.1 [3]PASS user@domain.com 230
+16:48:35 1.1.1.1 [3]sent /user/test.c 226
+16:48:41 1.1.1.1 [3]created readme.txt 226
+16:48:41 1.1.1.1 [3]created fileid.diz 226
+16:48:41 1.1.1.1 [3]created names.dll 226
+16:48:41 1.1.1.1 [3]created TEST.EXE 226
+16:48:44 1.1.1.1 [3]QUIT - 226
+16:44:49 1.1.1.1 [2]USER anonymous 331
+16:44:49 1.1.1.1 [2]PASS - 230
+16:48:05 1.1.1.1 [2]QUIT - 226
+EOF
+
+run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_w3c.6
+
+check_output "unicode in w3c not working?" <<EOF
+2015-01-13 00:32:17 100.79.192.81 GET /robots.txt - 80 - 157.55.39.146 ÄÖÜäöü\ßßßMözillä/5.0+(compatible;+bingbot/2.0;++http://www.bing.com/bingbot.htm) - 404 0 2 1405 242 283
+EOF
+
+run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_epoch.0
+
+check_output "rewriting machine-oriented timestamp didn't work?" <<EOF
+2015-04-10 02:58:07.123000 Hello, World!
+2015-04-10 02:58:07.456000 Goodbye, World!
+EOF
+
+run_test ${lnav_test} -n -I ${test_dir} ${srcdir}/logfile_crlf.0
+
+check_output "CR-LF line-endings not handled?" <<EOF
+2012-07-02 10:22:40,672:DEBUG:foo bar baz
+2014-10-08 16:56:38,344:WARN:foo bar baz
+EOF
+
+run_test ${lnav_test} -n -I ${test_dir} \
+ -c ';SELECT count(*) FROM haproxy_log' \
+ ${srcdir}/logfile_haproxy.0
+
+check_output "multi-pattern logs don't work?" <<EOF
+count(*)
+ 17
+EOF
+
+run_test ${lnav_test} -n \
+ ${srcdir}/logfile_syslog_with_header.0
+
+check_output "multi-pattern logs don't work?" <<EOF
+Header1: abc
+Header2: def
+Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed
+Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt
+Nov 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed
+Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
+EOF
+
+run_test ${lnav_test} -n \
+ ${srcdir}/logfile_generic_with_header.0
+
+check_output "multi-pattern logs don't work?" <<EOF
+Header1: abc
+Header2: def
+2012-07-02 10:22:40,672:DEBUG:foo bar baz
+2014-10-08 16:56:38,344:WARN:foo bar baz
+EOF
+
+# XXX get this working...
+# run_test ${lnav_test} -n -I ${test_dir} <(cat ${srcdir}/logfile_access_log.0)
+#
+# check_output "opening a FIFO didn't work?" <<EOF
+# 192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+# 192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+# 192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+# EOF
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT log_time, log_body FROM syslog_log' \
+ ${test_dir}/logfile_ansi.1
+
+run_cap_test ${lnav_test} -n \
+ -c ':switch-to-view pretty' \
+ ${test_dir}/logfile_ansi.1
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT basename(filepath),descriptor,mimetype,content FROM lnav_file_metadata' \
+ logfile_syslog.1.gz
diff --git a/test/test_md2attr_line.cc b/test/test_md2attr_line.cc
new file mode 100644
index 0000000..47e2454
--- /dev/null
+++ b/test/test_md2attr_line.cc
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2022, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest/doctest.h"
+#include "md2attr_line.hh"
+
+TEST_CASE("basics") {}
diff --git a/test/test_meta.sh b/test/test_meta.sh
new file mode 100644
index 0000000..caab4f9
--- /dev/null
+++ b/test/test_meta.sh
@@ -0,0 +1,110 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+export HOME="./meta-sessions"
+export XDG_CONFIG_HOME="./meta-sessions/.config"
+rm -rf "./meta-sessions"
+mkdir -p $HOME/.config
+
+# add comment/tag
+run_cap_test ${lnav_test} -n -dln.dbg \
+ -c ":comment Hello, World!" \
+ -c ":tag foo" \
+ -c ":save-session" \
+ -c ":write-screen-to -" \
+ ${test_dir}/logfile_access_log.0
+
+ls -lha meta-sessions
+find meta-sessions
+# cat ln.dbg
+if test ! -d meta-sessions/.config/lnav; then
+ echo "error: configuration not stored in .config/lnav?"
+ exit 1
+fi
+
+if test -d meta-sessions/.lnav; then
+ echo "error: configuration stored in .lnav?"
+ exit 1
+fi
+
+# tag was saved and :write-to displays the comments/tags
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ";UPDATE access_log SET log_mark = 1" \
+ -c ":write-to -" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ":untag #foo" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ":clear-comment" \
+ ${test_dir}/logfile_access_log.0
+
+# search for a tag
+run_cap_test ${lnav_test} -n \
+ -c ":goto 2" \
+ -c "/foo" \
+ -c ":tag #foo" \
+ -c ":goto 0" \
+ -c ":next-mark search" \
+ ${test_dir}/logfile_access_log.0
+
+# query meta columns
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ";SELECT log_line, log_comment, log_tags FROM access_log" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE access_log SET log_tags = json_array('#foo', '#foo') WHERE log_line = 1" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE access_log SET log_comment = 'Goodbye, World!' WHERE log_line = 1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE access_log SET log_tags = 1 WHERE log_line = 1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE access_log SET log_tags = json_array('foo') WHERE log_line = 1" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ";SELECT log_tags FROM access_log WHERE log_line = 1" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":tag foo" \
+ -c ":delete-tags #foo" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":tag foo" \
+ -c ";UPDATE access_log SET log_tags = null" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":comment foo" \
+ -c ";UPDATE access_log SET log_comment = null" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -d /tmp/lnav.err -n \
+ -I ${test_dir} \
+ ${test_dir}/logfile_xml_msg.0
+
+run_cap_test ${lnav_test} -n -f- \
+ ${test_dir}/logfile_access_log.0 <<'EOF'
+:comment Hello, **World**!
+
+This is `markdown` now!
+EOF
diff --git a/test/test_mvwattrline.sh b/test/test_mvwattrline.sh
new file mode 100644
index 0000000..c06c3ea
--- /dev/null
+++ b/test/test_mvwattrline.sh
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+run_test ./scripty -n -e ${srcdir}/mvwattrline_output.0 -- \
+ ./drive_mvwattrline < /dev/null
+
+on_error_fail_with "mvwattrline does not work"
diff --git a/test/test_ncurses_unicode.cc b/test/test_ncurses_unicode.cc
new file mode 100644
index 0000000..47f8ef2
--- /dev/null
+++ b/test/test_ncurses_unicode.cc
@@ -0,0 +1,40 @@
+
+#include <stdlib.h>
+
+#include "config.h"
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <locale.h>
+
+#if defined HAVE_NCURSESW_CURSES_H
+# include <ncursesw/curses.h>
+#elif defined HAVE_NCURSESW_H
+# include <ncursesw.h>
+#elif defined HAVE_NCURSES_CURSES_H
+# include <ncurses/curses.h>
+#elif defined HAVE_NCURSES_H
+# include <ncurses.h>
+#elif defined HAVE_CURSES_H
+# include <curses.h>
+#else
+# error "SysV or X/Open-compatible Curses header file required"
+#endif
+
+int
+main(int argc, char* argv[])
+{
+ setenv("LANG", "en_US.utf-8", 1);
+ setlocale(LC_ALL, "");
+
+ WINDOW* stdscr = initscr();
+ cbreak();
+ char buf[1024];
+ FILE* file = fopen(argv[1], "r");
+ int row = 0;
+ while (!feof(file)) {
+ if (fgets(buf, sizeof(buf), file) != nullptr) {
+ mvwaddstr(stdscr, row++, 0, buf);
+ }
+ }
+ getch();
+ endwin();
+}
diff --git a/test/test_pretty_print.sh b/test/test_pretty_print.sh
new file mode 100644
index 0000000..78f0c96
--- /dev/null
+++ b/test/test_pretty_print.sh
@@ -0,0 +1,45 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/logfile_cxx.0
+
+# check for ipv4 strings
+run_cap_test ${lnav_test} -n -c ":switch-to-view pretty" <<EOF
+2015-04-18T13:16:30.003 8.8.8.8 <foo>8.8.8.8</foo>9 8.8.8.8<1054 198.51.100.1546 544.9.8.7 98.542.241.99 19143.2.5.6
+EOF
+
+cat > test_pretty_in.1 <<EOF
+2015-04-18T13:16:30.003 {"wrapper": {"msg": r"Hello,\nWorld!\n"}}
+EOF
+
+# pretty print can interpret quoted strings correctly
+run_cap_test ${lnav_test} -n -c ":switch-to-view pretty" -d /tmp/lnav.err test_pretty_in.1
+
+cat > test_pretty_in.2 <<EOF
+{"wrapper": [{"message":"\nselect Id from Account where id = \$sfid\n ^\nERROR at Row:1:Column:34\nline 1:34 no viable alternative at character '$'"}]}
+EOF
+
+# pretty print includes leading white space
+run_cap_test ${lnav_test} -n -c ":switch-to-view pretty" test_pretty_in.2
+
+cat > test_pretty_in.3 <<EOF
+Hello\\nWorld\\n
+EOF
+
+run_cap_test ${lnav_test} -d /tmp/lnav.err -n -c ":switch-to-view pretty" test_pretty_in.3
+
+run_cap_test ${lnav_test} -d /tmp/lnav.err -n \
+ -I ${test_dir} \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/logfile_xml_msg.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/logfile_ansi.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":switch-to-view pretty" \
+ ${test_dir}/textfile_ansi.0
diff --git a/test/test_regex101.sh b/test/test_regex101.sh
new file mode 100644
index 0000000..861bf10
--- /dev/null
+++ b/test/test_regex101.sh
@@ -0,0 +1,77 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+rm -rf regex101-home
+mkdir -p regex101-home
+export HOME=regex101-home
+
+run_cap_test ${lnav_test} -m format syslog_log regex std
+
+run_cap_test ${lnav_test} -m format syslog_log regex std regex101
+
+run_cap_test ${lnav_test} -m format syslog_log regex std regex101 pull
+
+run_cap_test ${lnav_test} -m format syslog_log regex std regex101 delete
+
+run_cap_test env TEST_COMMENT="before import" ${lnav_test} -m regex101 list
+
+run_cap_test ${lnav_test} -m regex101 import
+
+run_cap_test ${lnav_test} -m regex101 import abc def-jkl
+
+run_cap_test ${lnav_test} -m regex101 import https://regex101.com/r/badregex123/1 unit_test_log
+
+# bad regex flavor
+run_cap_test ${lnav_test} -m regex101 import https://regex101.com/r/cvCJNP/1 unit_test_log
+
+run_cap_test ${lnav_test} -m regex101 import https://regex101.com/r/zpEnjV/2 unit_test_log
+
+# a second import should fail since the format file exists now
+run_cap_test ${lnav_test} -m regex101 import https://regex101.com/r/zpEnjV/1 unit_test_log
+
+run_cap_test cat regex101-home/.lnav/formats/installed/unit_test_log.json
+
+run_cap_test env TEST_COMMENT="after import" ${lnav_test} -m regex101 list
+
+run_cap_test ${lnav_test} -m format non-existent regex std regex101 pull
+
+run_cap_test ${lnav_test} -m format bro regex std regex101 pull
+
+run_cap_test ${lnav_test} -m format unit_test_log regex non-existent regex101 pull
+
+run_cap_test ${lnav_test} -m format unit_test_log regex s regex101 pull
+
+run_cap_test ${lnav_test} -m format unit_test_log regex std regex101
+
+run_cap_test ${lnav_test} -m format unit_test_log regex std regex101 pull
+
+cat > regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json <<EOF
+{
+ "unit_test_log": {
+ "regex": {
+ "std": {
+ "pattern": ""
+ }
+ }
+ }
+}
+EOF
+
+run_cap_test env TEST_COMMENT="pull after change" \
+ ${lnav_test} -m format unit_test_log regex std regex101 pull
+
+run_cap_test ${lnav_test} -m format unit_test_log sources
+
+run_cap_test cat regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json
+
+run_cap_test ${lnav_test} -m regex101 import https://regex101.com/r/hGiqBL/2 unit_test_log alt
+
+run_cap_test cat regex101-home/.lnav/formats/installed/unit_test_log.regex101-hGiqBL.json
+
+run_cap_test ${lnav_test} -m format unit_test_log regex std regex101 delete
+
+rm regex101-home/.lnav/formats/installed/unit_test_log.regex101-zpEnjV.json
+
+run_cap_test env TEST_COMMENT="delete after patch removed" \
+ ${lnav_test} -m format unit_test_log regex std regex101 delete
diff --git a/test/test_reltime.cc b/test/test_reltime.cc
new file mode 100644
index 0000000..a526c1d
--- /dev/null
+++ b/test/test_reltime.cc
@@ -0,0 +1,427 @@
+/**
+ * Copyright (c) 2015, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/time.h>
+
+#include "config.h"
+#include "fmt/format.h"
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest/doctest.h"
+#include "relative_time.hh"
+
+using namespace std;
+
+static struct {
+ const char* reltime{nullptr};
+ const char* expected{nullptr};
+ const char* expected_negate{nullptr};
+} TEST_DATA[] = {
+ // { "10 minutes after the next hour", "next 0:10" },
+ {"0s", "0s", "0s"},
+ {"next day", "next day 0:00", "last day 0:00"},
+ {"next month", "next month day 0 0:00", "last month day 0 0:00"},
+ {"next year",
+ "next year month 0 day 0 0:00",
+ "last year month 0 day 0 0:00"},
+ {"previous hour", "last 0:00", "next 0:00"},
+ {"next 10 minutes after the hour", "next 0:10", "last 0:10"},
+ {"1h50m", "1h50m", "-1h-50m"},
+ {"next hour", "next 0:00", "last 0:00"},
+ {"a minute ago", "0:-1", "0:-1"},
+ {"1m ago", "0:-1", "0:-1"},
+ {"a min ago", "0:-1", "0:-1"},
+ {"a m ago", "0:-1", "0:-1"},
+ {"+1 minute ago", "0:-1", "0:-1"},
+ {"-1 minute ago", "0:-1", "0:-1"},
+ {"-1 minute", "-1m", "1m"},
+ {"10 minutes after the hour", "0:10", "0:10"},
+ {"1:40", "1:40", "1:40"},
+ {"01:30", "1:30", "1:30"},
+ {"1pm", "13:00", "13:00"},
+ {"12pm", "12:00", "12:00"},
+ {"00:27:18.567", "0:27:18.567", "0:27:18.567"},
+
+ {},
+};
+
+static struct {
+ const char* reltime;
+ const char* expected_error;
+} BAD_TEST_DATA[] = {
+ {"10am am", "Time has already been set"},
+ {"yesterday today", "Current time reference has already been used"},
+ {"10am 10am", "Time has already been set"},
+ {"ago", "Expecting a time unit"},
+ {"minute", "Expecting a number before time unit"},
+ {"1 2", "No time unit given for the previous number"},
+ {"blah", "Unrecognized input"},
+ {"before", "'before' requires a point in time (e.g. before 10am)"},
+ {"after", "'after' requires a point in time (e.g. after 10am)"},
+ {"before after", "Before/after ranges are not supported yet"},
+
+ {nullptr, nullptr},
+};
+
+TEST_CASE("reltime")
+{
+ time_t base_time = 1317913200;
+ struct exttm base_tm;
+ base_tm.et_tm = *gmtime(&base_time);
+ struct timeval tv;
+ struct exttm tm, tm2;
+ time_t new_time;
+
+ {
+ auto rt_res = relative_time::from_str(
+ string_fragment::from_const("before 2014"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1438948860;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ CHECK(!win_opt.has_value());
+ }
+
+ {
+ auto rt_res = relative_time::from_str(
+ string_fragment::from_const("after 2014"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1438948860;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ CHECK(win_opt.has_value());
+ }
+
+ {
+ auto rt_res
+ = relative_time::from_str(string_fragment::from_const("after fri"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1438948860;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ CHECK(!win_opt.has_value());
+ }
+
+ {
+ auto rt_res = relative_time::from_str(
+ string_fragment::from_const("before fri"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1438948860;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ CHECK(!win_opt.has_value());
+ }
+
+ {
+ auto rt_res = relative_time::from_str(
+ string_fragment::from_const("before 12pm"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1438948860;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ CHECK(!win_opt.has_value());
+ }
+
+ {
+ auto rt_res = relative_time::from_str(
+ string_fragment::from_const("sun after 1pm"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1615727900;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ auto win_tm = *win_opt;
+ CHECK(win_tm.et_tm.tm_year == 121);
+ CHECK(win_tm.et_tm.tm_mon == 2);
+ CHECK(win_tm.et_tm.tm_mday == 14);
+ CHECK(win_tm.et_tm.tm_hour == 13);
+ CHECK(win_tm.et_tm.tm_min == 0);
+ CHECK(win_tm.et_tm.tm_sec == 0);
+ }
+
+ {
+ auto rt_res
+ = relative_time::from_str(string_fragment::from_const("0:05"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 5 * 60 + 15;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ auto win_tm = *win_opt;
+ CHECK(win_tm.et_tm.tm_sec == 0);
+ CHECK(win_tm.et_tm.tm_min == 5);
+ CHECK(win_tm.et_tm.tm_hour == 0);
+
+ t_in = 4 * 60 + 15;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ win_opt = rt.window_start(tm);
+ CHECK(!win_opt.has_value());
+ }
+
+ {
+ auto rt_res
+ = relative_time::from_str(string_fragment::from_const("mon"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 1615841352;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ auto win_tm = *win_opt;
+ CHECK(win_tm.et_tm.tm_year == 121);
+ CHECK(win_tm.et_tm.tm_mon == 2);
+ CHECK(win_tm.et_tm.tm_mday == 15);
+ CHECK(win_tm.et_tm.tm_hour == 0);
+ CHECK(win_tm.et_tm.tm_min == 0);
+ CHECK(win_tm.et_tm.tm_sec == 0);
+ }
+
+ {
+ auto rt_res
+ = relative_time::from_str(string_fragment::from_const("tue"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+ CHECK(rt.rt_included_days
+ == std::set<relative_time::token_t>{relative_time::RTT_TUESDAY});
+ }
+
+ {
+ auto rt_res
+ = relative_time::from_str(string_fragment::from_const("1m"));
+
+ CHECK(rt_res.isOk());
+ auto rt = rt_res.unwrap();
+
+ time_t t_in = 30;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ auto win_opt = rt.window_start(tm);
+ auto win_tm = *win_opt;
+ CHECK(win_tm.et_tm.tm_sec == 0);
+ CHECK(win_tm.et_tm.tm_min == 0);
+ CHECK(win_tm.et_tm.tm_hour == 0);
+
+ t_in = 90;
+ memset(&tm, 0, sizeof(tm));
+ tm.et_tm = *gmtime(&t_in);
+ win_opt = rt.window_start(tm);
+ win_tm = *win_opt;
+ CHECK(win_tm.et_tm.tm_sec == 0);
+ CHECK(win_tm.et_tm.tm_min == 1);
+ CHECK(win_tm.et_tm.tm_hour == 0);
+ }
+
+ relative_time rt;
+ for (int lpc = 0; TEST_DATA[lpc].reltime; lpc++) {
+ auto res = relative_time::from_str(
+ string_fragment::from_c_str(TEST_DATA[lpc].reltime));
+ CHECK_MESSAGE(res.isOk(), TEST_DATA[lpc].reltime);
+ rt = res.unwrap();
+ CHECK(std::string(TEST_DATA[lpc].expected) == rt.to_string());
+ rt.negate();
+ CHECK(std::string(TEST_DATA[lpc].expected_negate) == rt.to_string());
+ }
+
+ for (int lpc = 0; BAD_TEST_DATA[lpc].reltime; lpc++) {
+ auto res = relative_time::from_str(
+ string_fragment::from_c_str(BAD_TEST_DATA[lpc].reltime));
+ CHECK(res.isErr());
+ CHECK(res.unwrapErr().pe_msg
+ == string(BAD_TEST_DATA[lpc].expected_error));
+ }
+
+ rt = relative_time::from_str(string_fragment::from_const("")).unwrap();
+ CHECK(rt.empty());
+
+ rt = relative_time::from_str(string_fragment::from_const("a minute ago"))
+ .unwrap();
+ CHECK(rt.rt_field[relative_time::RTF_MINUTES].value == -1);
+ CHECK(rt.is_negative() == true);
+
+ rt = relative_time::from_str(string_fragment::from_const("5 milliseconds"))
+ .unwrap();
+ CHECK(rt.rt_field[relative_time::RTF_MICROSECONDS].value == 5 * 1000);
+
+ rt = relative_time::from_str(string_fragment::from_const("5000 ms ago"))
+ .unwrap();
+ CHECK(rt.rt_field[relative_time::RTF_SECONDS].value == -5);
+
+ rt = relative_time::from_str(
+ string_fragment::from_const("5 hours 20 minutes ago"))
+ .unwrap();
+
+ CHECK(rt.rt_field[relative_time::RTF_HOURS].value == -5);
+ CHECK(rt.rt_field[relative_time::RTF_MINUTES].value == -20);
+
+ rt = relative_time::from_str(
+ string_fragment::from_const("5 hours and 20 minutes ago"))
+ .unwrap();
+
+ CHECK(rt.rt_field[relative_time::RTF_HOURS].value == -5);
+ CHECK(rt.rt_field[relative_time::RTF_MINUTES].value == -20);
+
+ rt = relative_time::from_str(string_fragment::from_const("1:23")).unwrap();
+
+ CHECK(rt.rt_field[relative_time::RTF_HOURS].value == 1);
+ CHECK(rt.rt_field[relative_time::RTF_MINUTES].value == 23);
+ CHECK(rt.is_absolute());
+
+ rt = relative_time::from_str(string_fragment::from_const("1:23:45"))
+ .unwrap();
+
+ CHECK(rt.rt_field[relative_time::RTF_HOURS].value == 1);
+ CHECK(rt.rt_field[relative_time::RTF_MINUTES].value == 23);
+ CHECK(rt.rt_field[relative_time::RTF_SECONDS].value == 45);
+ CHECK(rt.is_absolute());
+
+ tm = base_tm;
+ tm = rt.adjust(tm);
+
+ new_time = timegm(&tm.et_tm);
+ tm.et_tm = *gmtime(&new_time);
+ CHECK(tm.et_tm.tm_hour == 1);
+ CHECK(tm.et_tm.tm_min == 23);
+
+ rt = relative_time::from_str(string_fragment::from_const("5 minutes ago"))
+ .unwrap();
+
+ tm = base_tm;
+ tm = rt.adjust(tm);
+
+ new_time = timegm(&tm.et_tm);
+
+ CHECK(new_time == (base_time - (5 * 60)));
+
+ rt = relative_time::from_str(string_fragment::from_const("today at 4pm"))
+ .unwrap();
+ memset(&tm, 0, sizeof(tm));
+ memset(&tm2, 0, sizeof(tm2));
+ gettimeofday(&tv, nullptr);
+ localtime_r(&tv.tv_sec, &tm.et_tm);
+ localtime_r(&tv.tv_sec, &tm2.et_tm);
+ tm2.et_tm.tm_hour = 16;
+ tm2.et_tm.tm_min = 0;
+ tm2.et_tm.tm_sec = 0;
+ tm = rt.adjust(tm);
+ tm.et_tm.tm_yday = 0;
+ tm2.et_tm.tm_yday = 0;
+ tm.et_tm.tm_wday = 0;
+ tm2.et_tm.tm_wday = 0;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ tm2.et_tm.tm_gmtoff = 0;
+ tm2.et_tm.tm_zone = nullptr;
+#endif
+ CHECK(tm.et_tm.tm_year == tm2.et_tm.tm_year);
+ CHECK(tm.et_tm.tm_mon == tm2.et_tm.tm_mon);
+ CHECK(tm.et_tm.tm_mday == tm2.et_tm.tm_mday);
+ CHECK(tm.et_tm.tm_hour == tm2.et_tm.tm_hour);
+ CHECK(tm.et_tm.tm_min == tm2.et_tm.tm_min);
+ CHECK(tm.et_tm.tm_sec == tm2.et_tm.tm_sec);
+
+ rt = relative_time::from_str(
+ string_fragment::from_const("yesterday at 4pm"))
+ .unwrap();
+ gettimeofday(&tv, nullptr);
+ localtime_r(&tv.tv_sec, &tm.et_tm);
+ localtime_r(&tv.tv_sec, &tm2.et_tm);
+ tm2.et_tm.tm_mday -= 1;
+ tm2.et_tm.tm_hour = 16;
+ tm2.et_tm.tm_min = 0;
+ tm2.et_tm.tm_sec = 0;
+ tm = rt.adjust(tm);
+ tm.et_tm.tm_yday = 0;
+ tm2.et_tm.tm_yday = 0;
+ tm.et_tm.tm_wday = 0;
+ tm2.et_tm.tm_wday = 0;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ tm2.et_tm.tm_gmtoff = 0;
+ tm2.et_tm.tm_zone = NULL;
+#endif
+ CHECK(tm.et_tm.tm_year == tm2.et_tm.tm_year);
+ CHECK(tm.et_tm.tm_mon == tm2.et_tm.tm_mon);
+ CHECK(tm.et_tm.tm_mday == tm2.et_tm.tm_mday);
+ CHECK(tm.et_tm.tm_hour == tm2.et_tm.tm_hour);
+ CHECK(tm.et_tm.tm_min == tm2.et_tm.tm_min);
+ CHECK(tm.et_tm.tm_sec == tm2.et_tm.tm_sec);
+
+ rt = relative_time::from_str(string_fragment::from_const("2 days ago"))
+ .unwrap();
+ gettimeofday(&tv, nullptr);
+ localtime_r(&tv.tv_sec, &tm.et_tm);
+ localtime_r(&tv.tv_sec, &tm2.et_tm);
+ tm2.et_tm.tm_mday -= 2;
+ tm2.et_tm.tm_hour = 0;
+ tm2.et_tm.tm_min = 0;
+ tm2.et_tm.tm_sec = 0;
+ tm = rt.adjust(tm);
+ tm.et_tm.tm_yday = 0;
+ tm2.et_tm.tm_yday = 0;
+ tm.et_tm.tm_wday = 0;
+ tm2.et_tm.tm_wday = 0;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ tm2.et_tm.tm_gmtoff = 0;
+ tm2.et_tm.tm_zone = nullptr;
+#endif
+ CHECK(tm.et_tm.tm_year == tm2.et_tm.tm_year);
+ CHECK(tm.et_tm.tm_mon == tm2.et_tm.tm_mon);
+ CHECK(tm.et_tm.tm_mday == tm2.et_tm.tm_mday);
+ CHECK(tm.et_tm.tm_hour == tm2.et_tm.tm_hour);
+ CHECK(tm.et_tm.tm_min == tm2.et_tm.tm_min);
+ CHECK(tm.et_tm.tm_sec == tm2.et_tm.tm_sec);
+}
diff --git a/test/test_remote.sh b/test/test_remote.sh
new file mode 100644
index 0000000..946b19f
--- /dev/null
+++ b/test/test_remote.sh
@@ -0,0 +1,119 @@
+#! /bin/bash
+
+echo "Hello, World!" > not:a:remote:file
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ not:a:remote:file
+
+check_output "a file with colons cannot be read?" <<EOF
+Hello, World!
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -Nn \
+ -c ':open not:a:remote:file'
+
+check_output "a file with colons cannot be read?" <<EOF
+Hello, World!
+EOF
+
+mkdir not:a:remote:dir
+echo "Hello, World!" > not:a:remote:dir/file
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ not:a:remote:dir
+
+check_output "a file in a dir with colons cannot be read?" <<EOF
+Hello, World!
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ not:a:remote:dir/f*
+
+check_output "a wildcard in a dir with colons cannot be read?" <<EOF
+Hello, World!
+EOF
+if [ -d /home/runner ]; then
+chmod 755 /home/runner
+ls -la /home/runner
+fi
+export HOME=${PWD}/remote
+unset XDG_CONFIG_HOME
+
+rm -rf remote-tmp
+mkdir -p remote-tmp
+export TMPDIR=remote-tmp
+
+cat > remote/sshd_config <<EOF
+Port 2222
+UsePam no
+AuthorizedKeysFile ${PWD}/remote/authorized_keys
+HostKey ${PWD}/remote/ssh_host_rsa_key
+HostKey ${PWD}/remote/ssh_host_dsa_key
+ChallengeResponseAuthentication no
+PidFile ${PWD}/remote/sshd.pid
+EOF
+
+cat > remote/ssh_config <<EOF
+Host *
+Port 2222
+IdentityFile ${PWD}/remote/id_rsa
+StrictHostKeyChecking no
+EOF
+
+SSHD_PATH=$(which sshd)
+echo "ssh path: ${SSHD_PATH}"
+
+trap 'kill $(cat remote/sshd.pid)' EXIT
+
+$SSHD_PATH -E ${PWD}/remote/sshd.log -f remote/sshd_config
+
+${lnav_test} -d /tmp/lnav.err -nN \
+ -c ":config /tuning/remote/ssh/options/F ${PWD}/remote/ssh_config"
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ nonexistent-host:${test_dir}/logfile_access_log.0
+
+sed -e "s|ssh:.*|...|g" `test_err_filename` | head -1 \
+ > test_remote.err
+
+mv test_remote.err `test_err_filename`
+check_error_output "no error for nonexistent-host?" <<EOF
+error: unable to open file: nonexistent-host: -- failed to ssh to host: ...
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ localhost:nonexistent-file
+
+cat remote/sshd.log
+check_error_output "no error for nonexistent-file?" <<EOF
+error: unable to open file: localhost:nonexistent-file -- unable to lstat -- ENOENT[2]
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ localhost:${test_dir}/logfile_access_log.0
+
+check_output "could not download remote file?" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ "localhost:${test_dir}/logfile_access_log.*"
+
+check_output "could not download remote file?" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
+EOF
+
+run_test ${lnav_test} -d /tmp/lnav.err -n \
+ "localhost:${test_dir}/remote-log-dir"
+
+check_output "could not download remote file?" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7"
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-"
+EOF
diff --git a/test/test_scripts.sh b/test/test_scripts.sh
new file mode 100644
index 0000000..cbd43e4
--- /dev/null
+++ b/test/test_scripts.sh
@@ -0,0 +1,51 @@
+#! /bin/bash
+
+lnav_test="${top_builddir}/src/lnav-test"
+
+touch scripts-empty
+
+run_test ${lnav_test} -n -d /tmp/lnav.err \
+ -I ${test_dir} \
+ -f 'multiline-echo' \
+ scripts-empty
+
+check_error_output "multiline-echo has errors?" <<EOF
+EOF
+
+check_output "multiline-echo is not working?" <<EOF
+Hello, World!
+Goodbye, World!
+EOF
+
+run_test ${lnav_test} -n -d /tmp/lnav.err \
+ -I ${test_dir} \
+ -f 'redirecting' \
+ scripts-empty
+
+check_error_output "redirecting has errors?" <<EOF
+EOF
+
+check_output "redirecting is not working?" <<EOF
+Howdy!
+Goodbye, World!
+EOF
+
+diff -w -u - hw.txt <<EOF
+Hello, World!
+HOWDY!
+GOODBYE, WORLD!
+EOF
+
+if test $? -ne 0; then
+ echo "Script output was not redirected?"
+ exit 1
+fi
+
+diff -w -u - hw2.txt <<EOF
+HELLO, WORLD!
+EOF
+
+if test $? -ne 0; then
+ echo "Script output was not redirected?"
+ exit 1
+fi
diff --git a/test/test_sessions.sh b/test/test_sessions.sh
new file mode 100644
index 0000000..db71e5f
--- /dev/null
+++ b/test/test_sessions.sh
@@ -0,0 +1,119 @@
+#! /bin/bash
+
+export HOME="./sessions"
+unset XDG_CONFIG_HOME
+rm -rf "./sessions"
+mkdir -p $HOME
+
+run_cap_test ${lnav_test} -n \
+ -c ":reset-session" \
+ -c ":goto 0" \
+ -c ":hide-file" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.*
+
+# hidden file saved in session
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ ${test_dir}/logfile_access_log.*
+
+# setting log_mark
+run_cap_test ${lnav_test} -nq \
+ -c ":reset-session" \
+ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \
+ -c ":goto 1" \
+ -c ":partition-name middle" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+mkdir -p support-dump
+echo 'Hello' > support-dump/readme
+cp ${test_dir}/logfile_access_log.0 support-dump/
+cp ${test_dir}/logfile_access_log.1 support-dump/
+
+run_cap_test ${lnav_test} -nq \
+ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \
+ -c ":goto 1" \
+ -c ":hide-file */logfile_access_log.1" \
+ -c ":export-session-to -" \
+ support-dump/logfile_access_log.*
+
+run_cap_test ${lnav_test} -nq \
+ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \
+ -c ":set-min-log-level debug" \
+ -c ":hide-lines-before 2005" \
+ -c ":hide-lines-after 2030" \
+ -c ":filter-out blah" \
+ -c "/foobar" \
+ -c ":goto 1" \
+ -c ":export-session-to exported-session.0.lnav" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c "|exported-session.0.lnav" \
+ -c ";SELECT * FROM lnav_view_filters" \
+ -c ":write-screen-to -" \
+ -c ";SELECT name,search FROM lnav_views" \
+ -c ":write-screen-to -" \
+ ${test_dir}/logfile_access_log.0
+
+# log mark was not saved in session
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ':write-to -' \
+ ${test_dir}/logfile_access_log.0
+
+# file was not closed
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ":close" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+# partition name was not saved in session
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ';select log_line,log_part from access_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+# adjust time is not working
+run_cap_test ${lnav_test} -nq \
+ -c ":adjust-log-time 2010-01-01T00:00:00" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+# adjust time is not saved in session
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ":test-comment adjust time in session" \
+ ${test_dir}/logfile_access_log.0
+
+# hiding fields failed
+rm -rf ./sessions
+mkdir -p $HOME
+run_cap_test ${lnav_test} -nq -d /tmp/lnav.err \
+ -c ":hide-fields c_ip" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+# restoring hidden fields failed
+run_cap_test ${lnav_test} -n \
+ -c ":load-session" \
+ -c ":test-comment restoring hidden fields" \
+ ${test_dir}/logfile_access_log.0
+
+# hiding fields failed
+rm -rf ./sessions
+mkdir -p $HOME
+run_cap_test ${lnav_test} -nq -d /tmp/lnav.err \
+ -c ":hide-lines-before 2009-07-20 22:59:29" \
+ -c ":save-session" \
+ ${test_dir}/logfile_access_log.0
+
+# XXX we don't actually check
+# restoring hidden fields failed
+run_cap_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ":load-session" \
+ -c ":test-comment restore hidden lines" \
+ ${test_dir}/logfile_access_log.0
diff --git a/test/test_shlexer.sh b/test/test_shlexer.sh
new file mode 100644
index 0000000..747de95
--- /dev/null
+++ b/test/test_shlexer.sh
@@ -0,0 +1,32 @@
+#! /bin/bash
+
+export FOO='bar'
+export DEF='xyz'
+
+run_cap_test ./drive_shlexer '$FOO'
+
+run_cap_test ./drive_shlexer '${FOO}'
+
+# run_cap_test ./drive_shlexer '\a'
+
+run_cap_test ./drive_shlexer '\'
+
+run_cap_test ./drive_shlexer "'abc'"
+
+run_cap_test ./drive_shlexer '"def"'
+
+run_cap_test ./drive_shlexer '"'"'"'"'
+
+run_cap_test ./drive_shlexer "'"'"'"'"
+
+run_cap_test ./drive_shlexer '"abc $DEF 123"'
+
+run_cap_test ./drive_shlexer '"abc ${DEF} 123"'
+
+run_cap_test ./drive_shlexer "'abc \$DEF 123'"
+
+run_cap_test ./drive_shlexer 'abc $DEF 123'
+
+run_cap_test ./drive_shlexer '~ foo'
+
+run_cap_test ./drive_shlexer '~nonexistent/bar baz'
diff --git a/test/test_sql.sh b/test/test_sql.sh
new file mode 100644
index 0000000..369351c
--- /dev/null
+++ b/test/test_sql.sh
@@ -0,0 +1,1097 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+lnav_test="${top_builddir}/src/lnav-test"
+unset XDG_CONFIG_HOME
+
+run_cap_test ${lnav_test} -nN \
+ -c ";SELECT 1 = ?"
+
+run_cap_test ${lnav_test} -n \
+ -c ";.read nonexistent-file" \
+ ${test_dir}/logfile_empty.0
+
+run_test ${lnav_test} -n \
+ -c ";.read ${test_dir}/file_for_dot_read.sql" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.0
+
+check_output ".read did not work?" <<EOF
+log_line,log_body
+1, attempting to mount entry /auto/opt
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT replicate('foobar', 120)" \
+ ${test_dir}/logfile_empty.0
+
+cp ${srcdir}/logfile_syslog.2 logfile_syslog_test.2
+touch -t 201511030923 logfile_syslog_test.2
+run_test ${lnav_test} -n \
+ -c ";SELECT *, log_msg_schema FROM all_logs" \
+ -c ":write-csv-to -" \
+ logfile_syslog_test.2
+
+check_output "all_logs does not work?" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,log_msg_format,log_msg_schema
+0,<NULL>,2015-11-03 09:23:38.000,0,info,0,<NULL>,<NULL>,<NULL>,# is up,aff2bfc3c61e7b86329b83190f0912b3
+1,<NULL>,2015-11-03 09:23:38.000,0,info,0,<NULL>,<NULL>,<NULL>,# is up,aff2bfc3c61e7b86329b83190f0912b3
+2,<NULL>,2015-11-03 09:23:38.000,0,info,0,<NULL>,<NULL>,<NULL>,# is down,506560b3c73dee057732e69a3c666718
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";SELECT fields FROM logfmt_log" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_logfmt.0
+
+check_output "logfmt fields are not handled correctly?" <<EOF
+[
+ {
+ "fields": {
+ "namespace": "inc-1-enh-domain-c14-ns-2",
+ "pod": "hello-inc-1-enh-domain-c14-ns-2-3-d8f465685-k75gp",
+ "reason": "",
+ "status": "Pending"
+ }
+ },
+ {
+ "fields": {
+ "error": "pod inc-1-domain-c14-ns-6/fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b is not found: PodNotFound",
+ "namespace": "inc-1-domain-c14-ns-6",
+ "pod": "fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b",
+ "uid": "be2def59-3a08-42fd-8f84-6f64cfcefa93"
+ }
+ },
+ {
+ "fields": {
+ "namespace": "inc-1-domain-c14-ns-6",
+ "pod": "fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b",
+ "uid": "be2def59-3a08-42fd-8f84-6f64cfcefa93"
+ }
+ },
+ {
+ "fields": {
+ "namespace": "inc-1-domain-c14-ns-6",
+ "pod": "fe-inc-1-domain-c14-ns-6-5-656d9bb695-4584b",
+ "uid": "be2def59-3a08-42fd-8f84-6f64cfcefa93"
+ }
+ },
+ {
+ "fields": {
+ "namespace": "inc-1-enh-domain-c14-ns-2",
+ "pod": "hello-inc-1-enh-domain-c14-ns-2-7-5ddd6bcd69-6rqct",
+ "reason": "",
+ "status": "Pending"
+ }
+ }
+]
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";SELECT sc_substatus FROM w3c_log" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_w3c.3
+
+check_output "w3c quoted strings are not handled correctly?" <<EOF
+[
+ {
+ "sc_substatus": 0
+ },
+ {
+ "sc_substatus": 0
+ },
+ {
+ "sc_substatus": null
+ }
+]
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";SELECT cs_headers FROM w3c_log" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_w3c.3
+
+check_output "w3c headers are not captured?" <<EOF
+[
+ {
+ "cs_headers": {
+ "User-Agent": "Mozilla/5.0 (Linux; Android 4.4.4; SM-G900V Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36",
+ "Referer": "http://example.com/Search/SearchResults.pg?informationRecipient.languageCode.c=en",
+ "Host": "xzy.example.com"
+ }
+ },
+ {
+ "cs_headers": {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
+ "Referer": null,
+ "Host": "example.hello.com"
+ }
+ },
+ {
+ "cs_headers": {
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
+ "Referer": null,
+ "Host": "hello.example.com"
+ }
+ }
+]
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM generate_series()" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM generate_series(1)" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT 1 AS inum, NULL AS nul, 2.0 AS fnum, 'abc' AS str" \
+ -c ";SELECT \$inum, \$nul, \$fnum, \$str, raise_error('oops!')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT raise_error('oops!')" \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ";SELECT basename(filepath) as name, content, length(content) FROM lnav_file" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_empty.0
+
+check_output "empty content not handled correctly?" <<EOF
+name,content,length(content)
+logfile_empty.0,,0
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";SELECT distinct xp.node_text FROM lnav_file, xpath('//author', content) as xp" \
+ -c ":write-csv-to -" \
+ ${test_dir}/books.xml
+
+check_output "xpath on file content not working?" <<EOF
+node_text
+"Gambardella, Matthew"
+"Ralls, Kim"
+"Corets, Eva"
+"Randall, Cynthia"
+"Thurman, Paula"
+"Knorr, Stefan"
+"Kress, Peter"
+"O'Brien, Tim"
+"Galos, Mike"
+EOF
+
+gzip -c ${srcdir}/logfile_json.json > logfile_json.json.gz
+dd if=logfile_json.json.gz of=logfile_json-trunc.json.gz bs=64 count=2
+
+# TODO re-enable this
+#run_test ${lnav_test} -n \
+# -c ";SELECT content FROM lnav_file" \
+# logfile_json-trunc.json.gz
+
+#check_error_output "invalid gzip file working?" <<EOF
+#command-option:1: error: unable to uncompress: logfile_json-trunc.json.gz -- buffer error
+#EOF
+
+run_test ${lnav_test} -n \
+ -c ";SELECT jget(rc.content, '/ts') AS ts FROM lnav_file, regexp_capture(lnav_file.content, '.*\n') as rc" \
+ -c ":write-csv-to -" \
+ logfile_json.json.gz
+
+check_output "jget on file content not working?" <<EOF
+ts
+2013-09-06T20:00:48.124817Z
+2013-09-06T20:00:49.124817Z
+2013-09-06T22:00:49.124817Z
+2013-09-06T22:00:59.124817Z
+2013-09-06T22:00:59.124817Z
+2013-09-06T22:00:59.124817Z
+2013-09-06T22:00:59.124817Z
+2013-09-06T22:00:59.124817Z
+2013-09-06T22:01:49.124817Z
+2013-09-06T22:01:49.124817Z
+2013-09-06T22:01:49.124817Z
+2013-09-06T22:01:49.124817Z
+2013-09-06T22:01:49.124817Z
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_file SET filepath='foo' WHERE endswith(filepath, '_log.0')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c "|rename-stdin" \
+ ${test_dir}/logfile_access_log.0 < /dev/null
+
+run_cap_test ${lnav_test} -n \
+ -c "|rename-stdin foo" \
+ ${test_dir}/logfile_access_log.0 < /dev/null
+
+run_cap_test ${lnav_test} -n \
+ -c "|rename-stdin foo" \
+ -c ";SELECT filepath FROM lnav_file" <<EOF
+Hello, World!
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";SELECT basename(filepath),format,lines,time_offset FROM lnav_file LIMIT 2" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_access_log.0 \
+ ${test_dir}/logfile_access_log.1
+
+check_output "lnav_file table is not working?" <<EOF
+basename(filepath),format,lines,time_offset
+logfile_access_log.0,access_log,3,0
+logfile_access_log.1,access_log,1,0
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_file SET time_offset = 60 * 1000" \
+ ${test_dir}/logfile_access_log.0 \
+ ${test_dir}/logfile_access_log.1
+
+run_test ${lnav_test} -n \
+ -c ";UPDATE lnav_file SET time_offset=14400000 WHERE endswith(filepath, 'logfile_block.1')" \
+ ${test_dir}/logfile_block.1 \
+ ${test_dir}/logfile_block.2
+
+check_output "time_offset in lnav_file table is not reordering?" <<EOF
+Wed May 19 12:00:01 2021 line 1
+/abc/def
+Wed May 19 12:00:02 UTC 2021 line 2
+Wed May 19 12:00:03 2021 line 3
+/ghi/jkl
+Wed May 19 12:00:04 UTC 2021 line 4
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";SELECT * FROM access_log LIMIT 0" \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "output generated for empty result set?" <<EOF
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 2" \
+ -c ";SELECT log_top_line()" \
+ ${test_dir}/logfile_uwsgi.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 2" \
+ -c ";SELECT log_top_line()" \
+ ${test_dir}/logfile_empty.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 2" \
+ -c ";SELECT log_top_datetime()" \
+ ${test_dir}/logfile_uwsgi.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":goto 2" \
+ -c ";SELECT log_top_datetime()" \
+ ${test_dir}/logfile_empty.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM uwsgi_log LIMIT 1" \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_uwsgi.0
+
+run_test ${lnav_test} -n \
+ -c ";SELECT s_runtime FROM uwsgi_log LIMIT 5" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_uwsgi.0
+
+check_output "uwsgi scaling not working?" <<EOF
+s_runtime
+0.129
+0.035
+6.8e-05
+0.016
+0.01
+EOF
+
+run_test env TZ=UTC ${lnav_test} -n \
+ -c ";SELECT bro_conn_log.bro_duration as duration, bro_conn_log.bro_uid, group_concat( distinct (bro_method || ' ' || bro_host)) as req from bro_http_log, bro_conn_log where bro_http_log.bro_uid = bro_conn_log.bro_uid group by bro_http_log.bro_uid order by duration desc limit 10" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_bro_http.log.0 ${test_dir}/logfile_bro_conn.log.0
+
+check_output "bro logs are not recognized?" <<EOF
+duration,bro_uid,req
+116.438679,CwFs1P2UcUdlSxD2La,GET www.reddit.com
+115.202498,CdZUPH2DKOE7zzCLE3,GET feeds.bbci.co.uk
+115.121914,CdrfXZ1NOFPEawF218,GET c.thumbs.redditmedia.com
+115.121837,CoX7zA3OJKGUOSCBY2,GET e.thumbs.redditmedia.com
+115.12181,CJxSUgkInyKSHiju1,GET e.thumbs.redditmedia.com
+115.121506,CT0JIh479jXIGt0Po1,GET f.thumbs.redditmedia.com
+115.121339,CJwUi9bdB9c1lLW44,GET f.thumbs.redditmedia.com
+115.119217,C6Q4Vm14ZJIlZhsXqk,GET a.thumbs.redditmedia.com
+72.274459,CbNCgO1MzloHRNeY4f,GET www.google.com
+71.658218,CnGze54kQWWpKqrrZ4,GET ajax.googleapis.com
+EOF
+
+run_test env TZ=UTC ${lnav_test} -n \
+ -c ";SELECT * FROM bro_http_log LIMIT 5" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_bro_http.log.0
+
+check_output "bro logs are not recognized?" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,bro_ts,bro_uid,bro_id_orig_h,bro_id_orig_p,bro_id_resp_h,bro_id_resp_p,bro_trans_depth,bro_method,bro_host,bro_uri,bro_referrer,bro_version,bro_user_agent,bro_request_body_len,bro_response_body_len,bro_status_code,bro_status_msg,bro_info_code,bro_info_msg,bro_tags,bro_username,bro_password,bro_proxied,bro_orig_fuids,bro_orig_filenames,bro_orig_mime_types,bro_resp_fuids,bro_resp_filenames,bro_resp_mime_types
+0,<NULL>,2011-11-03 00:19:26.452,0,info,0,<NULL>,<NULL>,<NULL>,1320279566.452687,CwFs1P2UcUdlSxD2La,192.168.2.76,52026,132.235.215.119,80,1,GET,www.reddit.com,/,<NULL>,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,109978,200,OK,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,Ftw3fJ2JJF3ntMTL2,<NULL>,text/html
+1,<NULL>,2011-11-03 00:19:26.831,379,info,0,<NULL>,<NULL>,<NULL>,1320279566.831619,CJxSUgkInyKSHiju1,192.168.2.76,52030,72.21.211.173,80,1,GET,e.thumbs.redditmedia.com,/E-pbDbmiBclPkDaX.jpg,http://www.reddit.com/,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,2300,200,OK,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,FFTf9Zdgk3YkfCKo3,<NULL>,image/jpeg
+2,<NULL>,2011-11-03 00:19:26.831,0,info,0,<NULL>,<NULL>,<NULL>,1320279566.831563,CJwUi9bdB9c1lLW44,192.168.2.76,52029,72.21.211.173,80,1,GET,f.thumbs.redditmedia.com,/BP5bQfy4o-C7cF6A.jpg,http://www.reddit.com/,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,2272,200,OK,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,FfXtOj3o7aub4vbs2j,<NULL>,image/jpeg
+3,<NULL>,2011-11-03 00:19:26.831,0,info,0,<NULL>,<NULL>,<NULL>,1320279566.831473,CoX7zA3OJKGUOSCBY2,192.168.2.76,52027,72.21.211.173,80,1,GET,e.thumbs.redditmedia.com,/SVUtep3Rhg5FTRn4.jpg,http://www.reddit.com/,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,2562,200,OK,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,F21Ybs3PTqS6O4Q2Zh,<NULL>,image/jpeg
+4,<NULL>,2011-11-03 00:19:26.831,0,info,0,<NULL>,<NULL>,<NULL>,1320279566.831643,CT0JIh479jXIGt0Po1,192.168.2.76,52031,72.21.211.173,80,1,GET,f.thumbs.redditmedia.com,/uuy31444rLSyKdHS.jpg,http://www.reddit.com/,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,1595,200,OK,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,Fdk0MZ1wQmKWAJ4WH4,<NULL>,image/jpeg
+EOF
+
+run_test env TZ=UTC ${lnav_test} -n \
+ -c ";SELECT * FROM bro_http_log WHERE log_level = 'error'" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_bro_http.log.0
+
+check_output "bro logs are not recognized?" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,bro_ts,bro_uid,bro_id_orig_h,bro_id_orig_p,bro_id_resp_h,bro_id_resp_p,bro_trans_depth,bro_method,bro_host,bro_uri,bro_referrer,bro_version,bro_user_agent,bro_request_body_len,bro_response_body_len,bro_status_code,bro_status_msg,bro_info_code,bro_info_msg,bro_tags,bro_username,bro_password,bro_proxied,bro_orig_fuids,bro_orig_filenames,bro_orig_mime_types,bro_resp_fuids,bro_resp_filenames,bro_resp_mime_types
+118,<NULL>,2011-11-03 00:19:49.337,18,error,0,<NULL>,<NULL>,<NULL>,1320279589.337053,CBHHuR1xFnm5C5CQBc,192.168.2.76,52074,74.125.225.76,80,1,GET,i4.ytimg.com,/vi/gDbg_GeuiSY/hqdefault.jpg,<NULL>,1.1,Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1,0,893,404,Not Found,<NULL>,<NULL>,,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,<NULL>,F2GiAw3j1m22R2yIg2,<NULL>,image/jpeg
+EOF
+
+run_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line > 100000' \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "out-of-range query failed?" <<EOF
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line > -100000' \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line < -10000' \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "out-of-range query failed?" <<EOF
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line > -10000' \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line < 0' \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "out-of-range query failed?" <<EOF
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line <= 0' \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time from access_log where log_line >= 0' \
+ -c ':switch-to-view db' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';select sc_bytes from access_log' \
+ -c ':spectrogram sc_bytes' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time,sc_bytes from access_log' \
+ -c ':spectrogram sc_byes' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time,c_ip from access_log' \
+ -c ':spectrogram c_ip' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test env TZ=UTC LC_NUMERIC=C ${lnav_test} -n \
+ -c ':spectrogram bro_response_body_len' \
+ ${test_dir}/logfile_bro_http.log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';select log_time,sc_bytes from access_log order by log_time desc' \
+ -c ':spectrogram sc_bytes' \
+ ${test_dir}/logfile_access_log.0
+
+cp ${srcdir}/logfile_syslog_with_mixed_times.0 logfile_syslog_with_mixed_times_test.0
+touch -t 201511030923 logfile_syslog_with_mixed_times_test.0
+run_test ${lnav_test} -n \
+ -c ";select log_time,log_actual_time from syslog_log" \
+ -c ':write-csv-to -' \
+ logfile_syslog_with_mixed_times_test.0
+
+check_output "log_actual_time column not working" <<EOF
+log_time,log_actual_time
+2015-09-13 00:58:45.000,2015-09-13 00:58:45.000
+2015-09-13 00:59:30.000,2015-09-13 00:59:30.000
+2015-09-13 01:23:54.000,2015-09-13 01:23:54.000
+2015-09-13 03:12:04.000,2015-09-13 03:12:04.000
+2015-09-13 03:12:04.000,2015-09-13 03:12:04.000
+2015-09-13 03:12:04.000,2015-09-13 01:25:39.000
+2015-09-13 03:12:04.000,2015-09-13 03:12:04.000
+2015-09-13 03:12:58.000,2015-09-13 03:12:58.000
+2015-09-13 03:46:03.000,2015-09-13 03:46:03.000
+2015-09-13 03:46:03.000,2015-09-13 03:46:03.000
+2015-09-13 03:46:03.000,2015-09-13 03:46:03.000
+2015-09-13 03:46:03.000,2015-09-13 03:13:16.000
+2015-09-13 03:46:03.000,2015-09-13 03:46:03.000
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";update access_log set log_part = 'middle' where log_line = 1" \
+ -c ';select log_line, log_part from access_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "setting log_part is not working" <<EOF
+log_line,log_part
+0,<NULL>
+1,middle
+2,middle
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";update access_log set log_part = 'middle' where log_line = 1" \
+ -c ";update access_log set log_part = NULL where log_line = 1" \
+ -c ';select log_line, log_part from access_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "setting log_part is not working" <<EOF
+log_line,log_part
+0,<NULL>
+1,<NULL>
+2,<NULL>
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";update access_log set log_part = 'middle' where log_line = 1" \
+ -c ";update access_log set log_part = NULL where log_line = 2" \
+ -c ';select log_line, log_part from access_log' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "setting log_part is not working" <<EOF
+log_line,log_part
+0,<NULL>
+1,middle
+2,middle
+EOF
+
+
+run_test ${lnav_test} -n \
+ -I "${top_srcdir}/test" \
+ -c ";select * from web_status" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "access_log table is not working" <<EOF
+group_concat(cs_uri_stem),sc_status
+"/vmw/cgi/tramp,/vmw/vSphere/default/vmkernel.gz",200
+/vmw/vSphere/default/vmkboot.gz,404
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";select * from access_log" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "access_log table is not working" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,c_ip,cs_method,cs_referer,cs_uri_query,cs_uri_stem,cs_user_agent,cs_username,cs_version,sc_bytes,sc_status,cs_host
+0,<NULL>,2009-07-20 22:59:26.000,0,info,0,<NULL>,<NULL>,<NULL>,192.168.202.254,GET,-,<NULL>,/vmw/cgi/tramp,gPXE/0.9.7,-,HTTP/1.0,134,200,<NULL>
+1,<NULL>,2009-07-20 22:59:29.000,3000,error,0,<NULL>,<NULL>,<NULL>,192.168.202.254,GET,-,<NULL>,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404,<NULL>
+2,<NULL>,2009-07-20 22:59:29.000,0,info,0,<NULL>,<NULL>,<NULL>,192.168.202.254,GET,-,<NULL>,/vmw/vSphere/default/vmkernel.gz,gPXE/0.9.7,-,HTTP/1.0,78929,200,<NULL>
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";select * from access_log where log_level >= 'warning'" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "loglevel collator is not working" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,c_ip,cs_method,cs_referer,cs_uri_query,cs_uri_stem,cs_user_agent,cs_username,cs_version,sc_bytes,sc_status,cs_host
+1,<NULL>,2009-07-20 22:59:29.000,3000,error,0,<NULL>,<NULL>,<NULL>,192.168.202.254,GET,-,<NULL>,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404,<NULL>
+EOF
+
+
+# XXX The timestamp on the file is used to determine the year for syslog files.
+touch -t 200711030923 ${test_dir}/logfile_syslog.0
+run_test ${lnav_test} -n \
+ -c ";select * from syslog_log" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.0
+
+check_output "syslog_log table is not working" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,log_hostname,log_msgid,log_pid,log_pri,log_procname,log_struct,log_syslog_tag,syslog_version
+0,<NULL>,2007-11-03 09:23:38.000,0,error,0,<NULL>,<NULL>,<NULL>,veridian,<NULL>,7998,<NULL>,automount,<NULL>,automount[7998],<NULL>
+1,<NULL>,2007-11-03 09:23:38.000,0,info,0,<NULL>,<NULL>,<NULL>,veridian,<NULL>,16442,<NULL>,automount,<NULL>,automount[16442],<NULL>
+2,<NULL>,2007-11-03 09:23:38.000,0,error,0,<NULL>,<NULL>,<NULL>,veridian,<NULL>,7999,<NULL>,automount,<NULL>,automount[7999],<NULL>
+3,<NULL>,2007-11-03 09:47:02.000,1404000,info,0,<NULL>,<NULL>,<NULL>,veridian,<NULL>,<NULL>,<NULL>,sudo,<NULL>,sudo,<NULL>
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";select * from syslog_log where log_time >= NULL" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.0
+
+check_output "log_time collation failed on null" <<EOF
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";select log_line from syslog_log where log_time >= datetime('2007-11-03T09:47:02.000')" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.0
+
+check_output "log_time collation is wrong" <<EOF
+log_line
+3
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ':filter-in sudo' \
+ -c ";select * from logline" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.0
+
+run_test ${lnav_test} -n \
+ -c ':goto 1' \
+ -c ";select log_line, log_pid, col_0 from logline" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.1
+
+check_output "logline table is not working" <<EOF
+log_line,log_pid,col_0
+1,16442,/auto/opt
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";select sc_bytes from logline" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "logline table is not working for defined columns" <<EOF
+sc_bytes
+134
+46210
+78929
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ':goto 1' \
+ -c ":summarize col_0" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog.1
+
+check_output "summarize is not working" <<EOF
+c_col_0,count_col_0
+/auto/opt,1
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \
+ -c ':write-to -' \
+ ${test_dir}/logfile_access_log.0
+
+export SQL_ENV_VALUE="foo bar,baz"
+
+run_test ${lnav_test} -n \
+ -c ';select $SQL_ENV_VALUE as val' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "env vars are not working in SQL" <<EOF
+val
+"foo bar,baz"
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';SELECT name,value FROM environ WHERE name = "SQL_ENV_VALUE"' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "environ table is not working in SQL" <<EOF
+name,value
+SQL_ENV_VALUE,"foo bar,baz"
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name) VALUES (null)' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name, value) VALUES (null, null)' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name, value) VALUES ("", null)' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name, value) VALUES ("foo=bar", "bar")' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar")' \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ';INSERT OR IGNORE INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar")' \
+ -c ';SELECT * FROM environ WHERE name = "SQL_ENV_VALUE"' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "insert into environ table works" <<EOF
+name,value
+SQL_ENV_VALUE,"foo bar,baz"
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';REPLACE INTO environ (name, value) VALUES ("SQL_ENV_VALUE", "bar")' \
+ -c ';SELECT * FROM environ WHERE name = "SQL_ENV_VALUE"' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "replace into environ table works" <<EOF
+name,value
+SQL_ENV_VALUE,bar
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';INSERT INTO environ (name, value) VALUES ("foo_env", "bar")' \
+ -c ';SELECT $foo_env as val' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "insert into environ table does not work" <<EOF
+val
+bar
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';UPDATE environ SET name="NEW_ENV_VALUE" WHERE name="SQL_ENV_VALUE"' \
+ -c ";SELECT * FROM environ WHERE name like '%ENV_VALUE'" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "update environ table does not work" <<EOF
+name,value
+NEW_ENV_VALUE,"foo bar,baz"
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';DELETE FROM environ WHERE name="SQL_ENV_VALUE"' \
+ -c ';SELECT * FROM environ WHERE name like "%ENV_VALUE"' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "delete from environ table does not work" <<EOF
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ';DELETE FROM environ' \
+ -c ';SELECT * FROM environ' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "delete environ table does not work" <<EOF
+EOF
+
+
+
+schema_dump() {
+ ${lnav_test} -n -c ';.schema' ${test_dir}/logfile_access_log.0 | head -n21
+}
+
+run_test schema_dump
+
+check_output "schema view is not working" <<EOF
+ATTACH DATABASE '' AS 'main';
+CREATE VIRTUAL TABLE environ USING environ_vtab_impl();
+CREATE VIRTUAL TABLE lnav_static_files USING lnav_static_file_vtab_impl();
+CREATE VIRTUAL TABLE lnav_views USING lnav_views_impl();
+CREATE VIRTUAL TABLE lnav_view_filter_stats USING lnav_view_filter_stats_impl();
+CREATE VIRTUAL TABLE lnav_view_files USING lnav_view_files_impl();
+CREATE VIRTUAL TABLE lnav_view_stack USING lnav_view_stack_impl();
+CREATE VIRTUAL TABLE lnav_view_filters USING lnav_view_filters_impl();
+CREATE VIRTUAL TABLE lnav_file USING lnav_file_impl();
+CREATE VIRTUAL TABLE lnav_file_metadata USING lnav_file_metadata_impl();
+CREATE VIEW lnav_view_filters_and_stats AS
+ SELECT * FROM lnav_view_filters LEFT NATURAL JOIN lnav_view_filter_stats;
+CREATE VIRTUAL TABLE regexp_capture USING regexp_capture_impl();
+CREATE VIRTUAL TABLE regexp_capture_into_json USING regexp_capture_into_json_impl();
+CREATE VIRTUAL TABLE xpath USING xpath_impl();
+CREATE VIRTUAL TABLE fstat USING fstat_impl();
+CREATE TABLE lnav_events (
+ ts TEXT NOT NULL DEFAULT(strftime('%Y-%m-%dT%H:%M:%f', 'now')),
+ content TEXT
+);
+CREATE TABLE http_status_codes
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ";select * from nonexistent_table" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";delete from access_log" \
+ ${test_dir}/logfile_access_log.0
+
+touch -t 201504070732 ${test_dir}/logfile_pretty.0
+run_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":partition-name middle" \
+ -c ":goto 21" \
+ -c ":partition-name end" \
+ -c ";select log_line,log_part,log_time from syslog_log" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_pretty.0
+
+check_output "partition-name does not work" <<EOF
+log_line,log_part,log_time
+0,<NULL>,2015-04-07 00:49:42.000
+1,middle,2015-04-07 05:49:53.000
+18,middle,2015-04-07 07:31:56.000
+20,middle,2015-04-07 07:31:56.000
+21,end,2015-04-07 07:31:56.000
+22,end,2015-04-07 07:32:56.000
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":partition-name middle" \
+ -c ":clear-partition" \
+ -c ";select log_line, log_part from access_log" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "clear-partition does not work" <<EOF
+log_line,log_part
+0,<NULL>
+1,<NULL>
+2,<NULL>
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":goto 1" \
+ -c ":partition-name middle" \
+ -c ":goto 2" \
+ -c ":clear-partition" \
+ -c ";select log_line, log_part from access_log" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "clear-partition does not work when in the middle of a part" <<EOF
+log_line,log_part
+0,<NULL>
+1,<NULL>
+2,<NULL>
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";SELECT * FROM openam_log" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_openam.0
+
+check_output "write-json-to isn't working?" <<EOF
+[
+ {
+ "log_line": 0,
+ "log_part": null,
+ "log_time": "2014-06-15 01:04:52.000",
+ "log_idle_msecs": 0,
+ "log_level": "info",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "contextid": "82e87195d704585501",
+ "data": "http://localhost:8086|/|<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"s2daac0735bf476f4560aab81104b623bedfb0cbc0\" InResponseTo=\"84cbf2be33f6410bbe55877545a93f02\" Version=\"2.0\" IssueInstant=\"2014-06-15T01:04:52Z\" Destination=\"http://localhost:8086/api/1/rest/admin/org/530e42ccd6f45fd16d0d0717/saml/consume\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://openam.vagrant.dev/openam</saml:Issuer><samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">\\\\n<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"\\\\nValue=\"urn:oasis:names:tc:SAML:2.0:status:Success\">\\\\n</samlp:StatusCode>\\\\n</samlp:Status><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"s2a0bee0da937e236167e99b209802056033816ac2\" IssueInstant=\"2014-06-15T01:04:52Z\" Version=\"2.0\">\\\\n<saml:Issuer>http://openam.vagrant.dev/openam</saml:Issuer><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\\\\n<ds:SignedInfo>\\\\n<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\\\\n<ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/>\\\\n<ds:Reference URI=\"#s2a0bee0da937e236167e99b209802056033816ac2\">\\\\n<ds:Transforms>\\\\n<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>\\\\n<ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>\\\\n</ds:Transforms>\\\\n<ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>\\\\n<ds:DigestValue>4uSmVzjovUdQd3px/RcnoxQBsqE=</ds:DigestValue>\\\\n</ds:Reference>\\\\n</ds:SignedInfo>\\\\n<ds:SignatureValue>\\\\nhm/grge36uA6j1OWif2bTcvVTwESjmuJa27NxepW0AiV5YlcsHDl7RAIk6k/CjsSero3bxGbm56m\\\\nYncOEi9F1Tu7dS0bfx+vhm/kKTPgwZctf4GWn4qQwP+KeoZywbNj9ShsYJ+zPKzXwN4xBSuPjMxP\\\\nNf5szzjEWpOndQO/uDs=\\\\n</ds:SignatureValue>\\\\n<ds:KeyInfo>\\\\n<ds:X509Data>\\\\n<ds:X509Certificate>\\\\nMIICQDCCAakCBEeNB0swDQYJKoZIhvcNAQEEBQAwZzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh\\\\nbGlmb3JuaWExFDASBgNVBAcTC1NhbnRhIENsYXJhMQwwCgYDVQQKEwNTdW4xEDAOBgNVBAsTB09w\\\\nZW5TU08xDTALBgNVBAMTBHRlc3QwHhcNMDgwMTE1MTkxOTM5WhcNMTgwMTEyMTkxOTM5WjBnMQsw\\\\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEUMBIGA1UEBxMLU2FudGEgQ2xhcmExDDAK\\\\nBgNVBAoTA1N1bjEQMA4GA1UECxMHT3BlblNTTzENMAsGA1UEAxMEdGVzdDCBnzANBgkqhkiG9w0B\\\\nAQEFAAOBjQAwgYkCgYEArSQc/U75GB2AtKhbGS5piiLkmJzqEsp64rDxbMJ+xDrye0EN/q1U5Of+\\\\nRkDsaN/igkAvV1cuXEgTL6RlafFPcUX7QxDhZBhsYF9pbwtMzi4A4su9hnxIhURebGEmxKW9qJNY\\\\nJs0Vo5+IgjxuEWnjnnVgHTs1+mq5QYTA7E6ZyL8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQB3Pw/U\\\\nQzPKTPTYi9upbFXlrAKMwtFf2OW4yvGWWvlcwcNSZJmTJ8ARvVYOMEVNbsT4OFcfu2/PeYoAdiDA\\\\ncGy/F2Zuj8XJJpuQRSE6PtQqBuDEHjjmOQJ0rV/r8mO1ZCtHRhpZ5zYRjhRC9eCbjx9VrFax0JDC\\\\n/FfwWigmrW0Y0Q==\\\\n</ds:X509Certificate>\\\\n</ds:X509Data>\\\\n</ds:KeyInfo>\\\\n</ds:Signature><saml:Subject>\\\\n<saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\" NameQualifier=\"http://openam.vagrant.dev/openam\">user@example.com</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\\\\n<saml:SubjectConfirmationData InResponseTo=\"84cbf2be33f6410bbe55877545a93f02\" NotOnOrAfter=\"2014-06-15T01:14:52Z\" Recipient=\"http://localhost:8086/api/1/rest/admin/org/530e42ccd6f45fd16d0d0717/saml/consume\"/></saml:SubjectConfirmation>\\\\n</saml:Subject><saml:Conditions NotBefore=\"2014-06-15T00:54:52Z\" NotOnOrAfter=\"2014-06-15T01:14:52Z\">\\\\n<saml:AudienceRestriction>\\\\n<saml:Audience>http://localhost:8086</saml:Audience>\\\\n</saml:AudienceRestriction>\\\\n</saml:Conditions>\\\\n<saml:AuthnStatement AuthnInstant=\"2014-06-15T01:00:25Z\" SessionIndex=\"s2f9b4d4b453d12b40ef3905cc959cdb40579c2301\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>",
+ "domain": "dc=openam",
+ "hostname": "192.168.33.1\t",
+ "ipaddr": "Not Available",
+ "loggedby": "cn=dsameuser,ou=DSAME Users,dc=openam",
+ "loginid": "id=openamuser,ou=user,dc=openam",
+ "messageid": "SAML2-37",
+ "modulename": "SAML2.access",
+ "nameid": "user@example.com"
+ },
+ {
+ "log_line": 1,
+ "log_part": null,
+ "log_time": "2014-06-15 01:04:52.000",
+ "log_idle_msecs": 0,
+ "log_level": "trace",
+ "log_mark": 0,
+ "log_comment": null,
+ "log_tags": null,
+ "log_filters": null,
+ "contextid": "ec5708a7f199678a01",
+ "data": "vagrant|/",
+ "domain": "dc=openam",
+ "hostname": "127.0.1.1\t",
+ "ipaddr": "Not Available",
+ "loggedby": "cn=dsameuser,ou=DSAME Users,dc=openam",
+ "loginid": "cn=dsameuser,ou=DSAME Users,dc=openam",
+ "messageid": "COT-22",
+ "modulename": "COT.access",
+ "nameid": "Not Available"
+ }
+]
+EOF
+
+run_cap_test ${lnav_test} -d "/tmp/lnav.err" -n \
+ -c ";select log_line, col_0 from logline" \
+ ${test_dir}/logfile_for_join.0
+
+run_cap_test ${lnav_test} -d "/tmp/lnav.err" -n \
+ -c ";select col_0 from logline where log_line > 4" \
+ ${test_dir}/logfile_for_join.0
+
+run_test ${lnav_test} -d "/tmp/lnav.err" -n \
+ -c ":goto 1" \
+ -c ":create-logline-table join_group" \
+ -c ":goto 2" \
+ -c ";select logline.log_line as llline, join_group.log_line as jgline from logline, join_group where logline.col_0 = join_group.col_2" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_for_join.0
+
+check_output "create-logline-table is not working" <<EOF
+llline,jgline
+2,1
+2,8
+9,1
+9,8
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ";select log_body from syslog_log where log_procname = 'automount'" \
+ < ${test_dir}/logfile_syslog.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";select log_body from syslog_log where log_procname = 'sudo'" \
+ < ${test_dir}/logfile_syslog.0
+
+# Create a dummy database for the next couple of tests to consume.
+touch empty
+rm simple-db.db
+run_test ${lnav_test} -n \
+ -c ";ATTACH DATABASE 'simple-db.db' as 'db'" \
+ -c ";CREATE TABLE IF NOT EXISTS db.person ( id integer PRIMARY KEY, first_name text, last_name, age integer )" \
+ -c ";INSERT INTO db.person(id, first_name, last_name, age) VALUES (0, 'Phil', 'Myman', 30)" \
+ -c ";INSERT INTO db.person(id, first_name, last_name, age) VALUES (1, 'Lem', 'Hewitt', 35)" \
+ -c ";DETACH DATABASE 'db'" \
+ empty
+
+check_output "Could not create db?" <<EOF
+EOF
+
+# Test to see if lnav can recognize a sqlite3 db file passed in as an argument.
+run_cap_test ${lnav_test} -n -c ";select * from person order by age asc" \
+ simple-db.db
+
+# Test to see if lnav can recognize a sqlite3 db file passed in as an argument.
+# XXX: Need to pass in a file, otherwise lnav keeps trying to open syslog
+# and we might not have sufficient privileges on the system the tests are being
+# run on.
+run_cap_test ${lnav_test} -n \
+ -c ";attach database 'simple-db.db' as 'db'" \
+ -c ';select * from person order by age asc' \
+ empty
+
+# Test to see if we can attach a database in LNAVSECURE mode.
+export LNAVSECURE=1
+
+run_cap_test ${lnav_test} -n \
+ -c ";attach database 'simple-db.db' as 'db'" \
+ empty
+
+run_cap_test ${lnav_test} -n \
+ -c ";attach database ':memdb:' as 'db'" \
+ empty
+
+run_cap_test ${lnav_test} -n \
+ -c ";attach database '/tmp/memdb' as 'db'" \
+ empty
+
+run_cap_test ${lnav_test} -n \
+ -c ";attach database 'file:memdb?cache=shared' as 'db'" \
+ empty
+
+unset LNAVSECURE
+
+
+touch -t 201503240923 ${test_dir}/logfile_syslog_with_access_log.0
+run_test ${lnav_test} -n -d /tmp/lnav.err \
+ -c ";select * from access_log" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_syslog_with_access_log.0
+
+check_output "access_log not found within syslog file" <<EOF
+log_line,log_part,log_time,log_idle_msecs,log_level,log_mark,log_comment,log_tags,log_filters,c_ip,cs_method,cs_referer,cs_uri_query,cs_uri_stem,cs_user_agent,cs_username,cs_version,sc_bytes,sc_status,cs_host
+1,<NULL>,2015-03-24 14:02:50.000,6927348000,info,0,<NULL>,<NULL>,<NULL>,127.0.0.1,GET,<NULL>,<NULL>,/includes/js/combined-javascript.js,<NULL>,-,HTTP/1.1,65508,200,<NULL>
+2,<NULL>,2015-03-24 14:02:50.000,0,error,0,<NULL>,<NULL>,<NULL>,127.0.0.1,GET,<NULL>,<NULL>,/bad.foo,<NULL>,-,HTTP/1.1,65508,404,<NULL>
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";select log_text from generic_log" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "multiline data is not right?" <<EOF
+[
+ {
+ "log_text": "2009-07-20 22:59:27,672:DEBUG:Hello, World!\n How are you today?"
+ },
+ {
+ "log_text": "2009-07-20 22:59:30,221:ERROR:Goodbye, World!"
+ }
+]
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";select log_text from generic_log where log_line = 1" \
+ -c ":write-json-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "able to select a continued line?" <<EOF
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ":create-search-table search_test1 (\w+), world!" \
+ -c ";select col_0 from search_test1" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "create-search-table is not working?" <<EOF
+col_0
+Hello
+Goodbye
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":create-search-table search_test1 (\w+), World!" \
+ -c ";select col_0 from search_test1 where log_line > 0" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "create-search-table is not working with where clause?" <<EOF
+col_0
+Goodbye
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":create-search-table search_test1 (?<word>\w+), World!" \
+ -c ";select word, typeof(word) from search_test1" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "create-search-table is not working?" <<EOF
+word,typeof(word)
+Hello,text
+Goodbye,text
+EOF
+
+run_test ${lnav_test} -n \
+ -c ":create-search-table search_test1 eth(?<ethnum>\d+)" \
+ -c ";select typeof(ethnum) from search_test1" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_syslog.2
+
+check_output "regex type guessing is not working?" <<EOF
+typeof(ethnum)
+integer
+integer
+integer
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ":delete-search-table search_test1" \
+ ${test_dir}/logfile_multiline.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":create-logline-table search_test1" \
+ -c ":delete-search-table search_test1" \
+ ${test_dir}/logfile_multiline.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":create-search-table search_test1 bad(" \
+ ${test_dir}/logfile_multiline.0
+
+NULL_GRAPH_SELECT_1=$(cat <<EOF
+;SELECT value FROM (
+ SELECT 10 as value
+ UNION ALL SELECT null as value)
+EOF
+)
+
+run_test ${lnav_test} -n \
+ -c "$NULL_GRAPH_SELECT_1" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_multiline.0
+
+check_output "number column with null does not work?" <<EOF
+value
+10
+<NULL>
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";SELECT regexp_capture.content FROM access_log, regexp_capture(access_log.cs_version, 'HTTP/(\d+\.\d+)') WHERE regexp_capture.capture_index = 1" \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "joining log table with regexp_capture is not working?" <<EOF
+content
+1.0
+1.0
+1.0
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT echoln(sc_bytes), 123 FROM access_log' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT lnav_top_file()' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ':switch-to-view db' \
+ -c ';SELECT lnav_top_file()' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -Nn \
+ -c ";select *,case match_index when 2 then replicate('abc', 1000) else '' end from regexp_capture_into_json('10;50;50;50;', '(\d+);')"
diff --git a/test/test_sql_anno.sh b/test/test_sql_anno.sh
new file mode 100644
index 0000000..e09c312
--- /dev/null
+++ b/test/test_sql_anno.sh
@@ -0,0 +1,50 @@
+#! /bin/bash
+
+# basic query
+run_cap_test ./drive_sql_anno "SELECT * FROM FOO"
+
+# no help for keyword flag
+run_cap_test ./drive_sql_anno "TABLE"
+
+# nested function calls
+run_cap_test ./drive_sql_anno "SELECT foo(bar())"
+
+# nested function calls
+run_cap_test ./drive_sql_anno "SELECT foo(bar())" 2
+
+# caret in keyword whitespace
+run_cap_test ./drive_sql_anno "SELECT lower(abc)" 9
+
+# caret in function whitespace
+run_cap_test ./drive_sql_anno "SELECT lower( abc )" 14
+
+# caret in unfinished function call
+run_cap_test ./drive_sql_anno "SELECT lower(abc" 16
+
+# caret on the outer function
+run_cap_test ./drive_sql_anno "SELECT instr(lower(abc), '123')" 9
+
+# caret on a nested function
+run_cap_test ./drive_sql_anno "SELECT instr(lower(abc), '123')" 15
+
+# caret on a flag
+run_cap_test ./drive_sql_anno "SELECT instr(lower(abc), '123') FROM bar" 30
+
+# multiple help hits
+run_cap_test ./drive_sql_anno "CREATE" 2
+
+# string vs ident
+run_cap_test ./drive_sql_anno "SELECT 'hello, world!' FROM \"my table\""
+
+# math
+run_cap_test ./drive_sql_anno "SELECT (1 + 2) AS three"
+
+run_cap_test ./drive_sql_anno "SELECT (1.5 + 2.2) AS decim"
+
+# subqueries
+run_cap_test ./drive_sql_anno "SELECT * FROM (SELECT foo, bar FROM baz)"
+
+run_cap_test ./drive_sql_anno \
+ "SELECT * from vmw_log, regexp_capture(log_body, '--> /SessionStats/SessionPool/Session/(?<line>[abc]+)')"
+
+run_cap_test ./drive_sql_anno "SELECT * FROM foo.bar"
diff --git a/test/test_sql_coll_func.sh b/test/test_sql_coll_func.sh
new file mode 100644
index 0000000..2e61f9a
--- /dev/null
+++ b/test/test_sql_coll_func.sh
@@ -0,0 +1,29 @@
+#! /bin/bash
+
+run_cap_test ./drive_sql "select '192.168.1.10' < '192.168.1.2'"
+
+run_cap_test ./drive_sql "select '192.168.1.10' < '192.168.1.2' collate ipaddress"
+
+run_cap_test ./drive_sql "select '192.168.1.10' < '192.168.1.12' collate ipaddress"
+
+run_cap_test ./drive_sql "select '::ffff:192.168.1.10' = '192.168.1.10' collate ipaddress"
+
+run_cap_test ./drive_sql "select 'fe80::a85f:80b4:5cbe:8691' = 'fe80:0000:0000:0000:a85f:80b4:5cbe:8691' collate ipaddress"
+
+run_cap_test ./drive_sql "select '' < '192.168.1.2' collate ipaddress"
+
+run_cap_test ./drive_sql "select '192.168.1.2' > '' collate ipaddress"
+
+run_cap_test ./drive_sql "select '192.168.1.2' < 'fe80::a85f:80b4:5cbe:8691' collate ipaddress"
+
+run_cap_test ./drive_sql "select 'h9.example.com' < 'h10.example.com' collate ipaddress"
+
+run_cap_test ./drive_sql "select 'file10.txt' < 'file2.txt'"
+
+run_cap_test ./drive_sql "select 'file10.txt' < 'file2.txt' collate naturalcase"
+
+run_cap_test ./drive_sql "select 'w' < 'e' collate loglevel"
+
+run_cap_test ./drive_sql "select 'e' < 'w' collate loglevel"
+
+run_cap_test ./drive_sql "select 'info' collate loglevel between 'trace' and 'fatal'"
diff --git a/test/test_sql_fs_func.sh b/test/test_sql_fs_func.sh
new file mode 100644
index 0000000..e3da92b
--- /dev/null
+++ b/test/test_sql_fs_func.sh
@@ -0,0 +1,53 @@
+#! /bin/bash
+
+run_cap_test ./drive_sql "select readlink('non-existent-link')"
+
+ln -sf sql_fs_readlink_test sql_fs_readlink_test.lnk
+run_cap_test ./drive_sql "select readlink('sql_fs_readlink_test.lnk')"
+rm sql_fs_readlink_test.lnk
+
+run_cap_test ./drive_sql "select realpath('non-existent-path')"
+
+# ln -sf drive_sql sql_fs_realpath_test.lnk
+# run_cap_test ./drive_sql "select realpath('sql_fs_realpath_test.lnk')"
+# rm sql_fs_realpath_test.lnk
+
+run_cap_test ./drive_sql "select basename('')"
+
+run_cap_test ./drive_sql "select basename('/')"
+
+run_cap_test ./drive_sql "select basename('//')"
+
+run_cap_test ./drive_sql "select basename('/foo')"
+
+run_cap_test ./drive_sql "select basename('foo/bar')"
+
+run_cap_test ./drive_sql "select basename('/foo/')"
+
+run_cap_test ./drive_sql "select basename('/foo///')"
+
+run_cap_test ./drive_sql "select basename('foo')"
+
+run_cap_test ./drive_sql "select dirname('')"
+
+run_cap_test ./drive_sql "select dirname('foo')"
+
+run_cap_test ./drive_sql "select dirname('foo///')"
+
+run_cap_test ./drive_sql "select dirname('/foo/bar')"
+
+run_cap_test ./drive_sql "select dirname('/')"
+
+run_cap_test ./drive_sql "select dirname('/foo')"
+
+run_cap_test ./drive_sql "select dirname('/foo//')"
+
+run_cap_test ./drive_sql "select dirname('foo//')"
+
+run_cap_test ./drive_sql "select joinpath()"
+
+run_cap_test ./drive_sql "select joinpath('foo')"
+
+run_cap_test ./drive_sql "select joinpath('foo', 'bar', 'baz')"
+
+run_cap_test ./drive_sql "select joinpath('foo', 'bar', 'baz', '/root')"
diff --git a/test/test_sql_indexes.sh b/test/test_sql_indexes.sh
new file mode 100644
index 0000000..951c7a6
--- /dev/null
+++ b/test/test_sql_indexes.sh
@@ -0,0 +1,45 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+# XXX sqlite reports different results for the "detail" column, so we
+# have to rewrite it.
+run_cap_test ${lnav_test} -n \
+ -c ";EXPLAIN QUERY PLAN SELECT * FROM access_log WHERE log_path GLOB '*/logfile_access_log.*'" \
+ -c ";SELECT \$id, \$parent, \$notused, replace(\$detail, 'SCAN TABLE', 'SCAN')" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT *,log_unique_path FROM access_log WHERE log_path GLOB '*/logfile_access_log.*'" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";EXPLAIN QUERY PLAN SELECT * FROM all_logs WHERE log_format = 'access_log'" \
+ -c ";SELECT \$id, \$parent, \$notused, replace(\$detail, 'SCAN TABLE', 'SCAN')" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT *,log_format FROM all_logs WHERE log_format = 'access_log'" \
+ ${test_dir}/logfile_access_log.* \
+ ${test_dir}/logfile_procstate.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";EXPLAIN QUERY PLAN SELECT * FROM all_logs WHERE log_level < 'error'" \
+ -c ";SELECT \$id, \$parent, \$notused, replace(\$detail, 'SCAN TABLE', 'SCAN')" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM all_logs WHERE log_level < 'error'" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM all_logs WHERE log_level <= 'error'" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM all_logs WHERE log_level >= 'error'" \
+ ${test_dir}/logfile_access_log.*
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM all_logs WHERE log_level > 'error'" \
+ ${test_dir}/logfile_access_log.*
diff --git a/test/test_sql_json_func.sh b/test/test_sql_json_func.sh
new file mode 100644
index 0000000..0865c45
--- /dev/null
+++ b/test/test_sql_json_func.sh
@@ -0,0 +1,132 @@
+#! /bin/bash
+
+run_cap_test ./drive_sql "select json_concat('[null,', 1.0, 2.0)"
+
+run_cap_test ./drive_sql "select json_concat(json('[null, true, 0]'), 1.0, 2.0)"
+
+run_cap_test ./drive_sql "select json_concat(json('[\"tag0\"]'), 'tag1', 'tag2')"
+
+run_cap_test ./drive_sql "select json_concat(NULL, NULL)"
+
+run_cap_test ./drive_sql "select json_concat(NULL, json('{\"abc\": 1}'))"
+
+run_cap_test ./drive_sql "select json_contains(NULL, 4)"
+
+run_cap_test ./drive_sql "select json_contains('', 4)"
+
+run_cap_test ./drive_sql "select json_contains('null', NULL)"
+
+run_cap_test ./drive_sql "select json_contains('[[0]]', 0)"
+
+run_cap_test ./drive_sql "select json_contains('4', 4)"
+
+run_cap_test ./drive_sql "select json_contains('4', 2)"
+
+run_cap_test env TEST_COMMENT='contains1' ./drive_sql <<EOF
+select json_contains('"hi"', 'hi')
+EOF
+
+run_cap_test env TEST_COMMENT='contains1.5' ./drive_sql <<EOF
+select json_contains('"hi"', 'hi there')
+EOF
+
+run_cap_test env TEST_COMMENT='contains2' ./drive_sql <<EOF
+select json_contains('["hi", "bye"]', 'hola') as res
+EOF
+
+run_cap_test env TEST_COMMENT='contains3' ./drive_sql <<EOF
+select json_contains('["hi", "bye", "solong"]', 'bye') as res
+EOF
+
+run_cap_test env TEST_COMMENT='contains4' ./drive_sql <<EOF
+select json_contains('["hi", "bye", "solong]', 'bye') as res
+EOF
+
+run_cap_test ./drive_sql "select jget()"
+
+run_cap_test ./drive_sql "select jget('[123, true', '/0')"
+
+run_cap_test ./drive_sql "select jget('4', '')"
+
+run_cap_test ./drive_sql "select jget('4', null)"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/3')"
+
+run_cap_test ./drive_sql "select typeof(jget('[null, true, 20, 30, 40]', '/3'))"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40, {\"msg\": \"Hello\"}]', '/5')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40, {\"msg\": \"Hello\"}]', '/5/msg')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40, {\"msg\": \"Hello\"}]', '')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/abc')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/abc', 1)"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/0')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40]', '/0/foo')"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 4.0]', '/4')"
+
+run_cap_test ./drive_sql "select typeof(jget('[null, true, 20, 30, 4.0]', '/4'))"
+
+run_cap_test ./drive_sql "select jget('[null, true, 20, 30, 40', '/0/foo')"
+
+run_cap_test ./drive_sql "select json_group_object(key) from (select 1 as key)"
+
+GROUP_SELECT_1=$(cat <<EOF
+SELECT id, json_group_object(key, value) as stack FROM (
+ SELECT 1 as id, 'key1' as key, 10 as value
+ UNION ALL SELECT 1 as id, 'key2' as key, 20 as value
+ UNION ALL SELECT 1 as id, 'key3' as key, 30 as value)
+EOF
+)
+
+run_cap_test ./drive_sql "$GROUP_SELECT_1"
+
+GROUP_SELECT_2=$(cat <<EOF
+SELECT id, json_group_object(key, value) as stack FROM (
+ SELECT 1 as id, 1 as key, 10 as value
+ UNION ALL SELECT 1 as id, 2 as key, null as value
+ UNION ALL SELECT 1 as id, 3 as key, 30.5 as value)
+EOF
+)
+
+run_cap_test ./drive_sql "$GROUP_SELECT_2"
+
+if test x"$HAVE_SQLITE3_VALUE_SUBTYPE" != x""; then
+ GROUP_SELECT_3=$(cat <<EOF
+SELECT id, json_group_object(key, json(value)) as stack FROM (
+ SELECT 1 as id, 1 as key, 10 as value
+ UNION ALL SELECT 1 as id, 2 as key, json_array(1, 2, 3) as value
+ UNION ALL SELECT 1 as id, 3 as key, 30.5 as value)
+EOF
+)
+
+ run_cap_test ./drive_sql "$GROUP_SELECT_3"
+fi
+
+
+GROUP_ARRAY_SELECT_1=$(cat <<EOF
+SELECT json_group_array(value) as stack FROM (
+ SELECT 10 as value
+ UNION ALL SELECT null as value
+ UNION ALL SELECT 'hello' as value)
+EOF
+)
+
+run_cap_test ./drive_sql "$GROUP_ARRAY_SELECT_1"
+
+GROUP_ARRAY_SELECT_2=$(cat <<EOF
+SELECT json_group_array(value, value * 10) as stack FROM (
+ SELECT 10 as value
+ UNION ALL SELECT 20 as value
+ UNION ALL SELECT 30 as value)
+EOF
+)
+
+run_cap_test ./drive_sql "$GROUP_ARRAY_SELECT_2"
+
+run_cap_test ./drive_sql "SELECT json_group_array(column1) FROM (VALUES (1)) WHERE 0" \ No newline at end of file
diff --git a/test/test_sql_regexp.sh b/test/test_sql_regexp.sh
new file mode 100644
index 0000000..d2fc5f8
--- /dev/null
+++ b/test/test_sql_regexp.sh
@@ -0,0 +1,30 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * FROM syslog_log, regexp_capture_into_json(log_body, '"'"'"(?<value>[^"'"'"]+)')" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_syslog.3
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * from regexp_capture_into_json('foo=0x123e;', '(?<key>\w+)=(?<value>[^;]+)')" \
+ ${test_dir}/logfile_syslog.3
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * from regexp_capture_into_json('foo=0x123e;', '(?<key>\w+)=(?<value>[^;]+)', json_object('convert-numbers', json('false')))" \
+ ${test_dir}/logfile_syslog.3
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * from regexp_capture_into_json('foo=0x123e;', '(?<key>\w+)=(?<value>[^;]+)', '{abc')" \
+ ${test_dir}/logfile_syslog.3
+
+run_cap_test ${lnav_test} -n \
+ -c ";SELECT * from regexp_capture_into_json('foo=123e;', '(?<key>\w+)=(?<value>[^;]+)')" \
+ ${test_dir}/logfile_syslog.3
+
+run_cap_test ${lnav_test} -nN \
+ -c ";SELECT * from regexp_capture('abc=def;ghi=jkl;', '^(\w+)=([^;]+);')"
+
+run_cap_test ${lnav_test} -nN \
+ -c ";SELECT * from regexp_capture_into_json('abc=def;ghi=jkl;', '^(\w+)=([^;]+);')"
diff --git a/test/test_sql_search_table.sh b/test/test_sql_search_table.sh
new file mode 100644
index 0000000..4976286
--- /dev/null
+++ b/test/test_sql_search_table.sh
@@ -0,0 +1,26 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT * FROM procstate_procs' \
+ ${test_dir}/logfile_procstate.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT *,log_body FROM vpx_lro_begin' \
+ ${test_dir}/logfile_vpxd.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";select * from vpx_lro_begin where log_line > 3 and lro_id = 'lro-846064'" \
+ -c ";select * from vpx_lro_begin where lro_id = 'lro-846064'" \
+ ${test_dir}/logfile_vpxd.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";select * from procstate_procs where cmd_name = '[kthreadd]'" \
+ -c ";select * from procstate_procs where cmd_name = '[kthreadd]'" \
+ ${test_dir}/logfile_procstate.0
+
+run_cap_test ${lnav_test} -n \
+ -c ':create-search-table asl_mod ASL Module "(?<name>[^"]+)"' \
+ -c ';SELECT * FROM asl_mod' \
+ ${test_dir}/logfile_syslog.3
diff --git a/test/test_sql_str_func.sh b/test/test_sql_str_func.sh
new file mode 100644
index 0000000..4c58214
--- /dev/null
+++ b/test/test_sql_str_func.sh
@@ -0,0 +1,170 @@
+#! /bin/bash
+
+run_cap_test ./drive_sql "select length(gzip(1))"
+
+run_cap_test ./drive_sql "select gunzip(gzip(1))"
+
+run_cap_test ./drive_sql "select humanize_file_size()"
+
+run_cap_test ./drive_sql "select humanize_file_size('abc')"
+
+run_cap_test ./drive_sql "select humanize_file_size(1, 2)"
+
+run_cap_test ./drive_sql "select humanize_file_size(10 * 1000 * 1000)"
+
+run_cap_test ./drive_sql "select startswith('.foo', '.')"
+
+run_cap_test ./drive_sql "select startswith('foo', '.')"
+
+run_cap_test ./drive_sql "select endswith('foo', '.')"
+
+run_cap_test ./drive_sql "select endswith('foo.', '.')"
+
+run_cap_test ./drive_sql "select endswith('foo.txt', '.txt')"
+
+run_cap_test ./drive_sql "select endswith('a', '.txt')"
+
+run_cap_test ./drive_sql "select regexp('abcd', 'abcd')"
+
+run_cap_test ./drive_sql "select regexp('bc', 'abcd')"
+
+run_cap_test ./drive_sql "select regexp('[e-z]+', 'abcd')"
+
+run_cap_test ./drive_sql "select regexp('[e-z]+', 'ea')"
+
+run_cap_test ./drive_sql "select regexp_replace('test 1 2 3', '\\d+', 'N')"
+
+run_cap_test env TEST_COMMENT=regexp_replace_with_bs1 ./drive_sql <<'EOF'
+select regexp_replace('test 1 2 3', '\s+', '{\0}') as repl
+EOF
+
+run_cap_test env TEST_COMMENT=regexp_replace_with_bs2 ./drive_sql <<'EOF'
+select regexp_replace('test 1 2 3', '\w*', '{\0}') as repl
+EOF
+
+run_cap_test ./drive_sql "select regexp_replace('123 abc', '(\w*)', '<\3>') as repl"
+
+run_cap_test env TEST_COMMENT=regexp_replace_with_bs3 ./drive_sql <<'EOF'
+select regexp_replace('123 abc', '(\w*)', '<\\>') as repl
+EOF
+
+run_cap_test ./drive_sql "select regexp_replace('abc: def', '(\w*):\s*(.*)', '\1=\2') as repl"
+
+run_cap_test ./drive_sql "select regexp_match('abc', 'abc')"
+
+run_cap_test ./drive_sql "select regexp_match(null, 'abc')"
+
+run_cap_test ./drive_sql "select regexp_match('abc', null) as result"
+
+run_cap_test ./drive_sql "select typeof(result), result from (select regexp_match('(\d*)abc', 'abc') as result)"
+
+run_cap_test ./drive_sql "select typeof(result), result from (select regexp_match('(\d*)abc(\d*)', 'abc') as result)"
+
+run_cap_test ./drive_sql "select typeof(result), result from (select regexp_match('(\d+)', '123') as result)"
+
+run_cap_test ./drive_sql "select typeof(result), result from (select regexp_match('a(\d+\.\d+)a', 'a123.456a') as result)"
+
+run_cap_test ./drive_sql "select regexp_match('foo=(?<foo>\w+); (\w+)', 'foo=abc; 123') as result"
+
+run_cap_test ./drive_sql "select regexp_match('foo=(?<foo>\w+); (\w+\.\w+)', 'foo=abc; 123.456') as result"
+
+run_cap_test ${lnav_test} -nN \
+ -c ";SELECT regexp_match('^(\w+)=([^;]+);', 'abc=def;ghi=jkl;')"
+
+run_cap_test ./drive_sql "select extract('foo=1') as result"
+
+run_cap_test ./drive_sql "select extract('foo=1; bar=2') as result"
+
+run_cap_test ./drive_sql "select extract(null) as result"
+
+run_cap_test ./drive_sql "select extract(1) as result"
+
+run_cap_test ./drive_sql "select logfmt2json('foo=1 bar=2 baz=2e1 msg=hello') as result"
+
+run_cap_test ./drive_sql "SELECT substr('#foo', range_start) AS value FROM regexp_capture('#foo', '(\w+)') WHERE capture_index = 1"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar', '\w+ (\w+)')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar', '\w+ \w+')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar', '\w+ (?<word>\w+)')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar', '(bar)|\w+ (?<word>\w+)')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture()"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo bar', '(')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('1 2 3 45', '(\d+)')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture('foo foo', '^foo')"
+
+run_cap_test ./drive_sql "SELECT * FROM regexp_capture_into_json('foo=1 bar=2; foo=3 bar=4', 'foo=(\d+) bar=(\d+)')"
+
+run_cap_test ./drive_sql "SELECT encode('foo', 'bar')"
+
+run_cap_test ./drive_sql "SELECT encode('foo', null)"
+
+run_cap_test ./drive_sql "SELECT encode(null, 'base64')"
+
+run_cap_test ./drive_sql "SELECT gunzip(decode(encode(gzip('Hello, World!'), 'base64'), 'base64'))"
+
+run_cap_test env TEST_COMMENT=invalid_url ./drive_sql <<'EOF'
+SELECT parse_url('https://bad@[fe::')
+EOF
+
+run_cap_test env TEST_COMMENT=unsupported_url ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com:100000')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url1 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url2 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com/')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url3 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com/search?flag')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url4 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com/search?flag&flag2')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url5 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com/search?flag&flag2&=def')
+EOF
+
+run_cap_test env TEST_COMMENT=parse_url6 ./drive_sql <<'EOF'
+SELECT parse_url('https://example.com/sea%26rch?flag&flag2&=def#frag1%20space')
+EOF
+
+
+run_cap_test env TEST_COMMENT=unparse_url3 ./drive_sql <<'EOF'
+SELECT unparse_url(parse_url('https://example.com/search?flag'))
+EOF
+
+run_cap_test env TEST_COMMENT=unparse_url4 ./drive_sql <<'EOF'
+SELECT unparse_url(parse_url('https://example.com/search?flag&flag2'))
+EOF
+
+run_cap_test env TEST_COMMENT=unparse_url5 ./drive_sql <<'EOF'
+SELECT unparse_url(parse_url('https://example.com/search?flag&flag2&=def'))
+EOF
+
+run_cap_test env TEST_COMMENT=unparse_url6 ./drive_sql <<'EOF'
+SELECT unparse_url(parse_url('https://example.com/search?flag&flag2&=def#frag1%20space'))
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT log_body, extract(log_body) from vmw_log' \
+ -c ':write-json-to -' \
+ ${test_dir}/logfile_vmw_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT anonymize(bro_id_resp_h) FROM bro_http_log' \
+ ${test_dir}/logfile_bro_http.log.0
diff --git a/test/test_sql_time_func.sh b/test/test_sql_time_func.sh
new file mode 100644
index 0000000..181dd70
--- /dev/null
+++ b/test/test_sql_time_func.sh
@@ -0,0 +1,71 @@
+#! /bin/bash
+
+# timeslice('blah')
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', 'blah')"
+
+# before 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', 'before fri')"
+
+# not before 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 11:59:00', 'after fri')"
+
+# not before 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 11:59:00', 'fri')"
+
+# before 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', 'before 12pm')"
+
+# not before 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 11:59:00', 'before 12pm')"
+
+# after 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', 'after 12pm')"
+
+# not after 12pm
+run_cap_test ./drive_sql "select timeslice('2015-08-07 11:59:00', 'after 12pm')"
+
+# timeslice()
+run_cap_test ./drive_sql "select timeslice()"
+
+# timeslice('2015-02-01T05:10:00')
+run_cap_test ./drive_sql "select timeslice('2015-02-01T05:10:00')"
+
+# timeslice empty
+run_cap_test ./drive_sql "select timeslice('', '')"
+
+# timeslice abs
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', '8 am')"
+
+# timeslice abs
+run_cap_test ./drive_sql "select timeslice('2015-08-07 08:00:33', '8 am')"
+
+# timeslice abs
+run_cap_test ./drive_sql "select timeslice('2015-08-07 08:01:33', '8 am')"
+
+# timeslice(null, null)
+run_cap_test ./drive_sql "select timeslice(null, null)"
+
+# timeslice(null)
+run_cap_test ./drive_sql "select timeslice(null)"
+
+# 100ms slice
+run_cap_test ./drive_sql "select timeslice(1616300753.333, '100ms')"
+
+# timeslice 5m
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', '5m')"
+
+# timeslice 1d
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', '1d')"
+
+# XXX This is wrong...
+# timeslice 1 month
+run_cap_test ./drive_sql "select timeslice('2015-08-07 12:01:00', '1 month')"
+
+# timeslice ms
+run_cap_test ./drive_sql "select timediff('2017-01-02T05:00:00.100', '2017-01-02T05:00:00.000')"
+
+# timeslice day
+run_cap_test ./drive_sql "select timediff('today', 'yesterday')"
+
+# timeslice day
+run_cap_test ./drive_sql "select timediff('foo', 'yesterday')"
diff --git a/test/test_sql_views_vtab.sh b/test/test_sql_views_vtab.sh
new file mode 100644
index 0000000..6b356f5
--- /dev/null
+++ b/test/test_sql_views_vtab.sh
@@ -0,0 +1,173 @@
+#! /bin/bash
+
+export YES_COLOR=1
+unset XDG_CONFIG_HOME
+
+run_test ${lnav_test} -n \
+ -c ";SELECT view_name,basename(filepath),visible FROM lnav_view_files" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_access_log.*
+
+check_output "lnav_view_files does not work?" <<EOF
+view_name,basename(filepath),visible
+log,logfile_access_log.0,1
+log,logfile_access_log.1,1
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_view_files SET visible=0 WHERE endswith(filepath, 'log.0')" \
+ ${test_dir}/logfile_access_log.*
+
+run_test ${lnav_test} -n \
+ -c ";DELETE FROM lnav_view_stack" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "deleting the view stack does not work?" <<EOF
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_view_stack SET name = 'foo'" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_stack VALUES ('help')" \
+ -c ";DELETE FROM lnav_view_stack WHERE name = 'log'" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', '')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters VALUES ('log', 0, 1, 'out', 'regex', 'abc(')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters VALUES ('bad', 0, 1, 'out', 'regex', 'abc')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters VALUES (NULL, 0, 1, 'out', 'regex', 'abc')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters VALUES ('log', 0 , 1, 'bad', 'regex', 'abc')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern) VALUES ('log', 'vmk')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk', 'in')" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk', 'in')" \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk', 'in')" \
+ -c ';SELECT * FROM lnav_view_filters' \
+ -c ':write-screen-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk', 'in')" \
+ -c ";INSERT INTO lnav_view_filters (view_name, pattern, type) VALUES ('log', 'vmk1', 'in')" \
+ -c ";UPDATE lnav_view_filters SET pattern = 'vmk'" \
+ -c ';SELECT * FROM lnav_view_filters' \
+ -c ':write-screen-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, language, pattern) VALUES ('log', 'sql', '1')" \
+ -c ";INSERT INTO lnav_view_filters (view_name, language, pattern) VALUES ('log', 'sql', '1')" \
+ -c ';SELECT * FROM lnav_view_filters' \
+ -c ':write-screen-to -' \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-out vmk" \
+ -c ";DELETE FROM lnav_view_filters" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ":filter-out vmk" \
+ -c ";UPDATE lnav_view_filters SET pattern = 'vmkboot'" \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ":filter-out vmk" \
+ -c ";SELECT * FROM lnav_view_filter_stats" \
+ -c ":write-csv-to -" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "view filter stats is not working?" <<EOF
+view_name,filter_id,hits
+log,1,2
+EOF
+
+run_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_view_filters (view_name, language, pattern) VALUES ('log', 'sql', ':sc_bytes = 134')" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "inserted filter-out did not work?" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7"
+EOF
+
+run_test ${lnav_test} -n \
+ -c ';DELETE FROM lnav_views' \
+ -c ';SELECT count(*) FROM lnav_views' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "delete from lnav_views table works?" <<EOF
+count(*)
+8
+EOF
+
+
+run_test ${lnav_test} -n \
+ -c ";INSERT INTO lnav_views (name) VALUES ('foo')" \
+ -c ';SELECT count(*) FROM lnav_views' \
+ -c ':write-csv-to -' \
+ ${test_dir}/logfile_access_log.0
+
+check_output "insert into lnav_views table works?" <<EOF
+count(*)
+8
+EOF
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET top = 1 WHERE name = 'log'" \
+ ${test_dir}/logfile_access_log.0
+
+run_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET top = inner_height - 1 WHERE name = 'log'" \
+ ${test_dir}/logfile_access_log.0
+
+check_output "updating lnav_views.top using inner_height does not work?" <<EOF
+192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7"
+EOF
+
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET top_time = 'bad-time' WHERE name = 'log'" \
+ ${test_dir}/logfile_access_log.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET top_time = '2014-10-08T00:00:00' WHERE name = 'log'" \
+ ${test_dir}/logfile_generic.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET search = 'warn' WHERE name = 'log'" \
+ -c ";SELECT search FROM lnav_views WHERE name = 'log'" \
+ ${test_dir}/logfile_generic.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET search = 'warn' WHERE name = 'log'" \
+ -c ":goto 0" \
+ -c ":next-mark search" \
+ ${test_dir}/logfile_generic.0
+
+run_cap_test ${lnav_test} -n \
+ -c ";UPDATE lnav_views SET top_meta = json_object('anchor', '#build') WHERE name = 'text'" \
+ ${top_srcdir}/README.md
diff --git a/test/test_sql_xml_func.sh b/test/test_sql_xml_func.sh
new file mode 100644
index 0000000..72f1b0c
--- /dev/null
+++ b/test/test_sql_xml_func.sh
@@ -0,0 +1,11 @@
+#! /bin/bash
+
+run_cap_test ./drive_sql "SELECT * FROM xpath('/abc[', '<abc/>')"
+
+run_cap_test ./drive_sql "SELECT * FROM xpath('/abc', '<abc')"
+
+run_cap_test ./drive_sql "SELECT * FROM xpath('/abc/def', '<abc/>')"
+
+run_cap_test ./drive_sql "SELECT * FROM xpath('/abc/def[@a=\"b\"]', '<abc><def/><def a=\"b\">ghi</def></abc>')"
+
+run_cap_test ./drive_sql "SELECT * FROM xpath('/abc/def', '<abc><def>Hello &gt;</def></abc>')"
diff --git a/test/test_sql_yaml_func.sh b/test/test_sql_yaml_func.sh
new file mode 100644
index 0000000..3daca41
--- /dev/null
+++ b/test/test_sql_yaml_func.sh
@@ -0,0 +1,5 @@
+#! /bin/bash
+
+export YES_COLOR=1
+
+run_cap_test ${lnav_test} -nN -c ";SELECT yaml_to_json('[abc')"
diff --git a/test/test_stubs.cc b/test/test_stubs.cc
new file mode 100644
index 0000000..7d273b3
--- /dev/null
+++ b/test/test_stubs.cc
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2021, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/injector.hh"
+#include "bound_tags.hh"
+#include "config.h"
+#include "lnav.hh"
+#include "service_tags.hh"
+#include "spectro_source.hh"
+
+struct lnav_data_t lnav_data;
+
+void
+rebuild_hist()
+{
+}
+
+bool
+setup_logline_table(exec_context& ec)
+{
+ return false;
+}
+
+bool
+rescan_files(bool required)
+{
+ return false;
+}
+
+void
+wait_for_children()
+{
+}
+
+size_t
+rebuild_indexes(nonstd::optional<ui_clock::time_point> deadline)
+{
+ return 0;
+}
+
+void
+rebuild_indexes_repeatedly()
+{
+}
+
+readline_context::command_map_t lnav_commands;
+
+namespace injector {
+
+template<>
+void
+force_linking(lnav_flags_tag anno)
+{
+}
+
+template<>
+void
+force_linking(services::curl_streamer_t anno)
+{
+}
+
+template<>
+void
+force_linking(services::remote_tailer_t anno)
+{
+}
+} // namespace injector
diff --git a/test/test_text_anonymizer.cc b/test/test_text_anonymizer.cc
new file mode 100644
index 0000000..162111f
--- /dev/null
+++ b/test/test_text_anonymizer.cc
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2022, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest/doctest.h"
+#include "text_anonymizer.hh"
+
+TEST_CASE("ipv4")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("127.0.1.1 says hi"))
+ == "10.0.0.1 says hi");
+ CHECK(ta.next(string_fragment::from_const("127.0.1.1 says hi"))
+ == "10.0.0.1 says hi");
+ CHECK(ta.next(string_fragment::from_const("u'127.0.1.1' says hi"))
+ == "u'10.0.0.1' says hi");
+}
+
+TEST_CASE("ipv6")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(
+ string_fragment::from_const("fe80::1887:2f2d:bc2e:8e41 says hi"))
+ == "2001:db8::1 says hi");
+}
+
+TEST_CASE("url")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("retrieving https://bob:abc@example.com/fooooooo22/192.168.1.33/barrrrr44?abcdef=foobar&ghijkl=123456&bazzer&ip=192.168.1.2#heading-2")) ==
+ "aback https://meerkat:67c93775f715ab8ab01178caf86713c6@achondroplasia.example.com/abaft22/10.0.0.1/abashed44?aberrant=abhorrent&abiding=123456&abject&ip=10.0.0.2#able-2");
+}
+
+TEST_CASE("email")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("hello support@lnav.org"))
+ == "aback meerkat@achondroplasia.example.com");
+}
+
+TEST_CASE("symbol")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const(
+ "state is Constants.DOWNLOAD_STARTED"))
+ == "aback is Abandoned.ABASHED_ABERRANT");
+}
+
+TEST_CASE("date")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("2022-06-02T12:26:22.072Z"))
+ == "2022-06-02T12:26:22.072Z");
+}
+
+TEST_CASE("uuid")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const(
+ "52556d7e-c34d-d7f9-73b6-f52ad939952e"))
+ == "bc8b6954-c2a4-e7f3-0e18-2fa4035db1c9");
+}
+
+TEST_CASE("MAC-address")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("ether f2:09:1a:a2:e3:e2"))
+ == "aback 00:00:5e:00:53:00");
+}
+
+TEST_CASE("hex-dump")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("key f2:09:1a:a2"))
+ == "key 68:48:d3:93");
+}
+
+TEST_CASE("cc")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("cc 6011 1111 1111 1117"))
+ == "cc 1a49 c794 31d9 3eb2");
+ CHECK(ta.next(string_fragment::from_const("cc 6011111111111117"))
+ == "cc 1a49c79431d93eb2");
+}
+
+TEST_CASE("xml")
+{
+ lnav::text_anonymizer ta;
+
+ CHECK(ta.next(string_fragment::from_const("<o:gupdate xmlns:o=\"http://www.google.com/update2/request\" protocol=\"2.0\" version=\"KeystoneDaemon-1.2.0.7709\" ismachine=\"1\" requestid=\"{0DFDBCD1-5E29-4DFC-BD99-31A2397198FE}\">")) ==
+ "<o:gupdate xmlns:o=\"http://achondroplasia.example.com/aback2/abandoned\" protocol=\"2.0\" version=\"Abashed-1.2.0.7709\" ismachine=\"1\" requestid=\"{1ca0a968-cbe9-e75b-d00b-4859609878ea}\">");
+}
diff --git a/test/test_text_file.sh b/test/test_text_file.sh
new file mode 100644
index 0000000..9f326a9
--- /dev/null
+++ b/test/test_text_file.sh
@@ -0,0 +1,33 @@
+#! /bin/bash
+
+export YES_COLOR=1
+unset XDG_CONFIG_HOME
+
+run_cap_test ${lnav_test} -n \
+ ${top_srcdir}/README.md
+
+run_cap_test ${lnav_test} -n -c ':goto #screenshot' \
+ ${top_srcdir}/README.md
+
+run_cap_test ${lnav_test} -n ${top_srcdir}/README.md#screenshot
+
+# run_cap_test ${lnav_test} -n ${test_dir}/non-existent:4
+
+run_cap_test ${lnav_test} -n ${top_srcdir}/README.md:-4
+
+run_cap_test ${lnav_test} -n \
+ -c ':goto 115' \
+ -c ";SELECT top_meta FROM lnav_views WHERE name = 'text'" \
+ -c ':write-json-to -' \
+ ${top_srcdir}/README.md
+
+run_cap_test ${lnav_test} -n \
+ ${top_srcdir}/src/log_level.cc
+
+cp ${test_dir}/UTF-8-test.txt UTF-8-test.md
+run_cap_test ${lnav_test} -n \
+ UTF-8-test.md
+
+run_cap_test ${lnav_test} -n \
+ -c ';SELECT * FROM lnav_file_metadata' \
+ ${test_dir}/textfile_0.md
diff --git a/test/test_top_status.cc b/test/test_top_status.cc
new file mode 100644
index 0000000..769c346
--- /dev/null
+++ b/test/test_top_status.cc
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2007-2012, Timothy Stack
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Timothy Stack nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "command_executor.hh"
+#include "config.h"
+#include "lnav_config.hh"
+#include "top_status_source.hh"
+
+static time_t current_time = 1;
+
+int
+gettimeofday(struct timeval* tp, void* tzp)
+{
+ tp->tv_sec = current_time;
+ tp->tv_usec = 0;
+
+ return 0;
+}
+
+int
+main(int argc, char* argv[])
+{
+ int retval = EXIT_SUCCESS;
+
+ auto_sqlite3 db;
+
+ if (sqlite3_open(":memory:", db.out()) != SQLITE_OK) {
+ fprintf(stderr, "error: unable to create sqlite memory database\n");
+ exit(EXIT_FAILURE);
+ }
+
+ top_status_source_cfg cfg;
+ top_status_source tss(db, cfg);
+
+ setenv("HOME", "/", 1);
+
+ std::vector<lnav::console::user_message> errors;
+ std::vector<ghc::filesystem::path> paths;
+
+ load_config(paths, errors);
+
+ {
+ status_field& sf
+ = tss.statusview_value_for_field(top_status_source::TSF_TIME);
+ attr_line_t val;
+
+ tss.update_time();
+ val = sf.get_value();
+ assert(val.get_string() == sf.get_value().get_string());
+ current_time += 2;
+ tss.update_time();
+ assert(val.get_string() != sf.get_value().get_string());
+
+ cfg.tssc_clock_format = "abc";
+ tss.update_time();
+ val = sf.get_value();
+ assert(val.get_string() == " abc");
+ }
+
+ return retval;
+}
diff --git a/test/test_tui.sh b/test/test_tui.sh
new file mode 100644
index 0000000..3b6f4e9
--- /dev/null
+++ b/test/test_tui.sh
@@ -0,0 +1,28 @@
+#! /bin/bash
+
+# Unsets the following so it does not show up in the term title
+unset SSH_CONNECTION
+
+lnav_test="${top_builddir}/src/lnav-test"
+export lnav_test
+
+for fn in ${srcdir}/tui-captures/*; do
+ base_fn=`basename $fn`
+ run_test ./scripty -n -e $fn -- ${lnav_test} -H < /dev/null
+
+ case "$base_fn" in
+ tui_echo.0)
+ on_error_log "Skipping $fn"
+ ;;
+ *)
+ on_error_log "TUI test ${fn} does not work?"
+ ;;
+ esac
+done
+
+run_test ./scripty -n -e ${srcdir}/xpath_tui.0 -- \
+ ${lnav_test} -I ${test_dir} \
+ -c ':goto 2' \
+ ${srcdir}/logfile_xml_msg.0
+
+on_error_log "xpath() fields are not working?"
diff --git a/test/test_view_colors.sh b/test/test_view_colors.sh
new file mode 100644
index 0000000..39d02a2
--- /dev/null
+++ b/test/test_view_colors.sh
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+run_test ./scripty -n -e ${srcdir}/view_colors_output.0 -- \
+ ./drive_view_colors < /dev/null
+
+on_error_fail_with "view colors are wrong?"
diff --git a/test/test_vt52_curses.sh b/test/test_vt52_curses.sh
new file mode 100644
index 0000000..946e645
--- /dev/null
+++ b/test/test_vt52_curses.sh
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+run_test ./scripty -n -e ${srcdir}/vt52_curses_input.0 \
+ -- ./drive_vt52_curses < /dev/null
+
+on_error_fail_with "single line vt52 did not work?"
diff --git a/test/textfile_0.md b/test/textfile_0.md
new file mode 100644
index 0000000..377e46f
--- /dev/null
+++ b/test/textfile_0.md
@@ -0,0 +1,9 @@
+{
+ "comment": "This is JSON front-matter"
+}
+
+## Test
+
+* One
+* Two
+* Three
diff --git a/test/textfile_ansi.0 b/test/textfile_ansi.0
new file mode 100644
index 0000000..5371c52
--- /dev/null
+++ b/test/textfile_ansi.0
@@ -0,0 +1 @@
+{ Example: foo, bar: baz }
diff --git a/test/textfile_json_indented.0 b/test/textfile_json_indented.0
new file mode 100644
index 0000000..80b5fb6
--- /dev/null
+++ b/test/textfile_json_indented.0
@@ -0,0 +1,12 @@
+{
+ "foo bar": null,
+ "array": [
+ 1,
+ 2,
+ 3
+ ],
+ "obj": {
+ "one": 1,
+ "two": true
+ }
+}
diff --git a/test/textfile_json_one_line.0 b/test/textfile_json_one_line.0
new file mode 100644
index 0000000..a83fd26
--- /dev/null
+++ b/test/textfile_json_one_line.0
@@ -0,0 +1 @@
+{ "foo bar" : null, "array" : [1, 2, 3], "obj" : { "one" : 1, "two" : true } }
diff --git a/test/textfile_quoted_json.0 b/test/textfile_quoted_json.0
new file mode 100644
index 0000000..cf46f72
--- /dev/null
+++ b/test/textfile_quoted_json.0
@@ -0,0 +1 @@
+'{ "foo bar" : null, "array" : [1, 2, 3], "obj" : { "one" : 1, "two" : true } }'
diff --git a/test/toplevel.lnav b/test/toplevel.lnav
new file mode 100644
index 0000000..b6309c8
--- /dev/null
+++ b/test/toplevel.lnav
@@ -0,0 +1,4 @@
+
+:echo toplevel here $1 $2
+
+|nested.lnav abc $3
diff --git a/test/tui-captures/tui_echo.0 b/test/tui-captures/tui_echo.0
new file mode 100644
index 0000000..962b066
--- /dev/null
+++ b/test/tui-captures/tui_echo.0
@@ -0,0 +1,229 @@
+CSI Don't Send Mouse X & Y
+CSI Don’t Use Cell Motion Mouse Tracking
+CSI Don't ...
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Application cursor keys
+CTRL =
+OSC Set window title: LOG
+S -1 ┋ ┋
+A └ normal, normal, normal
+CSI Erase all
+S 1 ┋ 2013-06-06T12:13:20 PDT ┋
+A └ bg(#008080)
+S 16 ┋ Files :: Text Filters :: Press q to exit ┋
+A └ bg(#000080), bold │ ││
+A ·└ fg(#008080), bg(#000080), underline ││
+A ··└ normal, bg(#000080), bold ││
+A ·······└ normal, fg(#000000), bg(#000080) ││
+A ········└ fg(#000080), bg(#c0c0c0) ││
+A ·········└ fg(#000000), bg(#c0c0c0), bold ││
+A ··········└ fg(#800080), bg(#c0c0c0), underline ││
+A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
+A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
+A ······································································└ bold
+A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
+S 17 ┋ ┋
+S 23 ┋ L0 0% ?:View Help ┋
+A └ normal, bg(#008080)
+S 18 ┋ ┋
+A └ normal, normal
+S 1 ┋ Press ENTER to focus on the breadcrumb bar ┋
+A ·····································└ bg(#008080) │
+A ···············································································└ carriage-return
+S 2 ┋ LOG ❭ ┋
+A └ fg(#000000), bg(#000080), bold
+A ·····└ normal, fg(#008080), bg(#c0c0c0)
+A ······└ fg(#000000), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································├ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 5 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 6 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 7 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 8 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 9 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 10 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 11 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 12 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 13 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 14 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 15 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 18 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 19 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 20 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 21 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 22 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 22 ┋ ┋
+A └ normal
+OSC Set window title: HELP
+S 2 ┋ HELP ❭⋯❭ ┋
+A ·└ fg(#000000), bg(#000080), bold
+A ······└ normal, fg(#008080), bg(#c0c0c0)
+A ·······└ fg(#000000), bg(#c0c0c0)
+A ········└ fg(#008080), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································└ normal, fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋lnav ┋
+A └ fg(#000000), normal, underline
+A ····└ carriage-return
+S 6 ┋A fancy log file viewer for the terminal. ┋
+A └ normal │
+A ·········································└ carriage-return
+S 8 ┋Overview ┋
+A └ underline
+A ········└ carriage-return
+S 10 ┋The Logfile Navigator, lnav, is an enhanced log file viewer that takes ┋
+A └ normal │ │ │
+A ·······················└ bold │
+A ···························└ normal │
+A ······································································└ carriage-return
+S 11 ┋advantage of any semantic information that can be gleaned from the ┋
+A ··································································└ carriage-return
+S 12 ┋files being viewed, such as timestamps and log levels. Using this ┋
+A ·································································└ carriage-return
+S 13 ┋extra semantic information, lnav can do things like interleaving ┋
+A ································································└ carriage-return
+S 14 ┋messages from different files, generate histograms of messages over ┋
+A ···································································└ carriage-return
+S 15 ┋time, and providing hotkeys for navigating through the file. It is ┋
+A ··································································└ carriage-return
+S 16 ┋hoped that these features will allow the user to quickly and x┋
+A └┛ alt
+A ················································································└ normal
+S 17 ┋efficiently zero in on problems. x┋
+A └┛ alt
+A ················································································└ normal
+S 19 ┋Opening Paths/URLs ┋
+A └ underline │
+A ··················└ carriage-return
+S 21 ┋The main arguments to lnav are the local/remote files, directories, ┋
+A └ normal │
+A ···································································└ carriage-return
+S 22 ┋glob patterns, or URLs to be viewed. If no arguments are given, the ┋
+A ···································································└ carriage-return
+S 23 ┋ L0 0% ?:View Help ┋
+A └ fg(#000000), bg(#c0c0c0)
+S 24 ┋ Press e/E to move forward/backward through error messags ┋
+A ·······················└ normal││ │
+A ·····························└ bold │
+A ······························└ normal │
+A ·······························└ bold │
+A ································└ normal │
+A ···············································································└ backspace, backspace
+CSI Set Replace mode
+S 24 ┋ e ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+A └ normal
+K 3a
+CSI Erase Below
+CSI Erase Below
+S 24 ┋: ┋
+A └ normal
+A ·└ normal
+S 23 ┋ Enter an lnav command: (Press CTRL+] to abort) ┋
+A ·└ fg(#000000), bg(#c0c0c0) │ │
+A ·······························└ bold│
+A ·····································└ normal, fg(#000000), bg(#c0c0c0)
+S 23 ┋ ┋
+S 24 ┋ e ┋
+A ·└ normal, normal
+A ··└ normal
+K 65
+S 24 ┋ c ┋
+A ···└ normal
+K 63
+S 24 ┋ h ┋
+A ····└ normal
+K 68
+S 24 ┋ o ┋
+A ·····└ normal
+K 6f
+S 24 ┋ echo ┋
+A ·····└ backspace
+A ····└ backspace
+A ···└ backspace
+A ··└ backspace
+A ·└ fg(#000080)
+A ······└ normal, normal
+K 20
+S 24 ┋ h ┋
+A ·······└ normal
+K 68
+S 24 ┋ i ┋
+A ········└ normal
+K 69
+S 24 ┋ ┋
+A ········└ carriage-return
+CSI Erase Below
+S 24 ┋hi ┋
+A └ normal
+A ··└ normal
+K 0d
+S 23 ┋ L0 0% ┋
+A ··└ backspace
+A ·└ fg(#000000), bg(#c0c0c0)
+S 23 ┋ ?:View Help ┋
+S 24 ┋ ┋
+A ··└ normal, normal
+K 71
+S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
+A ··└ carriage-return │ │ │
+A ·······································└ fg(#800080), bold, underline
+A ·············································└ normal │
+A ·······················································└ carriage-return
+A └ normal
+OSC Set window title: LOG
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/tui-captures/tui_help.0 b/test/tui-captures/tui_help.0
new file mode 100644
index 0000000..ae13ead
--- /dev/null
+++ b/test/tui-captures/tui_help.0
@@ -0,0 +1,179 @@
+CSI Don't Send Mouse X & Y
+CSI Don’t Use Cell Motion Mouse Tracking
+CSI Don't ...
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Application cursor keys
+CTRL =
+OSC Set window title: LOG
+S -1 ┋ ┋
+A └ normal, normal, normal
+CSI Erase all
+S 1 ┋ 2013-06-06T12:13:20 PDT ┋
+A └ bg(#008080)
+S 16 ┋ Files :: Text Filters :: Press q to exit ┋
+A └ bg(#000080), bold │ ││
+A ·└ fg(#008080), bg(#000080), underline ││
+A ··└ normal, bg(#000080), bold ││
+A ·······└ normal, fg(#000000), bg(#000080) ││
+A ········└ fg(#000080), bg(#c0c0c0) ││
+A ·········└ fg(#000000), bg(#c0c0c0), bold ││
+A ··········└ fg(#800080), bg(#c0c0c0), underline ││
+A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
+A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
+A ······································································└ bold
+A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
+S 17 ┋ ┋
+S 23 ┋ L0 0% ?:View Help ┋
+A └ normal, bg(#008080)
+S 18 ┋ ┋
+A └ normal, normal
+S 1 ┋ Press ENTER to focus on the breadcrumb bar ┋
+A ·····································└ bg(#008080) │
+A ···············································································└ carriage-return
+S 2 ┋ LOG ❭ ┋
+A └ fg(#000000), bg(#000080), bold
+A ·····└ normal, fg(#008080), bg(#c0c0c0)
+A ······└ fg(#000000), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································├ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 5 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 6 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 7 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 8 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 9 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 10 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 11 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 12 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 13 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 14 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 15 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 18 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 19 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 20 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 21 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 22 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 22 ┋ ┋
+A └ normal
+OSC Set window title: HELP
+S 2 ┋ HELP ❭⋯❭ ┋
+A ·└ fg(#000000), bg(#000080), bold
+A ······└ normal, fg(#008080), bg(#c0c0c0)
+A ·······└ fg(#000000), bg(#c0c0c0)
+A ········└ fg(#008080), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································└ normal, fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋lnav ┋
+A └ fg(#000000), normal, underline
+A ····└ carriage-return
+S 6 ┋A fancy log file viewer for the terminal. ┋
+A └ normal │
+A ·········································└ carriage-return
+S 8 ┋Overview ┋
+A └ underline
+A ········└ carriage-return
+S 10 ┋The Logfile Navigator, lnav, is an enhanced log file viewer that takes ┋
+A └ normal │ │ │
+A ·······················└ bold │
+A ···························└ normal │
+A ······································································└ carriage-return
+S 11 ┋advantage of any semantic information that can be gleaned from the ┋
+A ··································································└ carriage-return
+S 12 ┋files being viewed, such as timestamps and log levels. Using this ┋
+A ·································································└ carriage-return
+S 13 ┋extra semantic information, lnav can do things like interleaving ┋
+A ································································└ carriage-return
+S 14 ┋messages from different files, generate histograms of messages over ┋
+A ···································································└ carriage-return
+S 15 ┋time, and providing hotkeys for navigating through the file. It is ┋
+A ··································································└ carriage-return
+S 16 ┋hoped that these features will allow the user to quickly and x┋
+A └┛ alt
+A ················································································└ normal
+S 17 ┋efficiently zero in on problems. x┋
+A └┛ alt
+A ················································································└ normal
+S 19 ┋Opening Paths/URLs ┋
+A └ underline │
+A ··················└ carriage-return
+S 21 ┋The main arguments to lnav are the local/remote files, directories, ┋
+A └ normal │
+A ···································································└ carriage-return
+S 22 ┋glob patterns, or URLs to be viewed. If no arguments are given, the ┋
+A ···································································└ carriage-return
+S 23 ┋ L0 0% ?:View Help ┋
+A └ fg(#000000), bg(#c0c0c0)
+S 24 ┋ Press e/E to move forward/backward through error messags ┋
+A ·······················└ normal││ │
+A ·····························└ bold │
+A ······························└ normal │
+A ·······························└ bold │
+A ································└ normal │
+A ···············································································└ backspace, backspace
+CSI Set Replace mode
+S 24 ┋ e ┋
+CSI Reset Replace mode
+S 24 ┋ ┋
+A ···············································································└ carriage-return
+A └ normal
+K 71
+OSC Set window title: LOG
+S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
+A ·······································└ fg(#800080), bold, underline
+A ·············································└ normal
+CSI Erase to Right
+S 24 ┋ ┋
+A ·······················································└ carriage-return
+A └ normal
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/update_parser_output.sh b/test/update_parser_output.sh
new file mode 100755
index 0000000..334892b
--- /dev/null
+++ b/test/update_parser_output.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+test_dir=`dirname $0`
+
+for fn in ${test_dir}/datafile_simple.*; do
+ echo "Checking $fn"
+ ./drive_data_scanner -p $fn
+done
+
+for fn in ${test_dir}/log-samples/sample-*; do
+ echo "Checking $fn"
+ ./drive_data_scanner -p -l $fn
+done
diff --git a/test/view_colors_output.0 b/test/view_colors_output.0
new file mode 100644
index 0000000..cb70c4c
--- /dev/null
+++ b/test/view_colors_output.0
@@ -0,0 +1,54 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+S -1 ┋ ┋
+A └ normal, normal, normal
+CSI Erase all
+S 1 ┋This is line: 0 ┋
+A ···············└ carriage-return
+S 2 ┋This is line: 1 ┋
+A ···············└ carriage-return
+S 3 ┋This is line: 2 ┋
+A ···············└ carriage-return
+S 4 ┋This is line: 3 ┋
+A ···············└ carriage-return
+S 5 ┋This is line: 4 ┋
+A ···············└ carriage-return
+S 6 ┋This is line: 5 ┋
+A ···············└ carriage-return
+S 7 ┋This is line: 6 ┋
+A ···············└ carriage-return
+S 8 ┋This is line: 7 ┋
+A ···············└ carriage-return
+S 9 ┋This is line: 8 ┋
+A ···············└ carriage-return
+S 10 ┋This is line: 9 ┋
+A ···············└ carriage-return
+S 11 ┋This is line: 10 ┋
+A ················└ carriage-return
+S 12 ┋This is line: 11 ┋
+A ················└ carriage-return
+S 13 ┋This is line: 12 ┋
+A ················└ carriage-return
+S 14 ┋This is line: 13 ┋
+A ················└ carriage-return
+S 15 ┋This is line: 14 ┋
+A ················└ carriage-return
+S 16 ┋This is line: 15 ┋
+A ················└ carriage-return
+S 17 ┋before <123> after ┋
+A ········└ fg(#008080), inverse
+A ···········└ normal
+A ··················└ carriage-return
+A └ normal
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/vt52_curses_input.0 b/test/vt52_curses_input.0
new file mode 100644
index 0000000..c8a7ad7
--- /dev/null
+++ b/test/vt52_curses_input.0
@@ -0,0 +1,49 @@
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Erase all
+S 1 ┋Gruß ┋
+K 0d
+S 1 ┋ ┋
+A ····└ carriage-return
+K 0d
+CSI Erase Below
+K 0d
+S 1 ┋de ┋
+K 0d
+S 1 ┋ ┋
+A ··└ carriage-return
+CSI Erase Below
+K 0d
+S 1 ┋1 ┋
+K 0d
+S 1 ┋ 2 ┋
+K 0d
+S 1 ┋ 3 ┋
+K 0d
+S 1 ┋ ┋
+A ···└ carriage-return
+CSI Erase Below
+K 0d
+S 1 ┋abc ┋
+K 0d
+S 1 ┋ ┋
+A ···└ carriage-return
+CSI Erase Below
+K 0d
+CTRL bell
+K 0d
+S 1 ┋acdef ┋
+K 0d
+K 0d
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad
diff --git a/test/vt52_curses_input.1 b/test/vt52_curses_input.1
new file mode 100644
index 0000000..9ee3226
--- /dev/null
+++ b/test/vt52_curses_input.1
@@ -0,0 +1,38 @@
+sleep 1.124207
+write 31
+sleep 0.295830
+write 32
+sleep 0.487919
+write 33
+sleep 0.343913
+write 34
+sleep 0.303816
+write 35
+sleep 0.343703
+write 36
+sleep 0.295997
+write 37
+sleep 0.327862
+write 38
+sleep 0.295952
+write 39
+sleep 0.247670
+write 30
+sleep 0.911859
+write 61
+sleep 0.311780
+write 62
+sleep 0.407914
+write 63
+sleep 0.319836
+write 64
+sleep 0.199866
+write 65
+sleep 0.327904
+write 66
+sleep 0.359919
+write 67
+sleep 0.343907
+write 68
+sleep 0.288008
+write 69
diff --git a/test/vt52_curses_output.0 b/test/vt52_curses_output.0
new file mode 100644
index 0000000..b77311a
--- /dev/null
+++ b/test/vt52_curses_output.0
@@ -0,0 +1,39 @@
+read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a477275c39f
+# write 0d
+read 0d
+# write 0d
+read 1b5b4a
+# write 0d
+read 6465
+# write 0d
+read 0d1b5b4a
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read
+# write 0d
+read 616263
+# write 0d
+read 0d1b5b4a
+# write 0d
+read 07
+# write 0d
+read 6163646566
+# write 0d
+read
+# write 0d
+read 1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e
diff --git a/test/vt52_curses_output.1 b/test/vt52_curses_output.1
new file mode 100644
index 0000000..dfbe7dd
--- /dev/null
+++ b/test/vt52_curses_output.1
@@ -0,0 +1,38 @@
+read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a1b5b3542616263
+# write 31
+read 0d
+# write 32
+read 1b5b4a
+# write 33
+read 6465
+# write 34
+read 0d1b5b3138420a1b5b313841
+# write 35
+read 1b5b3138420a1b5b313941310a08
+# write 36
+read 1b5b3138420a1b5b313941320a08
+# write 37
+read 1b5b3138420a1b5b313941330a08
+# write 38
+read 1b5b3138420a1b5b313941340a08
+# write 39
+read 1b5b3138420a1b5b313941350a08
+# write 30
+read 1b5b3138420a1b5b313941360a08
+# write 61
+read 1b5b3138420a1b5b313941370a08
+# write 62
+read 1b5b3138420a1b5b313941380a08
+# write 63
+read 1b5b3138420a1b5b313941390a08
+# write 64
+read 616263
+# write 65
+read 0d1b5b4a
+# write 66
+read 07
+# write 67
+read 6163646566
+# write 68
+read
+# write 69
diff --git a/test/xpath_tui.0 b/test/xpath_tui.0
new file mode 100644
index 0000000..feb93ec
--- /dev/null
+++ b/test/xpath_tui.0
@@ -0,0 +1,458 @@
+CSI Don't Send Mouse X & Y
+CSI Don’t Use Cell Motion Mouse Tracking
+CSI Don't ...
+CTRL Use alt charset
+CTRL save cursor
+CSI Use alternate screen buffer
+CSI set scrolling region 1-24
+S -1 ┋ ┋
+A └ normal
+CSI Reset Replace mode
+CSI Application cursor keys
+CTRL =
+OSC Set window title: LOG
+S -1 ┋ ┋
+A └ normal, normal, normal
+CSI Erase all
+S 1 ┋ 2013-06-06T12:13:20 PDT Press ENTER to focus on the breadcrumb bar ┋
+A └ bg(#008080)
+S 2 ┋ LOG ❭ ┋
+A └ fg(#000000), bg(#000080), bold
+A ·····└ normal, fg(#008080), bg(#c0c0c0)
+A ······└ fg(#000000), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································├ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 5 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 6 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 7 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 8 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 9 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 10 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 11 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 12 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 13 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 14 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 15 ┋ x┋
+A └┛ alt
+A ················································································└ normal
+S 16 ┋ Files :: Text Filters :: 0 of 1 enabled Press q to exit ┋
+A └ bg(#000080), bold │ ││ ││ ││
+A ·└ fg(#008080), bg(#000080), underline ││
+A ··└ normal, bg(#000080), bold ││ ││
+A ·······└ normal, fg(#000000), bg(#000080) ││
+A ········└ fg(#000080), bg(#c0c0c0) ││
+A ·········└ fg(#000000), bg(#c0c0c0), bold ││
+A ··········└ fg(#800080), bg(#c0c0c0), underline ││
+A ···········└ normal, fg(#000000), bg(#c0c0c0), bold ││
+A ·······················└ normal, fg(#000000), bg(#c0c0c0) ││
+A ··························└ bold│ ││
+A ···························└ normal, fg(#000000), bg(#c0c0c0) ││
+A ·······························└ bold ││
+A ································└ normal, fg(#000000), bg(#c0c0c0) ││
+A ······································································└ bold
+A ·······································································└ normal, fg(#000000), bg(#c0c0c0)
+S 17 ┋ ┋
+S 18 ┋→ ` logfile_xml_msg.0 0.0 B — x┋
+A ··├ fg(#008000), bg(#c0c0c0) │ │ ││
+A └┛ alt │ │ │ ││
+A ···└ fg(#000000), bg(#c0c0c0) │ │ ││
+A ························└ bold│ │ ││
+A ······························└ normal, fg(#000000), bg(#c0c0c0) ││
+A ······································└ fg(#808000), bg(#c0c0c0) ││
+A ···············································································└ normal, fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 19 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 20 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 21 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 22 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 23 ┋ L0 0% ?:View Help ┋
+A └ fg(#000000), normal, bg(#008080)
+S 22 ┋ ┋
+A └ normal, normal
+S 18 ┋ 64.0 B 2020-12-10 06:56:41.061 — 2020-12-10 06:56:41. ┋
+A ··························└ fg(#000000), bg(#c0c0c0), bold │
+A ······························└ normal, fg(#000000), bg(#c0c0c0) │
+A ···············································································└ carriage-return
+S 22 ┋ ┋
+A └ normal, normal
+S 18 ┋ 628 ┋
+A ·························└ fg(#000000), bg(#c0c0c0), bold
+A ····························└ carriage-return
+S 22 ┋ ┋
+A └ normal, normal
+S 16 ┋ 1 ┋
+A ··························└ fg(#000000), bg(#c0c0c0), bold
+S 23 ┋ 25 10 ┋
+A ··└ normal, bg(#008080)
+A ·············└ carriage-return
+S 22 ┋ ┋
+A └ normal, normal
+S 2 ┋ 2020-12-10T06:56:41.061❭xml_msg_log❭logfile_xml_msg.0[0]❭ ┋
+A ······└ fg(#000000), bg(#c0c0c0) ││ ││
+A ·····························└ fg(#008080), bg(#c0c0c0) ││
+A ······························└ fg(#000000), bg(#c0c0c0) ││
+A ·········································└ fg(#008080), bg(#c0c0c0)
+A ··········································└ fg(#000000), bg(#c0c0c0)
+A ······························································└ fg(#008080), bg(#c0c0c0)
+A ·······························································└ carriage-return
+S 3 ┋l[2020-12-10 06:56:41,061] INFO [m:108] Calling 'x' with params: x┋
+A ├ normal │ │ ││
+A └┛ alt │ │ ││
+A ················································└ fg(#008000), bold ││
+A ···················································└ normal ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 4 ┋x x┋
+A ├ fg(#000000), normal ││
+A └┛ alt ││
+A ·└ normal ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 5 ┋x[2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text: x┋
+A ├ fg(#000000), normal ││
+A └┛ alt ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 6 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
+A ├ fg(#000000), normal│ ││ │ ││
+A └┛ alt │ ││ ││ ││ │ ││
+A ·······└ fg(#008080)││ ││ │ ││
+A ··············└ normal ││ │ ││
+A ···············└ fg(#008000), bold │ ││
+A ····················└ normal ││ │ ││
+A ·····················└ fg(#008080) │ ││
+A ·····························└ normal │ ││
+A ······························└ fg(#008000), bold ││
+A ··········································└ normal ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 7 ┋x<a-request> x┋
+A ├ fg(#000000), normal ││
+A └┛ alt ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 8 ┋x <head> ┋
+A ├ fg(#000000), normal
+A └┛ alt │
+A ·········└ carriage-return
+S 9 ┋x x ┋
+A └┛ alt│
+A ······└ carriage-return
+S 10 ┋x </head> ┋
+A └┛ alt │
+A ··········└ carriage-return
+S 11 ┋x <source> ┋
+A └┛ alt │
+A ···········└ carriage-return
+S 12 ┋x x ┋
+A └┛ alt│
+A ······└ carriage-return
+S 13 ┋x </source> ┋
+A └┛ alt │
+A ············└ carriage-return
+S 14 ┋x <request id="1"> ┋
+A └┛ alt │ ││ ││
+A ············└ fg(#008080)
+A ··············└ normal
+A ···············└ fg(#008000), bold
+A ··················└ normal
+A ···················└ carriage-return
+S 15 ┋x <name> ┋
+A └┛ alt │
+A ···········└ carriage-return
+S 22 ┋ ┋
+A └ normal
+CSI set scrolling region 3-20
+S 3 ┋ ┋
+A └ [2M
+CSI set scrolling region 1-24
+CSI Erase Below
+S 2 ┋ 92 ┋
+A ···························└ fg(#000000), bg(#c0c0c0)
+S 2 ┋ 2]❭⋯❭ ┋
+A ······························································└ fg(#008080), bg(#c0c0c0)
+A ·······························································└ fg(#000000), bg(#c0c0c0)
+A ································································└ fg(#008080), bg(#c0c0c0)
+S 3 ┋ x┋
+A ···············································································├ normal
+A └┛ alt
+A ················································································└ normal
+S 6 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 7 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 8 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 9 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 10 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 11 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 12 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 13 ┋ x┋
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 14 ┋x x x┋
+A ├ fg(#000000), normal ││
+A └┛ alt ││
+A ···············································································└ fg(#000000)
+A ················································································└ normal
+A └┛ alt
+A ················································································└ normal
+S 15 ┋x </name> x┋
+A ├ fg(#000000), normal ││
+A └┛ alt ││
+A └┛ alt
+A ················································································└ normal
+S 16 ┋x </request> x┋
+A └┛ alt ││
+A └┛ alt
+A ················································································└ normal
+S 17 ┋x</a-request> x┋
+A └┛ alt ││
+A └┛ alt
+A ················································································└ normal
+S 18 ┋x x┋
+A └┛ alt ││
+A ·└ normal ││
+A └┛ alt
+A ················································································└ normal
+S 19 ┋x[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text: x┋
+A └┛ alt ││
+A └┛ alt
+A ················································································└ normal
+S 20 ┋x<?xml version='1.0' encoding='iso-8859-2'?> x┋
+A └┛ alt │ ││ ││ ││ │ ││
+A ·······└ fg(#008080)││ ││ │ ││
+A ··············└ normal ││ │ ││
+A ···············└ fg(#008000), bold │ ││
+A ····················└ normal ││ │ ││
+A ·····················└ fg(#008080) │ ││
+A ·····························└ normal │ ││
+A ······························└ fg(#008000), bold ││
+A ··········································└ normal ││
+A └┛ alt
+A ················································································└ normal
+S 21 ┋x<a-reply> x┋
+A └┛ alt ││
+A └┛ alt
+A ················································································└ normal
+S 24 ┋ ┋
+A └ normal
+S 22 ┋ Files :: Text Filters :: 0 of 1 enabled Press TAB to edit ┋
+A └ bg(#008080) ││ ││ │ │
+A ··························└ bold│ │ │
+A ···························└ normal, bg(#008080) │ │
+A ·······························└ bold │ │
+A ································└ normal, bg(#008080) │ │
+A ····································································└ bold
+A ·······································································└ normal, bg(#008080)
+S 23 ┋ L2 58% ?:View Help ┋
+A └ fg(#000000), bg(#c0c0c0)
+S 24 ┋ ┋
+A └ normal, normal
+K 70
+S 4 ┋ Received Time: 2020-12-10T06:56:41.092 -- in the future ┋
+A ················└ bold │ │ │
+A ·······································└ normal │
+A ···········································└ bold │
+A ························································└ carriage-return
+S 5 ┋ Pattern: /xml_msg_log/regex/std = ^\[(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2 ┋
+A └ normal ││ │ ││ ││ │││││ │││││ │││││ │││││ │││
+A ···································└ fg(#008080) ││ │││││ │││││ │││││ │││││ │││
+A ····································└ normal ││ │││││ │││││ │││││ │││││ │││
+A ······································└ fg(#008000), bold│ │││││ │││││ │││││ │││
+A ········································└ normal, fg(#008080)│││ │││││ │││││ │││
+A ·········································└ normal ││ │││││ │││││ │││││ │││││ │││
+A ··················································└ fg(#008080)│ │││││ │││││ │││
+A ···················································└ fg(#000080) │││││ │││││ │││
+A ·····················································└ fg(#008000), bold││││ │││
+A ······················································└ normal││ │││││ │││││ │││
+A ·······················································└ fg(#008000), bold││ │││
+A ························································└ normal │││││ │││││ │││
+A ·························································└ fg(#000080) │││││ │││
+A ···························································└ fg(#008000), bold││
+A ····························································└ normal││ │││││ │││
+A ·····························································└ fg(#008000), bold
+A ······························································└ normal │││││ │││
+A ·······························································└ fg(#000080) │││
+A ·································································└ fg(#008000), bold
+A ··································································└ normal││ │││
+A ···································································└ fg(#008000), bold
+A ····································································└ normal │││
+A ·····································································└ fg(#000080)
+A ·······································································└ fg(#008000), bold
+A ········································································└ normal
+A ·········································································└ fg(#008000), bold
+A ··········································································└ normal
+A ···········································································└ fg(#000080)
+A ·············································································└ fg(#008000), bold
+A ··············································································└ normal
+A ···············································································└ carriage-return
+S 6 ┋ Known message fields for table xml_msg_log: ┋
+A ································└ bold ││
+A ···········································└ normal
+A ············································└ carriage-return
+S 7 ┋ t log_time = 2020-12-10 06:56:41,092 ┋
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 8 ┋ t level = DEBUG ┋
+A └ normal │ │
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 9 ┋ t module = connect.client ┋
+A └ normal │ │
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 10 ┋ t line = 69 ┋
+A └ normal │ │
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 11 ┋ t log_body = Full request text: ┋
+A └ normal │ │
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 12 ┋ t msg_data = <?xml version='1.0' encoding='iso-8859-2'?> <a-request> <head> ┋
+A └ normal │ │
+A └┛ alt │ │
+A ···············└ bold │
+A ···············································································└ carriage-return
+S 13 ┋ XML fields: ┋
+A └ normal │
+A ············└ carriage-return
+S 14 ┋ t xpath('/a-request/head/text()', msg_data) = x ┋
+A └┛ alt │
+A ······└ bold │
+A ···············································································└ carriage-return
+S 15 ┋ t xpath('/a-request/request/@id', msg_data) = 1 ┋
+A └ normal │
+A └┛ alt │
+A ······└ bold │
+A ···············································································└ carriage-return
+S 16 ┋ t xpath('/a-request/request/name/text()', msg_data) = x ┋
+A └ normal │
+A └┛ alt │
+A ······└ bold │
+A ···············································································└ carriage-return
+S 17 ┋ t xpath('/a-request/source/text()', msg_data) = x ┋
+A └ normal │
+A └┛ alt │
+A ······└ bold │
+A ···············································································└ carriage-return
+S 18 ┋ No discovered message fields ┋
+A └ normal
+S 19 ┋ <?xml version='1.0' encoding='iso-8859-2'?> ┋
+A ·······└ fg(#008080)││ ││ │
+A ··············└ normal ││ │
+A ···············└ fg(#008000), bold │
+A ····················└ normal ││ │
+A ·····················└ fg(#008080) │
+A ·····························└ normal │
+A ······························└ fg(#008000), bold
+A ··········································└ normal
+S 20 ┋ a-request> ┋
+S 21 ┋ <head> ┋
+A ··········└ carriage-return
+S 24 ┋ ┋
+A └ normal
+K 71
+S 23 ┋ 0 ┋
+A ··└ fg(#000000), bg(#c0c0c0)
+S 23 ┋ 0 ┋
+A ··············└ carriage-return
+S 24 ┋ⓘ info: executing SQL statement, press CTRL+] to cancel ┋
+A └ normal │ │ │
+A ·······································└ fg(#800080), bold, underline
+A ·············································└ normal │
+A ·······················································└ carriage-return
+A └ normal
+CSI Erase all
+CSI Use normal screen buffer
+CTRL restore cursor
+S 24 ┋ ┋
+A └ carriage-return
+CSI Normal cursor keys
+CTRL Normal keypad