arachni-rpc 0.1.3 → 0.2.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,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arachni::RPC::Exceptions do
4
+
5
+ describe '#rpc_exception?' do
6
+ context 'for RPC exceptions' do
7
+ subject { described_class::InvalidMethod.new.rpc_exception? }
8
+ it { should be_true }
9
+ end
10
+
11
+ context 'for other exceptions' do
12
+ subject { ::Exception.new.rpc_connection_error? }
13
+ it { should be_false }
14
+ end
15
+ end
16
+
17
+ describe '#rpc_connection_error?' do
18
+ context 'for ConnectionError' do
19
+ subject { described_class::ConnectionError.new.rpc_connection_error? }
20
+ it { should be_true }
21
+ end
22
+
23
+ context 'for other exceptions' do
24
+ subject { described_class::InvalidMethod.new.rpc_connection_error? }
25
+ it { should be_false }
26
+ end
27
+ end
28
+
29
+ describe '#rpc_remote_exception?' do
30
+ context 'for RemoteException' do
31
+ subject { described_class::RemoteException.new.rpc_remote_exception? }
32
+ it { should be_true }
33
+ end
34
+
35
+ context 'for other exceptions' do
36
+ subject { described_class::InvalidMethod.new.rpc_remote_exception? }
37
+ it { should be_false }
38
+ end
39
+ end
40
+
41
+ describe '#rpc_invalid_object_error?' do
42
+ context 'for invalid object RPC exceptions' do
43
+ subject { described_class::InvalidObject.new.rpc_invalid_object_error? }
44
+ it { should be_true }
45
+ end
46
+
47
+ context 'for other exceptions' do
48
+ subject { ::Exception.new.rpc_invalid_object_error? }
49
+ it { should be_false }
50
+ end
51
+ end
52
+
53
+ describe '#rpc_invalid_method_error?' do
54
+ context 'for invalid method RPC exceptions' do
55
+ subject { described_class::InvalidMethod.new.rpc_invalid_method_error? }
56
+ it { should be_true }
57
+ end
58
+
59
+ context 'for other exceptions' do
60
+ subject { ::Exception.new.rpc_invalid_method_error? }
61
+ it { should be_false }
62
+ end
63
+ end
64
+
65
+ describe '#rpc_invalid_token_error?' do
66
+ context 'for RPC exceptions' do
67
+ subject { described_class::InvalidToken.new.rpc_invalid_token_error? }
68
+ it { should be_true }
69
+ end
70
+
71
+ context 'for other exceptions' do
72
+ subject { ::Exception.new.rpc_invalid_token_error? }
73
+ it { should be_false }
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ class MyMessage < Arachni::RPC::Message
4
+ attr_accessor :foo
5
+ attr_accessor :boo
6
+
7
+ def transmit?( attr )
8
+ attr == :@boo
9
+ end
10
+ end
11
+
12
+ describe Arachni::RPC::Message do
13
+ let(:options) { { foo: 'foo val', boo: 'boo val' }}
14
+ subject { MyMessage.new( options ) }
15
+
16
+ describe '#initialize' do
17
+ it 'sets attributes' do
18
+ subject.foo == options[:foo]
19
+ subject.boo == options[:boo]
20
+ end
21
+ end
22
+
23
+ describe '#merge!' do
24
+ it 'assigns the attribute values of the provided object to self' do
25
+ opts = { foo: 'my foo' }
26
+ my_msg = MyMessage.new( opts )
27
+
28
+ subject.merge!( my_msg )
29
+
30
+ subject.foo == opts[:foo]
31
+ subject.boo == options[:boo]
32
+ end
33
+ end
34
+
35
+ describe '#prepare_for_tx' do
36
+ it 'converts self into a hash' do
37
+ subject.prepare_for_tx.class.should == Hash
38
+ end
39
+
40
+ it 'skips attributes based on #transmit?' do
41
+ subject.prepare_for_tx.should include 'boo'
42
+ subject.prepare_for_tx.should_not include 'callback_id'
43
+ subject.prepare_for_tx.should_not include 'foo'
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ class Translator < Arachni::RPC::Proxy
4
+
5
+ translate :foo do |response|
6
+ response.map(&:to_s)
7
+ end
8
+
9
+ translate :delay do |response, arguments|
10
+ [arguments, response.map(&:to_s)]
11
+ end
12
+
13
+ end
14
+
15
+ describe Arachni::RPC::Proxy do
16
+
17
+ def wait
18
+ Arachni::Reactor.global.wait rescue Arachni::Reactor::Error::NotRunning
19
+ end
20
+
21
+ before(:each) do
22
+ if Arachni::Reactor.global.running?
23
+ Arachni::Reactor.stop
24
+ end
25
+
26
+ Arachni::Reactor.global.run_in_thread
27
+ end
28
+
29
+ let(:translated_arguments) do
30
+ arguments.map(&:to_s)
31
+ end
32
+ let(:arguments) do
33
+ [
34
+ 'one',
35
+ 2,
36
+ { three: 3 },
37
+ [ 4 ]
38
+ ]
39
+ end
40
+ let(:reactor) { Arachni::Reactor.global }
41
+ let(:client) { start_client( rpc_opts ) }
42
+ let(:handler) { 'test' }
43
+ let(:translator) { Translator.new( client, handler ) }
44
+ subject do
45
+ Arachni::RPC::Proxy.new( client, handler )
46
+ end
47
+
48
+ it 'forwards synchronous calls' do
49
+ subject.foo( arguments ).should == arguments
50
+ end
51
+
52
+ it 'forwards synchronous calls' do
53
+ response = nil
54
+ subject.foo( arguments ) do |res|
55
+ response = res
56
+ Arachni::Reactor.stop
57
+ end
58
+ wait
59
+
60
+ response.should == arguments
61
+ end
62
+
63
+ describe '.translate' do
64
+ context 'when a synchronous call' do
65
+ context 'does not return an exception' do
66
+ it 'returns the translated result' do
67
+ translator.foo( arguments ).should == translated_arguments
68
+ end
69
+ end
70
+
71
+ context 'returns an exception' do
72
+ it 'returns the exception'
73
+ end
74
+ end
75
+
76
+ context 'when an asynchronous call' do
77
+ context 'does not result in an exception' do
78
+ it 'calls the block with the translated result' do
79
+ response = nil
80
+ translator.foo( arguments ) do |res|
81
+ response = res
82
+ Arachni::Reactor.stop
83
+ end
84
+ wait
85
+
86
+ response.should == translated_arguments
87
+ end
88
+ end
89
+
90
+ context 'results in an exception' do
91
+ it 'calls the block with the exception'
92
+ end
93
+ end
94
+
95
+ it 'passes the method arguments to the translator' do
96
+ translator.delay( arguments ).should == [arguments, translated_arguments]
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arachni::RPC::Request do
4
+ subject { described_class.new }
5
+
6
+ describe '#message' do
7
+ it 'should be an accessor' do
8
+ subject.message = 'test'
9
+ subject.message.should == 'test'
10
+ end
11
+ end
12
+
13
+ describe '#args' do
14
+ it 'should be an accessor' do
15
+ subject.args = %w(test)
16
+ subject.args.should == %w(test)
17
+ end
18
+ end
19
+
20
+ describe '#token' do
21
+ it 'should be an accessor' do
22
+ subject.token = 'blah'
23
+ subject.token.should == 'blah'
24
+ end
25
+ end
26
+
27
+ describe '#callback' do
28
+ it 'should be an accessor' do
29
+ called = false
30
+ subject.callback = proc { called = true }
31
+ subject.callback.call
32
+ called.should be_true
33
+ end
34
+ end
35
+
36
+ describe '#prepare_for_tx' do
37
+ it 'should convert the request to a hash ready for transmission' do
38
+ subject.prepare_for_tx.should be_empty
39
+
40
+ described_class.new(
41
+ message: 'obj.method',
42
+ args: %w(test),
43
+ token: 'mytoken',
44
+ callback: proc{}
45
+ ).prepare_for_tx.should =={
46
+ 'args' => %w(test),
47
+ 'message' => 'obj.method',
48
+ 'token' => 'mytoken'
49
+ }
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arachni::RPC::Response do
4
+ subject { described_class.new }
5
+
6
+ describe '#obj' do
7
+ it 'should be an accessor' do
8
+ subject.obj = 'test'
9
+ subject.obj.should == 'test'
10
+ end
11
+ end
12
+
13
+ describe '#exception' do
14
+ it 'should be an accessor' do
15
+ subject.exception = 'test'
16
+ subject.exception.should == 'test'
17
+ end
18
+ end
19
+
20
+ describe '#exception?' do
21
+ context 'when #exception is not set' do
22
+ it 'returns false' do
23
+ subject.exception?.should be_false
24
+ end
25
+ end
26
+
27
+ context 'when #exception is set' do
28
+ it 'returns true' do
29
+ subject.exception = 'stuff'
30
+ subject.exception?.should be_true
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#async?' do
36
+ context 'by default' do
37
+ it 'should return false' do
38
+ subject.async?.should be_false
39
+ end
40
+ end
41
+
42
+ context 'after #async!' do
43
+ it 'should return false' do
44
+ subject.async!
45
+ subject.async?.should be_true
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ class Arachni::RPC::Server
4
+ public :async?, :async_check, :object_exist?, :public_method?
5
+ attr_accessor :proxy
6
+ end
7
+
8
+ describe Arachni::RPC::Server do
9
+ let(:options) { rpc_opts.merge( port: 7333 ) }
10
+ subject { start_server( options, true ) }
11
+
12
+ describe '#initialize' do
13
+ it 'should be able to properly setup class options' do
14
+ subject.opts.should == options
15
+ end
16
+
17
+ context 'when passed no connection information' do
18
+ it 'raises ArgumentError' do
19
+ begin
20
+ described_class.new({})
21
+ rescue => e
22
+ e.should be_kind_of ArgumentError
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'when passed a host but not a port' do
28
+ it 'raises ArgumentError' do
29
+ begin
30
+ described_class.new( host: 'test' )
31
+ rescue => e
32
+ e.should be_kind_of ArgumentError
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'when passed a port but not a host' do
38
+ it 'raises ArgumentError' do
39
+ begin
40
+ described_class.new( port: 9999 )
41
+ rescue => e
42
+ e.should be_kind_of ArgumentError
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'when passed an invalid port' do
48
+ it 'raises ArgumentError' do
49
+ begin
50
+ described_class.new( host: 'tt', port: 'blah' )
51
+ rescue => e
52
+ e.should be_kind_of ArgumentError
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ it 'retains the supplied token' do
59
+ subject.token.should == options[:token]
60
+ end
61
+
62
+ it 'has a Logger' do
63
+ subject.logger.class.should == ::Logger
64
+ end
65
+
66
+ describe '#alive?' do
67
+ it 'returns true' do
68
+ subject.should be_alive
69
+ end
70
+ end
71
+
72
+ describe '#async?' do
73
+ context 'when a method is async' do
74
+ it 'returns true' do
75
+ subject.async?( 'test', 'delay' ).should be_true
76
+ end
77
+ end
78
+
79
+ context 'when a method is sync' do
80
+ it 'returns false' do
81
+ subject.async?( 'test', 'foo' ).should be_false
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#async_check' do
87
+ context 'when a method is async' do
88
+ it 'returns true' do
89
+ subject.async_check( Test.new.method( :delay ) ).should be_true
90
+ end
91
+ end
92
+
93
+ context 'when a method is sync' do
94
+ it 'returns false' do
95
+ subject.async_check( Test.new.method( :foo ) ).should be_false
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#object_exist?' do
101
+ context 'when an object exists' do
102
+ it 'returns true' do
103
+ subject.object_exist?( 'test' ).should be_true
104
+ end
105
+ end
106
+
107
+ context 'when an object does not exist' do
108
+ it 'returns false' do
109
+ subject.object_exist?( 'foo' ).should be_false
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#public_method?' do
115
+ context 'when a method is public' do
116
+ it 'returns true' do
117
+ subject.public_method?( 'test', 'foo' ).should be_true
118
+ end
119
+ end
120
+
121
+ context 'when a method is non-existent or not public' do
122
+ it 'returns false' do
123
+ subject.public_method?( 'test', 'bar' ).should be_false
124
+ end
125
+ end
126
+ end
127
+
128
+ end
129
+