sappho-socket 0.0.1

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.
@@ -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