www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unttests for nested functions

reply BCS <BCS_member pathlink.com> writes:
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 27 2006
next sibling parent BCS <BCS_member pathlink.com> writes:
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 27 2006
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
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 28 2006
parent reply BCS <BCS_member pathlink.com> writes:
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
next sibling parent Derek Parnell <derek psych.ward> writes:
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 29 2006
prev sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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?

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 29 2006
parent BCS <BCS_member pathlink.com> writes:
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.

May 30 2006