anujdas-thrift-validator 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7396a4d4b0ade73560af2af1a3582515b227011fa4f9e73bf139200c3cff328c
4
+ data.tar.gz: 2872e2cfb10594cdfc6239a2da1e363d0506d5092cb4e474eaafec1f84837a83
5
+ SHA512:
6
+ metadata.gz: 6b12095b4e3a0a7532bddaa5bb8d2237c14aebf59b776961dd14c307c77c528e06e76eddb152debd17c20d3865422acb7b4de04798aa00fdd320369e7416b716
7
+ data.tar.gz: fc9838ce5cfe1f42a7bb182568ddbc384ca04786d96cda2022ced77c58150c7d011ed35f89c13c3ada0cc6edb94ee9a33b4d7754c724afe0423309ea45220a99
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in thrift-validator.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 ahawkins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ # Thrift::Validator
2
+
3
+ Recursive [thrift][] struct validator. The thrift library out of the box does
4
+ not validated nested structs; This library fixes that problem. Rather than
5
+ monkey-patching Thrift, this library includes a class to validate objects
6
+ recursively.
7
+
8
+ Here's an example from this library's tests. Given the following schema:
9
+
10
+ ```thrift
11
+ struct SimpleStruct {
12
+ 1: required string required_string,
13
+ 2: optional string optional_string,
14
+ }
15
+
16
+ struct NestedExample {
17
+ 1: required SimpleStruct required_struct,
18
+ 2: optional SimpleStruct optional_struct,
19
+ }
20
+ ```
21
+
22
+ This library provides:
23
+
24
+ ```ruby
25
+ struct = SimpleStruct.new
26
+ nested = NestedStruct.new(required_struct: struct)
27
+
28
+ # Method defined by the Thrift library
29
+ struct.validate # => Thrift::ProtocolException
30
+
31
+ # Thrift only validates fields set as required on this instance. Since
32
+ # `required_struct` is non-nil, validation succeeds. Also note that Thrift
33
+ # does not validate semantics of the assigned objects, so assigning an
34
+ # invalid struct will pass its validation method.
35
+ nested.validate # => true
36
+
37
+ # With the validator
38
+ Thrift::Validator.new.validate(nested) # => Thrift::ProtocolException
39
+ ```
40
+
41
+ ## Semantics enforced
42
+
43
+ * all original Thrift validation semantics
44
+ * `optional` or `required` `struct` types
45
+ * `optional` or `required` `list<struct>` items
46
+ * `optional` or `required` `set<struct>` items
47
+ * `optional` or `required` `map` types with `struct` keys and/or values
48
+
49
+ ## Exception handling
50
+
51
+ Due to the recursive nature of `thrift-validator`, the validation
52
+ errors raised by Thrift become less than helpful. In order
53
+ to provide more information, the resulting `Thrift::ProtocolException`
54
+ message is prefixed with the type where the error occurred. For
55
+ example:
56
+
57
+ ```ruby
58
+ # Without thrift-validator
59
+ > struct.validate
60
+ Thrift::ProtocolException: Required field required_string is unset!
61
+
62
+ # With thrift-validator
63
+ > Thrift::Validator.new.validate(struct)
64
+ Thrift::ProtocolException: SimpleStruct: Required field required_string is unset!
65
+ ```
66
+
67
+ This feature becomes especially useful with nested structs, where validation
68
+ may fail at any depth.
69
+
70
+ ## Installation
71
+
72
+ Add this line to your application's Gemfile:
73
+
74
+ ```ruby
75
+ gem 'thrift-validator'
76
+ ```
77
+
78
+ And then execute:
79
+
80
+ $ bundle
81
+
82
+ Or install it yourself as:
83
+
84
+ $ gem install thrift-validator
85
+
86
+ ## Testing
87
+
88
+ First, install a `thrift` compiler on your platform (e.g., `brew install
89
+ thrift`, `sudo apt install thrift`). Then run:
90
+
91
+ $ rake test
92
+
93
+ ## Contributing
94
+
95
+ 1. Fork it ( https://github.com/saltside/thrift-validator-ruby/fork )
96
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
97
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
98
+ 4. Push to the branch (`git push origin my-new-feature`)
99
+ 5. Create a new Pull Request
100
+
101
+ [thrift]: https://thrift.apache.org
@@ -0,0 +1,23 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ THRIFT_IN = 'test/test.thrift'
5
+ THRIFT_OUT = Rake::FileList['test/gen-rb/test_constants.rb', 'test/gen-rb/test_types.rb']
6
+
7
+ THRIFT_OUT.each do |output|
8
+ file output => THRIFT_IN do
9
+ sh 'thrift', '-o', 'test', '--gen', 'rb', THRIFT_IN
10
+ end
11
+ end
12
+
13
+ desc 'Cleans generated files from workspace'
14
+ task :clean do
15
+ rm THRIFT_OUT
16
+ end
17
+
18
+ Rake::TestTask.new do |t|
19
+ t.test_files = Rake::FileList['test/**/*_test.rb']
20
+ end
21
+ task test: THRIFT_OUT # add dependency
22
+
23
+ task default: :test
@@ -0,0 +1 @@
1
+ require 'thrift/validator'
@@ -0,0 +1,32 @@
1
+ require 'thrift/validator/version'
2
+ require 'thrift'
3
+
4
+ module Thrift
5
+ class Validator
6
+ DEFAULT_TYPE = Thrift::ProtocolException::UNKNOWN
7
+
8
+ # @param structs [Object] any Thrift value -- struct, primitive, or a collection thereof
9
+ # @raise [Thrift::ProtocolException] if any deviation from schema was detected
10
+ # @return [nil] if no problems were detected; note that this does not include type checks
11
+ def validate(structs)
12
+ # handle anything -- Struct, Union, List, Set, Map, primitives...
13
+ Array(structs).flatten.each do |struct|
14
+ begin
15
+ # only Structs/Unions can be validated (see Thrift.type_checking for another option)
16
+ next unless struct.is_a?(Struct_Union)
17
+ # raises a ProtocolException if this specific struct is invalid
18
+ struct.validate
19
+ # recursively validate all fields except unset union fields
20
+ struct.struct_fields.each_value do |f|
21
+ next if struct.is_a?(Union) && struct.get_set_field != f[:name].to_sym
22
+ validate(struct.send(f[:name]))
23
+ end
24
+ rescue ProtocolException => e
25
+ raise ProtocolException.new(e.type, "#{struct.class}: #{e.message}")
26
+ rescue => e # union validation raises StandardError...
27
+ raise ProtocolException.new(DEFAULT_TYPE, "#{struct.class}: #{e.message}")
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ module Thrift
2
+ class Validator
3
+ VERSION = '0.2.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,163 @@
1
+ require_relative 'test_helper'
2
+
3
+ class AcceptanceTest < MiniTest::Unit::TestCase
4
+ def test_follows_thrift_semantics
5
+ struct = SimpleStruct.new required_string: nil, optional_string: nil
6
+ refute_valid struct
7
+ end
8
+
9
+ def test_fails_if_a_required_nested_struct_is_invalid
10
+ struct = NestedExample.new
11
+ struct.required_struct = SimpleStruct.new
12
+ refute_valid struct
13
+ end
14
+
15
+ def test_fails_if_an_optional_nested_struct_is_valid
16
+ struct = NestedExample.new
17
+ struct.required_struct = SimpleStruct.new required_string: 'foo'
18
+ struct.optional_struct = SimpleStruct.new
19
+ refute_valid struct
20
+ end
21
+
22
+ def test_passes_if_nested_structs_are_valid
23
+ struct = NestedExample.new
24
+ struct.required_struct = SimpleStruct.new required_string: 'foo'
25
+ struct.optional_struct = SimpleStruct.new required_string: 'bar'
26
+ assert_valid struct
27
+ end
28
+
29
+ def test_passes_if_nested_optional_struct_is_omitted
30
+ struct = NestedExample.new
31
+ struct.required_struct = SimpleStruct.new required_string: 'foo'
32
+ assert_valid struct
33
+ end
34
+
35
+ def test_fails_if_a_nested_list_item_is_invalid
36
+ struct = ListExample.new
37
+ struct.required_list = [ SimpleStruct.new ]
38
+ refute_valid struct
39
+ end
40
+
41
+ def test_fails_if_a_nested_list_item_is_invalid
42
+ struct = ListExample.new
43
+ struct.required_list = [ SimpleStruct.new({ required_string: 'foo' }) ]
44
+ struct.optional_list = [ SimpleStruct.new ]
45
+ refute_valid struct
46
+ end
47
+
48
+ def test_passes_if_given_valid_list_items
49
+ struct = ListExample.new
50
+ struct.required_list = [ SimpleStruct.new({ required_string: 'foo' }) ]
51
+ struct.optional_list = [ SimpleStruct.new({ required_string: 'bar' }) ]
52
+ assert_valid struct
53
+ end
54
+
55
+ def test_passes_with_primitives_list
56
+ struct = StringListExample.new
57
+ struct.required_list = [ 'foo' ]
58
+ assert_valid struct
59
+ end
60
+
61
+ def test_fails_if_a_nested_set_item_is_invalid
62
+ struct = SetExample.new
63
+ struct.required_set = Set.new([ SimpleStruct.new ])
64
+ refute_valid struct
65
+ end
66
+
67
+ def test_fails_if_a_nested_set_item_is_invalid
68
+ struct = SetExample.new
69
+ struct.required_set = Set.new([ SimpleStruct.new({ required_string: 'foo' }) ])
70
+ struct.optional_set = Set.new([ SimpleStruct.new ])
71
+ refute_valid struct
72
+ end
73
+
74
+ def test_passes_if_given_valid_set_items
75
+ struct = SetExample.new
76
+ struct.required_set = Set.new([ SimpleStruct.new({ required_string: 'foo' }) ])
77
+ struct.optional_set = Set.new([ SimpleStruct.new({ required_string: 'bar' }) ])
78
+ assert_valid struct
79
+ end
80
+
81
+ def test_passes_with_primitives_set
82
+ struct = StringSetExample.new
83
+ struct.required_set = Set.new([ 'foo' ])
84
+ assert_valid struct
85
+ end
86
+
87
+ def test_fails_if_nested_map_key_is_invalid
88
+ struct = MapKeyExample.new
89
+ struct.required_map = { SimpleStruct.new => 'foo' }
90
+ refute_valid struct
91
+ end
92
+
93
+ def test_fails_if_nested_map_key_is_invalid
94
+ struct = MapKeyExample.new
95
+ struct.required_map = { SimpleStruct.new({ required_string: 'foo' }) => 'foo' }
96
+ struct.optional_map = { SimpleStruct.new => 'foo' }
97
+ refute_valid struct
98
+ end
99
+
100
+ def test_passess_when_valid_map_keys_are_given
101
+ struct = MapKeyExample.new
102
+ struct.required_map = { SimpleStruct.new({ required_string: 'foo' }) => 'foo' }
103
+ struct.optional_map = { SimpleStruct.new({ required_string: 'bar' }) => 'bar' }
104
+ assert_valid struct
105
+ end
106
+
107
+ def test_fails_if_nested_map_value_is_invalid
108
+ struct = MapValueExample.new
109
+ struct.required_map = { 'foo' => SimpleStruct.new }
110
+ refute_valid struct
111
+ end
112
+
113
+ def test_fails_if_optional_nested_map_value_is_invalid
114
+ struct = MapValueExample.new
115
+ struct.required_map = { 'foo' => SimpleStruct.new({ required_string: 'foo' }) }
116
+ struct.required_map = { 'foo' => SimpleStruct.new }
117
+ refute_valid struct
118
+ end
119
+
120
+ def test_passes_if_optional_and_required_valid_map_values_are_given
121
+ struct = MapValueExample.new
122
+ struct.required_map = { 'foo' => SimpleStruct.new({ required_string: 'foo' }) }
123
+ struct.optional_map = { 'foo' => SimpleStruct.new({ required_string: 'bar' }) }
124
+ assert_valid struct
125
+ end
126
+
127
+ def test_fails_if_no_union_fields_set
128
+ union = UnionExample.new
129
+ refute_valid union
130
+ end
131
+
132
+ def test_fails_if_union_set_field_is_invalid
133
+ union = UnionExample.new
134
+ union.primary = [SimpleStruct.new]
135
+ refute_valid union
136
+ end
137
+
138
+ def test_passes_if_union_set_field_is_valid
139
+ union = UnionExample.new
140
+ union.primary = [SimpleStruct.new(required_string: 'foo')]
141
+ assert_valid union
142
+ end
143
+
144
+ def test_passes_if_unions_alternate_value_is_provided
145
+ union = UnionExample.new
146
+ union.alternate = 'foo'
147
+ assert_valid union
148
+ end
149
+
150
+ private
151
+
152
+ def refute_valid(struct)
153
+ assert_raises Thrift::ProtocolException, 'Incorrect validation' do
154
+ Thrift::Validator.new.validate(struct)
155
+ end
156
+ end
157
+
158
+ def assert_valid(struct)
159
+ Thrift::Validator.new.validate(struct)
160
+ rescue Thrift::ProtocolException => ex
161
+ flunk ex
162
+ end
163
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ExceptionsTest < MiniTest::Unit::TestCase
4
+ def test_exception_message_contains_class_name
5
+ # The error is in NestedExample - required_struct is unset
6
+ struct = NestedExample.new required_struct: nil
7
+
8
+ ex = assert_raises Thrift::ProtocolException do
9
+ Thrift::Validator.new.validate(struct)
10
+ end
11
+ assert_match /NestedExample/, ex.message
12
+ end
13
+
14
+ def test_exception_message_contains_nested_class_name
15
+ # Here NestedExample is valid, but the error is one level down
16
+ # in SimpleStruct (its required_string is unset)
17
+ struct = NestedExample.new
18
+ struct.required_struct = SimpleStruct.new required_string: nil
19
+
20
+ ex = assert_raises Thrift::ProtocolException do
21
+ Thrift::Validator.new.validate(struct)
22
+ end
23
+ assert_match /SimpleStruct/, ex.message
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.9.2)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'thrift'
8
+ require 'test_types'
9
+
@@ -0,0 +1,185 @@
1
+ #
2
+ # Autogenerated by Thrift Compiler (0.9.2)
3
+ #
4
+ # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5
+ #
6
+
7
+ require 'thrift'
8
+
9
+ class SimpleStruct
10
+ include ::Thrift::Struct, ::Thrift::Struct_Union
11
+ REQUIRED_STRING = 1
12
+ OPTIONAL_STRING = 2
13
+
14
+ FIELDS = {
15
+ REQUIRED_STRING => {:type => ::Thrift::Types::STRING, :name => 'required_string'},
16
+ OPTIONAL_STRING => {:type => ::Thrift::Types::STRING, :name => 'optional_string', :optional => true}
17
+ }
18
+
19
+ def struct_fields; FIELDS; end
20
+
21
+ def validate
22
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_string is unset!') unless @required_string
23
+ end
24
+
25
+ ::Thrift::Struct.generate_accessors self
26
+ end
27
+
28
+ class NestedExample
29
+ include ::Thrift::Struct, ::Thrift::Struct_Union
30
+ REQUIRED_STRUCT = 1
31
+ OPTIONAL_STRUCT = 2
32
+
33
+ FIELDS = {
34
+ REQUIRED_STRUCT => {:type => ::Thrift::Types::STRUCT, :name => 'required_struct', :class => ::SimpleStruct},
35
+ OPTIONAL_STRUCT => {:type => ::Thrift::Types::STRUCT, :name => 'optional_struct', :class => ::SimpleStruct, :optional => true}
36
+ }
37
+
38
+ def struct_fields; FIELDS; end
39
+
40
+ def validate
41
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_struct is unset!') unless @required_struct
42
+ end
43
+
44
+ ::Thrift::Struct.generate_accessors self
45
+ end
46
+
47
+ class ListExample
48
+ include ::Thrift::Struct, ::Thrift::Struct_Union
49
+ REQUIRED_LIST = 1
50
+ OPTIONAL_LIST = 2
51
+
52
+ FIELDS = {
53
+ REQUIRED_LIST => {:type => ::Thrift::Types::LIST, :name => 'required_list', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}},
54
+ OPTIONAL_LIST => {:type => ::Thrift::Types::LIST, :name => 'optional_list', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :optional => true}
55
+ }
56
+
57
+ def struct_fields; FIELDS; end
58
+
59
+ def validate
60
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_list is unset!') unless @required_list
61
+ end
62
+
63
+ ::Thrift::Struct.generate_accessors self
64
+ end
65
+
66
+ class StringListExample
67
+ include ::Thrift::Struct, ::Thrift::Struct_Union
68
+ REQUIRED_LIST = 1
69
+
70
+ FIELDS = {
71
+ REQUIRED_LIST => {:type => ::Thrift::Types::LIST, :name => 'required_list', :element => {:type => ::Thrift::Types::STRING}}
72
+ }
73
+
74
+ def struct_fields; FIELDS; end
75
+
76
+ def validate
77
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_list is unset!') unless @required_list
78
+ end
79
+
80
+ ::Thrift::Struct.generate_accessors self
81
+ end
82
+
83
+ class StringSetExample
84
+ include ::Thrift::Struct, ::Thrift::Struct_Union
85
+ REQUIRED_SET = 1
86
+
87
+ FIELDS = {
88
+ REQUIRED_SET => {:type => ::Thrift::Types::SET, :name => 'required_set', :element => {:type => ::Thrift::Types::STRING}}
89
+ }
90
+
91
+ def struct_fields; FIELDS; end
92
+
93
+ def validate
94
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_set is unset!') unless @required_set
95
+ end
96
+
97
+ ::Thrift::Struct.generate_accessors self
98
+ end
99
+
100
+ class SetExample
101
+ include ::Thrift::Struct, ::Thrift::Struct_Union
102
+ REQUIRED_SET = 1
103
+ OPTIONAL_SET = 2
104
+
105
+ FIELDS = {
106
+ REQUIRED_SET => {:type => ::Thrift::Types::SET, :name => 'required_set', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}},
107
+ OPTIONAL_SET => {:type => ::Thrift::Types::SET, :name => 'optional_set', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :optional => true}
108
+ }
109
+
110
+ def struct_fields; FIELDS; end
111
+
112
+ def validate
113
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_set is unset!') unless @required_set
114
+ end
115
+
116
+ ::Thrift::Struct.generate_accessors self
117
+ end
118
+
119
+ class MapKeyExample
120
+ include ::Thrift::Struct, ::Thrift::Struct_Union
121
+ REQUIRED_MAP = 1
122
+ OPTIONAL_MAP = 2
123
+
124
+ FIELDS = {
125
+ REQUIRED_MAP => {:type => ::Thrift::Types::MAP, :name => 'required_map', :key => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :value => {:type => ::Thrift::Types::STRING}},
126
+ OPTIONAL_MAP => {:type => ::Thrift::Types::MAP, :name => 'optional_map', :key => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :value => {:type => ::Thrift::Types::STRING}, :optional => true}
127
+ }
128
+
129
+ def struct_fields; FIELDS; end
130
+
131
+ def validate
132
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_map is unset!') unless @required_map
133
+ end
134
+
135
+ ::Thrift::Struct.generate_accessors self
136
+ end
137
+
138
+ class MapValueExample
139
+ include ::Thrift::Struct, ::Thrift::Struct_Union
140
+ REQUIRED_MAP = 1
141
+ OPTIONAL_MAP = 2
142
+
143
+ FIELDS = {
144
+ REQUIRED_MAP => {:type => ::Thrift::Types::MAP, :name => 'required_map', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}},
145
+ OPTIONAL_MAP => {:type => ::Thrift::Types::MAP, :name => 'optional_map', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :optional => true}
146
+ }
147
+
148
+ def struct_fields; FIELDS; end
149
+
150
+ def validate
151
+ raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Required field required_map is unset!') unless @required_map
152
+ end
153
+
154
+ ::Thrift::Struct.generate_accessors self
155
+ end
156
+
157
+ class UnionExample < ::Thrift::Union
158
+ include ::Thrift::Struct_Union
159
+ class << self
160
+ def primary(val)
161
+ UnionExample.new(:primary, val)
162
+ end
163
+
164
+ def alternate(val)
165
+ UnionExample.new(:alternate, val)
166
+ end
167
+ end
168
+
169
+ PRIMARY = 1
170
+ ALTERNATE = 2
171
+
172
+ FIELDS = {
173
+ PRIMARY => {:type => ::Thrift::Types::LIST, :name => 'primary', :element => {:type => ::Thrift::Types::STRUCT, :class => ::SimpleStruct}, :optional => true},
174
+ ALTERNATE => {:type => ::Thrift::Types::STRING, :name => 'alternate', :optional => true}
175
+ }
176
+
177
+ def struct_fields; FIELDS; end
178
+
179
+ def validate
180
+ raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?
181
+ end
182
+
183
+ ::Thrift::Union.generate_accessors self
184
+ end
185
+
@@ -0,0 +1,42 @@
1
+ struct SimpleStruct {
2
+ 1: required string required_string
3
+ 2: optional string optional_string
4
+ }
5
+
6
+ struct NestedExample {
7
+ 1: required SimpleStruct required_struct
8
+ 2: optional SimpleStruct optional_struct
9
+ }
10
+
11
+ struct ListExample {
12
+ 1: required list<SimpleStruct> required_list
13
+ 2: optional list<SimpleStruct> optional_list
14
+ }
15
+
16
+ struct StringListExample {
17
+ 1: required list<string> required_list
18
+ }
19
+
20
+ struct StringSetExample {
21
+ 1: required set<string> required_set
22
+ }
23
+
24
+ struct SetExample {
25
+ 1: required set<SimpleStruct> required_set
26
+ 2: optional set<SimpleStruct> optional_set
27
+ }
28
+
29
+ struct MapKeyExample {
30
+ 1: required map<SimpleStruct, string> required_map
31
+ 2: optional map<SimpleStruct, string> optional_map
32
+ }
33
+
34
+ struct MapValueExample {
35
+ 1: required map<string, SimpleStruct> required_map
36
+ 2: optional map<string, SimpleStruct> optional_map
37
+ }
38
+
39
+ union UnionExample {
40
+ 1: list<SimpleStruct> primary
41
+ 2: string alternate
42
+ }
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+
3
+ $LOAD_PATH << File.expand_path('../gen-rb', __FILE__)
4
+
5
+ require 'thrift-validator'
6
+
7
+ Thrift.type_checking = true
8
+
9
+ require 'test_types'
10
+ require 'minitest/autorun'
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'thrift/validator/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'anujdas-thrift-validator'
8
+ spec.version = Thrift::Validator::VERSION
9
+ spec.authors = ['ahawkins', 'anujdas']
10
+ spec.email = ['adam@hawkins.io', 'anujdas@gmail.com']
11
+ spec.summary = %q{Recursive thrift struct validator}
12
+ spec.description = %q{}
13
+ spec.homepage = 'https://github.com/anujdas/thrift-validator-ruby'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.test_files = spec.files.grep(%r{^test/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'thrift', '~> 0.9'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.7'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'minitest', '~> 5.11'
25
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: anujdas-thrift-validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - ahawkins
8
+ - anujdas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-05-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thrift
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.7'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.7'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '10.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '10.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: minitest
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '5.11'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '5.11'
70
+ description: ''
71
+ email:
72
+ - adam@hawkins.io
73
+ - anujdas@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/thrift-validator.rb
84
+ - lib/thrift/validator.rb
85
+ - lib/thrift/validator/version.rb
86
+ - test/acceptance_test.rb
87
+ - test/exceptions_test.rb
88
+ - test/gen-rb/test_constants.rb
89
+ - test/gen-rb/test_types.rb
90
+ - test/test.thrift
91
+ - test/test_helper.rb
92
+ - thrift-validator.gemspec
93
+ homepage: https://github.com/anujdas/thrift-validator-ruby
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.7.6
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Recursive thrift struct validator
117
+ test_files:
118
+ - test/acceptance_test.rb
119
+ - test/exceptions_test.rb
120
+ - test/gen-rb/test_constants.rb
121
+ - test/gen-rb/test_types.rb
122
+ - test/test.thrift
123
+ - test/test_helper.rb