Home | History | Annotate | Line # | Download | only in detail
      1 //
      2 // Automated Testing Framework (atf)
      3 //
      4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
      5 // All rights reserved.
      6 //
      7 // Redistribution and use in source and binary forms, with or without
      8 // modification, are permitted provided that the following conditions
      9 // are met:
     10 // 1. Redistributions of source code must retain the above copyright
     11 //    notice, this list of conditions and the following disclaimer.
     12 // 2. Redistributions in binary form must reproduce the above copyright
     13 //    notice, this list of conditions and the following disclaimer in the
     14 //    documentation and/or other materials provided with the distribution.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 
     30 #if defined(HAVE_CONFIG_H)
     31 #include "bconfig.h"
     32 #endif
     33 
     34 #include <cstdarg>
     35 #include <cstdio>
     36 #include <cstring>
     37 #include <new>
     38 
     39 extern "C" {
     40 #include "../../atf-c/error.h"
     41 };
     42 
     43 #include "exceptions.hpp"
     44 #include "sanity.hpp"
     45 
     46 // ------------------------------------------------------------------------
     47 // The "system_error" type.
     48 // ------------------------------------------------------------------------
     49 
     50 atf::system_error::system_error(const std::string& who,
     51                                 const std::string& message,
     52                                 int sys_err) :
     53     std::runtime_error(who + ": " + message),
     54     m_sys_err(sys_err)
     55 {
     56 }
     57 
     58 atf::system_error::~system_error(void)
     59     throw()
     60 {
     61 }
     62 
     63 int
     64 atf::system_error::code(void)
     65     const
     66     throw()
     67 {
     68     return m_sys_err;
     69 }
     70 
     71 const char*
     72 atf::system_error::what(void)
     73     const
     74     throw()
     75 {
     76     try {
     77         if (m_message.length() == 0) {
     78             m_message = std::string(std::runtime_error::what()) + ": ";
     79             m_message += ::strerror(m_sys_err);
     80         }
     81 
     82         return m_message.c_str();
     83     } catch (...) {
     84         return "Unable to format system_error message";
     85     }
     86 }
     87 
     88 // ------------------------------------------------------------------------
     89 // Free functions.
     90 // ------------------------------------------------------------------------
     91 
     92 static
     93 void
     94 throw_libc_error(atf_error_t err)
     95 {
     96     PRE(atf_error_is(err, "libc"));
     97 
     98     const int ecode = atf_libc_error_code(err);
     99     const std::string msg = atf_libc_error_msg(err);
    100     atf_error_free(err);
    101     throw atf::system_error("XXX", msg, ecode);
    102 }
    103 
    104 static
    105 void
    106 throw_no_memory_error(atf_error_t err)
    107 {
    108     PRE(atf_error_is(err, "no_memory"));
    109 
    110     atf_error_free(err);
    111     throw std::bad_alloc();
    112 }
    113 
    114 static
    115 void
    116 throw_unknown_error(atf_error_t err)
    117 {
    118     PRE(atf_is_error(err));
    119 
    120     static char buf[4096];
    121     atf_error_format(err, buf, sizeof(buf));
    122     atf_error_free(err);
    123     throw std::runtime_error(buf);
    124 }
    125 
    126 void
    127 atf::throw_atf_error(atf_error_t err)
    128 {
    129     static struct handler {
    130         const char* m_name;
    131         void (*m_func)(atf_error_t);
    132     } handlers[] = {
    133         { "libc", throw_libc_error },
    134         { "no_memory", throw_no_memory_error },
    135         { NULL, throw_unknown_error },
    136     };
    137 
    138     PRE(atf_is_error(err));
    139 
    140     handler* h = handlers;
    141     while (h->m_name != NULL) {
    142         if (atf_error_is(err, h->m_name)) {
    143             h->m_func(err);
    144             UNREACHABLE;
    145         } else
    146             h++;
    147     }
    148     // XXX: I'm not sure that raising an "unknown" error is a wise thing
    149     // to do here.  The C++ binding is supposed to have feature parity
    150     // with the C one, so all possible errors raised by the C library
    151     // should have their counterpart in the C++ library.  Still, removing
    152     // this will require some code auditing that I can't afford at the
    153     // moment.
    154     INV(h->m_name == NULL && h->m_func != NULL);
    155     h->m_func(err);
    156     UNREACHABLE;
    157 }
    158