sappho-socket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +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
+ require 'socket'
7
+
8
+ module Sappho
9
+ module 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
@@ -0,0 +1,150 @@
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 'timeout'
7
+
8
+ module Sappho
9
+ module Socket
10
+
11
+ class MockSocket
12
+
13
+ def MockSocket.session session
14
+ @@session = session
15
+ end
16
+
17
+ def attach socket
18
+ @@session.action :attach, socket
19
+ end
20
+
21
+ def open host, port
22
+ @@session.action :open, host, port
23
+ end
24
+
25
+ def read bytesNeeded
26
+ @@session.action :read, bytesNeeded
27
+ end
28
+
29
+ def write str
30
+ @@session.action :write, str
31
+ end
32
+
33
+ def settle seconds
34
+ @@session.action :settle, seconds
35
+ end
36
+
37
+ def close
38
+ @@session.action :close
39
+ end
40
+
41
+ end
42
+
43
+ class MockSocketSession
44
+
45
+ def initialize activities
46
+ @activities = activities
47
+ @index = -1
48
+ end
49
+
50
+ def action expectedActivityType, *parameters
51
+ activity = @activities[@index += 1]
52
+ activityType = activity[:type]
53
+ unless activityType == expectedActivityType
54
+ raise MockSocketSessionError,
55
+ "Expected #{activityType} call but code under test asked for #{expectedActivityType}"
56
+ end
57
+ activity[:action].action *parameters
58
+ end
59
+
60
+ end
61
+
62
+ class MockSocketAttach
63
+
64
+ def action socket
65
+ raise MockSocketSessionError, 'Nil socket supplied' unless socket
66
+ end
67
+
68
+ end
69
+
70
+ class MockSocketOpen
71
+
72
+ def initialize host, port
73
+ @host = host
74
+ @port = port
75
+ end
76
+
77
+ def action host, port
78
+ unless host == @host and port == @port
79
+ raise MockSocketSessionError,
80
+ "Expected connection to #{@host}:#{@port} but got #{host}:#{port}"
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ class MockSocketRead
87
+
88
+ def initialize str
89
+ @str = str
90
+ end
91
+
92
+ def action bytesNeeded
93
+ unless bytesNeeded >= @str.length
94
+ raise MockSocketSessionError,
95
+ "Expected read of #{@str.length} bytes but got request for #{bytesNeeded}"
96
+ end
97
+ raise Timeout::Error if bytesNeeded > @str.length
98
+ @str
99
+ end
100
+
101
+ end
102
+
103
+ class MockSocketWrite
104
+
105
+ def initialize str
106
+ @str = str
107
+ end
108
+
109
+ def action str
110
+ raise MockSocketSessionError, 'Unexpected string on write' unless str == @str
111
+ end
112
+
113
+ end
114
+
115
+ class MockSocketSettle
116
+
117
+ def initialize seconds
118
+ @seconds = seconds
119
+ end
120
+
121
+ def action seconds
122
+ unless seconds == @seconds
123
+ raise MockSocketSessionError,
124
+ "Expected settle sleep of #{@seconds} seconds but got request for #{seconds}"
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ class MockSocketClose
131
+
132
+ def action
133
+ end
134
+
135
+ end
136
+
137
+ class MockSocketTimeout
138
+
139
+ def action *parameters
140
+ # ignore parameters - this can be used for any action
141
+ raise Timeout::Error
142
+ end
143
+
144
+ end
145
+
146
+ class MockSocketSessionError < RuntimeError
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +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
+ require 'timeout'
7
+ require 'socket'
8
+ require 'sappho-socket/connected_socket'
9
+
10
+ module Sappho
11
+ module 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
@@ -0,0 +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.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
@@ -0,0 +1,75 @@
1
+ require "test/unit"
2
+ require 'sappho-socket/safe_socket'
3
+ require 'sappho-socket/mock_socket'
4
+
5
+ module Sappho
6
+ module Socket
7
+
8
+ class SocketTest < Test::Unit::TestCase
9
+
10
+ def test_session
11
+ @socket = SafeSocket.mock MockSocketSession.new [
12
+ { :type => :open, :action => MockSocketOpen.new('localhost', 80) },
13
+ { :type => :settle, :action => MockSocketSettle.new(42) },
14
+ { :type => :read, :action => MockSocketRead.new('login: ') },
15
+ { :type => :write, :action => MockSocketWrite.new('anon') },
16
+ { :type => :write, :action => MockSocketTimeout.new },
17
+ { :type => :close, :action => MockSocketClose.new },
18
+ { :type => :attach, :action => MockSocketAttach.new },
19
+ { :type => :attach, :action => MockSocketAttach.new },
20
+ { :type => :close, :action => MockSocketClose.new } ]
21
+ # test of initiated connect
22
+ @socket.open 'localhost', 80
23
+ assert @socket.open?
24
+ @socket.settle 42
25
+ assert_equal 'login: ', @socket.read(7)
26
+ @socket.write 'anon'
27
+ assert_raises Timeout::Error do
28
+ @socket.write 'abc'
29
+ end
30
+ assert @socket.close
31
+ assert !@socket.open?
32
+ assert !@socket.close # a second close does not actually close anything
33
+ assert !@socket.open?
34
+ # this should fail because the socket has been closed
35
+ assert_raises SocketError do
36
+ @socket.read(1)
37
+ end
38
+ # test of attached socket (ie. one that has come from a client connection to a server)
39
+ assert_raises MockSocketSessionError do
40
+ @socket.attach nil
41
+ end
42
+ @socket.attach 1 # any object will do here to satisfy the nil test
43
+ assert @socket.close
44
+ end
45
+
46
+ def test_attached_session
47
+ MockSocket.session MockSocketSession.new [
48
+ { :type => :read, :action => MockSocketRead.new('xyz') },
49
+ { :type => :write, :action => MockSocketWrite.new('pqr') },
50
+ { :type => :close, :action => MockSocketClose.new } ]
51
+ @socket = SafeSocket.new
52
+ @socket.attach MockSocket.new
53
+ assert @socket.open?
54
+ assert_equal 'xyz', @socket.read(3)
55
+ @socket.write 'pqr'
56
+ start = Time.now
57
+ @socket.settle 1
58
+ elapsed = Time.now - start
59
+ assert elapsed > 0.99 and elapsed < 1.01
60
+ assert @socket.close
61
+ assert !@socket.open?
62
+ end
63
+
64
+ def test_sequence_mismatch
65
+ @socket = SafeSocket.mock MockSocketSession.new [
66
+ { :type => :open, :action => MockSocketOpen.new('localhost', 80) } ]
67
+ assert_raises MockSocketSessionError do
68
+ @socket.settle 42
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sappho-socket
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Andrew Heald
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-13 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 11
29
+ segments:
30
+ - 0
31
+ - 9
32
+ - 2
33
+ - 2
34
+ version: 0.9.2.2
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: See the project home page for more information
38
+ email:
39
+ - andrew@heald.co.uk
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - lib/sappho-socket/version.rb
48
+ - lib/sappho-socket/connected_socket.rb
49
+ - lib/sappho-socket/mock_socket.rb
50
+ - lib/sappho-socket/safe_socket.rb
51
+ - test/ruby/socket_test.rb
52
+ homepage: https://github.com/sappho/sappho-socket/wiki
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project: sappho-socket
81
+ rubygems_version: 1.8.17
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Provides a usable TCP socket and mock implementation for testing
85
+ test_files:
86
+ - test/ruby/socket_test.rb