zmachine 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ require 'zmachine/connection_manager'
2
+
3
+ include ZMachine
4
+
5
+ module TCPEchoServer
6
+ end
7
+
8
+ module TCPEchoClient
9
+ end
10
+
11
+ describe ConnectionManager do
12
+
13
+ context 'TCP' do
14
+ end
15
+
16
+ end
@@ -0,0 +1,56 @@
1
+ require 'zmachine/connection'
2
+
3
+ include ZMachine
4
+
5
+ describe Connection do
6
+
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)
11
+ end
12
+
13
+ after(:each) do
14
+ @client.close
15
+ @server.close
16
+ end
17
+
18
+ let(:data) { "foo" }
19
+
20
+ context 'triggers' do
21
+
22
+ it 'triggers acceptable' do
23
+ @server.channel.should_receive(:accept).once.and_call_original
24
+ @server.should_receive(:connection_accepted).once
25
+ connection = @server.acceptable!
26
+ expect(connection).to be_connected
27
+ end
28
+
29
+ it 'triggers connectable' do
30
+ @server.acceptable!
31
+ @client.channel.should_receive(:finish_connecting).once.and_call_original
32
+ @client.should_receive(:connection_completed).once
33
+ @client.connectable!
34
+ expect(@client).to be_connected
35
+ end
36
+
37
+ it 'triggers writable' do
38
+ @server.acceptable!
39
+ @client.connectable!
40
+ @client.send_data(data.to_java_bytes)
41
+ @client.channel.should_receive(:write_outbound_data).and_call_original
42
+ @client.writable!
43
+ end
44
+
45
+ it 'triggers readable' do
46
+ connection = @server.acceptable!
47
+ @client.connectable!
48
+ @client.send_data(data.to_java_bytes)
49
+ @client.writable!
50
+ connection.channel.should_receive(:read_inbound_data).and_call_original
51
+ connection.should_receive(:receive_data).once
52
+ connection.readable!
53
+ end
54
+
55
+ end
56
+ end
@@ -1,12 +1,4 @@
1
- require 'spec_helper'
2
- require 'lib/zmachine/hashed_wheel'
3
-
4
- describe ZMachine::HashedWheelTimeout do
5
- it 'calculates the stop index correctly'
6
- it 'calculates remaining rounds correctly'
7
- it 'can be cancelled'
8
- it 'supports an action'
9
- end
1
+ require 'zmachine/hashed_wheel'
10
2
 
11
3
  describe ZMachine::HashedWheel do
12
4
  let(:wheel) { ZMachine::HashedWheel.new(16, 100) }
@@ -35,15 +27,26 @@ describe ZMachine::HashedWheel do
35
27
  expect(timedout.length).to eq(1)
36
28
  end
37
29
 
38
- it 'calculates the timeouted set correctly' do
30
+ it 'calculates the timeout set correctly' do
39
31
  now = wheel.reset
40
32
  wheel.add 10
41
33
  wheel.add 40
42
34
  wheel.add 1900
43
35
  wheel.add 3300
44
36
  wheel.add 4000
45
- timedout = wheel.advance( now + 3900 * 1_000_000)
37
+ timedout = wheel.advance(now + 3900 * 1_000_000)
46
38
  expect(timedout).to be
47
39
  expect(timedout.length).to eq(4)
48
40
  end
49
- end
41
+
42
+ it 'cancels timers correctly' do
43
+ now = wheel.reset
44
+ t1 = wheel.add 90
45
+ t2 = wheel.add 110
46
+ t1.cancel
47
+ timedout = wheel.advance(now + 200 * 1_000_000)
48
+ expect(timedout).to eq([t2])
49
+ expect(timedout.length).to eq(1)
50
+ end
51
+
52
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,17 +1,25 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'rspec'
6
+ require 'simplecov'
7
+
8
+ class SimpleCov::Formatter::QualityFormatter
9
+ def format(result)
10
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
11
+ File.open("coverage/covered_percent", "w") do |f|
12
+ f.puts result.source_files.covered_percent.to_f
13
+ end
14
+ end
15
+ end
16
+
17
+ SimpleCov.formatter = SimpleCov::Formatter::QualityFormatter
18
+
19
+ SimpleCov.start do
20
+ add_filter '/spec/'
21
+ end
22
+
7
23
  RSpec.configure do |config|
8
24
  config.treat_symbols_as_metadata_keys_with_true_values = true
9
- config.run_all_when_everything_filtered = true
10
- config.filter_run :focus
11
-
12
- # Run specs in random order to surface order dependencies. If you find an
13
- # order dependency and want to debug it, you can fix the order by providing
14
- # the seed, which is printed after each run.
15
- # --seed 1234
16
- config.order = 'random'
17
25
  end
@@ -0,0 +1,109 @@
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
@@ -0,0 +1,113 @@
1
+ require 'zmachine/zmq_channel'
2
+
3
+ include ZMachine
4
+
5
+ describe ZMachine::ZMQChannel do
6
+
7
+ before(:each) do
8
+ @server = ZMQChannel.new(ZMQ::REP)
9
+ @port = @server.bind("tcp://*:*")
10
+ @client = ZMQChannel.new(ZMQ::REQ)
11
+ @client.connect("tcp://0.0.0.0:#{@port}")
12
+ end
13
+
14
+ after(:each) do
15
+ @client.close
16
+ @server.close
17
+ end
18
+
19
+ after(:all) do
20
+ ZMachine.context.destroy
21
+ end
22
+
23
+ let(:data) { "foo" }
24
+
25
+ context '#bind' do
26
+
27
+ it 'binds a server socket' do
28
+ expect(@server).to be_bound
29
+ end
30
+
31
+ end
32
+
33
+ context '#connect' do
34
+
35
+ it 'connects to a server socket' do
36
+ expect(@client).to be_connected
37
+ end
38
+
39
+ end
40
+
41
+ context '#send/recv' do
42
+
43
+ it 'writes outbound buffers to the socket' do
44
+ @client.send_data([data.to_java_bytes])
45
+ expect(@client.write_outbound_data).to eq(true)
46
+ end
47
+
48
+ it 'receives data sent from the client' do
49
+ @client.send_data([data.to_java_bytes])
50
+ @client.write_outbound_data
51
+ received = String.from_java_bytes(@server.read_inbound_data.first)
52
+ expect(received).to eq(data)
53
+ end
54
+
55
+ it 'receives data sent from the server' do
56
+ @client.send_data([data.to_java_bytes])
57
+ @client.write_outbound_data
58
+ received = String.from_java_bytes(@server.read_inbound_data.first)
59
+ @server.send_data([data.to_java_bytes])
60
+ @server.write_outbound_data
61
+ received = String.from_java_bytes(@client.read_inbound_data.first)
62
+ expect(received).to eq(data)
63
+ end
64
+
65
+ it 'sends and receives multipart messages' do
66
+ parts = %w(foo bar baz)
67
+ @client.send_data(parts.map(&:to_java_bytes))
68
+ @client.write_outbound_data
69
+ received = @server.read_inbound_data.map do |part|
70
+ String.from_java_bytes(part)
71
+ end
72
+ expect(received).to eq(parts)
73
+ end
74
+
75
+ it 'queues data when ZMQ is MIA' do
76
+ socket = @client.socket
77
+ # https://github.com/jruby/jruby/wiki/Persistence#deprecating-proxy-caching
78
+ Java::OrgZeromq::ZMQ::Socket.__persistent__ = true
79
+ socket.stub(:send_byte_array) { socket.unstub(:send_byte_array); raise ZMQException.new(nil) }
80
+ @client.send_data([data.to_java_bytes])
81
+ expect(@client.can_send?).to eq(true)
82
+ @client.write_outbound_data
83
+ expect(@client.can_send?).to eq(false)
84
+ end
85
+
86
+ end
87
+
88
+ context '#close' do
89
+
90
+ it 'closes the client connection' do
91
+ @client.close
92
+ expect(@client).to be_closed
93
+ end
94
+
95
+ it 'closes the server connection' do
96
+ @server.close
97
+ expect(@server).to be_closed
98
+ end
99
+
100
+ it 'closes the connection after writing' do
101
+ @client.send_data([data.to_java_bytes])
102
+ @client.close_after_writing
103
+ @client.write_outbound_data
104
+ expect(@client).not_to be_connected
105
+ end
106
+
107
+ end
108
+
109
+ it 'has no concept of a peer' do
110
+ expect{@client.peer}.to raise_error(RuntimeError)
111
+ end
112
+
113
+ end
data/zmachine.gemspec CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "zmachine"
5
- spec.version = "0.1.3"
5
+ spec.version = "0.2.0"
6
6
  spec.authors = ["LiquidM, Inc."]
7
- spec.email = ["tech@liquidm.com"]
7
+ spec.email = ["opensource@liquidm.com"]
8
8
  spec.description = %q{pure JRuby multi-threaded mostly EventMachine compatible event loop}
9
9
  spec.summary = %q{pure JRuby multi-threaded mostly EventMachine compatible event loop}
10
10
  spec.homepage = "https://github.com/madvertise/zmachine"
@@ -15,6 +15,8 @@ Gem::Specification.new do |spec|
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ["lib"]
17
17
 
18
+ spec.add_dependency "madvertise-ext"
19
+
18
20
  spec.add_development_dependency "bundler", "~> 1.3"
19
21
  spec.add_development_dependency "rake"
20
22
  spec.add_development_dependency "rspec"
metadata CHANGED
@@ -1,75 +1,95 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LiquidM, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-05 00:00:00.000000000 Z
11
+ date: 2013-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: madvertise-ext
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
15
20
  requirement: !ruby/object:Gem::Requirement
16
21
  requirements:
17
- - - ~>
22
+ - - '>='
18
23
  - !ruby/object:Gem::Version
19
- version: '1.3'
20
- type: :development
24
+ version: '0'
21
25
  prerelease: false
26
+ type: :runtime
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
22
29
  version_requirements: !ruby/object:Gem::Requirement
23
30
  requirements:
24
31
  - - ~>
25
32
  - !ruby/object:Gem::Version
26
33
  version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
34
  requirement: !ruby/object:Gem::Requirement
30
35
  requirements:
31
- - - ! '>='
36
+ - - ~>
32
37
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
38
+ version: '1.3'
35
39
  prerelease: false
40
+ type: :development
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
36
43
  version_requirements: !ruby/object:Gem::Requirement
37
44
  requirements:
38
- - - ! '>='
45
+ - - '>='
39
46
  - !ruby/object:Gem::Version
40
47
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
48
  requirement: !ruby/object:Gem::Requirement
44
49
  requirements:
45
- - - ! '>='
50
+ - - '>='
46
51
  - !ruby/object:Gem::Version
47
52
  version: '0'
48
- type: :development
49
53
  prerelease: false
54
+ type: :development
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
50
57
  version_requirements: !ruby/object:Gem::Requirement
51
58
  requirements:
52
- - - ! '>='
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
53
65
  - !ruby/object:Gem::Version
54
66
  version: '0'
67
+ prerelease: false
68
+ type: :development
55
69
  description: pure JRuby multi-threaded mostly EventMachine compatible event loop
56
70
  email:
57
- - tech@liquidm.com
71
+ - opensource@liquidm.com
58
72
  executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - .gitignore
77
+ - .rspec
78
+ - .ruby-version
63
79
  - Gemfile
64
80
  - LICENSE.txt
65
81
  - README.md
66
82
  - Rakefile
83
+ - benchmarks/benchmark.sh
84
+ - benchmarks/tcp_channel.rb
85
+ - benchmarks/zmq_channel.rb
67
86
  - echo_client.rb
68
87
  - echo_server.rb
69
88
  - lib/zmachine.rb
70
89
  - lib/zmachine/acceptor.rb
71
90
  - lib/zmachine/channel.rb
72
91
  - lib/zmachine/connection.rb
92
+ - lib/zmachine/connection_manager.rb
73
93
  - lib/zmachine/deferrable.rb
74
94
  - lib/zmachine/hashed_wheel.rb
75
95
  - lib/zmachine/jeromq-0.3.0-SNAPSHOT.jar
@@ -77,34 +97,42 @@ files:
77
97
  - lib/zmachine/tcp_channel.rb
78
98
  - lib/zmachine/timers.rb
79
99
  - lib/zmachine/zmq_channel.rb
100
+ - spec/connection_manager_spec.rb
101
+ - spec/connection_spec.rb
80
102
  - spec/hashed_wheel_spec.rb
81
103
  - spec/spec_helper.rb
104
+ - spec/tcp_channel_spec.rb
105
+ - spec/zmq_channel_spec.rb
82
106
  - zmachine.gemspec
83
107
  homepage: https://github.com/madvertise/zmachine
84
108
  licenses:
85
109
  - MIT
86
110
  metadata: {}
87
- post_install_message:
111
+ post_install_message:
88
112
  rdoc_options: []
89
113
  require_paths:
90
114
  - lib
91
115
  required_ruby_version: !ruby/object:Gem::Requirement
92
116
  requirements:
93
- - - ! '>='
117
+ - - '>='
94
118
  - !ruby/object:Gem::Version
95
119
  version: '0'
96
120
  required_rubygems_version: !ruby/object:Gem::Requirement
97
121
  requirements:
98
- - - ! '>='
122
+ - - '>='
99
123
  - !ruby/object:Gem::Version
100
124
  version: '0'
101
125
  requirements: []
102
- rubyforge_project:
103
- rubygems_version: 2.0.6
104
- signing_key:
126
+ rubyforge_project:
127
+ rubygems_version: 2.1.9
128
+ signing_key:
105
129
  specification_version: 4
106
130
  summary: pure JRuby multi-threaded mostly EventMachine compatible event loop
107
131
  test_files:
132
+ - spec/connection_manager_spec.rb
133
+ - spec/connection_spec.rb
108
134
  - spec/hashed_wheel_spec.rb
109
135
  - spec/spec_helper.rb
110
- has_rdoc:
136
+ - spec/tcp_channel_spec.rb
137
+ - spec/zmq_channel_spec.rb
138
+ has_rdoc: