xref: /sqlite-3.40.0/test/shell1.test (revision db95f68b)
18df9185cSdrh# 2009 Nov 11
28df9185cSdrh#
38df9185cSdrh# The author disclaims copyright to this source code.  In place of
48df9185cSdrh# a legal notice, here is a blessing:
58df9185cSdrh#
68df9185cSdrh#    May you do good and not evil.
78df9185cSdrh#    May you find forgiveness for yourself and forgive others.
88df9185cSdrh#    May you share freely, never taking more than you give.
98df9185cSdrh#
108df9185cSdrh#***********************************************************************
118df9185cSdrh#
128df9185cSdrh# The focus of this file is testing the CLI shell tool.
138df9185cSdrh#
148df9185cSdrh#
158df9185cSdrh
168df9185cSdrh# Test plan:
178df9185cSdrh#
188df9185cSdrh#   shell1-1.*: Basic command line option handling.
198df9185cSdrh#   shell1-2.*: Basic "dot" command token parsing.
208df9185cSdrh#   shell1-3.*: Basic test that "dot" command can be called.
218df9185cSdrh#
228df9185cSdrhset testdir [file dirname $argv0]
238df9185cSdrhsource $testdir/tester.tcl
248df9185cSdrhif {$tcl_platform(platform)=="windows"} {
258df9185cSdrh  set CLI "sqlite3.exe"
268df9185cSdrh} else {
278df9185cSdrh  set CLI "./sqlite3"
288df9185cSdrh}
298df9185cSdrhif {![file executable $CLI]} {
308df9185cSdrh  finish_test
318df9185cSdrh  return
328df9185cSdrh}
338df9185cSdrhdb close
348df9185cSdrhforcedelete test.db test.db-journal test.db-wal
358df9185cSdrhsqlite3 db test.db
368df9185cSdrh
378df9185cSdrh#----------------------------------------------------------------------------
388df9185cSdrh# Test cases shell1-1.*: Basic command line option handling.
398df9185cSdrh#
408df9185cSdrh
418df9185cSdrh# invalid option
428df9185cSdrhdo_test shell1-1.1.1 {
438df9185cSdrh  set res [catchcmd "-bad test.db" ""]
448df9185cSdrh  set rc [lindex $res 0]
458df9185cSdrh  list $rc \
468df9185cSdrh       [regexp {Error: unknown option: -bad} $res]
478df9185cSdrh} {1 1}
488df9185cSdrh# error on extra options
498df9185cSdrhdo_test shell1-1.1.2 {
508df9185cSdrh  set res [catchcmd "-bad test.db \"select 3\" \"select 4\"" ""]
518df9185cSdrh  set rc [lindex $res 0]
528df9185cSdrh  list $rc \
538df9185cSdrh       [regexp {Error: too many options: "select 4"} $res]
548df9185cSdrh} {1 1}
558df9185cSdrh# error on extra options
568df9185cSdrhdo_test shell1-1.1.3 {
578df9185cSdrh  set res [catchcmd "-bad FOO test.db BAD" ".quit"]
588df9185cSdrh  set rc [lindex $res 0]
598df9185cSdrh  list $rc \
608df9185cSdrh       [regexp {Error: too many options: "BAD"} $res]
618df9185cSdrh} {1 1}
628df9185cSdrh
638df9185cSdrh# -help
648df9185cSdrhdo_test shell1-1.2.1 {
658df9185cSdrh  set res [catchcmd "-help test.db" ""]
668df9185cSdrh  set rc [lindex $res 0]
678df9185cSdrh  list $rc \
688df9185cSdrh       [regexp {Usage} $res] \
698df9185cSdrh       [regexp {\-init} $res] \
708df9185cSdrh       [regexp {\-version} $res]
718df9185cSdrh} {1 1 1 1}
728df9185cSdrh
738df9185cSdrh# -init filename       read/process named file
748df9185cSdrhdo_test shell1-1.3.1 {
758df9185cSdrh  catchcmd "-init FOO test.db" ""
768df9185cSdrh} {0 {}}
778df9185cSdrhdo_test shell1-1.3.2 {
788df9185cSdrh  set res [catchcmd "-init FOO test.db .quit BAD" ""]
798df9185cSdrh  set rc [lindex $res 0]
808df9185cSdrh  list $rc \
818df9185cSdrh       [regexp {Error: too many options: "BAD"} $res]
828df9185cSdrh} {1 1}
838df9185cSdrh
848df9185cSdrh# -echo                print commands before execution
858df9185cSdrhdo_test shell1-1.4.1 {
868df9185cSdrh  catchcmd "-echo test.db" ""
878df9185cSdrh} {0 {}}
888df9185cSdrh
898df9185cSdrh# -[no]header          turn headers on or off
908df9185cSdrhdo_test shell1-1.5.1 {
918df9185cSdrh  catchcmd "-header test.db" ""
928df9185cSdrh} {0 {}}
938df9185cSdrhdo_test shell1-1.5.2 {
948df9185cSdrh  catchcmd "-noheader test.db" ""
958df9185cSdrh} {0 {}}
968df9185cSdrh
978df9185cSdrh# -bail                stop after hitting an error
988df9185cSdrhdo_test shell1-1.6.1 {
998df9185cSdrh  catchcmd "-bail test.db" ""
1008df9185cSdrh} {0 {}}
1018df9185cSdrh
1028df9185cSdrh# -interactive         force interactive I/O
1038df9185cSdrhdo_test shell1-1.7.1 {
1048df9185cSdrh  set res [catchcmd "-interactive test.db" ".quit"]
1058df9185cSdrh  set rc [lindex $res 0]
1068df9185cSdrh  list $rc \
1078df9185cSdrh       [regexp {SQLite version} $res] \
1088df9185cSdrh       [regexp {Enter SQL statements} $res]
1098df9185cSdrh} {0 1 1}
1108df9185cSdrh
1118df9185cSdrh# -batch               force batch I/O
1128df9185cSdrhdo_test shell1-1.8.1 {
1138df9185cSdrh  catchcmd "-batch test.db" ""
1148df9185cSdrh} {0 {}}
1158df9185cSdrh
1168df9185cSdrh# -column              set output mode to 'column'
1178df9185cSdrhdo_test shell1-1.9.1 {
1188df9185cSdrh  catchcmd "-column test.db" ""
1198df9185cSdrh} {0 {}}
1208df9185cSdrh
1218df9185cSdrh# -csv                 set output mode to 'csv'
1228df9185cSdrhdo_test shell1-1.10.1 {
1238df9185cSdrh  catchcmd "-csv test.db" ""
1248df9185cSdrh} {0 {}}
1258df9185cSdrh
1268df9185cSdrh# -html                set output mode to HTML
1278df9185cSdrhdo_test shell1-1.11.1 {
1288df9185cSdrh  catchcmd "-html test.db" ""
1298df9185cSdrh} {0 {}}
1308df9185cSdrh
1318df9185cSdrh# -line                set output mode to 'line'
1328df9185cSdrhdo_test shell1-1.12.1 {
1338df9185cSdrh  catchcmd "-line test.db" ""
1348df9185cSdrh} {0 {}}
1358df9185cSdrh
1368df9185cSdrh# -list                set output mode to 'list'
1378df9185cSdrhdo_test shell1-1.13.1 {
1388df9185cSdrh  catchcmd "-list test.db" ""
1398df9185cSdrh} {0 {}}
1408df9185cSdrh
1418df9185cSdrh# -separator 'x'       set output field separator (|)
1428df9185cSdrhdo_test shell1-1.14.1 {
1438df9185cSdrh  catchcmd "-separator 'x' test.db" ""
1448df9185cSdrh} {0 {}}
1458df9185cSdrhdo_test shell1-1.14.2 {
1468df9185cSdrh  catchcmd "-separator x test.db" ""
1478df9185cSdrh} {0 {}}
1488df9185cSdrhdo_test shell1-1.14.3 {
1498df9185cSdrh  set res [catchcmd "-separator" ""]
1508df9185cSdrh  set rc [lindex $res 0]
1518df9185cSdrh  list $rc \
15298d312fcSdrh       [regexp {Error: missing argument to -separator} $res]
1538df9185cSdrh} {1 1}
1548df9185cSdrh
1558df9185cSdrh# -stats               print memory stats before each finalize
1568df9185cSdrhdo_test shell1-1.14b.1 {
1578df9185cSdrh  catchcmd "-stats test.db" ""
1588df9185cSdrh} {0 {}}
1598df9185cSdrh
1608df9185cSdrh# -nullvalue 'text'    set text string for NULL values
1618df9185cSdrhdo_test shell1-1.15.1 {
1628df9185cSdrh  catchcmd "-nullvalue 'x' test.db" ""
1638df9185cSdrh} {0 {}}
1648df9185cSdrhdo_test shell1-1.15.2 {
1658df9185cSdrh  catchcmd "-nullvalue x test.db" ""
1668df9185cSdrh} {0 {}}
1678df9185cSdrhdo_test shell1-1.15.3 {
1688df9185cSdrh  set res [catchcmd "-nullvalue" ""]
1698df9185cSdrh  set rc [lindex $res 0]
1708df9185cSdrh  list $rc \
17198d312fcSdrh       [regexp {Error: missing argument to -nullvalue} $res]
1728df9185cSdrh} {1 1}
1738df9185cSdrh
1748df9185cSdrh# -version             show SQLite version
1758df9185cSdrhdo_test shell1-1.16.1 {
1768df9185cSdrh  set x [catchcmd "-version test.db" ""]
177b24c61a2Sdrh} {/3.[0-9.]+ 20\d\d-[01]\d-\d\d \d\d:\d\d:\d\d [0-9a-f]+/}
1788df9185cSdrh
1798df9185cSdrh#----------------------------------------------------------------------------
1808df9185cSdrh# Test cases shell1-2.*: Basic "dot" command token parsing.
1818df9185cSdrh#
1828df9185cSdrh
1838df9185cSdrh# check first token handling
1848df9185cSdrhdo_test shell1-2.1.1 {
1858df9185cSdrh  catchcmd "test.db" ".foo"
1868df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "foo". Enter ".help" for help}}
1878df9185cSdrhdo_test shell1-2.1.2 {
1888df9185cSdrh  catchcmd "test.db" ".\"foo OFF\""
1898df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
1908df9185cSdrhdo_test shell1-2.1.3 {
1918df9185cSdrh  catchcmd "test.db" ".\'foo OFF\'"
1928df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
1938df9185cSdrh
1948df9185cSdrh# unbalanced quotes
1958df9185cSdrhdo_test shell1-2.2.1 {
1968df9185cSdrh  catchcmd "test.db" ".\"foo OFF"
1978df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
1988df9185cSdrhdo_test shell1-2.2.2 {
1998df9185cSdrh  catchcmd "test.db" ".\'foo OFF"
2008df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
2018df9185cSdrhdo_test shell1-2.2.3 {
2028df9185cSdrh  catchcmd "test.db" ".explain \"OFF"
2038df9185cSdrh} {0 {}}
2048df9185cSdrhdo_test shell1-2.2.4 {
2058df9185cSdrh  catchcmd "test.db" ".explain \'OFF"
2068df9185cSdrh} {0 {}}
2078df9185cSdrhdo_test shell1-2.2.5 {
2088df9185cSdrh  catchcmd "test.db" ".mode \"insert FOO"
2098df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
2108df9185cSdrhdo_test shell1-2.2.6 {
2118df9185cSdrh  catchcmd "test.db" ".mode \'insert FOO"
2128df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
2138df9185cSdrh
2148df9185cSdrh# check multiple tokens, and quoted tokens
2158df9185cSdrhdo_test shell1-2.3.1 {
2168df9185cSdrh  catchcmd "test.db" ".explain 1"
2178df9185cSdrh} {0 {}}
2188df9185cSdrhdo_test shell1-2.3.2 {
2198df9185cSdrh  catchcmd "test.db" ".explain on"
2208df9185cSdrh} {0 {}}
2218df9185cSdrhdo_test shell1-2.3.3 {
2228df9185cSdrh  catchcmd "test.db" ".explain \"1 2 3\""
223173ba099Sdrh} {1 {ERROR: Not a boolean value: "1 2 3". Assuming "no".}}
2248df9185cSdrhdo_test shell1-2.3.4 {
2258df9185cSdrh  catchcmd "test.db" ".explain \"OFF\""
2268df9185cSdrh} {0 {}}
2278df9185cSdrhdo_test shell1-2.3.5 {
2288df9185cSdrh  catchcmd "test.db" ".\'explain\' \'OFF\'"
2298df9185cSdrh} {0 {}}
2308df9185cSdrhdo_test shell1-2.3.6 {
2318df9185cSdrh  catchcmd "test.db" ".explain \'OFF\'"
2328df9185cSdrh} {0 {}}
2338df9185cSdrhdo_test shell1-2.3.7 {
2348df9185cSdrh  catchcmd "test.db" ".\'explain\' \'OFF\'"
2358df9185cSdrh} {0 {}}
2368df9185cSdrh
2378df9185cSdrh# check quoted args are unquoted
2388df9185cSdrhdo_test shell1-2.4.1 {
2398df9185cSdrh  catchcmd "test.db" ".mode FOO"
2408df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
2418df9185cSdrhdo_test shell1-2.4.2 {
2428df9185cSdrh  catchcmd "test.db" ".mode csv"
2438df9185cSdrh} {0 {}}
2448df9185cSdrhdo_test shell1-2.4.2 {
2458df9185cSdrh  catchcmd "test.db" ".mode \"csv\""
2468df9185cSdrh} {0 {}}
2478df9185cSdrh
2488df9185cSdrh
2498df9185cSdrh#----------------------------------------------------------------------------
2508df9185cSdrh# Test cases shell1-3.*: Basic test that "dot" command can be called.
2518df9185cSdrh#
2528df9185cSdrh
2538df9185cSdrh# .backup ?DB? FILE      Backup DB (default "main") to FILE
2548df9185cSdrhdo_test shell1-3.1.1 {
2558df9185cSdrh  catchcmd "test.db" ".backup"
256bc46f02cSdrh} {1 {missing FILENAME argument on .backup}}
2578df9185cSdrhdo_test shell1-3.1.2 {
2588df9185cSdrh  catchcmd "test.db" ".backup FOO"
2598df9185cSdrh} {0 {}}
2608df9185cSdrhdo_test shell1-3.1.3 {
2618df9185cSdrh  catchcmd "test.db" ".backup FOO BAR"
2628df9185cSdrh} {1 {Error: unknown database FOO}}
2638df9185cSdrhdo_test shell1-3.1.4 {
2648df9185cSdrh  # too many arguments
2658df9185cSdrh  catchcmd "test.db" ".backup FOO BAR BAD"
266bc46f02cSdrh} {1 {too many arguments to .backup}}
2678df9185cSdrh
2688df9185cSdrh# .bail ON|OFF           Stop after hitting an error.  Default OFF
2698df9185cSdrhdo_test shell1-3.2.1 {
2708df9185cSdrh  catchcmd "test.db" ".bail"
2718df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "bail". Enter ".help" for help}}
2728df9185cSdrhdo_test shell1-3.2.2 {
2738df9185cSdrh  catchcmd "test.db" ".bail ON"
2748df9185cSdrh} {0 {}}
2758df9185cSdrhdo_test shell1-3.2.3 {
2768df9185cSdrh  catchcmd "test.db" ".bail OFF"
2778df9185cSdrh} {0 {}}
2788df9185cSdrhdo_test shell1-3.2.4 {
2798df9185cSdrh  # too many arguments
2808df9185cSdrh  catchcmd "test.db" ".bail OFF BAD"
2818df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "bail". Enter ".help" for help}}
2828df9185cSdrh
2838df9185cSdrh# .databases             List names and files of attached databases
2848df9185cSdrhdo_test shell1-3.3.1 {
285e4d31957Sdrh  catchcmd "-csv test.db" ".databases"
28686ab48fcSmistachkin} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
2878df9185cSdrhdo_test shell1-3.3.2 {
2888df9185cSdrh  # too many arguments
2898df9185cSdrh  catchcmd "test.db" ".databases BAD"
2908df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "databases". Enter ".help" for help}}
2918df9185cSdrh
2928df9185cSdrh# .dump ?TABLE? ...      Dump the database in an SQL text format
2938df9185cSdrh#                          If TABLE specified, only dump tables matching
2948df9185cSdrh#                          LIKE pattern TABLE.
2958df9185cSdrhdo_test shell1-3.4.1 {
2968df9185cSdrh  set res [catchcmd "test.db" ".dump"]
2978df9185cSdrh  list [regexp {BEGIN TRANSACTION;} $res] \
2988df9185cSdrh       [regexp {COMMIT;} $res]
2998df9185cSdrh} {1 1}
3008df9185cSdrhdo_test shell1-3.4.2 {
3018df9185cSdrh  set res [catchcmd "test.db" ".dump FOO"]
3028df9185cSdrh  list [regexp {BEGIN TRANSACTION;} $res] \
3038df9185cSdrh       [regexp {COMMIT;} $res]
3048df9185cSdrh} {1 1}
3058df9185cSdrhdo_test shell1-3.4.3 {
3068df9185cSdrh  # too many arguments
3078df9185cSdrh  catchcmd "test.db" ".dump FOO BAD"
3088df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "dump". Enter ".help" for help}}
3098df9185cSdrh
3108df9185cSdrh# .echo ON|OFF           Turn command echo on or off
3118df9185cSdrhdo_test shell1-3.5.1 {
3128df9185cSdrh  catchcmd "test.db" ".echo"
3138df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "echo". Enter ".help" for help}}
3148df9185cSdrhdo_test shell1-3.5.2 {
3158df9185cSdrh  catchcmd "test.db" ".echo ON"
3168df9185cSdrh} {0 {}}
3178df9185cSdrhdo_test shell1-3.5.3 {
3188df9185cSdrh  catchcmd "test.db" ".echo OFF"
3198df9185cSdrh} {0 {}}
3208df9185cSdrhdo_test shell1-3.5.4 {
3218df9185cSdrh  # too many arguments
3228df9185cSdrh  catchcmd "test.db" ".echo OFF BAD"
3238df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "echo". Enter ".help" for help}}
3248df9185cSdrh
3258df9185cSdrh# .exit                  Exit this program
3268df9185cSdrhdo_test shell1-3.6.1 {
3278df9185cSdrh  catchcmd "test.db" ".exit"
3288df9185cSdrh} {0 {}}
3298df9185cSdrh
3308df9185cSdrh# .explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.
3318df9185cSdrhdo_test shell1-3.7.1 {
3328df9185cSdrh  catchcmd "test.db" ".explain"
3338df9185cSdrh  # explain is the exception to the booleans.  without an option, it turns it on.
3348df9185cSdrh} {0 {}}
3358df9185cSdrhdo_test shell1-3.7.2 {
3368df9185cSdrh  catchcmd "test.db" ".explain ON"
3378df9185cSdrh} {0 {}}
3388df9185cSdrhdo_test shell1-3.7.3 {
3398df9185cSdrh  catchcmd "test.db" ".explain OFF"
3408df9185cSdrh} {0 {}}
3418df9185cSdrhdo_test shell1-3.7.4 {
3428df9185cSdrh  # too many arguments
3438df9185cSdrh  catchcmd "test.db" ".explain OFF BAD"
3448df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "explain". Enter ".help" for help}}
3458df9185cSdrh
3468df9185cSdrh
3478df9185cSdrh# .header(s) ON|OFF      Turn display of headers on or off
3488df9185cSdrhdo_test shell1-3.9.1 {
3498df9185cSdrh  catchcmd "test.db" ".header"
3508df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "header". Enter ".help" for help}}
3518df9185cSdrhdo_test shell1-3.9.2 {
3528df9185cSdrh  catchcmd "test.db" ".header ON"
3538df9185cSdrh} {0 {}}
3548df9185cSdrhdo_test shell1-3.9.3 {
3558df9185cSdrh  catchcmd "test.db" ".header OFF"
3568df9185cSdrh} {0 {}}
3578df9185cSdrhdo_test shell1-3.9.4 {
3588df9185cSdrh  # too many arguments
3598df9185cSdrh  catchcmd "test.db" ".header OFF BAD"
3608df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "header". Enter ".help" for help}}
3618df9185cSdrh
3628df9185cSdrhdo_test shell1-3.9.5 {
3638df9185cSdrh  catchcmd "test.db" ".headers"
3648df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "headers". Enter ".help" for help}}
3658df9185cSdrhdo_test shell1-3.9.6 {
3668df9185cSdrh  catchcmd "test.db" ".headers ON"
3678df9185cSdrh} {0 {}}
3688df9185cSdrhdo_test shell1-3.9.7 {
3698df9185cSdrh  catchcmd "test.db" ".headers OFF"
3708df9185cSdrh} {0 {}}
3718df9185cSdrhdo_test shell1-3.9.8 {
3728df9185cSdrh  # too many arguments
3738df9185cSdrh  catchcmd "test.db" ".headers OFF BAD"
3748df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "headers". Enter ".help" for help}}
3758df9185cSdrh
3768df9185cSdrh# .help                  Show this message
3778df9185cSdrhdo_test shell1-3.10.1 {
3788df9185cSdrh  set res [catchcmd "test.db" ".help"]
3798df9185cSdrh  # look for a few of the possible help commands
3808df9185cSdrh  list [regexp {.help} $res] \
3818df9185cSdrh       [regexp {.quit} $res] \
3828df9185cSdrh       [regexp {.show} $res]
3838df9185cSdrh} {1 1 1}
3848df9185cSdrhdo_test shell1-3.10.2 {
3858df9185cSdrh  # we allow .help to take extra args (it is help after all)
3868df9185cSdrh  set res [catchcmd "test.db" ".help BAD"]
3878df9185cSdrh  # look for a few of the possible help commands
3888df9185cSdrh  list [regexp {.help} $res] \
3898df9185cSdrh       [regexp {.quit} $res] \
3908df9185cSdrh       [regexp {.show} $res]
3918df9185cSdrh} {1 1 1}
3928df9185cSdrh
3938df9185cSdrh# .import FILE TABLE     Import data from FILE into TABLE
3948df9185cSdrhdo_test shell1-3.11.1 {
3958df9185cSdrh  catchcmd "test.db" ".import"
3968df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
3978df9185cSdrhdo_test shell1-3.11.2 {
3988df9185cSdrh  catchcmd "test.db" ".import FOO"
3998df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
400*db95f68bSdrh#do_test shell1-3.11.2 {
401*db95f68bSdrh#  catchcmd "test.db" ".import FOO BAR"
402*db95f68bSdrh#} {1 {Error: no such table: BAR}}
4038df9185cSdrhdo_test shell1-3.11.3 {
4048df9185cSdrh  # too many arguments
4058df9185cSdrh  catchcmd "test.db" ".import FOO BAR BAD"
4068df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "import". Enter ".help" for help}}
4078df9185cSdrh
4088df9185cSdrh# .indices ?TABLE?       Show names of all indices
4098df9185cSdrh#                          If TABLE specified, only show indices for tables
4108df9185cSdrh#                          matching LIKE pattern TABLE.
4118df9185cSdrhdo_test shell1-3.12.1 {
4128df9185cSdrh  catchcmd "test.db" ".indices"
4138df9185cSdrh} {0 {}}
4148df9185cSdrhdo_test shell1-3.12.2 {
4158df9185cSdrh  catchcmd "test.db" ".indices FOO"
4168df9185cSdrh} {0 {}}
4178df9185cSdrhdo_test shell1-3.12.3 {
4188df9185cSdrh  # too many arguments
4198df9185cSdrh  catchcmd "test.db" ".indices FOO BAD"
4208df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "indices". Enter ".help" for help}}
4218df9185cSdrh
4228df9185cSdrh# .mode MODE ?TABLE?     Set output mode where MODE is one of:
4238df9185cSdrh#                          csv      Comma-separated values
4248df9185cSdrh#                          column   Left-aligned columns.  (See .width)
4258df9185cSdrh#                          html     HTML <table> code
4268df9185cSdrh#                          insert   SQL insert statements for TABLE
4278df9185cSdrh#                          line     One value per line
4288df9185cSdrh#                          list     Values delimited by .separator string
4298df9185cSdrh#                          tabs     Tab-separated values
4308df9185cSdrh#                          tcl      TCL list elements
4318df9185cSdrhdo_test shell1-3.13.1 {
4328df9185cSdrh  catchcmd "test.db" ".mode"
4338df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "mode". Enter ".help" for help}}
4348df9185cSdrhdo_test shell1-3.13.2 {
4358df9185cSdrh  catchcmd "test.db" ".mode FOO"
4368df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
4378df9185cSdrhdo_test shell1-3.13.3 {
4388df9185cSdrh  catchcmd "test.db" ".mode csv"
4398df9185cSdrh} {0 {}}
4408df9185cSdrhdo_test shell1-3.13.4 {
4418df9185cSdrh  catchcmd "test.db" ".mode column"
4428df9185cSdrh} {0 {}}
4438df9185cSdrhdo_test shell1-3.13.5 {
4448df9185cSdrh  catchcmd "test.db" ".mode html"
4458df9185cSdrh} {0 {}}
4468df9185cSdrhdo_test shell1-3.13.6 {
4478df9185cSdrh  catchcmd "test.db" ".mode insert"
4488df9185cSdrh} {0 {}}
4498df9185cSdrhdo_test shell1-3.13.7 {
4508df9185cSdrh  catchcmd "test.db" ".mode line"
4518df9185cSdrh} {0 {}}
4528df9185cSdrhdo_test shell1-3.13.8 {
4538df9185cSdrh  catchcmd "test.db" ".mode list"
4548df9185cSdrh} {0 {}}
4558df9185cSdrhdo_test shell1-3.13.9 {
4568df9185cSdrh  catchcmd "test.db" ".mode tabs"
4578df9185cSdrh} {0 {}}
4588df9185cSdrhdo_test shell1-3.13.10 {
4598df9185cSdrh  catchcmd "test.db" ".mode tcl"
4608df9185cSdrh} {0 {}}
4618df9185cSdrhdo_test shell1-3.13.11 {
4628df9185cSdrh  # too many arguments
4638df9185cSdrh  catchcmd "test.db" ".mode tcl BAD"
4648df9185cSdrh} {1 {Error: invalid arguments:  "BAD". Enter ".help" for help}}
4658df9185cSdrh
4668df9185cSdrh# don't allow partial mode type matches
4678df9185cSdrhdo_test shell1-3.13.12 {
4688df9185cSdrh  catchcmd "test.db" ".mode l"
4698df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
4708df9185cSdrhdo_test shell1-3.13.13 {
4718df9185cSdrh  catchcmd "test.db" ".mode li"
4728df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
4738df9185cSdrhdo_test shell1-3.13.14 {
4748df9185cSdrh  catchcmd "test.db" ".mode lin"
4758df9185cSdrh} {1 {Error: mode should be one of: column csv html insert line list tabs tcl}}
4768df9185cSdrh
4778df9185cSdrh# .nullvalue STRING      Print STRING in place of NULL values
4788df9185cSdrhdo_test shell1-3.14.1 {
4798df9185cSdrh  catchcmd "test.db" ".nullvalue"
4808df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "nullvalue". Enter ".help" for help}}
4818df9185cSdrhdo_test shell1-3.14.2 {
4828df9185cSdrh  catchcmd "test.db" ".nullvalue FOO"
4838df9185cSdrh} {0 {}}
4848df9185cSdrhdo_test shell1-3.14.3 {
4858df9185cSdrh  # too many arguments
4868df9185cSdrh  catchcmd "test.db" ".nullvalue FOO BAD"
4878df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "nullvalue". Enter ".help" for help}}
4888df9185cSdrh
4898df9185cSdrh# .output FILENAME       Send output to FILENAME
4908df9185cSdrhdo_test shell1-3.15.1 {
4918df9185cSdrh  catchcmd "test.db" ".output"
4928df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
4938df9185cSdrhdo_test shell1-3.15.2 {
4948df9185cSdrh  catchcmd "test.db" ".output FOO"
4958df9185cSdrh} {0 {}}
4968df9185cSdrhdo_test shell1-3.15.3 {
4978df9185cSdrh  # too many arguments
4988df9185cSdrh  catchcmd "test.db" ".output FOO BAD"
4998df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
5008df9185cSdrh
5018df9185cSdrh# .output stdout         Send output to the screen
5028df9185cSdrhdo_test shell1-3.16.1 {
5038df9185cSdrh  catchcmd "test.db" ".output stdout"
5048df9185cSdrh} {0 {}}
5058df9185cSdrhdo_test shell1-3.16.2 {
5068df9185cSdrh  # too many arguments
5078df9185cSdrh  catchcmd "test.db" ".output stdout BAD"
5088df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "output". Enter ".help" for help}}
5098df9185cSdrh
5108df9185cSdrh# .prompt MAIN CONTINUE  Replace the standard prompts
5118df9185cSdrhdo_test shell1-3.17.1 {
5128df9185cSdrh  catchcmd "test.db" ".prompt"
5138df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "prompt". Enter ".help" for help}}
5148df9185cSdrhdo_test shell1-3.17.2 {
5158df9185cSdrh  catchcmd "test.db" ".prompt FOO"
5168df9185cSdrh} {0 {}}
5178df9185cSdrhdo_test shell1-3.17.3 {
5188df9185cSdrh  catchcmd "test.db" ".prompt FOO BAR"
5198df9185cSdrh} {0 {}}
5208df9185cSdrhdo_test shell1-3.17.4 {
5218df9185cSdrh  # too many arguments
5228df9185cSdrh  catchcmd "test.db" ".prompt FOO BAR BAD"
5238df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "prompt". Enter ".help" for help}}
5248df9185cSdrh
5258df9185cSdrh# .quit                  Exit this program
5268df9185cSdrhdo_test shell1-3.18.1 {
5278df9185cSdrh  catchcmd "test.db" ".quit"
5288df9185cSdrh} {0 {}}
5298df9185cSdrhdo_test shell1-3.18.2 {
5308df9185cSdrh  # too many arguments
5318df9185cSdrh  catchcmd "test.db" ".quit BAD"
5328df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "quit". Enter ".help" for help}}
5338df9185cSdrh
5348df9185cSdrh# .read FILENAME         Execute SQL in FILENAME
5358df9185cSdrhdo_test shell1-3.19.1 {
5368df9185cSdrh  catchcmd "test.db" ".read"
5378df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "read". Enter ".help" for help}}
5388df9185cSdrhdo_test shell1-3.19.2 {
5398df9185cSdrh  file delete -force FOO
5408df9185cSdrh  catchcmd "test.db" ".read FOO"
5418df9185cSdrh} {1 {Error: cannot open "FOO"}}
5428df9185cSdrhdo_test shell1-3.19.3 {
5438df9185cSdrh  # too many arguments
5448df9185cSdrh  catchcmd "test.db" ".read FOO BAD"
5458df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "read". Enter ".help" for help}}
5468df9185cSdrh
5478df9185cSdrh# .restore ?DB? FILE     Restore content of DB (default "main") from FILE
5488df9185cSdrhdo_test shell1-3.20.1 {
5498df9185cSdrh  catchcmd "test.db" ".restore"
5508df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "restore". Enter ".help" for help}}
5518df9185cSdrhdo_test shell1-3.20.2 {
5528df9185cSdrh  catchcmd "test.db" ".restore FOO"
5538df9185cSdrh} {0 {}}
5548df9185cSdrhdo_test shell1-3.20.3 {
5558df9185cSdrh  catchcmd "test.db" ".restore FOO BAR"
5568df9185cSdrh} {1 {Error: unknown database FOO}}
5578df9185cSdrhdo_test shell1-3.20.4 {
5588df9185cSdrh  # too many arguments
5598df9185cSdrh  catchcmd "test.db" ".restore FOO BAR BAD"
5608df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "restore". Enter ".help" for help}}
5618df9185cSdrh
5628df9185cSdrh# .schema ?TABLE?        Show the CREATE statements
5638df9185cSdrh#                          If TABLE specified, only show tables matching
5648df9185cSdrh#                          LIKE pattern TABLE.
5658df9185cSdrhdo_test shell1-3.21.1 {
5668df9185cSdrh  catchcmd "test.db" ".schema"
5678df9185cSdrh} {0 {}}
5688df9185cSdrhdo_test shell1-3.21.2 {
5698df9185cSdrh  catchcmd "test.db" ".schema FOO"
5708df9185cSdrh} {0 {}}
5718df9185cSdrhdo_test shell1-3.21.3 {
5728df9185cSdrh  # too many arguments
5738df9185cSdrh  catchcmd "test.db" ".schema FOO BAD"
5748df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "schema". Enter ".help" for help}}
5758df9185cSdrh
576ac43e98dSdrhdo_test shell1-3.21.4 {
577ac43e98dSdrh  catchcmd "test.db" {
578ac43e98dSdrh     CREATE TABLE t1(x);
579ac43e98dSdrh     CREATE VIEW v2 AS SELECT x+1 AS y FROM t1;
580ac43e98dSdrh     CREATE VIEW v1 AS SELECT y+1 FROM v2;
581ac43e98dSdrh  }
582ac43e98dSdrh  catchcmd "test.db" ".schema"
583ac43e98dSdrh} {0 {CREATE TABLE t1(x);
584ac43e98dSdrhCREATE VIEW v2 AS SELECT x+1 AS y FROM t1;
585ac43e98dSdrhCREATE VIEW v1 AS SELECT y+1 FROM v2;}}
586ac43e98dSdrhdb eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
587ac43e98dSdrh
5888df9185cSdrh# .separator STRING      Change separator used by output mode and .import
5898df9185cSdrhdo_test shell1-3.22.1 {
5908df9185cSdrh  catchcmd "test.db" ".separator"
5918df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "separator". Enter ".help" for help}}
5928df9185cSdrhdo_test shell1-3.22.2 {
5938df9185cSdrh  catchcmd "test.db" ".separator FOO"
5948df9185cSdrh} {0 {}}
5958df9185cSdrhdo_test shell1-3.22.3 {
5968df9185cSdrh  # too many arguments
5978df9185cSdrh  catchcmd "test.db" ".separator FOO BAD"
5988df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "separator". Enter ".help" for help}}
5998df9185cSdrh
6008df9185cSdrh# .show                  Show the current values for various settings
6018df9185cSdrhdo_test shell1-3.23.1 {
6028df9185cSdrh  set res [catchcmd "test.db" ".show"]
6038df9185cSdrh  list [regexp {echo:} $res] \
6048df9185cSdrh       [regexp {explain:} $res] \
6058df9185cSdrh       [regexp {headers:} $res] \
6068df9185cSdrh       [regexp {mode:} $res] \
6078df9185cSdrh       [regexp {nullvalue:} $res] \
6088df9185cSdrh       [regexp {output:} $res] \
6098df9185cSdrh       [regexp {separator:} $res] \
6108df9185cSdrh       [regexp {stats:} $res] \
6118df9185cSdrh       [regexp {width:} $res]
6128df9185cSdrh} {1 1 1 1 1 1 1 1 1}
6138df9185cSdrhdo_test shell1-3.23.2 {
6148df9185cSdrh  # too many arguments
6158df9185cSdrh  catchcmd "test.db" ".show BAD"
6168df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "show". Enter ".help" for help}}
6178df9185cSdrh
6188df9185cSdrh# .stats ON|OFF          Turn stats on or off
6198df9185cSdrhdo_test shell1-3.23b.1 {
6208df9185cSdrh  catchcmd "test.db" ".stats"
6218df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "stats". Enter ".help" for help}}
6228df9185cSdrhdo_test shell1-3.23b.2 {
6238df9185cSdrh  catchcmd "test.db" ".stats ON"
6248df9185cSdrh} {0 {}}
6258df9185cSdrhdo_test shell1-3.23b.3 {
6268df9185cSdrh  catchcmd "test.db" ".stats OFF"
6278df9185cSdrh} {0 {}}
6288df9185cSdrhdo_test shell1-3.23b.4 {
6298df9185cSdrh  # too many arguments
6308df9185cSdrh  catchcmd "test.db" ".stats OFF BAD"
6318df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "stats". Enter ".help" for help}}
6328df9185cSdrh
6338df9185cSdrh# .tables ?TABLE?        List names of tables
6348df9185cSdrh#                          If TABLE specified, only list tables matching
6358df9185cSdrh#                          LIKE pattern TABLE.
6368df9185cSdrhdo_test shell1-3.24.1 {
6378df9185cSdrh  catchcmd "test.db" ".tables"
6388df9185cSdrh} {0 {}}
6398df9185cSdrhdo_test shell1-3.24.2 {
6408df9185cSdrh  catchcmd "test.db" ".tables FOO"
6418df9185cSdrh} {0 {}}
6428df9185cSdrhdo_test shell1-3.24.3 {
6438df9185cSdrh  # too many arguments
6448df9185cSdrh  catchcmd "test.db" ".tables FOO BAD"
6458df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "tables". Enter ".help" for help}}
6468df9185cSdrh
6478df9185cSdrh# .timeout MS            Try opening locked tables for MS milliseconds
6488df9185cSdrhdo_test shell1-3.25.1 {
6498df9185cSdrh  catchcmd "test.db" ".timeout"
6508df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "timeout". Enter ".help" for help}}
6518df9185cSdrhdo_test shell1-3.25.2 {
6528df9185cSdrh  catchcmd "test.db" ".timeout zzz"
6538df9185cSdrh  # this should be treated the same as a '0' timeout
6548df9185cSdrh} {0 {}}
6558df9185cSdrhdo_test shell1-3.25.3 {
6568df9185cSdrh  catchcmd "test.db" ".timeout 1"
6578df9185cSdrh} {0 {}}
6588df9185cSdrhdo_test shell1-3.25.4 {
6598df9185cSdrh  # too many arguments
6608df9185cSdrh  catchcmd "test.db" ".timeout 1 BAD"
6618df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "timeout". Enter ".help" for help}}
6628df9185cSdrh
6638df9185cSdrh# .width NUM NUM ...     Set column widths for "column" mode
6648df9185cSdrhdo_test shell1-3.26.1 {
6658df9185cSdrh  catchcmd "test.db" ".width"
6668df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "width". Enter ".help" for help}}
6678df9185cSdrhdo_test shell1-3.26.2 {
6688df9185cSdrh  catchcmd "test.db" ".width xxx"
6698df9185cSdrh  # this should be treated the same as a '0' width for col 1
6708df9185cSdrh} {0 {}}
6718df9185cSdrhdo_test shell1-3.26.3 {
6728df9185cSdrh  catchcmd "test.db" ".width xxx yyy"
6738df9185cSdrh  # this should be treated the same as a '0' width for col 1 and 2
6748df9185cSdrh} {0 {}}
6758df9185cSdrhdo_test shell1-3.26.4 {
6768df9185cSdrh  catchcmd "test.db" ".width 1 1"
6778df9185cSdrh  # this should be treated the same as a '1' width for col 1 and 2
6788df9185cSdrh} {0 {}}
679078b1fdaSdrhdo_test shell1-3.26.5 {
680078b1fdaSdrh  catchcmd "test.db" ".mode column\n.width 10 -10\nSELECT 'abcdefg', 123456;"
681078b1fdaSdrh  # this should be treated the same as a '1' width for col 1 and 2
682078b1fdaSdrh} {0 {abcdefg         123456}}
683078b1fdaSdrhdo_test shell1-3.26.6 {
684078b1fdaSdrh  catchcmd "test.db" ".mode column\n.width -10 10\nSELECT 'abcdefg', 123456;"
685078b1fdaSdrh  # this should be treated the same as a '1' width for col 1 and 2
686078b1fdaSdrh} {0 {   abcdefg  123456    }}
687078b1fdaSdrh
6888df9185cSdrh
6898df9185cSdrh# .timer ON|OFF          Turn the CPU timer measurement on or off
6908df9185cSdrhdo_test shell1-3.27.1 {
6918df9185cSdrh  catchcmd "test.db" ".timer"
6928df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "timer". Enter ".help" for help}}
6938df9185cSdrhdo_test shell1-3.27.2 {
6948df9185cSdrh  catchcmd "test.db" ".timer ON"
6958df9185cSdrh} {0 {}}
6968df9185cSdrhdo_test shell1-3.27.3 {
6978df9185cSdrh  catchcmd "test.db" ".timer OFF"
6988df9185cSdrh} {0 {}}
6998df9185cSdrhdo_test shell1-3.27.4 {
7008df9185cSdrh  # too many arguments
7018df9185cSdrh  catchcmd "test.db" ".timer OFF BAD"
7028df9185cSdrh} {1 {Error: unknown command or invalid arguments:  "timer". Enter ".help" for help}}
7038df9185cSdrh
7048df9185cSdrhdo_test shell1-3-28.1 {
7058df9185cSdrh  catchcmd test.db \
7068df9185cSdrh     ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');"
7078df9185cSdrh} "0 {(123) hello\n456}"
7088df9185cSdrh
709078b1fdaSdrhdo_test shell1-3-29.1 {
710078b1fdaSdrh  catchcmd "test.db" ".print this is a test"
711078b1fdaSdrh} {0 {this is a test}}
712078b1fdaSdrh
7135128e85cSdrh# Test the output of the ".dump" command
7145128e85cSdrh#
7155128e85cSdrhdo_test shell1-4.1 {
7165128e85cSdrh  db eval {
7175128e85cSdrh    CREATE TABLE t1(x);
718585dcb25Smistachkin    INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f');
7195128e85cSdrh  }
7205128e85cSdrh  catchcmd test.db {.dump}
7215128e85cSdrh} {0 {PRAGMA foreign_keys=OFF;
7225128e85cSdrhBEGIN TRANSACTION;
7235128e85cSdrhCREATE TABLE t1(x);
7245128e85cSdrhINSERT INTO "t1" VALUES(NULL);
725585dcb25SmistachkinINSERT INTO "t1" VALUES('');
7265128e85cSdrhINSERT INTO "t1" VALUES(1);
7275128e85cSdrhINSERT INTO "t1" VALUES(2.25);
7285128e85cSdrhINSERT INTO "t1" VALUES('hello');
7295128e85cSdrhINSERT INTO "t1" VALUES(X'807F');
7305128e85cSdrhCOMMIT;}}
7315128e85cSdrh
7325128e85cSdrh# Test the output of ".mode insert"
7335128e85cSdrh#
7345128e85cSdrhdo_test shell1-4.2 {
7355128e85cSdrh  catchcmd test.db ".mode insert t1\nselect * from t1;"
7365128e85cSdrh} {0 {INSERT INTO t1 VALUES(NULL);
737585dcb25SmistachkinINSERT INTO t1 VALUES('');
7385128e85cSdrhINSERT INTO t1 VALUES(1);
7395128e85cSdrhINSERT INTO t1 VALUES(2.25);
7405128e85cSdrhINSERT INTO t1 VALUES('hello');
7415128e85cSdrhINSERT INTO t1 VALUES(X'807f');}}
7425128e85cSdrh
743585dcb25Smistachkin# Test the output of ".mode tcl"
744585dcb25Smistachkin#
745585dcb25Smistachkindo_test shell1-4.3 {
746585dcb25Smistachkin  catchcmd test.db ".mode tcl\nselect * from t1;"
747585dcb25Smistachkin} {0 {""
748585dcb25Smistachkin""
749585dcb25Smistachkin"1"
750585dcb25Smistachkin"2.25"
751585dcb25Smistachkin"hello"
752585dcb25Smistachkin"\200\177"}}
753585dcb25Smistachkin
754585dcb25Smistachkin# Test the output of ".mode tcl" with multiple columns
755585dcb25Smistachkin#
756585dcb25Smistachkindo_test shell1-4.4 {
757585dcb25Smistachkin  db eval {
758585dcb25Smistachkin    CREATE TABLE t2(x,y);
759585dcb25Smistachkin    INSERT INTO t2 VALUES(null, ''), (1, 2.25), ('hello', x'807f');
760585dcb25Smistachkin  }
761585dcb25Smistachkin  catchcmd test.db ".mode tcl\nselect * from t2;"
762585dcb25Smistachkin} {0 {"" ""
763585dcb25Smistachkin"1" "2.25"
764585dcb25Smistachkin"hello" "\200\177"}}
765585dcb25Smistachkin
766585dcb25Smistachkin# Test the output of ".mode tcl" with ".nullvalue"
767585dcb25Smistachkin#
768585dcb25Smistachkindo_test shell1-4.5 {
769585dcb25Smistachkin  catchcmd test.db ".mode tcl\n.nullvalue NULL\nselect * from t2;"
770585dcb25Smistachkin} {0 {"NULL" ""
771585dcb25Smistachkin"1" "2.25"
772585dcb25Smistachkin"hello" "\200\177"}}
773585dcb25Smistachkin
774585dcb25Smistachkin# Test the output of ".mode tcl" with Tcl reserved characters
775585dcb25Smistachkin#
776585dcb25Smistachkindo_test shell1-4.6 {
777585dcb25Smistachkin  db eval {
778585dcb25Smistachkin    CREATE TABLE tcl1(x);
779585dcb25Smistachkin    INSERT INTO tcl1 VALUES('"'), ('['), (']'), ('\{'), ('\}'), (';'), ('$');
780585dcb25Smistachkin  }
781585dcb25Smistachkin  foreach {x y} [catchcmd test.db ".mode tcl\nselect * from tcl1;"] break
782585dcb25Smistachkin  list $x $y [llength $y]
783585dcb25Smistachkin} {0 {"\""
784585dcb25Smistachkin"["
785585dcb25Smistachkin"]"
786585dcb25Smistachkin"\\{"
787585dcb25Smistachkin"\\}"
788585dcb25Smistachkin";"
789585dcb25Smistachkin"$"} 7}
7905128e85cSdrh
7918df9185cSdrhfinish_test
792