Thread overview
Unttests for nested functions
May 28, 2006
BCS
May 28, 2006
BCS
May 29, 2006
Derek Parnell
May 29, 2006
BCS
May 29, 2006
Derek Parnell
May 30, 2006
Daniel Keep
May 30, 2006
BCS
May 28, 2006
how do I unittest bar?

int foo(int i)
{
int j=0;

int bar(int k)  //////////
{
j+=k;
}
/+	cant make unit test here
unittest
{
bar(0);
}
+/

while(i);
bar(i--);

return j;
}

/+	cant access nested function here
unittest
{
bar(0);
}
+/





May 28, 2006
OK, after think about it for a while, I have come up with a possible solution. It amounts to a small change to the semantics of D, and (maybe, depending on the implementation) a little quirk in the code generator.

First from the semantic standpoint, allow a unittest inside of a function. Just
like in a normal nested function, the unit test will have access to the
variables in the other function.
Secondly, when implementing this unittest, a fake stack frame is generated for
the function it is nested inside of. That way the unittest can have a context to
call the nested function with. This stack frame could be the first part of the
unittest's  stack frame in such a way the calling the nested function from the
unittest works just like calling it from it's enclosing function.

A purposeless example:

void fn()
{
int i;

void nf()
{
i--;
}
unittest
{
i=2;
nf();
assert(1==i);
}

i=10;
while(i) nf();
}



In article <e5b2u0$1ncl$1@digitaldaemon.com>, BCS says...
>
>how do I unittest bar?
>
>int foo(int i)
>{
>int j=0;
>
>int bar(int k)  //////////
>{
>j+=k;
>}
>/+	cant make unit test here
>unittest
>{
>bar(0);
>}
>+/
>
>while(i);
>bar(i--);
>
>return j;
>}
>
>/+	cant access nested function here
>unittest
>{
>bar(0);
>}
>+/
>
>
>
>
>


May 29, 2006
On Sun, 28 May 2006 02:46:24 +0000 (UTC), BCS wrote:

> how do I unittest bar?

Currently one can't directly test it using unit tests, however on the assumption that the outer function uses the inner function I guess you can test it indirectly, plus you can also use inner asserts and DbC.

 int foo(int i)
 {
   int j=0;

   int bar(int k)
   out(x)
   {
    assert( x == j - k);
   }
   body
   {
     int ov = j;
     j += k;
     return ov; // The old value.
   }

  while(i)
    bar(i--);

  return j;
 }

 unittest
 {
  assert (foo(0) == 0);
  assert (foo(1) == 1);
  assert (foo(10) == 55);
 }

 void main()
 {
 }

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
29/05/2006 10:38:21 AM
May 29, 2006
that is what I was expecting. :P  Any thoughts on how to make it so you can?
(ref. my second post)

In article <1o4n88vezpkym$.1cj5tqvwrl0up$.dlg@40tude.net>, Derek Parnell says...
>
>On Sun, 28 May 2006 02:46:24 +0000 (UTC), BCS wrote:
>
>> how do I unittest bar?
>
>Currently one can't directly test it using unit tests, however on the assumption that the outer function uses the inner function I guess you can test it indirectly, plus you can also use inner asserts and DbC.
[...]


May 29, 2006
On Mon, 29 May 2006 23:15:00 +0000 (UTC), BCS wrote:

> that is what I was expecting. :P  Any thoughts on how to make it so you can?
> (ref. my second post)
> 
> In article <1o4n88vezpkym$.1cj5tqvwrl0up$.dlg@40tude.net>, Derek Parnell says...
>>
>>On Sun, 28 May 2006 02:46:24 +0000 (UTC), BCS wrote:
>>
>>> how do I unittest bar?
>>
>>Currently one can't directly test it using unit tests, however on the assumption that the outer function uses the inner function I guess you can test it indirectly, plus you can also use inner asserts and DbC.
> [...]

The obvious way would be to allow unit test blocks to be nested inside functions, classes, and structs too. And if we are going that way, allow 'import' statements to allowed inside unit test blocks.

Yes, I know there are technical issues to solve but Walter's a smart cookie and will be able to solve them to the benefit of the D language. If D wants to have a few differentiating points then comprehensive DbC and quality control is a good place to start.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
30/05/2006 9:45:48 AM
May 30, 2006
I suppose the problem is that the inner function is inseperable from the outer function.  Since the inner function shares the outer function's stack, you can't really call it without the outer function.

The problem here is that unittests are run on program *startup*.  That means that in order those unittests inside a function, it would have to... uh... I dunno; maybe "fake" the function's stack.  But then you just end up with random garbage data in the inner function.

The one idea I *could* come up with was this: firstly, pull the inner function out into a template.  Then, in your unittest, mix the template into a dummy stub function whose only job is to call the inner function and return it's result.  So your example:

# int foo(int i)
# {
#     int j=0;
#
#     int bar(int k)  //////////
#     {
#         j+=k;
#     }
#     /+	cant make unit test here
#     unittest
#     {
#         bar(0);
#     }
#     +/
#
#     while(i);
#         bar(i--);
#
#     return j;
# }

Would become something like:

# template barT()
# {
#     int bar(int k)
#     {
#         j += k;
#     }
# }
#
# int foo(int i)
# {
#     int j = 0;
#
#     mixin barT;
#
#     while(i)
#         bar(i--);
#
#     return j;
# }
#
# unittest
# {
#     int j; // Out here so we can look at it.
#
#     int barShim(int arg)
#     {
#         mixin barT;
#         return bar(arg);
#     }
#
#     // Write tests here
# }

Please note that I have *not* tested the above.  Should work... the only possible problem would be if the template wants a proper reference to 'j' (in that case, just pass it in as an alias).

Hope this helps.

	-- Daniel

BCS wrote:
> that is what I was expecting. :P  Any thoughts on how to make it so you can?
> (ref. my second post)
> 
> In article <1o4n88vezpkym$.1cj5tqvwrl0up$.dlg@40tude.net>, Derek Parnell says...
>> On Sun, 28 May 2006 02:46:24 +0000 (UTC), BCS wrote:
>>
>>> how do I unittest bar?
>> Currently one can't directly test it using unit tests, however on the assumption that the outer function uses the inner function I guess you can test it indirectly, plus you can also use inner asserts and DbC.
> [...]
> 
> 

-- 

v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP    http://hackerkey.com/
May 30, 2006
That's about what I was thinking.

Really all that is needed is a chunk of memory that the unittest can manipulate and pass off to the nested function. It's own stack frame would do as long as all of the variables from the other function are mapped the same (&i == FramePointer + TheSameSomethin in both functions). I'm not sure where variable alignment is decided, so I don't know how hard this would be to implement, but it's not that complicated conceptually.


In article <e5gl5v$2icg$1@digitaldaemon.com>, Daniel Keep says...
>
>I suppose the problem is that the inner function is inseperable from the outer function.  Since the inner function shares the outer function's stack, you can't really call it without the outer function.
>
>The problem here is that unittests are run on program *startup*.  That means that in order those unittests inside a function, it would have to... uh... I dunno; maybe "fake" the function's stack.  But then you just end up with random garbage data in the inner function.
>