upfluence-thrift 1.0.1

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 (128) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +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/gen-rb/benchmark_constants.rb +11 -0
  7. data/benchmark/gen-rb/benchmark_service.rb +80 -0
  8. data/benchmark/gen-rb/benchmark_types.rb +10 -0
  9. data/benchmark/server.rb +82 -0
  10. data/benchmark/thin_server.rb +44 -0
  11. data/ext/binary_protocol_accelerated.c +460 -0
  12. data/ext/binary_protocol_accelerated.h +20 -0
  13. data/ext/bytes.c +36 -0
  14. data/ext/bytes.h +31 -0
  15. data/ext/compact_protocol.c +637 -0
  16. data/ext/compact_protocol.h +20 -0
  17. data/ext/constants.h +99 -0
  18. data/ext/extconf.rb +34 -0
  19. data/ext/macros.h +41 -0
  20. data/ext/memory_buffer.c +134 -0
  21. data/ext/memory_buffer.h +20 -0
  22. data/ext/protocol.c +0 -0
  23. data/ext/protocol.h +0 -0
  24. data/ext/strlcpy.c +41 -0
  25. data/ext/strlcpy.h +34 -0
  26. data/ext/struct.c +707 -0
  27. data/ext/struct.h +25 -0
  28. data/ext/thrift_native.c +201 -0
  29. data/lib/thrift.rb +68 -0
  30. data/lib/thrift/bytes.rb +131 -0
  31. data/lib/thrift/client.rb +71 -0
  32. data/lib/thrift/core_ext.rb +23 -0
  33. data/lib/thrift/core_ext/fixnum.rb +29 -0
  34. data/lib/thrift/exceptions.rb +87 -0
  35. data/lib/thrift/multiplexed_processor.rb +76 -0
  36. data/lib/thrift/processor.rb +57 -0
  37. data/lib/thrift/protocol/base_protocol.rb +379 -0
  38. data/lib/thrift/protocol/binary_protocol.rb +237 -0
  39. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  40. data/lib/thrift/protocol/compact_protocol.rb +435 -0
  41. data/lib/thrift/protocol/json_protocol.rb +769 -0
  42. data/lib/thrift/protocol/multiplexed_protocol.rb +40 -0
  43. data/lib/thrift/protocol/protocol_decorator.rb +194 -0
  44. data/lib/thrift/serializer/deserializer.rb +33 -0
  45. data/lib/thrift/serializer/serializer.rb +34 -0
  46. data/lib/thrift/server/base_server.rb +31 -0
  47. data/lib/thrift/server/mongrel_http_server.rb +60 -0
  48. data/lib/thrift/server/nonblocking_server.rb +305 -0
  49. data/lib/thrift/server/rack_application.rb +61 -0
  50. data/lib/thrift/server/simple_server.rb +43 -0
  51. data/lib/thrift/server/thin_http_server.rb +51 -0
  52. data/lib/thrift/server/thread_pool_server.rb +75 -0
  53. data/lib/thrift/server/threaded_server.rb +47 -0
  54. data/lib/thrift/struct.rb +237 -0
  55. data/lib/thrift/struct_union.rb +192 -0
  56. data/lib/thrift/thrift_native.rb +24 -0
  57. data/lib/thrift/transport/base_server_transport.rb +37 -0
  58. data/lib/thrift/transport/base_transport.rb +109 -0
  59. data/lib/thrift/transport/buffered_transport.rb +114 -0
  60. data/lib/thrift/transport/framed_transport.rb +117 -0
  61. data/lib/thrift/transport/http_client_transport.rb +56 -0
  62. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  63. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  64. data/lib/thrift/transport/server_socket.rb +63 -0
  65. data/lib/thrift/transport/socket.rb +139 -0
  66. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  67. data/lib/thrift/transport/unix_socket.rb +40 -0
  68. data/lib/thrift/types.rb +101 -0
  69. data/lib/thrift/union.rb +179 -0
  70. data/spec/BaseService.thrift +27 -0
  71. data/spec/ExtendedService.thrift +25 -0
  72. data/spec/Referenced.thrift +44 -0
  73. data/spec/ThriftNamespacedSpec.thrift +53 -0
  74. data/spec/ThriftSpec.thrift +183 -0
  75. data/spec/base_protocol_spec.rb +217 -0
  76. data/spec/base_transport_spec.rb +350 -0
  77. data/spec/binary_protocol_accelerated_spec.rb +42 -0
  78. data/spec/binary_protocol_spec.rb +66 -0
  79. data/spec/binary_protocol_spec_shared.rb +455 -0
  80. data/spec/bytes_spec.rb +160 -0
  81. data/spec/client_spec.rb +99 -0
  82. data/spec/compact_protocol_spec.rb +143 -0
  83. data/spec/exception_spec.rb +141 -0
  84. data/spec/flat_spec.rb +62 -0
  85. data/spec/gen-rb/base/base_service.rb +80 -0
  86. data/spec/gen-rb/base/base_service_constants.rb +11 -0
  87. data/spec/gen-rb/base/base_service_types.rb +26 -0
  88. data/spec/gen-rb/extended/extended_service.rb +78 -0
  89. data/spec/gen-rb/extended/extended_service_constants.rb +11 -0
  90. data/spec/gen-rb/extended/extended_service_types.rb +12 -0
  91. data/spec/gen-rb/flat/namespaced_nonblocking_service.rb +272 -0
  92. data/spec/gen-rb/flat/referenced_constants.rb +11 -0
  93. data/spec/gen-rb/flat/referenced_types.rb +17 -0
  94. data/spec/gen-rb/flat/thrift_namespaced_spec_constants.rb +11 -0
  95. data/spec/gen-rb/flat/thrift_namespaced_spec_types.rb +28 -0
  96. data/spec/gen-rb/namespaced_spec_namespace/namespaced_nonblocking_service.rb +272 -0
  97. data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_constants.rb +11 -0
  98. data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_types.rb +28 -0
  99. data/spec/gen-rb/nonblocking_service.rb +272 -0
  100. data/spec/gen-rb/other_namespace/referenced_constants.rb +11 -0
  101. data/spec/gen-rb/other_namespace/referenced_types.rb +17 -0
  102. data/spec/gen-rb/thrift_spec_constants.rb +11 -0
  103. data/spec/gen-rb/thrift_spec_types.rb +538 -0
  104. data/spec/http_client_spec.rb +120 -0
  105. data/spec/json_protocol_spec.rb +513 -0
  106. data/spec/namespaced_spec.rb +67 -0
  107. data/spec/nonblocking_server_spec.rb +263 -0
  108. data/spec/processor_spec.rb +80 -0
  109. data/spec/serializer_spec.rb +67 -0
  110. data/spec/server_socket_spec.rb +79 -0
  111. data/spec/server_spec.rb +147 -0
  112. data/spec/socket_spec.rb +61 -0
  113. data/spec/socket_spec_shared.rb +104 -0
  114. data/spec/spec_helper.rb +64 -0
  115. data/spec/struct_nested_containers_spec.rb +191 -0
  116. data/spec/struct_spec.rb +293 -0
  117. data/spec/thin_http_server_spec.rb +141 -0
  118. data/spec/types_spec.rb +115 -0
  119. data/spec/union_spec.rb +203 -0
  120. data/spec/unix_socket_spec.rb +107 -0
  121. data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +274 -0
  122. data/test/debug_proto/gen-rb/debug_proto_test_types.rb +761 -0
  123. data/test/debug_proto/gen-rb/empty_service.rb +24 -0
  124. data/test/debug_proto/gen-rb/inherited.rb +79 -0
  125. data/test/debug_proto/gen-rb/reverse_order_service.rb +82 -0
  126. data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +81 -0
  127. data/test/debug_proto/gen-rb/srv.rb +330 -0
  128. metadata +388 -0
@@ -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
@@ -0,0 +1,293 @@
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 'Struct' do
23
+
24
+ describe Thrift::Struct do
25
+ it "should iterate over all fields properly" do
26
+ fields = {}
27
+ SpecNamespace::Foo.new.each_field { |fid,field_info| fields[fid] = field_info }
28
+ fields.should == SpecNamespace::Foo::FIELDS
29
+ end
30
+
31
+ it "should initialize all fields to defaults" do
32
+ validate_default_arguments(SpecNamespace::Foo.new)
33
+ end
34
+
35
+ it "should initialize all fields to defaults and accept a block argument" do
36
+ SpecNamespace::Foo.new do |f|
37
+ validate_default_arguments(f)
38
+ end
39
+ end
40
+
41
+ def validate_default_arguments(object)
42
+ object.simple.should == 53
43
+ object.words.should == "words"
44
+ object.hello.should == SpecNamespace::Hello.new(:greeting => 'hello, world!')
45
+ object.ints.should == [1, 2, 2, 3]
46
+ object.complex.should be_nil
47
+ object.shorts.should == Set.new([5, 17, 239])
48
+ end
49
+
50
+ it "should not share default values between instances" do
51
+ begin
52
+ struct = SpecNamespace::Foo.new
53
+ struct.ints << 17
54
+ SpecNamespace::Foo.new.ints.should == [1,2,2,3]
55
+ ensure
56
+ # ensure no leakage to other tests
57
+ SpecNamespace::Foo::FIELDS[4][:default] = [1,2,2,3]
58
+ end
59
+ end
60
+
61
+ it "should properly initialize boolean values" do
62
+ struct = SpecNamespace::BoolStruct.new(:yesno => false)
63
+ struct.yesno.should be_false
64
+ end
65
+
66
+ it "should have proper == semantics" do
67
+ SpecNamespace::Foo.new.should_not == SpecNamespace::Hello.new
68
+ SpecNamespace::Foo.new.should == SpecNamespace::Foo.new
69
+ SpecNamespace::Foo.new(:simple => 52).should_not == SpecNamespace::Foo.new
70
+ end
71
+
72
+ it "should print enum value names in inspect" do
73
+ SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect.should == "<SpecNamespace::StructWithSomeEnum some_enum:ONE (0)>"
74
+
75
+ SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect.should == "<SpecNamespace::StructWithEnumMap my_map:{ONE (0): [TWO (1)]}>"
76
+ end
77
+
78
+ it "should pretty print binary fields" do
79
+ SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect.should == "<SpecNamespace::Foo2 my_binary:010203>"
80
+ end
81
+
82
+ it "should offer field? methods" do
83
+ SpecNamespace::Foo.new.opt_string?.should be_false
84
+ SpecNamespace::Foo.new(:simple => 52).simple?.should be_true
85
+ SpecNamespace::Foo.new(:my_bool => false).my_bool?.should be_true
86
+ SpecNamespace::Foo.new(:my_bool => true).my_bool?.should be_true
87
+ end
88
+
89
+ it "should be comparable" do
90
+ s1 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE)
91
+ s2 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::TWO)
92
+
93
+ (s1 <=> s2).should == -1
94
+ (s2 <=> s1).should == 1
95
+ (s1 <=> s1).should == 0
96
+ (s1 <=> SpecNamespace::StructWithSomeEnum.new()).should == -1
97
+ end
98
+
99
+ it "should read itself off the wire" do
100
+ struct = SpecNamespace::Foo.new
101
+ prot = Thrift::BaseProtocol.new(mock("transport"))
102
+ prot.should_receive(:read_struct_begin).twice
103
+ prot.should_receive(:read_struct_end).twice
104
+ prot.should_receive(:read_field_begin).and_return(
105
+ ['complex', Thrift::Types::MAP, 5], # Foo
106
+ ['words', Thrift::Types::STRING, 2], # Foo
107
+ ['hello', Thrift::Types::STRUCT, 3], # Foo
108
+ ['greeting', Thrift::Types::STRING, 1], # Hello
109
+ [nil, Thrift::Types::STOP, 0], # Hello
110
+ ['simple', Thrift::Types::I32, 1], # Foo
111
+ ['ints', Thrift::Types::LIST, 4], # Foo
112
+ ['shorts', Thrift::Types::SET, 6], # Foo
113
+ [nil, Thrift::Types::STOP, 0] # Hello
114
+ )
115
+ prot.should_receive(:read_field_end).exactly(7).times
116
+ prot.should_receive(:read_map_begin).and_return(
117
+ [Thrift::Types::I32, Thrift::Types::MAP, 2], # complex
118
+ [Thrift::Types::STRING, Thrift::Types::DOUBLE, 2], # complex/1/value
119
+ [Thrift::Types::STRING, Thrift::Types::DOUBLE, 1] # complex/2/value
120
+ )
121
+ prot.should_receive(:read_map_end).exactly(3).times
122
+ prot.should_receive(:read_list_begin).and_return([Thrift::Types::I32, 4])
123
+ prot.should_receive(:read_list_end)
124
+ prot.should_receive(:read_set_begin).and_return([Thrift::Types::I16, 2])
125
+ prot.should_receive(:read_set_end)
126
+ prot.should_receive(:read_i32).and_return(
127
+ 1, 14, # complex keys
128
+ 42, # simple
129
+ 4, 23, 4, 29 # ints
130
+ )
131
+ prot.should_receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
132
+ prot.should_receive(:read_double).and_return(Math::PI, Math::E, 4.669201609)
133
+ prot.should_receive(:read_i16).and_return(2, 3)
134
+ prot.should_not_receive(:skip)
135
+ struct.read(prot)
136
+
137
+ struct.simple.should == 42
138
+ struct.complex.should == {1 => {"pi" => Math::PI, "e" => Math::E}, 14 => {"feigenbaum" => 4.669201609}}
139
+ struct.hello.should == SpecNamespace::Hello.new(:greeting => "what's up?")
140
+ struct.words.should == "apple banana"
141
+ struct.ints.should == [4, 23, 4, 29]
142
+ struct.shorts.should == Set.new([3, 2])
143
+ end
144
+
145
+ it "should serialize false boolean fields correctly" do
146
+ b = SpecNamespace::BoolStruct.new(:yesno => false)
147
+ prot = Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new)
148
+ prot.should_receive(:write_bool).with(false)
149
+ b.write(prot)
150
+ end
151
+
152
+ it "should skip unexpected fields in structs and use default values" do
153
+ struct = SpecNamespace::Foo.new
154
+ prot = Thrift::BaseProtocol.new(mock("transport"))
155
+ prot.should_receive(:read_struct_begin)
156
+ prot.should_receive(:read_struct_end)
157
+ prot.should_receive(:read_field_begin).and_return(
158
+ ['simple', Thrift::Types::I32, 1],
159
+ ['complex', Thrift::Types::STRUCT, 5],
160
+ ['thinz', Thrift::Types::MAP, 7],
161
+ ['foobar', Thrift::Types::I32, 3],
162
+ ['words', Thrift::Types::STRING, 2],
163
+ [nil, Thrift::Types::STOP, 0]
164
+ )
165
+ prot.should_receive(:read_field_end).exactly(5).times
166
+ prot.should_receive(:read_i32).and_return(42)
167
+ prot.should_receive(:read_string).and_return("foobar")
168
+ prot.should_receive(:skip).with(Thrift::Types::STRUCT)
169
+ prot.should_receive(:skip).with(Thrift::Types::MAP)
170
+ # prot.should_receive(:read_map_begin).and_return([Thrift::Types::I32, Thrift::Types::I32, 0])
171
+ # prot.should_receive(:read_map_end)
172
+ prot.should_receive(:skip).with(Thrift::Types::I32)
173
+ struct.read(prot)
174
+
175
+ struct.simple.should == 42
176
+ struct.complex.should be_nil
177
+ struct.words.should == "foobar"
178
+ struct.hello.should == SpecNamespace::Hello.new(:greeting => 'hello, world!')
179
+ struct.ints.should == [1, 2, 2, 3]
180
+ struct.shorts.should == Set.new([5, 17, 239])
181
+ end
182
+
183
+ it "should write itself to the wire" do
184
+ prot = Thrift::BaseProtocol.new(mock("transport")) #mock("Protocol")
185
+ prot.should_receive(:write_struct_begin).with("SpecNamespace::Foo")
186
+ prot.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
187
+ prot.should_receive(:write_struct_end).twice
188
+ prot.should_receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4)
189
+ prot.should_receive(:write_i32).with(1)
190
+ prot.should_receive(:write_i32).with(2).twice
191
+ prot.should_receive(:write_i32).with(3)
192
+ prot.should_receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5)
193
+ prot.should_receive(:write_i32).with(5)
194
+ prot.should_receive(:write_string).with('foo')
195
+ prot.should_receive(:write_double).with(1.23)
196
+ prot.should_receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6)
197
+ prot.should_receive(:write_i16).with(5)
198
+ prot.should_receive(:write_i16).with(17)
199
+ prot.should_receive(:write_i16).with(239)
200
+ prot.should_receive(:write_field_stop).twice
201
+ prot.should_receive(:write_field_end).exactly(6).times
202
+ prot.should_receive(:write_field_begin).with('simple', Thrift::Types::I32, 1)
203
+ prot.should_receive(:write_i32).with(53)
204
+ prot.should_receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3)
205
+ prot.should_receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1)
206
+ prot.should_receive(:write_string).with('hello, world!')
207
+ prot.should_receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1)
208
+ prot.should_receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1)
209
+ prot.should_receive(:write_map_end).twice
210
+ prot.should_receive(:write_list_begin).with(Thrift::Types::I32, 4)
211
+ prot.should_receive(:write_list_end)
212
+ prot.should_receive(:write_set_begin).with(Thrift::Types::I16, 3)
213
+ prot.should_receive(:write_set_end)
214
+
215
+ struct = SpecNamespace::Foo.new
216
+ struct.words = nil
217
+ struct.complex = {5 => {"foo" => 1.23}}
218
+ struct.write(prot)
219
+ end
220
+
221
+ it "should raise an exception if presented with an unknown container" do
222
+ # yeah this is silly, but I'm going for code coverage here
223
+ struct = SpecNamespace::Foo.new
224
+ lambda { struct.send :write_container, nil, nil, {:type => "foo"} }.should raise_error(StandardError, "Not a container type: foo")
225
+ end
226
+
227
+ it "should support optional type-checking in Thrift::Struct.new" do
228
+ Thrift.type_checking = true
229
+ begin
230
+ lambda { SpecNamespace::Hello.new(:greeting => 3) }.should raise_error(Thrift::TypeError, "Expected Types::STRING, received Fixnum for field greeting")
231
+ ensure
232
+ Thrift.type_checking = false
233
+ end
234
+ lambda { SpecNamespace::Hello.new(:greeting => 3) }.should_not raise_error(Thrift::TypeError)
235
+ end
236
+
237
+ it "should support optional type-checking in field accessors" do
238
+ Thrift.type_checking = true
239
+ begin
240
+ hello = SpecNamespace::Hello.new
241
+ lambda { hello.greeting = 3 }.should raise_error(Thrift::TypeError, "Expected Types::STRING, received Fixnum for field greeting")
242
+ ensure
243
+ Thrift.type_checking = false
244
+ end
245
+ lambda { hello.greeting = 3 }.should_not raise_error(Thrift::TypeError)
246
+ end
247
+
248
+ it "should raise an exception when unknown types are given to Thrift::Struct.new" do
249
+ lambda { SpecNamespace::Hello.new(:fish => 'salmon') }.should raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
250
+ end
251
+
252
+ it "should support `raise Xception, 'message'` for Exception structs" do
253
+ begin
254
+ raise SpecNamespace::Xception, "something happened"
255
+ rescue Thrift::Exception => e
256
+ e.message.should == "something happened"
257
+ e.code.should == 1
258
+ # ensure it gets serialized properly, this is the really important part
259
+ prot = Thrift::BaseProtocol.new(mock("trans"))
260
+ prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
261
+ prot.should_receive(:write_struct_end)
262
+ prot.should_receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)#, "something happened")
263
+ prot.should_receive(:write_string).with("something happened")
264
+ prot.should_receive(:write_field_begin).with('code', Thrift::Types::I32, 2)#, 1)
265
+ prot.should_receive(:write_i32).with(1)
266
+ prot.should_receive(:write_field_stop)
267
+ prot.should_receive(:write_field_end).twice
268
+
269
+ e.write(prot)
270
+ end
271
+ end
272
+
273
+ it "should support the regular initializer for exception structs" do
274
+ begin
275
+ raise SpecNamespace::Xception, :message => "something happened", :code => 5
276
+ rescue Thrift::Exception => e
277
+ e.message.should == "something happened"
278
+ e.code.should == 5
279
+ prot = Thrift::BaseProtocol.new(mock("trans"))
280
+ prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
281
+ prot.should_receive(:write_struct_end)
282
+ prot.should_receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)
283
+ prot.should_receive(:write_string).with("something happened")
284
+ prot.should_receive(:write_field_begin).with('code', Thrift::Types::I32, 2)
285
+ prot.should_receive(:write_i32).with(5)
286
+ prot.should_receive(:write_field_stop)
287
+ prot.should_receive(:write_field_end).twice
288
+
289
+ e.write(prot)
290
+ end
291
+ end
292
+ end
293
+ end