avro-jruby 1.7.5

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,90 @@
1
+ #!/usr/bin/env ruby
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
+ class RandomData
19
+ def initialize(schm, seed=nil)
20
+ srand(seed) if seed
21
+ @seed = seed
22
+ @schm = schm
23
+ end
24
+
25
+ def next
26
+ nextdata(@schm)
27
+ end
28
+
29
+ def nextdata(schm, d=0)
30
+ case schm.type_sym
31
+ when :boolean
32
+ rand > 0.5
33
+ when :string
34
+ randstr()
35
+ when :int
36
+ rand(Avro::Schema::INT_MAX_VALUE - Avro::Schema::INT_MIN_VALUE) + Avro::Schema::INT_MIN_VALUE
37
+ when :long
38
+ rand(Avro::Schema::LONG_MAX_VALUE - Avro::Schema::LONG_MIN_VALUE) + Avro::Schema::LONG_MIN_VALUE
39
+ when :float
40
+ (-1024 + 2048 * rand).round.to_f
41
+ when :double
42
+ Avro::Schema::LONG_MIN_VALUE + (Avro::Schema::LONG_MAX_VALUE - Avro::Schema::LONG_MIN_VALUE) * rand
43
+ when :bytes
44
+ randstr(BYTEPOOL)
45
+ when :null
46
+ nil
47
+ when :array
48
+ arr = []
49
+ len = rand(5) + 2 - d
50
+ len = 0 if len < 0
51
+ len.times{ arr << nextdata(schm.items, d+1) }
52
+ arr
53
+ when :map
54
+ map = {}
55
+ len = rand(5) + 2 - d
56
+ len = 0 if len < 0
57
+ len.times do
58
+ map[nextdata(Avro::Schema::PrimitiveSchema.new(:string))] = nextdata(schm.values, d+1)
59
+ end
60
+ map
61
+ when :record, :error
62
+ m = {}
63
+ schm.fields.each do |field|
64
+ m[field.name] = nextdata(field.type, d+1)
65
+ end
66
+ m
67
+ when :union
68
+ types = schm.schemas
69
+ nextdata(types[rand(types.size)], d)
70
+ when :enum
71
+ symbols = schm.symbols
72
+ len = symbols.size
73
+ return nil if len == 0
74
+ symbols[rand(len)]
75
+ when :fixed
76
+ f = ""
77
+ schm.size.times { f << BYTEPOOL[rand(BYTEPOOL.size), 1] }
78
+ f
79
+ end
80
+ end
81
+
82
+ CHARPOOL = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'
83
+ BYTEPOOL = '12345abcd'
84
+
85
+ def randstr(chars=CHARPOOL, length=20)
86
+ str = ''
87
+ rand(length+1).times { str << chars[rand(chars.size)] }
88
+ str
89
+ end
90
+ end
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env ruby
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 'socket'
19
+ require 'avro'
20
+
21
+ MAIL_PROTOCOL_JSON = <<-JSON
22
+ {"namespace": "example.proto",
23
+ "protocol": "Mail",
24
+
25
+ "types": [
26
+ {"name": "Message", "type": "record",
27
+ "fields": [
28
+ {"name": "to", "type": "string"},
29
+ {"name": "from", "type": "string"},
30
+ {"name": "body", "type": "string"}
31
+ ]
32
+ }
33
+ ],
34
+
35
+ "messages": {
36
+ "send": {
37
+ "request": [{"name": "message", "type": "Message"}],
38
+ "response": "string"
39
+ },
40
+ "replay": {
41
+ "request": [],
42
+ "response": "string"
43
+ }
44
+ }
45
+ }
46
+ JSON
47
+
48
+ MAIL_PROTOCOL = Avro::Protocol.parse(MAIL_PROTOCOL_JSON)
49
+
50
+ def make_requestor(server_address, port, protocol)
51
+ sock = TCPSocket.new(server_address, port)
52
+ client = Avro::IPC::SocketTransport.new(sock)
53
+ Avro::IPC::Requestor.new(protocol, client)
54
+ end
55
+
56
+ if $0 == __FILE__
57
+ if ![3, 4].include?(ARGV.length)
58
+ raise "Usage: <to> <from> <body> [<count>]"
59
+ end
60
+
61
+ # client code - attach to the server and send a message
62
+ # fill in the Message record
63
+ message = {
64
+ 'to' => ARGV[0],
65
+ 'from' => ARGV[1],
66
+ 'body' => ARGV[2]
67
+ }
68
+
69
+ num_messages = (ARGV[3] || 1).to_i
70
+
71
+ # build the parameters for the request
72
+ params = {'message' => message}
73
+
74
+ # send the requests and print the result
75
+ num_messages.times do
76
+ requestor = make_requestor('localhost', 9090, MAIL_PROTOCOL)
77
+ result = requestor.request('send', params)
78
+ puts("Result: " + result)
79
+ end
80
+
81
+ # try out a replay message
82
+ requestor = make_requestor('localhost', 9090, MAIL_PROTOCOL)
83
+ result = requestor.request('replay', {})
84
+ puts("Replay Result: " + result)
85
+ end
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
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 'socket'
19
+ require 'avro'
20
+
21
+ MAIL_PROTOCOL_JSON = <<-JSON
22
+ {"namespace": "example.proto",
23
+ "protocol": "Mail",
24
+
25
+ "types": [
26
+ {"name": "Message", "type": "record",
27
+ "fields": [
28
+ {"name": "to", "type": "string"},
29
+ {"name": "from", "type": "string"},
30
+ {"name": "body", "type": "string"}
31
+ ]
32
+ }
33
+ ],
34
+
35
+ "messages": {
36
+ "send": {
37
+ "request": [{"name": "message", "type": "Message"}],
38
+ "response": "string"
39
+ },
40
+ "replay": {
41
+ "request": [],
42
+ "response": "string"
43
+ }
44
+ }
45
+ }
46
+ JSON
47
+
48
+ MAIL_PROTOCOL = Avro::Protocol.parse(MAIL_PROTOCOL_JSON)
49
+
50
+ def make_requestor(server_address, port, protocol)
51
+ transport = Avro::IPC::HTTPTransceiver.new(server_address, port)
52
+ Avro::IPC::Requestor.new(protocol, transport)
53
+ end
54
+
55
+ if $0 == __FILE__
56
+ if ![3, 4].include?(ARGV.length)
57
+ raise "Usage: <to> <from> <body> [<count>]"
58
+ end
59
+
60
+ # client code - attach to the server and send a message
61
+ # fill in the Message record
62
+ message = {
63
+ 'to' => ARGV[0],
64
+ 'from' => ARGV[1],
65
+ 'body' => ARGV[2]
66
+ }
67
+
68
+ num_messages = (ARGV[3] || 1).to_i
69
+
70
+ # build the parameters for the request
71
+ params = {'message' => message}
72
+ # send the requests and print the result
73
+
74
+ num_messages.times do
75
+ requestor = make_requestor('localhost', 9090, MAIL_PROTOCOL)
76
+ result = requestor.request('send', params)
77
+ puts("Result: " + result)
78
+ end
79
+
80
+ # try out a replay message
81
+ requestor = make_requestor('localhost', 9090, MAIL_PROTOCOL)
82
+ result = requestor.request('replay', {})
83
+ puts("Replay Result: " + result)
84
+ end
@@ -0,0 +1,79 @@
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
+ require 'avro'
17
+ require 'webrick'
18
+
19
+ MAIL_PROTOCOL_JSON = <<-JSON
20
+ {"namespace": "example.proto",
21
+ "protocol": "Mail",
22
+
23
+ "types": [
24
+ {"name": "Message", "type": "record",
25
+ "fields": [
26
+ {"name": "to", "type": "string"},
27
+ {"name": "from", "type": "string"},
28
+ {"name": "body", "type": "string"}
29
+ ]
30
+ }
31
+ ],
32
+
33
+ "messages": {
34
+ "send": {
35
+ "request": [{"name": "message", "type": "Message"}],
36
+ "response": "string"
37
+ },
38
+ "replay": {
39
+ "request": [],
40
+ "response": "string"
41
+ }
42
+ }
43
+ }
44
+ JSON
45
+
46
+ MAIL_PROTOCOL = Avro::Protocol.parse(MAIL_PROTOCOL_JSON)
47
+
48
+ class MailResponder < Avro::IPC::Responder
49
+ def initialize
50
+ super(MAIL_PROTOCOL)
51
+ end
52
+
53
+ def call(message, request)
54
+ if message.name == 'send'
55
+ request_content = request['message']
56
+ "Sent message to #{request_content['to']} from #{request_content['from']} with body #{request_content['body']}"
57
+ elsif message.name == 'replay'
58
+ 'replay'
59
+ end
60
+ end
61
+ end
62
+
63
+ class MailHandler < WEBrick::HTTPServlet::AbstractServlet
64
+ def do_POST(req, resp)
65
+ responder = MailResponder.new
66
+ call_request = Avro::IPC::FramedReader.new(StringIO.new(req.body)).read_framed_message
67
+ unframed_resp = responder.respond(call_request)
68
+ writer = Avro::IPC::FramedWriter.new(StringIO.new)
69
+ writer.write_framed_message(unframed_resp)
70
+ resp.body = writer.to_s
71
+ end
72
+ end
73
+
74
+ if $0 == __FILE__
75
+ server = WEBrick::HTTPServer.new(:Host => 'localhost', :Port => 9090)
76
+ server.mount '/', MailHandler
77
+ trap("INT") { server.shutdown }
78
+ server.start
79
+ end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
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 'socket'
19
+ require 'avro'
20
+
21
+ MAIL_PROTOCOL_JSON = <<-EOS
22
+ {"namespace": "example.proto",
23
+ "protocol": "Mail",
24
+
25
+ "types": [
26
+ {"name": "Message", "type": "record",
27
+ "fields": [
28
+ {"name": "to", "type": "string"},
29
+ {"name": "from", "type": "string"},
30
+ {"name": "body", "type": "string"}
31
+ ]
32
+ }
33
+ ],
34
+
35
+ "messages": {
36
+ "send": {
37
+ "request": [{"name": "message", "type": "Message"}],
38
+ "response": "string"
39
+ },
40
+ "replay": {
41
+ "request": [],
42
+ "response": "string"
43
+ }
44
+ }
45
+ }
46
+ EOS
47
+
48
+ MAIL_PROTOCOL = Avro::Protocol.parse(MAIL_PROTOCOL_JSON)
49
+
50
+ class MailResponder < Avro::IPC::Responder
51
+ def initialize
52
+ super(MAIL_PROTOCOL)
53
+ end
54
+
55
+ def call(message, request)
56
+ if message.name == 'send'
57
+ request_content = request['message']
58
+ "Sent message to #{request_content['to']} from #{request_content['from']} with body #{request_content['body']}"
59
+ elsif message.name == 'replay'
60
+ 'replay'
61
+ end
62
+ end
63
+ end
64
+
65
+ class RequestHandler
66
+ def initialize(address, port)
67
+ @ip_address = address
68
+ @port = port
69
+ end
70
+
71
+ def run
72
+ server = TCPServer.new(@ip_address, @port)
73
+ while (session = server.accept)
74
+ handle(session)
75
+ session.close
76
+ end
77
+ end
78
+ end
79
+
80
+ class MailHandler < RequestHandler
81
+ def handle(request)
82
+ responder = MailResponder.new()
83
+ transport = Avro::IPC::SocketTransport.new(request)
84
+ str = transport.read_framed_message
85
+ transport.write_framed_message(responder.respond(str))
86
+ end
87
+ end
88
+
89
+ if $0 == __FILE__
90
+ handler = MailHandler.new('localhost', 9090)
91
+ handler.run
92
+ end
@@ -0,0 +1,188 @@
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 TestDataFile < Test::Unit::TestCase
21
+ HERE = File.expand_path File.dirname(__FILE__)
22
+ def setup
23
+ if File.exists?(HERE + '/data.avr')
24
+ File.unlink(HERE + '/data.avr')
25
+ end
26
+ end
27
+
28
+ def teardown
29
+ if File.exists?(HERE + '/data.avr')
30
+ File.unlink(HERE + '/data.avr')
31
+ end
32
+ end
33
+
34
+ def test_differing_schemas_with_primitives
35
+ writer_schema = <<-JSON
36
+ { "type": "record",
37
+ "name": "User",
38
+ "fields" : [
39
+ {"name": "username", "type": "string"},
40
+ {"name": "age", "type": "int"},
41
+ {"name": "verified", "type": "boolean", "default": "false"}
42
+ ]}
43
+ JSON
44
+
45
+ data = [{"username" => "john", "age" => 25, "verified" => true},
46
+ {"username" => "ryan", "age" => 23, "verified" => false}]
47
+
48
+ Avro::DataFile.open('data.avr', 'w', writer_schema) do |dw|
49
+ data.each{|h| dw << h }
50
+ end
51
+
52
+ # extract the username only from the avro serialized file
53
+ reader_schema = <<-JSON
54
+ { "type": "record",
55
+ "name": "User",
56
+ "fields" : [
57
+ {"name": "username", "type": "string"}
58
+ ]}
59
+ JSON
60
+
61
+ Avro::DataFile.open('data.avr', 'r', reader_schema) do |dr|
62
+ dr.each_with_index do |record, i|
63
+ assert_equal data[i]['username'], record['username']
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_differing_schemas_with_complex_objects
69
+ writer_schema = <<-JSON
70
+ { "type": "record",
71
+ "name": "something",
72
+ "fields": [
73
+ {"name": "something_fixed", "type": {"name": "inner_fixed",
74
+ "type": "fixed", "size": 3}},
75
+ {"name": "something_enum", "type": {"name": "inner_enum",
76
+ "type": "enum",
77
+ "symbols": ["hello", "goodbye"]}},
78
+ {"name": "something_array", "type": {"type": "array", "items": "int"}},
79
+ {"name": "something_map", "type": {"type": "map", "values": "int"}},
80
+ {"name": "something_record", "type": {"name": "inner_record",
81
+ "type": "record",
82
+ "fields": [
83
+ {"name": "inner", "type": "int"}
84
+ ]}},
85
+ {"name": "username", "type": "string"}
86
+ ]}
87
+ JSON
88
+
89
+ data = [{"username" => "john",
90
+ "something_fixed" => "foo",
91
+ "something_enum" => "hello",
92
+ "something_array" => [1,2,3],
93
+ "something_map" => {"a" => 1, "b" => 2},
94
+ "something_record" => {"inner" => 2},
95
+ "something_error" => {"code" => 403}
96
+ },
97
+ {"username" => "ryan",
98
+ "something_fixed" => "bar",
99
+ "something_enum" => "goodbye",
100
+ "something_array" => [1,2,3],
101
+ "something_map" => {"a" => 2, "b" => 6},
102
+ "something_record" => {"inner" => 1},
103
+ "something_error" => {"code" => 401}
104
+ }]
105
+
106
+ Avro::DataFile.open('data.avr', 'w', writer_schema) do |dw|
107
+ data.each{|d| dw << d }
108
+ end
109
+
110
+ %w[fixed enum record error array map union].each do |s|
111
+ reader = MultiJson.load(writer_schema)
112
+ reader['fields'] = reader['fields'].reject{|f| f['type']['type'] == s}
113
+ Avro::DataFile.open('data.avr', 'r', MultiJson.dump(reader)) do |dr|
114
+ dr.each_with_index do |obj, i|
115
+ reader['fields'].each do |field|
116
+ assert_equal data[i][field['name']], obj[field['name']]
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ def test_data_writer_handles_sync_interval
124
+ writer_schema = <<-JSON
125
+ { "type": "record",
126
+ "name": "something",
127
+ "fields": [
128
+ {"name": "something_boolean", "type": "boolean"}
129
+ ]}
130
+ JSON
131
+
132
+ data = {"something_boolean" => true }
133
+
134
+ Avro::DataFile.open('data.avr', 'w', writer_schema) do |dw|
135
+ while dw.writer.tell < Avro::DataFile::SYNC_INTERVAL
136
+ dw << data
137
+ end
138
+ block_count = dw.block_count
139
+ dw << data
140
+ # ensure we didn't just write another block
141
+ assert_equal(block_count+1, dw.block_count)
142
+ end
143
+ end
144
+
145
+ def test_utf8
146
+ datafile = Avro::DataFile::open('data.avr', 'w', '"string"')
147
+ datafile << "家"
148
+ datafile.close
149
+
150
+ datafile = Avro::DataFile.open('data.avr')
151
+ datafile.each do |s|
152
+ assert_equal "家", s
153
+ end
154
+ datafile.close
155
+ end
156
+
157
+ def test_deflate
158
+ Avro::DataFile.open('data.avr', 'w', '"string"', :deflate) do |writer|
159
+ writer << 'a' * 10_000
160
+ end
161
+ assert(File.size('data.avr') < 500)
162
+
163
+ records = []
164
+ Avro::DataFile.open('data.avr') do |reader|
165
+ reader.each {|record| records << record }
166
+ end
167
+ assert_equal records, ['a' * 10_000]
168
+ end
169
+
170
+ def test_append_to_deflated_file
171
+ schema = Avro::Schema.parse('"string"')
172
+ writer = Avro::IO::DatumWriter.new(schema)
173
+ file = Avro::DataFile::Writer.new(File.open('data.avr', 'wb'), writer, schema, :deflate)
174
+ file << 'a' * 10_000
175
+ file.close
176
+
177
+ file = Avro::DataFile::Writer.new(File.open('data.avr', 'a+b'), writer)
178
+ file << 'b' * 10_000
179
+ file.close
180
+ assert(File.size('data.avr') < 1_000)
181
+
182
+ records = []
183
+ Avro::DataFile.open('data.avr') do |reader|
184
+ reader.each {|record| records << record }
185
+ end
186
+ assert_equal records, ['a' * 10_000, 'b' * 10_000]
187
+ end
188
+ end