File: thread_test.rb

package info (click to toggle)
ruby-byebug 11.1.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,252 kB
  • sloc: ruby: 8,835; ansic: 1,662; sh: 6; makefile: 4
file content (181 lines) | stat: -rw-r--r-- 4,965 bytes parent folder | download | duplicates (3)
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
# frozen_string_literal: true

require "test_helper"

module Byebug
  #
  # Tests threading functionality.
  #
  class ThreadTest < TestCase
    def program
      strip_line_numbers <<-RUBY
         1:  module Byebug
         2:    #
         3:    # Toy class to test threading
         4:    #
         5:    class #{example_class}
         6:      attr_accessor :lock
         7:
         8:      def initialize
         9:        @lock = Queue.new
        10:      end
        11:
        12:      def launch
        13:        t1 = Thread.new do
        14:          loop do
        15:            break unless lock.empty?
        16:            sleep 0.01
        17:          end
        18:        end
        19:
        20:        @t2 = Thread.new do
        21:          loop { sleep 0.01 }
        22:        end
        23:
        24:        t1.join
        25:      end
        26:
        27:      def kill
        28:        @t2.kill
        29:      end
        30:    end
        31:
        32:    byebug
        33:
        34:    t = #{example_class}.new
        35:    t.launch
        36:    t.kill
        37:  end
      RUBY
    end

    def t1_context
      Byebug.contexts[-2]
    end

    def t1_thnum
      t1_context.thnum
    end

    def t2_context
      Byebug.contexts[-1]
    end

    def t2_thnum
      t2_context.thnum
    end

    def curr_thnum
      Byebug.current_context.thnum
    end

    def test_thread_list_marks_current_thread_with_a_plus_sign
      file = example_path
      enter "cont 13", "thread list", "lock << 0"
      debug_code(program)

      check_output_includes(/\+ \d+ #<Thread:0x\h+ run> #{file}:13/)
    end

    def test_thread_list_shows_all_available_threads
      enter "cont 24", "thread list", "lock << 0"
      debug_code(program)

      check_output_includes(
        /(\+)?\d+ #<Thread:0x\h+(.+:\d+)? (sleep|sleep_forever|run)>/,
        /(\+)?\d+ #<Thread:0x\h+(.+:\d+)? (sleep|sleep_forever|run)>/,
        /(\+)?\d+ #<Thread:0x\h+(.+:\d+)? (sleep|sleep_forever|run)>/
      )
    end

    def test_thread_stop_marks_thread_as_suspended
      enter "cont 24", -> { "thread stop #{t2_thnum}" }, "lock << 0"
      debug_code(program)

      check_output_includes(/\$ \d+ #<Thread:/)
    end

    def test_thread_stop_actually_suspends_thread_execution
      enter "cont 24",
            "set linetrace",
            -> { "thread stop #{t2_thnum}" },
            "lock << 0"
      debug_code(program) { Setting[:linetrace] = false }

      check_output_doesnt_include(/Tracing: #{example_path}:21/)
    end

    def test_thread_stop_shows_help_when_no_thread_number_specified
      enter "cont 13", "thread stop", "lock << 0"
      debug_code(program)

      check_output_includes "Stops the execution of the specified thread"
    end

    def test_thread_stop_shows_error_when_trying_to_stop_current_thread
      enter "cont 13", -> { "thread stop #{curr_thnum}" }, "lock << 0"
      debug_code(program)

      check_error_includes "It's the current thread"
    end

    def test_thread_resume_removes_threads_from_the_suspended_state
      ctx = nil
      save_second_ctx_and_stop = lambda do
        ctx = t2_context
        "thread stop #{t2_thnum}"
      end

      enter "cont 24",
            save_second_ctx_and_stop,
            -> { "thread resume #{t2_thnum}" },
            "lock << 0"

      debug_code(program) { assert_equal false, ctx.suspended? }
      check_output_includes(/\$ #{ctx.thnum} #<Thread:0x\h+/,
                            /#{ctx.thnum} #<Thread:0x\h+/)
    end

    def test_thread_resume_shows_help_if_thread_number_not_specified
      enter "cont 13", "thread resume", "lock << 0"
      debug_code(program)

      check_output_includes "Resumes execution of the specified thread"
    end

    def test_thread_resume_shows_error_when_trying_to_resume_current_thread
      enter "cont 13", -> { "thread resume #{curr_thnum}" }, "lock << 0"
      debug_code(program)

      check_error_includes "It's the current thread"
    end

    def test_thread_resume_shows_error_if_thread_is_already_running
      enter "cont 24", -> { "thread resume #{t2_thnum}" }, "lock << 0"
      debug_code(program)

      check_error_includes "Already running"
    end

    def test_thread_switch_changes_execution_to_another_thread
      enter "cont 24", -> { "thread switch #{t2_thnum}" }, "lock << 0"
      debug_code(program)

      check_output_includes "=> 21:         loop { sleep 0.01 }"
    end

    def test_thread_switch_shows_help_if_thread_number_not_specified
      enter "cont 13", "thread switch", "lock << 0"
      debug_code(program)

      check_output_includes "Switches execution to the specified thread"
    end

    def test_thread_switch_shows_error_when_trying_to_switch_current_thread
      enter "cont 13", -> { "thread switch #{curr_thnum}" }, "lock << 0"
      debug_code(program)

      check_error_includes "It's the current thread"
    end
  end
end