bitescript 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,429 @@
1
+ require 'test/unit'
2
+ require 'bitescript'
3
+ require 'bitescript/builder'
4
+
5
+ class TestBuilder < Test::Unit::TestCase
6
+ JLong = java.lang.Long
7
+ JString = java.lang.String
8
+ System = java.lang.System
9
+ JRubyMethod = org.jruby.anno.JRubyMethod
10
+
11
+ def new_class_name
12
+ "Foo" + (System.nano_time + rand(JLong::MAX_VALUE)).to_s
13
+ end
14
+
15
+ def setup
16
+ # Java 1.5 compat required for annotation tests
17
+ BiteScript.bytecode_version = BiteScript::JAVA1_5
18
+ @builder = BiteScript::FileBuilder.build('somefile.source')
19
+ @class_name = new_class_name
20
+ end
21
+
22
+ def dummy_constructor(class_builder)
23
+ class_builder.public_constructor do
24
+ aload local 'this'
25
+ invokespecial object, '<init>', [void]
26
+ returnvoid
27
+ end
28
+ end
29
+
30
+ def load_and_construct(name, class_builder)
31
+ class_bytes = class_builder.generate
32
+ File.open(name + ".class", 'w') {|f| f.write(class_bytes)}
33
+ cls = JRuby.runtime.jruby_class_loader.define_class(name, class_bytes.to_java_bytes)
34
+
35
+ cls.new_instance
36
+ end
37
+
38
+ def load(name, builder)
39
+ bytes = builder.generate
40
+ JRuby.runtime.jruby_class_loader.define_class(name, bytes.to_java_bytes)
41
+ JavaUtilities.get_proxy_class(name)
42
+ end
43
+
44
+ def try(return_type, &b)
45
+ class_name = new_class_name
46
+ cb = @builder.public_class(class_name, @builder.object);
47
+ cb.public_static_method("foo", return_type, &b)
48
+ dummy_constructor(cb)
49
+ cls = load(class_name, cb)
50
+ cls.foo
51
+ end
52
+
53
+ def test_static_method
54
+ assert_equal 'ok', try(JString) {ldc 'ok'; areturn}
55
+ end
56
+
57
+ def test_field_ops
58
+ # TODO
59
+ end
60
+
61
+ def test_sync_ops
62
+ # TODO figure out what's wrong with this and add error cases
63
+ assert_equal 'ok', try(JString) {
64
+ after = label
65
+ ldc 'ok'
66
+ astore 0
67
+ ldc 'ok'
68
+ astore 1
69
+ aload 0
70
+ # monitorenter
71
+ label :begin
72
+ ldc 'ok'
73
+ astore 1
74
+ goto after
75
+ label :finally
76
+ pop
77
+ aload 0
78
+ # monitorexit
79
+ label :end
80
+ trycatch(:begin, :finally, :finally, nil)
81
+ trycatch(:finally, :end, :finally, nil)
82
+ after.set!
83
+ aload 1
84
+ areturn
85
+ }
86
+ end
87
+
88
+ def test_stack_ops
89
+ # TODO
90
+ end
91
+
92
+ def test_constants
93
+ assert_equal false, try(Java::boolean) {ldc false; ireturn}
94
+ assert_equal 1, try(Java::byte) {ldc 1; ireturn}
95
+ assert_equal 1, try(Java::short) {ldc 1; ireturn}
96
+ assert_equal 1, try(Java::char) {ldc 1; ireturn}
97
+ assert_equal 1, try(Java::int) {ldc 1; ireturn}
98
+ assert_equal 1, try(Java::long) {ldc_long 1; lreturn}
99
+ assert_equal 1.0, try(Java::float) {ldc_float 1.0; freturn}
100
+ assert_equal 1.0, try(Java::double) {ldc 1.0; dreturn}
101
+ assert_equal 'foo', try(JString) {ldc 'foo'; areturn}
102
+
103
+ assert_equal(-1, try(Java::int) {iconst_m1; ireturn})
104
+ assert_equal 0, try(Java::int) {iconst_0; ireturn}
105
+ assert_equal 1, try(Java::int) {iconst_1; ireturn}
106
+ assert_equal 2, try(Java::int) {iconst_2; ireturn}
107
+ assert_equal 3, try(Java::int) {iconst_3; ireturn}
108
+ assert_equal 4, try(Java::int) {iconst_4; ireturn}
109
+ assert_equal 5, try(Java::int) {iconst_5; ireturn}
110
+ assert_equal 0, try(Java::long) {lconst_0; lreturn}
111
+ assert_equal 1, try(Java::long) {lconst_1; lreturn}
112
+ assert_equal 0.0, try(Java::float) {fconst_0; freturn}
113
+ assert_equal 1.0, try(Java::float) {fconst_1; freturn}
114
+ assert_equal 2.0, try(Java::float) {fconst_2; freturn}
115
+ assert_equal 0.0, try(Java::double) {dconst_0; dreturn}
116
+ assert_equal 1.0, try(Java::double) {dconst_1; dreturn}
117
+ assert_equal nil, try(JString) {aconst_null; areturn}
118
+ end
119
+
120
+ def test_math
121
+ assert_equal 2, try(Java::int) {ldc 1; ldc 1; iadd; ireturn}
122
+ assert_equal 0, try(Java::int) {ldc 1; ldc 1; isub; ireturn}
123
+ assert_equal 4, try(Java::int) {ldc 2; ldc 2; imul; ireturn}
124
+ assert_equal 2, try(Java::int) {ldc 4; ldc 2; idiv; ireturn}
125
+ assert_equal 2, try(Java::int) {ldc 1; ldc 1; iadd; ireturn}
126
+ assert_equal 2, try(Java::int) {ldc 1; istore 0; iinc 0, 1; iload 0; ireturn}
127
+ assert_equal 0, try(Java::int) {ldc 1; istore 0; iinc 0, -1; iload 0; ireturn}
128
+ assert_equal 5, try(Java::int) {ldc 1; ldc 4; ior; ireturn}
129
+ assert_equal 5, try(Java::int) {ldc 7; ldc 13; iand; ireturn}
130
+ assert_equal 5, try(Java::int) {ldc 10; ldc 15; ixor; ireturn}
131
+ assert_equal(-5, try(Java::int) {ldc 5; ineg; ireturn})
132
+ assert_equal(2147483643, try(Java::int) {ldc(-10); ldc 1; iushr; ireturn})
133
+ assert_equal(-5, try(Java::int) {ldc(-10); ldc 1; ishr; ireturn})
134
+ assert_equal(8, try(Java::int) {ldc 4; ldc 1; ishl; ireturn})
135
+ assert_equal(3, try(Java::int) {ldc 15; ldc 4; irem; ireturn})
136
+
137
+ assert_equal 2, try(Java::long) {ldc_long 1; ldc_long 1; ladd; lreturn}
138
+ assert_equal 0, try(Java::long) {ldc_long 1; ldc_long 1; lsub; lreturn}
139
+ assert_equal 4, try(Java::long) {ldc_long 2; ldc_long 2; lmul; lreturn}
140
+ assert_equal 2, try(Java::long) {ldc_long 4; ldc_long 2; ldiv; lreturn}
141
+ assert_equal 5, try(Java::long) {ldc_long 1; ldc_long 4; lor; lreturn}
142
+ assert_equal 5, try(Java::long) {ldc_long 7; ldc_long 13; land; lreturn}
143
+ assert_equal 5, try(Java::long) {ldc_long 10; ldc_long 15; lxor; lreturn}
144
+ assert_equal(-5, try(Java::long) {ldc_long 5; lneg; lreturn})
145
+ assert_equal(9223372036854775803, try(Java::long) {ldc_long(-10); ldc 1; lushr; lreturn})
146
+ assert_equal(-5, try(Java::long) {ldc_long(-10); ldc 1; lshr; lreturn})
147
+ assert_equal(8, try(Java::long) {ldc_long 4; ldc 1; lshl; lreturn})
148
+ assert_equal(3, try(Java::long) {ldc_long 15; ldc_long 4; lrem; lreturn})
149
+
150
+ assert_equal 2.0, try(Java::float) {ldc_float 1; ldc_float 1; fadd; freturn}
151
+ assert_equal 0.0, try(Java::float) {ldc_float 1; ldc_float 1; fsub; freturn}
152
+ assert_equal 4.0, try(Java::float) {ldc_float 2; ldc_float 2; fmul; freturn}
153
+ assert_equal 2.0, try(Java::float) {ldc_float 4; ldc_float 2; fdiv; freturn}
154
+ assert_equal(-5.0, try(Java::float) {ldc_float 5; fneg; freturn})
155
+ assert_equal(3.0, try(Java::float) {ldc_float 15; ldc_float 4; frem; freturn})
156
+
157
+ assert_equal 2.0, try(Java::double) {ldc_double 1; ldc_double 1; dadd; dreturn}
158
+ assert_equal 0.0, try(Java::double) {ldc_double 1; ldc_double 1; dsub; dreturn}
159
+ assert_equal 4.0, try(Java::double) {ldc_double 2; ldc_double 2; dmul; dreturn}
160
+ assert_equal 2.0, try(Java::double) {ldc_double 4; ldc_double 2; ddiv; dreturn}
161
+ assert_equal(-5.0, try(Java::double) {ldc_double 5; dneg; dreturn})
162
+ assert_equal(3.0, try(Java::double) {ldc_double 15; ldc_double 4; drem; dreturn})
163
+ end
164
+
165
+ def test_trycatch
166
+ assert_equal 2, try(Java::int) {
167
+ label :begin
168
+ new java.lang.Exception
169
+ dup
170
+ invokespecial java.lang.Exception, '<init>', [void]
171
+ athrow
172
+ label :catch
173
+ ldc 2
174
+ ireturn
175
+ label :end
176
+ trycatch(:begin, :catch, :catch, java.lang.Exception)
177
+ }
178
+ end
179
+
180
+ def test_jumps
181
+ assert_equal 2, try(Java::int) {after = label; goto after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
182
+ assert_equal 2, try(Java::int) {after = label; ldc 0; ifeq after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
183
+ assert_equal 2, try(Java::int) {after = label; ldc 1; ifne after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
184
+ assert_equal 2, try(Java::int) {after = label; ldc -1; iflt after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
185
+ assert_equal 2, try(Java::int) {after = label; ldc 1; ifgt after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
186
+ assert_equal 2, try(Java::int) {after = label; aconst_null; ifnull after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
187
+ assert_equal 2, try(Java::int) {after = label; getstatic System, 'out', java.io.PrintStream; ifnonnull after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
188
+ assert_equal 2, try(Java::int) {after = label; aconst_null; aconst_null; if_acmpeq after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
189
+ assert_equal 2, try(Java::int) {after = label; aconst_null; getstatic System, 'out', java.io.PrintStream; if_acmpne after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
190
+ assert_equal 2, try(Java::int) {after = label; ldc 1; ldc 2; if_icmplt after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
191
+ assert_equal 2, try(Java::int) {after = label; ldc 1; ldc 1; if_icmple after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
192
+ assert_equal 2, try(Java::int) {after = label; ldc 2; ldc 1; if_icmpgt after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
193
+ assert_equal 2, try(Java::int) {after = label; ldc 2; ldc 2; if_icmpge after; ldc 1; ireturn; after.set!; ldc 2; ireturn}
194
+ # TODO: jsr and ret
195
+ end
196
+
197
+ def test_multianewaray
198
+ # TODO
199
+ end
200
+
201
+ def test_switches
202
+ assert_equal 3, try(Java::int) {
203
+ one, two, three, four, default = label, label, label, label, label
204
+ ldc 3
205
+ lookupswitch default, [1,2,3,4], [one, two, three, four]
206
+ one.set!; ldc 1; ireturn
207
+ two.set!; ldc 2; ireturn
208
+ three.set!; ldc 3; ireturn
209
+ four.set!; ldc 4; ireturn
210
+ default.set!; ldc 0; ireturn
211
+ }
212
+ assert_equal 3, try(Java::int) {
213
+ one, two, three, four, default = label, label, label, label, label
214
+ ldc 3
215
+ tableswitch 1, 4, default, [one, two, three, four]
216
+ one.set!; ldc 1; ireturn
217
+ two.set!; ldc 2; ireturn
218
+ three.set!; ldc 3; ireturn
219
+ four.set!; ldc 4; ireturn
220
+ default.set!; ldc 0; ireturn
221
+ }
222
+ end
223
+
224
+ def test_casts
225
+ assert_equal 1.0, try(Java::float) {ldc 1; i2f; freturn}
226
+ assert_equal 1, try(Java::int) {ldc_float 1.0; f2i; ireturn}
227
+
228
+ assert_equal 1.0, try(Java::double) {ldc 1; i2d; dreturn}
229
+ assert_equal 1, try(Java::int) {ldc 1.0; d2i; ireturn}
230
+
231
+ assert_equal -1, try(Java::int) {ldc_long java.lang.Long::MAX_VALUE; l2i; ireturn}
232
+ assert_equal 2147483648, try(Java::long) {ldc java.lang.Integer::MAX_VALUE; i2l; ldc_long 1; ladd; lreturn}
233
+
234
+ assert_equal 9.223372036854776e+18, try(Java::float) {ldc_long java.lang.Long::MAX_VALUE; l2f; freturn}
235
+ assert_equal -9223372036854775808, try(Java::long) {ldc_float java.lang.Float::MAX_VALUE; f2l; ldc_long 1; ladd; lreturn}
236
+
237
+ assert_equal 9.223372036854776e+18, try(Java::double) {ldc_long java.lang.Long::MAX_VALUE; l2d; dreturn}
238
+ assert_equal -9223372036854775808, try(Java::long) {ldc java.lang.Double::MAX_VALUE; d2l; ldc_long 1; ladd; lreturn}
239
+ end
240
+
241
+ def test_locals
242
+ assert_equal true, try(Java::boolean) {ldc true; istore 0; iload 0; ireturn}
243
+ assert_equal 1, try(Java::int) {ldc 1; istore 0; iload 0; ireturn}
244
+ assert_equal 1, try(Java::long) {ldc_long 1; lstore 0; lload 0; lreturn}
245
+ assert_equal 1.0, try(Java::float) {ldc_float 1.0; fstore 0; fload 0; freturn}
246
+ assert_equal 1.0, try(Java::double) {ldc_double 1.0; dstore 0; dload 0; dreturn}
247
+ assert_equal 'foo', try(JString) {ldc 'foo'; astore 0; aload 0; areturn}
248
+ end
249
+
250
+ def test_instance_method_this
251
+ cb = @builder.public_class(@class_name, @builder.object);
252
+ method = cb.public_method("foo", cb.this) {aload local 'this'; areturn}
253
+
254
+ # ensure "this" is taking slot zero
255
+ method.local('another')
256
+ assert_equal(method.local('this'), 0)
257
+ assert_equal(method.local('another'), 1)
258
+
259
+ dummy_constructor(cb)
260
+ obj = load_and_construct(@class_name, cb)
261
+
262
+ assert_equal(obj, obj.foo)
263
+ end
264
+
265
+ def test_constructor_this
266
+ cb = @builder.public_class(@class_name, @builder.object);
267
+ cb.private_field "self", cb.this
268
+ constructor = cb.public_constructor do
269
+ aload 0
270
+ dup
271
+ invokespecial object, "<init>", [void]
272
+ dup
273
+ putfield this, "self", this
274
+ returnvoid
275
+ end
276
+
277
+ cb.public_method "get_self", cb.this do
278
+ aload 0
279
+ getfield this, "self", this
280
+ areturn
281
+ end
282
+
283
+ # ensure "this" is taking slot zero
284
+ constructor.local('another')
285
+ assert_equal(constructor.local('this'), 0)
286
+ assert_equal(constructor.local('another'), 1)
287
+
288
+ obj = load_and_construct(@class_name, cb)
289
+ assert_equal(obj, obj.get_self)
290
+ end
291
+
292
+ def test_native_method
293
+ cb = @builder.public_class(@class_name, @builder.object);
294
+
295
+ body_called = false
296
+ cb.public_native_method("yoohoo") {body_called = true}
297
+
298
+ assert !body_called
299
+
300
+ dummy_constructor(cb)
301
+ obj = load_and_construct(@class_name, cb);
302
+
303
+ # expect NativeException (UnsatisfiedLinkError)
304
+ assert_raises(NativeException) {obj.yoohoo}
305
+ end
306
+
307
+ def test_fields
308
+ cb = @builder.public_class(@class_name, @builder.object);
309
+
310
+ cb.public_field('inst_field', JString)
311
+ cb.public_static_field('static_field', JString)
312
+
313
+ cb.public_method('set_inst', cb.void) {aload 0; ldc 'instance'; putfield this, 'inst_field', JString; returnvoid}
314
+ cb.public_method('set_static', cb.void) {ldc 'static'; putstatic this, 'static_field', JString; returnvoid}
315
+ cb.public_method('get_inst', JString) {aload 0; getfield this, 'inst_field', JString; areturn}
316
+ cb.public_method('get_static', JString) {getstatic this, 'static_field', JString; areturn}
317
+
318
+ dummy_constructor(cb)
319
+ obj = load_and_construct(@class_name, cb);
320
+
321
+ assert_equal nil, obj.get_inst
322
+ assert_equal nil, obj.get_static
323
+ obj.set_inst
324
+ obj.set_static
325
+ assert_equal 'instance', obj.get_inst
326
+ assert_equal 'static', obj.get_static
327
+ end
328
+
329
+ def test_arrays
330
+ cb = @builder.public_class(@class_name, @builder.object);
331
+
332
+ cb.public_method("newbooleanarray", cb.boolean[]) {ldc 5; newbooleanarray; dup; ldc 1; ldc true; bastore; dup; dup; ldc 2; swap; ldc 1; baload; bastore; areturn}
333
+ cb.public_method("newbytearray", cb.byte[]) {ldc 5; newbytearray; dup; ldc 1; ldc 1; bastore; dup; dup; ldc 2; swap; ldc 1; baload; bastore; areturn}
334
+ cb.public_method("newshortarray", cb.short[]) {ldc 5; newshortarray; dup; ldc 1; ldc 1; sastore; dup; dup; ldc 2; swap; ldc 1; saload; sastore; areturn}
335
+ cb.public_method("newchararray", cb.char[]) {ldc 5; newchararray; dup; ldc 1; ldc 1; castore; dup; dup; ldc 2; swap; ldc 1; caload; castore; areturn}
336
+ cb.public_method("newintarray", cb.int[]) {ldc 5; newintarray; dup; ldc 1; ldc 1; iastore; dup; dup; ldc 2; swap; ldc 1; iaload; iastore; areturn}
337
+ cb.public_method("newlongarray", cb.long[]) {ldc 5; newlongarray; dup; ldc 1; ldc_long 1; lastore; dup; dup; ldc 2; swap; ldc 1; laload; lastore; areturn}
338
+ cb.public_method("newfloatarray", cb.float[]) {ldc 5; newfloatarray; dup; ldc 1; ldc_float 1.0; fastore; dup; dup; ldc 2; swap; ldc 1; faload; fastore; areturn}
339
+ cb.public_method("newdoublearray", cb.double[]) {ldc 5; newdoublearray; dup; ldc 1; ldc 1.0; dastore; dup; dup; ldc 2; swap; ldc 1; daload; dastore; areturn}
340
+ cb.public_method("anewarray", cb.string[]) {ldc 5; anewarray JString; dup; ldc 1; ldc 'foo'; aastore; dup; dup; ldc 2; swap; ldc 1; aaload; aastore; areturn}
341
+
342
+ dummy_constructor(cb)
343
+ obj = load_and_construct(@class_name, cb);
344
+
345
+ ary = obj.newbooleanarray
346
+ assert_equal(Java::boolean.java_class, ary.class.java_class.component_type)
347
+ assert_equal(5, ary.size)
348
+ assert_equal([false,true,true,false,false], ary.to_a)
349
+
350
+ ary = obj.newbytearray
351
+ assert_equal(Java::byte.java_class, ary.class.java_class.component_type)
352
+ assert_equal(5, ary.size)
353
+ assert_equal([0,1,1,0,0], ary.to_a)
354
+
355
+ ary = obj.newshortarray
356
+ assert_equal(Java::short.java_class, ary.class.java_class.component_type)
357
+ assert_equal(5, ary.size)
358
+ assert_equal([0,1,1,0,0], ary.to_a)
359
+
360
+ ary = obj.newchararray
361
+ assert_equal(Java::char.java_class, ary.class.java_class.component_type)
362
+ assert_equal(5, ary.size)
363
+ assert_equal([0,1,1,0,0], ary.to_a)
364
+
365
+ ary = obj.newintarray
366
+ assert_equal(Java::int.java_class, ary.class.java_class.component_type)
367
+ assert_equal(5, ary.size)
368
+ assert_equal([0,1,1,0,0], ary.to_a)
369
+
370
+ ary = obj.newlongarray
371
+ assert_equal(Java::long.java_class, ary.class.java_class.component_type)
372
+ assert_equal(5, ary.size)
373
+ assert_equal([0,1,1,0,0], ary.to_a)
374
+
375
+ ary = obj.newfloatarray
376
+ assert_equal(Java::float.java_class, ary.class.java_class.component_type)
377
+ assert_equal(5, ary.size)
378
+ assert_equal([0.0,1.0,1.0,0.0,0.0], ary.to_a)
379
+
380
+ ary = obj.newdoublearray
381
+ assert_equal(Java::double.java_class, ary.class.java_class.component_type)
382
+ assert_equal(5, ary.size)
383
+ assert_equal([0.0,1.0,1.0,0.0,0.0], ary.to_a)
384
+
385
+ ary = obj.anewarray
386
+ assert_equal(java.lang.String.java_class, ary.class.java_class.component_type)
387
+ assert_equal(5, ary.size)
388
+ assert_equal([nil,'foo','foo',nil,nil], ary.to_a)
389
+
390
+ assert_equal 5, try(Java::int) {ldc 5; newintarray; arraylength; ireturn}
391
+ end
392
+
393
+ def test_static_init
394
+ cb = @builder.public_class(@class_name, @builder.object);
395
+
396
+ cb.public_static_field('static_field', JString)
397
+ cb.static_init {ldc "hello world"; putstatic this, "static_field", string; returnvoid}
398
+
399
+ dummy_constructor(cb)
400
+ obj = load_and_construct(@class_name, cb);
401
+
402
+ assert_equal("hello world", obj.class.static_field)
403
+ end
404
+
405
+ def test_annotation
406
+ cb = @builder.public_class(@class_name, @builder.object);
407
+
408
+ cb.public_method("annotated", cb.void) do
409
+ annotate(JRubyMethod, true) do |anno|
410
+ anno.name = ["foo"]
411
+ anno.required = 1
412
+ anno.optional = 1
413
+ anno.rest = true
414
+ anno.meta = true
415
+ anno.module = true
416
+ anno.frame = true
417
+ anno.scope = true
418
+ end
419
+ returnvoid
420
+ end
421
+
422
+ dummy_constructor(cb)
423
+ obj = load_and_construct(@class_name, cb);
424
+
425
+ method = obj.class.java_class.declared_method("annotated")
426
+ anno = method.annotation(JRubyMethod.java_class)
427
+ assert anno
428
+ end
429
+ end