zmachine 0.2.1 → 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.
@@ -0,0 +1,178 @@
1
+ require 'zmachine/tcp_channel'
2
+ require 'zmachine/zmq_channel'
3
+
4
+ include ZMachine
5
+
6
+ shared_examples_for "a Channel" do
7
+
8
+ context '#bind' do
9
+
10
+ it 'binds a server socket' do
11
+ expect(@server).to be_bound
12
+ end
13
+
14
+ it 'accepts client connections' do
15
+ channel = @server.accept
16
+ expect(channel).to be_a(klass)
17
+ expect(channel).to be_connected
18
+ end
19
+
20
+ end
21
+
22
+ context '#connect' do
23
+
24
+ it 'connects to a pending server socket' do
25
+ expect(@client).to be_connection_pending
26
+ end
27
+
28
+ it 'connects to an accepted server socket' do
29
+ @server.accept
30
+ @client.finish_connecting
31
+ expect(@client).to be_connected
32
+ end
33
+
34
+ end
35
+
36
+ context '#send/recv' do
37
+
38
+ before(:each) do
39
+ @channel = @server.accept
40
+ @channel.raw = false
41
+ @client.finish_connecting
42
+ end
43
+
44
+ it 'writes outbound buffers to the socket' do
45
+ @client.send_data(data)
46
+ expect(@client.write_outbound_data).to eq(true)
47
+ end
48
+
49
+ it 'receives data sent from the client' do
50
+ @client.send_data(data)
51
+ @client.write_outbound_data
52
+ received = @channel.read_inbound_data
53
+ expect(received.to_s).to eq(data.to_s)
54
+ end
55
+
56
+ it 'receives data sent from the server' do
57
+ @client.send_data(data)
58
+ @client.write_outbound_data
59
+ received = @channel.read_inbound_data
60
+ @channel.send_data(data)
61
+ @channel.write_outbound_data
62
+ received = @client.read_inbound_data
63
+ expect(received.to_s).to eq(data.to_s)
64
+ end
65
+
66
+ end
67
+
68
+ context '#close' do
69
+
70
+ it 'closes the client connection' do
71
+ @client.close
72
+ expect(@client).to be_closed
73
+ end
74
+
75
+ it 'closes the server connection' do
76
+ @server.close
77
+ expect(@server).to be_closed
78
+ end
79
+
80
+ it 'closes the accepted connection' do
81
+ channel = @server.accept
82
+ channel.close
83
+ expect(channel).to be_closed
84
+ end
85
+
86
+ it 'closes the connection after writing' do
87
+ channel = @server.accept
88
+ @client.finish_connecting
89
+ @client.send_data(data)
90
+ @client.close(true)
91
+ expect(@client).to be_connected
92
+ @client.write_outbound_data
93
+ expect(@client).not_to be_connected
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ describe TCPChannel do
101
+
102
+ it_behaves_like "a Channel"
103
+
104
+ let(:klass) { TCPChannel }
105
+ let(:address) { "0.0.0.0" }
106
+ let(:port_or_type) { [51635, 51635] }
107
+
108
+ before(:each) do
109
+ @server = klass.new
110
+ @server.bind(address, port_or_type[0])
111
+ @client = klass.new
112
+ @client.connect(address, port_or_type[1])
113
+ end
114
+
115
+ after(:each) do
116
+ @client.close
117
+ @server.close
118
+ ZMachine.context.destroy
119
+ end
120
+
121
+ let(:data) { "foo".to_java_bytes }
122
+
123
+ it 'has the correct peer information' do
124
+ expect(@client.peer).to eq([port_or_type[0], address])
125
+ channel = @server.accept
126
+ @client.finish_connecting
127
+ socket = @client.socket.socket
128
+ expect(channel.peer).to eq([socket.local_port, socket.local_address.host_address])
129
+ end
130
+
131
+ context '#send/recv' do
132
+
133
+ it 'reads data after server has closed connection' do
134
+ channel = @server.accept
135
+ @client.finish_connecting
136
+ channel.send_data(data)
137
+ channel.close(true)
138
+ expect(channel).to be_connected
139
+ channel.write_outbound_data
140
+ expect(channel).not_to be_connected
141
+ expect(@client).to be_connected
142
+ @client.read_inbound_data
143
+ expect{@client.read_inbound_data}.to raise_error(IOException)
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+
150
+ describe ZMQChannel do
151
+
152
+ it_behaves_like "a Channel"
153
+
154
+ let(:klass) { ZMQChannel }
155
+ let(:address) { "tcp://0.0.0.0:51634" }
156
+ let(:port_or_type) { [ZMQ::REP, ZMQ::REQ] }
157
+
158
+ before(:each) do
159
+ @server = klass.new
160
+ @server.bind(address, port_or_type[0])
161
+ @client = klass.new
162
+ @client.connect(address, port_or_type[1])
163
+ @client.raw = false
164
+ end
165
+
166
+ after(:each) do
167
+ @client.close
168
+ @server.close
169
+ ZMachine.context.destroy
170
+ end
171
+
172
+ let(:data) { "foo".to_java_bytes }
173
+
174
+ it 'has no concept of a peer' do
175
+ expect{@client.peer}.to raise_error(RuntimeError)
176
+ end
177
+
178
+ end
@@ -2,17 +2,19 @@ require 'zmachine/connection'
2
2
 
3
3
  include ZMachine
4
4
 
5
- describe Connection do
5
+ shared_examples_for "a Connection" do
6
6
 
7
7
  before(:each) do
8
- @server = Connection.new.bind("0.0.0.0", 0)
9
- @port = @server.channel.socket.socket.local_port
10
- @client = Connection.new.connect("0.0.0.0", @port)
8
+ @server = Connection.new.bind(address, port_or_type[0]) { |c| @accepted = c }
9
+ @server.channel.raw = false
10
+ @client = Connection.new.connect(address, port_or_type[1]) { |c| @connection = c }
11
+ @client.channel.raw = false
11
12
  end
12
13
 
13
14
  after(:each) do
14
15
  @client.close
15
16
  @server.close
17
+ ZMachine.context.destroy
16
18
  end
17
19
 
18
20
  let(:data) { "foo" }
@@ -20,16 +22,17 @@ describe Connection do
20
22
  context 'triggers' do
21
23
 
22
24
  it 'triggers acceptable' do
23
- @server.channel.should_receive(:accept).once.and_call_original
24
- @server.should_receive(:connection_accepted).once
25
+ @server.channel.should_receive(:accept).and_call_original
25
26
  connection = @server.acceptable!
26
27
  expect(connection).to be_connected
28
+ expect(@accepted).to eq(connection)
29
+ expect(@connection).to be_a(Connection)
27
30
  end
28
31
 
29
32
  it 'triggers connectable' do
30
33
  @server.acceptable!
31
- @client.channel.should_receive(:finish_connecting).once.and_call_original
32
- @client.should_receive(:connection_completed).once
34
+ @client.channel.should_receive(:finish_connecting).and_call_original
35
+ @client.should_receive(:connection_completed)
33
36
  @client.connectable!
34
37
  expect(@client).to be_connected
35
38
  end
@@ -37,7 +40,7 @@ describe Connection do
37
40
  it 'triggers writable' do
38
41
  @server.acceptable!
39
42
  @client.connectable!
40
- @client.send_data(data.to_java_bytes)
43
+ @client.send_data(data)
41
44
  @client.channel.should_receive(:write_outbound_data).and_call_original
42
45
  @client.writable!
43
46
  end
@@ -45,12 +48,34 @@ describe Connection do
45
48
  it 'triggers readable' do
46
49
  connection = @server.acceptable!
47
50
  @client.connectable!
48
- @client.send_data(data.to_java_bytes)
51
+ @client.send_data(data)
49
52
  @client.writable!
50
53
  connection.channel.should_receive(:read_inbound_data).and_call_original
51
- connection.should_receive(:receive_data).once
54
+ connection.should_receive(:receive_data).with(data)
52
55
  connection.readable!
53
56
  end
54
57
 
55
58
  end
59
+
60
+ end
61
+
62
+ describe Connection do
63
+
64
+ context 'TCP' do
65
+
66
+ it_behaves_like "a Connection"
67
+
68
+ let(:address) { "0.0.0.0" }
69
+ let(:port_or_type) { [51635, 51635] }
70
+
71
+ end
72
+
73
+ context 'ZMQ' do
74
+
75
+ it_behaves_like "a Connection"
76
+
77
+ let(:address) { "tcp://0.0.0.0:51634" }
78
+ let(:port_or_type) { [ZMQ::REP, ZMQ::REQ] }
79
+
80
+ end
56
81
  end
@@ -1,7 +1,7 @@
1
1
  require 'zmachine/hashed_wheel'
2
2
 
3
3
  describe ZMachine::HashedWheel do
4
- let(:wheel) { ZMachine::HashedWheel.new(16, 100) }
4
+ let(:wheel) { ZMachine::HashedWheel.new(16, 0.1) }
5
5
 
6
6
  it 'returns a timeout on add' do
7
7
  expect(wheel.add(0)).to be_instance_of(ZMachine::HashedWheelTimeout)
@@ -9,11 +9,11 @@ describe ZMachine::HashedWheel do
9
9
 
10
10
  it 'adds timeouts to the correct slot' do
11
11
  wheel.add 0
12
- wheel.add 90
13
- wheel.add 110
14
- wheel.add 1000
15
- wheel.add 1600
16
- wheel.add 3200
12
+ wheel.add 0.090
13
+ wheel.add 0.110
14
+ wheel.add 1.000
15
+ wheel.add 1.600
16
+ wheel.add 3.200
17
17
  expect(wheel.slots[0].length).to eq(4)
18
18
  expect(wheel.slots[1].length).to eq(1)
19
19
  expect(wheel.slots[10].length).to eq(1)
@@ -21,19 +21,19 @@ describe ZMachine::HashedWheel do
21
21
 
22
22
  it 'times out same slot timeouts correctly' do
23
23
  now = wheel.reset
24
- wheel.add 10
25
- wheel.add 50
24
+ wheel.add 0.01
25
+ wheel.add 0.05
26
26
  timedout = wheel.advance(now + 30 * 1_000_000)
27
27
  expect(timedout.length).to eq(1)
28
28
  end
29
29
 
30
30
  it 'calculates the timeout set correctly' do
31
31
  now = wheel.reset
32
- wheel.add 10
33
- wheel.add 40
34
- wheel.add 1900
35
- wheel.add 3300
36
- wheel.add 4000
32
+ wheel.add 0.010
33
+ wheel.add 0.040
34
+ wheel.add 1.900
35
+ wheel.add 3.300
36
+ wheel.add 4.000
37
37
  timedout = wheel.advance(now + 3900 * 1_000_000)
38
38
  expect(timedout).to be
39
39
  expect(timedout.length).to eq(4)
@@ -41,8 +41,8 @@ describe ZMachine::HashedWheel do
41
41
 
42
42
  it 'cancels timers correctly' do
43
43
  now = wheel.reset
44
- t1 = wheel.add 90
45
- t2 = wheel.add 110
44
+ t1 = wheel.add 0.090
45
+ t2 = wheel.add 0.110
46
46
  t1.cancel
47
47
  timedout = wheel.advance(now + 200 * 1_000_000)
48
48
  expect(timedout).to eq([t2])
@@ -0,0 +1,32 @@
1
+ require "socket"
2
+
3
+ module EchoMock
4
+ def self.start(port = 6380)
5
+ server = TCPServer.new("127.0.0.1", port)
6
+ loop do
7
+ session = server.accept
8
+ while line = session.gets
9
+ session.write(line)
10
+ session.write("\r\n")
11
+ end
12
+ end
13
+ end
14
+
15
+ module Helper
16
+ def echo_mock
17
+ begin
18
+ pid = fork do
19
+ trap("TERM") { exit }
20
+ EchoMock.start
21
+ end
22
+ sleep 1 # Give time for the socket to start listening.
23
+ yield
24
+ ensure
25
+ if pid
26
+ Process.kill("TERM", pid)
27
+ Process.wait(pid)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
data/zmachine.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "zmachine"
5
- spec.version = "0.2.1"
5
+ spec.version = "0.3.0"
6
6
  spec.authors = ["LiquidM, Inc."]
7
7
  spec.email = ["opensource@liquidm.com"]
8
8
  spec.description = %q{pure JRuby multi-threaded mostly EventMachine compatible event loop}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LiquidM, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-25 00:00:00.000000000 Z
11
+ date: 2013-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid-ext
@@ -42,8 +42,8 @@ files:
42
42
  - benchmarks/benchmark.sh
43
43
  - benchmarks/tcp_channel.rb
44
44
  - benchmarks/zmq_channel.rb
45
- - echo_client.rb
46
- - echo_server.rb
45
+ - examples/echo_client.rb
46
+ - examples/echo_server.rb
47
47
  - lib/zmachine.rb
48
48
  - lib/zmachine/acceptor.rb
49
49
  - lib/zmachine/channel.rb
@@ -51,17 +51,17 @@ files:
51
51
  - lib/zmachine/connection_manager.rb
52
52
  - lib/zmachine/deferrable.rb
53
53
  - lib/zmachine/hashed_wheel.rb
54
- - lib/zmachine/jeromq-0.3.0-SNAPSHOT.jar
54
+ - lib/zmachine/jeromq-0.3.2-SNAPSHOT.jar
55
55
  - lib/zmachine/reactor.rb
56
56
  - lib/zmachine/tcp_channel.rb
57
57
  - lib/zmachine/timers.rb
58
58
  - lib/zmachine/zmq_channel.rb
59
+ - spec/channel_spec.rb
59
60
  - spec/connection_manager_spec.rb
60
61
  - spec/connection_spec.rb
61
62
  - spec/hashed_wheel_spec.rb
62
63
  - spec/spec_helper.rb
63
- - spec/tcp_channel_spec.rb
64
- - spec/zmq_channel_spec.rb
64
+ - spec/support/echo_mock.rb
65
65
  - zmachine.gemspec
66
66
  homepage: https://github.com/liquidm/zmachine
67
67
  licenses:
@@ -88,10 +88,10 @@ signing_key:
88
88
  specification_version: 4
89
89
  summary: pure JRuby multi-threaded mostly EventMachine compatible event loop
90
90
  test_files:
91
+ - spec/channel_spec.rb
91
92
  - spec/connection_manager_spec.rb
92
93
  - spec/connection_spec.rb
93
94
  - spec/hashed_wheel_spec.rb
94
95
  - spec/spec_helper.rb
95
- - spec/tcp_channel_spec.rb
96
- - spec/zmq_channel_spec.rb
96
+ - spec/support/echo_mock.rb
97
97
  has_rdoc:
Binary file
@@ -1,109 +0,0 @@
1
- require 'zmachine/tcp_channel'
2
-
3
- include ZMachine
4
-
5
- describe ZMachine::TCPChannel do
6
-
7
- before(:each) do
8
- @server = TCPChannel.new
9
- @server.bind("0.0.0.0", 0)
10
- @port = @server.socket.socket.local_port
11
- @client = TCPChannel.new
12
- @client.connect("0.0.0.0", @port)
13
- end
14
-
15
- after(:each) do
16
- @client.close
17
- @server.close
18
- end
19
-
20
- let(:data) { "foo" }
21
-
22
- context '#bind' do
23
-
24
- it 'binds a server socket' do
25
- expect(@server).to be_bound
26
- end
27
-
28
- it 'accepts client connections' do
29
- channel = @server.accept
30
- expect(channel).to be_a(TCPChannel)
31
- expect(channel).to be_connected
32
- end
33
-
34
- end
35
-
36
- context '#connect' do
37
-
38
- it 'connects to a pending server socket' do
39
- expect(@client).to be_connection_pending
40
- end
41
-
42
- it 'connects to an accepted server socket' do
43
- @server.accept
44
- @client.finish_connecting
45
- expect(@client).to be_connected
46
- end
47
-
48
- end
49
-
50
- context '#send/recv' do
51
-
52
- before(:each) do
53
- @channel = @server.accept
54
- @client.finish_connecting
55
- @client.send_data(data.to_java_bytes)
56
- end
57
-
58
- it 'writes outbound buffers to the socket' do
59
- expect(@client.write_outbound_data).to eq(true)
60
- end
61
-
62
- it 'receives data sent from the client' do
63
- @client.write_outbound_data
64
- received = @channel.read_inbound_data
65
- expect(received).to eq(data)
66
- end
67
-
68
- it 'receives data sent from the server' do
69
- @client.write_outbound_data
70
- received = @channel.read_inbound_data
71
- @channel.send_data(data.to_java_bytes)
72
- @channel.write_outbound_data
73
- received = @client.read_inbound_data
74
- expect(received).to eq(data)
75
- end
76
-
77
- end
78
-
79
- context '#close' do
80
-
81
- it 'closes the client connection' do
82
- @client.close
83
- expect(@client).to be_closed
84
- end
85
-
86
- it 'closes the server connection' do
87
- @server.close
88
- expect(@server).to be_closed
89
- end
90
-
91
- it 'closes the accepted connection' do
92
- channel = @server.accept
93
- channel.close
94
- expect(channel).to be_closed
95
- end
96
-
97
- it 'closes the connection after writing' do
98
- channel = @server.accept
99
- @client.finish_connecting
100
- @client.send_data(data.to_java_bytes)
101
- @client.close_after_writing
102
- expect(@client).to be_connected
103
- @client.write_outbound_data
104
- expect(@client).not_to be_connected
105
- end
106
-
107
- end
108
-
109
- end