win32-pipe 0.2.2 → 0.3.0
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.
- data/CHANGES +51 -46
- data/MANIFEST +17 -15
- data/README +52 -55
- data/Rakefile +68 -48
- data/examples/example_client.rb +29 -29
- data/examples/example_client_async.rb +82 -82
- data/examples/example_server.rb +32 -32
- data/examples/example_server_async.rb +100 -100
- data/lib/win32/pipe.rb +251 -254
- data/lib/win32/pipe/client.rb +65 -65
- data/lib/win32/pipe/server.rb +96 -96
- data/lib/win32/pipe/windows/constants.rb +37 -0
- data/lib/win32/pipe/windows/functions.rb +31 -0
- data/test/test_win32_pipe.rb +162 -126
- data/test/test_win32_pipe_client.rb +62 -60
- data/test/test_win32_pipe_server.rb +34 -34
- data/win32-pipe.gemspec +25 -25
- metadata +22 -10
data/lib/win32/pipe/client.rb
CHANGED
@@ -1,65 +1,65 @@
|
|
1
|
-
# The Win32 module serves as a namespace only
|
2
|
-
module Win32
|
3
|
-
|
4
|
-
# The Pipe::Client class encapsulates the client side of a named pipe
|
5
|
-
# connection.
|
6
|
-
#
|
7
|
-
class Pipe::Client < Pipe
|
8
|
-
|
9
|
-
# Create and return a new Pipe::Client instance. The +name+, +pipe_mode+,
|
10
|
-
# and +open_mode+ are passed to the Win32::Pipe superclass.
|
11
|
-
#
|
12
|
-
# The default +pipe_mode+ is NOWAIT.
|
13
|
-
#
|
14
|
-
# The default +open_mode+ is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH.
|
15
|
-
#
|
16
|
-
# In block form the client object is yield, and is automatically
|
17
|
-
# disconnected and closed at the end of the block.
|
18
|
-
#
|
19
|
-
# Example:
|
20
|
-
#
|
21
|
-
# require 'win32/pipe'
|
22
|
-
#
|
23
|
-
# Pipe::Client.new('foo') do |pipe|
|
24
|
-
# puts "Connected..."
|
25
|
-
# pipe.write("Ruby rocks!")
|
26
|
-
# data = pipe.read
|
27
|
-
# puts "Got [#{data}] back from pipe server"
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE)
|
31
|
-
super(name, pipe_mode, open_mode)
|
32
|
-
|
33
|
-
@pipe = CreateFile(
|
34
|
-
@name,
|
35
|
-
GENERIC_READ | GENERIC_WRITE,
|
36
|
-
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
37
|
-
nil,
|
38
|
-
OPEN_EXISTING,
|
39
|
-
@open_mode,
|
40
|
-
|
41
|
-
)
|
42
|
-
|
43
|
-
error = GetLastError()
|
44
|
-
|
45
|
-
if error == ERROR_PIPE_BUSY
|
46
|
-
unless WaitNamedPipe(@name, NMPWAIT_WAIT_FOREVER)
|
47
|
-
raise
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
if @pipe == INVALID_HANDLE_VALUE
|
52
|
-
raise
|
53
|
-
end
|
54
|
-
|
55
|
-
if block_given?
|
56
|
-
begin
|
57
|
-
yield self
|
58
|
-
ensure
|
59
|
-
disconnect
|
60
|
-
close
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
1
|
+
# The Win32 module serves as a namespace only
|
2
|
+
module Win32
|
3
|
+
|
4
|
+
# The Pipe::Client class encapsulates the client side of a named pipe
|
5
|
+
# connection.
|
6
|
+
#
|
7
|
+
class Pipe::Client < Pipe
|
8
|
+
|
9
|
+
# Create and return a new Pipe::Client instance. The +name+, +pipe_mode+,
|
10
|
+
# and +open_mode+ are passed to the Win32::Pipe superclass.
|
11
|
+
#
|
12
|
+
# The default +pipe_mode+ is NOWAIT.
|
13
|
+
#
|
14
|
+
# The default +open_mode+ is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH.
|
15
|
+
#
|
16
|
+
# In block form the client object is yield, and is automatically
|
17
|
+
# disconnected and closed at the end of the block.
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
#
|
21
|
+
# require 'win32/pipe'
|
22
|
+
#
|
23
|
+
# Pipe::Client.new('foo') do |pipe|
|
24
|
+
# puts "Connected..."
|
25
|
+
# pipe.write("Ruby rocks!")
|
26
|
+
# data = pipe.read
|
27
|
+
# puts "Got [#{data}] back from pipe server"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE)
|
31
|
+
super(name, pipe_mode, open_mode)
|
32
|
+
|
33
|
+
@pipe = CreateFile(
|
34
|
+
@name,
|
35
|
+
GENERIC_READ | GENERIC_WRITE,
|
36
|
+
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
37
|
+
nil,
|
38
|
+
OPEN_EXISTING,
|
39
|
+
@open_mode,
|
40
|
+
0
|
41
|
+
)
|
42
|
+
|
43
|
+
error = GetLastError()
|
44
|
+
|
45
|
+
if error == ERROR_PIPE_BUSY
|
46
|
+
unless WaitNamedPipe(@name, NMPWAIT_WAIT_FOREVER)
|
47
|
+
raise SystemCallError.new("WaitNamedPipe", FFI.errno)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if @pipe == INVALID_HANDLE_VALUE
|
52
|
+
raise SystemCallError.new("CreateFile", error)
|
53
|
+
end
|
54
|
+
|
55
|
+
if block_given?
|
56
|
+
begin
|
57
|
+
yield self
|
58
|
+
ensure
|
59
|
+
disconnect
|
60
|
+
close
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/win32/pipe/server.rb
CHANGED
@@ -1,96 +1,96 @@
|
|
1
|
-
# The Win32 module serves as a namespace only.
|
2
|
-
module Win32
|
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
|
-
end
|
1
|
+
# The Win32 module serves as a namespace only.
|
2
|
+
module Win32
|
3
|
+
# The Pipe::Server class encapsulates the server side of a named pipe
|
4
|
+
# connection.
|
5
|
+
class Pipe::Server < Pipe
|
6
|
+
|
7
|
+
# Creates and returns a new Pipe::Server instance, using +name+ as the
|
8
|
+
# name for the pipe. Note that this does not actually connect the pipe.
|
9
|
+
# Use Pipe::Server#connect for that.
|
10
|
+
#
|
11
|
+
# The default pipe_mode is PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT.
|
12
|
+
#
|
13
|
+
# The default open_mode is Pipe::ACCESS_DUPLEX.
|
14
|
+
#--
|
15
|
+
# The default pipe_mode also happens to be 0.
|
16
|
+
#
|
17
|
+
def initialize(name, pipe_mode = 0, open_mode = Pipe::ACCESS_DUPLEX)
|
18
|
+
super(name, pipe_mode, open_mode)
|
19
|
+
|
20
|
+
@pipe = CreateNamedPipe(
|
21
|
+
@name,
|
22
|
+
@open_mode,
|
23
|
+
@pipe_mode,
|
24
|
+
PIPE_UNLIMITED_INSTANCES,
|
25
|
+
PIPE_BUFFER_SIZE,
|
26
|
+
PIPE_BUFFER_SIZE,
|
27
|
+
PIPE_TIMEOUT,
|
28
|
+
nil
|
29
|
+
)
|
30
|
+
|
31
|
+
if @pipe == INVALID_HANDLE_VALUE
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
if block_given?
|
36
|
+
begin
|
37
|
+
yield self
|
38
|
+
ensure
|
39
|
+
close
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Enables the named pipe server process to wait for a client process
|
45
|
+
# to connect to an instance of a named pipe. In other words, it puts
|
46
|
+
# the server in 'connection wait' status.
|
47
|
+
#
|
48
|
+
# In synchronous mode always returns true on success. In asynchronous
|
49
|
+
# mode returns true if there is pending IO, or false otherwise.
|
50
|
+
#
|
51
|
+
def connect
|
52
|
+
if @asynchronous
|
53
|
+
# An overlapped ConnectNamedPipe should return 0
|
54
|
+
if ConnectNamedPipe(@pipe, @overlapped)
|
55
|
+
raise SystemCallError.new("ConnectNamedPipe", FFI.errno)
|
56
|
+
end
|
57
|
+
|
58
|
+
error = GetLastError()
|
59
|
+
|
60
|
+
case error
|
61
|
+
when ERROR_IO_PENDING
|
62
|
+
@pending_io = true
|
63
|
+
when ERROR_PIPE_CONNECTED
|
64
|
+
unless SetEvent(@event)
|
65
|
+
raise Error, get_last_error(error)
|
66
|
+
end
|
67
|
+
when ERROR_PIPE_LISTENING
|
68
|
+
# Do nothing
|
69
|
+
else
|
70
|
+
raise Error, get_last_error(error)
|
71
|
+
end
|
72
|
+
|
73
|
+
if @pending_io
|
74
|
+
return false
|
75
|
+
else
|
76
|
+
return true
|
77
|
+
end
|
78
|
+
else
|
79
|
+
unless ConnectNamedPipe(@pipe, nil)
|
80
|
+
raise SystemCallError.new("ConnectNamedPipe", FFI.errno)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
return true
|
85
|
+
end
|
86
|
+
|
87
|
+
# Close the server. This will flush file buffers, disconnect the
|
88
|
+
# pipe, and close the pipe handle.
|
89
|
+
#
|
90
|
+
def close
|
91
|
+
FlushFileBuffers(@pipe)
|
92
|
+
DisconnectNamedPipe(@pipe)
|
93
|
+
super
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Windows
|
2
|
+
module Constants
|
3
|
+
PIPE_WAIT = 0x00000000
|
4
|
+
PIPE_NOWAIT = 0x00000001
|
5
|
+
PIPE_ACCESS_INBOUND = 0x00000001
|
6
|
+
PIPE_ACCESS_OUTBOUND = 0x00000002
|
7
|
+
PIPE_ACCESS_DUPLEX = 0x00000003
|
8
|
+
PIPE_TYPE_BYTE = 0x00000000
|
9
|
+
PIPE_TYPE_MESSAGE = 0x00000004
|
10
|
+
PIPE_READMODE_BYTE = 0x00000000
|
11
|
+
PIPE_READMODE_MESSAGE = 0x00000002
|
12
|
+
PIPE_CLIENT_END = 0x00000000
|
13
|
+
PIPE_SERVER_END = 0x00000001
|
14
|
+
|
15
|
+
PIPE_UNLIMITED_INSTANCES = 255
|
16
|
+
|
17
|
+
FILE_FLAG_OVERLAPPED = 0x40000000
|
18
|
+
FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000
|
19
|
+
FILE_FLAG_WRITE_THROUGH = 0x80000000
|
20
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
21
|
+
|
22
|
+
INFINITE = 0xFFFFFFFF
|
23
|
+
INVALID_HANDLE_VALUE = 0xFFFFFFFF
|
24
|
+
NMPWAIT_WAIT_FOREVER = 0xFFFFFFFF
|
25
|
+
ERROR_PIPE_BUSY = 231
|
26
|
+
ERROR_IO_PENDING = 997
|
27
|
+
|
28
|
+
WAIT_TIMEOUT = 0x102
|
29
|
+
WAIT_OBJECT_0 = 0
|
30
|
+
|
31
|
+
GENERIC_READ = 0x80000000
|
32
|
+
GENERIC_WRITE = 0x40000000
|
33
|
+
FILE_SHARE_READ = 1
|
34
|
+
FILE_SHARE_WRITE = 2
|
35
|
+
OPEN_EXISTING = 3
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Windows
|
4
|
+
module Functions
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib :kernel32
|
7
|
+
|
8
|
+
module FFI::Library
|
9
|
+
# Wrapper method for attach_function + private
|
10
|
+
def attach_pfunc(*args)
|
11
|
+
attach_function(*args)
|
12
|
+
private args[0]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attach_pfunc :CloseHandle, [:ulong], :bool
|
17
|
+
attach_pfunc :ConnectNamedPipe, [:ulong, :pointer], :bool
|
18
|
+
attach_pfunc :CreateEvent, :CreateEventA, [:pointer, :bool, :bool, :string], :ulong
|
19
|
+
attach_pfunc :CreateFile, :CreateFileA, [:string, :ulong, :ulong, :pointer, :ulong, :ulong, :ulong], :ulong
|
20
|
+
attach_pfunc :CreateNamedPipe, :CreateNamedPipeA, [:string, :ulong, :ulong, :ulong, :ulong, :ulong, :ulong, :pointer], :ulong
|
21
|
+
attach_pfunc :CreatePipe, [:pointer, :pointer, :pointer, :ulong], :bool
|
22
|
+
attach_pfunc :DisconnectNamedPipe, [:ulong], :bool
|
23
|
+
attach_pfunc :FlushFileBuffers, [:ulong], :bool
|
24
|
+
attach_pfunc :GetLastError, [], :ulong
|
25
|
+
attach_pfunc :GetOverlappedResult, [:ulong, :pointer, :pointer, :bool], :bool
|
26
|
+
attach_pfunc :ReadFile, [:ulong, :buffer_out, :ulong, :pointer, :pointer], :bool
|
27
|
+
attach_pfunc :WaitForSingleObject, [:ulong, :ulong], :ulong
|
28
|
+
attach_pfunc :WaitNamedPipe, :WaitNamedPipeA, [:string, :ulong], :bool
|
29
|
+
attach_pfunc :WriteFile, [:ulong, :buffer_in, :ulong, :pointer, :pointer], :bool
|
30
|
+
end
|
31
|
+
end
|
data/test/test_win32_pipe.rb
CHANGED
@@ -1,126 +1,162 @@
|
|
1
|
-
##########################################################################
|
2
|
-
# test_win32_pipe.rb
|
3
|
-
#
|
4
|
-
# Test suite for the win32-pipe library. This test suite should be run
|
5
|
-
# via the 'rake test' task.
|
6
|
-
##########################################################################
|
7
|
-
require '
|
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
|
-
end
|
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
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
@pipe
|
125
|
-
end
|
126
|
-
|
1
|
+
##########################################################################
|
2
|
+
# test_win32_pipe.rb
|
3
|
+
#
|
4
|
+
# Test suite for the win32-pipe library. This test suite should be run
|
5
|
+
# via the 'rake test' task.
|
6
|
+
##########################################################################
|
7
|
+
require 'test-unit'
|
8
|
+
require 'win32/pipe'
|
9
|
+
include Win32
|
10
|
+
|
11
|
+
class TC_Win32_Pipe < Test::Unit::TestCase
|
12
|
+
def setup
|
13
|
+
@pipe = Pipe.new('foo')
|
14
|
+
end
|
15
|
+
|
16
|
+
test "version is set to expected value" do
|
17
|
+
assert_equal('0.3.0', Pipe::VERSION)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "name method basic functionality" do
|
21
|
+
assert_respond_to(@pipe, :name)
|
22
|
+
assert_nothing_raised{ @pipe.name }
|
23
|
+
assert_kind_of(String, @pipe.name)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "name returns expected string" do
|
27
|
+
assert_equal("\\\\.\\pipe\\foo", @pipe.name)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "mode method basic functionality" do
|
31
|
+
assert_respond_to(@pipe, :pipe_mode)
|
32
|
+
assert_nothing_raised{ @pipe.pipe_mode }
|
33
|
+
assert_kind_of(Fixnum, @pipe.pipe_mode)
|
34
|
+
end
|
35
|
+
|
36
|
+
test "mode method returns expected value" do
|
37
|
+
assert_equal(Pipe::DEFAULT_PIPE_MODE, @pipe.pipe_mode)
|
38
|
+
end
|
39
|
+
|
40
|
+
test "open_mode basic functionality" do
|
41
|
+
assert_respond_to(@pipe, :open_mode)
|
42
|
+
assert_nothing_raised{ @pipe.open_mode }
|
43
|
+
assert_kind_of(Numeric, @pipe.open_mode)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "open_mode returns the expected value" do
|
47
|
+
assert_equal(Pipe::DEFAULT_OPEN_MODE, @pipe.open_mode)
|
48
|
+
end
|
49
|
+
|
50
|
+
test "buffer method basic functionality" do
|
51
|
+
assert_respond_to(@pipe, :buffer)
|
52
|
+
assert_nothing_raised{ @pipe.buffer }
|
53
|
+
end
|
54
|
+
|
55
|
+
test "size basic functionality" do
|
56
|
+
assert_respond_to(@pipe, :size)
|
57
|
+
assert_nothing_raised{ @pipe.size }
|
58
|
+
end
|
59
|
+
|
60
|
+
test "length is an alias for size" do
|
61
|
+
assert_respond_to(@pipe, :length)
|
62
|
+
assert_alias_method(@pipe, :length, :size)
|
63
|
+
end
|
64
|
+
|
65
|
+
test "pending method basic functionality" do
|
66
|
+
assert_respond_to(@pipe, :pending?)
|
67
|
+
assert_nothing_raised{ @pipe.pending? }
|
68
|
+
assert_boolean(@pipe.pending?)
|
69
|
+
end
|
70
|
+
|
71
|
+
test "pending method defaults to false" do
|
72
|
+
assert_false(@pipe.pending?)
|
73
|
+
end
|
74
|
+
|
75
|
+
test "asynchronous method basic functionality" do
|
76
|
+
assert_respond_to(@pipe, :asynchronous?)
|
77
|
+
assert_nothing_raised{ @pipe.asynchronous? }
|
78
|
+
assert_boolean(@pipe.asynchronous?)
|
79
|
+
end
|
80
|
+
|
81
|
+
test "asynchronous method defaults to false" do
|
82
|
+
assert_false(@pipe.asynchronous?)
|
83
|
+
end
|
84
|
+
|
85
|
+
test "read method basic functionality" do
|
86
|
+
assert_respond_to(@pipe, :read)
|
87
|
+
end
|
88
|
+
|
89
|
+
test "read method raises an error if there's nothing to read" do
|
90
|
+
assert_raises(Pipe::Error){ @pipe.read }
|
91
|
+
end
|
92
|
+
|
93
|
+
test "transfered method basic functionality" do
|
94
|
+
assert_respond_to(@pipe, :transferred)
|
95
|
+
assert_nothing_raised{ @pipe.transferred }
|
96
|
+
end
|
97
|
+
|
98
|
+
test "wait method basic functionality" do
|
99
|
+
assert_respond_to(@pipe, :wait)
|
100
|
+
end
|
101
|
+
|
102
|
+
test "wait method raises an error in blocking mode" do
|
103
|
+
assert_raises(Pipe::Error){ @pipe.wait }
|
104
|
+
end
|
105
|
+
|
106
|
+
test "write method basic functionality" do
|
107
|
+
assert_respond_to(@pipe, :write)
|
108
|
+
end
|
109
|
+
|
110
|
+
test "write method requires one argument" do
|
111
|
+
assert_raises(ArgumentError){ @pipe.write }
|
112
|
+
end
|
113
|
+
|
114
|
+
test "write method raises an error if there's nothing to write to" do
|
115
|
+
assert_raises(Pipe::Error){ @pipe.write("foo") }
|
116
|
+
end
|
117
|
+
|
118
|
+
test "disconnect method basic functionality" do
|
119
|
+
assert_respond_to(@pipe, :disconnect)
|
120
|
+
assert_nothing_raised{ @pipe.disconnect }
|
121
|
+
end
|
122
|
+
|
123
|
+
test "calling the disconnect method multiple times has no effect" do
|
124
|
+
assert_nothing_raised{ @pipe.disconnect; @pipe.disconnect }
|
125
|
+
end
|
126
|
+
|
127
|
+
test "close method basic functionality" do
|
128
|
+
assert_respond_to(@pipe, :close)
|
129
|
+
assert_nothing_raised{ @pipe.close }
|
130
|
+
end
|
131
|
+
|
132
|
+
test "calling close multiple times has no effect" do
|
133
|
+
assert_nothing_raised{ @pipe.close; @pipe.close }
|
134
|
+
end
|
135
|
+
|
136
|
+
test "pipe_mode constants" do
|
137
|
+
assert_not_nil(Pipe::WAIT)
|
138
|
+
assert_not_nil(Pipe::NOWAIT)
|
139
|
+
assert_not_nil(Pipe::TYPE_BYTE)
|
140
|
+
assert_not_nil(Pipe::TYPE_MESSAGE)
|
141
|
+
assert_not_nil(Pipe::READMODE_BYTE)
|
142
|
+
assert_not_nil(Pipe::READMODE_MESSAGE)
|
143
|
+
end
|
144
|
+
|
145
|
+
test "open_mode constants" do
|
146
|
+
assert_not_nil(Pipe::ACCESS_DUPLEX)
|
147
|
+
assert_not_nil(Pipe::ACCESS_INBOUND)
|
148
|
+
assert_not_nil(Pipe::ACCESS_OUTBOUND)
|
149
|
+
assert_not_nil(Pipe::FIRST_PIPE_INSTANCE)
|
150
|
+
assert_not_nil(Pipe::WRITE_THROUGH)
|
151
|
+
assert_not_nil(Pipe::OVERLAPPED)
|
152
|
+
end
|
153
|
+
|
154
|
+
test "other contants" do
|
155
|
+
assert_not_nil(Pipe::INFINITE)
|
156
|
+
end
|
157
|
+
|
158
|
+
def teardown
|
159
|
+
@pipe.close if @pipe
|
160
|
+
@pipe = nil
|
161
|
+
end
|
162
|
+
end
|