Module: Aruba::Api

Defined in:
lib/aruba/api.rb

Defined Under Namespace

Classes: ProcessTimeout

Constant Summary collapse

ARUBA_WORKING_DIR_DEFAULT =

You can override the default working directory by setting the environment variable ARUBA_WORKING_DIR

'tmp/aruba'
COMMON_RUBY_SCRIPTS =

This provides a regexp of commonly encountered Ruby scripts for use in testing Aruba itself. Used by detect_ruby_script.

/^(?:bundle|cucumber|gem|jeweler|rails|rake|rspec|spec)\s/
ARUBA_RUN_TIMEOUT_DEFAULT =

Set the default timeout in seconds for external process to finish May be overrriden by setting environment variable ARUBA_RUN_TIMEOUT

20

Instance Method Summary collapse

Instance Method Details

#_mkdir(dir_name) ⇒ Object

_mkdir(dir_name) is an internal helper name that does exactly as its stem suggests, performs a mkdir using the provided name.



488
489
490
# File 'lib/aruba/api.rb', line 488

def _mkdir(dir_name)
  FileUtils.mkdir_p(dir_name) unless File.directory?(dir_name)
end

#announce_or_puts(msg) ⇒ Object

announce_or_puts(msg) is an internal helper method for reproducing test process output in the Aruba run.



12
13
14
15
16
17
18
# File 'lib/aruba/api.rb', line 12

def announce_or_puts(msg)
  if(@puts)
    puts(msg)
  else
    announce(msg)
  end
end

#append_to_file(file_name, file_content) ⇒ Object

append_to_file is used to add data to the end of a file in a step definition. The data is of course a string obtained from the feature. A typical invocation looks like:

Given I do have a file named "foo/bar/example.rb" with:
"""
puts "hello world"
"""


30
31
32
33
34
# File 'lib/aruba/api.rb', line 30

def append_to_file(file_name, file_content)
  in_current_dir do
    File.open(file_name, 'a') { |f| f << file_content }
  end
end

#aruba_working_dirObject

aruba_working_dir simply returns the value of the current directory that aruba is running its features in. This is set using the aruba_working_dir_set method from within the step definitions or through the environment variable ARUBA_WORKING_DIR



42
43
44
# File 'lib/aruba/api.rb', line 42

def aruba_working_dir
  @aruba_working_dir
end

#aruba_working_dir_initObject

aruba_working_dir_init initializes the aruba_working_dir to either the default value specified in ARUBA_WORKING_DIR_DEFAULT or the value of the the environment variable ARUBA_WORKING_DIR if present.

This method also rebases the list of comma delimited directories contained in the ARUBA_REBASE environmental variable, if found.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/aruba/api.rb', line 67

def aruba_working_dir_init
  
  @aruba_working_dir = [ARUBA_WORKING_DIR_DEFAULT]

  if ( ENV['ARUBA_WORKING_DIR'] != nil )
    @aruba_working_dir = [ENV['ARUBA_WORKING_DIR']] 
  end

  dirs_init
  clean_up
  rebase_dirs_clear

  if ( ENV['ARUBA_REBASE'] != nil )
    rebase(ENV['ARUBA_REBASE'].split(%r{,|;\s*}))
  end
end

#aruba_working_dir_set(dir) ⇒ Object

aruba_working_dir_set allows before hooks to set aruba’s working directory relative to user’s cwd.



49
50
51
52
# File 'lib/aruba/api.rb', line 49

def aruba_working_dir_set(dir)
  @aruba_working_dir = dir
  dirs_init
end

#assert_exit_status_and_partial_output(expect_to_pass, partial_output) ⇒ Object

assert_exit_status_and_partial_output is an internal helper method that really should not be used in a step definition.



87
88
89
90
91
92
93
94
# File 'lib/aruba/api.rb', line 87

def assert_exit_status_and_partial_output(expect_to_pass, partial_output)
  assert_partial_output(partial_output)
  if expect_to_pass
    @last_exit_status.should == 0
  else
    @last_exit_status.should_not == 0
  end
end

#assert_failing_with(partial_output) ⇒ Object

assert_failing_with uses assert_exit_status_and_partial_output. It passes the exit status expectation as false (fail) and the text expected in the output to that method.

Usage:

Then the program should fail with:
"""
No such entry
"""

Then /the program should fail with:$/ do |content|
  assert_failing_with(content)


109
110
111
# File 'lib/aruba/api.rb', line 109

def assert_failing_with(partial_output)
  assert_exit_status_and_partial_output(false, partial_output)
end

#assert_partial_output(partial_output) ⇒ Object

assert_partial_output test if the provided string or rexexo occurs in either $stdout or $stderr.

Usage:

Then I should see "this text" in the output

Then /I should see "([^\"]*)" in the output/ do |content\
  assert_partial_output(content)


122
123
124
# File 'lib/aruba/api.rb', line 122

def assert_partial_output(partial_output)
  combined_output.should =~ regexp(partial_output)
end

#assert_passing_with(partial_output) ⇒ Object

assert_passing_with uses assert_exit_status_and_partial_output. It passes the exit status expectation as true (pass) and the text expected in the output to that method. See assert_failing_with.

Usage:

Then the program should run successfully with ""

Then /the program should run successfully with "([^\"]*)"/ do |output|
  assert_passing_with(output)


136
137
138
# File 'lib/aruba/api.rb', line 136

def assert_passing_with(partial_output)
  assert_exit_status_and_partial_output(true, partial_output)
end

#cd(dir) ⇒ Object

cd(path) changes aruba’s working directory (awd) to path.

Usage:

When I cd to "foo/nonexistant"

When /I cd to "([^\"]*)"/ do |dir|
  cd(dir)


148
149
150
151
152
# File 'lib/aruba/api.rb', line 148

def cd(dir)
  dirs << dir
  raise "#{current_dir} is not a directory." \
    unless File.directory?(current_dir)
end

#check_directory_presence(paths, expect_presence) ⇒ Object

check_directory_presence(paths, expect_presence) operates on an enumable collection of paths and determines if each exits passes if they do when expect_presence = true and passes if they do not when expect_presence = false.

Usage:

Then the following directories should exist:
  | foo/bar |
  | foo/bla |

Then the following directories should not exist:
  | bar/foo |
  | bar/none |

When /following directories should exist:$/ do |directories|
  check_directory_presence(directories.raw.map{
    |directory_row| directory_row[0]}, true)


172
173
174
175
176
177
178
179
180
181
182
# File 'lib/aruba/api.rb', line 172

def check_directory_presence(paths, expect_presence)
  in_current_dir do
    paths.each do |path|
      if expect_presence
        File.should be_directory(path)
      else
        File.should_not be_directory(path)
      end
    end
  end
end

#check_exact_file_content(file, contents) ⇒ Object

check_exact_file_content veries that the specified file contains exactly the provided text.

Usage:

Then the file "foo" should contain exactly:
  """
  My file should have this.
  And this
  """

When /the file "([^\"]*)" should contain exactly:$/ do |file,contents|
  check_exact_file_content(exact_output)


198
199
200
201
202
# File 'lib/aruba/api.rb', line 198

def check_exact_file_content(file, contents)
  in_current_dir do
    IO.read(file).should == contents
  end
end

#check_file_content(file, partial_content, expect_match) ⇒ Object

check_file_content(file, partial_content, expect_match) veries that the specified file contains at least the provided text.

Usage:

Then the file named "foo" should contain:
  """
  My file should have this.
  And this
  """

Then the file "foo" should not contain:
  """
  My file should not have this.
  And this
  """

When /the file named "foo" should contain:$/ do |file, content|
  check_file_content(file, content, true)


223
224
225
226
227
228
229
230
231
232
233
# File 'lib/aruba/api.rb', line 223

def check_file_content(file, partial_content, expect_match)
  regexp = regexp(partial_content)
  in_current_dir do
    content = IO.read(file)
    if expect_match
      content.should =~ regexp
    else
      content.should_not =~ regexp
    end
  end
end

#check_file_presence(paths, expect_presence) ⇒ Object

check_file_presence operates on files in a fashion similar to check_directory_presence. it enumerates on a collection of file names and passes or fails on the first presence or abscence in the filesystem according to the expect_presence setting.

Usage:

When the following files should exist:
"""
blah/file.tst
bare/file1.test
foor/barnet.tst
"""
When /following files? should exist:$/ do |files|
  check_file_presence(files.raw.map{|file_row| file_row[0]}, true)


250
251
252
253
254
255
256
257
258
259
260
# File 'lib/aruba/api.rb', line 250

def check_file_presence(paths, expect_presence)
  in_current_dir do
    paths.each do |path|
      if expect_presence
        File.should be_file(path)
      else
        File.should_not be_file(path)
      end
    end
  end
end

#clean_up(dir = current_dir) ⇒ Object

clean_up is an internal helper method that empties the current working directory of all content. It is used in the Aruba before hook to clear out the awd at the start of each scenario.

It will not clear any directory that does not contain the directory /tmp/ somewhare in its path.



269
270
271
272
273
274
275
276
277
# File 'lib/aruba/api.rb', line 269

def clean_up(dir = current_dir)
  check_tmp_dir = File.expand_path(dir)
  if File.fnmatch('**/tmp/**',check_tmp_dir)
    clean_up!
  else
    raise "#{check_tmp_dir} is outside the tmp " + 
      "subtree and may not be deleted."
  end
end

#clean_up!(dir = current_dir) ⇒ Object

clean_up! is an Internal helper method that clears the awd without checking for tmp in the directory path. Do not use this.



282
283
284
285
# File 'lib/aruba/api.rb', line 282

def clean_up!(dir = current_dir)
  FileUtils.rm_rf(dir)
  _mkdir(dir)
end

#combined_outputObject

combined_output is an internal helper methiod that concatenates the contents of $stdout with $stderr.

Usage:

Then output should contain:
  """
  toto
  red shoes
  """
Then output should contain "toto"
Then output should contain exactly:
  """
  toto
  red shoes
  """
Then output should contain exactly "toto"
Then output should not contain:
  """
  toto
  red shoes
  """
Then output should not contain "toto"
Then output should not contain exactly:
  """
  toto
  red shoes
  """
Then output should not contain exactly "toto"

When /output should contain "([^\"]*)"$/ do |partial_output|
  combined_output.should =~ regexp(partial_output)


319
320
321
322
323
324
325
326
327
328
329
# File 'lib/aruba/api.rb', line 319

def combined_output
  if @interactive
    interactive_output.to_s
  else
    if @last_stderr != nil and @last_stderr != ""
      @last_stdout.to_s + @last_stderr.inspect.to_s
    else
      @last_stdout.to_s
    end
  end
end

#create_dir(dir_name) ⇒ Object

create_dir creates the given directory name within the awd subject to normal filesystem restrictions.

‘Usage:

Given I do have a directory named "foobar"$

When /I do have a directory named "([^\"]*)"$/ do |dir_name|
  create_dir(dir_name)


340
341
342
343
344
# File 'lib/aruba/api.rb', line 340

def create_dir(dir_name)
  in_current_dir do
    _mkdir(dir_name)
  end
end

#create_file(file_name, file_content, check_presence = false) ⇒ Object

create_file creates the given file name in the awd and fills it with the provided content, optionally checking first to see if the file exists.

Usage:

When we do have a file named "foo" containing:
  """
  This is in my new file.
  And so is this
  """

When /do have a file named "([^\"]*)" containing:$/ do |file, content|
  create_file(file, content)

When I do have an empty file named "empty"

When /I do have an empty file named "([^\"]*)"$/ do |file_name|
  create_file(file_name, "")


365
366
367
368
369
370
371
# File 'lib/aruba/api.rb', line 365

def create_file(file_name, file_content, check_presence = false)
  in_current_dir do
    raise "expected #{file_name} to be present" if check_presence && !File.file?(file_name)
    _mkdir(File.dirname(file_name))
    File.open(file_name, 'w') { |f| f << file_content }
  end
end

#current_dirObject

current_dir is an internal helper method that returns the current awd as a path.



376
377
378
# File 'lib/aruba/api.rb', line 376

def current_dir
  File.join(*dirs)
end

#current_rubyObject

current_ruby is an internal helper method that returns the path to the currently active Ruby VM.



383
384
385
386
# File 'lib/aruba/api.rb', line 383

def current_ruby
  File.join(RbConfig::CONFIG['bindir'], 
    RbConfig::CONFIG['ruby_install_name'])
end

#detect_ruby(cmd) ⇒ Object

detect_ruby is an internal helper method that checks to see if the Aruba test cli command is ruby itself. If so then it returns the value of current_ruby to the run method. If not then it returns the the value of cmd.



393
394
395
396
397
398
399
# File 'lib/aruba/api.rb', line 393

def detect_ruby(cmd)
  if cmd =~ /^ruby\s/
    cmd.gsub(/^ruby\s/, "#{current_ruby} ")
  else
    cmd
  end
end

#detect_ruby_script(cmd) ⇒ Object

detect_ruby_script is an internal helper script used in testing Aruba itself. Uses COMMON_RUBY_SCRIPTS.



410
411
412
413
414
415
416
417
# File 'lib/aruba/api.rb', line 410

def detect_ruby_script(cmd)
  if cmd =~ COMMON_RUBY_SCRIPTS
    "ruby -S #{cmd}"
  else
    cmd
  
  end
end

#dirsObject

dirs is an internal helper method that returns the current directory components as an array.



422
423
424
# File 'lib/aruba/api.rb', line 422

def dirs
  @dirs ||= dirs_init
end

#dirs_initObject

dirs_init is an internal helper method that intializes the content of the dirs to the value of aruba_working_dir.



429
430
431
432
# File 'lib/aruba/api.rb', line 429

def dirs_init
  @dirs = []
  @dirs << aruba_working_dir
end

#ensure_newline(str) ⇒ Object

ensure_newline is an internal helper method used to test interactive CLI programs with Aruba.



437
438
439
# File 'lib/aruba/api.rb', line 437

def ensure_newline(str)
  str.chomp << "\n"
end

#in_current_dir(&block) ⇒ Object

in_current_dir is an internal helper method wherein all the magic of Aruba takes place. It uses the value of current_dir to determine what directory to change to before running Aruba steps.



445
446
447
448
# File 'lib/aruba/api.rb', line 445

def in_current_dir(&block)
  _mkdir(current_dir)
  Dir.chdir(current_dir, &block)
end

#install_gems(gemfile) ⇒ Object

install_gems internal helper method that uses up Bundler to install the gems specified in the given Gemfile name into the current Ruby VM. If Bundler is not present then this method will attempt to install it.



455
456
457
458
459
460
461
# File 'lib/aruba/api.rb', line 455

def install_gems(gemfile)
  create_file("Gemfile", gemfile)
  if ENV['GOTGEMS'].nil?
    run("gem install bundler")
    run("bundle --no-color install")
  end
end

#interactive_outputObject

interactive_output is an internal helper method that provides the contents of $stdout from interactive Aruba processes.



466
467
468
469
470
471
472
473
# File 'lib/aruba/api.rb', line 466

def interactive_output
  @_interactive ||= if @interactive
    @interactive.wait(1) || @interactive.kill('TERM')
    @interactive.stdout.read
  else
    ""
  end
end

#last_stderrObject

Attribute.



476
477
478
# File 'lib/aruba/api.rb', line 476

def last_stderr
  @last_stderr
end

#last_stdoutObject

Attribute



481
482
483
# File 'lib/aruba/api.rb', line 481

def last_stdout
  @last_stdout
end

#original_envObject

original_env is an internal helper method that returns a hash of the env variables and their values. See: remove_env(), restore_env() and set_env().



496
497
498
# File 'lib/aruba/api.rb', line 496

def original_env
  @original_env ||= {}
end

#rebase(dirs = nil) ⇒ Object

rebase creates a symbolic link in the awd to each directory contained in the passed array.Each entry is named relative to the user’s cwd. It first checkes that the awd path contains a directory named /tmp/ and fails if it does not.

Usage:

When I rebase the directory named "bar/foo"$

When /I rebase the directory named "([^\"]*)"$/ do |dir|
  rebase(dir)


511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'lib/aruba/api.rb', line 511

def rebase(dirs=nil)

  rebase_dirs_add(dirs) if dirs
  working_dir = File.expand_path(File.join(FileUtils.pwd, aruba_working_dir))

  if rebase_dirs and File.fnmatch('**/tmp/**', working_dir)
    rebase_dirs.each do |dir|
      FileUtils.ln_s(File.join(user_working_dir, dir.to_s), 
        working_dir, :force => true)
    end
  else
    raise "Aruba's working directory, #{working_dir}, \n" +
      "is outside the tmp subtree and may not be rebased."
  end
end

#rebase_dirsObject

rebase_dirs is an internal helper mehtod that returns the array containing all the directories to be rebased.



530
531
532
# File 'lib/aruba/api.rb', line 530

def rebase_dirs
  @aruba_rebase_dirs
end

#rebase_dirs_add(dirs = nil) ⇒ Object

rebase_dirs_add is an internal helper method that adds directory names to the rebase_dirs array.



537
538
539
540
541
542
543
# File 'lib/aruba/api.rb', line 537

def rebase_dirs_add(dirs=nil)
  return unless dirs
  dirs = dirs.lines.to_a if dirs.respond_to?('lines')
  dirs = dirs.flatten
  @aruba_rebase_dirs ||= []
  @aruba_rebase_dirs = (@aruba_rebase_dirs + dirs).uniq
end

#rebase_dirs_clearObject

rebase_dirs_clear is an internal helper method that empties the rebase_dirs array.



548
549
550
# File 'lib/aruba/api.rb', line 548

def rebase_dirs_clear
  @aruba_rebase_dirs = []
end

#regexp(string_or_regexp) ⇒ Object

regexp(string_or_regexp) is an internal helper method used to compile regexp for use in step definations.

Usage:

Then should (pass|fail) with regexp:
  """
  /^Better start with this/
  """
Then stderr should contain "this"
Then stdout should contain "this"
Then stderr should not contain "this"
Then stdout should not contain "this"

When /stderr should contain "([^\"]*)"$/ do |partial_output|
  last_stderr.should =~ regexp(partial_output)


568
569
570
# File 'lib/aruba/api.rb', line 568

def regexp(string_or_regexp)
  Regexp === string_or_regexp ? string_or_regexp : Regexp.compile(Regexp.escape(string_or_regexp))
end

#remove_env(key) ⇒ Object

remove_env removes (unsets) the given environmental variable from the original working environment. See restore_env() and set_env()

Usage:

When /(?:delete|unset) the env variable "([^\"]*)"$/ do |var|
  remove_env(var)
end


581
582
583
# File 'lib/aruba/api.rb', line 581

def remove_env(key)
  original_env[key] = ENV.delete(key)
end

#remove_file(file_name) ⇒ Object

remove file implements the rm command and removes the file whose name is given as the argument.



587
588
589
590
591
# File 'lib/aruba/api.rb', line 587

def remove_file(file_name)
  in_current_dir do
    FileUtils.rm(file_name)
  end
end

#restore_envObject

restore_env method restores the user’s original environment at the completion of a scenario using Aruba. See set_env().



596
597
598
599
600
# File 'lib/aruba/api.rb', line 596

def restore_env
  original_env.each do |key, value|
    ENV[key] = value
  end
end

#run(cmd, fail_on_error = true, tlimit = nil) ⇒ Object

run is the internal helper method that actually runs the external test process, optionally failing if the exit status != 0. Takes an optional third parameter to specify the maximum time a process should take before exiting on its own.

Usage:

When I run "ruby -e 'puts "hello world"'
When I run "ruby -e 'print "Name? "; my_name = gets'" interactively
When I run "ruby -e 'fail' with errors
When I run "ruby -e 'exit' without errors

When /I run a long process without error/ do
    run(long_process, true, 15) # allow 15 seconds.

When /run "(.*)" with timeout of "(\d+\.\d*)" seconds$/ do |cmd, time|
  run(unescape(cmd), true, time.to_f)
end

When I set the env variable "SOME_THING" to "some value"


627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
# File 'lib/aruba/api.rb', line 627

def run(cmd, fail_on_error=true, tlimit=nil)

  @last_stderr = ""
  @last_stdout = ""
  cmd = detect_ruby(cmd)

  if tlimit == nil || tlimit == ""
    if ( ENV['ARUBA_RUN_TIMEOUT'] != nil ) 
      tlimit = ENV['ARUBA_RUN_TIMEOUT']
    else
      tlimit = ARUBA_RUN_TIMEOUT_DEFAULT
    end
  end

  in_current_dir do
    announce_or_puts("$ cd #{Dir.pwd}") if @announce_dir
    announce_or_puts("$ #{cmd}") if @announce_cmd
    begin
      Timeout::timeout(tlimit.to_f, ProcessTimeout) {
        ps = BackgroundProcess.run(cmd)
        @last_stdout = ps.stdout.read 
        announce_or_puts(@last_stdout) if @announce_stdout
        @last_stderr = ps.stderr.read
        announce_or_puts(@last_stderr) if @announce_stderr 
      # Waits for process to finish or timeout
        @last_exit_status = ps.exitstatus
      }
    rescue ProcessTimeout => e
      if @last_stderr 
        @last_stderr += e.inspect
      else
        @last_stderr = e.inspect
      end
      @last_exit_status = -1
      announce_or_puts(@last_exit_status.to_i.to_s) if @announce_stderr
      announce_or_puts(@last_stderr) if @announce_stderr
    end
  end

  if(@last_exit_status != 0 && fail_on_error)
    fail("Exit status was #{@last_exit_status}. Output:\n#{combined_output}")
  end

end

#run_interactive(cmd) ⇒ Object

run_interactive(cmd) is an internal helper method that runs CLI programs returning user input.

Usage:

When I run "ruby -e 'print "Name? "; my_name = gets'" interactively


678
679
680
681
682
683
684
# File 'lib/aruba/api.rb', line 678

def run_interactive(cmd)
  cmd = detect_ruby(cmd)

  in_current_dir do
    @interactive = BackgroundProcess.run(cmd)
  end
end

#set_env(key, value) ⇒ Object

set_env method permits setting of environment variables for aruba run commands. See restore_env() and remove_env().

Usage:

When /(?:add|set) the env variable "([^\"]*)" to "(.*)"$/ do |var, val|
  set_env(var, val)
end


694
695
696
697
698
# File 'lib/aruba/api.rb', line 694

def set_env(key, value)
  announce_or_puts(%{$ export #{key}="#{value}"}) if @announce_env
  remove_env(key)
  ENV[key] = value
end

#unescape(string) ⇒ Object

unescape(string) is an internal helper method that evals the passed string.



703
704
705
# File 'lib/aruba/api.rb', line 703

def unescape(string)
  eval(%{"#{string}"})
end

#unset_bundler_env_varsObject

unset_bundler_env_vars is an internal helper method that unsets enviromental variables used by the Bundler gem.



710
711
712
713
714
# File 'lib/aruba/api.rb', line 710

def unset_bundler_env_vars
  %w[RUBYOPT BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE].each do |key|
    set_env(key, nil)
  end
end

#use_clean_gemset(gemset) ⇒ Object

use_clean_gemset(gemset) takes a gemset name and creates it using gemset.

Usage:

When I am using a clean gemset "my_global*)"


722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
# File 'lib/aruba/api.rb', line 722

def use_clean_gemset(gemset)
  run(%{rvm gemset create "#{gemset}"}, true)
  if @last_stdout =~ /'#{gemset}' gemset created \((.*)\)\./
    gem_home = $1
    set_env('GEM_HOME', gem_home)
    set_env('GEM_PATH', gem_home)
    set_env('BUNDLE_PATH', gem_home)

    paths = (ENV['PATH'] || "").split(File::PATH_SEPARATOR)
    paths.unshift(File.join(gem_home, 'bin'))
    set_env('PATH', paths.uniq.join(File::PATH_SEPARATOR))

    run("gem install bundler", true)
  else
    raise "I didn't understand rvm's output: #{@last_stdout}"
  end
end

#user_working_dirObject

user_working_dir is an internal helper method used by the rebase method that initially sets and then returns the user’s pwd.



743
744
745
746
# File 'lib/aruba/api.rb', line 743

def user_working_dir
  # This allows us to find the user's original working directory
  @user_working_dir ||= FileUtils.pwd
end

#write_interactive(input) ⇒ Object

write_interactive(input) writes the provided string to $stdin of the interactive process run by Aruba. Usage

When I type "the answwer is 42"


753
754
755
# File 'lib/aruba/api.rb', line 753

def write_interactive(input)
  @interactive.stdin.write(input)
end