schemata-router 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/schemata/common/error.rb +12 -0
- data/lib/schemata/common/msgbase.rb +281 -0
- data/lib/schemata/common/msgtypebase.rb +144 -0
- data/lib/schemata/common/parsed_msg.rb +43 -0
- data/lib/schemata/helpers/hash_copy.rb +28 -0
- data/lib/schemata/helpers/stringify.rb +26 -0
- data/lib/schemata/router.rb +14 -0
- data/lib/schemata/router/register_request.rb +13 -0
- data/lib/schemata/router/register_request/register_request_v1.rb +53 -0
- data/lib/schemata/router/start_message.rb +13 -0
- data/lib/schemata/router/start_message/start_message_v1.rb +35 -0
- data/lib/schemata/router/version.rb +5 -0
- data/spec/common/helpers_spec.rb +115 -0
- data/spec/common/parsed_msg_spec.rb +46 -0
- data/spec/router/register_request_spec.rb +10 -0
- data/spec/router/router_spec.rb +6 -0
- data/spec/router/start_message_spec.rb +10 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/component_helpers.rb +51 -0
- data/spec/support/helpers.rb +54 -0
- data/spec/support/message_helpers.rb +138 -0
- data/spec/support/message_type_helpers.rb +171 -0
- metadata +158 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Schemata
|
2
|
+
module HashCopyHelpers
|
3
|
+
class CopyError < StandardError; end
|
4
|
+
|
5
|
+
def self.deep_copy(node)
|
6
|
+
case node
|
7
|
+
when String
|
8
|
+
return node.dup
|
9
|
+
when Numeric, TrueClass, FalseClass
|
10
|
+
return node
|
11
|
+
when Hash
|
12
|
+
copy = {}
|
13
|
+
# XXX NB: The 'to_s' below was included because some components use
|
14
|
+
# symbols as keys instead of strings. This fix is temporary; in the
|
15
|
+
# long term, we should change all components to use the same type for
|
16
|
+
# their keys
|
17
|
+
node.each { |k, v| copy[k.to_s] = deep_copy(v) }
|
18
|
+
return copy
|
19
|
+
when Array
|
20
|
+
return node.map { |v| deep_copy(v) }
|
21
|
+
when NilClass
|
22
|
+
return nil
|
23
|
+
else
|
24
|
+
raise CopyError.new("Unexpected class: #{node.class}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Schemata
|
2
|
+
module HashCopyHelpers
|
3
|
+
|
4
|
+
def self.stringify(node)
|
5
|
+
case node
|
6
|
+
when String
|
7
|
+
return node
|
8
|
+
when Numeric, TrueClass, FalseClass
|
9
|
+
return node
|
10
|
+
when Hash
|
11
|
+
copy = {}
|
12
|
+
node.each { |k, v| copy[k.to_s] = stringify(v) }
|
13
|
+
return copy
|
14
|
+
when Array
|
15
|
+
return node.map { |v| stringify(v) }
|
16
|
+
when NilClass
|
17
|
+
return nil
|
18
|
+
when Symbol
|
19
|
+
return node.to_s
|
20
|
+
else
|
21
|
+
raise CopyError.new("Unexpected class: #{node.class}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'schemata/router/register_request'
|
2
|
+
require 'schemata/router/start_message'
|
3
|
+
|
4
|
+
module Schemata
|
5
|
+
module Router
|
6
|
+
def self.mock_register_request(version=RegisterRequest.current_version)
|
7
|
+
RegisterRequest::const_get("V#{version}").mock
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.mock_start_message(version=StartMessage.current_version)
|
11
|
+
StartMessage::const_get("V#{version}").mock
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#require 'vcap/common'
|
2
|
+
|
3
|
+
module Schemata
|
4
|
+
module Router
|
5
|
+
module RegisterRequest
|
6
|
+
version 1 do
|
7
|
+
include_preschemata
|
8
|
+
|
9
|
+
define_schema do
|
10
|
+
{
|
11
|
+
optional("dea") => String,
|
12
|
+
optional("app") => String,
|
13
|
+
"uris" => [String],
|
14
|
+
"host" => String,
|
15
|
+
"port" => Integer,
|
16
|
+
"tags" => {
|
17
|
+
optional("framework") => String,
|
18
|
+
optional("runtime") => String,
|
19
|
+
optional("component") => String,
|
20
|
+
},
|
21
|
+
optional("private_instance_id") => String,
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
define_min_version 1
|
26
|
+
|
27
|
+
define_upvert do |old_data|
|
28
|
+
raise NotImplementedError.new
|
29
|
+
end
|
30
|
+
|
31
|
+
define_generate_old_fields do |msg_obj|
|
32
|
+
raise NotImplementedError.new
|
33
|
+
end
|
34
|
+
|
35
|
+
define_mock_values do
|
36
|
+
{
|
37
|
+
"dea" => "deadbeef", #proc { VCAP.secure_uuid },
|
38
|
+
"app" => proc { Random.rand(100).to_s },
|
39
|
+
"uris" => ["foo.vcap.me"],
|
40
|
+
"host" => "127.0.0.1",
|
41
|
+
"port" => 80,
|
42
|
+
"tags" => {
|
43
|
+
"framework" => "rails3",
|
44
|
+
"runtime" => "ruby18",
|
45
|
+
"component" => "dashboard",
|
46
|
+
},
|
47
|
+
"private_instance_id" => "deadbeef1",#proc { VCAP.secure_uuid },
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#require "vcap/common"
|
2
|
+
|
3
|
+
module Schemata
|
4
|
+
module Router
|
5
|
+
module StartMessage
|
6
|
+
version 1 do
|
7
|
+
include_preschemata
|
8
|
+
|
9
|
+
define_schema do
|
10
|
+
{
|
11
|
+
"id" => String,
|
12
|
+
"version" => String,
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
define_min_version 1
|
17
|
+
|
18
|
+
define_upvert do |old_data|
|
19
|
+
raise NotImplmenetedError.new
|
20
|
+
end
|
21
|
+
|
22
|
+
define_generate_old_fields do |msg_obj|
|
23
|
+
raise NotImplementedError.new
|
24
|
+
end
|
25
|
+
|
26
|
+
define_mock_values do
|
27
|
+
{
|
28
|
+
"id" => "deadbeef", #proc { VCAP.secure_uuid },
|
29
|
+
"version" => "0.1.0",
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'schemata/helpers/hash_copy'
|
2
|
+
require 'schemata/helpers/stringify'
|
3
|
+
|
4
|
+
describe Schemata::HashCopyHelpers do
|
5
|
+
describe "#deep_copy" do
|
6
|
+
it "should deep copy nil" do
|
7
|
+
copy = Schemata::HashCopyHelpers.deep_copy(nil)
|
8
|
+
copy.should == nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should deep copy a given string" do
|
12
|
+
original = "foo"
|
13
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
14
|
+
copy.should be_instance_of String
|
15
|
+
copy.should == original
|
16
|
+
copy.object_id.should_not == original.object_id
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should deep copy a given boolean" do
|
20
|
+
Schemata::HashCopyHelpers.deep_copy(true).
|
21
|
+
should be_an_instance_of TrueClass
|
22
|
+
Schemata::HashCopyHelpers.deep_copy(false).
|
23
|
+
should be_an_instance_of FalseClass
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should deep copy a given numeric type" do
|
27
|
+
original = 0
|
28
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
29
|
+
copy.should == original
|
30
|
+
copy.should be_an_instance_of Fixnum
|
31
|
+
|
32
|
+
# set original to be max fixnum + 1
|
33
|
+
original = 2**(0.size * 8 - 2)
|
34
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
35
|
+
copy.should == original
|
36
|
+
copy.should be_an_instance_of Bignum
|
37
|
+
|
38
|
+
original = 0.0
|
39
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
40
|
+
copy.should == original
|
41
|
+
copy.should be_an_instance_of Float
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should deep copy a given hash" do
|
45
|
+
original = {"foo" => "bar"}
|
46
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
47
|
+
copy.should be_instance_of Hash
|
48
|
+
copy.should == original
|
49
|
+
|
50
|
+
copy.object_id.should_not == original.object_id
|
51
|
+
copy["foo"].object_id.should_not == original["foo"].object_id
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should deep copy a given array" do
|
55
|
+
original = [1, 2, "hello"]
|
56
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
57
|
+
copy.should be_instance_of Array
|
58
|
+
copy.should == original
|
59
|
+
|
60
|
+
copy.object_id.should_not == original.object_id
|
61
|
+
# only check object_id of String object
|
62
|
+
copy[2].object_id.should_not == original[2].object_id
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should deep copy nested types" do
|
66
|
+
original = {
|
67
|
+
"foo" => "bar",
|
68
|
+
"inner" => {
|
69
|
+
"hello" => "goodbye",
|
70
|
+
},
|
71
|
+
}
|
72
|
+
copy = Schemata::HashCopyHelpers.deep_copy(original)
|
73
|
+
copy.should be_instance_of Hash
|
74
|
+
copy.should == original
|
75
|
+
|
76
|
+
copy.object_id.should_not == original.object_id
|
77
|
+
copy["foo"].object_id.should_not == original["foo"].object_id
|
78
|
+
copy["inner"].object_id.should_not == original["inner"].object_id
|
79
|
+
copy["inner"]["hello"].object_id.
|
80
|
+
should_not == original["inner"]["hello"].object_id
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise error for unknown type" do
|
84
|
+
klass = Class.new
|
85
|
+
expect do
|
86
|
+
Schemata::HashCopyHelpers.deep_copy(klass.new)
|
87
|
+
end.to raise_error(described_class::CopyError, /Unexpected class: /)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#stringify" do
|
92
|
+
it "should stringify nil" do
|
93
|
+
str = Schemata::HashCopyHelpers.stringify(nil)
|
94
|
+
str.should == nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should stringify a string" do
|
98
|
+
original = "foo"
|
99
|
+
str = Schemata::HashCopyHelpers.stringify(original)
|
100
|
+
str.should == "foo"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should stringify a symbol" do
|
104
|
+
original = :foo
|
105
|
+
str = Schemata::HashCopyHelpers.stringify(original)
|
106
|
+
str.should == "foo"
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should stringify a hash" do
|
110
|
+
original = { "foo" => :foo }
|
111
|
+
str = Schemata::HashCopyHelpers.stringify(original)
|
112
|
+
str.should == { "foo" => "foo" }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'schemata/common/parsed_msg'
|
2
|
+
|
3
|
+
describe Schemata::ParsedMessage do
|
4
|
+
describe "#new" do
|
5
|
+
it "should raise an error if 'min_version' is missing" do
|
6
|
+
json = '{
|
7
|
+
"V10" : { "foo" : "bar" }
|
8
|
+
}'
|
9
|
+
expect {
|
10
|
+
msg = Schemata::ParsedMessage.new(json)
|
11
|
+
}.to raise_error(Schemata::DecodeError)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should raise an error if there are non-Vxx hashes" do
|
15
|
+
json = '{
|
16
|
+
"min_version" : 10,
|
17
|
+
"foo" : "bar"
|
18
|
+
}'
|
19
|
+
expect {
|
20
|
+
msg = Schemata::ParsedMessage.new(json)
|
21
|
+
}.to raise_error(Schemata::DecodeError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an error if there are no Vxx hashes" do
|
25
|
+
json = '{
|
26
|
+
"min_version" : 10
|
27
|
+
}'
|
28
|
+
expect {
|
29
|
+
msg = Schemata::ParsedMessage.new(json)
|
30
|
+
}.to raise_error(Schemata::DecodeError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return a new Schemata::ParsedMessage if the hash is valid" do
|
34
|
+
json = '{
|
35
|
+
"min_version" : 10,
|
36
|
+
"V10" : { "foo" : "bar" },
|
37
|
+
"V11" : { "foo" : "bar"}
|
38
|
+
}'
|
39
|
+
msg = Schemata::ParsedMessage.new(json)
|
40
|
+
msg.min_version.should == 10
|
41
|
+
msg.version.should == 11
|
42
|
+
msg.contents["V10"]["foo"].should == "bar"
|
43
|
+
msg.contents["V11"]["foo"].should == "bar"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'support/helpers'
|
2
|
+
|
3
|
+
shared_examples "a schemata component" do
|
4
|
+
|
5
|
+
described_class.constants.select { |x| x != :VERSION }.each do |msg_type|
|
6
|
+
describe ".mock_#{decamelize(msg_type.to_s)}" do
|
7
|
+
versions = described_class::const_get(msg_type).constants.select { |x| x =~ /V[0-9]+/ }
|
8
|
+
versions.map { |x| x = x.to_s[1..-1].to_i }.each do |version|
|
9
|
+
it_behaves_like "a mocking method", version do
|
10
|
+
let(:message_type) { described_class::const_get(msg_type) }
|
11
|
+
let(:message_type_name) { msg_type.to_s }
|
12
|
+
let(:component) { described_class }
|
13
|
+
let(:component_name) { component.name.split("::")[1] }
|
14
|
+
|
15
|
+
let(:mock_method) { "mock_#{decamelize(msg_type)}"}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
shared_examples "a mocking method" do |version|
|
23
|
+
|
24
|
+
context "when current_version is #{version}" do
|
25
|
+
before :each do
|
26
|
+
set_current_version(message_type, version)
|
27
|
+
end
|
28
|
+
|
29
|
+
after :each do
|
30
|
+
reset_version(message_type)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return a V#{version} object if called with no argument" do
|
34
|
+
msg_obj = component.send(mock_method)
|
35
|
+
msg_obj.class.should == message_type::const_get("V#{version}")
|
36
|
+
end
|
37
|
+
|
38
|
+
1.upto(version) do |i|
|
39
|
+
it "should return a V#{i} object if called with input #{i}" do
|
40
|
+
msg_obj = component.send(mock_method, i)
|
41
|
+
msg_obj.class.should == message_type::const_get("V#{i}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should raise an error if called with input > #{version}" do
|
46
|
+
expect {
|
47
|
+
msg_obj = component.send(mock_method, version + 1)
|
48
|
+
}.to raise_error(NameError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|