Wolfgang Thallergcc 15.1.0ada185d1 year agoHistory
2482 lines · 71.6 KB · D
RawDownload
// Written in the D programming language. /++    This module defines functions related to exceptions and general error    handling. It also defines functions intended to aid in unit testing. $(SCRIPT inhibitQuickIndex = 1;)$(DIVC quickindex,$(BOOKTABLE,$(TR $(TH Category) $(TH Functions))$(TR $(TD Assumptions) $(TD        $(LREF assertNotThrown)        $(LREF assertThrown)        $(LREF assumeUnique)        $(LREF assumeWontThrow)        $(LREF mayPointTo)))$(TR $(TD Enforce) $(TD        $(LREF doesPointTo)        $(LREF enforce)        $(LREF errnoEnforce)))$(TR $(TD Handlers) $(TD        $(LREF collectException)        $(LREF collectExceptionMsg)        $(LREF ifThrown)        $(LREF handle)))$(TR $(TD Other) $(TD        $(LREF basicExceptionCtors)        $(LREF emptyExceptionMsg)        $(LREF ErrnoException)        $(LREF RangePrimitive)))))     Copyright: Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-.    License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)    Authors:   $(HTTP erdani.org, Andrei Alexandrescu) and               $(HTTP jmdavisprog.com, Jonathan M Davis)    Source:    $(PHOBOSSRC std/exception.d)  +/module std.exception; /// Synopis@system unittest{    import core.stdc.stdlib : malloc, free;    import std.algorithm.comparison : equal;    import std.algorithm.iteration : map, splitter;    import std.algorithm.searching : endsWith;    import std.conv : ConvException, to;    import std.range : front, retro;     // use enforce like assert    int a = 3;    enforce(a > 2, "a needs to be higher than 2.");     // enforce can throw a custom exception    enforce!ConvException(a > 2, "a needs to be higher than 2.");     // enforce will return it's input    enum size = 42;    auto memory = enforce(malloc(size), "malloc failed")[0 .. size];    scope(exit) free(memory.ptr);     // collectException can be used to test for exceptions    Exception e = collectException("abc".to!int);    assert(e.file.endsWith("conv.d"));     // and just for the exception message    string msg = collectExceptionMsg("abc".to!int);    assert(msg == "Unexpected 'a' when converting from type string to type int");     // assertThrown can be used to assert that an exception is thrown    assertThrown!ConvException("abc".to!int);     // ifThrown can be used to provide a default value if an exception is thrown    assert("x".to!int().ifThrown(0) == 0);     // handle is a more advanced version of ifThrown for ranges    auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a));    auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);    assert(h.equal([12, 0, 54]));    assertThrown!ConvException(h.retro.equal([54, 0, 12]));     // basicExceptionCtors avoids the boilerplate when creating custom exceptions    static class MeaCulpa : Exception    {        mixin basicExceptionCtors;    }    e = collectException((){throw new MeaCulpa("diagnostic message");}());    assert(e.msg == "diagnostic message");    assert(e.file == __FILE__);    assert(e.line == __LINE__ - 3);     // assumeWontThrow can be used to cast throwing code into `nothrow`    void exceptionFreeCode() nothrow    {        // auto-decoding only throws if an invalid UTF char is given        assumeWontThrow("abc".front);    }     // assumeUnique can be used to cast mutable instance to an `immutable` one    // use with care    char[] str = "  mutable".dup;    str[0 .. 2] = "im";    immutable res = assumeUnique(str);    assert(res == "immutable");} import std.range.primitives;import std.traits; /++    Asserts that the given expression does $(I not) throw the given type    of `Throwable`. If a `Throwable` of the given type is thrown,    it is caught and does not escape assertNotThrown. Rather, an    `AssertError` is thrown. However, any other `Throwable`s will escape.     Params:        T          = The `Throwable` to test for.        expression = The expression to test.        msg        = Optional message to output on test failure.                     If msg is empty, and the thrown exception has a                     non-empty msg field, the exception's msg field                     will be output on test failure.        file       = The file where the error occurred.                     Defaults to `__FILE__`.        line       = The line where the error occurred.                     Defaults to `__LINE__`.     Throws:        `AssertError` if the given `Throwable` is thrown.     Returns:        the result of `expression`. +/auto assertNotThrown(T : Throwable = Exception, E)                    (lazy E expression,                     string msg = null,                     string file = __FILE__,                     size_t line = __LINE__){    import core.exception : AssertError;    try    {        return expression();    }    catch (T t)    {        immutable message = msg.length == 0 ? t.msg : msg;        immutable tail = message.length == 0 ? "." : ": " ~ message;        throw new AssertError("assertNotThrown failed: " ~ T.stringof ~ " was thrown" ~ tail, file, line, t);    }}///@system unittest{    import core.exception : AssertError;     import std.string;    assertNotThrown!StringException(enforce!StringException(true, "Error!"));     //Exception is the default.    assertNotThrown(enforce!StringException(true, "Error!"));     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(               enforce!StringException(false, "Error!"))) ==           `assertNotThrown failed: StringException was thrown: Error!`);}@system unittest{    import core.exception : AssertError;    import std.string;    assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(               enforce!StringException(false, ""), "Error!")) ==           `assertNotThrown failed: StringException was thrown: Error!`);     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(               enforce!StringException(false, ""))) ==           `assertNotThrown failed: StringException was thrown.`);     assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(               enforce!StringException(false, ""), "")) ==           `assertNotThrown failed: StringException was thrown.`);} @system unittest{    import core.exception : AssertError;     static noreturn throwEx(Throwable t) { throw t; }    bool nothrowEx() { return true; }     try    {        assert(assertNotThrown!Exception(nothrowEx()));    }    catch (AssertError) assert(0);     try    {        assert(assertNotThrown!Exception(nothrowEx(), "It's a message"));    }    catch (AssertError) assert(0);     try    {        assert(assertNotThrown!AssertError(nothrowEx()));    }    catch (AssertError) assert(0);     try    {        assert(assertNotThrown!AssertError(nothrowEx(), "It's a message"));    }    catch (AssertError) assert(0);     {        bool thrown = false;        try        {            assertNotThrown!Exception(                throwEx(new Exception("It's an Exception")));        }        catch (AssertError) thrown = true;        assert(thrown);    }     {        bool thrown = false;        try        {            assertNotThrown!Exception(                throwEx(new Exception("It's an Exception")), "It's a message");        }        catch (AssertError) thrown = true;        assert(thrown);    }     {        bool thrown = false;        try        {            assertNotThrown!AssertError(                throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));        }        catch (AssertError) thrown = true;        assert(thrown);    }     {        bool thrown = false;        try        {            assertNotThrown!AssertError(                throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)),                        "It's a message");        }        catch (AssertError) thrown = true;        assert(thrown);    }} /++    Asserts that the given expression throws the given type of `Throwable`.    The `Throwable` is caught and does not escape assertThrown. However,    any other `Throwable`s $(I will) escape, and if no `Throwable`    of the given type is thrown, then an `AssertError` is thrown.     Params:        T          = The `Throwable` to test for.        expression = The expression to test.        msg        = Optional message to output on test failure.        file       = The file where the error occurred.                     Defaults to `__FILE__`.        line       = The line where the error occurred.                     Defaults to `__LINE__`.     Throws:        `AssertError` if the given `Throwable` is not thrown.  +/void assertThrown(T : Throwable = Exception, E)                 (lazy E expression,                  string msg = null,                  string file = __FILE__,                  size_t line = __LINE__){    import core.exception : AssertError;     try        expression();    catch (T)        return;     static if (!is(immutable E == immutable noreturn))        throw new AssertError("assertThrown failed: No " ~ T.stringof ~ " was thrown"                                 ~ (msg.length == 0 ? "." : ": ") ~ msg,                          file, line);}///@system unittest{    import core.exception : AssertError;    import std.string;     assertThrown!StringException(enforce!StringException(false, "Error!"));     //Exception is the default.    assertThrown(enforce!StringException(false, "Error!"));     assert(collectExceptionMsg!AssertError(assertThrown!StringException(               enforce!StringException(true, "Error!"))) ==           `assertThrown failed: No StringException was thrown.`);} @system unittest{    import core.exception : AssertError;     static noreturn throwEx(Throwable t) { throw t; }    void nothrowEx() { }     try    {        assertThrown!Exception(throwEx(new Exception("It's an Exception")));    }    catch (AssertError) assert(0);     try    {        assertThrown!Exception(throwEx(new Exception("It's an Exception")),                               "It's a message");    }    catch (AssertError) assert(0);     try    {        assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",                                                         __FILE__, __LINE__)));    }    catch (AssertError) assert(0);     try    {        assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",                                                         __FILE__, __LINE__)),                                 "It's a message");    }    catch (AssertError) assert(0);      {        bool thrown = false;        try            assertThrown!Exception(nothrowEx());        catch (AssertError)            thrown = true;         assert(thrown);    }     {        bool thrown = false;        try            assertThrown!Exception(nothrowEx(), "It's a message");        catch (AssertError)            thrown = true;         assert(thrown);    }     {        bool thrown = false;        try            assertThrown!AssertError(nothrowEx());        catch (AssertError)            thrown = true;         assert(thrown);    }     {        bool thrown = false;        try            assertThrown!AssertError(nothrowEx(), "It's a message");        catch (AssertError)            thrown = true;         assert(thrown);    }}  /++    Enforces that the given value is true.    If the given value is false, an exception is thrown.    The    $(UL        $(LI `msg` - error message as a `string`)        $(LI `dg` - custom delegate that return a string and is only called if an exception occurred)        $(LI `ex` - custom exception to be thrown. It is `lazy` and is only created if an exception occurred)    )     Params:        value = The value to test.        E = Exception type to throw if the value evaluates to false.        msg = The error message to put in the exception if it is thrown.        dg = The delegate to be called if the value evaluates to false.        ex = The exception to throw if the value evaluates to false.        file = The source file of the caller.        line = The line number of the caller.     Returns: `value`, if `cast(bool) value` is true. Otherwise,    depending on the chosen overload, `new Exception(msg)`, `dg()` or `ex` is thrown.         $(PANEL        $(NOTE `enforce` is used to throw exceptions and is therefore intended to        aid in error handling. It is $(I not) intended for verifying the logic        of your program - that is what `assert` is for.)         Do not use        `enforce` inside of contracts (i.e. inside of `in` and `out`        blocks and `invariant`s), because contracts are compiled out when        compiling with $(I -release).        )         If a delegate is passed, the safety and purity of this function are inferred        from `Dg`'s safety and purity. +/template enforce(E : Throwable = Exception)if (is(typeof(new E("", string.init, size_t.init)) : Throwable) ||    is(typeof(new E(string.init, size_t.init)) : Throwable)){    ///    T enforce(T)(T value, lazy const(char)[] msg = null,    string file = __FILE__, size_t line = __LINE__)    if (is(typeof({ if (!value) {} })))    {        if (!value) bailOut!E(file, line, msg);        return value;    }} /// dittoT enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)    (T value, scope Dg dg)if (isSomeFunction!Dg && is(typeof( dg() )) &&    is(typeof({ if (!value) {} }))){    if (!value) dg();    return value;} /// dittoT enforce(T)(T value, lazy Throwable ex){    if (!value) throw ex();    return value;} ///@system unittest{    import core.stdc.stdlib : malloc, free;    import std.conv : ConvException, to;     // use enforce like assert    int a = 3;    enforce(a > 2, "a needs to be higher than 2.");     // enforce can throw a custom exception    enforce!ConvException(a > 2, "a needs to be higher than 2.");     // enforce will return it's input    enum size = 42;    auto memory = enforce(malloc(size), "malloc failed")[0 .. size];    scope(exit) free(memory.ptr);} ///@safe unittest{    assertNotThrown(enforce(true, new Exception("this should not be thrown")));    assertThrown(enforce(false, new Exception("this should be thrown")));} ///@safe unittest{    assert(enforce(123) == 123);     try    {        enforce(false, "error");        assert(false);    }    catch (Exception e)

Lines 1–500 of 2482.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t