warden-protocol 0.1.3
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.
- 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
|