avro-salsify-fork 1.9.0.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,111 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'test_help'
19
+
20
+ class TestLogicalTypes < Test::Unit::TestCase
21
+ def test_int_date
22
+ schema = Avro::Schema.parse <<-SCHEMA
23
+ { "type": "int", "logicalType": "date" }
24
+ SCHEMA
25
+
26
+ assert_equal 'date', schema.logical_type
27
+ assert_encode_and_decode Date.today, schema
28
+ end
29
+
30
+ def test_int_date_conversion
31
+ type = Avro::LogicalTypes::IntDate
32
+
33
+ assert_equal 5, type.encode(Date.new(1970, 1, 6))
34
+ assert_equal 0, type.encode(Date.new(1970, 1, 1))
35
+ assert_equal -5, type.encode(Date.new(1969, 12, 27))
36
+
37
+ assert_equal Date.new(1970, 1, 6), type.decode(5)
38
+ assert_equal Date.new(1970, 1, 1), type.decode(0)
39
+ assert_equal Date.new(1969, 12, 27), type.decode(-5)
40
+ end
41
+
42
+ def test_timestamp_millis_long
43
+ schema = Avro::Schema.parse <<-SCHEMA
44
+ { "type": "long", "logicalType": "timestamp-millis" }
45
+ SCHEMA
46
+
47
+ # The Time.at format is (seconds, microseconds) since Epoch.
48
+ datum = Time.at(628232400, 12000)
49
+
50
+ assert_equal 'timestamp-millis', schema.logical_type
51
+ assert_encode_and_decode datum, schema
52
+ end
53
+
54
+ def test_timestamp_millis_long_conversion
55
+ type = Avro::LogicalTypes::TimestampMillis
56
+
57
+ now = Time.now.utc
58
+ now_millis = Time.utc(now.year, now.month, now.day, now.hour, now.min, now.sec, now.usec / 1000 * 1000)
59
+
60
+ assert_equal now_millis, type.decode(type.encode(now_millis))
61
+ assert_equal 1432849613221, type.encode(Time.utc(2015, 5, 28, 21, 46, 53, 221000))
62
+ assert_equal 1432849613221, type.encode(DateTime.new(2015, 5, 28, 21, 46, 53.221))
63
+ assert_equal Time.utc(2015, 5, 28, 21, 46, 53, 221000), type.decode(1432849613221)
64
+ end
65
+
66
+ def test_timestamp_micros_long
67
+ schema = Avro::Schema.parse <<-SCHEMA
68
+ { "type": "long", "logicalType": "timestamp-micros" }
69
+ SCHEMA
70
+
71
+ # The Time.at format is (seconds, microseconds) since Epoch.
72
+ datum = Time.at(628232400, 12345)
73
+
74
+ assert_equal 'timestamp-micros', schema.logical_type
75
+ assert_encode_and_decode datum, schema
76
+ end
77
+
78
+ def test_timestamp_micros_long_conversion
79
+ type = Avro::LogicalTypes::TimestampMicros
80
+
81
+ now = Time.now.utc
82
+
83
+ assert_equal now, type.decode(type.encode(now))
84
+ assert_equal 1432849613221843, type.encode(Time.utc(2015, 5, 28, 21, 46, 53, 221843))
85
+ assert_equal 1432849613221843, type.encode(DateTime.new(2015, 5, 28, 21, 46, 53.221843))
86
+ assert_equal Time.utc(2015, 5, 28, 21, 46, 53, 221843), type.decode(1432849613221843)
87
+ end
88
+
89
+ def encode(datum, schema)
90
+ buffer = StringIO.new("")
91
+ encoder = Avro::IO::BinaryEncoder.new(buffer)
92
+
93
+ datum_writer = Avro::IO::DatumWriter.new(schema)
94
+ datum_writer.write(datum, encoder)
95
+
96
+ buffer.string
97
+ end
98
+
99
+ def decode(encoded, schema)
100
+ buffer = StringIO.new(encoded)
101
+ decoder = Avro::IO::BinaryDecoder.new(buffer)
102
+
103
+ datum_reader = Avro::IO::DatumReader.new(schema, schema)
104
+ datum_reader.read(decoder)
105
+ end
106
+
107
+ def assert_encode_and_decode(datum, schema)
108
+ encoded = encode(datum, schema)
109
+ assert_equal datum, decode(encoded, schema)
110
+ end
111
+ end
@@ -0,0 +1,199 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'test_help'
18
+
19
+ class TestProtocol < Test::Unit::TestCase
20
+
21
+ class ExampleProtocol
22
+ attr_reader :protocol_string, :valid, :name
23
+ attr_accessor :comment
24
+ def initialize(protocol_string, name=nil, comment='')
25
+ @protocol_string = protocol_string
26
+ @name = name || protocol_string # default to schema_string for name
27
+ @comment = comment
28
+ end
29
+ end
30
+ #
31
+ # Example Protocols
32
+ #
33
+
34
+ EXAMPLES = [
35
+ ExampleProtocol.new(<<-EOS, true),
36
+ {
37
+ "namespace": "com.acme",
38
+ "protocol": "HelloWorld",
39
+
40
+ "types": [
41
+ {"name": "Greeting", "type": "record", "fields": [
42
+ {"name": "message", "type": "string"}]},
43
+ {"name": "Curse", "type": "error", "fields": [
44
+ {"name": "message", "type": "string"}]}
45
+ ],
46
+
47
+ "messages": {
48
+ "hello": {
49
+ "request": [{"name": "greeting", "type": "Greeting" }],
50
+ "response": "Greeting",
51
+ "errors": ["Curse"]
52
+ }
53
+ }
54
+ }
55
+ EOS
56
+
57
+ ExampleProtocol.new(<<-EOS, true),
58
+ {"namespace": "org.apache.avro.test",
59
+ "protocol": "Simple",
60
+
61
+ "types": [
62
+ {"name": "Kind", "type": "enum", "symbols": ["FOO","BAR","BAZ"]},
63
+
64
+ {"name": "MD5", "type": "fixed", "size": 16},
65
+
66
+ {"name": "TestRecord", "type": "record",
67
+ "fields": [
68
+ {"name": "name", "type": "string", "order": "ignore"},
69
+ {"name": "kind", "type": "Kind", "order": "descending"},
70
+ {"name": "hash", "type": "MD5"}
71
+ ]
72
+ },
73
+
74
+ {"name": "TestError", "type": "error", "fields": [
75
+ {"name": "message", "type": "string"}
76
+ ]
77
+ }
78
+
79
+ ],
80
+
81
+ "messages": {
82
+
83
+ "hello": {
84
+ "request": [{"name": "greeting", "type": "string"}],
85
+ "response": "string"
86
+ },
87
+
88
+ "echo": {
89
+ "request": [{"name": "record", "type": "TestRecord"}],
90
+ "response": "TestRecord"
91
+ },
92
+
93
+ "add": {
94
+ "request": [{"name": "arg1", "type": "int"}, {"name": "arg2", "type": "int"}],
95
+ "response": "int"
96
+ },
97
+
98
+ "echoBytes": {
99
+ "request": [{"name": "data", "type": "bytes"}],
100
+ "response": "bytes"
101
+ },
102
+
103
+ "error": {
104
+ "request": [],
105
+ "response": "null",
106
+ "errors": ["TestError"]
107
+ }
108
+ }
109
+
110
+ }
111
+ EOS
112
+ ExampleProtocol.new(<<-EOS, true),
113
+ {"namespace": "org.apache.avro.test.namespace",
114
+ "protocol": "TestNamespace",
115
+
116
+ "types": [
117
+ {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
118
+ {"name": "TestRecord", "type": "record",
119
+ "fields": [ {"name": "hash", "type": "org.apache.avro.test.util.MD5"} ]
120
+ },
121
+ {"name": "TestError", "namespace": "org.apache.avro.test.errors",
122
+ "type": "error", "fields": [ {"name": "message", "type": "string"} ]
123
+ }
124
+ ],
125
+
126
+ "messages": {
127
+ "echo": {
128
+ "request": [{"name": "record", "type": "TestRecord"}],
129
+ "response": "TestRecord"
130
+ },
131
+
132
+ "error": {
133
+ "request": [],
134
+ "response": "null",
135
+ "errors": ["org.apache.avro.test.errors.TestError"]
136
+ }
137
+
138
+ }
139
+
140
+ }
141
+ EOS
142
+ ExampleProtocol.new(<<-EOS, true)
143
+ {"namespace": "org.apache.avro.test",
144
+ "protocol": "BulkData",
145
+
146
+ "types": [],
147
+
148
+ "messages": {
149
+
150
+ "read": {
151
+ "request": [],
152
+ "response": "bytes"
153
+ },
154
+
155
+ "write": {
156
+ "request": [ {"name": "data", "type": "bytes"} ],
157
+ "response": "null"
158
+ }
159
+
160
+ }
161
+
162
+ }
163
+ EOS
164
+ ]
165
+
166
+ Protocol = Avro::Protocol
167
+ def test_parse
168
+ EXAMPLES.each do |example|
169
+ assert_nothing_raised("should be valid: #{example.protocol_string}") {
170
+ Protocol.parse(example.protocol_string)
171
+ }
172
+ end
173
+ end
174
+
175
+ def test_valid_cast_to_string_after_parse
176
+ EXAMPLES.each do |example|
177
+ assert_nothing_raised("round tripped okay #{example.protocol_string}") {
178
+ foo = Protocol.parse(example.protocol_string).to_s
179
+ Protocol.parse(foo)
180
+ }
181
+ end
182
+ end
183
+
184
+ def test_equivalence_after_round_trip
185
+ EXAMPLES.each do |example|
186
+ original = Protocol.parse(example.protocol_string)
187
+ round_trip = Protocol.parse(original.to_s)
188
+
189
+ assert_equal original, round_trip
190
+ end
191
+ end
192
+
193
+ def test_namespaces
194
+ protocol = Protocol.parse(EXAMPLES.first.protocol_string)
195
+ protocol.types.each do |type|
196
+ assert_equal type.namespace, 'com.acme'
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,146 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'test_help'
18
+
19
+ class TestSchema < Test::Unit::TestCase
20
+ def test_default_namespace
21
+ schema = Avro::Schema.parse <<-SCHEMA
22
+ {"type": "record", "name": "OuterRecord", "fields": [
23
+ {"name": "field1", "type": {
24
+ "type": "record", "name": "InnerRecord", "fields": []
25
+ }},
26
+ {"name": "field2", "type": "InnerRecord"}
27
+ ]}
28
+ SCHEMA
29
+
30
+ assert_equal schema.name, 'OuterRecord'
31
+ assert_equal schema.fullname, 'OuterRecord'
32
+ assert_nil schema.namespace
33
+
34
+ schema.fields.each do |field|
35
+ assert_equal field.type.name, 'InnerRecord'
36
+ assert_equal field.type.fullname, 'InnerRecord'
37
+ assert_nil field.type.namespace
38
+ end
39
+ end
40
+
41
+ def test_inherited_namespace
42
+ schema = Avro::Schema.parse <<-SCHEMA
43
+ {"type": "record", "name": "OuterRecord", "namespace": "my.name.space",
44
+ "fields": [
45
+ {"name": "definition", "type": {
46
+ "type": "record", "name": "InnerRecord", "fields": []
47
+ }},
48
+ {"name": "relativeReference", "type": "InnerRecord"},
49
+ {"name": "absoluteReference", "type": "my.name.space.InnerRecord"}
50
+ ]}
51
+ SCHEMA
52
+
53
+ assert_equal schema.name, 'OuterRecord'
54
+ assert_equal schema.fullname, 'my.name.space.OuterRecord'
55
+ assert_equal schema.namespace, 'my.name.space'
56
+ schema.fields.each do |field|
57
+ assert_equal field.type.name, 'InnerRecord'
58
+ assert_equal field.type.fullname, 'my.name.space.InnerRecord'
59
+ assert_equal field.type.namespace, 'my.name.space'
60
+ end
61
+ end
62
+
63
+ def test_inherited_namespace_from_dotted_name
64
+ schema = Avro::Schema.parse <<-SCHEMA
65
+ {"type": "record", "name": "my.name.space.OuterRecord", "fields": [
66
+ {"name": "definition", "type": {
67
+ "type": "enum", "name": "InnerEnum", "symbols": ["HELLO", "WORLD"]
68
+ }},
69
+ {"name": "relativeReference", "type": "InnerEnum"},
70
+ {"name": "absoluteReference", "type": "my.name.space.InnerEnum"}
71
+ ]}
72
+ SCHEMA
73
+
74
+ assert_equal schema.name, 'OuterRecord'
75
+ assert_equal schema.fullname, 'my.name.space.OuterRecord'
76
+ assert_equal schema.namespace, 'my.name.space'
77
+ schema.fields.each do |field|
78
+ assert_equal field.type.name, 'InnerEnum'
79
+ assert_equal field.type.fullname, 'my.name.space.InnerEnum'
80
+ assert_equal field.type.namespace, 'my.name.space'
81
+ end
82
+ end
83
+
84
+ def test_nested_namespaces
85
+ schema = Avro::Schema.parse <<-SCHEMA
86
+ {"type": "record", "name": "outer.OuterRecord", "fields": [
87
+ {"name": "middle", "type": {
88
+ "type": "record", "name": "middle.MiddleRecord", "fields": [
89
+ {"name": "inner", "type": {
90
+ "type": "record", "name": "InnerRecord", "fields": [
91
+ {"name": "recursive", "type": "MiddleRecord"}
92
+ ]
93
+ }}
94
+ ]
95
+ }}
96
+ ]}
97
+ SCHEMA
98
+
99
+ assert_equal schema.name, 'OuterRecord'
100
+ assert_equal schema.fullname, 'outer.OuterRecord'
101
+ assert_equal schema.namespace, 'outer'
102
+ middle = schema.fields.first.type
103
+ assert_equal middle.name, 'MiddleRecord'
104
+ assert_equal middle.fullname, 'middle.MiddleRecord'
105
+ assert_equal middle.namespace, 'middle'
106
+ inner = middle.fields.first.type
107
+ assert_equal inner.name, 'InnerRecord'
108
+ assert_equal inner.fullname, 'middle.InnerRecord'
109
+ assert_equal inner.namespace, 'middle'
110
+ assert_equal inner.fields.first.type, middle
111
+ end
112
+
113
+ def test_to_avro_includes_namespaces
114
+ schema = Avro::Schema.parse <<-SCHEMA
115
+ {"type": "record", "name": "my.name.space.OuterRecord", "fields": [
116
+ {"name": "definition", "type": {
117
+ "type": "fixed", "name": "InnerFixed", "size": 16
118
+ }},
119
+ {"name": "reference", "type": "InnerFixed"}
120
+ ]}
121
+ SCHEMA
122
+
123
+ assert_equal schema.to_avro, {
124
+ 'type' => 'record', 'name' => 'OuterRecord', 'namespace' => 'my.name.space',
125
+ 'fields' => [
126
+ {'name' => 'definition', 'type' => {
127
+ 'type' => 'fixed', 'name' => 'InnerFixed', 'namespace' => 'my.name.space',
128
+ 'size' => 16
129
+ }},
130
+ {'name' => 'reference', 'type' => 'my.name.space.InnerFixed'}
131
+ ]
132
+ }
133
+ end
134
+
135
+ def test_unknown_named_type
136
+ error = assert_raise Avro::UnknownSchemaError do
137
+ Avro::Schema.parse <<-SCHEMA
138
+ {"type": "record", "name": "my.name.space.Record", "fields": [
139
+ {"name": "reference", "type": "MissingType"}
140
+ ]}
141
+ SCHEMA
142
+ end
143
+
144
+ assert_equal '"MissingType" is not a schema we know about.', error.message
145
+ end
146
+ end