| # 2025-02-24 |
| # |
| # The author disclaims copyright to this source code. In place of |
| # a legal notice, here is a blessing: |
| # |
| # May you do good and not evil. |
| # May you find forgiveness for yourself and forgive others. |
| # May you share freely, never taking more than you give. |
| # |
| #*********************************************************************** |
| # TESTRUNNER: shell |
| # |
| # Test cases for the command-line shell - focusing on .mode and |
| # especially control-character escaping and the --escape option. |
| # |
| # |
| |
| set testdir [file dirname $argv0] |
| source $testdir/tester.tcl |
| set CLI [test_cli_invocation] |
| |
| do_execsql_test shellA-1.0 { |
| CREATE TABLE t1(a INT, x TEXT); |
| INSERT INTO t1 VALUES |
| (1, 'line with '' single quote'), |
| (2, concat(char(0x1b),'[31mVT-100 codes',char(0x1b),'[0m')), |
| (3, NULL), |
| (4, 1234), |
| (5, 568.25), |
| (6, unistr('new\u000aline')), |
| (7, unistr('carriage\u000dreturn')), |
| (8, 'last line'); |
| } {} |
| |
| # Initial verification that the database created correctly |
| # and that our calls to the CLI are working. |
| # |
| do_test_with_ansi_output shellA-1.2 { |
| exec {*}$CLI -noinit test.db {.mode box -quote off --escape symbol} {SELECT * FROM t1;} |
| } { |
| ╭───┬──────────────────────────╮ |
| │ a │ x │ |
| ╞═══╪══════════════════════════╡ |
| │ 1 │ line with ' single quote │ |
| ├───┼──────────────────────────┤ |
| │ 2 │ ␛[31mVT-100 codes␛[0m │ |
| ├───┼──────────────────────────┤ |
| │ 3 │ │ |
| ├───┼──────────────────────────┤ |
| │ 4 │ 1234 │ |
| ├───┼──────────────────────────┤ |
| │ 5 │ 568.25 │ |
| ├───┼──────────────────────────┤ |
| │ 6 │ new │ |
| │ │ line │ |
| ├───┼──────────────────────────┤ |
| │ 7 │ carriage␍return │ |
| ├───┼──────────────────────────┤ |
| │ 8 │ last line │ |
| ╰───┴──────────────────────────╯ |
| } |
| |
| # ".mode list" |
| # |
| do_test shellA-1.3 { |
| exec {*}$CLI -noinit -list test.db {SELECT x FROM t1 WHERE a=2;} |
| } { |
| ^[[31mVT-100 codes^[[0m |
| } |
| do_test_with_ansi_output shellA-1.4 { |
| exec {*}$CLI -noinit -list test.db --escape symbol {SELECT x FROM t1 WHERE a=2;} |
| } { |
| ␛[31mVT-100 codes␛[0m |
| } |
| do_test shellA-1.5 { |
| exec {*}$CLI -noinit -list test.db --escape ascii {SELECT x FROM t1 WHERE a=2;} |
| } { |
| ^[[31mVT-100 codes^[[0m |
| } |
| do_test_with_ansi_output shellA-1.6 { |
| exec {*}$CLI -noinit test.db {.mode list --escape symbol} {SELECT x FROM t1 WHERE a=2;} |
| } { |
| ␛[31mVT-100 codes␛[0m |
| } |
| do_test shellA-1.7 { |
| exec {*}$CLI -noinit test.db {.mode list --escape ascii} {SELECT x FROM t1 WHERE a=2;} |
| } { |
| ^[[31mVT-100 codes^[[0m |
| } |
| do_test shellA-1.8 { |
| file delete -force out.txt |
| exec {*}$CLI -noinit test.db {.mode list --escape off} {SELECT x FROM t1 WHERE a=7;} \ |
| >out.txt |
| set fd [open out.txt rb] |
| set res [read $fd] |
| close $fd |
| string trim $res |
| } "carriage\rreturn" |
| do_test shellA-1.9 { |
| set rc [catch { |
| exec {*}$CLI -noinit test.db {.mode test --escape xyz} |
| } msg] |
| lappend rc $msg |
| } {1 {argv[3]: .mode test --escape xyz |
| argv[3]: ^--- unknown mode |
| argv[3]: Use ".help .mode" for more info}} |
| do_test shellA-1.10 { |
| set rc [catch { |
| exec {*}$CLI --noinit --escape abc test.db .q |
| } msg] |
| lappend rc $msg |
| } {1 {unknown control character escape mode "abc" - choices: auto off ascii symbol}} |
| |
| # ".mode quote" |
| # |
| do_test shellA-2.1 { |
| exec {*}$CLI -noinit test.db --quote {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| 1,'line with '' single quote' |
| 2,unistr('\u001b[31mVT-100 codes\u001b[0m') |
| 6,unistr('new\u000aline') |
| 7,unistr('carriage\u000dreturn') |
| 8,'last line' |
| } |
| do_test shellA-2.2 { |
| exec {*}$CLI -noinit test.db --quote {.mode -v} |
| } {/*.mode quote* --escape auto*/} |
| do_test shellA-2.3 { |
| exec {*}$CLI -noinit test.db --quote --escape SYMBOL {.mode} |
| } {.mode quote --escape symbol} |
| do_test shellA-2.4 { |
| exec {*}$CLI -noinit test.db --quote --escape OFF {.mode} |
| } {.mode quote --escape off} |
| |
| |
| # ".mode line" |
| # |
| do_test_with_ansi_output shellA-3.1 { |
| exec {*}$CLI -noinit test.db --line --escape symbol \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| a: 1 |
| x: line with ' single quote |
| |
| a: 2 |
| x: ␛[31mVT-100 codes␛[0m |
| |
| a: 6 |
| x: new |
| line |
| |
| a: 7 |
| x: carriage␍return |
| |
| a: 8 |
| x: last line |
| } |
| do_test shellA-3.2 { |
| exec {*}$CLI -noinit test.db --line --escape ascii \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| a: 1 |
| x: line with ' single quote |
| |
| a: 2 |
| x: ^[[31mVT-100 codes^[[0m |
| |
| a: 6 |
| x: new |
| line |
| |
| a: 7 |
| x: carriage^Mreturn |
| |
| a: 8 |
| x: last line |
| } |
| |
| # ".mode box" |
| # |
| do_test_with_ansi_output shellA-4.1 { |
| exec {*}$CLI -noinit test.db --box --escape ascii \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| ╭───┬──────────────────────────╮ |
| │ a │ x │ |
| ╞═══╪══════════════════════════╡ |
| │ 1 │ line with ' single quote │ |
| ├───┼──────────────────────────┤ |
| │ 2 │ ^[[31mVT-100 codes^[[0m │ |
| ├───┼──────────────────────────┤ |
| │ 6 │ new │ |
| │ │ line │ |
| ├───┼──────────────────────────┤ |
| │ 7 │ carriage^Mreturn │ |
| ├───┼──────────────────────────┤ |
| │ 8 │ last line │ |
| ╰───┴──────────────────────────╯ |
| } |
| do_test_with_ansi_output shellA-4.1b { |
| exec {*}$CLI -noinit test.db --box --escape ascii \ |
| {.mode -border off} \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| a │ x |
| ═══╪══════════════════════════ |
| 1 │ line with ' single quote |
| ───┼────────────────────────── |
| 2 │ ^[[31mVT-100 codes^[[0m |
| ───┼────────────────────────── |
| 6 │ new |
| │ line |
| ───┼────────────────────────── |
| 7 │ carriage^Mreturn |
| ───┼────────────────────────── |
| 8 │ last line |
| } |
| do_test_with_ansi_output shellA-4.2 { |
| exec {*}$CLI -noinit test.db {.mode qbox} {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| ╭───┬───────────────────────────────────────────╮ |
| │ a │ x │ |
| ╞═══╪═══════════════════════════════════════════╡ |
| │ 1 │ 'line with '' single quote' │ |
| │ 2 │ unistr('\u001b[31mVT-100 codes\u001b[0m') │ |
| │ 6 │ unistr('new\u000aline') │ |
| │ 7 │ unistr('carriage\u000dreturn') │ |
| │ 8 │ 'last line' │ |
| ╰───┴───────────────────────────────────────────╯ |
| } |
| do_test_with_ansi_output shellA-4.2b { |
| exec {*}$CLI -noinit test.db {.mode qbox -border off} \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| a │ x |
| ═══╪═══════════════════════════════════════════ |
| 1 │ 'line with '' single quote' |
| 2 │ unistr('\u001b[31mVT-100 codes\u001b[0m') |
| 6 │ unistr('new\u000aline') |
| 7 │ unistr('carriage\u000dreturn') |
| 8 │ 'last line' |
| } |
| |
| # ".mode insert" |
| # |
| do_test shellA-5.1 { |
| exec {*}$CLI -noinit test.db {.mode insert t1 --escape ascii} \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| INSERT INTO t1 VALUES(1,'line with '' single quote'); |
| INSERT INTO t1 VALUES(2,unistr('\u001b[31mVT-100 codes\u001b[0m')); |
| INSERT INTO t1 VALUES(6,unistr('new\u000aline')); |
| INSERT INTO t1 VALUES(7,unistr('carriage\u000dreturn')); |
| INSERT INTO t1 VALUES(8,'last line'); |
| } |
| do_test shellA-5.2 { |
| exec {*}$CLI -noinit test.db {.mode insert t1 --escape symbol} \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} |
| } { |
| INSERT INTO t1 VALUES(1,'line with '' single quote'); |
| INSERT INTO t1 VALUES(2,unistr('\u001b[31mVT-100 codes\u001b[0m')); |
| INSERT INTO t1 VALUES(6,unistr('new\u000aline')); |
| INSERT INTO t1 VALUES(7,unistr('carriage\u000dreturn')); |
| INSERT INTO t1 VALUES(8,'last line'); |
| } |
| do_test shellA-5.3 { |
| file delete -force out.txt |
| exec {*}$CLI -noinit test.db {.mode insert t1 --escape off} \ |
| {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)} >out.txt |
| set fd [open out.txt rb] |
| set res [read $fd] |
| close $fd |
| string trim [string map [list \r\n \n] $res] |
| } " |
| INSERT INTO t1 VALUES(1,'line with '' single quote'); |
| INSERT INTO t1 VALUES(2,'\033\13331mVT-100 codes\033\1330m'); |
| INSERT INTO t1 VALUES(6,'new |
| line'); |
| INSERT INTO t1 VALUES(7,'carriage\rreturn'); |
| INSERT INTO t1 VALUES(8,'last line'); |
| " |
| |
| # ".mode split" |
| # |
| do_test shellA-6.1 { |
| db eval { |
| CREATE TABLE t2(x); |
| INSERT INTO t2(x) VALUES |
| ('one'), ('two'), ('three'), ('four'), ('five'), |
| ('six'), ('seven'), ('eight'), ('nine'), ('ten'), |
| ('eleven'), ('twelve'), ('thirteen'), ('fourteen'); |
| } |
| exec {*}$CLI -noinit test.db \ |
| {.print} \ |
| {.mode split -screenwidth 30} \ |
| {SELECT x FROM t2} |
| } { |
| one five nine thirteen |
| two six ten fourteen |
| three seven eleven |
| four eight twelve} |
| # 3456789 123456789 123456789 |
| |
| do_test shellA-6.2 { |
| exec {*}$CLI -noinit test.db \ |
| {.print} \ |
| {.mode split -screenwidth 30} \ |
| {SELECT x FROM t2} \ |
| {.mode column -titles off} \ |
| {SELECT x FROM t2} |
| } { |
| one five nine thirteen |
| two six ten fourteen |
| three seven eleven |
| four eight twelve |
| one |
| two |
| three |
| four |
| five |
| six |
| seven |
| eight |
| nine |
| ten |
| eleven |
| twelve |
| thirteen |
| fourteen} |
| |
| do_test shellA-6.3 { |
| exec {*}$CLI -noinit test.db \ |
| {.print} \ |
| {.mode table} \ |
| {.mode --once split -screenwidth 30} \ |
| {SELECT x FROM t2} \ |
| {SELECT x FROM t2} |
| } { |
| one five nine thirteen |
| two six ten fourteen |
| three seven eleven |
| four eight twelve |
| +----------+ |
| | x | |
| +----------+ |
| | one | |
| | two | |
| | three | |
| | four | |
| | five | |
| | six | |
| | seven | |
| | eight | |
| | nine | |
| | ten | |
| | eleven | |
| | twelve | |
| | thirteen | |
| | fourteen | |
| +----------+} |
| |
| finish_test |