forward 0.3.3 → 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +0 -2
- data/README.md +24 -0
- data/Rakefile +3 -1
- data/bin/forward +1 -1
- data/forward.gemspec +17 -11
- data/lib/forward/api/resource.rb +51 -83
- data/lib/forward/api/tunnel.rb +41 -68
- data/lib/forward/api/user.rb +14 -11
- data/lib/forward/api.rb +7 -26
- data/lib/forward/cli.rb +55 -253
- data/lib/forward/command/account.rb +69 -0
- data/lib/forward/command/base.rb +62 -0
- data/lib/forward/command/config.rb +64 -0
- data/lib/forward/command/tunnel.rb +178 -0
- data/lib/forward/common.rb +44 -0
- data/lib/forward/config.rb +75 -118
- data/lib/forward/request.rb +72 -0
- data/lib/forward/socket.rb +125 -0
- data/lib/forward/static/app.rb +157 -0
- data/lib/forward/static/directory.erb +142 -0
- data/lib/forward/tunnel.rb +102 -40
- data/lib/forward/version.rb +1 -1
- data/lib/forward.rb +80 -63
- data/test/api/resource_test.rb +70 -54
- data/test/api/tunnel_test.rb +50 -51
- data/test/api/user_test.rb +33 -20
- data/test/cli_test.rb +0 -126
- data/test/command/account_test.rb +26 -0
- data/test/command/tunnel_test.rb +133 -0
- data/test/config_test.rb +103 -54
- data/test/forward_test.rb +47 -0
- data/test/test_helper.rb +35 -26
- data/test/tunnel_test.rb +50 -22
- metadata +210 -169
- data/forwardhq.crt +0 -112
- data/lib/forward/api/client_log.rb +0 -20
- data/lib/forward/api/tunnel_key.rb +0 -18
- data/lib/forward/client.rb +0 -110
- data/lib/forward/error.rb +0 -12
- data/test/api/tunnel_key_test.rb +0 -28
- data/test/api_test.rb +0 -0
- data/test/client_test.rb +0 -8
data/test/api/resource_test.rb
CHANGED
@@ -1,82 +1,98 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
describe Forward::
|
4
|
-
Api = Forward::Api
|
5
|
-
|
3
|
+
describe Forward::API::Resource do
|
6
4
|
before :each do
|
7
|
-
|
5
|
+
Forward::Config.accounts = { foo: 'abc123' }
|
6
|
+
Forward::Config.default_account = :foo
|
8
7
|
end
|
9
8
|
|
10
9
|
it 'builds http requests based on given method' do
|
11
|
-
resource
|
12
|
-
resource.uri = '/path'
|
10
|
+
resource = Forward::API::Resource.new
|
13
11
|
|
14
|
-
[ :get, :post, :
|
15
|
-
|
16
|
-
klass = eval("Net::HTTP::#{method.capitalize}")
|
17
|
-
request = resource.instance_variable_get('@request')
|
12
|
+
[ :get, :post, :delete ].each do |method|
|
13
|
+
options = {}
|
18
14
|
|
19
|
-
|
15
|
+
resource.expects(:request).with(method, options)
|
16
|
+
resource.send(method, options)
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
23
|
-
it
|
24
|
-
resource
|
25
|
-
|
20
|
+
it "adds json headers to every request" do
|
21
|
+
resource = Forward::API::Resource.new
|
22
|
+
headers = {
|
23
|
+
'Accept' => 'application/json',
|
24
|
+
'Content-Type' => 'application/json'
|
25
|
+
}
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
klass = eval("Net::HTTP::#{method.capitalize}")
|
31
|
-
request = resource.instance_variable_get('@request')
|
27
|
+
stub_request(:get, 'localhost/').
|
28
|
+
with(headers: headers).
|
29
|
+
to_return(status: 200)
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
EM.run_block {
|
32
|
+
Forward::API::Resource.new.get(path: '/') {}
|
33
|
+
}
|
36
34
|
end
|
37
35
|
|
38
|
-
it
|
39
|
-
resource
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
it "adds auth header if request is authenticated" do
|
37
|
+
resource = Forward::API::Resource.new
|
38
|
+
headers = {
|
39
|
+
'Accept' => 'application/json',
|
40
|
+
'Authorization' => 'Token token=abc123',
|
41
|
+
'Content-Type' => 'application/json'
|
42
|
+
}
|
43
|
+
|
44
|
+
stub_request(:get, 'localhost/').
|
45
|
+
with(headers: headers).
|
46
|
+
to_return(status: 200)
|
47
|
+
|
48
|
+
EM.run_block {
|
49
|
+
Forward::API::Resource.new.get(path: '/', authenticated: true) {}
|
50
|
+
}
|
48
51
|
end
|
49
52
|
|
53
|
+
it "adds a json body if params given" do
|
54
|
+
resource = Forward::API::Resource.new
|
55
|
+
params = { foo: 'bar' }
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
response.stubs(:code).returns(403)
|
55
|
-
response.stubs(:body)
|
57
|
+
stub_request(:post, 'localhost/').
|
58
|
+
with(body: params.to_json).
|
59
|
+
to_return(status: 200)
|
56
60
|
|
57
|
-
|
61
|
+
EM.run_block {
|
62
|
+
Forward::API::Resource.new.post(path: '/', params: params) {}
|
63
|
+
}
|
58
64
|
end
|
59
65
|
|
60
|
-
it
|
61
|
-
resource =
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
response.stubs(:[]).with('content-type').returns('text/html')
|
66
|
+
it "exits with message if status is 401" do
|
67
|
+
resource = Forward::API::Resource.new
|
68
|
+
|
69
|
+
stub_request(:get, 'localhost/').
|
70
|
+
to_return(status: 401)
|
66
71
|
|
67
|
-
|
72
|
+
out, err = capture_io do
|
73
|
+
begin
|
74
|
+
EM.run_block {
|
75
|
+
Forward::API::Resource.new.get(path: '/') {}
|
76
|
+
}
|
77
|
+
rescue SystemExit; end
|
78
|
+
end
|
79
|
+
out.must_match /Unable to authenticate/i
|
68
80
|
end
|
69
81
|
|
70
|
-
it
|
71
|
-
resource =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
response.stubs(:body).returns('{ "foo": "bar" }')
|
82
|
+
it "exits with message if response is invalid JSON" do
|
83
|
+
resource = Forward::API::Resource.new
|
84
|
+
|
85
|
+
stub_request(:get, 'localhost/').
|
86
|
+
to_return(status: 200, body: '{"foo"}')
|
76
87
|
|
77
|
-
|
78
|
-
|
79
|
-
|
88
|
+
out, err = capture_io do
|
89
|
+
begin
|
90
|
+
EM.run_block {
|
91
|
+
Forward::API::Resource.new.get(path: '/') {}
|
92
|
+
}
|
93
|
+
rescue SystemExit; end
|
94
|
+
end
|
95
|
+
out.must_match /Unable to connect to API/i
|
80
96
|
end
|
81
97
|
|
82
98
|
end
|
data/test/api/tunnel_test.rb
CHANGED
@@ -1,90 +1,89 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
describe Forward::
|
3
|
+
describe Forward::API::Tunnel do
|
4
4
|
|
5
5
|
before :each do
|
6
|
-
|
7
|
-
Forward::
|
6
|
+
Forward::Config.accounts = { foo: 'abc123' }
|
7
|
+
Forward::Config.default_account = :foo
|
8
8
|
end
|
9
9
|
|
10
10
|
it "creates a tunnel and returns the attributes" do
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
tunnel_options = { port: '3000', host: 'localhost' }
|
12
|
+
params = {
|
13
|
+
hostport: tunnel_options[:port],
|
14
|
+
vhost: tunnel_options[:host],
|
15
|
+
subdomain: nil, cname: nil,
|
16
|
+
username: nil, password: nil, no_auth: nil,
|
17
|
+
client: Forward.client_string,
|
18
|
+
}
|
19
|
+
body = { tunnel: { _id: '1', subdomain: 'foo', port: 56789 }}
|
14
20
|
|
15
|
-
|
21
|
+
stub_request(:post, 'localhost/api/v3/tunnels/').
|
22
|
+
with(body: params.to_json).
|
23
|
+
to_return(status: 200, body: body.to_json)
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
25
|
+
EM.run_block {
|
26
|
+
Forward::API::Tunnel.create(tunnel_options) do |tunnel|
|
27
|
+
tunnel[:id].must_equal body[:id]
|
28
|
+
tunnel[:subdomain].must_equal body[:subdomain]
|
29
|
+
tunnel[:port].must_equal body[:port]
|
30
|
+
end
|
31
|
+
}
|
20
32
|
end
|
21
33
|
|
22
|
-
it "exits with message
|
23
|
-
|
24
|
-
:type => 'resource_error',
|
25
|
-
:errors => {
|
26
|
-
:base => [ 'did not work '],
|
27
|
-
:subdomain => [ 'is invalid', 'is too short' ]
|
28
|
-
}
|
29
|
-
}
|
34
|
+
it "exits with message on 422" do
|
35
|
+
tunnel_options = { port: '3000', host: 'localhost' }
|
30
36
|
|
31
|
-
|
37
|
+
stub_request(:post, 'localhost/api/v3/tunnels/').
|
38
|
+
to_return(status: 422)
|
32
39
|
|
33
40
|
out, err = capture_io do
|
34
41
|
begin
|
35
|
-
|
42
|
+
EM.run_block {
|
43
|
+
Forward::API::Tunnel.create(tunnel_options) { }
|
44
|
+
}
|
36
45
|
rescue SystemExit; end
|
37
46
|
end
|
38
|
-
out.must_match /
|
39
|
-
out.must_match /subdomain is invalid/i
|
40
|
-
out.must_match /subdomain is too short/i
|
47
|
+
out.must_match /unable to allocate tunnel/i
|
41
48
|
end
|
42
49
|
|
43
|
-
it "exits with message
|
44
|
-
|
45
|
-
|
46
|
-
:
|
50
|
+
it "exits with message and displays account errors" do
|
51
|
+
tunnel_options = { port: '3000', host: 'localhost' }
|
52
|
+
body = {
|
53
|
+
type: 'account_error',
|
54
|
+
errors: { account: ['Trial has expired'] }
|
47
55
|
}
|
48
56
|
|
49
|
-
|
57
|
+
stub_request(:post, 'localhost/api/v3/tunnels/').
|
58
|
+
to_return(status: 422, body: body.to_json)
|
50
59
|
|
51
60
|
out, err = capture_io do
|
52
61
|
begin
|
53
|
-
|
62
|
+
EM.run_block {
|
63
|
+
Forward::API::Tunnel.create(tunnel_options) { }
|
64
|
+
}
|
54
65
|
rescue SystemExit; end
|
55
66
|
end
|
56
67
|
out.must_match /trial has expired/i
|
57
68
|
end
|
58
69
|
|
59
|
-
it "exits with message
|
60
|
-
|
61
|
-
|
62
|
-
:
|
70
|
+
it "exits with message on bad tunnel data" do
|
71
|
+
tunnel_options = { port: '3000', host: 'localhost' }
|
72
|
+
body = {
|
73
|
+
type: 'invalid_request_error'
|
63
74
|
}
|
64
75
|
|
65
|
-
|
76
|
+
stub_request(:post, 'localhost/api/v3/tunnels/').
|
77
|
+
to_return(status: 422, body: body.to_json)
|
66
78
|
|
67
79
|
out, err = capture_io do
|
68
80
|
begin
|
69
|
-
|
81
|
+
EM.run_block {
|
82
|
+
Forward::API::Tunnel.create(tunnel_options) { }
|
83
|
+
}
|
70
84
|
rescue SystemExit; end
|
71
85
|
end
|
72
|
-
out.must_match /
|
86
|
+
out.must_match /invalid tunnel parameters/i
|
73
87
|
end
|
74
88
|
|
75
|
-
it "gives a choice and closes a tunnel if limit is reached" do
|
76
|
-
post_options = [
|
77
|
-
{ :body => { :type => 'tunnel_limit_reached', :message => 'you have reached your limit' }.to_json, :status => [ 422, 'Unprocessable Entity' ] },
|
78
|
-
{ :body => { :tunnel => { :_id => '1', :subdomain => 'foo', :port => 56789 } }.to_json }
|
79
|
-
]
|
80
|
-
index_body = { :tunnels => [ { :_id => 'abc123', :hostport => 1234 }, { :_id => 'def456', :hostport => 1235 } ] }
|
81
|
-
|
82
|
-
stub_api_request(:post, '/api/v2/tunnels', post_options)
|
83
|
-
stub_api_request(:get, '/api/v2/tunnels', :body => index_body.to_json)
|
84
|
-
STDIN.expects(:gets).returns('1')
|
85
|
-
Forward::Api::Tunnel.expects(:destroy).with(index_body[:tunnels].first[:_id])
|
86
|
-
|
87
|
-
dev_null { Forward::Api::Tunnel.create(:port => 3000) }
|
88
|
-
end
|
89
|
-
|
90
89
|
end
|
data/test/api/user_test.rb
CHANGED
@@ -1,41 +1,54 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
describe Forward::
|
4
|
-
|
5
|
-
before :each do
|
6
|
-
FakeWeb.allow_net_connect = false
|
7
|
-
end
|
3
|
+
describe Forward::API::User do
|
8
4
|
|
9
5
|
it "retrieves the users api token and returns it" do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
params = { email: 'guy@example.com', password: 'secret' }
|
7
|
+
body = { subdomain: 'fooco', token: '123abc' }
|
8
|
+
|
9
|
+
stub_request(:post, 'localhost/api/v3/user/token').
|
10
|
+
with(body: params.to_json).
|
11
|
+
to_return(status: 200, body: body.to_json)
|
12
|
+
|
13
|
+
EM.run_block {
|
14
|
+
Forward::API::User.authenticate(params[:email], params[:password]) do |subdomain, token|
|
15
|
+
token.must_equal '123abc'
|
16
|
+
end
|
17
|
+
}
|
16
18
|
end
|
17
19
|
|
18
20
|
it "exits with message if authentication fails" do
|
19
|
-
|
21
|
+
params = { email: 'guy@example.com', password: 'secret' }
|
20
22
|
|
21
|
-
|
23
|
+
stub_request(:post, 'localhost/api/v3/user/token').
|
24
|
+
with(body: params.to_json).
|
25
|
+
to_return(status: 401)
|
22
26
|
|
23
27
|
out, err = capture_io do
|
24
28
|
begin
|
25
|
-
|
29
|
+
EM.run_block {
|
30
|
+
Forward::API::User.authenticate(params[:email], params[:password]) {}
|
31
|
+
}
|
26
32
|
rescue SystemExit; end
|
27
33
|
end
|
28
|
-
out.must_match /
|
34
|
+
out.must_match /Unable to authenticate/i
|
29
35
|
end
|
30
36
|
|
31
37
|
it "exits with message if response has errors" do
|
32
|
-
|
38
|
+
params = { email: 'guy@example.com', password: 'secret' }
|
33
39
|
|
34
|
-
|
40
|
+
stub_request(:post, 'localhost/api/v3/user/token').
|
41
|
+
with(body: params.to_json).
|
42
|
+
to_return(status: 422)
|
35
43
|
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
out, err = capture_io do
|
45
|
+
begin
|
46
|
+
EM.run_block {
|
47
|
+
Forward::API::User.authenticate(params[:email], params[:password]) {}
|
48
|
+
}
|
49
|
+
rescue SystemExit; end
|
50
|
+
end
|
51
|
+
out.must_match /Unable to authenticate/i
|
39
52
|
end
|
40
53
|
|
41
54
|
end
|
data/test/cli_test.rb
CHANGED
@@ -2,130 +2,4 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
describe Forward::CLI do
|
4
4
|
|
5
|
-
it 'parses a forwarded port' do
|
6
|
-
forwarded = Forward::CLI.parse_forwarded('600')
|
7
|
-
forwarded.has_key?(:port).must_equal true
|
8
|
-
forwarded[:port].must_equal 600
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'parses a forwarded host' do
|
12
|
-
forwarded = Forward::CLI.parse_forwarded('mysite.dev')
|
13
|
-
forwarded.has_key?(:host).must_equal true
|
14
|
-
forwarded[:host].must_equal 'mysite.dev'
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'parses a forwarded host and port' do
|
18
|
-
forwarded = Forward::CLI.parse_forwarded('mysite.dev:88')
|
19
|
-
forwarded.has_key?(:host).must_equal true
|
20
|
-
forwarded.has_key?(:port).must_equal true
|
21
|
-
forwarded[:host].must_equal 'mysite.dev'
|
22
|
-
forwarded[:port].must_equal 88
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'exits if username is invalid' do
|
26
|
-
[ 'foo ', ' asdfasdf ', 'fooo bar' ].each do |username|
|
27
|
-
lambda {
|
28
|
-
dev_null { Forward::CLI.validate_username(username) }
|
29
|
-
}.must_raise SystemExit
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'validates a good username' do
|
34
|
-
[ 'foo', 'asdflkj3r&)(#@#)', 'DF#R::#SFSDF' ].each do |username|
|
35
|
-
Forward::CLI.validate_username(username).must_be_nil
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'exits if password is invalid' do
|
40
|
-
[ 'foo ', ' asdfasdf ', 'fooo bar' ].each do |password|
|
41
|
-
lambda {
|
42
|
-
dev_null { Forward::CLI.validate_password(password) }
|
43
|
-
}.must_raise SystemExit
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'validates a good password' do
|
48
|
-
[ 'foo', 'asdflkj3r&)(#@#)', 'DF#R::#SFSDF' ].each do |password|
|
49
|
-
Forward::CLI.validate_password(password).must_be_nil
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'parses a Forwardfile' do
|
54
|
-
hash_to_forwardfile(:auth => 'username:password')
|
55
|
-
|
56
|
-
options = Forward::CLI.parse_forwardfile
|
57
|
-
options.has_key?(:auth).must_equal true
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'exits if a Forwardfile does not parse to a Hash' do
|
61
|
-
hash_to_forwardfile('username:password')
|
62
|
-
|
63
|
-
lambda {
|
64
|
-
dev_null { Forward::CLI.parse_forwardfile }
|
65
|
-
}.must_raise SystemExit
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'overloads Forwardfile options via commandline options' do
|
69
|
-
hash_to_forwardfile(
|
70
|
-
:port => 8000,
|
71
|
-
:username => 'username',
|
72
|
-
:password => 'password',
|
73
|
-
:subdomain_prefix => 'foo'
|
74
|
-
)
|
75
|
-
args = [ '3000', '-a', 'example:secret', 'bar' ]
|
76
|
-
options = Forward::CLI.parse_args_and_options(args)
|
77
|
-
|
78
|
-
options[:port].must_equal 3000
|
79
|
-
options[:username].must_equal 'example'
|
80
|
-
options[:password].must_equal 'secret'
|
81
|
-
options[:subdomain_prefix].must_equal 'bar'
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'doesnt exit on valid ports' do
|
85
|
-
Forward::CLI.validate_port(69).must_be_nil
|
86
|
-
Forward::CLI.validate_port(3000).must_be_nil
|
87
|
-
Forward::CLI.validate_port(65535).must_be_nil
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'validates port and exits if invalid' do
|
91
|
-
[ 0, 65536 ].each do |port|
|
92
|
-
lambda {
|
93
|
-
dev_null { Forward::CLI.validate_port(port) }
|
94
|
-
}.must_raise SystemExit
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'doesnt exit on valid cnames' do
|
99
|
-
[ 'foo.com', 'whatever-foo.com', 'www.foo.com', 'asdf.asdf.asdf.com' ].each do |cname|
|
100
|
-
Forward::CLI.validate_cname(cname).must_be_nil
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'validates cname and exits if invalid' do
|
105
|
-
[ 'whatever', 'asdfasdf.', '-asdf', 'adsf#$).com' ].each do |cname|
|
106
|
-
lambda {
|
107
|
-
dev_null { Forward::CLI.validate_cname(cname) }
|
108
|
-
}.must_raise SystemExit
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'doesnt exit on valid subdomains prefix' do
|
113
|
-
[ 'foo', 'whatever-foo', 'asdf40' ].each do |subdomain|
|
114
|
-
Forward::CLI.validate_subdomain_prefix(subdomain).must_be_nil
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'validates subdomain prefix and exits if invalid' do
|
119
|
-
[ '-asdf', 'adsf#$)' ].each do |subdomain|
|
120
|
-
lambda {
|
121
|
-
dev_null { Forward::CLI.validate_subdomain_prefix(subdomain) }
|
122
|
-
}.must_raise SystemExit
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
def hash_to_forwardfile(hash)
|
129
|
-
yaml = YAML.dump(hash)
|
130
|
-
File.open('Forwardfile', 'w') { |f| f.write(yaml) }
|
131
5
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Forward::Command::Account do
|
4
|
+
before :each do
|
5
|
+
FakeFS.activate!
|
6
|
+
FileUtils.mkdir_p(ENV['HOME'])
|
7
|
+
end
|
8
|
+
|
9
|
+
after :each do
|
10
|
+
FileUtils.rm_rf(ENV['HOME'])
|
11
|
+
FakeFS.deactivate!
|
12
|
+
end
|
13
|
+
|
14
|
+
it "logs a client in with a provided email" do
|
15
|
+
email = 'foo@example.com'
|
16
|
+
password = 'bar'
|
17
|
+
command = Forward::Command::Account.new({}, [email])
|
18
|
+
|
19
|
+
Forward::API::User.expects(:authenticate).with(email, password)
|
20
|
+
command.expects(:ask_for_credentials).with(email).returns([email, password])
|
21
|
+
|
22
|
+
EM.run_block {
|
23
|
+
command.login
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Forward::Command::Tunnel do
|
4
|
+
before :each do
|
5
|
+
FakeFS.activate!
|
6
|
+
FileUtils.mkdir_p(ENV['HOME'])
|
7
|
+
end
|
8
|
+
|
9
|
+
after :each do
|
10
|
+
FileUtils.rm_rf(ENV['HOME'])
|
11
|
+
FakeFS.deactivate!
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'parses a forwarded port' do
|
15
|
+
command = Forward::Command::Tunnel.new({}, ['600'])
|
16
|
+
|
17
|
+
command.send(:parse_forwarded)
|
18
|
+
command.options[:port].must_equal 600
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'parses a forwarded host' do
|
22
|
+
command = Forward::Command::Tunnel.new({}, ['mysite.dev'])
|
23
|
+
|
24
|
+
command.send(:parse_forwarded)
|
25
|
+
command.options[:host].must_equal 'mysite.dev'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'parses a forwarded host and port' do
|
29
|
+
command = Forward::Command::Tunnel.new({}, ['mysite.dev:8888'])
|
30
|
+
|
31
|
+
command.send(:parse_forwarded)
|
32
|
+
command.options[:host].must_equal 'mysite.dev'
|
33
|
+
command.options[:port].must_equal 8888
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'exits if auth pair is invalid' do
|
37
|
+
[ 'as:df:asdf', 'fooo bar', 'foo oo:bar' ].each do |auth|
|
38
|
+
lambda {
|
39
|
+
dev_null {
|
40
|
+
command = Forward::Command::Tunnel.new(auth: auth)
|
41
|
+
command.send(:validate_auth)
|
42
|
+
}
|
43
|
+
}.must_raise Forward::CLIError
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'validates a auth pair' do
|
48
|
+
[ 'foo:asdflkj3r&)', 'tom:#SFSDF' ].each do |auth|
|
49
|
+
command = Forward::Command::Tunnel.new(auth: auth)
|
50
|
+
command.send(:validate_auth)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'parses a Forwardfile' do
|
55
|
+
hash_to_forwardfile(auth: 'username:password')
|
56
|
+
|
57
|
+
command = Forward::Command::Tunnel.new
|
58
|
+
command.send(:parse_forwardfile)
|
59
|
+
command.options[:auth].must_equal 'username:password'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'exits if a Forwardfile does not parse to a Hash' do
|
63
|
+
hash_to_forwardfile('username:password')
|
64
|
+
|
65
|
+
lambda {
|
66
|
+
dev_null { Forward::Command::Tunnel.new.send(:parse_forwardfile) }
|
67
|
+
}.must_raise SystemExit
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'overloads Forwardfile options via commandline options' do
|
71
|
+
hash_to_forwardfile(
|
72
|
+
port: 8000,
|
73
|
+
username: 'username',
|
74
|
+
password: 'password',
|
75
|
+
subdomain_prefix: 'foo'
|
76
|
+
)
|
77
|
+
|
78
|
+
EM.expects(:run)
|
79
|
+
|
80
|
+
command = Forward::Command::Tunnel.new({auth: 'example:secret'}, ['3000', 'bar'])
|
81
|
+
command.start
|
82
|
+
|
83
|
+
command.options[:port].must_equal 3000
|
84
|
+
command.options[:username].must_equal 'example'
|
85
|
+
command.options[:password].must_equal 'secret'
|
86
|
+
command.options[:subdomain_prefix].must_equal 'bar'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'validates port and exits if invalid' do
|
90
|
+
command = Forward::Command::Tunnel.new
|
91
|
+
command.options = { port: 3000 }
|
92
|
+
|
93
|
+
command.send(:validate_port)
|
94
|
+
|
95
|
+
[ 0, 65536 ].each do |port|
|
96
|
+
lambda {
|
97
|
+
dev_null {
|
98
|
+
command.options[:port] = port
|
99
|
+
command.send(:validate_port) }
|
100
|
+
}.must_raise Forward::CLIError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'validates cname and exits if invalid' do
|
105
|
+
command = Forward::Command::Tunnel.new
|
106
|
+
command.options = { cname: 'foo.bar.com' }
|
107
|
+
|
108
|
+
command.send(:validate_cname)
|
109
|
+
[ 'whatever', 'asdfasdf.', '-asdf', 'adsf#$).com' ].each do |cname|
|
110
|
+
lambda {
|
111
|
+
dev_null {
|
112
|
+
command.options[:cname] = cname
|
113
|
+
command.send(:validate_cname)
|
114
|
+
}
|
115
|
+
}.must_raise Forward::CLIError
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'validates subdomain prefix and exits if invalid' do
|
120
|
+
command = Forward::Command::Tunnel.new
|
121
|
+
command.options = { subdomain_prefix: 'foo' }
|
122
|
+
|
123
|
+
command.send(:validate_subdomain_prefix)
|
124
|
+
[ '-asdf', 'adsf#$)' ].each do |subdomain|
|
125
|
+
lambda {
|
126
|
+
dev_null {
|
127
|
+
command.options[:subdomain_prefix] = subdomain
|
128
|
+
command.send(:validate_subdomain_prefix)
|
129
|
+
}
|
130
|
+
}.must_raise Forward::CLIError
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|