service_contract 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8533a9479365f0e1fe622726619e7d269df19251
4
- data.tar.gz: 152c90e5d6a2ce67720ba9de55998225801d2feb
3
+ metadata.gz: 8cb40a77b33371d743328e30c58742c07a57d77c
4
+ data.tar.gz: b9bc84d00c6147ef1c3ecfec18ad7753cf17ec89
5
5
  SHA512:
6
- metadata.gz: b13fb54905469260e43b5bc26c2840ca2ddfc32e35a3a240b884070aec49ba27ecafb6ba5b8ae667a8cee83593b6b0a4ebfb4d6fe50eda0f5472afc3f76f382c
7
- data.tar.gz: 9aa632cd295c6a161544150cb0a5d83568fdf3d6dbf0bd1e09ca77bba52d763c33e3928fed2a2f63d53652497f44f736d327247ede0aec0ec05b7ffb1f5b4335
6
+ metadata.gz: b18b92ce0dcd4eefa1dac486dc51e98bfa4b6353717fb0175b0781b297c0f94694f85942071b49b40d9ea04069c3a9ae6b08b5e6daf3cf9fe7b6fc46f55b6863
7
+ data.tar.gz: 8f02a7a4235704d826932c5cb5b3d1c9b7f9f2ae9ce1a43f277af081b3d19a6020984202ffe6e922eb57b5eae24db855452c4a7958138d25cee09324814f462b
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  *.a
14
14
  mkmf.log
15
15
  *.gem
16
+ .idea
@@ -54,6 +54,8 @@ module ServiceContract
54
54
 
55
55
  # seems kinda hacky
56
56
  def member?
57
+ return false if parameters.empty?
58
+
57
59
  first_param_type = parameters.first.type
58
60
  first_param_type.complex? && first_param_type.name == protocol.main_type
59
61
  end
@@ -21,6 +21,11 @@ module ServiceContract
21
21
  File.join(service.path, resource_name)
22
22
  end
23
23
 
24
+ def main_type
25
+ # convert protocol name to a class like name. i.e. "city_state" => "CityState"
26
+ name.split("_").map{|o| o.capitalize}.join
27
+ end
28
+
24
29
  protected
25
30
 
26
31
  def resource_name
@@ -16,7 +16,9 @@ module ServiceContract
16
16
  end
17
17
 
18
18
  def to_s
19
- name
19
+ return name unless union?
20
+
21
+ union_types.map(&:name).join(", ")
20
22
  end
21
23
 
22
24
  def subtype
@@ -36,6 +38,10 @@ module ServiceContract
36
38
  type_string == "record"
37
39
  end
38
40
 
41
+ def union?
42
+ type_string == "union"
43
+ end
44
+
39
45
  def valid_ruby_types
40
46
  case type_string
41
47
  when "array"
@@ -48,6 +54,10 @@ module ServiceContract
48
54
  [Float]
49
55
  when "boolean"
50
56
  [TrueClass, FalseClass]
57
+ when "null"
58
+ [NilClass]
59
+ when "union"
60
+ union_types.map(&:valid_ruby_types).flatten
51
61
  else # a complex type
52
62
  [Hash]
53
63
  end
@@ -55,6 +65,10 @@ module ServiceContract
55
65
 
56
66
  protected
57
67
 
68
+ def union_types
69
+ definition.schemas.map{|schema| Type.build(schema)}
70
+ end
71
+
58
72
  def type_string
59
73
  type = definition.type
60
74
  type = type.type_sym.to_s if type.respond_to?(:type_sym)
@@ -1,3 +1,3 @@
1
1
  module ServiceContract
2
- VERSION = "0.0.10"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -8,7 +8,7 @@ class AssertionsTest < Minitest::Test
8
8
  assert service, "expect to find a service by version"
9
9
  assert_equal "1", service.version
10
10
 
11
- assert_equal 2, service.protocols.length
11
+ assert_equal 3, service.protocols.length
12
12
  protocol = service.protocol("location")
13
13
  endpoint = protocol.endpoint("index")
14
14
 
@@ -41,4 +41,21 @@ class AssertionsTest < Minitest::Test
41
41
  assert_endpoint_response(data, endpoint)
42
42
  end
43
43
 
44
+ def test_union_data_matching
45
+ service = SampleService.find(2)
46
+ assert service, "expect to find a service by version"
47
+
48
+ protocol = service.protocol("search_param")
49
+ endpoint = protocol.endpoint("index")
50
+
51
+ # test can be nil
52
+ assert_endpoint_response([{customer_id: nil}], endpoint)
53
+
54
+ # should be able to be an integer
55
+ assert_endpoint_response([{customer_id: 4}], endpoint)
56
+
57
+ # should be able to be an array of ints
58
+ assert_endpoint_response([{customer_id: [1,2,3]}], endpoint)
59
+ end
60
+
44
61
  end
@@ -0,0 +1,68 @@
1
+ {
2
+ "protocol" : "CityState",
3
+ "namespace" : "Gnomon",
4
+ "types" : [ {
5
+ "type" : "record",
6
+ "name" : "Timestamp",
7
+ "fields" : [ {
8
+ "name" : "timestamp",
9
+ "type" : "int"
10
+ } ]
11
+ }, {
12
+ "type" : "record",
13
+ "name" : "CityState",
14
+ "doc" : "This main class for this protocol",
15
+ "fields" : [ {
16
+ "name" : "id",
17
+ "type" : "int",
18
+ "doc" : "foo"
19
+ }, {
20
+ "name" : "city_id",
21
+ "type" : "int"
22
+ }, {
23
+ "name" : "state_id",
24
+ "type" : "int"
25
+ } ]
26
+ }, {
27
+ "type" : "record",
28
+ "name" : "FetchOption",
29
+ "fields" : [ {
30
+ "name" : "page",
31
+ "type" : "int",
32
+ "default" : 0
33
+ }, {
34
+ "name" : "per_page",
35
+ "type" : "int",
36
+ "default" : 30
37
+ } ]
38
+ } ],
39
+ "messages" : {
40
+ "bogus" : {
41
+ "doc" : "bogus method for testing no parameters",
42
+ "request" : [ ],
43
+ "response" : "null"
44
+ },
45
+ "non_member_method" : {
46
+ "doc" : "method that uses non \"main_type\" as the first parameter is considered non-member",
47
+ "request" : [ {
48
+ "name" : "options",
49
+ "type" : "FetchOption"
50
+ } ],
51
+ "response" : {
52
+ "type" : "array",
53
+ "items" : "CityState"
54
+ }
55
+ },
56
+ "member_method" : {
57
+ "doc" : "method that uses \"main_type\" as the first parameter is considered member",
58
+ "request" : [ {
59
+ "name" : "params",
60
+ "type" : "CityState"
61
+ } ],
62
+ "response" : {
63
+ "type" : "array",
64
+ "items" : "CityState"
65
+ }
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,30 @@
1
+ @namespace("Gnomon")
2
+
3
+ protocol CityState {
4
+
5
+ record Timestamp {
6
+ int timestamp;
7
+ }
8
+
9
+ /** This main class for this protocol */
10
+ record CityState {
11
+ /** foo */
12
+ int id;
13
+ int city_id;
14
+ int state_id;
15
+ }
16
+
17
+ record FetchOption {
18
+ int page = 0;
19
+ int per_page = 30;
20
+ }
21
+
22
+ /** bogus method for testing no parameters */
23
+ void bogus();
24
+
25
+ /** method that uses non "main_type" as the first parameter is considered non-member */
26
+ array<CityState> non_member_method(FetchOption options);
27
+
28
+ /** method that uses "main_type" as the first parameter is considered member */
29
+ array<CityState> member_method(CityState params);
30
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "protocol" : "SearchParam",
3
+ "namespace" : "Gnomon",
4
+ "types" : [ {
5
+ "type" : "record",
6
+ "name" : "SearchParam",
7
+ "fields" : [ {
8
+ "name" : "customer_id",
9
+ "type" : [ "null", "int", {
10
+ "type" : "array",
11
+ "items" : "int"
12
+ } ],
13
+ "doc" : "Required search params"
14
+ } ]
15
+ } ],
16
+ "messages" : {
17
+ "index" : {
18
+ "request" : [ ],
19
+ "response" : {
20
+ "type" : "array",
21
+ "items" : "SearchParam"
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,12 @@
1
+ @namespace("Gnomon")
2
+
3
+ protocol SearchParam {
4
+
5
+ record SearchParam {
6
+ /** Required search params */
7
+ union {null, int, array<int>} customer_id;
8
+ }
9
+
10
+ array<SearchParam> index();
11
+
12
+ }
data/test/service_test.rb CHANGED
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  class ServiceTest < Minitest::Test
4
4
 
5
5
  def test_all
6
- assert_equal(1, SampleService.all.length)
6
+ assert_equal(2, SampleService.all.length)
7
7
  end
8
8
 
9
9
  def test_find
@@ -11,11 +11,66 @@ class ServiceTest < Minitest::Test
11
11
  assert service, "expect to find a service by version"
12
12
  assert_equal "1", service.version
13
13
 
14
- assert_equal 2, service.protocols.length
14
+ assert_equal 3, service.protocols.length
15
15
  protocol = service.protocol("location")
16
16
 
17
17
  assert_equal "location", protocol.name
18
18
  assert_equal 3, protocol.endpoints.length
19
19
  end
20
20
 
21
+ def test_null_params
22
+ # the member? method would error if the endpoint method had no parameters. This test verifies the fix.
23
+ service = SampleService.find(1)
24
+ protocol = service.protocol("city_state")
25
+
26
+ # find the endpoint with no parameters.
27
+ empty_param_endpoints = protocol.endpoints.select{|e| e.parameters.empty?}
28
+ assert !empty_param_endpoints.empty?
29
+
30
+ empty_param_endpoints.each do |endpoint|
31
+ assert_equal(false, endpoint.send("member?"))
32
+ end
33
+ end
34
+
35
+ # The member? method determines if an endpoint is a "member" by looking at its first parameter. If that parameter
36
+ # is equal to the 'main_type' then it is a member, otherwise it is not a member. Main_type is nothing more than the
37
+ # classname of the protocol.
38
+ def test_member_endpoint
39
+ service = SampleService.find(1)
40
+ protocol = service.protocol("city_state")
41
+
42
+ # only one endpoint is a member method, "member_method"
43
+ member_names = protocol.endpoints.select{|e| e.send("member?")}.map(&:name)
44
+ assert_equal(1, member_names.length)
45
+ assert_equal('member_method', member_names.first)
46
+ end
47
+
48
+ def test_non_member_endpoint
49
+ service = SampleService.find(1)
50
+ protocol = service.protocol("city_state")
51
+
52
+ # two endpoints are non member method, "bogus" and "non_member_method"
53
+ non_member_names = protocol.endpoints.select{|e| !e.send("member?")}.map(&:name)
54
+ assert_equal(2, non_member_names.length)
55
+ assert non_member_names.include?('non_member_method')
56
+ assert non_member_names.include?('bogus')
57
+ end
58
+
59
+ def test_union_types
60
+ service = SampleService.find(2)
61
+ protocol = service.protocol('search_param')
62
+
63
+ type = protocol.type('SearchParam')
64
+ assert(type, 'expected to find a SearchParam type')
65
+
66
+ field = type.fields.detect{|field| field.name == 'customer_id'}
67
+ assert(field, 'expected to find a customer_id field')
68
+
69
+ field_type = field.type
70
+
71
+ assert_equal('union', field_type.name)
72
+ assert_equal('null, int, Array(int)', field_type.to_s)
73
+ assert_equal([NilClass, Fixnum, Array], field_type.valid_ruby_types)
74
+ end
75
+
21
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: service_contract
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Ching
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-16 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro
@@ -120,10 +120,14 @@ files:
120
120
  - src/avro-tools-1.7.7.jar
121
121
  - test/assertions_test.rb
122
122
  - test/mock_test.rb
123
+ - test/sample/1/compiled/city_state.avpr
123
124
  - test/sample/1/compiled/location.avpr
124
125
  - test/sample/1/compiled/sales_region.avpr
126
+ - test/sample/1/source/city_state.avdl
125
127
  - test/sample/1/source/location.avdl
126
128
  - test/sample/1/source/sales_region.avdl
129
+ - test/sample/2/compiled/search_param.avpr
130
+ - test/sample/2/source/search_param.avdl
127
131
  - test/service_test.rb
128
132
  - test/test_helper.rb
129
133
  homepage: ''
@@ -153,10 +157,14 @@ summary: Abstract the definition of a service's interface contract
153
157
  test_files:
154
158
  - test/assertions_test.rb
155
159
  - test/mock_test.rb
160
+ - test/sample/1/compiled/city_state.avpr
156
161
  - test/sample/1/compiled/location.avpr
157
162
  - test/sample/1/compiled/sales_region.avpr
163
+ - test/sample/1/source/city_state.avdl
158
164
  - test/sample/1/source/location.avdl
159
165
  - test/sample/1/source/sales_region.avdl
166
+ - test/sample/2/compiled/search_param.avpr
167
+ - test/sample/2/source/search_param.avdl
160
168
  - test/service_test.rb
161
169
  - test/test_helper.rb
162
170
  has_rdoc: