2009-06-11 3 views
3

最終的にStackOverflowを引き起こす無限の反復でスタックされたコードを防ぐために、junitテストを作成しようとしています。実行時にJavaでmax stacksizeを小さくする

私は実行時にスタックサイズを減らす方法を探していますので、Junittestはより速く失敗します。

テストがもっと大きなテストスイートの一部であるため、maxスタックをjvm引数として設定することはできません。

答えて

5

あなたはその後、自分自身に所定の回数を実行します再帰的な方法を実行することができます指定されたアクションを実行します。サウンドはかなりサクサクしかし:(

のような何か:

public void eatStackThenExecute(int depth, Runnable action) 
{ 
    // Maybe put some locals here (and use them) to eat more stack per iteration? 
    if (depth == 0) 
    { 
     action(); 
    } 
    else 
    { 
     eatStackThenExecute(depth - 1, action); 
    } 
} 

EDIT:それはスマートなJVMがここに末尾呼び出しを最適化することが可能ですので、我々は後に「何か」を行う必要があるだろうということかもしれ再帰呼び出しは

嫌「Nのもの:(

+0

ワウ。何かひどい考え。しかし、実際にはスタックの深さをJVMのMaxに設定します - 実行時に深度argなので、とにかく+1します。 –

2

それは、実行時にスタックサイズを設定することはできませんが、おそらく次のことができます。

  • 異なるスレッド内のコードのその部分を呼び出す - それへの参照を保持。
  • は、周期的にポーリングthread.getStackTrace()をポーリングし、そのサイズがxより大きい場合は失敗します。
  • 実行が正しく終了するかどうかのチェックをキャンセルします。

コンセプトコードのコンパイルではない証拠(適切にすべてのエッジ条件をチェックしません):

AtomicBoolean success = new AtomicBoolean(false); 

Thread t= new Thread(new Runnable() { 
    public void run() { 
     codeToTest(); 
     success.set(true); 
    } 

}); 

t.start(); 

while (t.isAlive()) { 
    if (t.getStackTrace().length > 50) 
      fail("Stack trace too large"); 

    Thread.sleep(50); 
} 

assertTrue(sucess.get()); 
1

あなたは起動時にこのようなセットのみのパラメータは、しかし、あなたはJavaから別のプロセスを開始することができますすることができます...起きてからそれを停止します。あなたのユニットテストを作ることができるのでより小さいスタックサイズを持つ第2のプロセスをpに開始するあなたのテストをerformしてください。

+0

"プロセス"によって最初に "進捗"する必要がありますか? –

+0

@MattFenwickはい、ありがとうございます。 –

0

これはちょっと...面白いですが、それはそれに値するかもしれません。

  1. .classファイルを取り出し、jasperで逆コンパイルします。
  2. 結果のJVMアセンブリのesqueコードを編集し、この方法でテストするルーチンの ".limit stack x"引数を追加または変更します。
  3. Jasminで再コンパイルしてください。
  4. 実行してテストします。
+0

これは、テストケースに使用する多くの失敗点を紹介すると思いますが、ありがとうございます。 – pvgoddijn

関連する問題