3

我正在尝试编写一个 junit 测试来防止一段代码陷入无休止的迭代中,这最终会导致 StackOverflow。

所以我正在寻找一种在运行时减少堆栈大小的方法,这样 Junittest 会更快地失败。

无法将最大堆栈设置为 jvm 参数,因为测试是更大的测试套件的一部分。

4

4 回答 4

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);
    }
}

编辑:智能 JVM 可能会在这里优化尾调用,所以我们可能需要在递归调用之后做一些“事情”来阻止这种情况的发生......

Ick'n东西:(

于 2009-06-11T11:02:55.907 回答
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());
于 2009-06-11T11:02:20.027 回答
1

您只能在启动时设置这样的参数,但是您可以从 Java 启动另一个进程。因此,您可以让您的单元测试以较小的堆栈大小启动第二个进程来执行您的测试。

于 2009-06-12T03:00:08.507 回答
0

这有点……嗯,很有趣……但这可能是值得的。

  1. 获取您的 .class 文件并使用jasper对其进行反编译。
  2. 编辑生成的 JVM 汇编式代码,并为要以这种方式测试的例程添加或更改“.limit stack x”参数。
  3. 用Jasmin 重新编译。
  4. 运行它并测试。
于 2009-06-12T03:08:59.080 回答