1
1
"""sqlite3 CLI tests."""
2
-
3
- import sqlite3 as sqlite
4
- import subprocess
5
- import sys
2
+ import sqlite3
6
3
import unittest
7
4
8
- from test . support import SHORT_TIMEOUT , requires_subprocess
5
+ from sqlite3 . __main__ import main as cli
9
6
from test .support .os_helper import TESTFN , unlink
7
+ from test .support import captured_stdout , captured_stderr , captured_stdin
10
8
11
9
12
- @requires_subprocess ()
13
10
class CommandLineInterface (unittest .TestCase ):
14
11
15
12
def _do_test (self , * args , expect_success = True ):
16
- with subprocess .Popen (
17
- [sys .executable , "-Xutf8" , "-m" , "sqlite3" , * args ],
18
- encoding = "utf-8" ,
19
- bufsize = 0 ,
20
- stdout = subprocess .PIPE ,
21
- stderr = subprocess .PIPE ,
22
- ) as proc :
23
- proc .wait ()
24
- if expect_success == bool (proc .returncode ):
25
- self .fail ("" .join (proc .stderr ))
26
- stdout = proc .stdout .read ()
27
- stderr = proc .stderr .read ()
28
- if expect_success :
29
- self .assertEqual (stderr , "" )
30
- else :
31
- self .assertEqual (stdout , "" )
32
- return stdout , stderr
13
+ with (
14
+ captured_stdout () as out ,
15
+ captured_stderr () as err ,
16
+ self .assertRaises (SystemExit ) as cm
17
+ ):
18
+ cli (args )
19
+ return out .getvalue (), err .getvalue (), cm .exception .code
33
20
34
21
def expect_success (self , * args ):
35
- out , _ = self ._do_test (* args )
22
+ out , err , code = self ._do_test (* args )
23
+ self .assertEqual (code , 0 ,
24
+ "\n " .join ([f"Unexpected failure: { args = } " , out , err ]))
25
+ self .assertEqual (err , "" )
36
26
return out
37
27
38
28
def expect_failure (self , * args ):
39
- _ , err = self ._do_test (* args , expect_success = False )
29
+ out , err , code = self ._do_test (* args , expect_success = False )
30
+ self .assertNotEqual (code , 0 ,
31
+ "\n " .join ([f"Unexpected failure: { args = } " , out , err ]))
32
+ self .assertEqual (out , "" )
40
33
return err
41
34
42
35
def test_cli_help (self ):
@@ -45,7 +38,7 @@ def test_cli_help(self):
45
38
46
39
def test_cli_version (self ):
47
40
out = self .expect_success ("-v" )
48
- self .assertIn (sqlite .sqlite_version , out )
41
+ self .assertIn (sqlite3 .sqlite_version , out )
49
42
50
43
def test_cli_execute_sql (self ):
51
44
out = self .expect_success (":memory:" , "select 1" )
@@ -68,87 +61,68 @@ def test_cli_on_disk_db(self):
68
61
self .assertIn ("(0,)" , out )
69
62
70
63
71
- @requires_subprocess ()
72
64
class InteractiveSession (unittest .TestCase ):
73
- TIMEOUT = SHORT_TIMEOUT / 10.
74
65
MEMORY_DB_MSG = "Connected to a transient in-memory database"
75
66
PS1 = "sqlite> "
76
67
PS2 = "... "
77
68
78
- def start_cli (self , * args ):
79
- return subprocess .Popen (
80
- [sys .executable , "-Xutf8" , "-m" , "sqlite3" , * args ],
81
- encoding = "utf-8" ,
82
- bufsize = 0 ,
83
- stdin = subprocess .PIPE ,
84
- # Note: the banner is printed to stderr, the prompt to stdout.
85
- stdout = subprocess .PIPE ,
86
- stderr = subprocess .PIPE ,
87
- )
88
-
89
- def expect_success (self , proc ):
90
- proc .wait ()
91
- if proc .returncode :
92
- self .fail ("" .join (proc .stderr ))
69
+ def run_cli (self , * args , commands = ()):
70
+ with (
71
+ captured_stdin () as stdin ,
72
+ captured_stdout () as stdout ,
73
+ captured_stderr () as stderr ,
74
+ self .assertRaises (SystemExit ) as cm
75
+ ):
76
+ for cmd in commands :
77
+ stdin .write (cmd + "\n " )
78
+ stdin .seek (0 )
79
+ cli (args )
80
+
81
+ out = stdout .getvalue ()
82
+ err = stderr .getvalue ()
83
+ self .assertEqual (cm .exception .code , 0 ,
84
+ f"Unexpected failure: { args = } \n { out } \n { err } " )
85
+ return out , err
93
86
94
87
def test_interact (self ):
95
- with self .start_cli () as proc :
96
- out , err = proc .communicate (timeout = self .TIMEOUT )
97
- self .assertIn (self .MEMORY_DB_MSG , err )
98
- self .assertIn (self .PS1 , out )
99
- self .expect_success (proc )
88
+ out , err = self .run_cli ()
89
+ self .assertIn (self .MEMORY_DB_MSG , err )
90
+ self .assertIn (self .PS1 , out )
100
91
101
92
def test_interact_quit (self ):
102
- with self .start_cli () as proc :
103
- out , err = proc .communicate (input = ".quit" , timeout = self .TIMEOUT )
104
- self .assertIn (self .MEMORY_DB_MSG , err )
105
- self .assertIn (self .PS1 , out )
106
- self .expect_success (proc )
93
+ out , err = self .run_cli (commands = (".quit" ,))
94
+ self .assertIn (self .PS1 , out )
107
95
108
96
def test_interact_version (self ):
109
- with self .start_cli () as proc :
110
- out , err = proc .communicate (input = ".version" , timeout = self .TIMEOUT )
111
- self .assertIn (self .MEMORY_DB_MSG , err )
112
- self .assertIn (sqlite .sqlite_version , out )
113
- self .expect_success (proc )
97
+ out , err = self .run_cli (commands = (".version" ,))
98
+ self .assertIn (self .MEMORY_DB_MSG , err )
99
+ self .assertIn (sqlite3 .sqlite_version , out )
114
100
115
101
def test_interact_valid_sql (self ):
116
- with self .start_cli () as proc :
117
- out , err = proc .communicate (input = "select 1;" ,
118
- timeout = self .TIMEOUT )
119
- self .assertIn (self .MEMORY_DB_MSG , err )
120
- self .assertIn ("(1,)" , out )
121
- self .expect_success (proc )
102
+ out , err = self .run_cli (commands = ("SELECT 1;" ,))
103
+ self .assertIn (self .MEMORY_DB_MSG , err )
104
+ self .assertIn ("(1,)" , out )
122
105
123
106
def test_interact_valid_multiline_sql (self ):
124
- with self .start_cli () as proc :
125
- out , err = proc .communicate (input = "select 1\n ;" ,
126
- timeout = self .TIMEOUT )
127
- self .assertIn (self .MEMORY_DB_MSG , err )
128
- self .assertIn (self .PS2 , out )
129
- self .assertIn ("(1,)" , out )
130
- self .expect_success (proc )
107
+ out , err = self .run_cli (commands = ("SELECT 1\n ;" ,))
108
+ self .assertIn (self .MEMORY_DB_MSG , err )
109
+ self .assertIn (self .PS2 , out )
110
+ self .assertIn ("(1,)" , out )
131
111
132
112
def test_interact_invalid_sql (self ):
133
- with self .start_cli () as proc :
134
- out , err = proc .communicate (input = "sel;" , timeout = self .TIMEOUT )
135
- self .assertIn (self .MEMORY_DB_MSG , err )
136
- self .assertIn ("OperationalError (SQLITE_ERROR)" , err )
137
- self .expect_success (proc )
113
+ out , err = self .run_cli (commands = ("sel;" ,))
114
+ self .assertIn (self .MEMORY_DB_MSG , err )
115
+ self .assertIn ("OperationalError (SQLITE_ERROR)" , err )
138
116
139
117
def test_interact_on_disk_file (self ):
140
118
self .addCleanup (unlink , TESTFN )
141
- with self .start_cli (TESTFN ) as proc :
142
- out , err = proc .communicate (input = "create table t(t);" ,
143
- timeout = self .TIMEOUT )
144
- self .assertIn (TESTFN , err )
145
- self .assertIn (self .PS1 , out )
146
- self .expect_success (proc )
147
- with self .start_cli (TESTFN , "select count(t) from t" ) as proc :
148
- out = proc .stdout .read ()
149
- err = proc .stderr .read ()
150
- self .assertIn ("(0,)" , out )
151
- self .expect_success (proc )
119
+
120
+ out , err = self .run_cli (TESTFN , commands = ("CREATE TABLE t(t);" ,))
121
+ self .assertIn (TESTFN , err )
122
+ self .assertIn (self .PS1 , out )
123
+
124
+ out , _ = self .run_cli (TESTFN , commands = ("SELECT count(t) FROM t;" ,))
125
+ self .assertIn ("(0,)" , out )
152
126
153
127
154
128
if __name__ == "__main__" :
0 commit comments