forward 0.3.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|