RubyCocoa 今日のコミット 2013-09-10
ぜんぶのテストが10.9 DP7でpassするよになった。ランタイムのコアとしては10.9 readyになったと思う。はじめにSEGVやテスト失敗がでまくったときに覚悟したほどヤバイ問題が起きてなくて助かった。。
test_passbyrefでSEGVする問題を修正
Ruby側からObjective-Cのメソッドを呼び出すとき、.bridgesupportファイルのmethod要素でignore='true'になってるメソッドだと、そのメソッドを呼び出しせずにRuntimeErrorを発生させるというようになっている。(実は今日まで知らなかったぜ!)
% uname -r 12.4.0 % /usr/bin/ruby /usr/bin/irb -rosx/cocoa --simple-prompt >> d = OSX::NSData.alloc.initWithBytes_length('foobar') => #<OSX::NSConcreteData:0x83353288 class='NSConcreteData' id=0x7ff1323d73f0> >> d.testGetBytes(nil) OSX::OCMessageSendException: Can't get Objective-C method signature for selector 'testGetBytes:' of receiver #<OSX::NSConcreteData:0x83353288 class='NSConcreteData' id=0x7ff1323d73f0> >> quit % ack getBytes /System/Library/Frameworks/Foundation.framework/Resources/BridgeSupport /System/Library/Frameworks/Foundation.framework/Resources/BridgeSupport/Foundation.bridgesupport 2608:<method suggestion='Call bytes or getBytes:length:.' selector='getBytes:' ignore='true'/>
で、10.9だとテストに使ってる-[NSData getBytes:]や-[NSData getBytes:range:]のエントリがFoundation.bridgesupportからなくなっているのだ。ま、ずいぶん前からdeprecatedだから、いつなくなっても不思議じゃなかったんだけどさ。
def test_ignored d = OSX::NSData.alloc.initWithBytes_length('foobar') assert_raises(RuntimeError) { d.getBytes(nil) } assert_raises(RuntimeError) { d.getBytes_range(nil, OSX::NSRange.new(0, 1)) } end
最初見た時は「なんでnilで大丈夫なんだろ?」と思ったけど、ObjC側は呼び出されないからなんだね。テストコード側では呼び出されないものと思ってバッファちゃんと用意せずにメソッド呼び出しててるから、Obj-C側が呼び出されたらそりゃもうSEGVコースなわけです。
修正として、別のメソッドでのテストにする。という対応も考えたんだけど、ちょうどよさそうなメソッドが見つからなかったのと、また同じことが起きて対処するのもばからしいので、テスト用のインターフェイスを定義してそのメソッドを使うようにした。
test_passbyref単体を流すとtest_null_acceptedがFailになる現象を回避
上の問題を調べてるときに気付いたんだけど
% ruby1.8 install.rb test TESTS="-t TC_PassByRef"
でテスト流してるときにtest_null_acceptedも失敗してるのね。でもテストケースをぜんぶ流すときには通ってる。NSCountWindows()の実行で問題が起きてるっぽいんだけど、他のテスト通したときは大丈夫ってことはなんかプロセス内のなんかの状態とかによるもののよう。で、CGなんとかからアタリをつけて、
OSX.CGMainDisplayID()
を実行したときに直ったので、test_null_acceptedのassertion前に実行するようにした。本来はちゃんと調べるべきだろうけどあまり本質的なとこじゃないのでまあいいでしょう。