yamatanooroti 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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