rtype-native 0.2.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.
data/ext/rtype/rtype.c ADDED
@@ -0,0 +1,122 @@
1
+ #include "rtype.h"
2
+
3
+ VALUE rb_mRtype, rb_mRtypeBehavior, rb_cRtypeBehaviorBase, rb_eRtypeArgumentTypeError, rb_eRtypeTypeSignatureError, rb_eRtypeReturnTypeError;
4
+
5
+ VALUE
6
+ rb_rtype_valid(VALUE self, VALUE expected, VALUE value) {
7
+ switch(TYPE(expected)) {
8
+ case T_MODULE:
9
+ case T_CLASS:
10
+ return rb_obj_is_kind_of(value, expected) ? Qtrue : Qfalse;
11
+ case T_SYMBOL:
12
+ return rb_respond_to(value, rb_to_id(expected)) ? Qtrue : Qfalse;
13
+ case T_REGEXP:
14
+ return rb_reg_match( expected, rb_funcall(value, rb_intern("to_s"), 0) ) != Qnil ? Qtrue : Qfalse;
15
+ case T_ARRAY:
16
+ if( !RB_TYPE_P(value, T_ARRAY) ) {
17
+ return Qfalse;
18
+ }
19
+ else if( RARRAY_LEN(expected) != RARRAY_LEN(value) ) {
20
+ return Qfalse;
21
+ }
22
+ else {
23
+ // 'for' loop initial declarations are only allowed in c99 mode
24
+ long i;
25
+ for(i = 0; i < RARRAY_LEN(expected); i++) {
26
+ VALUE e = rb_ary_entry(expected, i);
27
+ VALUE v = rb_ary_entry(value, i);
28
+ VALUE valid = rb_rtype_valid(self, e, v);
29
+ if(valid == Qfalse) {
30
+ return Qfalse;
31
+ }
32
+ }
33
+ return Qtrue;
34
+ }
35
+ case T_TRUE:
36
+ return RTEST(value) ? Qtrue : Qfalse;
37
+ case T_FALSE:
38
+ return !RTEST(value) ? Qtrue : Qfalse;
39
+ default:
40
+ if(CLASS_OF(expected) == rb_cRange) {
41
+ return rb_funcall(expected, rb_intern("include?"), 1, value);
42
+ }
43
+ else if(CLASS_OF(expected) == rb_cProc) {
44
+ return RTEST(rb_funcall(expected, rb_intern("call"), 1, value)) ? Qtrue : Qfalse;
45
+ }
46
+ else if( RTEST(rb_obj_is_kind_of(expected, rb_cRtypeBehaviorBase)) ) {
47
+ return rb_funcall(expected, rb_intern("valid?"), 1, value);
48
+ }
49
+ else {
50
+ VALUE str = rb_any_to_s(expected);
51
+ rb_raise(rb_eRtypeTypeSignatureError, "Invalid type signature: Unknown type behavior %s", StringValueCStr(str));
52
+ return Qfalse;
53
+ }
54
+ }
55
+ }
56
+
57
+ VALUE
58
+ rb_rtype_assert_arguments_type(VALUE self, VALUE expected_args, VALUE args) {
59
+ // 'for' loop initial declarations are only allowed in c99 mode
60
+ long i;
61
+ for(i = 0; i < RARRAY_LEN(args); i++) {
62
+ VALUE e = rb_ary_entry(expected_args, i);
63
+ VALUE v = rb_ary_entry(args, i);
64
+ if(e != Qnil) {
65
+ if( !RTEST(rb_rtype_valid(self, e, v)) ) {
66
+ VALUE msg = rb_funcall(rb_mRtype, rb_intern("arg_type_error_message"), 3, LONG2FIX(i), e, v);
67
+ rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
68
+ }
69
+ }
70
+ }
71
+ return Qnil;
72
+ }
73
+
74
+ static int
75
+ kwargs_do_each(VALUE key, VALUE val, VALUE in) {
76
+ VALUE expected = rb_hash_aref(in, key);
77
+ if(expected != Qnil) {
78
+ if( !RTEST(rb_rtype_valid((VALUE) NULL, expected, val)) ) {
79
+ VALUE msg = rb_funcall(rb_mRtype, rb_intern("kwarg_type_error_message"), 3, key, expected, val);
80
+ rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
81
+ }
82
+ }
83
+ return ST_CONTINUE;
84
+ }
85
+
86
+ VALUE
87
+ rb_rtype_assert_arguments_type_with_keywords(VALUE self, VALUE expected_args, VALUE args, VALUE expected_kwargs, VALUE kwargs) {
88
+ rb_rtype_assert_arguments_type(self, expected_args, args);
89
+ rb_hash_foreach(kwargs, kwargs_do_each, expected_kwargs);
90
+ return Qnil;
91
+ }
92
+
93
+ VALUE
94
+ rb_rtype_assert_return_type(VALUE self, VALUE expected, VALUE result) {
95
+ if(expected == Qnil) {
96
+ if(result != Qnil) {
97
+ VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
98
+ rb_raise(rb_eRtypeReturnTypeError, "for return:\n %s", StringValueCStr(msg));
99
+ }
100
+ }
101
+ else {
102
+ if( !RTEST(rb_rtype_valid(self, expected, result)) ) {
103
+ VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
104
+ rb_raise(rb_eRtypeReturnTypeError, "for return:\n %s", StringValueCStr(msg));
105
+ }
106
+ }
107
+ return Qnil;
108
+ }
109
+
110
+ void Init_rtype_native(void) {
111
+ rb_mRtype = rb_define_module("Rtype");
112
+ rb_mRtypeBehavior = rb_define_module_under(rb_mRtype, "Behavior");
113
+ rb_cRtypeBehaviorBase = rb_define_class_under(rb_mRtypeBehavior, "Base", rb_cObject);
114
+ rb_eRtypeArgumentTypeError = rb_define_class_under(rb_mRtype, "ArgumentTypeError", rb_eArgError);
115
+ rb_eRtypeTypeSignatureError = rb_define_class_under(rb_mRtype, "TypeSignatureError", rb_eArgError);
116
+ rb_eRtypeReturnTypeError = rb_define_class_under(rb_mRtype, "ReturnTypeError", rb_eStandardError);
117
+
118
+ rb_define_singleton_method(rb_mRtype, "valid?", rb_rtype_valid, 2);
119
+ rb_define_singleton_method(rb_mRtype, "assert_arguments_type", rb_rtype_assert_arguments_type, 2);
120
+ rb_define_singleton_method(rb_mRtype, "assert_arguments_type_with_keywords", rb_rtype_assert_arguments_type_with_keywords, 4);
121
+ rb_define_singleton_method(rb_mRtype, "assert_return_type", rb_rtype_assert_return_type, 2);
122
+ }
data/ext/rtype/rtype.h ADDED
@@ -0,0 +1,5 @@
1
+ #ifndef RTYPE_H
2
+ #define RTYPE_H
3
+ #include "ruby.h"
4
+ #include <string.h>
5
+ #endif
@@ -0,0 +1,541 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Rtype do
4
+ let(:klass) do
5
+ Class.new do
6
+ attr_accessor :value
7
+
8
+ def initialize
9
+ @value = 123
10
+ end
11
+
12
+ def return_arg(obj)
13
+ obj
14
+ end
15
+
16
+ def three_args(a, b, c)
17
+ end
18
+
19
+ def three_kwargs(a:, b:, c:)
20
+ end
21
+
22
+ def return_nil(obj)
23
+ nil
24
+ end
25
+
26
+ def sum(a, b)
27
+ a + b
28
+ end
29
+
30
+ def kwarg(a:)
31
+ a
32
+ end
33
+
34
+ def sum_kwargs(a:, b:)
35
+ a + b
36
+ end
37
+
38
+ def arg_and_kwarg(a, b:)
39
+ end
40
+
41
+ def arg_and_kwargs(a, b:, c:)
42
+ end
43
+
44
+ def args_and_kwargs(a, b, c:, d:)
45
+ end
46
+
47
+ protected
48
+ def protected_func
49
+ end
50
+
51
+ private
52
+ def private_func
53
+ end
54
+ end
55
+ end
56
+
57
+ let(:instance) do
58
+ klass.new
59
+ end
60
+
61
+ describe 'Kernel#rtype' do
62
+ it "outside of module" do
63
+ rtype :test_args, [String] => Any
64
+ def test_args(str)
65
+ end
66
+
67
+ expect {test_args 123}.to raise_error Rtype::ArgumentTypeError
68
+
69
+ rtype :test_return, [] => String
70
+ def test_return
71
+ 369
72
+ end
73
+
74
+ expect {test_return}.to raise_error Rtype::ReturnTypeError
75
+ end
76
+
77
+ it "in module" do
78
+ class TestClass
79
+ rtype :test_args, [String] => Any
80
+ def test_args(str)
81
+ end
82
+ end
83
+
84
+ expect {TestClass.new.test_args 123}.to raise_error Rtype::ArgumentTypeError
85
+
86
+ class TestClass
87
+ rtype :test_return, [] => String
88
+ def test_return
89
+ 369
90
+ end
91
+ end
92
+
93
+ expect {TestClass.new.test_return}.to raise_error Rtype::ReturnTypeError
94
+ end
95
+ end
96
+
97
+ it "Kernel#rtype_self" do
98
+ class TestClass
99
+ rtype_self :static_test_args, [String] => Any
100
+ def self.static_test_args(str)
101
+ end
102
+ end
103
+
104
+ expect {TestClass::static_test_args 123}.to raise_error Rtype::ArgumentTypeError
105
+
106
+ class TestClass
107
+ rtype_self :static_test_return, [] => String
108
+ def self.static_test_return
109
+ 369
110
+ end
111
+ end
112
+
113
+ expect {TestClass::static_test_return}.to raise_error Rtype::ReturnTypeError
114
+ end
115
+
116
+ it 'Kernel#rtype_accessor' do
117
+ class TestClass
118
+ rtype_accessor :value, String
119
+ attr_accessor :value
120
+
121
+ def initialize
122
+ @value = 123
123
+ end
124
+ end
125
+ expect {TestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
126
+ expect {TestClass.new.value}.to raise_error Rtype::ReturnTypeError
127
+ end
128
+
129
+ it 'Kernel#rtype_accessor_self' do
130
+ class TestClass
131
+ @@val = 123
132
+
133
+ rtype_accessor_self :value, String
134
+ def self.value=(val)
135
+ @@val = val
136
+ end
137
+ def self.value
138
+ @@val
139
+ end
140
+ end
141
+ expect {TestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
142
+ expect {TestClass::value}.to raise_error Rtype::ReturnTypeError
143
+ end
144
+
145
+ describe 'Test type behaviors' do
146
+ describe 'Module' do
147
+ it "is right" do
148
+ klass.send :rtype, :return_arg, [String] => Any
149
+ instance.return_arg("This is a string!")
150
+ end
151
+ it "is wrong" do
152
+ klass.send :rtype, :return_arg, [String] => Any
153
+ expect {instance.return_arg(123)}.to raise_error Rtype::ArgumentTypeError
154
+ end
155
+ it "is wrong result" do
156
+ klass.send :rtype, :return_nil, [Any] => String
157
+ expect {instance.return_nil("This is a string!")}.to raise_error Rtype::ReturnTypeError
158
+ end
159
+ end
160
+
161
+ describe 'Symbol' do
162
+ it "is right" do
163
+ klass.send :rtype, :return_arg, [:to_i] => Any
164
+ instance.return_arg(123)
165
+ end
166
+ it "is wrong args" do
167
+ klass.send :rtype, :return_arg, [:to_i] => Any
168
+ expect {instance.return_arg(true)}.to raise_error Rtype::ArgumentTypeError
169
+ end
170
+ it "is wrong result" do
171
+ klass.send :rtype, :return_nil, [Any] => :odd?
172
+ expect {instance.return_nil(123)}.to raise_error Rtype::ReturnTypeError
173
+ end
174
+ end
175
+
176
+ describe 'Regexp' do
177
+ it "is right" do
178
+ klass.send :rtype, :return_arg, [/cuba/] => Any
179
+ instance.return_arg("cuba")
180
+ end
181
+ it "is wrong args" do
182
+ klass.send :rtype, :return_arg, [/cuba/] => Any
183
+ expect {instance.return_arg("brazil")}.to raise_error Rtype::ArgumentTypeError
184
+ end
185
+ it "is wrong result" do
186
+ klass.send :rtype, :return_nil, [Any] => /cuba/
187
+ expect {instance.return_nil("cuba")}.to raise_error Rtype::ReturnTypeError
188
+ end
189
+ end
190
+
191
+ describe 'Range' do
192
+ it "is right" do
193
+ klass.send :rtype, :return_arg, [1..10] => Any
194
+ instance.return_arg(5)
195
+ end
196
+ it "is wrong args" do
197
+ klass.send :rtype, :return_arg, [1..10] => Any
198
+ expect {instance.return_arg(1001)}.to raise_error Rtype::ArgumentTypeError
199
+ end
200
+ it "is wrong result" do
201
+ klass.send :rtype, :return_nil, [Any] => 1..10
202
+ expect {instance.return_nil(5)}.to raise_error Rtype::ReturnTypeError
203
+ end
204
+ end
205
+
206
+ describe 'Array' do
207
+ it "is right" do
208
+ klass.send :rtype, :return_arg, [[:to_i, :to_i]] => Any
209
+ instance.return_arg([123, 456])
210
+ end
211
+ it "is wrong args" do
212
+ klass.send :rtype, :return_arg, [[:to_i, :to_i]] => Any
213
+ expect {instance.return_arg([123, true])}.to raise_error Rtype::ArgumentTypeError
214
+ end
215
+ it "is wrong result" do
216
+ klass.send :rtype, :return_arg, [Any] => [:to_i, :to_i]
217
+ expect {instance.return_arg(true)}.to raise_error Rtype::ReturnTypeError
218
+ end
219
+ end
220
+
221
+ describe 'Proc' do
222
+ it "is right" do
223
+ klass.send :rtype, :return_arg, [->(arg){!arg.nil?}] => Any
224
+ instance.return_arg(123)
225
+ end
226
+ it "is wrong args" do
227
+ klass.send :rtype, :return_arg, [->(arg){!arg.nil?}] => Any
228
+ expect {instance.return_arg(nil)}.to raise_error Rtype::ArgumentTypeError
229
+ end
230
+ it "is wrong result" do
231
+ klass.send :rtype, :return_nil, [Any] => ->(arg){!arg.nil?}
232
+ expect {instance.return_nil(123)}.to raise_error Rtype::ReturnTypeError
233
+ end
234
+ end
235
+
236
+ describe 'true' do
237
+ it "is right" do
238
+ klass.send :rtype, :return_arg, [true] => Any
239
+ instance.return_arg(123)
240
+ end
241
+ it "is wrong args" do
242
+ klass.send :rtype, :return_arg, [true] => Any
243
+ expect {instance.return_arg(nil)}.to raise_error Rtype::ArgumentTypeError
244
+ end
245
+ it "is wrong result" do
246
+ klass.send :rtype, :return_nil, [Any] => true
247
+ expect {instance.return_nil(123)}.to raise_error Rtype::ReturnTypeError
248
+ end
249
+ end
250
+
251
+ describe 'false' do
252
+ it "is right" do
253
+ klass.send :rtype, :return_arg, [false] => Any
254
+ instance.return_arg(nil)
255
+ end
256
+ it "is wrong args" do
257
+ klass.send :rtype, :return_arg, [false] => Any
258
+ expect {instance.return_arg(123)}.to raise_error Rtype::ArgumentTypeError
259
+ end
260
+ it "is wrong result" do
261
+ klass.send :rtype, :return_arg, [Any] => false
262
+ expect {instance.return_arg(123)}.to raise_error Rtype::ReturnTypeError
263
+ end
264
+ end
265
+
266
+ describe 'nil' do
267
+ it "is only for return" do
268
+ klass.send :rtype, :return_nil, [] => nil
269
+ instance.return_nil(123)
270
+
271
+ klass.send :rtype, :return_arg, [] => nil
272
+ expect {instance.return_arg(123)}.to raise_error Rtype::ReturnTypeError
273
+ end
274
+ it "could not be used for args" do
275
+ expect {
276
+ klass.send :rtype, :return_arg, [nil] => Any
277
+ }.to raise_error Rtype::TypeSignatureError
278
+ end
279
+ end
280
+
281
+ describe 'Special type behaviors' do
282
+ it 'Rtype::Behavior::And' do
283
+ klass.send :rtype, :return_nil, [Rtype.and(:to_i, :chars)] => nil
284
+ instance.return_nil("Hello")
285
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
286
+ end
287
+
288
+ it 'Rtype::Behavior::Or' do
289
+ klass.send :rtype, :return_nil, [Rtype.or(Integer, String)] => nil
290
+ instance.return_nil(123)
291
+ instance.return_nil("abc")
292
+ expect {instance.return_nil(nil)}.to raise_error Rtype::ArgumentTypeError
293
+ end
294
+
295
+ it 'Rtype::Behavior::Nilable' do
296
+ klass.send :rtype, :return_nil, [Rtype.nilable(Integer)] => nil
297
+ instance.return_nil(nil)
298
+ instance.return_nil(123)
299
+ expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
300
+ end
301
+
302
+ it 'Rtype::Behavior::Not' do
303
+ klass.send :rtype, :return_nil, [Rtype.not(String)] => nil
304
+ instance.return_nil(123)
305
+ expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
306
+ end
307
+
308
+ it 'Rtype::Behavior::Xor' do
309
+ klass.send :rtype, :return_nil, [Rtype.xor(:to_i, String)] => nil
310
+ instance.return_nil(123)
311
+ expect {instance.return_nil("abc")}.to raise_error Rtype::ArgumentTypeError
312
+ end
313
+ end
314
+ end
315
+
316
+ describe 'Signature' do
317
+ describe 'check arguments' do
318
+ it 'nothing' do
319
+ klass.send :rtype, :sum, [] => Any
320
+ instance.sum(1, 2)
321
+ instance.sum(1, 2.0)
322
+ instance.sum(1.0, 2.0)
323
+ instance.sum("a", "b")
324
+ end
325
+
326
+ it 'two' do
327
+ klass.send :rtype, :sum, [Integer, Integer] => Any
328
+ expect {instance.sum(1, 2.0)}.to raise_error Rtype::ArgumentTypeError
329
+ end
330
+
331
+ it 'one keyword argument' do
332
+ klass.send :rtype, :kwarg, {a: Float} => Any
333
+ expect {instance.kwarg(a: 1)}.to raise_error Rtype::ArgumentTypeError
334
+ end
335
+
336
+ it 'two keyword argument' do
337
+ klass.send :rtype, :sum_kwargs, {a: Integer, b: Float} => Any
338
+ expect {instance.sum_kwargs(a: 1, b: 2)}.to raise_error Rtype::ArgumentTypeError
339
+ end
340
+
341
+ it 'one with one keyword argument' do
342
+ klass.send :rtype, :arg_and_kwarg, [Integer, {b: Float}] => Any
343
+ expect {instance.arg_and_kwarg(1, b: 2)}.to raise_error Rtype::ArgumentTypeError
344
+ end
345
+
346
+ it 'one with two keyword argument' do
347
+ klass.send :rtype, :arg_and_kwargs, [Integer, {c: String, d: String}] => Any
348
+ expect {instance.arg_and_kwargs(1, b: 2, c: 3)}.to raise_error Rtype::ArgumentTypeError
349
+ end
350
+
351
+ it 'two with two keyword argument' do
352
+ klass.send :rtype, :args_and_kwargs, [Integer, Integer, {c: String, d: String}] => Any
353
+ expect {instance.args_and_kwargs(1, 2, c: 3, d: 4)}.to raise_error Rtype::ArgumentTypeError
354
+ end
355
+
356
+ it 'string key could not be used for keyword argument' do
357
+ expect {
358
+ klass.send :rtype, :kwarg, {'a' => Float} => Any
359
+ }.to raise_error Rtype::TypeSignatureError
360
+ end
361
+
362
+ it 'only symbol key is used for keyword argument' do
363
+ klass.send :rtype, :kwarg, {:a => Float} => Any
364
+ expect {instance.kwarg(a: 1)}.to raise_error Rtype::ArgumentTypeError
365
+ expect {instance.kwarg(:a => 1)}.to raise_error Rtype::ArgumentTypeError
366
+ end
367
+ end
368
+
369
+ describe 'check return' do
370
+ it 'Any' do
371
+ klass.send :rtype, :return_arg, [] => Any
372
+ instance.return_arg("str")
373
+ end
374
+
375
+ it 'Array (tuple)' do
376
+ klass.send :rtype, :return_arg, [] => [Integer, Float]
377
+ expect {instance.return_arg([1, 2])}.to raise_error Rtype::ReturnTypeError
378
+ end
379
+ end
380
+
381
+ it 'check arguments and return value' do
382
+ klass.send :rtype, :return_nil, [Float] => nil
383
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
384
+ klass.send :rtype, :return_nil, [Integer] => Integer
385
+ expect {instance.return_nil(123)}.to raise_error Rtype::ReturnTypeError
386
+ end
387
+
388
+ describe 'wrong case' do
389
+ describe 'invalid signature form' do
390
+ it 'invalid argument signature' do
391
+ expect {
392
+ klass.send :rtype, :return_arg, Any => nil
393
+ }.to raise_error Rtype::TypeSignatureError
394
+ end
395
+ it 'invalid return signature' do
396
+ expect {
397
+ klass.send :rtype, :return_arg, [] => {}
398
+ }.to raise_error Rtype::TypeSignatureError
399
+ end
400
+
401
+ it 'invalid type behavior in arguments' do
402
+ expect {
403
+ klass.send :rtype, :sum_kwargs, [{a: Integer}, {b: Integer}] => Any
404
+ }.to raise_error Rtype::TypeSignatureError
405
+ expect {
406
+ klass.send :rtype, :return_arg, [123] => Any
407
+ }.to raise_error Rtype::TypeSignatureError
408
+ expect {
409
+ klass.send :rtype, :return_arg, ["abc"] => Any
410
+ }.to raise_error Rtype::TypeSignatureError
411
+ expect {
412
+ klass.send :rtype, :kwarg, {a: 123} => Any
413
+ }.to raise_error Rtype::TypeSignatureError
414
+ expect {
415
+ klass.send :rtype, :kwarg, {a: {b: Integer}} => Any
416
+ }.to raise_error Rtype::TypeSignatureError
417
+ expect {
418
+ klass.send :rtype, :kwarg, {Object.new => Integer} => Any
419
+ }.to raise_error Rtype::TypeSignatureError
420
+ end
421
+
422
+ it 'invalid type behavior in return' do
423
+ expect {
424
+ klass.send :rtype, :return_arg, [] => 123
425
+ }.to raise_error Rtype::TypeSignatureError
426
+ expect {
427
+ klass.send :rtype, :return_arg, [] => "abc"
428
+ }.to raise_error Rtype::TypeSignatureError
429
+ end
430
+ end
431
+ end
432
+ end
433
+
434
+ describe "Implementation" do
435
+ it 'can be called before method definition' do
436
+ class TestClass
437
+ rtype :method_def, [Integer] => Any
438
+ def method_def(i)
439
+ end
440
+ end
441
+ expect {
442
+ TestClass.new.method_def("abc")
443
+ }.to raise_error Rtype::ArgumentTypeError
444
+ end
445
+
446
+ it 'can be called after method definition' do
447
+ class TestClass
448
+ def method_def_2(i)
449
+ end
450
+ rtype :method_def_2, [Integer] => Any
451
+ end
452
+ expect {
453
+ TestClass.new.method_def_2("abc")
454
+ }.to raise_error Rtype::ArgumentTypeError
455
+ end
456
+
457
+ it 'method name can be both symbol and string' do
458
+ class TestClass
459
+ rtype 'method_def_3', [Integer] => Any
460
+ def method_def_3(i)
461
+ end
462
+ rtype :method_def_4, [Integer] => Any
463
+ def method_def_4(i)
464
+ end
465
+ end
466
+ expect {
467
+ TestClass.new.method_def_3("abc")
468
+ }.to raise_error Rtype::ArgumentTypeError
469
+ expect {
470
+ TestClass.new.method_def_4("abc")
471
+ }.to raise_error Rtype::ArgumentTypeError
472
+ end
473
+
474
+ describe 'method visibility works' do
475
+ it 'protected' do
476
+ expect {instance.protected_func}.to raise_error NoMethodError
477
+ end
478
+ it 'private' do
479
+ expect {instance.private_func}.to raise_error NoMethodError
480
+ end
481
+ end
482
+
483
+ context 'with empty argument signature' do
484
+ it 'accept any arguments' do
485
+ klass.send :rtype, :three_args, [] => Any
486
+ instance.three_args("abc", 123, 456)
487
+ end
488
+ end
489
+
490
+ context 'when args length is more than arg signature length' do
491
+ it 'type checking ignore rest args' do
492
+ klass.send :rtype, :three_args, [String] => Any
493
+ instance.three_args("abc", 123, 456)
494
+ end
495
+ end
496
+
497
+ context 'when keyword args contain a key not configured to rtype' do
498
+ it 'type checking ignore the key' do
499
+ klass.send :rtype, :three_kwargs, {a: String} => Any
500
+ instance.three_kwargs(a: "abc", b: 123, c: 456)
501
+ end
502
+ end
503
+ end
504
+
505
+ describe "Call Rtype`s static method directly" do
506
+ it 'Rtype::define_typed_method' do
507
+ Rtype::define_typed_method klass, :return_arg, [String] => Any
508
+ expect {instance.return_arg(123)}.to raise_error Rtype::ArgumentTypeError
509
+ end
510
+
511
+ it 'Rtype::define_typed_accessor' do
512
+ Rtype::define_typed_accessor klass, :value, String
513
+ expect { instance.value = 123 }.to raise_error Rtype::ArgumentTypeError
514
+ expect { instance.value }.to raise_error Rtype::ReturnTypeError
515
+ end
516
+
517
+ it 'Rtype::valid?' do
518
+ expect {
519
+ Rtype::valid?("Invalid type behavior", "Test Value")
520
+ }.to raise_error Rtype::TypeSignatureError
521
+ end
522
+
523
+ it 'Rtype::assert_arguments_type' do
524
+ expect {
525
+ Rtype::assert_arguments_type([Integer, String], [123, 123])
526
+ }.to raise_error Rtype::ArgumentTypeError
527
+ end
528
+
529
+ it 'Rtype::assert_arguments_type_with_keywords' do
530
+ expect {
531
+ Rtype::assert_arguments_type_with_keywords([Integer, String], [123, "abc"], {arg: String}, {arg: 123})
532
+ }.to raise_error Rtype::ArgumentTypeError
533
+ end
534
+
535
+ it 'Rtype::assert_return_type' do
536
+ expect {
537
+ Rtype::assert_return_type nil, "No nil"
538
+ }.to raise_error Rtype::ReturnTypeError
539
+ end
540
+ end
541
+ end
@@ -0,0 +1,5 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'rtype'
5
+ require 'rspec'