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