better assertions and __FILE__ (compile time functions)

Chris Nicholson-Sauls ibisbasenji at gmail.com
Wed Aug 22 15:31:53 PDT 2007


Bruce Adams wrote:
> Hi all,
>        Still stuck. How do I get the template to include the name of a run-time variable at compile-time? Please somebody put me out of my misery.
> 
> template assertEqual8(actual_, expected_)
> {
>    const char[] assertEqual8(actual_ a_, expected_ e_) { 
>       return 
> 	 "mixin(assertEqual5!("[]
> 	 ~actual_.stringof
> 	 ~")("[]
> 	 ~a_.stringof
> 	 ~","[]
> 	 ~e_.stringof
> 	 ~"));"[];
>    }
> }
> alias assertEqual8!(int, int) assertEqual9;
> 
> unittest {
>    // all fine
>    // writes: "mixin(assertEqual5!(int)(a_,e_));" when var5, var6 wanted
>    writefln(assertEqual9(var5,var6));
> 
>    // not allowed at CT :(
>    mixin(assertEqual9(var5,var6))
> }
> 
> UnitTest.d(246): Error: variable var5 is used before initialization
> UnitTest.d(246): Error: cannot evaluate assertEqual8(var5,var6) at compile time
> UnitTest.d(246): Error: argument to mixin must be a string, not (assertEqual8(va
> r5,var6))
> 
> 
> Bruce Adams Wrote:
> 
>> Right, thanks. I'm nearly there. 
>> Here's where I'm at:
>>
>> // for example only
>> void assertWrapper(char[] file_, uint line_) {
>>       _d_assert(file_,line_);
>> }
>>  
>> // the run-time assert part
>> void assertEqual(Type)(Type actual_, Type expected_, 
>> 		       char[] file_, 
>> 		       uint line_) {
>>    if (actual_ != expected_) {
>>       writefln("Equality assertion failed");
>>       writefln("actual:   '", actual_, "'");
>>       writefln("expected: '", expected_, "'");
>>    }
>>    assertWrapper(file_,line_);
>> }
>>
>> const char[] assertEqual4(const char[] actualVar_, const char[] expectedVar_) {
>>    return "assertEqual!(int)("[]
>>       ~actualVar_
>>       ~","[]
>>       ~expectedVar_
>>       ~",cast(char[])(__FILE__),__LINE__);"[]; 
>> }
>>
>> const char[] assertEqual5(T)(const char[] actualVar_, const char[] expectedVar_) {
>>    return "assertEqual!(" 
>>       ~typeof(T).stringof
>>       ~")("[]
>>       ~actualVar_
>>       ~","[]
>>       ~expectedVar_
>>       ~",cast(char[])(__FILE__),__LINE__);"[]; 
>> }
>>
>> unittest {
>>    // declare at run-time
>>    const int var3 = 1;
>>    const int var4 = 2;
>>
>>    int var5 = 1;
>>    int var6 = 2;
>>
>>     // okay - but must give name of variables
>>    writefln(assertEqual4("var5"[],"var6"[]));
>>    mixin(assertEqual4("var5"[],"var6"[]));
>>
>>    // must provide name and type
>>    mixin(assertEqual5!(int)("var5"[],"var6"[]));
>>
>>    // must provide name and type
>>    mixin(assertEqual5!(typeof(var5))(var5.stringof,var6.stringof));
>> }
>>
>> I reckon "mixin(assertEqual(var5,var6));" should be possible but I haven't quite figured it out yet.
>>
>> Regards,
>>
>> Bruce.
>>
>>
>> Lutger Wrote:
>>
>> [Some helpful stuff]
>>
> 

Try this...

void assertEqual (T) (T actual, T expected, char[] file, uint line) {
   if (actual != expected) {
     writeln("Equality assertion failed.");
     writefln("  actual:   '%s'", actual);
     writefln("  expected: '%s'", expected);
     _d_assert(file, line);
   }
}

template MAssertEqual (alias actual, alias expected) {
   const MAssertEqual =
     `assertEqual(`
     ~actual.stringof~
     `, `
     ~expected.stringof~
     `, __FILE__, __LINE__);`
   ;
}

unittest {
   int var5 = 1;
   int var6 = 2;

   mixin(MAssertEqual!(var5, var6)); // -> assertEqual(var5, var6, __FILE__, __LINE__);
}

Note: Untested.

-- Chris Nicholson-Sauls


More information about the Digitalmars-d-learn mailing list