digitalmars.D.learn - Unttests for nested functions

• BCS (24/24) May 27 2006 how do I unittest bar?
• BCS (29/53) May 27 2006 OK, after think about it for a while, I have come up with a possible sol...
• Derek Parnell (37/38) May 28 2006 Currently one can't directly test it using unit tests, however on the
• BCS (4/9) May 29 2006 that is what I was expecting. :P Any thoughts on how to make it so you ...
• Derek Parnell (14/27) May 29 2006 The obvious way would be to allow unit test blocks to be nested inside
• Daniel Keep (73/86) May 29 2006 I suppose the problem is that the inner function is inseperable from the
• BCS (8/15) May 30 2006 That's about what I was thinking.
```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
```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
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
```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
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
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?

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 29 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.

```
May 30 2006