~ubuntu-branches/ubuntu/vivid/bash-completion/vivid-proposed

« back to all changes in this revision

Viewing changes to test/lib/library.exp

  • Committer: Package Import Robot
  • Author(s): David Paleino
  • Date: 2011-02-06 22:00:58 UTC
  • mfrom: (1.1.4)
  • mto: (5.1.9 sid)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20110206220058-zfh1gyor3vp1goqc
Tags: 1:1.3-1
* New upstream release
  - Fixed "service" completion, thanks to John Hedges (Closes: #586210)
  - Fixed typo in openssl completion (Closes: #609552)
  - Added ip completion (Closes: #600617)
  - Added _tilde(), fix ~username completion (Closes: #587095)
  - Add *.webm to mplayer file completions (Closes: #588079).
* debian/watch: fix to handle .tar.bz2 files
* Bump Standards-Version to 3.9.1, no changes needed
* Install upstream CHANGES file
* Update copyright years in debian/copyright
* debian/rules: reflect new source layout

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
    # Source `init.tcl' again to restore the `unknown' procedure
2
 
    # NOTE: DejaGnu has an old `unknown' procedure which unfortunately disables
3
 
    #       tcl auto-loading.
 
1
# Source `init.tcl' again to restore the `unknown' procedure
 
2
# NOTE: DejaGnu has an old `unknown' procedure which unfortunately disables
 
3
#       tcl auto-loading.
4
4
source [file join [info library] init.tcl]
 
5
package require cmdline
5
6
package require textutil::string
6
7
 
7
8
 
22
23
    if {[string length $aCmd] != 0} {
23
24
        send "$aCmd\r"
24
25
        expect -ex "$aCmd\r\n"
25
 
    }; # if
 
26
    }
26
27
    if {[string length $title] == 0} {set title $aCmd}
27
28
    expect -ex $prompt
28
29
    set results $expect_out(buffer);  # Catch output
33
34
        ]
34
35
    ]
35
36
    if {$out == -1 && [string length $results] > 0} {
36
 
        if {[info exists multipass_name]} {
37
 
            fail "ERROR Unexpected output from bash command \"$title\""
38
 
        }; # if
39
 
        send_user "ERROR Unexpected output from bash command \"$title\":\n$results"
40
 
    }; # if
 
37
        fail "ERROR Unexpected output from bash command \"$title\""
 
38
    }
41
39
 
42
40
    set cmd "echo $?"
43
41
    send "$cmd\r"
44
42
    expect {
45
43
        -ex "$cmd\r\n0\r\n$prompt" {}
46
 
        $prompt {
47
 
            if {[info exists multipass_name]} {
48
 
                fail "ERROR executing bash command \"$title\""
49
 
            }; # if
50
 
            send_user "ERROR executing bash command \"$title\""
51
 
        }
52
 
    }; # expect
53
 
}; # assert_bash_exec()
 
44
        $prompt {fail "ERROR executing bash command \"$title\""}
 
45
    }
 
46
}
54
47
 
55
48
 
56
49
# Test `type ...' in bash
64
57
    expect {
65
58
        -ex 0 { set result true }
66
59
        -ex 1 { set result false; unsupported "$test" }
67
 
    }; # expect
 
60
    }
68
61
    expect "/@"
69
62
    return $result
70
 
}; # assert_bash_type()
71
 
 
72
 
 
73
 
# Make sure the expected list is returned by executing the specified command.
74
 
# @param list $expected
75
 
# @param string $cmd  Command given to generate items
76
 
# @param string $test  (optional) Test title.  Default is "$cmd<TAB> should show completions"
77
 
# @param string $prompt  (optional) Bash prompt.  Default is "/@"
78
 
# @param integer $size  (optional) Chunk size.  Default is 20.
79
 
# @result boolean  True if successful, False if not
80
 
proc assert_bash_list {expected cmd {test ""} {prompt /@} {size 20}} {
 
63
}
 
64
 
 
65
 
 
66
# Make sure the expected list matches the real list, as returned by executing
 
67
# the specified bash command.
 
68
# Specify `-sort' if the real list is sorted.
 
69
# @param list $expected  Expected list items
 
70
# @param string $cmd  Bash command to execute in order to generate real list
 
71
#                     items
 
72
# @param string $test  Test title.  Becomes "$cmd should show expected output"
 
73
#                      if empty string.
 
74
# @param list $args  Options:
 
75
#                    -sort           Compare list sorted.  Default is unsorted
 
76
#                    -prompt         Bash prompt.  Default is `/@'
 
77
#                    -chunk-size N   Compare list N items at a time.  Default 
 
78
#                                    is 20.
 
79
proc assert_bash_list {expected cmd test {args {}}} {
 
80
    array set arg [::cmdline::getoptions args {
 
81
        {sort                "compare list sorted"}
 
82
        {prompt.arg     /@   "bash prompt"}
 
83
        {chunk-size.arg 20   "compare N list items at a time"}
 
84
    }]
 
85
    set prompt $arg(prompt)
81
86
    if {$test == ""} {set test "$cmd should show expected output"}
82
87
    if {[llength $expected] == 0} {
83
88
        assert_no_output $cmd $test $prompt
84
89
    } else {
85
90
        send "$cmd\r"
86
91
        expect -ex "$cmd\r\n"
87
 
 
88
 
        if {[match_items $expected $test $prompt $size]} {
89
 
            expect {
90
 
                -re $prompt { pass "$test" }
91
 
                -re eof { unresolved "eof" }
92
 
            }
 
92
        if {$arg(sort)} {set bash_sort "-bash-sort"} {set bash_sort ""}
 
93
        if {[
 
94
            eval match_items \$expected $bash_sort -chunk-size \
 
95
                \$arg(chunk-size) -end-newline -end-prompt \
 
96
                -prompt \$prompt
 
97
        ]} {
 
98
            pass "$test"
93
99
        } else {
94
100
            fail "$test"
95
101
        }
97
103
}
98
104
 
99
105
 
100
 
proc assert_bash_list_dir {expected cmd dir {test ""} {prompt /@} {size 20}} {
101
 
    set prompt "/$dir/@"
 
106
# Make sure the expected list matches the real list, as returned by executing
 
107
# the specified bash command within the specified directory.
 
108
# Specify `-sort' if the real list is sorted.
 
109
# @param list $expected  Expected list items
 
110
# @param string $cmd  Bash command to generate real list items
 
111
# @param string $dir  Directory to execute $cmd within
 
112
# @param string $test  Test title.  Becomes "$cmd should show expected output"
 
113
#                      if empty string.
 
114
# @param list $args  Options:
 
115
#                    -sort           Compare list sorted.  Default is unsorted
 
116
#                    -prompt         Bash prompt.  Default is `/@'
 
117
#                    -chunk-size N   Compare list N items at a time.  Default 
 
118
#                                    is 20.
 
119
proc assert_bash_list_dir {expected cmd dir test {args {}}} {
 
120
    array set arg [::cmdline::getoptions args {
 
121
        {sort                 "compare list sorted"}
 
122
        {prompt.arg     "/@"  "bash prompt"}
 
123
        {chunk-size.arg 20    "compare N list items at a time"}
 
124
    }]
 
125
    set prompt $arg(prompt)
 
126
    if {$arg(sort)} {set arg_sort "-sort"} else {set arg_sort ""}
102
127
    assert_bash_exec "cd $dir" "" $prompt
103
 
    assert_bash_list $expected $cmd $test $prompt $size
 
128
    assert_bash_list $expected $cmd $test $arg_sort \
 
129
        -chunk-size $arg(chunk-size) -prompt $prompt 
104
130
    sync_after_int $prompt
105
131
    assert_bash_exec {cd "$TESTDIR"}
106
 
}; # assert_bash_list_dir()
 
132
}
107
133
 
108
134
 
109
135
# Make sure the expected items are returned by TAB-completing the specified
110
 
# command.
 
136
# command.  If the number of expected items is one, expected is:
 
137
#
 
138
#     $cmd<TAB>$expected[<SPACE>]
 
139
#
 
140
# SPACE is not expected if -nospace is specified.
 
141
#
 
142
# If the number of expected items is greater than one, expected is:
 
143
#
 
144
#     $cmd<TAB>\n
 
145
#     $expected\n
 
146
#     $prompt + ($cmd - AUTO) + longest-common-prefix-of-$expected
 
147
#
 
148
# AUTO is calculated like this: If $cmd ends with non-whitespace, and
 
149
# the last argument of $cmd equals the longest-common-prefix of
 
150
# $expected, $cmd minus this argument will be expected.
 
151
#
 
152
# If the algorithm above fails, you can manually specify the CWORD to be
 
153
# subtracted from $cmd specifying `-expect-cmd-minus CWORD'.  Known cases where
 
154
# this is useful are when:
 
155
# - the last whitespace is escaped, e.g. "finger foo\ " or "finger
 
156
#   'foo "
 
157
#
 
158
# If the entire $cmd is expected, specify `-expect-cmd-full'.
 
159
#
111
160
# @param list $expected  Expected completions.
112
161
# @param string $cmd  Command given to generate items
113
 
# @param string $test  (optional) Test title.  Default is "$cmd<TAB> should show completions"
114
 
# @param string $prompt  (optional) Bash prompt.  Default is "/@"
115
 
# @param integer $size  (optional) Chunk size.  Default is 20.
116
 
# @param string $cword  (optional) Last argument of $cmd which is an
117
 
#     argument-to-complete and to be replaced with the longest common prefix
118
 
#     of $expected.  If empty string (default), `assert_complete' autodetects
119
 
#     if the last argument is an argument-to-complete by checking if $cmd
120
 
#     doesn't end with whitespace.  Specifying `cword' should only be necessary
121
 
#     if this autodetection fails, e.g.  when the last whitespace is escaped or
122
 
#     quoted, e.g. "finger foo\ " or "finger 'foo "
123
 
# @param list $filters  (optional) List of filters to apply to this function to tweak
124
 
#     the expected completions and argument-to-complete.  Possible values:
125
 
#     - "ltrim_colon_completions"
126
 
# @result boolean  True if successful, False if not
127
 
proc assert_complete {expected cmd {test ""} {prompt /@} {size 20} {cword ""} {filters ""}} {
 
162
# @param string $test  Test title
 
163
# @param list $args  Options:
 
164
#     -prompt PROMPT   Bash prompt.  Default is `/@'
 
165
#     -chunk-size CHUNK-SIZE   Compare list CHUNK-SIZE items at
 
166
#         a time.  Default is 20.
 
167
#     -nospace   Don't expect space character to be output after completion match.
 
168
#         Valid only if a single completion is expected.
 
169
#     -ltrim-colon-completions   Left-trim completions with cword containing
 
170
#         colon (:)
 
171
#     -expect-cmd-full   Expect the full $cmd to be echoed.  Expected is:
 
172
#
 
173
#             $cmd<TAB>\n
 
174
#             $expected\n
 
175
#             $prompt + $cmd + longest-common-prefix-of-$expected
 
176
#
 
177
#     -expect-cmd-minus DWORD   Expect $cmd minus DWORD to be echoed.
 
178
#         Expected is:
 
179
#
 
180
#             $cmd<TAB>\n
 
181
#             $expected\n
 
182
#             $prompt + ($cmd - DWORD) + longest-common-prefix-of-$expected
 
183
#
 
184
proc assert_complete {expected cmd {test ""} {args {}}} {
 
185
    set args_orig $args
 
186
    array set arg [::cmdline::getoptions args {
 
187
        {prompt.arg     "/@" "bash prompt"}
 
188
        {chunk-size.arg 20   "compare N list items at a time"}
 
189
        {nospace             "don't expect space after completion"}
 
190
        {ltrim-colon-completions  "left-trim completions with cword containing :"}
 
191
        {expect-cmd-full          "Expect full cmd after prompt"}
 
192
        {expect-cmd-minus.arg ""  "Expect cmd minus DWORD after prompt"}
 
193
    }]
128
194
    if {[llength $expected] == 0} {
129
195
        assert_no_complete $cmd $test
130
 
    } else {
131
 
        if {$test == ""} {set test "$cmd should show completions"}
132
 
        send "$cmd\t"
133
 
        if {[llength $expected] == 1} {
134
 
            expect -ex "$cmd"
135
 
 
136
 
            if {[lsearch -exact $filters "ltrim_colon_completions"] == -1} {
137
 
                set cur "";  # Default to empty word to complete on
138
 
                set words [split_words_bash $cmd]
139
 
                if {[llength $words] > 1} {
140
 
                        # Assume last word of `$cmd' is word to complete on.
141
 
                    set index [expr [llength $words] - 1]
142
 
                    set cur [lindex $words $index]
143
 
                }; # if
144
 
                    # Remove second word from beginning of single item $expected
145
 
                if {[string first $cur $expected] == 0} {
146
 
                    set expected [list [string range $expected [string length $cur] end]]
147
 
                }; # if
148
 
            }; # if
149
 
        } else {
150
 
            expect -ex "$cmd\r\n"
151
 
            # Make sure expected items are unique
152
 
            set expected [lsort -unique $expected]
153
 
        }; # if
154
 
 
155
 
        if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} {
156
 
                # If partial contains colon (:), remove partial from begin of items
157
 
                # See also: bash_completion.__ltrim_colon_completions()
158
 
            _ltrim_colon_completions cword expected
159
 
        }; # if
160
 
 
161
 
        if {[match_items $expected $test $prompt $size]} {
162
 
            if {[llength $expected] == 1} {
163
 
                pass "$test"
164
 
            } else {
165
 
                # Remove optional (partial) last argument-to-complete from `cmd',
166
 
                # E.g. "finger test@" becomes "finger"
167
 
 
168
 
                if {[lsearch -exact $filters "ltrim_colon_completions"] != -1} {
169
 
                    set cmd2 $cmd
170
 
                } else {
171
 
                    set cmd2 [_remove_cword_from_cmd $cmd $cword]
172
 
                }; # if
173
 
 
174
 
                # Determine common prefix of completions
175
 
                set common [::textutil::string::longestCommonPrefixList $expected]
176
 
                #if {[string length $common] > 0} {set common " $common"}
177
 
                expect {
178
 
                    -ex "$prompt$cmd2$common" { pass "$test" }
179
 
                    -re $prompt { unresolved "$test at prompt" }
180
 
                    -re eof { unresolved "eof" }
181
 
                }; # expect
182
 
            }; # if
183
 
        } else {
184
 
            fail "$test"
185
 
        }; # if
186
 
    }; # if
187
 
}; # assert_complete()
188
 
 
189
 
 
190
 
# @param string $cmd  Command to remove cword from
191
 
# @param string $cword  (optional) Last argument of $cmd which is an
192
 
#     argument-to-complete and to be deleted.  If empty string (default),
193
 
#     `_remove_cword_from_cmd' autodetects if the last argument is an
194
 
#     argument-to-complete by checking if $cmd doesn't end with whitespace.
195
 
#     Specifying `cword' is only necessary if this autodetection fails, e.g.
 
196
    } elseif {[llength $expected] == 1} {
 
197
        eval assert_complete_one \$expected \$cmd \$test $args_orig
 
198
    } else {
 
199
        eval assert_complete_many \$expected \$cmd \$test $args_orig
 
200
    }
 
201
}
 
202
 
 
203
 
 
204
# Make sure the expected multiple items are returned by TAB-completing the
 
205
# specified command.
 
206
# @see assert_complete()
 
207
proc assert_complete_many {expected cmd {test ""} {args {}}} {
 
208
    array set arg [::cmdline::getoptions args {
 
209
        {prompt.arg     "/@" "bash prompt"}
 
210
        {chunk-size.arg 20   "compare N list items at a time"}
 
211
        {nospace             "don't expect space after completion"}
 
212
        {ltrim-colon-completions  "left-trim completions with cword containing :"}
 
213
        {expect-cmd-full          "Expect full cmd after prompt"}
 
214
        {expect-cmd-minus.arg ""  "Expect cmd minus CWORD after prompt"}
 
215
    }]
 
216
    if {$test == ""} {set test "$cmd should show completions"}
 
217
    set prompt $arg(prompt)
 
218
    set dword ""
 
219
    if {$arg(expect-cmd-minus) != ""} {set dword $arg(expect-cmd-minus)}
 
220
 
 
221
    send "$cmd\t"
 
222
    expect -ex "$cmd\r\n"
 
223
 
 
224
    # Make sure expected items are unique
 
225
    set expected [lsort -unique $expected]
 
226
 
 
227
    # Determine common prefix of completions
 
228
    set common [::textutil::string::longestCommonPrefixList $expected]
 
229
 
 
230
    if {$arg(ltrim-colon-completions)} {
 
231
        # If partial contains colon (:), remove partial from begin of items
 
232
        _ltrim_colon_completions $cmd expected dword
 
233
    }
 
234
    set cmd2 [_remove_cword_from_cmd $cmd $dword $common]
 
235
 
 
236
    set prompt "$prompt$cmd2$common"
 
237
    if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
 
238
    set endprompt "-end-prompt"
 
239
    if {[
 
240
        eval match_items \$expected -bash-sort -chunk-size \
 
241
            \$arg(chunk-size) $endprompt $endspace -prompt \$prompt
 
242
    ]} {
 
243
        pass "$test"
 
244
    } else {
 
245
        fail "$test"
 
246
    }
 
247
}
 
248
 
 
249
 
 
250
# Make sure the expected single item is returned by TAB-completing the
 
251
# specified command.
 
252
# @see assert_complete()
 
253
proc assert_complete_one {expected cmd {test ""} {args {}}} {
 
254
    array set arg [::cmdline::getoptions args {
 
255
        {prompt.arg     "/@" "bash prompt"}
 
256
        {chunk-size.arg 20   "compare N list items at a time"}
 
257
        {nospace             "don't expect space after completion"}
 
258
        {ltrim-colon-completions  "left-trim completions with cword containing :"}
 
259
        {expect-cmd-full          "Expect full cmd after prompt"}
 
260
        {expect-cmd-minus.arg ""  "Expect cmd minus CWORD after prompt"}
 
261
    }]
 
262
    set prompt $arg(prompt)
 
263
 
 
264
    if {$test == ""} {set test "$cmd should show completion"}
 
265
    send "$cmd\t"
 
266
    expect -ex "$cmd"
 
267
    if {$arg(ltrim-colon-completions)} {
 
268
        # If partial contains colon (:), remove partial from begin of items
 
269
        _ltrim_colon_completions $cmd expected cword
 
270
    } else {
 
271
        set cur "";  # Default to empty word to complete on
 
272
        set words [split_words_bash $cmd]
 
273
        if {[llength $words] > 1} {
 
274
            # Assume last word of `$cmd' is word to complete on.
 
275
            set index [expr [llength $words] - 1]
 
276
            set cur [lindex $words $index]
 
277
        }
 
278
        # Remove second word from beginning of $expected
 
279
        if {[string first $cur $expected] == 0} {
 
280
            set expected [list [string range $expected [string length $cur] end]]
 
281
        }
 
282
    }
 
283
 
 
284
    if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
 
285
    if {[
 
286
        eval match_items \$expected -bash-sort -chunk-size \
 
287
            \$arg(chunk-size) $endspace -prompt \$prompt
 
288
    ]} {
 
289
        pass "$test"
 
290
    } else {
 
291
        fail "$test"
 
292
    }
 
293
}
 
294
 
 
295
 
 
296
# @param string $cmd  Command to remove current-word-to-complete from.
 
297
# @param string $dword  (optional) Manually specify current-word-to-complete,
 
298
#     i.e. word to remove from $cmd.  If empty string (default),
 
299
#     `_remove_cword_from_cmd' autodetects if the last argument is the
 
300
#     current-word-to-complete by checking if $cmd doesn't end with whitespace.
 
301
#     Specifying `dword' is only necessary if this autodetection fails, e.g.
196
302
#     when the last whitespace is escaped or quoted, e.g. "finger foo\ " or
197
303
#     "finger 'foo "
198
 
# @return string  Command with cword removed
199
 
proc _remove_cword_from_cmd {cmd {cword ""}} {
 
304
# @param string $common  (optional) Common prefix of expected completions.
 
305
# @return string  Command with current-word-to-complete removed
 
306
proc _remove_cword_from_cmd {cmd {dword ""} {common ""}} {
200
307
    set cmd2 $cmd
201
 
    # Is $cword specified?
202
 
    if {[string length $cword] > 0} {
203
 
        # Remove $cword from end of $cmd
204
 
        if {[string last $cword $cmd] == [string length $cmd] - [string length $cword]} {
205
 
            set cmd2 [string range $cmd 0 [expr [string last $cword $cmd] - 1]]
206
 
        }; # if
 
308
    # Is $dword specified?
 
309
    if {[string length $dword] > 0} {
 
310
        # Remove $dword from end of $cmd
 
311
        if {[string last $dword $cmd] == [string length $cmd] - [string length $dword]} {
 
312
            set cmd2 [string range $cmd 0 [expr [string last $dword $cmd] - 1]]
 
313
        }
207
314
    } else {
208
 
        # No, $cword not specified;
209
 
        # Check if last argument is really an-argument-to-complete, i.e.
 
315
        # No, $dword not specified;
 
316
        # Check if last argument is really a word-to-complete, i.e.
210
317
        # doesn't end with whitespace.
211
318
        # NOTE: This check fails if trailing whitespace is escaped or quoted,
212
319
        #       e.g. "finger foo\ " or "finger 'foo ".  Specify parameter
213
 
        #       $cword in those cases.
 
320
        #       $dword in those cases.
214
321
        # Is last char whitespace?
215
322
        if {! [string is space [string range $cmd end end]]} {
216
323
            # No, last char isn't whitespace;
217
 
            # Remove argument-to-complete from end of $cmd
218
 
            set cmd2 [lrange [split $cmd] 0 end-1]
219
 
            append cmd2 " "
220
 
        }; # if
221
 
    }; # if
 
324
            set cmds [split $cmd]
 
325
            # Does word-to-complete start with $common?
 
326
            if {[string first $common [lrange $cmds end end]] == 0} {
 
327
                # Remove word-to-complete from end of $cmd
 
328
                set cmd2 [lrange $cmds 0 end-1]
 
329
                append cmd2 " "
 
330
            }
 
331
        }
 
332
    }
222
333
    return $cmd2
223
 
}; # _remove_cword_from_cmd()
 
334
}
224
335
 
225
336
 
226
337
# Escape regexp special characters
253
364
        }
254
365
        -re $prompt { unresolved "$test at prompt" }
255
366
        eof { unresolved "eof" }
256
 
    }; # expect
257
 
}; # assert_complete_any()
 
367
    }
 
368
}
258
369
 
259
370
 
260
371
# Make sure the expected files are returned by TAB-completing the
262
373
# @param list $expected
263
374
# @param string $cmd  Command given to generate items
264
375
# @param string $dir  Subdirectory to attempt completion in.  The directory must be relative from the $TESTDIR and without a trailing slash.  E.g. `fixtures/evince'
265
 
# @param string $test  (optional) Test title.  Default is "$cmd<TAB> should show completions"
266
 
# @param string $prompt  (optional) Bash prompt.  Default is "/@"
267
 
# @param integer $size  (optional) Chunk size.  Default is 20.
268
 
# @param string $cword  (optional) Last word of $cmd to complete.  See: assert_complete()
 
376
# @param string $test  Test title
 
377
# @param list $args  See: assert_complete()
269
378
# @result boolean  True if successful, False if not
270
 
proc assert_complete_dir {expected cmd dir {test ""} {size 20} {cword ""}} {
271
 
    set prompt "/$dir/@"
 
379
proc assert_complete_dir {expected cmd dir {test ""} {args {}}} {
 
380
    set prompt "/@"
272
381
    assert_bash_exec "cd $dir" "" $prompt
273
 
    assert_complete $expected $cmd $test $prompt $size $cword
 
382
    assert_complete $expected $cmd $test $args
274
383
    sync_after_int $prompt
275
384
    assert_bash_exec {cd "$TESTDIR"}
276
 
}; # assert_complete_dir
 
385
}
277
386
    
278
387
 
279
388
 
284
393
# @param list $expected  List of all completions.
285
394
# @param string $cmd  Command given to generate items
286
395
# @param string $partial  Word to complete
287
 
# @param string $test  (optional) Test title.  Default is "$cmd<TAB> should show completions"
288
 
# @param string $prompt  (optional) Bash prompt.  Default is "/@"
289
 
# @param integer $size  (optional) Chunk size.  Default is 20.
290
 
# @param list $filters  (optional) List of filters to apply to this function to tweak
291
 
#     the expected completions and argument-to-complete.
292
 
#     @see assert_complete()
293
 
# @result boolean  True if successful, False if not
294
 
proc assert_complete_partial {expected cmd {partial ""} {test ""} {prompt /@} {size 20} {filters ""}} {
 
396
# @param string $test  Test title
 
397
# @param list $args  See: assert_complete()
 
398
proc assert_complete_partial {expected cmd {partial ""} {test ""} {args {}}} {
295
399
    if {$test == ""} {set test "$cmd should complete partial argument"}
296
400
    if {[llength $expected] == 0} {
297
401
        unresolved "$test"
301
405
        set expected [lsort -unique $expected]
302
406
        foreach item $expected {
303
407
            if {$partial == ""} {set partial [string range $item 0 0]}
304
 
                # Only append item if starting with $partial
 
408
            # Only append item if starting with $partial
305
409
            if {[string range $item 0 [expr [string length $partial] - 1]] == "$partial"} {
306
410
                lappend pick $item
307
 
            }; # if
308
 
        }; # foreach
309
 
        assert_complete $pick "$cmd $partial" $test $prompt $size $partial $filters
310
 
    }; # if
311
 
}; # assert_complete_partial()
312
 
 
313
 
 
 
411
            }
 
412
        }
 
413
        # NOTE: The `eval' is necessary to flatten the $args list
 
414
        #       See also: http://wiki.tcl.tk/11787 - {expand}
 
415
        eval assert_complete \$pick \"\$cmd \$partial\" \$test $args; #"
 
416
    }
 
417
}
 
418
 
 
419
 
 
420
# If cword contains colon (:), left-trim completions with cword
 
421
# @param string $cmd  Command to complete 
 
422
# @param list $items  Reference to list of completions to trim
 
423
# @param string $dword   Reference to variable to contain word to remove from
 
424
#                        expected cmd.
314
425
# See also: bash_completion._ltrim_colon_completions
315
 
proc _ltrim_colon_completions {cword items} {
316
 
    upvar 1 $cword cword_out
 
426
proc _ltrim_colon_completions {cmd items dword} {
317
427
    upvar 1 $items items_out
 
428
    upvar 1 $dword dword_out
 
429
 
 
430
    set cur "";  # Default to empty word to complete on
 
431
    set words [split_words_bash $cmd]
 
432
    if {[llength $words] > 1} {
 
433
        # Assume last word of `$cmd' is word to complete on.
 
434
        set index [expr [llength $words] - 1]
 
435
        set cur [lindex $words $index]
 
436
    }
318
437
    # If word-to-complete contains a colon,
319
438
    # and bash-version < 4,
320
439
    # or bash-version >= 4 and COMP_WORDBREAKS contains a colon
321
440
    if {
322
 
        [string first : $cword_out] > -1 && (
 
441
        [string first : $cur] > -1 && (
323
442
            [lindex $::BASH_VERSINFO 0] < 4 ||
324
443
            ([lindex $::BASH_VERSINFO 0] >= 4 && [string first ":" $::COMP_WORDBREAKS] > -1)
325
444
        )
326
445
    } {
 
446
        set dword_out $cur
327
447
        for {set i 0} {$i < [llength $items_out]} {incr i} {
328
448
            set item [lindex $items_out $i]
329
 
            if {[string first $cword_out $item] == 0} {
 
449
            if {[string first $cur $item] == 0} {
330
450
                # Strip colon-prefix
331
 
                lset items_out $i [string range $item [string length $cword_out] end]
332
 
            }; # if
333
 
        }; # for
334
 
        #set cword_out ""
335
 
    }; # if
336
 
}; # _ltrim_colon_completions()
 
451
                lset items_out $i [string range $item [string length $cur] end]
 
452
            }
 
453
        }
 
454
    }
 
455
}
337
456
 
338
457
 
339
458
# Make sure the bash environment hasn't changed between now and the last call
370
489
        append diff "\r\n"
371
490
    } else {
372
491
        set diff ""
373
 
    }; # if
 
492
    }
374
493
 
375
494
        # Execute diff
376
495
 
392
511
            # Remove possible `\r\n[wd]@' from end of diff
393
512
            if {[string last "\r\n[wd]@" $diff] == [string length $diff] - [string length "\r\n[wd]@"]} {
394
513
                set diff [string range $diff 0 [expr [string last "\r\n[wd]@" $diff] - 1]]
395
 
            }; # if
 
514
            }
396
515
            send_user $diff;
397
516
        }
398
 
    }; # expect
399
 
}; # assert_env_unmodified()
 
517
    }
 
518
}
400
519
 
401
520
 
402
521
# Make sure the specified command executed from within Tcl/Expect.
426
545
            unsupported "$test"
427
546
        } else {
428
547
            $failcmd "$test"
429
 
        }; # if
430
 
    }; # if
 
548
        }
 
549
    }
431
550
    return $result
432
 
}; # assert_exec()
 
551
}
433
552
 
434
553
 
435
554
# Check that no completion is attempted on a certain command.
439
558
proc assert_no_complete {{cmd} {test ""}} {
440
559
    if {[string length $test] == 0} {
441
560
        set test "$cmd shouldn't complete"
442
 
    }; # if
 
561
    }
443
562
 
444
563
    send "$cmd\t"
445
564
    expect -ex "$cmd"
451
570
        -re "^$endguard$" { pass "$test" }
452
571
        default { fail "$test" }
453
572
        timeout { fail "$test" }
454
 
    }; # expect
455
 
}; # assert_no_complete()
 
573
    }
 
574
}
456
575
 
457
576
 
458
577
# Check that no output is generated on a certain command.
483
602
proc assert_source_completions {command {file ""}} {
484
603
    if {[is_bash_completion_installed_for $command]} {
485
604
        if {[string length $file] == 0} {
486
 
            set file "lib/completions/$command.exp"
 
605
            set file "$::srcdir/lib/completions/$command.exp"
487
606
        }
488
607
        source $file
489
608
    } else {
510
629
    assert_bash_exec "_known_hosts_real '$cword'; echo_array COMPREPLY" \
511
630
        {} /@ result
512
631
    return $result
513
 
}; # get_known_hosts()
 
632
}
514
633
 
515
634
 
516
635
# Get hostnames
517
636
# @return list  Hostnames
518
637
# @see get_known_hosts()
519
638
proc get_hosts {} {
520
 
    set hosts [exec bash -c "compgen -A hostname"]
 
639
    set hosts [exec bash -c "compgen -A hostname | sort -u"]
521
640
    # NOTE: Circumventing var `avahi_hosts' and appending directly to `hosts'
522
641
    #       causes an empty element to be inserted in `hosts'.
523
642
    #       -- FVu, Fri Jul 17 23:11:46 CEST 2009
524
643
    set avahi_hosts [get_hosts_avahi]
525
644
    if {[llength $avahi_hosts] > 0} {
526
645
        lappend hosts $avahi_hosts
527
 
    }; # if
 
646
    }
528
647
    return $hosts
529
 
}; # get_hosts()
 
648
}
530
649
 
531
650
 
532
651
# Get hostnames according to avahi
540
659
        # No, retrieving hosts yields error;
541
660
            # Reset hosts
542
661
        set hosts {}
543
 
    }; # if
 
662
    }
544
663
    return $hosts
545
 
}; # get_hosts_avahi()
 
664
}
546
665
 
547
666
 
548
667
# Get signals
558
677
            set signal [string range $signal 3 end]
559
678
                # Add signal (with dash (-) prefix) to list
560
679
            lappend signals -$signal
561
 
        }; # if
562
 
    }; # foreach
 
680
        }
 
681
    }
563
682
    return $signals
564
 
}; # get_signals()
 
683
}
565
684
 
566
685
 
567
686
# Initialize tcl globals with bash variables
568
687
proc init_tcl_bash_globals {} {
569
 
    global BASH_VERSINFO BASH_VERSION COMP_WORDBREAKS
 
688
    global BASH_VERSINFO BASH_VERSION COMP_WORDBREAKS LC_CTYPE
570
689
    assert_bash_exec {printf "%s" "$COMP_WORDBREAKS"} {} /@ COMP_WORDBREAKS
571
690
    assert_bash_exec {printf "%s " "${BASH_VERSINFO[@]}"} "" /@ BASH_VERSINFO
572
691
    set BASH_VERSINFO [eval list $BASH_VERSINFO]
573
692
    assert_bash_exec {printf "%s" "$BASH_VERSION"} "" /@ BASH_VERSION
574
693
    assert_bash_exec {printf "%s" "$TESTDIR"} "" /@ TESTDIR
575
 
}; # init_tcl_bash_globals()
 
694
    assert_bash_exec {eval $(locale); printf "%s" "$LC_CTYPE"} "" /@ LC_CTYPE
 
695
}
576
696
 
577
697
 
578
698
# Check whether completion is installed for the specified command by executing
590
710
    }
591
711
    expect "/@"
592
712
    return $result
593
 
}; # is_bash_completion_installed_for()
 
713
}
594
714
 
595
715
 
596
716
# Detect if test suite is running under Cygwin/Windows
597
717
proc is_cygwin {} {
598
718
    expr {[string first [string tolower [exec uname -s]] cygwin] >= 0}
599
 
}; # is_cygwin()
600
 
 
601
 
 
602
 
# Expect items.
 
719
}
 
720
 
 
721
 
 
722
# Expect items, a limited number (20) at a time.
603
723
# Break items into chunks because `expect' seems to have a limited buffer size
604
 
# @param list $items
605
 
# @param integer $size  Chunk size
 
724
# @param list $items  Expected list items 
 
725
# @param list $args  Options:
 
726
#                    -bash-sort      Compare list bash-sorted.  Default is
 
727
#                                    unsorted
 
728
#                    -prompt PROMPT  Bash prompt.  Default is `/@'
 
729
#                    -chunk-size CHUNK-SIZE   Compare list CHUNK-SIZE items at
 
730
#                                             a time.  Default is 20.
 
731
#                    -end-newline  Expect newline after last item.
 
732
#                                  Default is not.
 
733
#                    -end-prompt   Expect prompt after last item.
 
734
#                                  Default is not.
 
735
#                    -end-space    Expect single space after last item.
 
736
#                                  Default is not.  Valid only if
 
737
#                                  `end-newline' not set.
606
738
# @result boolean  True if successful, False if not
607
 
proc match_items {items test {prompt /@} {size 20}} {
608
 
    set items [bash_sort $items]
 
739
proc match_items {items {args {}}} {
 
740
    array set arg [::cmdline::getoptions args {
 
741
        {bash-sort      "compare list sorted"}
 
742
        {prompt.arg     "/@" "bash prompt"}
 
743
        {chunk-size.arg 20   "compare N list items at a time"}
 
744
        {end-newline   "expect newline after last item"}
 
745
        {end-prompt    "expect prompt after last item"}
 
746
        {end-space     "expect space ater last item"}
 
747
    }]
 
748
    set prompt $arg(prompt)
 
749
    set size $arg(chunk-size)
 
750
    if {$arg(bash-sort)} {set items [bash_sort $items]}
609
751
    set result false
610
752
    for {set i 0} {$i < [llength $items]} {set i [expr {$i + $size}]} {
611
753
            # For chunks > 1, allow leading whitespace
614
756
            set item "[lindex $items [expr {$i + $j}]]"
615
757
            _escape_regexp_chars item
616
758
            append expected $item
617
 
            if {[llength $items] > 1} {append expected {\s+}};
618
 
        }; # for
 
759
            if {[llength $items] > 1} {append expected {\s+}}
 
760
        }
619
761
        if {[llength $items] == 1} {
 
762
            if {$arg(end-prompt)} {set end $prompt} {set end ""}
 
763
            # Both trailing space and newline are specified?
 
764
            if {$arg(end-newline) && $arg(end-space)} {
 
765
                # Indicate both trailing space or newline are ok
 
766
                set expected2 "|^$expected $end$";  # Include space
 
767
                append expected "\r\n$end";      # Include newline
 
768
            } else {
 
769
                if {$arg(end-newline)} {append expected "\r\n$end"}
 
770
                if {$arg(end-space)}   {append expected " $end"}
 
771
                set expected2 ""
 
772
            }
620
773
            expect {
621
 
                -re "^$expected\r\n$" { set result true }
622
 
                # NOTE: The optional space ( ?) depends on whether -o nospace is active
623
 
                -re "^$expected ?$" { set result true }
 
774
                -re "^$expected$$expected2" { set result true }
624
775
                -re "^$prompt$" {set result false; break }
625
 
                "\r\n" { set result false; break }
626
776
                default { set result false; break }
627
777
                timeout { set result false; break }
628
 
            }; # expect
 
778
            }
629
779
        } else {
 
780
            set end ""
 
781
            if {$arg(end-prompt) && $i + $j == [llength $items]} {
 
782
                set end "$prompt"
 
783
                _escape_regexp_chars end
 
784
                # \$ matches real end of expect_out buffer
 
785
                set end "$end\$"
 
786
            }
630
787
            expect {
631
 
                -re "^$expected" { set result true }
 
788
                -re "^$expected$end" { set result true }
632
789
                default { set result false; break }
633
790
                timeout { set result false; break }
634
 
            }; # expect
635
 
        }; # if
636
 
    }; # for
 
791
            }
 
792
        }
 
793
    }
637
794
    return $result
638
 
}; # match_items()
 
795
}
639
796
 
640
797
 
641
798
 
651
808
            set result [exec readlink -f $path]
652
809
        } else {
653
810
            set result $path
654
 
        }; # if
655
 
    }; # if
 
811
        }
 
812
    }
656
813
    return $result
657
 
}; # realcommand()
 
814
}
658
815
 
659
816
 
660
817
# Generate filename to save environment to.
674
831
            # Remove possible '.exp' suffix from filename
675
832
        if {[string last ".exp" $file] == [string length $file] - [string length ".exp"]} {
676
833
            set file [string range $file 0 [expr [string last ".exp" $file] - 1]]
677
 
        }; # if
678
 
    }; # if
 
834
        }
 
835
    }
679
836
    return "\$TESTDIR/tmp/$file.env$seq~"
680
 
}; # gen_env_filename()
 
837
}
681
838
 
682
839
 
683
840
# Save the environment for later comparison
685
842
#                      `gen_env_filename()'.
686
843
proc save_env {{file ""}} {
687
844
    _save_env [gen_env_filename $file 1]
688
 
}; # save_env()
 
845
}
689
846
 
690
847
 
691
848
# Save the environment for later comparison
693
850
# @see assert_env_unmodified()
694
851
proc _save_env {{file ""}} {
695
852
    assert_bash_exec "{ set; declare -F; shopt -p; } > \"$file\""
696
 
}; # _save_env()
 
853
}
697
854
 
698
855
 
699
856
# Source bash_completion package
700
857
proc source_bash_completion {} {
701
 
    assert_bash_exec {BASH_COMPLETION_DIR=$(cd "$TESTDIR/.."; pwd)/contrib}
 
858
    assert_bash_exec {BASH_COMPLETION_DIR=$(cd "$SRCDIR/.."; pwd)/completions}
702
859
    assert_bash_exec {BASH_COMPLETION_COMPAT_DIR=$BASH_COMPLETION_DIR}
703
 
    assert_bash_exec {BASH_COMPLETION=$(cd "$TESTDIR/.."; pwd)/bash_completion}
 
860
    assert_bash_exec {BASH_COMPLETION=$(cd "$SRCDIR/.."; pwd)/bash_completion}
704
861
    assert_bash_exec {source "$BASH_COMPLETION"}
705
 
}; # source_bash_completion()
 
862
}
706
863
 
707
864
 
708
865
# Split line into words, disregarding backslash escapes (e.g. \b (backspace),
727
884
            set part [string range $part 0 [expr [string length $part] - [string length "\\"] - 1]]
728
885
            # Indicate glue on next run
729
886
            set glue_next true
730
 
        }; # if
 
887
        }
731
888
        # Must `part' be appended to latest word (= glue)?
732
889
        if {[llength $words] > 0 && [string is true $glue]} {
733
890
            # Yes, join `part' to latest word;
738
895
            # No, don't append word to latest word;
739
896
            # Append `part' as separate word
740
897
            lappend words $part
741
 
        }; # if
 
898
        }
742
899
        set glue $glue_next
743
 
    }; # foreach
 
900
    }
744
901
    return $words
745
 
}; # split_words_bash()
 
902
}
746
903
 
747
904
 
748
905
# Given a list of items this proc finds a (part, full) pair so that when
814
971
 
815
972
# Start bash running as test environment.
816
973
proc start_bash {} {
817
 
    global TESTDIR TOOL_EXECUTABLE spawn_id
 
974
    global TESTDIR TOOL_EXECUTABLE spawn_id env srcdirabs
818
975
    set TESTDIR [pwd]
 
976
    set srcdirabs [file normalize $::srcdir];  # Absolute srcdir
819
977
    # If `--tool_exec' option not specified, use "bash"
820
978
    if {! [info exists TOOL_EXECUTABLE]} {set TOOL_EXECUTABLE bash}
821
 
    exp_spawn $TOOL_EXECUTABLE --rcfile config/bashrc
822
 
    assert_bash_exec {} "$TOOL_EXECUTABLE --rcfile config/bashrc"
 
979
    set env(SRCDIR) $::srcdir
 
980
    set env(SRCDIRABS) $::srcdirabs
 
981
    exp_spawn $TOOL_EXECUTABLE --rcfile $::srcdir/config/bashrc
 
982
    assert_bash_exec {} "$TOOL_EXECUTABLE --rcfile $::srcdir/config/bashrc"
823
983
    # Bash < 3.2.41 has a bug where 'history' disappears from SHELLOPTS
824
984
    # whenever a shopt setting is sourced or eval'ed.  Disabling 'history'
825
985
    # makes it not show in tests "Environment should not be modified"
826
986
    # for bash < 3.2.41.
827
987
    # -- FVu, Tue Sep 15 22:52:00 CEST 2009
828
988
    assert_bash_exec {is_bash_version_minimal 3 2 41 || set +o history}
829
 
}; # start_bash()
 
989
}
830
990
 
831
991
 
832
992
# Redirect xtrace output to a file.
896
1056
        #       installed, so that "^$cdm.*$" doesn't match too early - before
897
1057
        #       comp_install has finished
898
1058
    sleep .4
899
 
}; # sync_after_tab()
 
1059
}
900
1060
 
901
1061
 
902
1062
# Return current working directory with `TESTDIR' stripped
905
1065
    global TESTDIR
906
1066
        # Remove `$TESTDIR' prefix from current working directory
907
1067
    set wd [string replace [pwd] 0 [expr [string length $TESTDIR] - 1]]/
908
 
}; # wd()
 
1068
}