service_contract 0.0.10 → 0.1.0

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.
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: