warden-protocol 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +6 -0
- data/README.md +13 -0
- data/Rakefile +40 -0
- data/lib/warden/protocol.rb +4 -0
- data/lib/warden/protocol/base.rb +168 -0
- data/lib/warden/protocol/buffer.rb +69 -0
- data/lib/warden/protocol/build.sh +13 -0
- data/lib/warden/protocol/message.rb +50 -0
- data/lib/warden/protocol/pb.rb +497 -0
- data/lib/warden/protocol/pb/copy_in.proto +35 -0
- data/lib/warden/protocol/pb/copy_out.proto +39 -0
- data/lib/warden/protocol/pb/create.proto +65 -0
- data/lib/warden/protocol/pb/destroy.proto +33 -0
- data/lib/warden/protocol/pb/echo.proto +26 -0
- data/lib/warden/protocol/pb/error.proto +19 -0
- data/lib/warden/protocol/pb/info.proto +95 -0
- data/lib/warden/protocol/pb/limit_bandwidth.proto +30 -0
- data/lib/warden/protocol/pb/limit_disk.proto +70 -0
- data/lib/warden/protocol/pb/limit_memory.proto +34 -0
- data/lib/warden/protocol/pb/link.proto +40 -0
- data/lib/warden/protocol/pb/list.proto +25 -0
- data/lib/warden/protocol/pb/message.proto +36 -0
- data/lib/warden/protocol/pb/net_in.proto +39 -0
- data/lib/warden/protocol/pb/net_out.proto +35 -0
- data/lib/warden/protocol/pb/ping.proto +24 -0
- data/lib/warden/protocol/pb/resource_limits.proto +30 -0
- data/lib/warden/protocol/pb/run.proto +29 -0
- data/lib/warden/protocol/pb/spawn.proto +37 -0
- data/lib/warden/protocol/pb/stop.proto +40 -0
- data/lib/warden/protocol/pb/stream.proto +41 -0
- data/lib/warden/protocol/version.rb +7 -0
- data/spec/base_spec.rb +150 -0
- data/spec/buffer_spec.rb +65 -0
- data/spec/copy_in_spec.rb +51 -0
- data/spec/copy_out_spec.rb +56 -0
- data/spec/create_spec.rb +70 -0
- data/spec/destroy_spec.rb +36 -0
- data/spec/echo_spec.rb +42 -0
- data/spec/error_spec.rb +33 -0
- data/spec/info_spec.rb +122 -0
- data/spec/limit_bandwidth_spec.rb +57 -0
- data/spec/limit_disk_spec.rb +103 -0
- data/spec/limit_memory_spec.rb +47 -0
- data/spec/link_spec.rb +67 -0
- data/spec/list_spec.rb +41 -0
- data/spec/net_in_spec.rb +57 -0
- data/spec/net_out_spec.rb +47 -0
- data/spec/ping_spec.rb +32 -0
- data/spec/resource_limits_spec.rb +84 -0
- data/spec/run_spec.rb +79 -0
- data/spec/spawn_spec.rb +55 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/stop_spec.rb +46 -0
- data/spec/stream_spec.rb +65 -0
- data/spec/support/examples/wrappable_reply.rb +26 -0
- data/spec/support/examples/wrappable_request.rb +26 -0
- data/spec/support/helper.rb +122 -0
- data/spec/support/matchers.rb +22 -0
- data/warden-protocol.gemspec +21 -0
- metadata +166 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Warden::Protocol::ResourceLimits do
|
6
|
+
subject do
|
7
|
+
described_class.new
|
8
|
+
end
|
9
|
+
|
10
|
+
field :as do
|
11
|
+
it_should_be_optional
|
12
|
+
it_should_be_typed_as_uint64
|
13
|
+
end
|
14
|
+
|
15
|
+
field :core do
|
16
|
+
it_should_be_optional
|
17
|
+
it_should_be_typed_as_uint64
|
18
|
+
end
|
19
|
+
|
20
|
+
field :cpu do
|
21
|
+
it_should_be_optional
|
22
|
+
it_should_be_typed_as_uint64
|
23
|
+
end
|
24
|
+
|
25
|
+
field :data do
|
26
|
+
it_should_be_optional
|
27
|
+
it_should_be_typed_as_uint64
|
28
|
+
end
|
29
|
+
|
30
|
+
field :fsize do
|
31
|
+
it_should_be_optional
|
32
|
+
it_should_be_typed_as_uint64
|
33
|
+
end
|
34
|
+
|
35
|
+
field :locks do
|
36
|
+
it_should_be_optional
|
37
|
+
it_should_be_typed_as_uint64
|
38
|
+
end
|
39
|
+
|
40
|
+
field :memlock do
|
41
|
+
it_should_be_optional
|
42
|
+
it_should_be_typed_as_uint64
|
43
|
+
end
|
44
|
+
|
45
|
+
field :msgqueue do
|
46
|
+
it_should_be_optional
|
47
|
+
it_should_be_typed_as_uint64
|
48
|
+
end
|
49
|
+
|
50
|
+
field :nice do
|
51
|
+
it_should_be_optional
|
52
|
+
it_should_be_typed_as_uint64
|
53
|
+
end
|
54
|
+
|
55
|
+
field :nofile do
|
56
|
+
it_should_be_optional
|
57
|
+
it_should_be_typed_as_uint64
|
58
|
+
end
|
59
|
+
|
60
|
+
field :nproc do
|
61
|
+
it_should_be_optional
|
62
|
+
it_should_be_typed_as_uint64
|
63
|
+
end
|
64
|
+
|
65
|
+
field :rss do
|
66
|
+
it_should_be_optional
|
67
|
+
it_should_be_typed_as_uint64
|
68
|
+
end
|
69
|
+
|
70
|
+
field :rtprio do
|
71
|
+
it_should_be_optional
|
72
|
+
it_should_be_typed_as_uint64
|
73
|
+
end
|
74
|
+
|
75
|
+
field :sigpending do
|
76
|
+
it_should_be_optional
|
77
|
+
it_should_be_typed_as_uint64
|
78
|
+
end
|
79
|
+
|
80
|
+
field :stack do
|
81
|
+
it_should_be_optional
|
82
|
+
it_should_be_typed_as_uint64
|
83
|
+
end
|
84
|
+
end
|
data/spec/run_spec.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
module Warden::Protocol
|
6
|
+
describe RunRequest do
|
7
|
+
subject(:request) do
|
8
|
+
described_class.new(:handle => "handle", :script => "echo foo")
|
9
|
+
end
|
10
|
+
|
11
|
+
it_should_behave_like "wrappable request"
|
12
|
+
|
13
|
+
its("class.type_camelized") { should == "Run" }
|
14
|
+
its("class.type_underscored") { should == "run" }
|
15
|
+
|
16
|
+
field :handle do
|
17
|
+
it_should_be_required
|
18
|
+
end
|
19
|
+
|
20
|
+
field :script do
|
21
|
+
it_should_be_required
|
22
|
+
end
|
23
|
+
|
24
|
+
field :privileged do
|
25
|
+
it_should_be_optional
|
26
|
+
it_should_default_to false
|
27
|
+
end
|
28
|
+
|
29
|
+
field :rlimits do
|
30
|
+
it_should_be_optional
|
31
|
+
|
32
|
+
it "should be populated with ResourceLimits object" do
|
33
|
+
request.rlimits = ResourceLimits.new
|
34
|
+
request.should be_valid
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should respond to #create_response" do
|
39
|
+
request.create_response.should be_a(RunResponse)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe RunResponse do
|
44
|
+
subject(:response) do
|
45
|
+
described_class.new
|
46
|
+
end
|
47
|
+
|
48
|
+
it_should_behave_like "wrappable response"
|
49
|
+
|
50
|
+
its("class.type_camelized") { should == "Run" }
|
51
|
+
its("class.type_underscored") { should == "run" }
|
52
|
+
|
53
|
+
it { should be_ok }
|
54
|
+
it { should_not be_error }
|
55
|
+
|
56
|
+
field :exit_status do
|
57
|
+
it_should_be_optional
|
58
|
+
it_should_be_typed_as_uint
|
59
|
+
end
|
60
|
+
|
61
|
+
field :stdout do
|
62
|
+
it_should_be_optional
|
63
|
+
it_should_be_typed_as_string
|
64
|
+
end
|
65
|
+
|
66
|
+
field :stderr do
|
67
|
+
it_should_be_optional
|
68
|
+
it_should_be_typed_as_string
|
69
|
+
end
|
70
|
+
|
71
|
+
field :info do
|
72
|
+
it_should_be_optional
|
73
|
+
|
74
|
+
it "should be a InfoResponse" do
|
75
|
+
field.type.should == InfoResponse
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/spec/spawn_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Warden::Protocol::SpawnRequest do
|
6
|
+
subject(:request) do
|
7
|
+
described_class.new(:handle => "handle", :script => "echo foo")
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like "wrappable request"
|
11
|
+
|
12
|
+
its("class.type_camelized") { should == "Spawn" }
|
13
|
+
its("class.type_underscored") { should == "spawn" }
|
14
|
+
|
15
|
+
field :handle do
|
16
|
+
it_should_be_required
|
17
|
+
end
|
18
|
+
|
19
|
+
field :script do
|
20
|
+
it_should_be_required
|
21
|
+
end
|
22
|
+
|
23
|
+
field :privileged do
|
24
|
+
it_should_be_optional
|
25
|
+
it_should_default_to false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be populated with ResourceLimits object" do
|
29
|
+
request.rlimits = Warden::Protocol::ResourceLimits.new
|
30
|
+
request.should be_valid
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should respond to #create_response" do
|
34
|
+
request.create_response.should be_a(Warden::Protocol::SpawnResponse)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe Warden::Protocol::SpawnResponse do
|
39
|
+
subject(:response) do
|
40
|
+
described_class.new(:job_id => 1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_behave_like "wrappable response"
|
44
|
+
|
45
|
+
its("class.type_camelized") { should == "Spawn" }
|
46
|
+
its("class.type_underscored") { should == "spawn" }
|
47
|
+
|
48
|
+
it { should be_ok }
|
49
|
+
it { should_not be_error }
|
50
|
+
|
51
|
+
field :job_id do
|
52
|
+
it_should_be_required
|
53
|
+
it_should_be_typed_as_uint
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/stop_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Warden::Protocol::StopRequest do
|
6
|
+
subject(:request) do
|
7
|
+
described_class.new(:handle => "handle")
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like "wrappable request"
|
11
|
+
|
12
|
+
its("class.type_camelized") { should == "Stop" }
|
13
|
+
its("class.type_underscored") { should == "stop" }
|
14
|
+
|
15
|
+
field :handle do
|
16
|
+
it_should_be_required
|
17
|
+
end
|
18
|
+
|
19
|
+
field :background do
|
20
|
+
it_should_be_optional
|
21
|
+
it_should_be_typed_as_boolean
|
22
|
+
end
|
23
|
+
|
24
|
+
field :kill do
|
25
|
+
it_should_be_optional
|
26
|
+
it_should_be_typed_as_boolean
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should respond to #create_response" do
|
30
|
+
request.create_response.should be_a(Warden::Protocol::StopResponse)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Warden::Protocol::StopResponse do
|
35
|
+
subject(:response) do
|
36
|
+
described_class.new
|
37
|
+
end
|
38
|
+
|
39
|
+
it_should_behave_like "wrappable response"
|
40
|
+
|
41
|
+
its("class.type_camelized") { should == "Stop" }
|
42
|
+
its("class.type_underscored") { should == "stop" }
|
43
|
+
|
44
|
+
it { should be_ok }
|
45
|
+
it { should_not be_error }
|
46
|
+
end
|
data/spec/stream_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Warden::Protocol::StreamRequest do
|
6
|
+
subject(:request) do
|
7
|
+
described_class.new(:handle => "handle", :job_id => 1)
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like "wrappable request"
|
11
|
+
|
12
|
+
its("class.type_camelized") { should == "Stream" }
|
13
|
+
its("class.type_underscored") { should == "stream" }
|
14
|
+
|
15
|
+
field :handle do
|
16
|
+
it_should_be_required
|
17
|
+
it_should_be_typed_as_string
|
18
|
+
end
|
19
|
+
|
20
|
+
field :job_id do
|
21
|
+
it_should_be_required
|
22
|
+
it_should_be_typed_as_uint
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should respond to #create_response" do
|
26
|
+
request.create_response.should be_a(Warden::Protocol::StreamResponse)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Warden::Protocol::StreamResponse do
|
31
|
+
subject(:response) do
|
32
|
+
described_class.new
|
33
|
+
end
|
34
|
+
|
35
|
+
it_should_behave_like "wrappable response"
|
36
|
+
|
37
|
+
its("class.type_camelized") { should == "Stream" }
|
38
|
+
its("class.type_underscored") { should == "stream" }
|
39
|
+
|
40
|
+
it { should be_ok }
|
41
|
+
it { should_not be_error }
|
42
|
+
|
43
|
+
field :name do
|
44
|
+
it_should_be_optional
|
45
|
+
it_should_be_typed_as_string
|
46
|
+
end
|
47
|
+
|
48
|
+
field :data do
|
49
|
+
it_should_be_optional
|
50
|
+
it_should_be_typed_as_string
|
51
|
+
end
|
52
|
+
|
53
|
+
field :exit_status do
|
54
|
+
it_should_be_optional
|
55
|
+
it_should_be_typed_as_uint
|
56
|
+
end
|
57
|
+
|
58
|
+
field :info do
|
59
|
+
it_should_be_optional
|
60
|
+
|
61
|
+
it "should be a InfoResponse" do
|
62
|
+
field.type.should == Warden::Protocol::InfoResponse
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
shared_examples "wrappable response" do
|
4
|
+
let(:wrapped) { subject.wrap }
|
5
|
+
|
6
|
+
it "should respond to #wrap" do
|
7
|
+
wrapped.should be_a(Warden::Protocol::Message)
|
8
|
+
|
9
|
+
type_const = described_class.name.split("::").last.gsub(/Response$/, "")
|
10
|
+
wrapped.type.should == Warden::Protocol::Message::Type.const_get(type_const)
|
11
|
+
wrapped.payload.to_s.should == subject.encode.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should retain class when unwrapped" do
|
15
|
+
wrapped.response.should be_a(described_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should retain properties when unwrapped" do
|
19
|
+
compare_without_encoding(wrapped.response.to_hash, subject.to_hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should retain properties when encoded and decoded" do
|
23
|
+
freshly_wrapped = Warden::Protocol::Message.decode(wrapped.encode.to_s)
|
24
|
+
compare_without_encoding(freshly_wrapped.response.to_hash, subject.to_hash)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
shared_examples "wrappable request" do
|
4
|
+
let(:wrapped) { subject.wrap }
|
5
|
+
|
6
|
+
it "should respond to #wrap" do
|
7
|
+
wrapped.should be_a(Warden::Protocol::Message)
|
8
|
+
|
9
|
+
type_const = described_class.name.split("::").last.gsub(/Request$/, "")
|
10
|
+
wrapped.type.should == Warden::Protocol::Message::Type.const_get(type_const)
|
11
|
+
wrapped.payload.to_s.should == subject.encode.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should retain class when unwrapped" do
|
15
|
+
wrapped.request.should be_a(described_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should retain properties when unwrapped" do
|
19
|
+
compare_without_encoding(wrapped.request.to_hash, subject.to_hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should retain properties when encoded and decoded" do
|
23
|
+
freshly_wrapped = Warden::Protocol::Message.decode(wrapped.encode.to_s)
|
24
|
+
compare_without_encoding(freshly_wrapped.request.to_hash, subject.to_hash)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
module Helper
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Compare strings in hashes regardless of their encoding
|
9
|
+
def compare_without_encoding(a, b)
|
10
|
+
(a.keys + b.keys).uniq.each do |key|
|
11
|
+
if a[key].respond_to?(:encoding)
|
12
|
+
a[key].should == b[key].force_encoding(a[key].encoding)
|
13
|
+
else
|
14
|
+
a[key].should == b[key]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def field(field, &blk)
|
21
|
+
describe field do
|
22
|
+
let(:field) do
|
23
|
+
subject.fields.values.detect { |f| f.name == field }
|
24
|
+
end
|
25
|
+
|
26
|
+
instance_eval(&blk)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def it_should_be_required
|
31
|
+
it "should be required" do
|
32
|
+
subject.should be_valid
|
33
|
+
subject.send("#{field.name}=", nil)
|
34
|
+
subject.should_not be_valid
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def it_should_be_optional
|
39
|
+
it "should be optional" do
|
40
|
+
subject.should be_valid
|
41
|
+
subject.send("#{field.name}=", nil)
|
42
|
+
subject.should be_valid
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def it_should_default_to(default)
|
47
|
+
it "should default to #{default}" do
|
48
|
+
instance = subject.reload
|
49
|
+
instance.send(field.name).should == default
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def it_should_be_typed_as_uint
|
54
|
+
it "should not allow a signed integer" do
|
55
|
+
subject.send("#{field.name}=", -1)
|
56
|
+
subject.should_not be_valid
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should allow zero" do
|
60
|
+
subject.send("#{field.name}=", 0)
|
61
|
+
subject.should be_valid
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should allow integers larger than zero" do
|
65
|
+
subject.send("#{field.name}=", 37)
|
66
|
+
subject.should be_valid
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def it_should_be_typed_as_uint32
|
71
|
+
it_should_be_typed_as_uint
|
72
|
+
|
73
|
+
it "should allow integer 2^32-1" do
|
74
|
+
subject.send("#{field.name}=", 2**32-1)
|
75
|
+
subject.should be_valid
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not allow integer 2^32" do
|
79
|
+
subject.send("#{field.name}=", 2**32)
|
80
|
+
subject.should_not be_valid
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def it_should_be_typed_as_uint64
|
85
|
+
it_should_be_typed_as_uint
|
86
|
+
|
87
|
+
it "should allow integer 2^64-1" do
|
88
|
+
subject.send("#{field.name}=", 2**64-1)
|
89
|
+
subject.should be_valid
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should not allow integer 2^64" do
|
93
|
+
subject.send("#{field.name}=", 2**64)
|
94
|
+
subject.should_not be_valid
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def it_should_be_typed_as_string
|
99
|
+
it "should allow an empty string" do
|
100
|
+
subject.send("#{field.name}=", "")
|
101
|
+
subject.should be_valid
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should allow a non-empty string" do
|
105
|
+
subject.send("#{field.name}=", "non-empty")
|
106
|
+
subject.should be_valid
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def it_should_be_typed_as_boolean
|
111
|
+
it "should allow false" do
|
112
|
+
subject.send("#{field.name}=", false)
|
113
|
+
subject.should be_valid
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should allow true" do
|
117
|
+
subject.send("#{field.name}=", true)
|
118
|
+
subject.should be_valid
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|