forked from FooBarWidget/crash-watch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gdb_controller_spec.rb
116 lines (103 loc) · 3 KB
/
gdb_controller_spec.rb
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
source_root = File.expand_path(File.dirname(__FILE__) + "/..")
$LOAD_PATH.unshift("#{source_root}/lib")
Thread.abort_on_exception = true
require 'crash_watch/gdb_controller'
describe CrashWatch::GdbController do
before :each do
@gdb = CrashWatch::GdbController.new
end
after :each do
@gdb.close
if @process
Process.kill('KILL', @process.pid)
@process.close
end
end
def run_script_and_wait(code, snapshot_callback = nil, &block)
@process = IO.popen(%Q{ruby -e '#{code}'}, 'w')
@gdb.attach(@process.pid)
thread = Thread.new do
sleep 0.1
if block
block.call
end
@process.write("\n")
end
exit_info = @gdb.wait_until_exit(&snapshot_callback)
thread.join
return exit_info
end
describe "#execute" do
it "executes the desired command and returns its output" do
@gdb.execute("echo hello world").should == "hello world\n"
end
end
describe "#attach" do
before :each do
@process = IO.popen("sleep 9999", "w")
end
it "returns true if attaching worked" do
@gdb.attach(@process.pid).should be_true
end
it "returns false if the PID doesn't exist" do
Process.kill('KILL', @process.pid)
sleep 0.25
@gdb.attach(@process.pid).should be_false
end
end
describe "#wait_until_exit" do
it "returns the expected information if the process exited normally" do
exit_info = run_script_and_wait('STDIN.readline')
exit_info.exit_code.should == 0
exit_info.should_not be_signaled
end
it "returns the expected information if the process exited with a non-zero exit code" do
exit_info = run_script_and_wait('STDIN.readline; exit 3')
exit_info.exit_code.should == 3
exit_info.should_not be_signaled
exit_info.backtrace.should_not be_nil
exit_info.backtrace.should_not be_empty
end
it "returns the expected information if the process exited because of a signal" do
exit_info = run_script_and_wait(
'STDIN.readline;' +
'require "rubygems";' +
'require "ffi";' +
'module MyLib;' +
'extend FFI::Library;' +
'ffi_lib "c";' +
'attach_function :abort, [], :void;' +
'end;' +
'MyLib.abort')
exit_info.should be_signaled
exit_info.backtrace.should =~ /abort/
end
it "ignores non-fatal signals" do
exit_info = run_script_and_wait('trap("INT") { }; STDIN.readline; exit 2') do
Process.kill('INT', @process.pid)
end
exit_info.exit_code.should == 2
exit_info.should_not be_signaled
exit_info.backtrace.should_not be_nil
exit_info.backtrace.should_not be_empty
end
it "returns information of the signal that aborted the process, not information of ignored signals" do
exit_info = run_script_and_wait(
'trap("INT") { };' +
'STDIN.readline;' +
'require "rubygems";' +
'require "ffi";' +
'module MyLib;' +
'extend FFI::Library;' +
'ffi_lib "c";' +
'attach_function :abort, [], :void;' +
'end;' +
'MyLib.abort'
) do
Process.kill('INT', @process.pid)
end
exit_info.should be_signaled
exit_info.backtrace.should =~ /abort/
end
end
end