avro-salsify-fork 1.9.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,83 @@
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
+ module Avro
18
+ class SchemaNormalization
19
+ def self.to_parsing_form(schema)
20
+ new.to_parsing_form(schema)
21
+ end
22
+
23
+ def initialize
24
+ @processed_names = []
25
+ end
26
+
27
+ def to_parsing_form(schema)
28
+ MultiJson.dump(normalize_schema(schema))
29
+ end
30
+
31
+ private
32
+
33
+ def normalize_schema(schema)
34
+ type = schema.type_sym.to_s
35
+
36
+ if Schema::NAMED_TYPES.include?(type)
37
+ if @processed_names.include?(schema.name)
38
+ return schema.name
39
+ else
40
+ @processed_names << schema.name
41
+ end
42
+ end
43
+
44
+ case type
45
+ when *Schema::PRIMITIVE_TYPES
46
+ type
47
+ when "record"
48
+ fields = schema.fields.map {|field| normalize_field(field) }
49
+
50
+ normalize_named_type(schema, fields: fields)
51
+ when "enum"
52
+ normalize_named_type(schema, symbols: schema.symbols)
53
+ when "fixed"
54
+ normalize_named_type(schema, size: schema.size)
55
+ when "array"
56
+ { type: type, items: normalize_schema(schema.items) }
57
+ when "map"
58
+ { type: type, values: normalize_schema(schema.values) }
59
+ when "union"
60
+ if schema.schemas.nil?
61
+ []
62
+ else
63
+ schema.schemas.map {|s| normalize_schema(s) }
64
+ end
65
+ else
66
+ raise "unknown type #{type}"
67
+ end
68
+ end
69
+
70
+ def normalize_field(field)
71
+ {
72
+ name: field.name,
73
+ type: normalize_schema(field.type)
74
+ }
75
+ end
76
+
77
+ def normalize_named_type(schema, attributes = {})
78
+ name = Name.make_fullname(schema.name, schema.namespace)
79
+
80
+ { name: name, type: schema.type_sym.to_s }.merge(attributes)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,87 @@
1
+ #
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,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+ require 'strscan'
20
+
21
+ class CaseFinder
22
+ PATH = File.expand_path("../../../../share/test/data/schema-tests.txt", __FILE__)
23
+
24
+ Case = Struct.new(:id, :input, :canonical, :fingerprint)
25
+
26
+ def self.cases
27
+ new.cases
28
+ end
29
+
30
+ def initialize
31
+ @scanner = StringScanner.new(File.read(PATH))
32
+ @cases = []
33
+ end
34
+
35
+ def cases
36
+ until @scanner.eos?
37
+ test_case = scan_case
38
+ @cases << test_case if test_case
39
+ end
40
+
41
+ @cases
42
+ end
43
+
44
+ private
45
+
46
+ def scan_case
47
+ if id = @scanner.scan(/\/\/ \d+\n/)
48
+ while @scanner.skip(/\/\/ .*\n/); end
49
+
50
+ input = scan_input
51
+ canonical = scan_canonical
52
+ fingerprint = scan_fingerprint
53
+
54
+ Case.new(id, input, canonical, fingerprint)
55
+ else
56
+ @scanner.skip(/.*\n/)
57
+ nil
58
+ end
59
+ end
60
+
61
+ def scan_item(name)
62
+ if @scanner.scan(/<<#{name}\n/)
63
+ lines = []
64
+ while line = @scanner.scan(/.+\n/)
65
+ break if line.chomp == name
66
+ lines << line
67
+ end
68
+ lines.join
69
+ elsif @scanner.scan(/<<#{name} /)
70
+ input = @scanner.scan(/.+$/)
71
+ @scanner.skip(/\n/)
72
+ input
73
+ end
74
+ end
75
+
76
+ def scan_input
77
+ scan_item("INPUT")
78
+ end
79
+
80
+ def scan_canonical
81
+ scan_item("canonical")
82
+ end
83
+
84
+ def scan_fingerprint
85
+ scan_item("fingerprint")
86
+ end
87
+ end
@@ -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