summaryrefslogtreecommitdiffstats
path: root/src/testdir/test_xxd.vim
blob: 92a4d059988cf9497a56e6ef11ccc038fa78f04e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
" Test for the xxd command

if empty($XXD) && executable('..\xxd\xxd.exe')
  let s:xxd_cmd = '..\xxd\xxd.exe'
elseif empty($XXD) || !executable($XXD)
  throw 'Skipped: xxd program missing'
else
  let s:xxd_cmd = $XXD
endif

func PrepareBuffer(lines)
  new
  call append(0, a:lines)
  $d
endfunc

func s:Mess(counter)
  return printf("Failed xxd test %d:", a:counter)
endfunc

func Test_xxd()
  call PrepareBuffer(range(1,30))
  set ff=unix
  w! XXDfile

  " Test 1: simple, filter the result through xxd
  let s:test = 1
  exe '%!' . s:xxd_cmd . ' %'
  let expected = [
        \ '00000000: 310a 320a 330a 340a 350a 360a 370a 380a  1.2.3.4.5.6.7.8.',
        \ '00000010: 390a 3130 0a31 310a 3132 0a31 330a 3134  9.10.11.12.13.14',
        \ '00000020: 0a31 350a 3136 0a31 370a 3138 0a31 390a  .15.16.17.18.19.',
        \ '00000030: 3230 0a32 310a 3232 0a32 330a 3234 0a32  20.21.22.23.24.2',
        \ '00000040: 350a 3236 0a32 370a 3238 0a32 390a 3330  5.26.27.28.29.30',
        \ '00000050: 0a                                       .']
  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))

  " Test 2: reverse the result
  let s:test += 1
  exe '%!' . s:xxd_cmd . ' -r'
  call assert_equal(map(range(1,30), {v,c -> string(c)}), getline(1,'$'), s:Mess(s:test))

  " Test 3: Skip the first 0x30 bytes
  let s:test += 1
  for arg in ['-s 0x30', '-s0x30', '-s+0x30', '-skip 0x030', '-seek 0x30', '-seek +0x30 --']
    exe '%!' . s:xxd_cmd . ' ' . arg . ' %'
    call assert_equal(expected[3:], getline(1,'$'), s:Mess(s:test))
  endfor

  " Test 4: Skip the first 30 bytes
  let s:test += 1
  for arg in ['-s -0x31', '-s-0x31']
    exe '%!' . s:xxd_cmd . ' ' . arg . ' %'
    call assert_equal(expected[2:], getline(1,'$'), s:Mess(s:test))
  endfor

  " The following tests use the xxd man page.
  " For these tests to pass, the fileformat must be "unix".
  let man_copy = 'Xxd.1'
  let man_page = '../../runtime/doc/xxd.1'
  if has('win32') && !filereadable(man_page)
    let man_page = '../../doc/xxd.1'
  endif
  %d
  exe '0r ' man_page '| set ff=unix | $d | w' man_copy '| bwipe!' man_copy

  " Test 5: Print 120 bytes as continuous hexdump with 20 octets per line
  let s:test += 1
  %d
  exe '0r! ' . s:xxd_cmd . ' -l 120 -ps -c20 ' . man_copy
  $d
  let expected = [
      \ '2e54482058584420312022417567757374203139',
      \ '39362220224d616e75616c207061676520666f72',
      \ '20787864220a2e5c220a2e5c222032317374204d',
      \ '617920313939360a2e5c22204d616e2070616765',
      \ '20617574686f723a0a2e5c2220202020546f6e79',
      \ '204e7567656e74203c746f6e79407363746e7567']
  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))

  " Test 6: Print the date from xxd.1
  let s:test += 1
  for arg in ['-l 13', '-l13', '-len 13']
    %d
    exe '0r! ' . s:xxd_cmd . ' -s 0x36 ' . arg . ' -cols 13 ' . man_copy
    $d
    call assert_equal('00000036: 3231 7374 204d 6179 2031 3939 36  21st May 1996', getline(1), s:Mess(s:test))
  endfor

  " Cleanup after tests 5 and 6
  call delete(man_copy)

  " Test 7: Print C include
  let s:test += 1
  call writefile(['TESTabcd09'], 'XXDfile')
  %d
  exe '0r! ' . s:xxd_cmd . ' -i XXDfile'
  $d
  let expected =<< trim [CODE]
    unsigned char XXDfile[] = {
      0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a
    };
    unsigned int XXDfile_len = 11;
  [CODE]

  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))

  " Test 8: Print C include capitalized
  let s:test += 1
  for arg in ['-C', '-capitalize']
    call writefile(['TESTabcd09'], 'XXDfile')
    %d
    exe '0r! ' . s:xxd_cmd . ' -i ' . arg . ' XXDfile'
    $d
    let expected =<< trim [CODE]
      unsigned char XXDFILE[] = {
        0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a
      };
      unsigned int XXDFILE_LEN = 11;
    [CODE]
    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
  endfor

  " Test 9: Create a file with containing a single 'A'
  let s:test += 1
  call delete('XXDfile')
  bwipe! XXDfile
  if has('unix')
    call system('echo "010000: 41"|' . s:xxd_cmd . ' -r -s -0x10000 > XXDfile')
  else
    call writefile(['010000: 41'], 'Xinput')
    silent exe '!' . s:xxd_cmd . ' -r -s -0x10000 < Xinput > XXDfile'
    call delete('Xinput')
  endif
  call PrepareBuffer(readfile('XXDfile')[0])
  call assert_equal('A', getline(1), s:Mess(s:test))
  call delete('XXDfile')

  " Test 10: group with 4 octets
  let s:test += 1
  for arg in ['-g 4', '-group 4', '-g4']
    call writefile(['TESTabcd09'], 'XXDfile')
    %d
    exe '0r! ' . s:xxd_cmd . ' ' . arg . ' XXDfile'
    $d
    let expected = ['00000000: 54455354 61626364 30390a             TESTabcd09.']
    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
    call delete('XXDfile')
  endfor

  " Test 11: reverse with CR, hex upper, Postscript style with a TAB
  let s:test += 1
  call writefile([" 54455354\t610B6364 30390A             TESTa\0x0bcd09.\r"], 'Xinput')
  silent exe '!' . s:xxd_cmd . ' -r -p < Xinput > XXDfile'
  let blob = readfile('XXDfile', 'B')
  call assert_equal(0z54455354.610B6364.30390A, blob)
  call delete('Xinput')
  call delete('XXDfile')

  " Test 12: reverse with seek
  let s:test += 1
  call writefile(["00000000: 54455354\t610B6364 30390A             TESTa\0x0bcd09.\r"], 'Xinput')
  silent exe '!' . s:xxd_cmd . ' -r -seek 5 < Xinput > XXDfile'
  let blob = readfile('XXDfile', 'B')
  call assert_equal(0z0000000000.54455354.610B6364.30390A, blob)
  call delete('Xinput')
  call delete('XXDfile')

  " Test 13: simple, decimal offset
  call PrepareBuffer(range(1,30))
  set ff=unix
  w! XXDfile
  let s:test += 1
  exe '%!' . s:xxd_cmd . ' -d %'
  let expected = [
        \ '00000000: 310a 320a 330a 340a 350a 360a 370a 380a  1.2.3.4.5.6.7.8.',
        \ '00000016: 390a 3130 0a31 310a 3132 0a31 330a 3134  9.10.11.12.13.14',
        \ '00000032: 0a31 350a 3136 0a31 370a 3138 0a31 390a  .15.16.17.18.19.',
        \ '00000048: 3230 0a32 310a 3232 0a32 330a 3234 0a32  20.21.22.23.24.2',
        \ '00000064: 350a 3236 0a32 370a 3238 0a32 390a 3330  5.26.27.28.29.30',
        \ '00000080: 0a                                       .']
  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))

  " Test 14: grouping with -d
  let s:test += 1
  let expected = [
        \ '00000000: 310a320a 330a340a 350a360a 370a380a  1.2.3.4.5.6.7.8.',
        \ '00000016: 390a3130 0a31310a 31320a31 330a3134  9.10.11.12.13.14',
        \ '00000032: 0a31350a 31360a31 370a3138 0a31390a  .15.16.17.18.19.',
        \ '00000048: 32300a32 310a3232 0a32330a 32340a32  20.21.22.23.24.2',
        \ '00000064: 350a3236 0a32370a 32380a32 390a3330  5.26.27.28.29.30',
        \ '00000080: 0a                                   .']
  for arg in ['-g 4', '-group 4', '-g4']
    exe '%!' . s:xxd_cmd . ' ' . arg . ' -d %'
    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
  endfor

  " Test 15: cols with decimal offset: -c 21 -d
  let s:test += 1
  let expected = [
        \ '00000000: 310a 320a 330a 340a 350a 360a 370a 380a 390a 3130 0a  1.2.3.4.5.6.7.8.9.10.',
        \ '00000021: 3131 0a31 320a 3133 0a31 340a 3135 0a31 360a 3137 0a  11.12.13.14.15.16.17.',
        \ '00000042: 3138 0a31 390a 3230 0a32 310a 3232 0a32 330a 3234 0a  18.19.20.21.22.23.24.',
        \ '00000063: 3235 0a32 360a 3237 0a32 380a 3239 0a33 300a          25.26.27.28.29.30.']
  exe '%!' . s:xxd_cmd . ' -c 21 -d %'
  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))

  " Test 16: -o -offset
  let s:test += 1
  let expected = [
        \ '0000000f: 310a 320a 330a 340a 350a 360a 370a 380a  1.2.3.4.5.6.7.8.',
        \ '0000001f: 390a 3130 0a31 310a 3132 0a31 330a 3134  9.10.11.12.13.14',
        \ '0000002f: 0a31 350a 3136 0a31 370a 3138 0a31 390a  .15.16.17.18.19.',
        \ '0000003f: 3230 0a32 310a 3232 0a32 330a 3234 0a32  20.21.22.23.24.2',
        \ '0000004f: 350a 3236 0a32 370a 3238 0a32 390a 3330  5.26.27.28.29.30',
        \ '0000005f: 0a                                       .']
  for arg in ['-o 15', '-offset 15', '-o15']
    exe '%!' . s:xxd_cmd . ' ' . arg . ' %'
    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
  endfor

  " Test 17: Print C include with custom variable name
  let s:test += 1
  call writefile(['TESTabcd09'], 'XXDfile')
  for arg in ['-nvarName', '-n varName', '-name varName']
    %d
    exe '0r! ' . s:xxd_cmd . ' -i ' . arg . ' XXDfile'
    $d
    let expected =<< trim [CODE]
      unsigned char varName[] = {
        0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a
      };
      unsigned int varName_len = 11;
    [CODE]

    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
  endfor

  " using "-n name" reading from stdin
  %d
  exe '0r! ' . s:xxd_cmd . ' -i < XXDfile -n StdIn'
  $d
  let expected =<< trim [CODE]
    unsigned char StdIn[] = {
      0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a
    };
    unsigned int StdIn_len = 11;
  [CODE]
  call assert_equal(expected, getline(1,'$'), s:Mess(s:test))


  " Test 18: Print C include: custom variable names can be capitalized
  let s:test += 1
  for arg in ['-C', '-capitalize']
    call writefile(['TESTabcd09'], 'XXDfile')
    %d
    exe '0r! ' . s:xxd_cmd . ' -i ' . arg . ' -n varName XXDfile'
    $d
    let expected =<< trim [CODE]
      unsigned char VARNAME[] = {
        0x54, 0x45, 0x53, 0x54, 0x61, 0x62, 0x63, 0x64, 0x30, 0x39, 0x0a
      };
      unsigned int VARNAME_LEN = 11;
    [CODE]
    call assert_equal(expected, getline(1,'$'), s:Mess(s:test))
  endfor


  %d
  bwipe!
  call delete('XXDfile')
endfunc

func Test_xxd_patch()
  let cmd1 = 'silent !' .. s:xxd_cmd .. ' -r Xxxdin Xxxdfile'
  let cmd2 = 'silent !' .. s:xxd_cmd .. ' -g1 Xxxdfile > Xxxdout'
  call writefile(["2: 41 41", "8: 42 42"], 'Xxxdin', 'D')
  call writefile(['::::::::'], 'Xxxdfile', 'D')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 41 41 3a 3a 3a 3a 42 42                    ::AA::::BB'], readfile('Xxxdout'))

  call writefile(["2: 43 43 ", "8: 44 44"], 'Xxxdin')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 43 43 3a 3a 3a 3a 44 44                    ::CC::::DD'], readfile('Xxxdout'))

  call writefile(["2: 45 45  ", "8: 46 46"], 'Xxxdin')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 45 45 3a 3a 3a 3a 46 46                    ::EE::::FF'], readfile('Xxxdout'))

  call writefile(["2: 41 41", "08: 42 42"], 'Xxxdin')
  call writefile(['::::::::'], 'Xxxdfile')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 41 41 3a 3a 3a 3a 42 42                    ::AA::::BB'], readfile('Xxxdout'))

  call writefile(["2: 43 43 ", "09: 44 44"], 'Xxxdin')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 43 43 3a 3a 3a 3a 42 44 44                 ::CC::::BDD'], readfile('Xxxdout'))

  call writefile(["2: 45 45  ", "0a: 46 46"], 'Xxxdin')
  exe cmd1
  exe cmd2
  call assert_equal(['00000000: 3a 3a 45 45 3a 3a 3a 3a 42 44 46 46              ::EE::::BDFF'], readfile('Xxxdout'))

  call delete('Xxxdout')
endfunc

" Various ways with wrong arguments that trigger the usage output.
func Test_xxd_usage()
  for arg in ['-h', '-c', '-g', '-o', '-s', '-l', '-X', 'one two three']
    new
    exe 'r! ' . s:xxd_cmd . ' ' . arg
    call assert_match("Usage:", join(getline(1, 3)))
    bwipe!
  endfor
endfunc

func Test_xxd_ignore_garbage()
  new
  exe 'r! printf "\n\r xxxx 0: 42 42" | ' . s:xxd_cmd . ' -r'
  call assert_match('BB', join(getline(1, 3)))
  bwipe!
endfunc

func Test_xxd_bit_dump()
  new
  exe 'r! printf "123456" | ' . s:xxd_cmd . ' -b1'
  call assert_match('00000000: 00110001 00110010 00110011 00110100 00110101 00110110  123456', join(getline(1, 3)))
  bwipe!
endfunc

func Test_xxd_version()
  new
  exe 'r! ' . s:xxd_cmd . ' -v'
  call assert_match('xxd 20\d\d-\d\d-\d\d by Juergen Weigert et al\.', join(getline(1, 3)))
  bwipe!
endfunc

" number of columns must be non-negative
func Test_xxd_min_cols()
  for cols in ['-c-1', '-c -1', '-cols -1']
    for fmt in ['', '-b', '-e', '-i', '-p', ]
      new
      exe 'r! printf "ignored" | ' . s:xxd_cmd . ' ' . cols . ' ' . fmt
      call assert_match("invalid number of columns", join(getline(1, '$')))
      bwipe!
    endfor
  endfor
endfunc

" some hex formats limit columns to 256 (a #define in xxd.c)
func Test_xxd_max_cols()
  for cols in ['-c257', '-c 257', '-cols 257']
    for fmt in ['', '-b', '-e' ]
      new
      exe 'r! printf "ignored" | ' . s:xxd_cmd . ' ' . cols . ' ' . fmt
      call assert_match("invalid number of columns", join(getline(1, '$')))
      bwipe!
    endfor
  endfor
endfunc

" -c0 selects the format specific default column value, as if no -c was given
" except for -ps, where it disables extra newlines
func Test_xxd_c0_is_def_cols()
  call writefile(["abcdefghijklmnopqrstuvwxyz0123456789"], 'Xxdin', 'D')
  for cols in ['-c0', '-c 0', '-cols 0']
    for fmt in ['', '-b', '-e', '-i']
      exe 'r! ' . s:xxd_cmd . ' ' . fmt ' Xxdin > Xxdout1'
      exe 'r! ' . s:xxd_cmd . ' ' . cols . ' ' . fmt ' Xxdin > Xxdout2'
      call assert_equalfile('Xxdout1', 'Xxdout2')
    endfor
  endfor
  call delete('Xxdout1')
  call delete('Xxdout2')
endfunc

" all output in a single line for -c0 -ps
func Test_xxd_plain_one_line()
  call writefile([
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"],
        \ 'Xxdin', 'D')
  for cols in ['-c0', '-c 0', '-cols 0']
    exe 'r! ' . s:xxd_cmd . ' -ps ' . cols ' Xxdin'
    " output seems to start in line 2
    let out = join(getline(2, '$'))
    bwipe!
    " newlines in xxd output result in spaces in the string variable out
    call assert_notmatch(" ", out)
    " xxd output must be non-empty and comprise only lower case hex digits
    call assert_match("^[0-9a-f][0-9a-f]*$", out)
  endfor
endfunc

" vim: shiftwidth=2 sts=2 expandtab