diff --git a/exceptions.cpp b/exceptions.cpp index 8018b7a..a740812 100644 --- a/exceptions.cpp +++ b/exceptions.cpp @@ -94,3 +94,30 @@ lutok::api_error::api_function(void) const { return _api_function; } + + +/// Constructs a new error. +/// +/// \param filename_ The file that count not be found. +lutok::file_not_found_error::file_not_found_error( + const std::string& filename_) : + error("File '" + filename_ + "' not found"), + _filename(filename_) +{ +} + + +/// Destructor for the error. +lutok::file_not_found_error::~file_not_found_error(void) throw() +{ +} + + +/// Gets the name of the file that could not be found. +/// +/// \return The name of the file. +const std::string& +lutok::file_not_found_error::filename(void) const +{ + return _filename; +} diff --git a/exceptions.hpp b/exceptions.hpp index 93fe842..5045f4c 100644 --- a/exceptions.hpp +++ b/exceptions.hpp @@ -65,6 +65,18 @@ class api_error : public error { }; +/// File not found error. +class file_not_found_error : public error { + std::string _filename; + +public: + explicit file_not_found_error(const std::string&); + virtual ~file_not_found_error(void) throw(); + + const std::string& filename(void) const; +}; + + } // namespace lutok diff --git a/exceptions_test.cpp b/exceptions_test.cpp index 8b17d88..2a19e95 100644 --- a/exceptions_test.cpp +++ b/exceptions_test.cpp @@ -66,10 +66,21 @@ ATF_TEST_CASE_BODY(api_error__from_stack) } +ATF_TEST_CASE_WITHOUT_HEAD(file_not_found_error); +ATF_TEST_CASE_BODY(file_not_found_error) +{ + const lutok::file_not_found_error e("missing-file"); + ATF_REQUIRE(std::strcmp("File 'missing-file' not found", e.what()) == 0); + ATF_REQUIRE_EQ("missing-file", e.filename()); +} + + ATF_INIT_TEST_CASES(tcs) { ATF_ADD_TEST_CASE(tcs, error); ATF_ADD_TEST_CASE(tcs, api_error__explicit); ATF_ADD_TEST_CASE(tcs, api_error__from_stack); + + ATF_ADD_TEST_CASE(tcs, file_not_found_error); } diff --git a/operations_test.cpp b/operations_test.cpp index b59f003..c19de7f 100644 --- a/operations_test.cpp +++ b/operations_test.cpp @@ -175,7 +175,7 @@ ATF_TEST_CASE_BODY(do_file__not_found) { lutok::state state; stack_balance_checker checker(state); - ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'missing.lua'", + ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", lutok::do_file(state, "missing.lua")); } diff --git a/wrap.cpp b/wrap.cpp index 1e14e0d..2f1c6ee 100644 --- a/wrap.cpp +++ b/wrap.cpp @@ -26,6 +26,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +extern "C" { +#include +} + #include #include @@ -360,11 +364,14 @@ lutok::state::is_userdata(const int index) /// \param file The second parameter to luaL_loadfile. /// /// \throw api_error If luaL_loadfile returns an error. +/// \throw file_not_found_error If the file cannot be accessed. /// /// \warning Terminates execution if there is not enough memory. void lutok::state::load_file(const std::string& file) { + if (!::access(file.c_str(), R_OK) == 0) + throw lutok::file_not_found_error(file); if (luaL_loadfile(_pimpl->lua_state, file.c_str()) != 0) throw lutok::api_error::from_stack(_pimpl->lua_state, "luaL_loadfile"); } diff --git a/wrap_test.cpp b/wrap_test.cpp index 1b3289c..12eec9e 100644 --- a/wrap_test.cpp +++ b/wrap_test.cpp @@ -615,11 +615,12 @@ ATF_TEST_CASE_BODY(state__load_file__api_error) } -ATF_TEST_CASE_WITHOUT_HEAD(state__load_file__missing); -ATF_TEST_CASE_BODY(state__load_file__missing) +ATF_TEST_CASE_WITHOUT_HEAD(state__load_file__file_not_found_error); +ATF_TEST_CASE_BODY(state__load_file__file_not_found_error) { lutok::state state; - REQUIRE_API_ERROR("luaL_loadfile", state.load_file("missing.lua")); + ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", + state.load_file("missing.lua")); } @@ -1278,7 +1279,7 @@ ATF_INIT_TEST_CASES(tcs) ATF_ADD_TEST_CASE(tcs, state__is_userdata__explicit); ATF_ADD_TEST_CASE(tcs, state__load_file__ok); ATF_ADD_TEST_CASE(tcs, state__load_file__api_error); - ATF_ADD_TEST_CASE(tcs, state__load_file__missing); + ATF_ADD_TEST_CASE(tcs, state__load_file__file_not_found_error); ATF_ADD_TEST_CASE(tcs, state__load_string__ok); ATF_ADD_TEST_CASE(tcs, state__load_string__fail); ATF_ADD_TEST_CASE(tcs, state__new_table);