私は常に、単体テストに使用する次のコードを作成する方法に興味を持っていました。
特定のスレッドがブロックされているかどうかをチェックするメソッドでNSThreadを拡張することは可能ですか?
現在、 NSConditionを使用しています。Xcodeは、スレッドをブロックするために-waitによって呼び出されるチェーンを表示します。
[NSCondition wait]
pthread_cond_wait$UNIX2003
_pthread_cond_wait
__psynch_cvwait
NSConditionによって行われたロックをチェックする以外に、可能であれば、他のブロッキング機能(ディスパッチセマフォ、コンディションロック、スリーピングスレッドなど)でも機能するメソッドを高く評価します-Objective-Cの内部についてはわかりません、もしそれらが1つの方法で捕まえられるか、それぞれが独自の方法を必要とする場合。
これが私が達成したいことの簡単な例です。不思議な方法はisBlockedと呼ばれます。
// Some test case
// ...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
});
while(1) {
NSLog(@"Thread is blocked: %d", thread.isBlocked);
}
注:私はCと、これらすべての低レベルのPOSIXのものが得意ではないので、冗長にしてください。
注2:ディスパッチキューでも機能するソリューションに興味があります:someQueue()が-[NSCondition wait]によってブロックされるという事実をテストする方法を誰かが教えてくれる場合(ブロックされるという事実ではありません(fx -[condition wait]が実行され、ブロックが設定される前にいくつかのコードをハッキングします)が、スレッド/キューがブロックされているという事実)、-[NSThreadisBlocked]メソッドを使用する場合と同じようにこれを回答として受け入れます。
注3:「不可能」などの悪いニュースを疑って、-[条件待機]が実行され、スレッドがブロックされた(注2を参照)という事実をキャッチするためのアイデアはありがたいと思います。答え!
リチャードJ.ロスIIIによる素晴らしい答えへのアドレスの更新1 。残念ながら、彼の答えは私の元の例、つまり私の実際の仕事に近いバージョンでは機能しません(ただし、最初に提供した例と大差ありません-申し訳ありませんが、の最初の版にそれを含めませんでした質問):
// Example
// Here I've bootstrapped Richard's isLocking categories for both NSThread and NSCondition
// ...
// somewhere in SenTesting test case...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
__block BOOL wePassedBlocking = NO;
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
wePassedBlocking = YES; // (*) This line is occasionally never reached!
});
while(!thread.isWaitingOnCondition); // I want this loop to exit after the condition really locks someQueue() and _thread_ __.
// sleep(1);
[condition lock];
[condition broadcast]; // BUT SOMETIMES this line is called before -[condition wait] is called inside someQueue() so the entire test case becomes blocked!
[condition unlock];
while(!wePassedBlocking); // (*) And so this loop occasionally never ends!
私がsleep(1)のコメントを外すと、テストは時折ロックされることなく非常に安定して動作し始めます!
これは問題につながります。Richardのコードには同期メカニズムが含まれていないため、実際にsomeQueue / threadがブロックされる前に、テストケースのメインスレッドがこの新しい状態をキャッチすることがあります。 :@ synchronized、NSLockまたはそのようなもの!このトリッキーなケースについて明確に説明したいと思います。私がここに投稿した内容に疑問がある人のために、私は複数のキューやさらに複雑なケースも試していると思います。必要に応じて、さらに多くの例を提供する準備ができています。リチャード、あなたの努力にもう一度感謝します、あなたがこれらの私のポイントを理解するならば、もっと一緒に考えましょう!
更新2
行き止まりのパラドックスがわかります。明らかに、waitingOnConditionの状態を実際に設定するには、この状態の変更をいくつかの同期クロージャ内にラップする必要がありますが、問題は、同期ロックのロックを解除するクロージングを-[conditionの後に呼び出す必要があることです。待機]、しかし、スレッドがすでにブロックされているため、それはできません。繰り返しになりますが、私はそれをかなり明確に説明していると思います。