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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +23 -0
- data/lib/thrift-validator.rb +1 -0
- data/lib/thrift/validator.rb +32 -0
- data/lib/thrift/validator/version.rb +5 -0
- data/test/acceptance_test.rb +163 -0
- data/test/exceptions_test.rb +25 -0
- data/test/gen-rb/test_constants.rb +9 -0
- data/test/gen-rb/test_types.rb +185 -0
- data/test/test.thrift +42 -0
- data/test/test_helper.rb +10 -0
- data/thrift-validator.gemspec +25 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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,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,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
|
+
|
data/test/test.thrift
ADDED
@@ -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
|
+
}
|
data/test/test_helper.rb
ADDED
@@ -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
|