デッドロックや競合状態の影響を受けやすいコードの繰り返し可能な単体テストを作成する方法について何か提案はありますか?
今、私はユニットテストをスキップしてストレステストに集中することに傾いています。それに関する問題は、ストレステストを5回実行して、5つの異なる結果を確認できることです。
編集:私はそれがおそらく単なる夢であることを知っていますが、個々のスレッドを制御し、一度に1つの命令を実行させる方法があれば、どこかに到達する可能性があります。
デッドロックや競合状態の影響を受けやすいコードの繰り返し可能な単体テストを作成する方法について何か提案はありますか?
今、私はユニットテストをスキップしてストレステストに集中することに傾いています。それに関する問題は、ストレステストを5回実行して、5つの異なる結果を確認できることです。
編集:私はそれがおそらく単なる夢であることを知っていますが、個々のスレッドを制御し、一度に1つの命令を実行させる方法があれば、どこかに到達する可能性があります。
TypeMock Racerを見てください(ベータ版です)
編集:実際にはアルファ
http://www.typemock.com/Typemock_software_development_tools.html
通常、ManualResetEventなどを使用して、各スレッドを解放する前に期待される状態にすることで、予測される競合状態とデッドロックを強制することができます。つまり、スレッドAにロックを設定させ、シグナルを待機させます...スレッドBに要求を取得します。ロックなど...
ただし、通常は、疑わしいバグを調査し、いつ修正され、再表示されないかを証明するために、このようなテストを作成する場合があります。通常、競合状態を中心に設計します(ただし、実用的な方法でテストするのが最善です)。
競合状態を探すことは、実際には単体テストの領域に入るとは思いません。定義上、多かれ少なかれ、競合状態をテストする唯一の方法は疑似ランダムです。ロック戦略の正しさを正式に証明する努力を惜しまない限り、ストレステストを行う必要があります。
ロック戦略ではなく、アルゴリズムの正しさを検証するために、単体テストを作成する必要があります。
マルチスレッドコードのストレステストを行う場合は、スレッドごとに1つのCPUがあり、複数のスレッドがCPUを共有し、スレッドよりも多くのCPUがある(可能な場合)という条件下でテストする必要があります。
ロック操作の順序を調べることで、潜在的なデッドロックを検出するロック クラスを作成できます。これを行うには、すべてのロックが取得時に登録されるスレッド コンテキストを用意します (DEBUG のみのオプションにすることができます)。
アイデアは、ノードがロックを表し、A と B の間の有向エッジが「ロック B が取得されたときにロック A が保持されていた」ことを意味するグラフを作成することです。通常の負荷を使用してプログラムを実行し、グラフでサイクルを確認します。サイクルは、コードがヒットしなくても、デッドロックの可能性があることを意味します。
良い自動化された方法を考えることはできませんが、デッドロックを「公開」する単体テストを作成するのに最も近いのは、単体テストに加えてブレークポイントを使用することでした。ブレークポイントを追加する場所に関するいくつかの指示を追加しただけです。手作業が必要ですが、それらを使用すると、最悪の場合のスレッドスケジュールをいつでも公開できます。
おそらく誰かがこのタイプの機能を自動化する良い方法を考え出したのでしょうか?デバッガーを自動的に実行し、特定の行で1つのスレッドを中断し、特定の条件まで別のスレッドを実行させてから、単体テストをアサートすることを想像できます。
Corensic Jinxを試しましたか?
私は以前、リクエストのいくつかのパラメーターによってトリガーされるコードで人為的な遅延を使用しました。たとえば、ある要求はサーバーに 2 つの書き込みの間で書き込みを遅らせるように指示し、別の要求は間に遅延なしでそれらを実行するように指示します。
A Mark Bessey は、これは問題の発見ではなく、再現の作成にのみ役立つと書いています。