tiny_thrift 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/README +43 -0
  3. data/benchmark/Benchmark.thrift +24 -0
  4. data/benchmark/benchmark.rb +271 -0
  5. data/benchmark/client.rb +74 -0
  6. data/benchmark/server.rb +82 -0
  7. data/benchmark/thin_server.rb +44 -0
  8. data/ext/binary_protocol_accelerated.c +460 -0
  9. data/ext/binary_protocol_accelerated.h +20 -0
  10. data/ext/bytes.c +36 -0
  11. data/ext/bytes.h +31 -0
  12. data/ext/compact_protocol.c +635 -0
  13. data/ext/compact_protocol.h +20 -0
  14. data/ext/constants.h +96 -0
  15. data/ext/extconf.rb +32 -0
  16. data/ext/macros.h +41 -0
  17. data/ext/memory_buffer.c +134 -0
  18. data/ext/memory_buffer.h +20 -0
  19. data/ext/protocol.c +0 -0
  20. data/ext/protocol.h +0 -0
  21. data/ext/strlcpy.c +41 -0
  22. data/ext/strlcpy.h +34 -0
  23. data/ext/struct.c +688 -0
  24. data/ext/struct.h +25 -0
  25. data/ext/thrift_native.c +195 -0
  26. data/lib/thrift.rb +66 -0
  27. data/lib/thrift/bytes.rb +131 -0
  28. data/lib/thrift/client.rb +62 -0
  29. data/lib/thrift/core_ext.rb +23 -0
  30. data/lib/thrift/core_ext/fixnum.rb +29 -0
  31. data/lib/thrift/exceptions.rb +87 -0
  32. data/lib/thrift/processor.rb +57 -0
  33. data/lib/thrift/protocol/base_protocol.rb +377 -0
  34. data/lib/thrift/protocol/binary_protocol.rb +237 -0
  35. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  36. data/lib/thrift/protocol/compact_protocol.rb +434 -0
  37. data/lib/thrift/protocol/json_protocol.rb +769 -0
  38. data/lib/thrift/serializer/deserializer.rb +33 -0
  39. data/lib/thrift/serializer/serializer.rb +34 -0
  40. data/lib/thrift/server/base_server.rb +31 -0
  41. data/lib/thrift/server/mongrel_http_server.rb +60 -0
  42. data/lib/thrift/server/nonblocking_server.rb +305 -0
  43. data/lib/thrift/server/simple_server.rb +43 -0
  44. data/lib/thrift/server/thin_http_server.rb +91 -0
  45. data/lib/thrift/server/thread_pool_server.rb +75 -0
  46. data/lib/thrift/server/threaded_server.rb +47 -0
  47. data/lib/thrift/struct.rb +237 -0
  48. data/lib/thrift/struct_union.rb +192 -0
  49. data/lib/thrift/thrift_native.rb +24 -0
  50. data/lib/thrift/transport/base_server_transport.rb +37 -0
  51. data/lib/thrift/transport/base_transport.rb +109 -0
  52. data/lib/thrift/transport/buffered_transport.rb +114 -0
  53. data/lib/thrift/transport/framed_transport.rb +117 -0
  54. data/lib/thrift/transport/http_client_transport.rb +56 -0
  55. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  56. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  57. data/lib/thrift/transport/server_socket.rb +63 -0
  58. data/lib/thrift/transport/socket.rb +139 -0
  59. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  60. data/lib/thrift/transport/unix_socket.rb +40 -0
  61. data/lib/thrift/types.rb +101 -0
  62. data/lib/thrift/union.rb +179 -0
  63. data/lib/tiny_thrift.rb +1 -0
  64. data/spec/ThriftSpec.thrift +183 -0
  65. data/spec/base_protocol_spec.rb +217 -0
  66. data/spec/base_transport_spec.rb +350 -0
  67. data/spec/binary_protocol_accelerated_spec.rb +42 -0
  68. data/spec/binary_protocol_spec.rb +66 -0
  69. data/spec/binary_protocol_spec_shared.rb +455 -0
  70. data/spec/bytes_spec.rb +160 -0
  71. data/spec/client_spec.rb +99 -0
  72. data/spec/compact_protocol_spec.rb +143 -0
  73. data/spec/exception_spec.rb +141 -0
  74. data/spec/http_client_spec.rb +120 -0
  75. data/spec/json_protocol_spec.rb +513 -0
  76. data/spec/nonblocking_server_spec.rb +263 -0
  77. data/spec/processor_spec.rb +80 -0
  78. data/spec/serializer_spec.rb +67 -0
  79. data/spec/server_socket_spec.rb +79 -0
  80. data/spec/server_spec.rb +147 -0
  81. data/spec/socket_spec.rb +61 -0
  82. data/spec/socket_spec_shared.rb +104 -0
  83. data/spec/spec_helper.rb +61 -0
  84. data/spec/struct_nested_containers_spec.rb +191 -0
  85. data/spec/struct_spec.rb +293 -0
  86. data/spec/thin_http_server_spec.rb +141 -0
  87. data/spec/types_spec.rb +115 -0
  88. data/spec/union_spec.rb +203 -0
  89. data/spec/unix_socket_spec.rb +107 -0
  90. metadata +313 -0
@@ -0,0 +1,147 @@
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 'spec_helper'
20
+
21
+ describe 'Server' do
22
+
23
+ describe Thrift::BaseServer do
24
+ it "should default to BaseTransportFactory and BinaryProtocolFactory when not specified" do
25
+ server = Thrift::BaseServer.new(mock("Processor"), mock("BaseServerTransport"))
26
+ server.instance_variable_get(:'@transport_factory').should be_an_instance_of(Thrift::BaseTransportFactory)
27
+ server.instance_variable_get(:'@protocol_factory').should be_an_instance_of(Thrift::BinaryProtocolFactory)
28
+ end
29
+
30
+ # serve is a noop, so can't test that
31
+ end
32
+
33
+ describe Thrift::SimpleServer do
34
+ before(:each) do
35
+ @processor = mock("Processor")
36
+ @serverTrans = mock("ServerTransport")
37
+ @trans = mock("BaseTransport")
38
+ @prot = mock("BaseProtocol")
39
+ @client = mock("Client")
40
+ @server = described_class.new(@processor, @serverTrans, @trans, @prot)
41
+ end
42
+
43
+ it "should serve in the main thread" do
44
+ @serverTrans.should_receive(:listen).ordered
45
+ @serverTrans.should_receive(:accept).exactly(3).times.and_return(@client)
46
+ @trans.should_receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
47
+ @prot.should_receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
48
+ x = 0
49
+ @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
50
+ case (x += 1)
51
+ when 1 then raise Thrift::TransportException
52
+ when 2 then raise Thrift::ProtocolException
53
+ when 3 then throw :stop
54
+ end
55
+ end
56
+ @trans.should_receive(:close).exactly(3).times
57
+ @serverTrans.should_receive(:close).ordered
58
+ lambda { @server.serve }.should throw_symbol(:stop)
59
+ end
60
+ end
61
+
62
+ describe Thrift::ThreadedServer do
63
+ before(:each) do
64
+ @processor = mock("Processor")
65
+ @serverTrans = mock("ServerTransport")
66
+ @trans = mock("BaseTransport")
67
+ @prot = mock("BaseProtocol")
68
+ @client = mock("Client")
69
+ @server = described_class.new(@processor, @serverTrans, @trans, @prot)
70
+ end
71
+
72
+ it "should serve using threads" do
73
+ @serverTrans.should_receive(:listen).ordered
74
+ @serverTrans.should_receive(:accept).exactly(3).times.and_return(@client)
75
+ @trans.should_receive(:get_transport).exactly(3).times.with(@client).and_return(@trans)
76
+ @prot.should_receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot)
77
+ Thread.should_receive(:new).with(@prot, @trans).exactly(3).times.and_yield(@prot, @trans)
78
+ x = 0
79
+ @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
80
+ case (x += 1)
81
+ when 1 then raise Thrift::TransportException
82
+ when 2 then raise Thrift::ProtocolException
83
+ when 3 then throw :stop
84
+ end
85
+ end
86
+ @trans.should_receive(:close).exactly(3).times
87
+ @serverTrans.should_receive(:close).ordered
88
+ lambda { @server.serve }.should throw_symbol(:stop)
89
+ end
90
+ end
91
+
92
+ describe Thrift::ThreadPoolServer do
93
+ before(:each) do
94
+ @processor = mock("Processor")
95
+ @server_trans = mock("ServerTransport")
96
+ @trans = mock("BaseTransport")
97
+ @prot = mock("BaseProtocol")
98
+ @client = mock("Client")
99
+ @server = described_class.new(@processor, @server_trans, @trans, @prot)
100
+ end
101
+
102
+ it "should serve inside a thread" do
103
+ exception_q = @server.instance_variable_get(:@exception_q)
104
+ described_class.any_instance.should_receive(:serve) do
105
+ exception_q.push(StandardError.new('ERROR'))
106
+ end
107
+ expect { @server.rescuable_serve }.to(raise_error('ERROR'))
108
+ end
109
+
110
+ it "should avoid running the server twice when retrying rescuable_serve" do
111
+ exception_q = @server.instance_variable_get(:@exception_q)
112
+ described_class.any_instance.should_receive(:serve) do
113
+ exception_q.push(StandardError.new('ERROR1'))
114
+ exception_q.push(StandardError.new('ERROR2'))
115
+ end
116
+ expect { @server.rescuable_serve }.to(raise_error('ERROR1'))
117
+ expect { @server.rescuable_serve }.to(raise_error('ERROR2'))
118
+ end
119
+
120
+ it "should serve using a thread pool" do
121
+ thread_q = mock("SizedQueue")
122
+ exception_q = mock("Queue")
123
+ @server.instance_variable_set(:@thread_q, thread_q)
124
+ @server.instance_variable_set(:@exception_q, exception_q)
125
+ @server_trans.should_receive(:listen).ordered
126
+ thread_q.should_receive(:push).with(:token)
127
+ thread_q.should_receive(:pop)
128
+ Thread.should_receive(:new).and_yield
129
+ @server_trans.should_receive(:accept).exactly(3).times.and_return(@client)
130
+ @trans.should_receive(:get_transport).exactly(3).times.and_return(@trans)
131
+ @prot.should_receive(:get_protocol).exactly(3).times.and_return(@prot)
132
+ x = 0
133
+ error = RuntimeError.new("Stopped")
134
+ @processor.should_receive(:process).exactly(3).times.with(@prot, @prot).and_return do
135
+ case (x += 1)
136
+ when 1 then raise Thrift::TransportException
137
+ when 2 then raise Thrift::ProtocolException
138
+ when 3 then raise error
139
+ end
140
+ end
141
+ @trans.should_receive(:close).exactly(3).times
142
+ exception_q.should_receive(:push).with(error).and_throw(:stop)
143
+ @server_trans.should_receive(:close)
144
+ expect { @server.serve }.to(throw_symbol(:stop))
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,61 @@
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
+
20
+ require 'spec_helper'
21
+ require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared")
22
+
23
+ describe 'Socket' do
24
+
25
+ describe Thrift::Socket do
26
+ before(:each) do
27
+ @socket = Thrift::Socket.new
28
+ @handle = mock("Handle", :closed? => false)
29
+ @handle.stub!(:close)
30
+ @handle.stub!(:connect_nonblock)
31
+ @handle.stub!(:setsockopt)
32
+ ::Socket.stub!(:new).and_return(@handle)
33
+ end
34
+
35
+ it_should_behave_like "a socket"
36
+
37
+ it "should raise a TransportException when it cannot open a socket" do
38
+ ::Socket.should_receive(:new).and_raise(StandardError)
39
+ lambda { @socket.open }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
40
+ end
41
+
42
+ it "should open a ::Socket with default args" do
43
+ ::Socket.should_receive(:new).and_return(mock("Handle", :connect_nonblock => true, :setsockopt => nil))
44
+ ::Socket.should_receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]])
45
+ ::Socket.should_receive(:sockaddr_in)
46
+ @socket.open
47
+ end
48
+
49
+ it "should accept host/port options" do
50
+ ::Socket.should_receive(:new).and_return(mock("Handle", :connect_nonblock => true, :setsockopt => nil))
51
+ ::Socket.should_receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]])
52
+ ::Socket.should_receive(:sockaddr_in)
53
+ Thrift::Socket.new('my.domain', 1234).open
54
+ end
55
+
56
+ it "should accept an optional timeout" do
57
+ ::Socket.stub!(:new)
58
+ Thrift::Socket.new('localhost', 8080, 5).timeout.should == 5
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,104 @@
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
+
20
+ require 'spec_helper'
21
+
22
+ shared_examples_for "a socket" do
23
+ it "should open a socket" do
24
+ @socket.open.should == @handle
25
+ end
26
+
27
+ it "should be open whenever it has a handle" do
28
+ @socket.should_not be_open
29
+ @socket.open
30
+ @socket.should be_open
31
+ @socket.handle = nil
32
+ @socket.should_not be_open
33
+ @socket.handle = @handle
34
+ @socket.close
35
+ @socket.should_not be_open
36
+ end
37
+
38
+ it "should write data to the handle" do
39
+ @socket.open
40
+ @handle.should_receive(:write).with("foobar")
41
+ @socket.write("foobar")
42
+ @handle.should_receive(:write).with("fail").and_raise(StandardError)
43
+ lambda { @socket.write("fail") }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
44
+ end
45
+
46
+ it "should raise an error when it cannot read from the handle" do
47
+ @socket.open
48
+ @handle.should_receive(:readpartial).with(17).and_raise(StandardError)
49
+ lambda { @socket.read(17) }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::NOT_OPEN }
50
+ end
51
+
52
+ it "should return the data read when reading from the handle works" do
53
+ @socket.open
54
+ @handle.should_receive(:readpartial).with(17).and_return("test data")
55
+ @socket.read(17).should == "test data"
56
+ end
57
+
58
+ it "should declare itself as closed when it has an error" do
59
+ @socket.open
60
+ @handle.should_receive(:write).with("fail").and_raise(StandardError)
61
+ @socket.should be_open
62
+ lambda { @socket.write("fail") }.should raise_error
63
+ @socket.should_not be_open
64
+ end
65
+
66
+ it "should raise an error when the stream is closed" do
67
+ @socket.open
68
+ @handle.stub!(:closed?).and_return(true)
69
+ @socket.should_not be_open
70
+ lambda { @socket.write("fail") }.should raise_error(IOError, "closed stream")
71
+ lambda { @socket.read(10) }.should raise_error(IOError, "closed stream")
72
+ end
73
+
74
+ it "should support the timeout accessor for read" do
75
+ @socket.timeout = 3
76
+ @socket.open
77
+ IO.should_receive(:select).with([@handle], nil, nil, 3).and_return([[@handle], [], []])
78
+ @handle.should_receive(:readpartial).with(17).and_return("test data")
79
+ @socket.read(17).should == "test data"
80
+ end
81
+
82
+ it "should support the timeout accessor for write" do
83
+ @socket.timeout = 3
84
+ @socket.open
85
+ IO.should_receive(:select).with(nil, [@handle], nil, 3).twice.and_return([[], [@handle], []])
86
+ @handle.should_receive(:write_nonblock).with("test data").and_return(4)
87
+ @handle.should_receive(:write_nonblock).with(" data").and_return(5)
88
+ @socket.write("test data").should == 9
89
+ end
90
+
91
+ it "should raise an error when read times out" do
92
+ @socket.timeout = 0.5
93
+ @socket.open
94
+ IO.should_receive(:select).once {sleep(0.5); nil}
95
+ lambda { @socket.read(17) }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::TIMED_OUT }
96
+ end
97
+
98
+ it "should raise an error when write times out" do
99
+ @socket.timeout = 0.5
100
+ @socket.open
101
+ IO.should_receive(:select).with(nil, [@handle], nil, 0.5).any_number_of_times.and_return(nil)
102
+ lambda { @socket.write("test data") }.should raise_error(Thrift::TransportException) { |e| e.type.should == Thrift::TransportException::TIMED_OUT }
103
+ end
104
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ require 'rubygems'
22
+ require 'rspec'
23
+
24
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. ext])
25
+
26
+ # pretend we already loaded fastthread, otherwise the nonblocking_server_spec
27
+ # will get screwed up
28
+ # $" << 'fastthread.bundle'
29
+
30
+ require 'thrift'
31
+
32
+ unless Object.method_defined? :tap
33
+ # if Object#tap isn't defined, then add it; this should only happen in Ruby < 1.8.7
34
+ class Object
35
+ def tap(&block)
36
+ block.call(self)
37
+ self
38
+ end
39
+ end
40
+ end
41
+
42
+ RSpec.configure do |configuration|
43
+ configuration.before(:each) do
44
+ Thrift.type_checking = true
45
+ end
46
+ end
47
+
48
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. test debug_proto gen-rb])
49
+ require 'srv'
50
+ require 'debug_proto_test_constants'
51
+
52
+ $:.unshift File.join(File.dirname(__FILE__), *%w[gen-rb])
53
+ require 'thrift_spec_types'
54
+ require 'nonblocking_service'
55
+
56
+ module Fixtures
57
+ COMPACT_PROTOCOL_TEST_STRUCT = COMPACT_TEST.dup
58
+ COMPACT_PROTOCOL_TEST_STRUCT.a_binary = [0,1,2,3,4,5,6,7,8].pack('c*')
59
+ COMPACT_PROTOCOL_TEST_STRUCT.set_byte_map = nil
60
+ COMPACT_PROTOCOL_TEST_STRUCT.map_byte_map = nil
61
+ end
@@ -0,0 +1,191 @@
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
+
20
+ require 'spec_helper'
21
+
22
+ describe 'StructNestedContainers' do
23
+
24
+ def with_type_checking
25
+ saved_type_checking, Thrift.type_checking = Thrift.type_checking, true
26
+ begin
27
+ yield
28
+ ensure
29
+ Thrift.type_checking = saved_type_checking
30
+ end
31
+ end
32
+
33
+ describe Thrift::Struct do
34
+ # Nested container tests, see THRIFT-369.
35
+ it "should support nested lists inside lists" do
36
+ with_type_checking do
37
+ a, b = SpecNamespace::NestedListInList.new, SpecNamespace::NestedListInList.new
38
+ [a, b].each do |thrift_struct|
39
+ thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ]
40
+ thrift_struct.validate
41
+ end
42
+ a.should == b
43
+ b.value.push [3, 4, 5]
44
+ a.should_not == b
45
+ end
46
+ end
47
+
48
+ it "should support nested lists inside sets" do
49
+ with_type_checking do
50
+ a, b = SpecNamespace::NestedListInSet.new, SpecNamespace::NestedListInSet.new
51
+ [a, b].each do |thrift_struct|
52
+ thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ].to_set
53
+ thrift_struct.validate
54
+ end
55
+ a.should == b
56
+ b.value.add [3, 4, 5]
57
+ a.should_not == b
58
+ end
59
+ end
60
+
61
+ it "should support nested lists in map keys" do
62
+ with_type_checking do
63
+ a, b = SpecNamespace::NestedListInMapKey.new, SpecNamespace::NestedListInMapKey.new
64
+ [a, b].each do |thrift_struct|
65
+ thrift_struct.value = { [1, 2, 3] => 1, [2, 3, 4] => 2 }
66
+ thrift_struct.validate
67
+ end
68
+ a.should == b
69
+ b.value[[3, 4, 5]] = 3
70
+ a.should_not == b
71
+ end
72
+ end
73
+
74
+ it "should support nested lists in map values" do
75
+ with_type_checking do
76
+ a, b = SpecNamespace::NestedListInMapValue.new, SpecNamespace::NestedListInMapValue.new
77
+ [a, b].each do |thrift_struct|
78
+ thrift_struct.value = { 1 => [1, 2, 3], 2 => [2, 3, 4] }
79
+ thrift_struct.validate
80
+ end
81
+ a.should == b
82
+ b.value[3] = [3, 4, 5]
83
+ a.should_not == b
84
+ end
85
+ end
86
+
87
+ it "should support nested sets inside lists" do
88
+ with_type_checking do
89
+ a, b = SpecNamespace::NestedSetInList.new, SpecNamespace::NestedSetInList.new
90
+ [a, b].each do |thrift_struct|
91
+ thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ]
92
+ thrift_struct.validate
93
+ end
94
+ a.should == b
95
+ b.value.push([3, 4, 5].to_set)
96
+ a.should_not == b
97
+ end
98
+ end
99
+
100
+ it "should support nested sets inside sets" do
101
+ with_type_checking do
102
+ a, b = SpecNamespace::NestedSetInSet.new, SpecNamespace::NestedSetInSet.new
103
+ [a, b].each do |thrift_struct|
104
+ thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ].to_set
105
+ thrift_struct.validate
106
+ end
107
+ a.should == b
108
+ b.value.add([3, 4, 5].to_set)
109
+ a.should_not == b
110
+ end
111
+ end
112
+
113
+ it "should support nested sets in map keys" do
114
+ with_type_checking do
115
+ a, b = SpecNamespace::NestedSetInMapKey.new, SpecNamespace::NestedSetInMapKey.new
116
+ [a, b].each do |thrift_struct|
117
+ thrift_struct.value = { [1, 2, 3].to_set => 1, [2, 3, 4].to_set => 2 }
118
+ thrift_struct.validate
119
+ end
120
+ a.should == b
121
+ b.value[[3, 4, 5].to_set] = 3
122
+ a.should_not == b
123
+ end
124
+ end
125
+
126
+ it "should support nested sets in map values" do
127
+ with_type_checking do
128
+ a, b = SpecNamespace::NestedSetInMapValue.new, SpecNamespace::NestedSetInMapValue.new
129
+ [a, b].each do |thrift_struct|
130
+ thrift_struct.value = { 1 => [1, 2, 3].to_set, 2 => [2, 3, 4].to_set }
131
+ thrift_struct.validate
132
+ end
133
+ a.should == b
134
+ b.value[3] = [3, 4, 5].to_set
135
+ a.should_not == b
136
+ end
137
+ end
138
+
139
+ it "should support nested maps inside lists" do
140
+ with_type_checking do
141
+ a, b = SpecNamespace::NestedMapInList.new, SpecNamespace::NestedMapInList.new
142
+ [a, b].each do |thrift_struct|
143
+ thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ]
144
+ thrift_struct.validate
145
+ end
146
+ a.should == b
147
+ b.value.push({ 3 => 4, 5 => 6 })
148
+ a.should_not == b
149
+ end
150
+ end
151
+
152
+ it "should support nested maps inside sets" do
153
+ with_type_checking do
154
+ a, b = SpecNamespace::NestedMapInSet.new, SpecNamespace::NestedMapInSet.new
155
+ [a, b].each do |thrift_struct|
156
+ thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ].to_set
157
+ thrift_struct.validate
158
+ end
159
+ a.should == b
160
+ b.value.add({ 3 => 4, 5 => 6 })
161
+ a.should_not == b
162
+ end
163
+ end
164
+
165
+ it "should support nested maps in map keys" do
166
+ with_type_checking do
167
+ a, b = SpecNamespace::NestedMapInMapKey.new, SpecNamespace::NestedMapInMapKey.new
168
+ [a, b].each do |thrift_struct|
169
+ thrift_struct.value = { { 1 => 2, 3 => 4} => 1, {2 => 3, 4 => 5} => 2 }
170
+ thrift_struct.validate
171
+ end
172
+ a.should == b
173
+ b.value[{3 => 4, 5 => 6}] = 3
174
+ a.should_not == b
175
+ end
176
+ end
177
+
178
+ it "should support nested maps in map values" do
179
+ with_type_checking do
180
+ a, b = SpecNamespace::NestedMapInMapValue.new, SpecNamespace::NestedMapInMapValue.new
181
+ [a, b].each do |thrift_struct|
182
+ thrift_struct.value = { 1 => { 1 => 2, 3 => 4}, 2 => {2 => 3, 4 => 5} }
183
+ thrift_struct.validate
184
+ end
185
+ a.should == b
186
+ b.value[3] = { 3 => 4, 5 => 6 }
187
+ a.should_not == b
188
+ end
189
+ end
190
+ end
191
+ end