sappho-socket 0.1.2 → 0.1.3
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/lib/sappho-socket/connected_socket.rb +40 -40
- data/lib/sappho-socket/mock_socket.rb +148 -148
- data/lib/sappho-socket/safe_server.rb +79 -77
- data/lib/sappho-socket/safe_socket.rb +88 -88
- data/lib/sappho-socket/version.rb +16 -16
- data/test/ruby/socket_test.rb +80 -80
- metadata +7 -7
@@ -1,40 +1,40 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
module Sappho
|
7
|
-
module Socket
|
8
|
-
|
9
|
-
require 'socket'
|
10
|
-
|
11
|
-
class ConnectedSocket
|
12
|
-
|
13
|
-
def attach socket
|
14
|
-
@socket = socket
|
15
|
-
end
|
16
|
-
|
17
|
-
def open host, port
|
18
|
-
@socket = TCPSocket.new host, port
|
19
|
-
end
|
20
|
-
|
21
|
-
def read bytesNeeded
|
22
|
-
@socket.read bytesNeeded
|
23
|
-
end
|
24
|
-
|
25
|
-
def write str
|
26
|
-
@socket.write str
|
27
|
-
end
|
28
|
-
|
29
|
-
def settle seconds
|
30
|
-
sleep seconds
|
31
|
-
end
|
32
|
-
|
33
|
-
def close
|
34
|
-
@socket.close
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
module Sappho
|
7
|
+
module Socket
|
8
|
+
|
9
|
+
require 'socket'
|
10
|
+
|
11
|
+
class ConnectedSocket
|
12
|
+
|
13
|
+
def attach socket
|
14
|
+
@socket = socket
|
15
|
+
end
|
16
|
+
|
17
|
+
def open host, port
|
18
|
+
@socket = TCPSocket.new host, port
|
19
|
+
end
|
20
|
+
|
21
|
+
def read bytesNeeded
|
22
|
+
@socket.read bytesNeeded
|
23
|
+
end
|
24
|
+
|
25
|
+
def write str
|
26
|
+
@socket.write str
|
27
|
+
end
|
28
|
+
|
29
|
+
def settle seconds
|
30
|
+
sleep seconds
|
31
|
+
end
|
32
|
+
|
33
|
+
def close
|
34
|
+
@socket.close
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -1,148 +1,148 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
module Sappho
|
7
|
-
module Socket
|
8
|
-
|
9
|
-
class MockSocket
|
10
|
-
|
11
|
-
def MockSocket.session session
|
12
|
-
@@session = session
|
13
|
-
end
|
14
|
-
|
15
|
-
def attach socket
|
16
|
-
@@session.action :attach, socket
|
17
|
-
end
|
18
|
-
|
19
|
-
def open host, port
|
20
|
-
@@session.action :open, host, port
|
21
|
-
end
|
22
|
-
|
23
|
-
def read bytesNeeded
|
24
|
-
@@session.action :read, bytesNeeded
|
25
|
-
end
|
26
|
-
|
27
|
-
def write str
|
28
|
-
@@session.action :write, str
|
29
|
-
end
|
30
|
-
|
31
|
-
def settle seconds
|
32
|
-
@@session.action :settle, seconds
|
33
|
-
end
|
34
|
-
|
35
|
-
def close
|
36
|
-
@@session.action :close
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
class MockSocketSession
|
42
|
-
|
43
|
-
def initialize activities
|
44
|
-
@activities = activities
|
45
|
-
@index = -1
|
46
|
-
end
|
47
|
-
|
48
|
-
def action expectedActivityType, *parameters
|
49
|
-
activity = @activities[@index += 1]
|
50
|
-
activityType = activity[:type]
|
51
|
-
unless activityType == expectedActivityType
|
52
|
-
raise MockSocketSessionError,
|
53
|
-
"Expected #{activityType} call but code under test asked for #{expectedActivityType}"
|
54
|
-
end
|
55
|
-
activity[:action].action *parameters
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
class MockSocketAttach
|
61
|
-
|
62
|
-
def action socket
|
63
|
-
raise MockSocketSessionError, 'Nil socket supplied' unless socket
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
class MockSocketOpen
|
69
|
-
|
70
|
-
def initialize host, port
|
71
|
-
@host = host
|
72
|
-
@port = port
|
73
|
-
end
|
74
|
-
|
75
|
-
def action host, port
|
76
|
-
unless host == @host and port == @port
|
77
|
-
raise MockSocketSessionError,
|
78
|
-
"Expected connection to #{@host}:#{@port} but got #{host}:#{port}"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
class MockSocketRead
|
85
|
-
|
86
|
-
def initialize str
|
87
|
-
@str = str
|
88
|
-
end
|
89
|
-
|
90
|
-
def action bytesNeeded
|
91
|
-
unless bytesNeeded >= @str.length
|
92
|
-
raise MockSocketSessionError,
|
93
|
-
"Expected read of #{@str.length} bytes but got request for #{bytesNeeded}"
|
94
|
-
end
|
95
|
-
raise Timeout::Error if bytesNeeded > @str.length
|
96
|
-
@str
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
class MockSocketWrite
|
102
|
-
|
103
|
-
def initialize str
|
104
|
-
@str = str
|
105
|
-
end
|
106
|
-
|
107
|
-
def action str
|
108
|
-
raise MockSocketSessionError, 'Unexpected string on write' unless str == @str
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
class MockSocketSettle
|
114
|
-
|
115
|
-
def initialize seconds
|
116
|
-
@seconds = seconds
|
117
|
-
end
|
118
|
-
|
119
|
-
def action seconds
|
120
|
-
unless seconds == @seconds
|
121
|
-
raise MockSocketSessionError,
|
122
|
-
"Expected settle sleep of #{@seconds} seconds but got request for #{seconds}"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
class MockSocketClose
|
129
|
-
|
130
|
-
def action
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
class MockSocketTimeout
|
136
|
-
|
137
|
-
def action *parameters
|
138
|
-
# ignore parameters - this can be used for any action
|
139
|
-
raise Timeout::Error
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
class MockSocketSessionError < RuntimeError
|
145
|
-
end
|
146
|
-
|
147
|
-
end
|
148
|
-
end
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
module Sappho
|
7
|
+
module Socket
|
8
|
+
|
9
|
+
class MockSocket
|
10
|
+
|
11
|
+
def MockSocket.session session
|
12
|
+
@@session = session
|
13
|
+
end
|
14
|
+
|
15
|
+
def attach socket
|
16
|
+
@@session.action :attach, socket
|
17
|
+
end
|
18
|
+
|
19
|
+
def open host, port
|
20
|
+
@@session.action :open, host, port
|
21
|
+
end
|
22
|
+
|
23
|
+
def read bytesNeeded
|
24
|
+
@@session.action :read, bytesNeeded
|
25
|
+
end
|
26
|
+
|
27
|
+
def write str
|
28
|
+
@@session.action :write, str
|
29
|
+
end
|
30
|
+
|
31
|
+
def settle seconds
|
32
|
+
@@session.action :settle, seconds
|
33
|
+
end
|
34
|
+
|
35
|
+
def close
|
36
|
+
@@session.action :close
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class MockSocketSession
|
42
|
+
|
43
|
+
def initialize activities
|
44
|
+
@activities = activities
|
45
|
+
@index = -1
|
46
|
+
end
|
47
|
+
|
48
|
+
def action expectedActivityType, *parameters
|
49
|
+
activity = @activities[@index += 1]
|
50
|
+
activityType = activity[:type]
|
51
|
+
unless activityType == expectedActivityType
|
52
|
+
raise MockSocketSessionError,
|
53
|
+
"Expected #{activityType} call but code under test asked for #{expectedActivityType}"
|
54
|
+
end
|
55
|
+
activity[:action].action *parameters
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class MockSocketAttach
|
61
|
+
|
62
|
+
def action socket
|
63
|
+
raise MockSocketSessionError, 'Nil socket supplied' unless socket
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class MockSocketOpen
|
69
|
+
|
70
|
+
def initialize host, port
|
71
|
+
@host = host
|
72
|
+
@port = port
|
73
|
+
end
|
74
|
+
|
75
|
+
def action host, port
|
76
|
+
unless host == @host and port == @port
|
77
|
+
raise MockSocketSessionError,
|
78
|
+
"Expected connection to #{@host}:#{@port} but got #{host}:#{port}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
class MockSocketRead
|
85
|
+
|
86
|
+
def initialize str
|
87
|
+
@str = str
|
88
|
+
end
|
89
|
+
|
90
|
+
def action bytesNeeded
|
91
|
+
unless bytesNeeded >= @str.length
|
92
|
+
raise MockSocketSessionError,
|
93
|
+
"Expected read of #{@str.length} bytes but got request for #{bytesNeeded}"
|
94
|
+
end
|
95
|
+
raise Timeout::Error if bytesNeeded > @str.length
|
96
|
+
@str
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
class MockSocketWrite
|
102
|
+
|
103
|
+
def initialize str
|
104
|
+
@str = str
|
105
|
+
end
|
106
|
+
|
107
|
+
def action str
|
108
|
+
raise MockSocketSessionError, 'Unexpected string on write' unless str == @str
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
class MockSocketSettle
|
114
|
+
|
115
|
+
def initialize seconds
|
116
|
+
@seconds = seconds
|
117
|
+
end
|
118
|
+
|
119
|
+
def action seconds
|
120
|
+
unless seconds == @seconds
|
121
|
+
raise MockSocketSessionError,
|
122
|
+
"Expected settle sleep of #{@seconds} seconds but got request for #{seconds}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
class MockSocketClose
|
129
|
+
|
130
|
+
def action
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
class MockSocketTimeout
|
136
|
+
|
137
|
+
def action *parameters
|
138
|
+
# ignore parameters - this can be used for any action
|
139
|
+
raise Timeout::Error
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
class MockSocketSessionError < RuntimeError
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -1,77 +1,79 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
module Sappho
|
7
|
-
module Socket
|
8
|
-
|
9
|
-
require 'sappho-basics/auto_flush_log'
|
10
|
-
require 'thread'
|
11
|
-
require 'socket'
|
12
|
-
|
13
|
-
class SafeServer
|
14
|
-
|
15
|
-
def initialize name, port, maxClients = 10, detailedLogging = false
|
16
|
-
@name = name
|
17
|
-
@port = port
|
18
|
-
@maxClients = maxClients
|
19
|
-
@detailedLogging = detailedLogging
|
20
|
-
@clients = {}
|
21
|
-
@mutex = Mutex.new
|
22
|
-
@log = Sappho::ApplicationAutoFlushLog.instance
|
23
|
-
end
|
24
|
-
|
25
|
-
def serve
|
26
|
-
Thread.new do
|
27
|
-
begin
|
28
|
-
@log.info "opening #{@name} server port #{@port}"
|
29
|
-
@server = TCPServer.open @port
|
30
|
-
@log.info "#{@name} server port #{@port} is now open"
|
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
|
-
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
module Sappho
|
7
|
+
module Socket
|
8
|
+
|
9
|
+
require 'sappho-basics/auto_flush_log'
|
10
|
+
require 'thread'
|
11
|
+
require 'socket'
|
12
|
+
|
13
|
+
class SafeServer
|
14
|
+
|
15
|
+
def initialize name, port, maxClients = 10, detailedLogging = false
|
16
|
+
@name = name
|
17
|
+
@port = port
|
18
|
+
@maxClients = maxClients
|
19
|
+
@detailedLogging = detailedLogging
|
20
|
+
@clients = {}
|
21
|
+
@mutex = Mutex.new
|
22
|
+
@log = Sappho::ApplicationAutoFlushLog.instance
|
23
|
+
end
|
24
|
+
|
25
|
+
def serve
|
26
|
+
Thread.new do
|
27
|
+
begin
|
28
|
+
@log.info "opening #{@name} server port #{@port}"
|
29
|
+
@server = TCPServer.open @port
|
30
|
+
@log.info "#{@name} server port #{@port} is now open"
|
31
|
+
loop do
|
32
|
+
if clientCount >= @maxClients
|
33
|
+
sleep 1
|
34
|
+
else
|
35
|
+
@log.info "listening for new clients on #{@name} server port #{@port}" if @detailedLogging
|
36
|
+
client = @server.accept
|
37
|
+
ip = client.getpeername
|
38
|
+
ip = (4 ... 8).map{|pos|ip[pos]}.join('.')
|
39
|
+
@mutex.synchronize do
|
40
|
+
@clients[client] = ip
|
41
|
+
log ip, 'connected' if @detailedLogging
|
42
|
+
end
|
43
|
+
Thread.new client, ip do | client, ip |
|
44
|
+
socket = SafeSocket.new 30
|
45
|
+
socket.attach client
|
46
|
+
begin
|
47
|
+
yield socket, ip, @name, @port
|
48
|
+
rescue => error
|
49
|
+
@log.error error
|
50
|
+
end
|
51
|
+
socket.close
|
52
|
+
@mutex.synchronize do
|
53
|
+
@clients.delete client
|
54
|
+
log ip, 'disconnected' if @detailedLogging
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def clientCount
|
64
|
+
@mutex.synchronize do
|
65
|
+
@clients.size
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def log ip, status
|
72
|
+
@log.info "client #{ip} #{status}"
|
73
|
+
@log.info "clients: #{@clients.size > 0 ? (@clients.collect{|client, ip| ip}).join(', ') : 'none'}"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -1,88 +1,88 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
module Sappho
|
7
|
-
module Socket
|
8
|
-
|
9
|
-
require 'timeout'
|
10
|
-
require 'socket'
|
11
|
-
require 'sappho-socket/connected_socket'
|
12
|
-
|
13
|
-
class SafeSocket
|
14
|
-
|
15
|
-
def SafeSocket.mock session, timeout = 10
|
16
|
-
MockSocket.session session
|
17
|
-
SafeSocket.new timeout, MockSocket.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize timeout = 10, socket = ConnectedSocket.new
|
21
|
-
@socket = socket
|
22
|
-
@open = false
|
23
|
-
@timeout = timeout
|
24
|
-
end
|
25
|
-
|
26
|
-
def attach socket
|
27
|
-
@socket.attach socket
|
28
|
-
@open = true
|
29
|
-
end
|
30
|
-
|
31
|
-
def open host, port
|
32
|
-
timeout @timeout do
|
33
|
-
@socket.open host, port
|
34
|
-
@open = true
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def setTimeout timeout
|
39
|
-
@timeout = timeout
|
40
|
-
end
|
41
|
-
|
42
|
-
def read bytesNeeded
|
43
|
-
check
|
44
|
-
timeout @timeout do
|
45
|
-
@socket.read bytesNeeded
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def write str
|
50
|
-
check
|
51
|
-
timeout @timeout do
|
52
|
-
@socket.write str
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def settle seconds
|
57
|
-
@socket.settle seconds
|
58
|
-
end
|
59
|
-
|
60
|
-
def close
|
61
|
-
actuallyClosed = false
|
62
|
-
begin
|
63
|
-
timeout @timeout do
|
64
|
-
if @open
|
65
|
-
@socket.close
|
66
|
-
actuallyClosed = true
|
67
|
-
end
|
68
|
-
end
|
69
|
-
rescue
|
70
|
-
end
|
71
|
-
@open = false
|
72
|
-
actuallyClosed
|
73
|
-
end
|
74
|
-
|
75
|
-
def open?
|
76
|
-
@open
|
77
|
-
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
def check
|
82
|
-
raise SocketError, 'Attempt to access unopened TCP/IP socket' unless @open
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
module Sappho
|
7
|
+
module Socket
|
8
|
+
|
9
|
+
require 'timeout'
|
10
|
+
require 'socket'
|
11
|
+
require 'sappho-socket/connected_socket'
|
12
|
+
|
13
|
+
class SafeSocket
|
14
|
+
|
15
|
+
def SafeSocket.mock session, timeout = 10
|
16
|
+
MockSocket.session session
|
17
|
+
SafeSocket.new timeout, MockSocket.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize timeout = 10, socket = ConnectedSocket.new
|
21
|
+
@socket = socket
|
22
|
+
@open = false
|
23
|
+
@timeout = timeout
|
24
|
+
end
|
25
|
+
|
26
|
+
def attach socket
|
27
|
+
@socket.attach socket
|
28
|
+
@open = true
|
29
|
+
end
|
30
|
+
|
31
|
+
def open host, port
|
32
|
+
timeout @timeout do
|
33
|
+
@socket.open host, port
|
34
|
+
@open = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def setTimeout timeout
|
39
|
+
@timeout = timeout
|
40
|
+
end
|
41
|
+
|
42
|
+
def read bytesNeeded
|
43
|
+
check
|
44
|
+
timeout @timeout do
|
45
|
+
@socket.read bytesNeeded
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def write str
|
50
|
+
check
|
51
|
+
timeout @timeout do
|
52
|
+
@socket.write str
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def settle seconds
|
57
|
+
@socket.settle seconds
|
58
|
+
end
|
59
|
+
|
60
|
+
def close
|
61
|
+
actuallyClosed = false
|
62
|
+
begin
|
63
|
+
timeout @timeout do
|
64
|
+
if @open
|
65
|
+
@socket.close
|
66
|
+
actuallyClosed = true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue
|
70
|
+
end
|
71
|
+
@open = false
|
72
|
+
actuallyClosed
|
73
|
+
end
|
74
|
+
|
75
|
+
def open?
|
76
|
+
@open
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def check
|
82
|
+
raise SocketError, 'Attempt to access unopened TCP/IP socket' unless @open
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
module Sappho
|
7
|
-
module Socket
|
8
|
-
NAME = 'sappho-socket'
|
9
|
-
VERSION = '0.1.
|
10
|
-
AUTHORS = ['Andrew Heald']
|
11
|
-
EMAILS = ['andrew@heald.co.uk']
|
12
|
-
HOMEPAGE = 'https://github.com/sappho/sappho-socket/wiki'
|
13
|
-
SUMMARY = 'Provides a usable TCP socket and mock implementation for testing'
|
14
|
-
DESCRIPTION = 'See the project home page for more information'
|
15
|
-
end
|
16
|
-
end
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
module Sappho
|
7
|
+
module Socket
|
8
|
+
NAME = 'sappho-socket'
|
9
|
+
VERSION = '0.1.3'
|
10
|
+
AUTHORS = ['Andrew Heald']
|
11
|
+
EMAILS = ['andrew@heald.co.uk']
|
12
|
+
HOMEPAGE = 'https://github.com/sappho/sappho-socket/wiki'
|
13
|
+
SUMMARY = 'Provides a usable TCP socket and mock implementation for testing'
|
14
|
+
DESCRIPTION = 'See the project home page for more information'
|
15
|
+
end
|
16
|
+
end
|
data/test/ruby/socket_test.rb
CHANGED
@@ -1,80 +1,80 @@
|
|
1
|
-
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
-
# Copyright 2012 Andrew Heald.
|
5
|
-
|
6
|
-
require "test/unit"
|
7
|
-
require 'sappho-socket/safe_socket'
|
8
|
-
require 'sappho-socket/mock_socket'
|
9
|
-
|
10
|
-
module Sappho
|
11
|
-
module Socket
|
12
|
-
|
13
|
-
class SocketTest < Test::Unit::TestCase
|
14
|
-
|
15
|
-
def test_session
|
16
|
-
@socket = SafeSocket.mock MockSocketSession.new [
|
17
|
-
{ :type => :open, :action => MockSocketOpen.new('localhost', 80) },
|
18
|
-
{ :type => :settle, :action => MockSocketSettle.new(42) },
|
19
|
-
{ :type => :read, :action => MockSocketRead.new('login: ') },
|
20
|
-
{ :type => :write, :action => MockSocketWrite.new('anon') },
|
21
|
-
{ :type => :write, :action => MockSocketTimeout.new },
|
22
|
-
{ :type => :close, :action => MockSocketClose.new },
|
23
|
-
{ :type => :attach, :action => MockSocketAttach.new },
|
24
|
-
{ :type => :attach, :action => MockSocketAttach.new },
|
25
|
-
{ :type => :close, :action => MockSocketClose.new } ]
|
26
|
-
# test of initiated connect
|
27
|
-
@socket.open 'localhost', 80
|
28
|
-
assert @socket.open?
|
29
|
-
@socket.settle 42
|
30
|
-
assert_equal 'login: ', @socket.read(7)
|
31
|
-
@socket.write 'anon'
|
32
|
-
assert_raises Timeout::Error do
|
33
|
-
@socket.write 'abc'
|
34
|
-
end
|
35
|
-
assert @socket.close
|
36
|
-
assert !@socket.open?
|
37
|
-
assert !@socket.close # a second close does not actually close anything
|
38
|
-
assert !@socket.open?
|
39
|
-
# this should fail because the socket has been closed
|
40
|
-
assert_raises SocketError do
|
41
|
-
@socket.read(1)
|
42
|
-
end
|
43
|
-
# test of attached socket (ie. one that has come from a client connection to a server)
|
44
|
-
assert_raises MockSocketSessionError do
|
45
|
-
@socket.attach nil
|
46
|
-
end
|
47
|
-
@socket.attach 1 # any object will do here to satisfy the nil test
|
48
|
-
assert @socket.close
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_attached_session
|
52
|
-
MockSocket.session MockSocketSession.new [
|
53
|
-
{ :type => :read, :action => MockSocketRead.new('xyz') },
|
54
|
-
{ :type => :write, :action => MockSocketWrite.new('pqr') },
|
55
|
-
{ :type => :close, :action => MockSocketClose.new } ]
|
56
|
-
@socket = SafeSocket.new
|
57
|
-
@socket.attach MockSocket.new
|
58
|
-
assert @socket.open?
|
59
|
-
assert_equal 'xyz', @socket.read(3)
|
60
|
-
@socket.write 'pqr'
|
61
|
-
start = Time.now
|
62
|
-
@socket.settle 1
|
63
|
-
elapsed = Time.now - start
|
64
|
-
assert elapsed > 0.99 and elapsed < 1.01
|
65
|
-
assert @socket.close
|
66
|
-
assert !@socket.open?
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_sequence_mismatch
|
70
|
-
@socket = SafeSocket.mock MockSocketSession.new [
|
71
|
-
{ :type => :open, :action => MockSocketOpen.new('localhost', 80) } ]
|
72
|
-
assert_raises MockSocketSessionError do
|
73
|
-
@socket.settle 42
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|
1
|
+
# See https://github.com/sappho/sappho-socket/wiki for project documentation.
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
4
|
+
# Copyright 2012 Andrew Heald.
|
5
|
+
|
6
|
+
require "test/unit"
|
7
|
+
require 'sappho-socket/safe_socket'
|
8
|
+
require 'sappho-socket/mock_socket'
|
9
|
+
|
10
|
+
module Sappho
|
11
|
+
module Socket
|
12
|
+
|
13
|
+
class SocketTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_session
|
16
|
+
@socket = SafeSocket.mock MockSocketSession.new [
|
17
|
+
{ :type => :open, :action => MockSocketOpen.new('localhost', 80) },
|
18
|
+
{ :type => :settle, :action => MockSocketSettle.new(42) },
|
19
|
+
{ :type => :read, :action => MockSocketRead.new('login: ') },
|
20
|
+
{ :type => :write, :action => MockSocketWrite.new('anon') },
|
21
|
+
{ :type => :write, :action => MockSocketTimeout.new },
|
22
|
+
{ :type => :close, :action => MockSocketClose.new },
|
23
|
+
{ :type => :attach, :action => MockSocketAttach.new },
|
24
|
+
{ :type => :attach, :action => MockSocketAttach.new },
|
25
|
+
{ :type => :close, :action => MockSocketClose.new } ]
|
26
|
+
# test of initiated connect
|
27
|
+
@socket.open 'localhost', 80
|
28
|
+
assert @socket.open?
|
29
|
+
@socket.settle 42
|
30
|
+
assert_equal 'login: ', @socket.read(7)
|
31
|
+
@socket.write 'anon'
|
32
|
+
assert_raises Timeout::Error do
|
33
|
+
@socket.write 'abc'
|
34
|
+
end
|
35
|
+
assert @socket.close
|
36
|
+
assert !@socket.open?
|
37
|
+
assert !@socket.close # a second close does not actually close anything
|
38
|
+
assert !@socket.open?
|
39
|
+
# this should fail because the socket has been closed
|
40
|
+
assert_raises SocketError do
|
41
|
+
@socket.read(1)
|
42
|
+
end
|
43
|
+
# test of attached socket (ie. one that has come from a client connection to a server)
|
44
|
+
assert_raises MockSocketSessionError do
|
45
|
+
@socket.attach nil
|
46
|
+
end
|
47
|
+
@socket.attach 1 # any object will do here to satisfy the nil test
|
48
|
+
assert @socket.close
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_attached_session
|
52
|
+
MockSocket.session MockSocketSession.new [
|
53
|
+
{ :type => :read, :action => MockSocketRead.new('xyz') },
|
54
|
+
{ :type => :write, :action => MockSocketWrite.new('pqr') },
|
55
|
+
{ :type => :close, :action => MockSocketClose.new } ]
|
56
|
+
@socket = SafeSocket.new
|
57
|
+
@socket.attach MockSocket.new
|
58
|
+
assert @socket.open?
|
59
|
+
assert_equal 'xyz', @socket.read(3)
|
60
|
+
@socket.write 'pqr'
|
61
|
+
start = Time.now
|
62
|
+
@socket.settle 1
|
63
|
+
elapsed = Time.now - start
|
64
|
+
assert elapsed > 0.99 and elapsed < 1.01
|
65
|
+
assert @socket.close
|
66
|
+
assert !@socket.open?
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_sequence_mismatch
|
70
|
+
@socket = SafeSocket.mock MockSocketSession.new [
|
71
|
+
{ :type => :open, :action => MockSocketOpen.new('localhost', 80) } ]
|
72
|
+
assert_raises MockSocketSessionError do
|
73
|
+
@socket.settle 42
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sappho-socket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andrew Heald
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-04-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rake
|
@@ -60,11 +60,11 @@ extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
61
61
|
|
62
62
|
files:
|
63
|
+
- lib/sappho-socket/version.rb
|
63
64
|
- lib/sappho-socket/connected_socket.rb
|
64
|
-
- lib/sappho-socket/mock_socket.rb
|
65
65
|
- lib/sappho-socket/safe_server.rb
|
66
|
+
- lib/sappho-socket/mock_socket.rb
|
66
67
|
- lib/sappho-socket/safe_socket.rb
|
67
|
-
- lib/sappho-socket/version.rb
|
68
68
|
- test/ruby/socket_test.rb
|
69
69
|
homepage: https://github.com/sappho/sappho-socket/wiki
|
70
70
|
licenses: []
|
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
95
|
requirements: []
|
96
96
|
|
97
97
|
rubyforge_project: sappho-socket
|
98
|
-
rubygems_version: 1.8.
|
98
|
+
rubygems_version: 1.8.17
|
99
99
|
signing_key:
|
100
100
|
specification_version: 3
|
101
101
|
summary: Provides a usable TCP socket and mock implementation for testing
|