1"""
2Test script for the 'cmd' module
3Original by Michael Schneider
4"""
5
6
7import cmd
8import sys
9import unittest
10import io
11from test import support
12
13class samplecmdclass(cmd.Cmd):
14    """
15    Instance the sampleclass:
16    >>> mycmd = samplecmdclass()
17
18    Test for the function parseline():
19    >>> mycmd.parseline("")
20    (None, None, '')
21    >>> mycmd.parseline("?")
22    ('help', '', 'help ')
23    >>> mycmd.parseline("?help")
24    ('help', 'help', 'help help')
25    >>> mycmd.parseline("!")
26    ('shell', '', 'shell ')
27    >>> mycmd.parseline("!command")
28    ('shell', 'command', 'shell command')
29    >>> mycmd.parseline("func")
30    ('func', '', 'func')
31    >>> mycmd.parseline("func arg1")
32    ('func', 'arg1', 'func arg1')
33
34
35    Test for the function onecmd():
36    >>> mycmd.onecmd("")
37    >>> mycmd.onecmd("add 4 5")
38    9
39    >>> mycmd.onecmd("")
40    9
41    >>> mycmd.onecmd("test")
42    *** Unknown syntax: test
43
44    Test for the function emptyline():
45    >>> mycmd.emptyline()
46    *** Unknown syntax: test
47
48    Test for the function default():
49    >>> mycmd.default("default")
50    *** Unknown syntax: default
51
52    Test for the function completedefault():
53    >>> mycmd.completedefault()
54    This is the completedefault method
55    >>> mycmd.completenames("a")
56    ['add']
57
58    Test for the function completenames():
59    >>> mycmd.completenames("12")
60    []
61    >>> mycmd.completenames("help")
62    ['help']
63
64    Test for the function complete_help():
65    >>> mycmd.complete_help("a")
66    ['add']
67    >>> mycmd.complete_help("he")
68    ['help']
69    >>> mycmd.complete_help("12")
70    []
71    >>> sorted(mycmd.complete_help(""))
72    ['add', 'exit', 'help', 'shell']
73
74    Test for the function do_help():
75    >>> mycmd.do_help("testet")
76    *** No help on testet
77    >>> mycmd.do_help("add")
78    help text for add
79    >>> mycmd.onecmd("help add")
80    help text for add
81    >>> mycmd.do_help("")
82    <BLANKLINE>
83    Documented commands (type help <topic>):
84    ========================================
85    add  help
86    <BLANKLINE>
87    Undocumented commands:
88    ======================
89    exit  shell
90    <BLANKLINE>
91
92    Test for the function print_topics():
93    >>> mycmd.print_topics("header", ["command1", "command2"], 2 ,10)
94    header
95    ======
96    command1
97    command2
98    <BLANKLINE>
99
100    Test for the function columnize():
101    >>> mycmd.columnize([str(i) for i in range(20)])
102    0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19
103    >>> mycmd.columnize([str(i) for i in range(20)], 10)
104    0  7   14
105    1  8   15
106    2  9   16
107    3  10  17
108    4  11  18
109    5  12  19
110    6  13
111
112    This is an interactive test, put some commands in the cmdqueue attribute
113    and let it execute
114    This test includes the preloop(), postloop(), default(), emptyline(),
115    parseline(), do_help() functions
116    >>> mycmd.use_rawinput=0
117    >>> mycmd.cmdqueue=["", "add", "add 4 5", "help", "help add","exit"]
118    >>> mycmd.cmdloop()
119    Hello from preloop
120    help text for add
121    *** invalid number of arguments
122    9
123    <BLANKLINE>
124    Documented commands (type help <topic>):
125    ========================================
126    add  help
127    <BLANKLINE>
128    Undocumented commands:
129    ======================
130    exit  shell
131    <BLANKLINE>
132    help text for add
133    Hello from postloop
134    """
135
136    def preloop(self):
137        print("Hello from preloop")
138
139    def postloop(self):
140        print("Hello from postloop")
141
142    def completedefault(self, *ignored):
143        print("This is the completedefault method")
144
145    def complete_command(self):
146        print("complete command")
147
148    def do_shell(self, s):
149        pass
150
151    def do_add(self, s):
152        l = s.split()
153        if len(l) != 2:
154            print("*** invalid number of arguments")
155            return
156        try:
157            l = [int(i) for i in l]
158        except ValueError:
159            print("*** arguments should be numbers")
160            return
161        print(l[0]+l[1])
162
163    def help_add(self):
164        print("help text for add")
165        return
166
167    def do_exit(self, arg):
168        return True
169
170
171class TestAlternateInput(unittest.TestCase):
172
173    class simplecmd(cmd.Cmd):
174
175        def do_print(self, args):
176            print(args, file=self.stdout)
177
178        def do_EOF(self, args):
179            return True
180
181
182    class simplecmd2(simplecmd):
183
184        def do_EOF(self, args):
185            print('*** Unknown syntax: EOF', file=self.stdout)
186            return True
187
188
189    def test_file_with_missing_final_nl(self):
190        input = io.StringIO("print test\nprint test2")
191        output = io.StringIO()
192        cmd = self.simplecmd(stdin=input, stdout=output)
193        cmd.use_rawinput = False
194        cmd.cmdloop()
195        self.assertMultiLineEqual(output.getvalue(),
196            ("(Cmd) test\n"
197             "(Cmd) test2\n"
198             "(Cmd) "))
199
200
201    def test_input_reset_at_EOF(self):
202        input = io.StringIO("print test\nprint test2")
203        output = io.StringIO()
204        cmd = self.simplecmd2(stdin=input, stdout=output)
205        cmd.use_rawinput = False
206        cmd.cmdloop()
207        self.assertMultiLineEqual(output.getvalue(),
208            ("(Cmd) test\n"
209             "(Cmd) test2\n"
210             "(Cmd) *** Unknown syntax: EOF\n"))
211        input = io.StringIO("print \n\n")
212        output = io.StringIO()
213        cmd.stdin = input
214        cmd.stdout = output
215        cmd.cmdloop()
216        self.assertMultiLineEqual(output.getvalue(),
217            ("(Cmd) \n"
218             "(Cmd) \n"
219             "(Cmd) *** Unknown syntax: EOF\n"))
220
221
222def test_main(verbose=None):
223    from test import test_cmd
224    support.run_doctest(test_cmd, verbose)
225    support.run_unittest(TestAlternateInput)
226
227def test_coverage(coverdir):
228    trace = support.import_module('trace')
229    tracer=trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,],
230                        trace=0, count=1)
231    tracer.run('import importlib; importlib.reload(cmd); test_main()')
232    r=tracer.results()
233    print("Writing coverage results...")
234    r.write_results(show_missing=True, summary=True, coverdir=coverdir)
235
236if __name__ == "__main__":
237    if "-c" in sys.argv:
238        test_coverage('/tmp/cmd.cover')
239    elif "-i" in sys.argv:
240        samplecmdclass().cmdloop()
241    else:
242        test_main()
243