stark 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +10 -0
- data/History.txt +19 -0
- data/Manifest.txt +17 -3
- data/README.md +164 -0
- data/Rakefile +4 -1
- data/bin/stark +11 -3
- data/examples/README.md +114 -0
- data/examples/client.rb +13 -0
- data/examples/health.thrift +9 -0
- data/examples/server.rb +18 -0
- data/lib/stark.rb +16 -2
- data/lib/stark/ast.rb +5 -0
- data/lib/stark/client.rb +3 -67
- data/lib/stark/exception.rb +9 -9
- data/lib/stark/processor.rb +13 -52
- data/lib/stark/protocol_helpers.rb +161 -0
- data/lib/stark/raw_parser.rb +75 -14
- data/lib/stark/ruby.rb +267 -248
- data/lib/stark/struct.rb +37 -26
- data/lib/stark/thrift.kpeg +6 -4
- data/stark.gemspec +15 -15
- data/test/ThriftSpec.thrift +4 -0
- data/test/comments.thrift +15 -0
- data/test/leg.rb +0 -2
- data/test/parsing_error.thrift +5 -0
- data/test/properties.thrift +9 -0
- data/test/test_client.rb +116 -241
- data/test/test_coerce_strings.rb +187 -0
- data/test/test_helper.rb +113 -0
- data/test/test_marshal.rb +131 -0
- data/test/test_parser.rb +61 -0
- data/test/test_ruby.rb +148 -9
- data/test/test_server.rb +96 -212
- data/test/test_stark.rb +67 -0
- data/test/types.thrift +49 -0
- data/test/users.thrift +16 -0
- metadata +33 -15
- data/README.txt +0 -67
- data/lib/stark/converters.rb +0 -188
- data/lib/stark/field.rb +0 -27
data/test/test_ruby.rb
CHANGED
@@ -3,25 +3,164 @@ require 'stark'
|
|
3
3
|
require 'stark/ruby'
|
4
4
|
|
5
5
|
class TestRuby < Test::Unit::TestCase
|
6
|
-
def
|
7
|
-
ast = Stark::Parser.ast
|
8
|
-
|
6
|
+
def create_ruby(thrift, options = {})
|
7
|
+
ast = Stark::Parser.ast thrift
|
8
|
+
stream = StringIO.new
|
9
|
+
ruby = Stark::Ruby.new stream
|
10
|
+
options[:skip_prologue] = options[:skip_epilogue] = true if options[:only_ast]
|
11
|
+
stream.string = '' if options[:skip_prologue]
|
12
|
+
if options[:skip_epilogue]
|
13
|
+
ast.each { |a| a.accept ruby }
|
14
|
+
else
|
15
|
+
ruby.run ast
|
16
|
+
end
|
17
|
+
stream.string
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_ns_module(name, lang = 'rb')
|
21
|
+
thrift = <<-EOM
|
22
|
+
namespace #{lang} #{name}
|
9
23
|
enum Status {
|
10
24
|
DEAD
|
11
25
|
ALIVE
|
12
26
|
}
|
13
27
|
EOM
|
14
28
|
|
15
|
-
stream = StringIO.new
|
16
|
-
ruby = Stark::Ruby.new stream
|
17
|
-
|
18
|
-
ruby.run ast
|
19
|
-
|
20
29
|
ns = Module.new
|
21
30
|
|
22
|
-
ns.module_eval
|
31
|
+
ns.module_eval create_ruby(thrift)
|
32
|
+
ns
|
33
|
+
end
|
23
34
|
|
35
|
+
def test_namespace1
|
36
|
+
ns = create_ns_module 'Blah'
|
24
37
|
assert ns::Blah
|
25
38
|
assert ns::Blah::Enum_Status
|
26
39
|
end
|
40
|
+
|
41
|
+
def test_namespace2
|
42
|
+
ns = create_ns_module 'Blah.Blerg'
|
43
|
+
assert ns::Blah::Blerg
|
44
|
+
assert ns::Blah::Blerg::Enum_Status
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_namespace3
|
48
|
+
ns = create_ns_module 'Blah.Blerg', '*'
|
49
|
+
assert ns::Blah::Blerg
|
50
|
+
assert ns::Blah::Blerg::Enum_Status
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_namespace4
|
54
|
+
ns = create_ns_module 'Blah.Blerg', 'c'
|
55
|
+
assert ns::Enum_Status
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_forward_declaration
|
59
|
+
code = <<-EOM
|
60
|
+
struct Foo {
|
61
|
+
1: Bar bar
|
62
|
+
}
|
63
|
+
|
64
|
+
struct Bar {
|
65
|
+
1: i32 ids
|
66
|
+
}
|
67
|
+
EOM
|
68
|
+
|
69
|
+
ns = Module.new
|
70
|
+
ns.module_eval create_ruby code
|
71
|
+
assert ns::Foo
|
72
|
+
assert ns::Bar
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_struct_attr_accessor
|
76
|
+
ruby = create_ruby <<-EOM, :only_ast => true
|
77
|
+
struct Foo {
|
78
|
+
1:string str
|
79
|
+
2:map<string,string> map
|
80
|
+
3:i32 int
|
81
|
+
}
|
82
|
+
EOM
|
83
|
+
assert ruby =~ %r{class\sFoo\s<\sStark::Struct
|
84
|
+
.*
|
85
|
+
attr_accessor\s:str
|
86
|
+
.*
|
87
|
+
attr_accessor\s:map
|
88
|
+
.*
|
89
|
+
attr_accessor\s:int}mx, "did not match:\n#{ruby}"
|
90
|
+
ns = Module.new
|
91
|
+
ns.module_eval ruby
|
92
|
+
fields = ns::Foo.fields
|
93
|
+
assert_equal({ 1 => :str, 2 => :map, 3 => :int }, fields)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_struct_set_field_number
|
97
|
+
ruby = create_ruby <<-EOM, :only_ast => true
|
98
|
+
struct Foo {
|
99
|
+
3:string str
|
100
|
+
2:map<string,string> map
|
101
|
+
1:i32 int
|
102
|
+
}
|
103
|
+
EOM
|
104
|
+
|
105
|
+
assert ruby =~ %r{class\sFoo\s<\sStark::Struct
|
106
|
+
.*
|
107
|
+
field_number\s3
|
108
|
+
.*
|
109
|
+
attr_accessor\s:str
|
110
|
+
.*
|
111
|
+
field_number\s2
|
112
|
+
.*
|
113
|
+
attr_accessor\s:map
|
114
|
+
.*
|
115
|
+
field_number\s1
|
116
|
+
.*
|
117
|
+
attr_accessor\s:int}mx, "did not match:\n#{ruby}"
|
118
|
+
ns = Module.new
|
119
|
+
ns.module_eval ruby
|
120
|
+
fields = ns::Foo.fields
|
121
|
+
assert_equal({ 3 => :str, 2 => :map, 1 => :int }, fields)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_to_struct_to_hash
|
125
|
+
ruby = create_ruby <<-EOM, :only_ast => true
|
126
|
+
struct Foo {
|
127
|
+
1:string str
|
128
|
+
2:map<string,string> map
|
129
|
+
3:i32 int
|
130
|
+
}
|
131
|
+
EOM
|
132
|
+
|
133
|
+
ns = Module.new
|
134
|
+
ns.module_eval ruby
|
135
|
+
assert ns::Foo
|
136
|
+
|
137
|
+
foo = ns::Foo.new :str => "hi", :int => 20
|
138
|
+
assert_equal({:str => "hi", :int => 20}, foo.to_hash)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_to_struct_aref
|
142
|
+
ruby = create_ruby <<-EOM, :only_ast => true
|
143
|
+
struct Foo {
|
144
|
+
1:string str
|
145
|
+
2:map<string,string> map
|
146
|
+
3:i32 int
|
147
|
+
}
|
148
|
+
EOM
|
149
|
+
|
150
|
+
ns = Module.new
|
151
|
+
ns.module_eval ruby
|
152
|
+
assert ns::Foo
|
153
|
+
|
154
|
+
foo = ns::Foo.new :str => "hi", :int => 20
|
155
|
+
assert_equal "hi", foo["str"]
|
156
|
+
assert_equal "hi", foo[:str]
|
157
|
+
assert_equal "hi", foo[1]
|
158
|
+
assert_equal 20, foo["int"]
|
159
|
+
assert_equal 20, foo[:int]
|
160
|
+
assert_equal 20, foo[3]
|
161
|
+
assert_equal ["hi", nil, 20], foo[1..3]
|
162
|
+
assert_equal ["hi", 20], foo[1, 3]
|
163
|
+
assert_equal ["hi", 20], foo[:str, :int]
|
164
|
+
end
|
165
|
+
|
27
166
|
end
|
data/test/test_server.rb
CHANGED
@@ -5,99 +5,27 @@ require 'stark'
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'thrift'
|
7
7
|
|
8
|
-
|
8
|
+
require 'test/test_helper'
|
9
9
|
|
10
10
|
class TestServer < Test::Unit::TestCase
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@server_p = Thrift::BinaryProtocol.new @server_t
|
15
|
-
|
16
|
-
@n = Module.new
|
17
|
-
Stark.materialize "test/profile.thrift", @n
|
18
|
-
|
19
|
-
@client = @n::UserStorage::Client.new @client_p, @client_p
|
20
|
-
@handler = Handler.new @n
|
21
|
-
@server = @n::UserStorage::Processor.new @handler
|
22
|
-
end
|
23
|
-
|
24
|
-
def teardown
|
25
|
-
@client_t.close
|
26
|
-
@server_t.close
|
27
|
-
end
|
28
|
-
|
29
|
-
class Handler
|
30
|
-
def initialize(n)
|
31
|
-
@users = {}
|
32
|
-
@last_map = nil
|
33
|
-
@last_list = nil
|
34
|
-
@last_status = nil
|
35
|
-
@n = n
|
36
|
-
@user_status = nil
|
37
|
-
end
|
38
|
-
|
39
|
-
attr_accessor :last_map, :last_list, :last_status, :user_status
|
40
|
-
|
41
|
-
def store(obj)
|
42
|
-
@users[obj.uid] = obj
|
43
|
-
end
|
44
|
-
|
45
|
-
def retrieve(id)
|
46
|
-
@users[id]
|
47
|
-
end
|
48
|
-
|
49
|
-
def set_map(m)
|
50
|
-
@last_map = m
|
51
|
-
end
|
52
|
-
|
53
|
-
def set_list(l)
|
54
|
-
@last_list = l
|
55
|
-
end
|
56
|
-
|
57
|
-
def set_status(s)
|
58
|
-
@last_status = s
|
59
|
-
end
|
60
|
-
|
61
|
-
def volume_up
|
62
|
-
raise @n::RockTooHard.new('volume' => 11)
|
63
|
-
end
|
11
|
+
IDL = "test/profile.thrift"
|
12
|
+
SERVICE = "UserStorage"
|
13
|
+
include TestHelper
|
64
14
|
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
def add(a,b)
|
70
|
-
a + b
|
71
|
-
end
|
72
|
-
|
73
|
-
def set_user_status(s)
|
74
|
-
@user_status = s
|
75
|
-
end
|
76
|
-
|
77
|
-
attr_accessor :user_relationship
|
78
|
-
def set_user_relationship(rel)
|
79
|
-
@user_relationship = rel
|
80
|
-
end
|
15
|
+
def setup
|
16
|
+
setup_server
|
81
17
|
end
|
82
18
|
|
83
19
|
def test_store_and_retrieve
|
84
|
-
|
85
|
-
@
|
86
|
-
end
|
87
|
-
|
88
|
-
xuser = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
89
|
-
|
90
|
-
@client.store xuser
|
20
|
+
send_to_server do
|
21
|
+
xuser = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
91
22
|
|
92
|
-
|
93
|
-
|
94
|
-
st = Thread.new do
|
95
|
-
@server.process @server_p, @server_p
|
23
|
+
@client.store xuser
|
96
24
|
end
|
97
25
|
|
98
|
-
obj =
|
99
|
-
|
100
|
-
|
26
|
+
obj = send_to_server do
|
27
|
+
@client.retrieve 0
|
28
|
+
end
|
101
29
|
|
102
30
|
assert_equal 0, obj.uid
|
103
31
|
assert_equal "root", obj.name
|
@@ -105,215 +33,171 @@ class TestServer < Test::Unit::TestCase
|
|
105
33
|
end
|
106
34
|
|
107
35
|
def test_set_map
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
m = { "blah" => "foo", "a" => "b" }
|
36
|
+
send_to_server do
|
37
|
+
m = { "blah" => "foo", "a" => "b" }
|
113
38
|
|
114
|
-
|
115
|
-
|
116
|
-
st.join
|
39
|
+
@client.set_map m
|
40
|
+
end
|
117
41
|
|
118
42
|
assert_equal "foo", @handler.last_map["blah"]
|
119
43
|
assert_equal "b", @handler.last_map["a"]
|
120
44
|
end
|
121
45
|
|
122
46
|
def test_last_map
|
123
|
-
|
124
|
-
@
|
125
|
-
end
|
126
|
-
|
127
|
-
@handler.last_map = { "blah" => "foo", "a" => "b" }
|
128
|
-
|
129
|
-
m = @client.last_map
|
47
|
+
m = send_to_server do
|
48
|
+
@handler.last_map = { "blah" => "foo", "a" => "b" }
|
130
49
|
|
131
|
-
|
50
|
+
@client.last_map
|
51
|
+
end
|
132
52
|
|
133
53
|
assert_equal "foo", m["blah"]
|
134
54
|
assert_equal "b", m["a"]
|
135
55
|
end
|
136
56
|
|
137
57
|
def test_set_list
|
138
|
-
st = Thread.new do
|
139
|
-
@server.process @server_p, @server_p
|
140
|
-
end
|
141
|
-
|
142
58
|
m = [ "blah", "foo", "a", "b" ]
|
59
|
+
send_to_server do
|
143
60
|
|
144
|
-
|
145
|
-
|
146
|
-
st.join
|
61
|
+
@client.set_list m
|
62
|
+
end
|
147
63
|
|
148
64
|
assert_equal m, @handler.last_list
|
149
65
|
end
|
150
66
|
|
151
67
|
def test_last_list
|
152
|
-
|
153
|
-
|
154
|
-
|
68
|
+
send_to_server do
|
69
|
+
l = [ "blah", "foo", "a", "b" ]
|
70
|
+
@handler.last_list = l
|
155
71
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
assert_equal l, @client.last_list
|
160
|
-
|
161
|
-
st.join
|
72
|
+
assert_equal l, @client.last_list
|
73
|
+
end
|
162
74
|
end
|
163
75
|
|
164
76
|
def test_last_list_is_nil
|
165
|
-
|
166
|
-
|
77
|
+
send_to_server do
|
78
|
+
assert_equal nil, @client.last_list
|
167
79
|
end
|
168
|
-
|
169
|
-
assert_equal [], @client.last_list
|
170
|
-
|
171
|
-
st.join
|
172
80
|
end
|
173
81
|
|
174
82
|
def test_enum
|
175
|
-
|
176
|
-
@
|
83
|
+
send_to_server do
|
84
|
+
@client.set_status :ON
|
177
85
|
end
|
178
86
|
|
179
|
-
@client.set_status :ON
|
180
|
-
|
181
|
-
st.join
|
182
|
-
|
183
87
|
assert_equal :ON, @handler.last_status
|
184
88
|
end
|
185
89
|
|
186
90
|
def test_enum_recv
|
187
|
-
|
188
|
-
@
|
189
|
-
end
|
190
|
-
|
191
|
-
@handler.last_status = :ON
|
192
|
-
|
193
|
-
assert_equal :ON, @client.last_status
|
91
|
+
send_to_server do
|
92
|
+
@handler.last_status = :ON
|
194
93
|
|
195
|
-
|
94
|
+
assert_equal :ON, @client.last_status
|
95
|
+
end
|
196
96
|
end
|
197
97
|
|
198
98
|
def test_throw
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
e = assert_raises @n::RockTooHard do
|
204
|
-
@client.volume_up
|
99
|
+
e = send_to_server do
|
100
|
+
assert_raises @n::RockTooHard do
|
101
|
+
@client.volume_up
|
102
|
+
end
|
205
103
|
end
|
206
104
|
|
207
|
-
st.join
|
208
|
-
|
209
105
|
assert_equal 11, e.volume
|
210
106
|
end
|
211
107
|
|
212
|
-
# Thread.abort_on_exception = true
|
213
|
-
|
214
108
|
def test_oneway
|
215
|
-
|
216
|
-
|
217
|
-
end
|
109
|
+
send_to_server do
|
110
|
+
t = Time.now
|
218
111
|
|
219
|
-
|
112
|
+
Timeout.timeout 3 do
|
113
|
+
assert_equal nil, @client.make_bitcoins
|
114
|
+
end
|
220
115
|
|
221
|
-
|
222
|
-
assert_equal nil, @client.make_bitcoins
|
116
|
+
assert Time.now - t < 0.1
|
223
117
|
end
|
224
|
-
|
225
|
-
assert Time.now - t < 0.1
|
226
|
-
|
227
|
-
st.join
|
228
118
|
end
|
229
119
|
|
230
120
|
def test_2args
|
231
|
-
|
232
|
-
@
|
121
|
+
send_to_server do
|
122
|
+
assert_equal 7, @client.add(3, 4)
|
233
123
|
end
|
234
|
-
|
235
|
-
assert_equal 7, @client.add(3, 4)
|
236
|
-
|
237
|
-
st.join
|
238
124
|
end
|
239
125
|
|
240
126
|
def test_read_struct_in_a_struct
|
241
|
-
|
242
|
-
@
|
243
|
-
|
244
|
-
|
245
|
-
prof = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
246
|
-
stat = @n::UserStatus.new 'profile' => prof, 'active' => true
|
127
|
+
send_to_server do
|
128
|
+
prof = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
129
|
+
stat = @n::UserStatus.new 'profile' => prof, 'active' => true
|
247
130
|
|
248
|
-
|
131
|
+
@handler.user_status = stat
|
249
132
|
|
250
|
-
|
133
|
+
status = @client.user_status
|
251
134
|
|
252
|
-
|
253
|
-
|
254
|
-
prof = status.profile
|
135
|
+
assert_equal true, status.active
|
255
136
|
|
256
|
-
|
257
|
-
assert_equal "root", prof.name
|
258
|
-
assert_equal "god", prof.blurb
|
137
|
+
prof = status.profile
|
259
138
|
|
260
|
-
|
139
|
+
assert_equal 0, prof.uid
|
140
|
+
assert_equal "root", prof.name
|
141
|
+
assert_equal "god", prof.blurb
|
142
|
+
end
|
261
143
|
end
|
262
144
|
|
263
145
|
def test_write_struct_in_a_struct
|
264
|
-
|
265
|
-
@
|
266
|
-
|
267
|
-
|
268
|
-
prof = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
269
|
-
stat = @n::UserStatus.new 'profile' => prof, 'active' => true
|
146
|
+
send_to_server do
|
147
|
+
prof = @n::UserProfile.new 'uid' => 0, 'name' => 'root', 'blurb' => 'god'
|
148
|
+
stat = @n::UserStatus.new 'profile' => prof, 'active' => true
|
270
149
|
|
271
|
-
|
150
|
+
@client.set_user_status stat
|
272
151
|
|
273
|
-
|
152
|
+
status = @handler.user_status
|
274
153
|
|
275
|
-
|
276
|
-
|
277
|
-
prof = status.profile
|
154
|
+
assert_equal true, status.active
|
278
155
|
|
279
|
-
|
280
|
-
assert_equal "root", prof.name
|
281
|
-
assert_equal "god", prof.blurb
|
156
|
+
prof = status.profile
|
282
157
|
|
283
|
-
|
158
|
+
assert_equal 0, prof.uid
|
159
|
+
assert_equal "root", prof.name
|
160
|
+
assert_equal "god", prof.blurb
|
161
|
+
end
|
284
162
|
end
|
285
163
|
|
286
164
|
def test_read_enum_in_struct
|
287
|
-
|
288
|
-
@
|
289
|
-
end
|
290
|
-
|
291
|
-
stat = @n::UserRelationship.new 'user' => 0, 'status' => :ITS_COMPLICATED
|
165
|
+
send_to_server do
|
166
|
+
stat = @n::UserRelationship.new 'user' => 0, 'status' => :ITS_COMPLICATED
|
292
167
|
|
293
|
-
|
168
|
+
@handler.user_relationship = stat
|
294
169
|
|
295
|
-
|
170
|
+
rel = @client.user_relationship
|
296
171
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
st.join
|
172
|
+
assert_equal 0, rel.user
|
173
|
+
assert_equal :ITS_COMPLICATED, rel.status
|
174
|
+
end
|
301
175
|
end
|
302
176
|
|
303
177
|
def test_write_enum_in_struct
|
304
|
-
|
305
|
-
@server.process @server_p, @server_p
|
306
|
-
end
|
178
|
+
send_to_server do
|
307
179
|
|
308
|
-
|
180
|
+
stat = @n::UserRelationship.new 'user' => 0, 'status' => :ITS_COMPLICATED
|
309
181
|
|
310
|
-
|
182
|
+
@client.set_user_relationship stat
|
311
183
|
|
312
|
-
|
184
|
+
rel = @handler.user_relationship
|
313
185
|
|
314
|
-
|
315
|
-
|
186
|
+
assert_equal 0, rel.user
|
187
|
+
assert_equal :ITS_COMPLICATED, rel.status
|
188
|
+
end
|
189
|
+
end
|
316
190
|
|
317
|
-
|
191
|
+
def test_exception_raised
|
192
|
+
set_handler Object.new.tap {|h| def h.respond_to?(*); true; end}
|
193
|
+
|
194
|
+
e = send_to_server do
|
195
|
+
assert_raises Thrift::ApplicationException do
|
196
|
+
@client.last_status
|
197
|
+
end
|
198
|
+
end
|
199
|
+
assert e.type == Thrift::ApplicationException::INTERNAL_ERROR
|
200
|
+
assert e.message =~ /undefined method/
|
201
|
+
assert @log_stream.string =~ /undefined method/
|
318
202
|
end
|
319
203
|
end
|