tiny_thrift 1.0.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.
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