www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Catch block not hit in unittest

reply Lucia Cojocaru <lucia.mcojocaru gmail.com> writes:
Hello,

I am trying to assert the fact that a UnicodeException is thrown 
by the piece of code added in this PR:
https://github.com/dlang/druntime/pull/1696/files

The unittest is in druntime/src/rt/lifetime.d:

unittest
{
     import core.exception : UnicodeException;

     try
     {
         string ret;
         int i = -1;
         ret ~= i;
     }
     catch(UnicodeException e)
     {
         assert(e.msg == "Invalid UTF-8 sequence");
     }
}

However running the tests for druntime fails because the 
exception is not caught:
****** FAIL release64 rt.lifetime
core.exception.UnicodeException src/rt/lifetime.d(2031): Invalid 
UTF-8 sequence

I tried to use the same code as in the unittest above in a 
regular D source file and the UnicodeException was properly 
caught there.

Do you know what the problem might be?

Thank you,
Lucia
Nov 24 2016
parent reply Kagamin <spam here.lot> writes:
Linux? Probably another bug.
Try this:
unittest
{
     import core.exception : UnicodeException;
     void f()
     {
         string ret;
         int i = -1;
         ret ~= i;
     }

     try
     {
         f();
     }
     catch(UnicodeException e)
     {
         assert(e.msg == "Invalid UTF-8 sequence");
     }
}
Nov 24 2016
next sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Thursday, November 24, 2016 13:42:25 Kagamin via Digitalmars-d-learn 
wrote:
 Linux? Probably another bug.
 Try this:
 unittest
 {
      import core.exception : UnicodeException;
      void f()
      {
          string ret;
          int i = -1;
          ret ~= i;
      }

      try
      {
          f();
      }
      catch(UnicodeException e)
      {
          assert(e.msg == "Invalid UTF-8 sequence");
      }
 }
If you're doing that, you might as well use std.exception.assertThrown or collectException. e.g. assertThrown!UnicodeException(f()); or assert(collectException!UnicodeException(f()).msg == "Invalid UTF-8 sequence."); You could also do the same with a lambda to avoid the explicit function. Regardless, I don't know why the OP is hitting this problem, and unfortunately, I can't test it on my local machine at the moment to try and see what's going on. - Jonathan M Davis
Nov 24 2016
parent reply Lucia Cojocaru <lucia.mcojocaru gmail.com> writes:
On Thursday, 24 November 2016 at 14:47:32 UTC, Jonathan M Davis 
wrote:
 On Thursday, November 24, 2016 13:42:25 Kagamin via 
 Digitalmars-d-learn wrote:
 Linux? Probably another bug.
 Try this:
 unittest
 {
      import core.exception : UnicodeException;
      void f()
      {
          string ret;
          int i = -1;
          ret ~= i;
      }

      try
      {
          f();
      }
      catch(UnicodeException e)
      {
          assert(e.msg == "Invalid UTF-8 sequence");
      }
 }
If you're doing that, you might as well use std.exception.assertThrown or collectException. e.g. assertThrown!UnicodeException(f()); or assert(collectException!UnicodeException(f()).msg == "Invalid UTF-8 sequence."); You could also do the same with a lambda to avoid the explicit function. Regardless, I don't know why the OP is hitting this problem, and unfortunately, I can't test it on my local machine at the moment to try and see what's going on. - Jonathan M Davis
Thanks Kagamin and Jonathan for your suggestions! I was able to hack my way around it. In druntime there are other modules which need the exact same thing and have their own assertThrown template: https://github.com/dlang/druntime/search?utf8=%E2%9C%93&q=assertThrown So I did the same thing and defined assertThrown in my unittest. Now it works fine: unittest { import core.exception : UnicodeException; static void assertThrown(T : Throwable = Exception, E)(lazy E expr, string msg) { try expr; catch (T e) { assert(e.msg == msg); return; } } static void f() { string ret; int i = -1; ret ~= i; } assertThrown!UnicodeException(f(), "Invalid UTF-8 sequence"); } It is still unclear why this approach is necessary. Thanks, Lucia
Nov 24 2016
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Thursday, November 24, 2016 15:41:12 Lucia Cojocaru via Digitalmars-d-
learn wrote:
 I was able to hack my way around it. In druntime there are other
 modules which need the exact same thing and have their own
 assertThrown template:
 https://github.com/dlang/druntime/search?utf8=%E2%9C%93&q=assertThrown

 So I did the same thing and defined assertThrown in my unittest.
 Now it works fine:
 unittest
 {
      import core.exception : UnicodeException;

      static void assertThrown(T : Throwable = Exception, E)(lazy E
 expr, string msg)
      {
          try
              expr;
          catch (T e) {
              assert(e.msg == msg);
              return;
          }
      }

      static void f()
      {
          string ret;
          int i = -1;
          ret ~= i;
      }

      assertThrown!UnicodeException(f(), "Invalid UTF-8 sequence");
 }

 It is still unclear why this approach is necessary.

 Thanks,
 Lucia
I would advise against this, because it does not match what std.exception.assertThrown does. It use the message you give as the message in the AssertError that gets thrown on failure. It doesn't assert what the message in the thrown exception is. It doesn't care. It just cares that the right type of exception was thrown. If you want to check the message, collectException is more appropriate (though you should check that it's result is non-null, which my example didn't). Regardless, if you're talking about essentially adding a Phobos function as a private helper in druntime, it's a bad idea to make it operate differently from the one in Phobos. It should either be the same, or it should be named differently. - Jonathan M Davis
Nov 24 2016
prev sibling parent reply Ryan <clumsycodemonkey gmail.com> writes:
On Thursday, 24 November 2016 at 13:42:25 UTC, Kagamin wrote:
 Linux? Probably another bug.
 Try this:
 unittest
 {
     import core.exception : UnicodeException;
     void f()
     {
         string ret;
         int i = -1;
         ret ~= i;
     }

     try
     {
         f();
     }
     catch(UnicodeException e)
     {
         assert(e.msg == "Invalid UTF-8 sequence");
     }
 }
Both the OP's code and this code gives me a segfault on DMD 2.071.1 on my Mac.
Nov 24 2016
parent Lucia Cojocaru <lucia.mcojocaru gmail.com> writes:
On Thursday, 24 November 2016 at 15:18:40 UTC, Ryan wrote:
 On Thursday, 24 November 2016 at 13:42:25 UTC, Kagamin wrote:
 Linux? Probably another bug.
 Try this:
 unittest
 {
     import core.exception : UnicodeException;
     void f()
     {
         string ret;
         int i = -1;
         ret ~= i;
     }

     try
     {
         f();
     }
     catch(UnicodeException e)
     {
         assert(e.msg == "Invalid UTF-8 sequence");
     }
 }
Both the OP's code and this code gives me a segfault on DMD 2.071.1 on my Mac.
The PR this unittest is for fixes the segfault issue. Check out: https://issues.dlang.org/show_bug.cgi?id=5995
Nov 24 2016