neuroncheck 0.1.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.
@@ -0,0 +1,3 @@
1
+ module Neuroncheck
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,125 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
2
+ require 'test/unit'
3
+ require 'neuroncheck'
4
+
5
+ # スクリプトエラーのチェック
6
+ class ScriptErrorTest < Test::Unit::TestCase
7
+ # 二重に定義することはできない
8
+ test 'double declaration' do
9
+ assert_raise(NeuronCheckSystem::DeclarationError) do
10
+ module Foo2
11
+ extend NeuronCheck
12
+
13
+ ndecl {
14
+ }
15
+
16
+ ndecl {
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # ndeclを複数回定義してもエラーにならないことと、1回しか呼ばれないことをチェック
24
+ class MultipleDeclareTest < Test::Unit::TestCase
25
+ def self.counter; @counter; end
26
+ def self.counter=(v); @counter = v; end
27
+ test "" do
28
+ cls = Class.new
29
+ MultipleDeclareTest.counter = 0
30
+
31
+ assert_nothing_raised(NeuronCheckSystem::DeclarationError){
32
+ cls.class_eval do
33
+ extend NeuronCheck
34
+
35
+ 3.times do
36
+ ndecl {
37
+ args String
38
+ }
39
+
40
+ def foo_method(arg)
41
+ MultipleDeclareTest.counter += 1
42
+ end
43
+ end
44
+ end
45
+ }
46
+
47
+ cls.new.foo_method('')
48
+ assert_equal(1, MultipleDeclareTest.counter)
49
+
50
+ assert_raise(NeuronCheckError){
51
+ cls.new.foo_method(1)
52
+ }
53
+ end
54
+ end
55
+
56
+ # もともとmethod_addedが定義されていたときに両方とも呼ばれるかどうかのチェック
57
+ class MethodAddedPreservedTest < Test::Unit::TestCase
58
+ test 'define method_added -> extend NeuronCheck' do
59
+ class Foo3
60
+ def self.original_method_added_called; @original_method_added_called; end
61
+ def self.method_added(name)
62
+ super
63
+ @original_method_added_called = true
64
+ end
65
+ extend NeuronCheck
66
+
67
+ ndecl {
68
+ args String
69
+ }
70
+ def foo3_method(arg1)
71
+ end
72
+ end
73
+
74
+ assert(Foo3.original_method_added_called)
75
+
76
+ assert_raise(NeuronCheckError) do
77
+ Foo3.new.foo3_method(nil)
78
+ end
79
+ end
80
+ end
81
+
82
+
83
+ # もともとsingleton_method_addedが定義されていたときに呼ばれるかどうかのチェック
84
+ class SingletonMethodAddedPreservedTest < Test::Unit::TestCase
85
+ test 'define method_added -> extend NeuronCheck' do
86
+ class Foo1
87
+ def self.original_singleton_method_added_called; @original_singleton_method_added_called; end
88
+ def self.original_singleton_method_added_called=(v); @original_singleton_method_added_called = v; end
89
+
90
+ def self.singleton_method_added(name)
91
+ @original_singleton_method_added_called = true
92
+ end
93
+
94
+ extend NeuronCheck
95
+
96
+ ndecl {
97
+ args String
98
+ }
99
+ def foo1_method(arg1)
100
+ end
101
+ end
102
+
103
+ Foo1.original_singleton_method_added_called = false
104
+ def Foo1.test1
105
+ p 1
106
+ end
107
+ assert{ Foo1.original_singleton_method_added_called }
108
+
109
+ assert_raise(NeuronCheckError) do
110
+ Foo1.new.foo1_method(nil)
111
+ end
112
+ end
113
+ end
114
+
115
+ # 複数回extendしても例外は発生しないか?
116
+ class MultipleExtendTest < Test::Unit::TestCase
117
+ test 'define method_added -> extend NeuronCheck' do
118
+ assert_nothing_raised do
119
+ module Foo3
120
+ extend NeuronCheck
121
+ extend NeuronCheck
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,153 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
2
+ require 'test/unit'
3
+ require 'neuroncheck'
4
+
5
+ # 継承時のチェック
6
+ class InheritanceTest < Test::Unit::TestCase
7
+ def setup
8
+ parent_cls = Class.new do
9
+ extend NeuronCheck
10
+
11
+ ndecl {
12
+ args /a/
13
+ returns /A/
14
+ }
15
+ def test1(name, ret)
16
+ ret
17
+ end
18
+
19
+ ndecl {
20
+ args /c/
21
+ returns /C/
22
+ }
23
+ def test2_only_parent(name, ret)
24
+ ret
25
+ end
26
+
27
+
28
+ ndecl {
29
+ precond do
30
+ assert{arg1 =~ /a/}
31
+ end
32
+
33
+ postcond do |ret|
34
+ assert{ret =~ /A/}
35
+ end
36
+ }
37
+ def cond_test1(arg1, ret1)
38
+ ret1
39
+ end
40
+
41
+ ndecl {
42
+ val String
43
+ }
44
+ attr_accessor :attr1
45
+ end
46
+
47
+ child_cls = Class.new(parent_cls) do
48
+ extend NeuronCheck
49
+
50
+ ndecl {
51
+ args /b/
52
+ returns /B/
53
+ }
54
+ def test1(name, ret = 'ABC')
55
+ super
56
+
57
+ ret
58
+ end
59
+
60
+ ndecl {
61
+ precond do
62
+ assert{ arg1 =~ /b/ }
63
+ end
64
+
65
+ postcond do |ret|
66
+ assert{ ret =~ /B/ }
67
+ end
68
+ }
69
+ def cond_test1(arg1, ret1 = 'ABC')
70
+ super
71
+
72
+ ret1
73
+ end
74
+ end
75
+
76
+ @parent_inst = parent_cls.new
77
+ @inst = child_cls.new
78
+ end
79
+
80
+ # 親の引数チェックを引き継ぐ
81
+ test 'arguments check inherited by superclass' do
82
+ assert_raise(NeuronCheckError){ @inst.test1(nil) }
83
+ assert_raise(NeuronCheckError){ @inst.test1('') }
84
+ assert_raise(NeuronCheckError){ @inst.test1('a123') }
85
+ assert_raise(NeuronCheckError){ @inst.test1('b123') }
86
+ assert_nothing_raised{ @inst.test1('a123b') }
87
+ end
88
+
89
+ # 親の引数チェックを引き継ぐ (子で再定義されていない場合)
90
+ test 'arguments check inherited by superclass (without child overridding)' do
91
+ assert_raise(NeuronCheckError){ @inst.test2_only_parent('c', 10) }
92
+ assert_raise(NeuronCheckError){ @inst.test2_only_parent('a', 'C') }
93
+ assert_nothing_raised{ @inst.test2_only_parent('c', 'C') }
94
+ end
95
+
96
+ # 親の戻り値チェックを引き継ぐ
97
+ test 'results check inherited by superclass' do
98
+ assert_raise(NeuronCheckError){ @inst.test1('ab', 'AC') }
99
+ assert_raise(NeuronCheckError){ @inst.test1('ab', 'BC') }
100
+ assert_nothing_raised{ @inst.test1('ab', 'aaABC') }
101
+ end
102
+ # 親の事前条件チェックを引き継ぐ
103
+ test 'precond check inherited by superclass' do
104
+ assert_raise(NeuronCheckError){ @inst.cond_test1(nil) }
105
+ assert_raise(NeuronCheckError){ @inst.cond_test1('') }
106
+ assert_raise(NeuronCheckError){ @inst.cond_test1('a123') }
107
+ assert_raise(NeuronCheckError){ @inst.cond_test1('b123') }
108
+ assert_nothing_raised{ @inst.cond_test1('a123b') }
109
+ end
110
+
111
+ # 親の事後条件チェックを引き継ぐ
112
+ test 'postcond check inherited by superclass' do
113
+ assert_raise(NeuronCheckError){ @inst.cond_test1('ab', 'AC') }
114
+ assert_raise(NeuronCheckError){ @inst.cond_test1('ab', 'BC') }
115
+ assert_nothing_raised{ @inst.cond_test1('ab', 'aaABC') }
116
+ end
117
+
118
+ # 親の属性チェックを引き継ぐ
119
+ test 'attribute check inherited by superclass' do
120
+ assert_raise(NeuronCheckError){ @inst.attr1 = 30 }
121
+ assert_nothing_raised{ @inst.attr1 = '1s' }
122
+ end
123
+ end
124
+
125
+ # 親と子でそれぞれ別々にextendした場合
126
+ class InheritanceOtherExtendTest < Test::Unit::TestCase
127
+
128
+ # 親のみextend
129
+ test 'extend only Parent' do
130
+ par_cls = Class.new do
131
+ extend NeuronCheck
132
+
133
+ ndecl {
134
+ args String
135
+ }
136
+ def foo_method(str1)
137
+ end
138
+ end
139
+
140
+ chd_cls = Class.new(par_cls) do
141
+ ndecl {
142
+ args String
143
+ }
144
+ def bar_method(str2)
145
+ end
146
+ end
147
+
148
+ chd = chd_cls.new
149
+ assert_raise(NeuronCheckError){ chd.foo_method(1) }
150
+ assert_raise(NeuronCheckError){ chd.bar_method(2) }
151
+ end
152
+
153
+ end
@@ -0,0 +1,943 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
2
+ require 'test/unit'
3
+ require 'neuroncheck'
4
+
5
+ class BasicArgumentTest < Test::Unit::TestCase
6
+ setup do
7
+ @cls = Class.new
8
+ @cls.class_eval do
9
+ extend NeuronCheck
10
+
11
+ ndecl {
12
+ args String
13
+ }
14
+ def single_string_method(arg1)
15
+ return ">" + arg1.to_s
16
+ end
17
+
18
+ ndecl {
19
+ args String, String, String
20
+ }
21
+ def multiple_string_method_invalid(arg1, arg2, arg3 = nil)
22
+ return ">#{arg1},#{arg2},#{arg3}"
23
+ end
24
+
25
+ ndecl {
26
+ args String, String, [String, nil]
27
+ }
28
+ def multiple_string_method(arg1, arg2, arg3 = nil)
29
+ return ">#{arg1},#{arg2},#{arg3}"
30
+ end
31
+
32
+ ndecl {
33
+ args String, String, [String, nil], String
34
+ }
35
+ def some_string_method(arg1, arg2, arg3 = nil, *rest)
36
+ return ">" + ([arg1, arg2, arg3] + rest).join(',')
37
+ end
38
+
39
+ ndecl {
40
+ args Numeric, String, [true, false], (0..1)
41
+ }
42
+ def kw_method(arg1_num, *arg2_str, flag: false, rate: 1.0, **kwrest)
43
+ end
44
+
45
+ end
46
+
47
+ @instance = @cls.new
48
+ end
49
+
50
+ test 'single String argument check is correct' do
51
+ assert_equal(">abc", @instance.single_string_method("abc"))
52
+ assert_equal(">", @instance.single_string_method(""))
53
+
54
+ unexpected_values = [nil, true, 1, -1, Array, :test]
55
+ expected_error_msg = %r|1st argument `arg1' of `#single_string_method' must be String|
56
+
57
+ unexpected_values.each do |v|
58
+ assert_raise_message(expected_error_msg) { @instance.single_string_method(v) }
59
+ end
60
+ end
61
+
62
+ test 'multiple String arguments check is correct - basic valid' do
63
+ assert_equal(">a,b,c", @instance.multiple_string_method("a", "b", "c"))
64
+ end
65
+
66
+ test 'multiple String arguments check is correct - basic invalid' do
67
+ unexpected_values = [[nil, "", "", "1st"], ["", nil, "", "2nd"], [nil, nil, nil, "1st"]]
68
+ unexpected_values.each do |v1, v2, v3, ord|
69
+ expected_error_msg = %r|#{ord} argument `.+?' of `#multiple_string_method' must be String|
70
+ assert_raise_message(expected_error_msg) { @instance.multiple_string_method(v1, v2, v3) }
71
+ end
72
+ end
73
+
74
+ test 'multiple String arguments check is correct - omitted parameter check NOT skipped' do
75
+ expected_error_msg = %r|3rd argument `.+?' of `#multiple_string_method_invalid' must be String|
76
+ assert_raise_message(expected_error_msg) { @instance.multiple_string_method_invalid("", "") }
77
+ assert_equal('>,,', @instance.multiple_string_method("", ""))
78
+ end
79
+
80
+ test 'some number String arguments check is correct' do
81
+ expected_value = {["a", "b", "c"] => ">a,b,c", ["a", "b"] => ">a,b,", ["a", "b", "c", "d", "e"] => ">a,b,c,d,e"}
82
+ expected_value.each do |params, expected_res|
83
+ assert_nothing_raised { @instance.some_string_method(*params) }
84
+ assert_equal(expected_res, @instance.some_string_method(*params))
85
+ end
86
+ end
87
+
88
+ unexpected_values = {
89
+ [nil, "", ""] => "1st",
90
+ ["", "", "", nil] => "4th",
91
+ ["", "", "", "", "", nil] => "6th",
92
+ }
93
+ unexpected_values.each_pair do |params, error_ord|
94
+ test "some number String arguments check raises - #{params.inspect} => #{error_ord} argument raises " do
95
+ expected_error_msg = %r|#{error_ord} argument `.+?' of `#some_string_method' must be String|
96
+ assert_raise_message(expected_error_msg) { @instance.some_string_method(*params) }
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ # 戻り値のテスト
103
+ class ReturnValueTest < Test::Unit::TestCase
104
+
105
+ test 'basic return value' do
106
+ cls = Class.new
107
+ cls.class_eval do
108
+ extend NeuronCheck
109
+
110
+ ndecl {
111
+ returns String
112
+ }
113
+ def valid_method
114
+ return 'ABC'
115
+ end
116
+
117
+ ndecl {
118
+ returns String
119
+ }
120
+ def invalid_method
121
+ return nil
122
+ end
123
+ end
124
+
125
+ instance = cls.new
126
+ assert_nothing_raised{ instance.valid_method }
127
+ assert_raise(NeuronCheckError){ instance.invalid_method }
128
+ end
129
+
130
+ test 'returns self' do
131
+ cls = Class.new
132
+ cls.class_eval do
133
+ extend NeuronCheck
134
+
135
+ ndecl {
136
+ returns :self
137
+ }
138
+ def valid_method
139
+ return self
140
+ end
141
+
142
+ ndecl {
143
+ returns :self
144
+ }
145
+ def invalid_method
146
+ return nil
147
+ end
148
+ end
149
+
150
+ instance = cls.new
151
+ assert_nothing_raised{ instance.valid_method }
152
+ assert_raise(NeuronCheckError){ instance.invalid_method }
153
+ end
154
+ end
155
+
156
+ # 可変長引数とキーワード引数の混在パターン
157
+ class ComplexArgumentTest < Test::Unit::TestCase
158
+ setup do
159
+ @cls = Class.new
160
+ @cls.class_eval do
161
+ extend NeuronCheck
162
+
163
+ ndecl {
164
+ args Numeric, [String, nil], String, [true, false], (0..1), String
165
+ }
166
+ def kw_method(arg1_num, arg2_optional_str = nil, *arg3_str, flag: false, rate: 1.0, **kwrest)
167
+ end
168
+
169
+ end
170
+
171
+ @instance = @cls.new
172
+ end
173
+
174
+ test "complex argument valid pattern" do
175
+ assert_nothing_raised{ @instance.kw_method(100) }
176
+ assert_nothing_raised{ @instance.kw_method(100, "A", "B") }
177
+ assert_nothing_raised{ @instance.kw_method(100, "A", "B", flag: true) }
178
+ assert_nothing_raised{ @instance.kw_method(100, "A", "B", rate: 0.7) }
179
+ assert_nothing_raised{ @instance.kw_method(100, "A", "B", some_arg: "some") }
180
+ assert_nothing_raised{ @instance.kw_method(100, "A", flag: true) }
181
+ assert_nothing_raised{ @instance.kw_method(100, flag: true) }
182
+ end
183
+
184
+ patterns = []
185
+ patterns << ["1st argument `arg1_num'", "Numeric", [""], {}]
186
+ patterns << ["2nd argument `arg2_optional_str'", "String or nil", [20, 0], {}]
187
+ patterns << ["6th argument `arg3_str'", "String", [20, "op", "A", "B", "C", nil], {}]
188
+ patterns << ["argument `flag'", "true or false", [20, "op", "A", "B", "C"], {flag: nil}]
189
+ patterns << ["argument `kwrest'", "String", [20, "op", "A", "B", "C"], {flag: true, some_arg1: '', some_arg2: 100}]
190
+
191
+ patterns.each do |expected_arg_context, expected, args, kwargs|
192
+ test "complex argument invalid pattern (args=#{args.inspect}, kwargs=#{kwargs.inspect})" do
193
+ expected_error_msg = %r|#{expected_arg_context} of `#kw_method' must be #{expected}|
194
+ assert_raise_message(expected_error_msg){
195
+ @instance.kw_method(*args, **kwargs)
196
+ }
197
+ end
198
+ end
199
+ end
200
+
201
+ # ブロック引数パターン
202
+ class BlockArgPattern < Test::Unit::TestCase
203
+ setup do
204
+ @cls = Class.new do
205
+ extend NeuronCheck
206
+
207
+ ndecl {
208
+ args any
209
+ }
210
+ def method_arg0(&block)
211
+ end
212
+
213
+ ndecl {
214
+ args String, any
215
+ }
216
+ def method_arg1(val1, &block)
217
+ end
218
+
219
+ ndecl {
220
+ args String
221
+ }
222
+ def method_arg1_without_block_decl(val1, &block)
223
+ end
224
+
225
+ ndecl {
226
+ args String, block
227
+ }
228
+ def method_arg1_with_block_type(val1, &block)
229
+ end
230
+ end
231
+
232
+ @instance = @cls.new
233
+ end
234
+
235
+ test "block arg check is corrent" do
236
+ assert_nothing_raised{ @instance.method_arg0 }
237
+ assert_nothing_raised{ @instance.method_arg0{ 1 } }
238
+ assert_nothing_raised{ @instance.method_arg1('') }
239
+ assert_nothing_raised{ @instance.method_arg1(''){ 1 } }
240
+ assert_nothing_raised{ @instance.method_arg1_without_block_decl('') }
241
+ assert_nothing_raised{ @instance.method_arg1_without_block_decl(''){ 1 } }
242
+ assert_nothing_raised{ @instance.method_arg1_with_block_type('') }
243
+ assert_nothing_raised{ @instance.method_arg1_with_block_type(''){ 1 } }
244
+ end
245
+
246
+ test "block arg invalid declarations" do
247
+ assert_raise_message(/`block' of `#method_arg0' is block argument/) do
248
+ Class.new do
249
+ extend NeuronCheck
250
+
251
+ ndecl {
252
+ args String
253
+ }
254
+ def method_arg0(&block)
255
+ end
256
+ end
257
+ end
258
+
259
+ assert_raise_message(/`block' of `#method_arg0' is block argument/) do
260
+ Class.new do
261
+ extend NeuronCheck
262
+
263
+ ndecl {
264
+ args String, String
265
+ }
266
+ def method_arg0(v1, &block)
267
+ end
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+
274
+ # 属性パターン
275
+ class AttrTest < Test::Unit::TestCase
276
+ setup do
277
+ @cls = Class.new do
278
+ extend NeuronCheck
279
+
280
+ ndecl {
281
+ val String
282
+ }
283
+ attr_accessor :name1, :name2
284
+
285
+ end
286
+
287
+ @instance = @cls.new
288
+ end
289
+
290
+ test "name is settable only String" do
291
+ assert_nothing_raised{ @instance.name1 = '' }
292
+ assert_nothing_raised{ @instance.name2 = '' }
293
+ assert_raise_message(/value of attribute `#name1' must be String/){ @instance.name1 = 11 }
294
+ assert_raise_message(/value of attribute `#name2' must be String/){ @instance.name2 = 11 }
295
+ end
296
+
297
+ test "checked to get attribute" do
298
+ assert_raise_message(/value of attribute `#name1' must be String/){ @instance.name1 }
299
+ assert_raise_message(/value of attribute `#name2' must be String/){ @instance.name2 }
300
+ @instance.name1 = ''
301
+ @instance.name2 = ''
302
+ assert_nothing_raised{ @instance.name1 }
303
+ assert_nothing_raised{ @instance.name2 }
304
+ end
305
+ end
306
+
307
+ # 属性パターン+モジュール
308
+ class AttrModTest < Test::Unit::TestCase
309
+ setup do
310
+ module AttrModTest_Mod
311
+ extend NeuronCheck
312
+
313
+ ndecl {
314
+ val String
315
+ }
316
+ attr_accessor :name1, :name2
317
+ end
318
+
319
+ class AttrModTest_Class
320
+ include AttrModTest_Mod
321
+ end
322
+
323
+ @instance = AttrModTest_Class.new
324
+ end
325
+
326
+ test "module attribute is included" do
327
+ assert_nothing_raised{ @instance.name1 = '' }
328
+ assert_nothing_raised{ @instance.name2 = '' }
329
+ assert_raise_message(/value of attribute `\S*#name1' must be String/){ @instance.name1 = 11 }
330
+ assert_raise_message(/value of attribute `\S*#name2' must be String/){ @instance.name2 = 11 }
331
+ end
332
+ end
333
+
334
+
335
+
336
+ # 各種特殊マッチャのテスト
337
+ class AdvancedMatcherTest < Test::Unit::TestCase
338
+ test "respondable matcher" do
339
+ cls = Class.new
340
+ cls.class_eval do
341
+ extend NeuronCheck
342
+
343
+ ndecl {
344
+ args respondable(:each)
345
+ }
346
+ def test_method(arg1)
347
+ end
348
+ end
349
+
350
+ inst = cls.new
351
+
352
+ assert_nothing_raised(){ inst.test_method([]) }
353
+ assert_raise_message(%r|must be any value except nil|){ inst.test_method(1) }
354
+ end
355
+
356
+ test "except matcher" do
357
+ cls = Class.new
358
+ cls.class_eval do
359
+ extend NeuronCheck
360
+
361
+ ndecl {
362
+ args except(nil)
363
+ }
364
+ def test_method(arg1)
365
+ end
366
+ end
367
+
368
+ inst = cls.new
369
+
370
+ assert_nothing_raised(){ inst.test_method([]) }
371
+ assert_nothing_raised(){ inst.test_method(1) }
372
+ assert_raise_message(%r|must be any value except nil|){ inst.test_method(nil) }
373
+ end
374
+
375
+ test "array_of matcher" do
376
+ cls = Class.new
377
+ cls.class_eval do
378
+ extend NeuronCheck
379
+
380
+ ndecl {
381
+ args array_of(String)
382
+ }
383
+ def test_method(arg1)
384
+ end
385
+ end
386
+
387
+ inst = cls.new
388
+
389
+ assert_nothing_raised(){ inst.test_method([]) }
390
+ assert_nothing_raised(){ inst.test_method(['1', '2', '5']) }
391
+ assert_raise_message(%r|must be array of String|){ inst.test_method(['1', '2', 3]) }
392
+ assert_raise_message(%r|must be array of String|){ inst.test_method(['1', '2', nil]) }
393
+ end
394
+
395
+ test "hash_of matcher" do
396
+ cls = Class.new
397
+ cls.class_eval do
398
+ extend NeuronCheck
399
+
400
+ ndecl {
401
+ args hash_of(String, Integer)
402
+ }
403
+ def test_method(arg1)
404
+ end
405
+ end
406
+
407
+ inst = cls.new
408
+
409
+ assert_nothing_raised(){ inst.test_method('A' => 1) }
410
+ assert_nothing_raised(){ inst.test_method({}) }
411
+ assert_raise_message(%r|must be hash that has keys of String and values of Integer|){ inst.test_method(2 => 1) }
412
+ assert_raise_message(%r|must be hash that has keys of String and values of Integer|){ inst.test_method(2 => 'V') }
413
+ assert_raise_message(%r|must be hash that has keys of String and values of Integer|){ inst.test_method('a') }
414
+ assert_raise_message(%r|must be hash that has keys of String and values of Integer|){ inst.test_method(nil) }
415
+ end
416
+
417
+ test "Range matcher" do
418
+ cls = Class.new
419
+ cls.class_eval do
420
+ extend NeuronCheck
421
+
422
+ ndecl {
423
+ args 1..100
424
+ }
425
+ def test_method(arg1)
426
+ end
427
+ end
428
+
429
+ inst = cls.new
430
+
431
+ assert_nothing_raised(){ inst.test_method(1) }
432
+ assert_nothing_raised(){ inst.test_method(100) }
433
+ assert_raise_message(%r|must be included in 1\.\.100|){ inst.test_method(0) }
434
+ assert_raise_message(%r|must be included in 1\.\.100|){ inst.test_method(101) }
435
+ assert_raise_message(%r|must be included in 1\.\.100|){ inst.test_method('') }
436
+ end
437
+
438
+ test "Regexp matcher" do
439
+ cls = Class.new
440
+ cls.class_eval do
441
+ extend NeuronCheck
442
+
443
+ ndecl {
444
+ args /[a]+/
445
+ }
446
+ def test_method(arg1)
447
+ end
448
+ end
449
+
450
+ inst = cls.new
451
+
452
+ assert_nothing_raised(){ inst.test_method('baac') }
453
+ assert_nothing_raised(){ inst.test_method('a') }
454
+ assert_raise_message(%r|must be String that matches with /\[a\]\+/|){ inst.test_method('d') }
455
+ assert_raise_message(%r|must be String that matches with /\[a\]\+/|){ inst.test_method('') }
456
+ end
457
+
458
+ test "Any matcher" do
459
+ cls = Class.new
460
+ cls.class_eval do
461
+ extend NeuronCheck
462
+
463
+ ndecl {
464
+ args any
465
+ }
466
+ def test_method(arg1)
467
+ end
468
+ end
469
+
470
+ inst = cls.new
471
+
472
+ assert_nothing_raised(){ inst.test_method('baac') }
473
+ assert_nothing_raised(){ inst.test_method('a') }
474
+ assert_nothing_raised(){ inst.test_method(1) }
475
+ assert_nothing_raised(){ inst.test_method(nil) }
476
+ end
477
+ end
478
+
479
+ # initializeに対する定義のテスト
480
+ class InitializeDeclarationTest < Test::Unit::TestCase
481
+ test "initialize declare" do
482
+ cls = Class.new
483
+ cls.class_eval do
484
+ extend NeuronCheck
485
+
486
+ ndecl {
487
+ args String
488
+ }
489
+ def initialize(arg1 = '')
490
+ end
491
+ end
492
+
493
+ assert_nothing_raised(){ cls.new() }
494
+ assert_nothing_raised(){ cls.new('a') }
495
+ assert_raise_message(%r|1st argument `arg1' of `#initialize' must be String|){ cls.new(3) }
496
+ end
497
+
498
+ test "returns cannot be used in initialize declaration" do
499
+ assert_raise(NeuronCheckSystem::DeclarationError) do
500
+ cls = Class.new
501
+ cls.class_eval do
502
+ extend NeuronCheck
503
+
504
+ ndecl {
505
+ returns String
506
+ }
507
+ def initialize(arg1)
508
+ end
509
+ end
510
+ end
511
+ end
512
+ end
513
+
514
+ # 無効化テスト
515
+ class DisableTest < Test::Unit::TestCase
516
+ def setup
517
+ @cls = Class.new
518
+ @cls.class_eval do
519
+ extend NeuronCheck
520
+ ndecl{
521
+ args String
522
+ }
523
+ def foo_method(arg1)
524
+ end
525
+ end
526
+
527
+ NeuronCheck.disable
528
+ @instance = @cls.new
529
+ end
530
+
531
+ def teardown
532
+ NeuronCheck.enable
533
+ end
534
+
535
+ test "enabled NeuronCheck raises nothing" do
536
+ NeuronCheck.enable
537
+ assert_raise(NeuronCheckError) do
538
+ @instance.foo_method(:invalid)
539
+ end
540
+ end
541
+ test "disabled NeuronCheck raises nothing" do
542
+ assert_nothing_raised do
543
+ @instance.foo_method(:invalid)
544
+ end
545
+ end
546
+ end
547
+
548
+ # 簡易宣言のテスト
549
+ # class ShortDeclarationTest < Test::Unit::TestCase
550
+ # test "short decl - args only" do
551
+ # cls = Class.new
552
+ # cls.class_eval do
553
+ # extend NeuronCheck
554
+ #
555
+ # ndecl String, String
556
+ # def test_method(arg1, arg2 = '')
557
+ # end
558
+ # end
559
+ #
560
+ # inst = cls.new
561
+ #
562
+ # assert_nothing_raised(){ inst.test_method('baac') }
563
+ # assert_nothing_raised(){ inst.test_method('a', '42') }
564
+ # assert_raise(NeuronCheckError){ inst.test_method('a', 1) }
565
+ # end
566
+ #
567
+ # test "short decl - args and returns" do
568
+ # cls = Class.new
569
+ # cls.class_eval do
570
+ # extend NeuronCheck
571
+ #
572
+ # ndecl String, String => /a/
573
+ # def test_method(arg1, arg2 = '')
574
+ # return arg1
575
+ # end
576
+ # end
577
+ #
578
+ # inst = cls.new
579
+ #
580
+ # assert_nothing_raised(){ inst.test_method('baac') }
581
+ # assert_nothing_raised(){ inst.test_method('a', '42') }
582
+ # assert_raise(NeuronCheckError){ inst.test_method('a', 1) }
583
+ # assert_raise(NeuronCheckError){ inst.test_method('b', 'a') }
584
+ # end
585
+ # end
586
+
587
+ # モジュールへの定義のテスト
588
+ class ModuleTest < Test::Unit::TestCase
589
+ test 'module instance method' do
590
+ module ModuleTest_Mod1
591
+ extend NeuronCheck
592
+
593
+ # インスタンスメソッド
594
+ ndecl {
595
+ args String
596
+ }
597
+ def test_method(name)
598
+ end
599
+ end
600
+
601
+ class ModuleTest_Class1
602
+ include ModuleTest_Mod1
603
+ end
604
+
605
+ instance = ModuleTest_Class1.new
606
+ assert_nothing_raised{ instance.test_method('') }
607
+ assert_raise_message(/ModuleTest_Mod1#test_method'/){ instance.test_method(1) }
608
+ end
609
+
610
+ test 'module function' do
611
+ module ModuleTest_ModuleFunction_Mod
612
+ extend NeuronCheck
613
+
614
+ # モジュール関数
615
+ module_function
616
+ ndecl {
617
+ args String
618
+ }
619
+ def test_func(name)
620
+ end
621
+ end
622
+
623
+ class ModuleTest_ModuleFunction_Class
624
+ include ModuleTest_ModuleFunction_Mod
625
+ end
626
+
627
+ instance = ModuleTest_ModuleFunction_Class.new
628
+ assert_nothing_raised{ ModuleTest_ModuleFunction_Mod.test_func('') }
629
+ assert_raise_message(/ModuleTest_ModuleFunction_Mod#test_func'/){ ModuleTest_ModuleFunction_Mod.test_func(1) }
630
+ assert_nothing_raised{ instance.instance_eval{ test_func('') } }
631
+ assert_raise_message(/ModuleTest_ModuleFunction_Mod#test_func'/){ instance.instance_eval{ test_func(1) } }
632
+ end
633
+ end
634
+
635
+ # 特異メソッドのテスト
636
+ class SingletonTest < Test::Unit::TestCase
637
+ test 'singleton method checkable with instance method' do
638
+ class SingletonTestClass1
639
+ extend NeuronCheck
640
+
641
+ # 特異メソッド
642
+ ndecl {
643
+ args Numeric
644
+ }
645
+ def self.test_method(threshold)
646
+ end
647
+
648
+ # 同名のインスタンスメソッド
649
+ ndecl {
650
+ args String
651
+ }
652
+ def test_method(name)
653
+ end
654
+ end
655
+
656
+ assert_nothing_raised{ SingletonTestClass1.test_method(1) }
657
+ assert_raise_message(/SingletonTestClass1\.test_method'/){ SingletonTestClass1.test_method('') }
658
+
659
+ instance = SingletonTestClass1.new
660
+ assert_nothing_raised{ instance.test_method('') }
661
+ assert_raise_message(/SingletonTestClass1#test_method'/){ instance.test_method(1) }
662
+ end
663
+ end
664
+
665
+ # エイリアスのテスト
666
+ class AliasTest < Test::Unit::TestCase
667
+ test 'aliasing will copy method body and NeuronCheck declaration' do
668
+ cls = Class.new do
669
+ extend NeuronCheck
670
+
671
+ ndecl {
672
+ args Numeric
673
+ }
674
+ def test_method1(threshold)
675
+ end
676
+
677
+ alias test_method2 test_method1
678
+ alias test_method3 test_method1
679
+ end
680
+
681
+ instance = cls.new
682
+ assert_nothing_raised{ instance.test_method1(1) }
683
+ assert_raise(NeuronCheckError){ instance.test_method1('') }
684
+ assert_nothing_raised{ instance.test_method2(1) }
685
+ assert_raise(NeuronCheckError){ instance.test_method2('') }
686
+ assert_nothing_raised{ instance.test_method3(1) }
687
+ assert_raise(NeuronCheckError){ instance.test_method3('') }
688
+ end
689
+ end
690
+
691
+ # 事前条件、事後条件のテスト
692
+ class PrePostCondTest < Test::Unit::TestCase
693
+ test 'argument precond' do
694
+ cls = Class.new
695
+ cls.class_eval do
696
+ extend NeuronCheck
697
+
698
+ ndecl {
699
+ args Numeric
700
+ precond do
701
+ assert{ threshold >= 0 }
702
+ end
703
+ }
704
+ def cond_method(threshold = 0)
705
+ end
706
+ end
707
+
708
+ instance = cls.new
709
+ assert_nothing_raised{ instance.cond_method }
710
+ assert_raise(NeuronCheckError){ instance.cond_method(-1.2) }
711
+ end
712
+
713
+ test 'instance variable precond' do
714
+ cls = Class.new
715
+ cls.class_eval do
716
+ extend NeuronCheck
717
+ attr_accessor :counter
718
+
719
+
720
+ def initialize
721
+ @counter = 0
722
+ end
723
+
724
+ ndecl {
725
+ precond do
726
+ assert{ @counter >= 1 }
727
+ end
728
+ }
729
+ def cond_method
730
+ end
731
+
732
+ def counter_increment
733
+ @counter += 1
734
+ end
735
+ end
736
+
737
+ instance = cls.new
738
+
739
+ # チェックエラー
740
+ assert_raise(NeuronCheckError){ instance.cond_method }
741
+
742
+ # 正常
743
+ instance.counter_increment
744
+ assert_nothing_raised{ instance.cond_method }
745
+ end
746
+
747
+ test 'result postcond' do
748
+ cls = Class.new
749
+ cls.class_eval do
750
+ extend NeuronCheck
751
+
752
+ ndecl {
753
+ postcond do |ret|
754
+ assert{ ret.kind_of?(String) }
755
+ end
756
+ }
757
+ def postcond_method(arg1)
758
+ return arg1
759
+ end
760
+ end
761
+
762
+ instance = cls.new
763
+ assert_nothing_raised{ instance.postcond_method('') }
764
+ assert_raise(NeuronCheckError){ instance.postcond_method(-1.2) }
765
+ end
766
+
767
+ test 'instance variable postcond' do
768
+ cls = Class.new
769
+ cls.class_eval do
770
+ extend NeuronCheck
771
+ attr_accessor :counter
772
+
773
+
774
+ def initialize
775
+ @counter = 0
776
+ end
777
+
778
+ ndecl {
779
+ postcond do |ret|
780
+ # 2回目の実行の後であれば通るメソッド
781
+ assert{ @counter >= 2 }
782
+ end
783
+ }
784
+ def counter_increment
785
+ @counter += 1
786
+ end
787
+ end
788
+
789
+ instance = cls.new
790
+
791
+ # チェックエラー (1回目)
792
+ assert_raise(NeuronCheckError){ instance.counter_increment }
793
+
794
+ # 正常
795
+ assert_nothing_raised{ instance.counter_increment }
796
+ end
797
+
798
+ test 'instance method call forbidden in precond' do
799
+ cls = Class.new do
800
+ extend NeuronCheck
801
+
802
+ ndecl {
803
+ precond do
804
+ counter_increment
805
+ end
806
+ }
807
+ def cond_method
808
+ end
809
+
810
+ ndecl {
811
+ precond(allow_instance_method: true) do
812
+ counter_increment
813
+ end
814
+ }
815
+ def cond_method2
816
+ end
817
+
818
+ ndecl {
819
+ precond do
820
+ unknown_meth
821
+ end
822
+ }
823
+ def cond_method3
824
+ end
825
+
826
+ ndecl {
827
+ precond(allow_instance_method: true) do
828
+ unknown_meth
829
+ end
830
+ }
831
+ def cond_method4
832
+ end
833
+
834
+
835
+ def counter_increment
836
+ @counter ||= 0
837
+ @counter += 1
838
+ end
839
+ end
840
+
841
+ instance = cls.new
842
+
843
+ # チェックエラー
844
+ assert_raise_message(%r|instance method `counter_increment' cannot be called|){ instance.cond_method }
845
+ assert_nothing_raised{ instance.cond_method2 }
846
+ assert_raise_message(%r|undefined local variable or method `unknown_meth'|){ instance.cond_method3 }
847
+ assert_raise_message(%r|undefined local variable or method `unknown_meth'|){ instance.cond_method4 }
848
+ end
849
+ end
850
+
851
+ # 不正な宣言のテスト
852
+ class InvalidDeclarationTest < Test::Unit::TestCase
853
+ # test "insufficient argument declaration" do
854
+ # assert_raise(NeuronCheckSystem::ExceptionBase) do
855
+ # class Foo1
856
+ # extend NeuronCheck
857
+ #
858
+ # ndecl {
859
+ # args String
860
+ # }
861
+ # def args_insuff(arg1, arg2)
862
+ # end
863
+ # end
864
+ # end
865
+ # end
866
+
867
+ test "over argument declaration" do
868
+ assert_raise(NeuronCheckSystem::DeclarationError) do
869
+ class Foo2
870
+ extend NeuronCheck
871
+
872
+ ndecl {
873
+ args String, String, String
874
+ }
875
+ def args_over(arg1, arg2)
876
+ end
877
+ end
878
+ end
879
+ end
880
+
881
+ test "over argument complex declaration" do
882
+ assert_nothing_raised do
883
+ class Foo4
884
+ extend NeuronCheck
885
+
886
+ ndecl {
887
+ args String, String, Numeric, [true, false]
888
+ returns :self
889
+ }
890
+ def foo_method(arg1, arg2, *arg3, flag1: false)
891
+ return self
892
+ end
893
+ end
894
+ end
895
+ end
896
+
897
+ test "over argument declaration (with rest)" do
898
+ assert_raise(NeuronCheckSystem::DeclarationError) do
899
+ class Foo3
900
+ extend NeuronCheck
901
+
902
+ ndecl {
903
+ args String, String, String
904
+ }
905
+ def args_over(arg1, *arg2)
906
+ end
907
+ end
908
+ end
909
+ end
910
+
911
+
912
+ end
913
+
914
+ # 2016年3月に発生した原因不明の不具合のテスト
915
+ class Bug201603Test < Test::Unit::TestCase
916
+ test "return value become nil" do
917
+ cls = Class.new
918
+ cls.class_eval do
919
+ extend NeuronCheck
920
+
921
+ ndecl {
922
+ args String, String, Numeric, [true, false]
923
+ returns :self
924
+
925
+ precond do
926
+ assert{ arg2.length == 1 }
927
+ end
928
+
929
+ postcond do |ret|
930
+ assert(ret)
931
+ end
932
+ }
933
+ def foo_method(arg1, arg2 = 20, *arg3, flag1: false)
934
+ return self
935
+ end
936
+ end
937
+
938
+ inst = cls.new
939
+ assert_raise(NeuronCheckSystem::DeclarationError){
940
+ inst.foo_method("1", "2", 1, 2, 3, flag1: true)
941
+ }
942
+ end
943
+ end