Skip to content

Commit

Permalink
Fix a misparameter of RubyLex#set_input in termination_checker.rb (#482)
Browse files Browse the repository at this point in the history
* Fix a misparameter of RubyLex#set_input in termination_checker.rb

The keyword parameter `:context` of RubyLex#set_input became mandatory due to this commit:
https://github.com/ruby/irb/pull/427/files#diff-612b926e42ed78aed1a889ac1944f7d22229b3a489cc08f837a7f75eca3d3399R51

Without my patch, tests that specify "--auto-indent" option in test_yamatanooroti fall into an infinite loop.

This would need more explanation:
- The infinite loop happens in Yamatanooroti::VTermTestCaseModule#sync
  see: https://github.com/aycabta/yamatanooroti/blob/v0.0.9/lib/yamatanooroti/vterm.rb#L60-L63
- `@pty_output.read_nonblock(1024)` actually returned an exception
- However, this method doesn't anticipate such a situation
- As a result, `startup_message` couldn't be resolved for good and the
  infinite loop happens
- I think we would eventually have to fix yamatanooroti, though the
  inconsistency of the kwarg of "set_input" has to be fixed anyway

The actual exception message that is raised but ignored silently in Yamatanooroti::VTermTestCaseModule#sync:

```
/home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/bundler/gems/irb-d30c0c994351/lib/irb/ruby-lex.rb:51:in `set_input': missing keyword: :context (ArgumentError)
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/termination_checker.rb:23:in `initialize'
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/multiline_repl:43:in `new'
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/multiline_repl:43:in `block in <main>'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1576:in `block in parse_in_order'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1559:in `catch'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1559:in `parse_in_order'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1553:in `order!'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1659:in `permute!'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/optparse.rb:1684:in `parse!'
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/multiline_repl:174:in `<main>'
```

Backtrace of an inifinite loop:

```
/home/hasumi/work/ruby/yamatanooroti/lib/yamatanooroti/vterm.rb:59:in `sleep': Interrupt
        from /home/hasumi/work/ruby/yamatanooroti/lib/yamatanooroti/vterm.rb:59:in `block in sync'
        from /home/hasumi/work/ruby/yamatanooroti/lib/yamatanooroti/vterm.rb:58:in `loop'
        from /home/hasumi/work/ruby/yamatanooroti/lib/yamatanooroti/vterm.rb:58:in `sync'
        from /home/hasumi/work/ruby/yamatanooroti/lib/yamatanooroti/vterm.rb:28:in `start_terminal'
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/test_rendering.rb:653:in `test_suppress_auto_indent_just_after_pasted'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testcase.rb:871:in `run_test'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testcase.rb:566:in `block (2 levels) in run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/fixture.rb:276:in `block in create_fixtures_runner'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/fixture.rb:276:in `block in create_fixtures_runner'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/fixture.rb:257:in `run_fixture'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/fixture.rb:292:in `run_setup'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testcase.rb:564:in `block in run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testcase.rb:563:in `catch'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testcase.rb:563:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:124:in `run_test'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:53:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:124:in `run_test'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:53:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:124:in `run_test'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:53:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:124:in `run_test'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/testsuite.rb:53:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:67:in `run_suite'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:45:in `block (2 levels) in run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:102:in `with_listener'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:41:in `block in run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:39:in `catch'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnermediator.rb:39:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunner.rb:40:in `start_mediator'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunner.rb:25:in `start'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/ui/testrunnerutilities.rb:24:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/autorunner.rb:458:in `block in run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/autorunner.rb:514:in `change_work_directory'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/autorunner.rb:457:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit/autorunner.rb:66:in `run'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/test-unit-3.5.5/lib/test/unit.rb:518:in `block (2 levels) in <top (required)>'
```

* Fix mock object of Context

The previous commit solved one problem, but it found the next problem.

Following error message got from the command `RELINE_STDERR_TTY=error.log rake test_yamatanooroti`:

```
Reline is used by 24373
/home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/bundler/gems/irb-d30c0c994351/lib/irb/ruby-lex.rb:151:in `ripper_lex_without_warning': private method `local_variables' called for #<struct auto_indent_mode=true, workspace=nil> (NoMethodError)

    lvars_code = generate_local_variables_assign_code(context&.local_variables || [])
                                                             ^^^^^^^^^^^^^^^^^
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/bundler/gems/irb-d30c0c994351/lib/irb/ruby-lex.rb:213:in `block in set_auto_indent'
        from /home/hasumi/work/ruby/reline/lib/reline/line_editor.rb:1721:in `process_auto_indent'
        from /home/hasumi/work/ruby/reline/lib/reline/line_editor.rb:1663:in `input_key'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:346:in `block (3 levels) in inner_readline'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:345:in `each'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:345:in `block (2 levels) in inner_readline'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:420:in `block in read_io'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:390:in `loop'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:390:in `read_io'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:343:in `block in inner_readline'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:341:in `loop'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:341:in `inner_readline'
        from /home/hasumi/work/ruby/reline/lib/reline.rb:271:in `readmultiline'
        from /home/hasumi/.rbenv/versions/3.1.2/lib/ruby/3.1.0/forwardable.rb:238:in `readmultiline'
        from /home/hasumi/work/ruby/reline/test/reline/yamatanooroti/multiline_repl:185:in `<main>'
```

In irb/ruby-lex.rb, `context` is originally supposed to be an instance of IRB::Context with a public method `#local_variables`.
However, the `context` in reline/test/reline/yamatanooroti/termination_checker.rb is a Struct that is a mock object with no `#local_variables` method.

Thus, `rake test_yamatanooroti` no longer causes an infinite loop and an unexpected error with these two commits (at least in WITH_VTERM environment)

* Name the Struct "MockIRBContext" to specify what it is for
  • Loading branch information
hasumikin authored Dec 14, 2022
1 parent 7c14f02 commit a9960ad
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions test/reline/yamatanooroti/termination_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def terminated?(code)

class AutoIndent < RubyLex
def initialize
set_input(self)
context = Struct.new(:auto_indent_mode, :workspace).new(true, nil)
context = Struct.new("MockIRBContext", :auto_indent_mode, :workspace, :local_variables).new(true, nil, [])
set_input(self, context: context)
set_auto_indent(context)
end

Expand Down

0 comments on commit a9960ad

Please sign in to comment.