11"""sqlite3 CLI tests."""
2-
3- import sqlite3 as sqlite
4- import subprocess
5- import sys
2+ import sqlite3
63import unittest
74
8- from test . support import SHORT_TIMEOUT , requires_subprocess
5+ from sqlite3 . __main__ import main as cli
96from test .support .os_helper import TESTFN , unlink
7+ from test .support import captured_stdout , captured_stderr , captured_stdin
108
119
12- @requires_subprocess ()
1310class CommandLineInterface (unittest .TestCase ):
1411
1512 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
3320
3421 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 , "" )
3626 return out
3727
3828 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 , "" )
4033 return err
4134
4235 def test_cli_help (self ):
@@ -45,7 +38,7 @@ def test_cli_help(self):
4538
4639 def test_cli_version (self ):
4740 out = self .expect_success ("-v" )
48- self .assertIn (sqlite .sqlite_version , out )
41+ self .assertIn (sqlite3 .sqlite_version , out )
4942
5043 def test_cli_execute_sql (self ):
5144 out = self .expect_success (":memory:" , "select 1" )
@@ -68,87 +61,68 @@ def test_cli_on_disk_db(self):
6861 self .assertIn ("(0,)" , out )
6962
7063
71- @requires_subprocess ()
7264class InteractiveSession (unittest .TestCase ):
73- TIMEOUT = SHORT_TIMEOUT / 10.
7465 MEMORY_DB_MSG = "Connected to a transient in-memory database"
7566 PS1 = "sqlite> "
7667 PS2 = "... "
7768
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
9386
9487 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 )
10091
10192 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 )
10795
10896 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 )
114100
115101 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 )
122105
123106 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 )
131111
132112 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 )
138116
139117 def test_interact_on_disk_file (self ):
140118 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 )
152126
153127
154128if __name__ == "__main__" :
0 commit comments