How to get the code testable when there is an endless loop?

301 views
Skip to first unread message

xiaohong liu

unread,
Aug 25, 2011, 5:43:39 AM8/25/11
to cpputest
Hi, all

We have code under test function bspmsgrx, which tends to use an
endless loop to check if there are packets received, and send the
packets received to a queue.
Here is the source code as reference, in which SocApiRecvPonPkt will
call ioctl to read packets.

We can fake the functions SocApiRecvPonPkt and appmsgsend to make sure
the msg received and msg sent are same. But when Test Case call this
function, it will be in the endless "while" and won’t end this TC.
How can we get such code testable?

Thanks.
Xiaohong Liu

Void bspmsgrx()
{

/* some var initialization */
…………


while (1)
{
/* If there are not message, will be blocked here. */
ret = SocApiRecvPonPkt(&omciCb.ParamRead);
if (0 != ret)
{
perror("DRV_IOC_READ operation failing \n");
continue;
}

rcvdPktNum = omciCb.ParamRead.rcvdPktNum;
cnt += rcvdPktNum;

if (rcvdPktNum == 0)
{
GPONDBG("RcvOmciMsg() failed, rcvdPktNum = %d.\n",
rcvdPktNum);
continue;
}

for (entryI=0; entryI<rcvdPktNum; entryI++)
{
omciMsgP = omciCb.ParamRead.readEntry[entryI].dataP;

msg = appmsgnew(APPMSG_OMCIRX, 48, omciMsgP);
if (msg != nil)
{
appmsgsend(msg);
appmsgfree(msg);
}
}

}
}



Terry Yin

unread,
Aug 25, 2011, 5:59:54 AM8/25/11
to cppu...@googlegroups.com
James has a solution for this in his book TDD for Embedded C:-)

You need to insert a 'spy' in the loop. It can be a stub for one of the function calls in the loop or a function only for test purpose.
And the 'spy' should be able to detect the dead loop, e.g. by counting or comparing temporary result with previous time.
Then when a deadloop is detected, the spy's assertion will fail and break out of the code under test.

 above is the direct answer to your question. But in most situation, it will be better if you can separate the loop logic & working logic, and test them respectively.

br, Terry
--
-terry
-------------------------
Blog: http://terryyin.blogbus.com/
twitter: http://twitter.com/terryyin

Bas Vodde

unread,
Aug 25, 2011, 9:33:03 PM8/25/11
to cppu...@googlegroups.com

Hi,

Usually the way to deal with this is to refactor the code a bit in:

void bsdpmsdgrx()
{
while(1)
doSomething();
}

This way you just test the doSomething without the loop.

Alternatively, you make the loop "end-ing" rather than "end-less" and I'm sure there are some conditions when the loop needs to be stopped ;)

Bas

xiaohong liu

unread,
Aug 26, 2011, 1:42:28 AM8/26/11
to cpputest
Terry, Bas

Thank you both:) For current CUT, I will add a FAIL assert to break
out of the loop. In the future refector, I will do the refactor.

thanks
Xiaohong Liu

James Grenning

unread,
Aug 26, 2011, 10:58:05 AM8/26/11
to cppu...@googlegroups.com

On Aug 26, 2011, at 12:42 AM, xiaohong liu wrote:

> Terry, Bas
>
> Thank you both:) For current CUT, I will add a FAIL assert to break
> out of the loop. In the future refector, I will do the refactor.


Having a FAIL in the loop will mean the test will always fail. You need a test that passes when it is working. Can you refactor the body of the loop as Bas suggested and then test doSomething?

James

xiaohong liu

unread,
Sep 1, 2011, 3:14:56 AM9/1/11
to cppu...@googlegroups.com
Yes. There will be a  refector and test doSomething instead.

2011/8/26 James Grenning <ja...@grenning.net>
Reply all
Reply to author
Forward
0 new messages