yamatanooroti 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c009e6dc5f113b62e9e62a6c1ce27130b2f2100f9ab0aa2a959afb893eace993
4
- data.tar.gz: dd24b52416f695388dda859d1f538662d15bead1e16b6b0b5702baf40702a54e
3
+ metadata.gz: 642a33b1504b4ecfdf9698597be8c5cff356950cfe71379cfb8c05ae6af45ec6
4
+ data.tar.gz: 8f4c37ab46ff74d2f14f4f2069c0b7c1847ea59c5d6b43990eaeff462c99474e
5
5
  SHA512:
6
- metadata.gz: 5a412b98347bd3e0b251905fa8f2de3dd54763899dcd80f50635d5d13f9166a2d0dbe80daa06faabd03a5ef000862db7d42951b935c15ecb75fd278b7e79c834
7
- data.tar.gz: 137f7d47e13c565daf6ffaf3cf56b47f00937ac6c61255bab821013fc408e14318b5b9110edf80e3c8796d7866e498665a190ff444fc28bea3704f9efb67afe6
6
+ metadata.gz: d017372f678c86f9e7f3dc0f6a6d96b4f26a0de534d96e508fe92b63e2ff129f2ae664dff1dcb4170aea0208420d014d5587ba66b6081c13d98713157f3a9c17
7
+ data.tar.gz: 77e04395752636618fd8202ccd8942440e7d5dfaa920d5650f60dd8b5ad4e83581d07297fcae62af46147ef063e25ee3ea0a2ab9531d840a2818d24a79c9fbeb
data/README.md CHANGED
@@ -75,10 +75,24 @@ Likewise, you can specify Windows command prompt test by `Yamatanooroti::Windows
75
75
 
76
76
  ## Method Reference
77
77
 
78
- ### `start_terminal(height, width, command)`
78
+ ### `start_terminal(height, width, command, startup_message: nil)`
79
79
 
80
80
  Starts terminal internally that is sized `height` and `width` with `command` to test the result. The `command` should be an array of strings with a path of command and zero or more options. This should be called in `setup` method.
81
81
 
82
+ If `startup_message` is given, `start_terminal` waits for the string to be printed and then returns.
83
+
84
+ ```ruby
85
+ code = 'sleep 1; puts "aaa"; sleep 10; puts "bbb"'
86
+ start_terminal(5, 30, ['ruby', '-e', code], startup_message: 'aaa')
87
+ close
88
+ assert_screen(<<~EOC)
89
+ aaa
90
+ EOC
91
+ # The start_terminal method waits for the output of the "aaa" as specified by
92
+ # the startup_message option, the "bbb" after 10 seconds won't come because
93
+ # the I/O is closed immediately after it.
94
+ ```
95
+
82
96
  ### `write(str)`
83
97
 
84
98
  Writes `str` like inputting by a keyboard to the started terminal.
@@ -1,3 +1,3 @@
1
1
  class Yamatanooroti
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
@@ -4,7 +4,7 @@ require 'pty'
4
4
  require 'io/console'
5
5
 
6
6
  module Yamatanooroti::VTermTestCaseModule
7
- def start_terminal(height, width, command, wait: 0.1)
7
+ def start_terminal(height, width, command, wait: 0.1, startup_message: nil)
8
8
  @wait = wait
9
9
  @result = nil
10
10
 
@@ -16,6 +16,15 @@ module Yamatanooroti::VTermTestCaseModule
16
16
  @screen = @vterm.screen
17
17
  @screen.reset(true)
18
18
 
19
+ case startup_message
20
+ when String
21
+ @startup_message = ->(message) { message.start_with?(startup_message) }
22
+ when Regexp
23
+ @startup_message = ->(message) { startup_message.match?(message) }
24
+ else
25
+ @startup_message = nil
26
+ end
27
+
19
28
  sync
20
29
  end
21
30
 
@@ -30,20 +39,34 @@ module Yamatanooroti::VTermTestCaseModule
30
39
  @pty_input.close
31
40
  sync
32
41
  Process.kill('KILL', @pid)
42
+ Process.waitpid(@pid)
33
43
  end
34
44
 
35
45
  private def sync
46
+ startup_message = '' if @startup_message
36
47
  loop do
37
48
  sleep @wait
38
49
  chunk = @pty_output.read_nonblock(1024)
50
+ if @startup_message
51
+ startup_message << chunk
52
+ if @startup_message.(startup_message)
53
+ @startup_message = nil
54
+ chunk = startup_message
55
+ else
56
+ redo
57
+ end
58
+ end
39
59
  @vterm.write(chunk)
40
60
  chunk = @vterm.read
41
61
  @pty_input.write(chunk)
42
62
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK
63
+ retry if @startup_message
43
64
  break
44
65
  rescue Errno::EIO # EOF
66
+ retry if @startup_message
45
67
  break
46
68
  rescue IO::EAGAINWaitReadable # emtpy buffer
69
+ retry if @startup_message
47
70
  break
48
71
  end
49
72
  end
@@ -289,8 +289,37 @@ module Yamatanooroti::WindowsTestCaseModule
289
289
  end
290
290
  end
291
291
 
292
+ private def quote_command_arg(arg)
293
+ if not arg.match?(/[ \t"]/)
294
+ # No quotation needed.
295
+ return arg
296
+ end
297
+
298
+ if not arg.match?(/["\\]/)
299
+ # No embedded double quotes or backlashes, so I can just wrap quote
300
+ # marks around the whole thing.
301
+ return %{"#{arg}"}
302
+ end
303
+
304
+ quote_hit = true
305
+ result = '"'
306
+ arg.chars.reverse.each do |c|
307
+ result << c
308
+ if quote_hit and c == '\\'
309
+ result << '\\'
310
+ elsif c == '"'
311
+ quote_hit = true
312
+ result << '\\'
313
+ else
314
+ quote_hit = false
315
+ end
316
+ end
317
+ result << '"'
318
+ result.reverse
319
+ end
320
+
292
321
  private def launch(command)
293
- command = %Q{cmd.exe /q /c "#{command.gsub('"', '\\"')}"}
322
+ command = %Q{cmd.exe /q /c "#{command}"}
294
323
  converted_command = mb2wc(command)
295
324
  @pi = DL::PROCESS_INFORMATION.malloc
296
325
  (@pi.to_ptr + 0)[0, DL::PROCESS_INFORMATION.size] = "\x00" * DL::PROCESS_INFORMATION.size
@@ -402,6 +431,12 @@ module Yamatanooroti::WindowsTestCaseModule
402
431
  def close
403
432
  sleep @wait
404
433
  # read first before kill the console process including output
434
+ @result = retrieve_screen
435
+
436
+ free_resources
437
+ end
438
+
439
+ private def retrieve_screen
405
440
  char_info_matrix = Fiddle::Pointer.to_ptr("\x00" * (DL::CHAR_INFO.size * (@height * @width)))
406
441
  region = DL::SMALL_RECT.malloc
407
442
  region.Left = 0
@@ -410,7 +445,7 @@ module Yamatanooroti::WindowsTestCaseModule
410
445
  region.Bottom = @height
411
446
  r = DL.ReadConsoleOutputW(@output_handle, char_info_matrix, @height * 65536 + @width, 0, region)
412
447
  error_message(r, "ReadConsoleOutputW")
413
- @result = []
448
+ screen = []
414
449
  prev_c = nil
415
450
  @height.times do |y|
416
451
  line = ''
@@ -425,10 +460,9 @@ module Yamatanooroti::WindowsTestCaseModule
425
460
  prev_c = mb
426
461
  end
427
462
  end
428
- @result << line.gsub(/ *$/, '')
463
+ screen << line.gsub(/ *$/, '')
429
464
  end
430
-
431
- free_resources
465
+ screen
432
466
  end
433
467
 
434
468
  def result
@@ -450,7 +484,20 @@ module Yamatanooroti::WindowsTestCaseModule
450
484
  @wait = wait
451
485
  @result = nil
452
486
  setup_console(height, width)
453
- launch(command.join(' '))
487
+ launch(command.map{ |c| quote_command_arg(c) }.join(' '))
488
+ case startup_message
489
+ when String
490
+ check_startup_message = ->(message) { message.start_with?(startup_message) }
491
+ when Regexp
492
+ check_startup_message = ->(message) { startup_message.match?(message) }
493
+ end
494
+ if check_startup_message
495
+ loop do
496
+ screen = retrieve_screen.join("\n").sub(/\n*\z/, "\n")
497
+ break if check_startup_message.(screen)
498
+ sleep @wait
499
+ end
500
+ end
454
501
  end
455
502
  end
456
503
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yamatanooroti
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-08 00:00:00.000000000 Z
11
+ date: 2020-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
85
  - !ruby/object:Gem::Version
86
86
  version: '0'
87
87
  requirements: []
88
- rubygems_version: 3.1.2
88
+ rubygems_version: 3.0.3
89
89
  signing_key:
90
90
  specification_version: 4
91
91
  summary: Multi-platform real(?) terminal test framework