~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_script.py

  • Committer: Tarmac
  • Author(s): Florent Gallaire
  • Date: 2017-03-17 12:23:47 UTC
  • mfrom: (6621.1.1 fix-gmtime-lite)
  • Revision ID: tarmac-20170317122347-2nnf3cicpgrhux3h
Fix for Windows and 32-bit platforms buggy gmtime(). [r=vila,richard-wilbur]

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2009, 2010, 2011, 2016 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
from bzrlib import (
 
19
    commands,
 
20
    osutils,
 
21
    tests,
 
22
    trace,
 
23
    ui,
 
24
    )
 
25
from bzrlib.tests import script
 
26
 
 
27
 
 
28
class TestSyntax(tests.TestCase):
 
29
 
 
30
    def test_comment_is_ignored(self):
 
31
        self.assertEqual([], script._script_to_commands('#comment\n'))
 
32
 
 
33
    def test_comment_multiple_lines(self):
 
34
        self.assertEqual([
 
35
            (['bar'], None, None, None),
 
36
            ],
 
37
            script._script_to_commands("""
 
38
            # this comment is ignored
 
39
            # so is this
 
40
            # no we run bar
 
41
            $ bar
 
42
            """))
 
43
 
 
44
    def test_trim_blank_lines(self):
 
45
        """Blank lines are respected, but trimmed at the start and end.
 
46
 
 
47
        Python triple-quoted syntax is going to give stubby/empty blank lines 
 
48
        right at the start and the end.  These are cut off so that callers don't 
 
49
        need special syntax to avoid them.
 
50
 
 
51
        However we do want to be able to match commands that emit blank lines.
 
52
        """
 
53
        self.assertEqual([
 
54
            (['bar'], None, '\n', None),
 
55
            ],
 
56
            script._script_to_commands("""
 
57
            $bar
 
58
 
 
59
            """))
 
60
 
 
61
    def test_simple_command(self):
 
62
        self.assertEqual([(['cd', 'trunk'], None, None, None)],
 
63
                           script._script_to_commands('$ cd trunk'))
 
64
 
 
65
    def test_command_with_single_quoted_param(self):
 
66
        story = """$ bzr commit -m 'two words'"""
 
67
        self.assertEqual([(['bzr', 'commit', '-m', "'two words'"],
 
68
                            None, None, None)],
 
69
                           script._script_to_commands(story))
 
70
 
 
71
    def test_command_with_double_quoted_param(self):
 
72
        story = """$ bzr commit -m "two words" """
 
73
        self.assertEqual([(['bzr', 'commit', '-m', '"two words"'],
 
74
                            None, None, None)],
 
75
                           script._script_to_commands(story))
 
76
 
 
77
    def test_command_with_input(self):
 
78
        self.assertEqual(
 
79
            [(['cat', '>file'], 'content\n', None, None)],
 
80
            script._script_to_commands('$ cat >file\n<content\n'))
 
81
 
 
82
    def test_indented(self):
 
83
        # scripts are commonly given indented within the test source code, and
 
84
        # common indentation is stripped off
 
85
        story = """
 
86
            $ bzr add
 
87
            adding file
 
88
            adding file2
 
89
            """
 
90
        self.assertEqual([(['bzr', 'add'], None,
 
91
                            'adding file\nadding file2\n', None)],
 
92
                          script._script_to_commands(story))
 
93
 
 
94
    def test_command_with_output(self):
 
95
        story = """
 
96
$ bzr add
 
97
adding file
 
98
adding file2
 
99
"""
 
100
        self.assertEqual([(['bzr', 'add'], None,
 
101
                            'adding file\nadding file2\n', None)],
 
102
                          script._script_to_commands(story))
 
103
 
 
104
    def test_command_with_error(self):
 
105
        story = """
 
106
$ bzr branch foo
 
107
2>bzr: ERROR: Not a branch: "foo"
 
108
"""
 
109
        self.assertEqual([(['bzr', 'branch', 'foo'],
 
110
                            None, None, 'bzr: ERROR: Not a branch: "foo"\n')],
 
111
                          script._script_to_commands(story))
 
112
 
 
113
    def test_input_without_command(self):
 
114
        self.assertRaises(SyntaxError, script._script_to_commands, '<input')
 
115
 
 
116
    def test_output_without_command(self):
 
117
        self.assertRaises(SyntaxError, script._script_to_commands, '>input')
 
118
 
 
119
    def test_command_with_backquotes(self):
 
120
        story = """
 
121
$ foo = `bzr file-id toto`
 
122
"""
 
123
        self.assertEqual([(['foo', '=', '`bzr file-id toto`'],
 
124
                            None, None, None)],
 
125
                          script._script_to_commands(story))
 
126
 
 
127
 
 
128
class TestRedirections(tests.TestCase):
 
129
 
 
130
    def _check(self, in_name, out_name, out_mode, remaining, args):
 
131
        self.assertEqual(script._scan_redirection_options(args),
 
132
                         (in_name, out_name, out_mode, remaining))
 
133
 
 
134
    def test_no_redirection(self):
 
135
        self._check(None, None, None, [], [])
 
136
        self._check(None, None, None, ['foo', 'bar'], ['foo', 'bar'])
 
137
 
 
138
    def test_input_redirection(self):
 
139
        self._check('foo', None, None, [], ['<foo'])
 
140
        self._check('foo', None, None, ['bar'], ['bar', '<foo'])
 
141
        self._check('foo', None, None, ['bar'], ['bar', '<', 'foo'])
 
142
        self._check('foo', None, None, ['bar'], ['<foo', 'bar'])
 
143
        self._check('foo', None, None, ['bar', 'baz'], ['bar', '<foo', 'baz'])
 
144
 
 
145
    def test_output_redirection(self):
 
146
        self._check(None, 'foo', 'wb+', [], ['>foo'])
 
147
        self._check(None, 'foo', 'wb+', ['bar'], ['bar', '>foo'])
 
148
        self._check(None, 'foo', 'wb+', ['bar'], ['bar', '>', 'foo'])
 
149
        self._check(None, 'foo', 'ab+', [], ['>>foo'])
 
150
        self._check(None, 'foo', 'ab+', ['bar'], ['bar', '>>foo'])
 
151
        self._check(None, 'foo', 'ab+', ['bar'], ['bar', '>>', 'foo'])
 
152
 
 
153
    def test_redirection_syntax_errors(self):
 
154
        self._check('', None, None, [], ['<'])
 
155
        self._check(None, '', 'wb+', [], ['>'])
 
156
        self._check(None, '', 'ab+', [], ['>>'])
 
157
        self._check('>', '', 'ab+', [], ['<', '>', '>>'])
 
158
 
 
159
 
 
160
 
 
161
class TestExecution(script.TestCaseWithTransportAndScript):
 
162
 
 
163
    def test_unknown_command(self):
 
164
        """A clear error is reported for commands that aren't recognised
 
165
 
 
166
        Testing the attributes of the SyntaxError instance is equivalent to
 
167
        using traceback.format_exception_only and comparing with:
 
168
          File "<string>", line 1
 
169
            foo --frob
 
170
            ^
 
171
        SyntaxError: Command not found "foo"
 
172
        """
 
173
        e = self.assertRaises(SyntaxError, self.run_script, "$ foo --frob")
 
174
        self.assertContainsRe(e.msg, "not found.*foo")
 
175
        self.assertEqual(e.text, "foo --frob")
 
176
 
 
177
    def test_blank_output_mismatches_output(self):
 
178
        """If you give output, the output must actually be blank.
 
179
        
 
180
        See <https://bugs.launchpad.net/bzr/+bug/637830>: previously blank
 
181
        output was a wildcard.  Now you must say ... if you want that.
 
182
        """
 
183
        self.assertRaises(AssertionError,
 
184
            self.run_script,
 
185
            """
 
186
            $ echo foo
 
187
            """)
 
188
 
 
189
    def test_null_output_matches_option(self):
 
190
        """If you want null output to be a wild card, you can pass 
 
191
        null_output_matches_anything to run_script"""
 
192
        self.run_script(
 
193
            """
 
194
            $ echo foo
 
195
            """, null_output_matches_anything=True)
 
196
 
 
197
    def test_ellipsis_everything(self):
 
198
        """A simple ellipsis matches everything."""
 
199
        self.run_script("""
 
200
        $ echo foo
 
201
        ...
 
202
        """)
 
203
 
 
204
    def test_ellipsis_matches_empty(self):
 
205
        self.run_script("""
 
206
        $ cd .
 
207
        ...
 
208
        """)
 
209
 
 
210
    def test_stops_on_unexpected_output(self):
 
211
        story = """
 
212
$ mkdir dir
 
213
$ cd dir
 
214
The cd command ouputs nothing
 
215
"""
 
216
        self.assertRaises(AssertionError, self.run_script, story)
 
217
 
 
218
    def test_stops_on_unexpected_error(self):
 
219
        story = """
 
220
$ cat
 
221
<Hello
 
222
$ bzr not-a-command
 
223
"""
 
224
        self.assertRaises(AssertionError, self.run_script, story)
 
225
 
 
226
    def test_continue_on_expected_error(self):
 
227
        story = """
 
228
$ bzr not-a-command
 
229
2>..."not-a-command"
 
230
"""
 
231
        self.run_script(story)
 
232
 
 
233
    def test_continue_on_error_output(self):
 
234
        # The status matters, not the output
 
235
        story = """
 
236
$ bzr init
 
237
...
 
238
$ cat >file
 
239
<Hello
 
240
$ bzr add file
 
241
...
 
242
$ bzr commit -m 'adding file'
 
243
2>...
 
244
"""
 
245
        self.run_script(story)
 
246
 
 
247
    def test_ellipsis_output(self):
 
248
        story = """
 
249
$ cat
 
250
<first line
 
251
<second line
 
252
<last line
 
253
first line
 
254
...
 
255
last line
 
256
"""
 
257
        self.run_script(story)
 
258
        story = """
 
259
$ bzr not-a-command
 
260
2>..."not-a-command"
 
261
"""
 
262
        self.run_script(story)
 
263
 
 
264
        story = """
 
265
$ bzr branch not-a-branch
 
266
2>bzr: ERROR: Not a branch...not-a-branch/".
 
267
"""
 
268
        self.run_script(story)
 
269
 
 
270
 
 
271
class TestArgumentProcessing(script.TestCaseWithTransportAndScript):
 
272
 
 
273
    def test_globing(self):
 
274
        self.run_script("""
 
275
$ echo cat >cat
 
276
$ echo dog >dog
 
277
$ cat *
 
278
cat
 
279
dog
 
280
""")
 
281
 
 
282
    def test_quoted_globbing(self):
 
283
        self.run_script("""
 
284
$ echo cat >cat
 
285
$ cat '*'
 
286
2>*: No such file or directory
 
287
""")
 
288
 
 
289
    def test_quotes_removal(self):
 
290
        self.run_script("""
 
291
$ echo 'cat' "dog" '"chicken"' "'dragon'"
 
292
cat dog "chicken" 'dragon'
 
293
""")
 
294
 
 
295
    def test_verbosity_isolated(self):
 
296
        """Global verbosity is isolated from commands run in scripts.
 
297
        """
 
298
        # see also 656694; we should get rid of global verbosity
 
299
        self.run_script("""
 
300
        $ bzr init --quiet a
 
301
        """)
 
302
        self.assertEqual(trace.is_quiet(), False)
 
303
 
 
304
 
 
305
class TestCat(script.TestCaseWithTransportAndScript):
 
306
 
 
307
    def test_cat_usage(self):
 
308
        self.assertRaises(SyntaxError, self.run_script, 'cat foo <bar')
 
309
 
 
310
    def test_cat_input_to_output(self):
 
311
        retcode, out, err = self.run_command(['cat'],
 
312
                                             'content\n', 'content\n', None)
 
313
        self.assertEqual('content\n', out)
 
314
        self.assertEqual(None, err)
 
315
 
 
316
    def test_cat_file_to_output(self):
 
317
        self.build_tree_contents([('file', 'content\n')])
 
318
        retcode, out, err = self.run_command(['cat', 'file'],
 
319
                                             None, 'content\n', None)
 
320
        self.assertEqual('content\n', out)
 
321
        self.assertEqual(None, err)
 
322
 
 
323
    def test_cat_input_to_file(self):
 
324
        retcode, out, err = self.run_command(['cat', '>file'],
 
325
                                             'content\n', None, None)
 
326
        self.assertFileEqual('content\n', 'file')
 
327
        self.assertEqual(None, out)
 
328
        self.assertEqual(None, err)
 
329
        retcode, out, err = self.run_command(['cat', '>>file'],
 
330
                                             'more\n', None, None)
 
331
        self.assertFileEqual('content\nmore\n', 'file')
 
332
        self.assertEqual(None, out)
 
333
        self.assertEqual(None, err)
 
334
 
 
335
    def test_cat_file_to_file(self):
 
336
        self.build_tree_contents([('file', 'content\n')])
 
337
        retcode, out, err = self.run_command(['cat', 'file', '>file2'],
 
338
                                             None, None, None)
 
339
        self.assertFileEqual('content\n', 'file2')
 
340
 
 
341
    def test_cat_files_to_file(self):
 
342
        self.build_tree_contents([('cat', 'cat\n')])
 
343
        self.build_tree_contents([('dog', 'dog\n')])
 
344
        retcode, out, err = self.run_command(['cat', 'cat', 'dog', '>file'],
 
345
                                             None, None, None)
 
346
        self.assertFileEqual('cat\ndog\n', 'file')
 
347
 
 
348
    def test_cat_bogus_input_file(self):
 
349
        self.run_script("""
 
350
$ cat <file
 
351
2>file: No such file or directory
 
352
""")
 
353
 
 
354
    def test_cat_bogus_output_file(self):
 
355
        self.run_script("""
 
356
$ cat >
 
357
2>: No such file or directory
 
358
""")
 
359
 
 
360
    def test_echo_bogus_output_file(self):
 
361
        # We need a backing file sysytem for that test so it can't be in
 
362
        # TestEcho
 
363
        self.run_script("""
 
364
$ echo >
 
365
2>: No such file or directory
 
366
""")
 
367
 
 
368
 
 
369
class TestMkdir(script.TestCaseWithTransportAndScript):
 
370
 
 
371
    def test_mkdir_usage(self):
 
372
        self.assertRaises(SyntaxError, self.run_script, '$ mkdir')
 
373
        self.assertRaises(SyntaxError, self.run_script, '$ mkdir foo bar')
 
374
 
 
375
    def test_mkdir_jailed(self):
 
376
        self.assertRaises(ValueError, self.run_script, '$ mkdir /out-of-jail')
 
377
        self.assertRaises(ValueError, self.run_script, '$ mkdir ../out-of-jail')
 
378
 
 
379
    def test_mkdir_in_jail(self):
 
380
        self.run_script("""
 
381
$ mkdir dir
 
382
$ cd dir
 
383
$ mkdir ../dir2
 
384
$ cd ..
 
385
""")
 
386
        self.assertPathExists('dir')
 
387
        self.assertPathExists('dir2')
 
388
 
 
389
 
 
390
class TestCd(script.TestCaseWithTransportAndScript):
 
391
 
 
392
    def test_cd_usage(self):
 
393
        self.assertRaises(SyntaxError, self.run_script, '$ cd foo bar')
 
394
 
 
395
    def test_cd_out_of_jail(self):
 
396
        self.assertRaises(ValueError, self.run_script, '$ cd /out-of-jail')
 
397
        self.assertRaises(ValueError, self.run_script, '$ cd ..')
 
398
 
 
399
    def test_cd_dir_and_back_home(self):
 
400
        self.assertEqual(self.test_dir, osutils.getcwd())
 
401
        self.run_script("""
 
402
$ mkdir dir
 
403
$ cd dir
 
404
""")
 
405
        self.assertEqual(osutils.pathjoin(self.test_dir, 'dir'),
 
406
                          osutils.getcwd())
 
407
 
 
408
        self.run_script('$ cd')
 
409
        self.assertEqual(self.test_dir, osutils.getcwd())
 
410
 
 
411
 
 
412
class TestBzr(script.TestCaseWithTransportAndScript):
 
413
 
 
414
    def test_bzr_smoke(self):
 
415
        self.run_script("""
 
416
            $ bzr init branch
 
417
            Created a standalone tree (format: ...)
 
418
            """)
 
419
        self.assertPathExists('branch')
 
420
 
 
421
 
 
422
class TestEcho(script.TestCaseWithMemoryTransportAndScript):
 
423
 
 
424
    def test_echo_usage(self):
 
425
        story = """
 
426
$ echo foo
 
427
<bar
 
428
"""
 
429
        self.assertRaises(SyntaxError, self.run_script, story)
 
430
 
 
431
    def test_echo_input(self):
 
432
        self.assertRaises(SyntaxError, self.run_script, """
 
433
            $ echo <foo
 
434
            """)
 
435
 
 
436
    def test_echo_to_output(self):
 
437
        retcode, out, err = self.run_command(['echo'], None, '\n', None)
 
438
        self.assertEqual('\n', out)
 
439
        self.assertEqual(None, err)
 
440
 
 
441
    def test_echo_some_to_output(self):
 
442
        retcode, out, err = self.run_command(['echo', 'hello'],
 
443
                                             None, 'hello\n', None)
 
444
        self.assertEqual('hello\n', out)
 
445
        self.assertEqual(None, err)
 
446
 
 
447
    def test_echo_more_output(self):
 
448
        retcode, out, err = self.run_command(
 
449
            ['echo', 'hello', 'happy', 'world'],
 
450
            None, 'hello happy world\n', None)
 
451
        self.assertEqual('hello happy world\n', out)
 
452
        self.assertEqual(None, err)
 
453
 
 
454
    def test_echo_appended(self):
 
455
        retcode, out, err = self.run_command(['echo', 'hello', '>file'],
 
456
                                             None, None, None)
 
457
        self.assertEqual(None, out)
 
458
        self.assertEqual(None, err)
 
459
        self.assertFileEqual('hello\n', 'file')
 
460
        retcode, out, err = self.run_command(['echo', 'happy', '>>file'],
 
461
                                             None, None, None)
 
462
        self.assertEqual(None, out)
 
463
        self.assertEqual(None, err)
 
464
        self.assertFileEqual('hello\nhappy\n', 'file')
 
465
 
 
466
    def test_empty_line_in_output_is_respected(self):
 
467
        self.run_script("""
 
468
            $ echo
 
469
 
 
470
            $ echo bar
 
471
            bar
 
472
            """)
 
473
 
 
474
 
 
475
class TestRm(script.TestCaseWithTransportAndScript):
 
476
 
 
477
    def test_rm_usage(self):
 
478
        self.assertRaises(SyntaxError, self.run_script, '$ rm')
 
479
        self.assertRaises(SyntaxError, self.run_script, '$ rm -ff foo')
 
480
 
 
481
    def test_rm_file(self):
 
482
        self.run_script('$ echo content >file')
 
483
        self.assertPathExists('file')
 
484
        self.run_script('$ rm file')
 
485
        self.assertPathDoesNotExist('file')
 
486
 
 
487
    def test_rm_file_force(self):
 
488
        self.assertPathDoesNotExist('file')
 
489
        self.run_script('$ rm -f file')
 
490
        self.assertPathDoesNotExist('file')
 
491
 
 
492
    def test_rm_files(self):
 
493
        self.run_script("""
 
494
$ echo content >file
 
495
$ echo content >file2
 
496
""")
 
497
        self.assertPathExists('file2')
 
498
        self.run_script('$ rm file file2')
 
499
        self.assertPathDoesNotExist('file2')
 
500
 
 
501
    def test_rm_dir(self):
 
502
        self.run_script('$ mkdir dir')
 
503
        self.assertPathExists('dir')
 
504
        self.run_script("""
 
505
$ rm dir
 
506
2>rm: cannot remove 'dir': Is a directory
 
507
""")
 
508
        self.assertPathExists('dir')
 
509
 
 
510
    def test_rm_dir_recursive(self):
 
511
        self.run_script("""
 
512
$ mkdir dir
 
513
$ rm -r dir
 
514
""")
 
515
        self.assertPathDoesNotExist('dir')
 
516
 
 
517
 
 
518
class TestMv(script.TestCaseWithTransportAndScript):
 
519
 
 
520
    def test_usage(self):
 
521
        self.assertRaises(SyntaxError, self.run_script, '$ mv')
 
522
        self.assertRaises(SyntaxError, self.run_script, '$ mv f')
 
523
        self.assertRaises(SyntaxError, self.run_script, '$ mv f1 f2 f3')
 
524
 
 
525
    def test_move_file(self):
 
526
        self.run_script('$ echo content >file')
 
527
        self.assertPathExists('file')
 
528
        self.run_script('$ mv file new_name')
 
529
        self.assertPathDoesNotExist('file')
 
530
        self.assertPathExists('new_name')
 
531
 
 
532
    def test_move_unknown_file(self):
 
533
        self.assertRaises(AssertionError,
 
534
                          self.run_script, '$ mv unknown does-not-exist')
 
535
 
 
536
    def test_move_dir(self):
 
537
        self.run_script("""
 
538
$ mkdir dir
 
539
$ echo content >dir/file
 
540
""")
 
541
        self.run_script('$ mv dir new_name')
 
542
        self.assertPathDoesNotExist('dir')
 
543
        self.assertPathExists('new_name')
 
544
        self.assertPathExists('new_name/file')
 
545
 
 
546
    def test_move_file_into_dir(self):
 
547
        self.run_script("""
 
548
$ mkdir dir
 
549
$ echo content > file
 
550
""")
 
551
        self.run_script('$ mv file dir')
 
552
        self.assertPathExists('dir')
 
553
        self.assertPathDoesNotExist('file')
 
554
        self.assertPathExists('dir/file')
 
555
 
 
556
 
 
557
class cmd_test_confirm(commands.Command):
 
558
 
 
559
    def run(self):
 
560
        if ui.ui_factory.get_boolean(
 
561
            u'Really do it',
 
562
            # 'bzrlib.tests.test_script.confirm',
 
563
            # {}
 
564
            ):
 
565
            self.outf.write('Do it!\n')
 
566
        else:
 
567
            print 'ok, no'
 
568
 
 
569
 
 
570
class TestUserInteraction(script.TestCaseWithMemoryTransportAndScript):
 
571
 
 
572
    def test_confirm_action(self):
 
573
        """You can write tests that demonstrate user confirmation.
 
574
        
 
575
        Specifically, ScriptRunner does't care if the output line for the
 
576
        prompt isn't terminated by a newline from the program; it's implicitly
 
577
        terminated by the input.
 
578
        """
 
579
        commands.builtin_command_registry.register(cmd_test_confirm)
 
580
        self.addCleanup(commands.builtin_command_registry.remove, 'test-confirm')
 
581
        self.run_script("""
 
582
            $ bzr test-confirm
 
583
            2>Really do it? ([y]es, [n]o): yes
 
584
            <y
 
585
            Do it!
 
586
            $ bzr test-confirm
 
587
            2>Really do it? ([y]es, [n]o): no
 
588
            <n
 
589
            ok, no
 
590
            """)
 
591
 
 
592
class TestShelve(script.TestCaseWithTransportAndScript):
 
593
 
 
594
    def setUp(self):
 
595
        super(TestShelve, self).setUp()
 
596
        self.run_script("""
 
597
            $ bzr init test
 
598
            Created a standalone tree (format: 2a)
 
599
            $ cd test
 
600
            $ echo foo > file
 
601
            $ bzr add
 
602
            adding file
 
603
            $ bzr commit -m 'file added'
 
604
            2>Committing to:...test/
 
605
            2>added file
 
606
            2>Committed revision 1.
 
607
            $ echo bar > file
 
608
            """)
 
609
 
 
610
    def test_shelve(self):
 
611
        self.run_script("""
 
612
            $ bzr shelve -m 'shelve bar'
 
613
            2>Shelve? ([y]es, [N]o, [f]inish, [q]uit): yes
 
614
            <y
 
615
            2>Selected changes:
 
616
            2> M  file
 
617
            2>Shelve 1 change(s)? ([y]es, [N]o, [f]inish, [q]uit): yes
 
618
            <y
 
619
            2>Changes shelved with id "1".
 
620
            """,
 
621
                        null_output_matches_anything=True)
 
622
        self.run_script("""
 
623
            $ bzr shelve --list
 
624
              1: shelve bar
 
625
            """)
 
626
 
 
627
    def test_dont_shelve(self):
 
628
        # We intentionally provide no input here to test EOF
 
629
        self.run_script("""
 
630
            $ bzr shelve -m 'shelve bar'
 
631
            2>Shelve? ([y]es, [N]o, [f]inish, [q]uit): 
 
632
            2>No changes to shelve.
 
633
            """,
 
634
                        null_output_matches_anything=True)
 
635
        self.run_script("""
 
636
            $ bzr st
 
637
            modified:
 
638
              file
 
639
            """)