Skip to content

Commit

Permalink
Introducing library specific exception
Browse files Browse the repository at this point in the history
User code can catch it and do appropriate action. This allows the application
code to distinguish between exceptions specific to fprops and other ones.
  • Loading branch information
andrsd committed Mar 8, 2024
1 parent e8d2818 commit 4d99b75
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 52 deletions.
24 changes: 24 additions & 0 deletions include/fprops/Exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include "fmt/format.h"
#include <exception>

namespace fprops {

class Exception : public std::exception {
public:
template <typename... T>
Exception(fmt::format_string<T...> format, T... args) :
msg(fmt::format(format, std::forward<T>(args)...))
{
}

/// Get the exception message
[[nodiscard]] auto what() const noexcept -> const char * override;

private:
/// Error message
std::string msg;
};

} // namespace fprops
11 changes: 11 additions & 0 deletions src/Exception.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "fprops/Exception.h"

namespace fprops {

auto
Exception::what() const noexcept -> const char *
{
return this->msg.c_str();
}

} // namespace fprops
16 changes: 8 additions & 8 deletions src/Helmholtz.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "fprops/Helmholtz.h"
#include "fprops/Numerics.h"
#include "fprops/Exception.h"
#include <cmath>
#include <stdexcept>

namespace fprops {

Expand All @@ -18,9 +18,9 @@ State
Helmholtz::rho_T(double rho, double T) const
{
if (rho < 0)
throw std::domain_error("Negative density");
throw Exception("Negative density");
if (T < 0)

Check warning on line 22 in src/Helmholtz.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

src/Helmholtz.cpp:22:15 [readability-braces-around-statements]

statement should be inside braces
throw std::domain_error("Negative temperature");
throw Exception("Negative temperature");

const double delta = rho / this->rho_c;
const double tau = this->T_c / T;
Expand Down Expand Up @@ -50,7 +50,7 @@ State
Helmholtz::rho_p(double rho, double p) const
{
if (rho < 0)
throw std::domain_error("Negative density");
throw Exception("Negative density");

const double T = T_from_rho_p(rho, p);

Expand Down Expand Up @@ -81,7 +81,7 @@ State
Helmholtz::p_T(double p, double T) const
{
if (T < 0)
throw std::domain_error("Negative temperature");
throw Exception("Negative temperature");

const double rho = rho_from_p_T(p, T);

Expand Down Expand Up @@ -112,9 +112,9 @@ State
Helmholtz::v_u(double v, double u) const
{
if (v <= 0.)
throw std::domain_error("Negative specific volume");
throw Exception("Negative specific volume");
if (u <= 0.)

Check warning on line 116 in src/Helmholtz.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

src/Helmholtz.cpp:116:17 [readability-braces-around-statements]

statement should be inside braces
throw std::domain_error("Negative internal energy");
throw Exception("Negative internal energy");

const double rho = 1. / v;
const double delta = rho / this->rho_c;
Expand Down Expand Up @@ -143,7 +143,7 @@ Helmholtz::v_u(double v, double u) const
State
Helmholtz::h_s(double h, double s) const
{
throw std::domain_error("Not implemented");
throw Exception("Not implemented");
}

double
Expand Down
24 changes: 12 additions & 12 deletions src/IdealGas.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "fprops/IdealGas.h"
#include "fprops/Exception.h"
#include <cmath>
#include <stdexcept>

namespace fprops {

Expand Down Expand Up @@ -35,9 +35,9 @@ State
IdealGas::rho_T(double rho, double T) const
{
if (rho < 0)
throw std::domain_error("Negative density");
throw Exception("Negative density");
if (T < 0)

Check warning on line 39 in src/IdealGas.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

src/IdealGas.cpp:39:15 [readability-braces-around-statements]

statement should be inside braces
throw std::domain_error("Negative temperature");
throw Exception("Negative temperature");

State state;
state.rho = rho;
Expand All @@ -51,7 +51,7 @@ IdealGas::rho_T(double rho, double T) const
state.v = 1. / state.rho;
const double n = std::pow(T, this->gamma) / std::pow(state.p, this->gamma - 1.0);
if (n <= 0)
throw std::domain_error("Invalid log base for computing entropy");
throw Exception("Invalid log base for computing entropy");
state.s = this->cv * std::log(n);
state.h = this->cp * T;
state.w = std::sqrt(this->cp * R * T / (this->cv * this->molar_mass));
Expand All @@ -62,7 +62,7 @@ State
IdealGas::rho_p(double rho, double p) const
{
if (rho < 0)
throw std::domain_error("Negative density");
throw Exception("Negative density");

State state;
state.rho = rho;
Expand All @@ -76,7 +76,7 @@ IdealGas::rho_p(double rho, double p) const
state.v = 1. / state.rho;
const double n = std::pow(state.T, this->gamma) / std::pow(state.p, this->gamma - 1.0);
if (n <= 0)
throw std::domain_error("Invalid log base for computing entropy");
throw Exception("Invalid log base for computing entropy");
state.s = this->cv * std::log(n);
state.h = this->cp * state.T;
state.w = std::sqrt(this->cp * R * state.T / (this->cv * this->molar_mass));
Expand All @@ -87,7 +87,7 @@ State
IdealGas::p_T(double p, double T) const
{
if (T < 0)
throw std::domain_error("Negative temperature");
throw Exception("Negative temperature");

State state;
state.p = p;
Expand All @@ -101,7 +101,7 @@ IdealGas::p_T(double p, double T) const
state.v = 1. / state.rho;
const double n = std::pow(T, this->gamma) / std::pow(p, this->gamma - 1.0);
if (n <= 0)
throw std::domain_error("Invalid log base for computing entropy");
throw Exception("Invalid log base for computing entropy");
state.s = this->cv * std::log(n);
state.h = this->cp * T;
state.w = std::sqrt(this->cp * R * T / (this->cv * this->molar_mass));
Expand All @@ -112,9 +112,9 @@ State
IdealGas::v_u(double v, double u) const
{
if (v <= 0.)
throw std::domain_error("Negative specific volume");
throw Exception("Negative specific volume");
if (u <= 0.)

Check warning on line 116 in src/IdealGas.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

src/IdealGas.cpp:116:17 [readability-braces-around-statements]

statement should be inside braces
throw std::domain_error("Negative internal energy");
throw Exception("Negative internal energy");

State state;
state.v = v;
Expand All @@ -128,7 +128,7 @@ IdealGas::v_u(double v, double u) const
state.T = u / this->cv;
const double n = std::pow(state.T, this->gamma) / std::pow(state.p, this->gamma - 1.0);
if (n <= 0)
throw std::domain_error("Invalid log base for computing entropy");
throw Exception("Invalid log base for computing entropy");
state.s = this->cv * std::log(n);
state.h = this->cp * state.T;
state.w = std::sqrt(this->gamma * this->R_specific * state.T);
Expand All @@ -154,7 +154,7 @@ IdealGas::h_s(double h, double s) const
state.v = 1. / state.rho;
const double n = std::pow(state.T, this->gamma) / std::pow(state.p, this->gamma - 1.0);
if (n <= 0)
throw std::domain_error("Invalid log base for computing entropy");
throw Exception("Invalid log base for computing entropy");
state.w = std::sqrt(this->gamma * this->R_specific * state.T);
return state;
}
Expand Down
17 changes: 9 additions & 8 deletions src/InterpolatedFluidProperties.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "fprops/InterpolatedFluidProperties.h"
#include "fprops/Utils.h"
#include "fprops/Numerics.h"
#include "fprops/Exception.h"
#include "h5pp/h5pp.h"
#include "fmt/printf.h"
#include "Eigen/Dense"
Expand Down Expand Up @@ -50,7 +51,7 @@ InterpolatedFluidProperties::load(const std::string & file_name)
this->hs_data = read_data(file, "h_s", { H, S }, { U, V, P, T, RHO, MU, CP, CV, K, W });
}
else
throw std::runtime_error(fmt::format("File '{}' does not exist.", file_name));
throw Exception("File '{}' does not exist.", file_name);
}

State
Expand All @@ -62,7 +63,7 @@ InterpolatedFluidProperties::p_T(double p, double T) const
vals[CP], vals[CV], vals[S], vals[K], vals[H], vals[W] };
}
else
throw std::runtime_error("'p_T' data set is missing.");
throw Exception("'p_T' data set is missing.");
}

State
Expand All @@ -74,7 +75,7 @@ InterpolatedFluidProperties::rho_T(double rho, double T) const
vals[CP], vals[CV], vals[S], vals[K], vals[H], vals[W] };
}
else
throw std::runtime_error("'rho_T' data set is missing.");
throw Exception("'rho_T' data set is missing.");
}

State
Expand All @@ -86,7 +87,7 @@ InterpolatedFluidProperties::rho_p(double rho, double p) const
vals[CP], vals[CV], vals[S], vals[K], vals[H], vals[W] };
}
else
throw std::runtime_error("'rho_p' data set is missing.");
throw Exception("'rho_p' data set is missing.");
}

State
Expand All @@ -98,7 +99,7 @@ InterpolatedFluidProperties::v_u(double v, double u) const
vals[CP], vals[CV], vals[S], vals[K], vals[H], vals[W] };
}
else
throw std::runtime_error("'v_u' data set is missing.");
throw Exception("'v_u' data set is missing.");
}

State
Expand All @@ -110,7 +111,7 @@ InterpolatedFluidProperties::h_s(double h, double s) const
vals[CP], vals[CV], s, vals[K], h, vals[W] };
}
else
throw std::runtime_error("'h_s' data set is missing.");
throw Exception("'h_s' data set is missing.");
}

void
Expand All @@ -120,7 +121,7 @@ InterpolatedFluidProperties::check_unit(const h5pp::File & file,
{
auto attr = file.readAttribute<std::string>(dataset_name, "unit");
if (attr != unit)
throw std::runtime_error(fmt::format("Expected unit '{}' for '{}'.", unit, dataset_name));
throw Exception("Expected unit '{}' for '{}'.", unit, dataset_name);
}

Eigen::VectorXd
Expand All @@ -133,7 +134,7 @@ InterpolatedFluidProperties::read_var_range(const h5pp::File & file,
check_unit(file, nm, this->var_units[var_idx]);
file.readDataset(range, nm);
if (range.size() < 2)
throw std::runtime_error(
throw Exception(
fmt::format("'{}' range must have 2 or more grid points.", this->var_names[var_idx]));
return range;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Numerics.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "fprops/Numerics.h"
#include "fprops/Exception.h"
#include <cmath>
#include <stdexcept>

namespace fprops {

Expand Down Expand Up @@ -29,7 +29,7 @@ root(double x0,
x0 = x1;
}

throw std::runtime_error("Newton's method failed to converge");
throw Exception("Newton's method failed to converge");
}

} // namespace newton
Expand Down
28 changes: 28 additions & 0 deletions test/src/ExceptionTestMacros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include "fprops/Exception.h"

/// Test that the `cmd` will throw `fprops::Exception` with message `msg`
#define EXPECT_THROW_MSG(cmd, msg) \

Check warning on line 6 in test/src/ExceptionTestMacros.h

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/ExceptionTestMacros.h:6:9 [cppcoreguidelines-macro-usage]

function-like macro 'EXPECT_THROW_MSG' used; consider a 'constexpr' template function
try { \
cmd; \
FAIL(); \
} \
catch (Exception & e) { \
EXPECT_STREQ(e.what(), msg); \
} \
catch (...) { \
FAIL(); \
}

#define EXPECT_THAT_THROW_MSG(cmd, matcher) \

Check warning on line 18 in test/src/ExceptionTestMacros.h

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/ExceptionTestMacros.h:18:9 [cppcoreguidelines-macro-usage]

function-like macro 'EXPECT_THAT_THROW_MSG' used; consider a 'constexpr' template function
try { \
cmd; \
FAIL(); \
} \
catch (Exception & e) { \
EXPECT_THAT(e.what(), matcher); \
} \
catch (...) { \
FAIL(); \
}
3 changes: 2 additions & 1 deletion test/src/Helium_test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "gtest/gtest.h"
#include "ExceptionTestMacros.h"
#include "fprops/Helium.h"

using namespace fprops;
Expand Down Expand Up @@ -95,7 +96,7 @@ TEST(HeliumTest, v_u)
double p = 1.0e6;
auto state0 = fp.p_T(p, T);

EXPECT_THROW(auto f = fp.v_u(state0.v, state0.u), std::runtime_error);
EXPECT_THROW_MSG(auto f = fp.v_u(state0.v, state0.u), "Newton's method failed to converge");

Check warning on line 99 in test/src/Helium_test.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/Helium_test.cpp:99:27 [readability-identifier-length]

variable name 'f' is too short, expected at least 3 characters
/*
State state = fp.v_u(state0.v, state0.u);
Expand Down
15 changes: 8 additions & 7 deletions test/src/Helmholtz_test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "gmock/gmock.h"
#include "ExceptionTestMacros.h"
#include "fprops/Helmholtz.h"

using namespace fprops;
Expand Down Expand Up @@ -26,37 +27,37 @@ TEST(HelmholtzTest, rho_T_incorrect)
{
MockHelmholtz fp;

EXPECT_THROW(auto p = fp.rho_T(-1, 300), std::domain_error);
EXPECT_THROW(auto p = fp.rho_T(1, -1), std::domain_error);
EXPECT_THROW_MSG(auto p = fp.rho_T(-1, 300), "Negative density");

Check warning on line 30 in test/src/Helmholtz_test.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/Helmholtz_test.cpp:30:27 [readability-identifier-length]

variable name 'p' is too short, expected at least 3 characters
EXPECT_THROW_MSG(auto p = fp.rho_T(1, -1), "Negative temperature");

Check warning on line 31 in test/src/Helmholtz_test.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/Helmholtz_test.cpp:31:27 [readability-identifier-length]

variable name 'p' is too short, expected at least 3 characters
}

TEST(HelmholtzTest, rho_p_incorrect)
{
MockHelmholtz fp;

EXPECT_THROW(auto p = fp.rho_p(-1, 300), std::domain_error);
EXPECT_THROW_MSG(auto p = fp.rho_p(-1, 300), "Negative density");

Check warning on line 38 in test/src/Helmholtz_test.cpp

View workflow job for this annotation

GitHub Actions / c++ linter

test/src/Helmholtz_test.cpp:38:27 [readability-identifier-length]

variable name 'p' is too short, expected at least 3 characters
}

TEST(HelmholtzTest, h_s)
{
MockHelmholtz fp;

EXPECT_THROW(auto p = fp.h_s(1, 1), std::domain_error);
EXPECT_THROW_MSG(auto p = fp.h_s(1, 1), "Not implemented");
}

TEST(HelmholtzTest, p_T_incorrect)
{
MockHelmholtz fp;

EXPECT_THROW(auto p = fp.p_T(1e5, -1), std::domain_error);
EXPECT_THROW_MSG(auto p = fp.p_T(1e5, -1), "Negative temperature");
}

TEST(HelmholtzTest, v_u_incorrect)
{
MockHelmholtz fp;

EXPECT_THROW(auto p = fp.v_u(-1, 1), std::domain_error);
EXPECT_THROW(auto p = fp.v_u(1, -1), std::domain_error);
EXPECT_THROW_MSG(auto st = fp.v_u(-1, 1), "Negative specific volume");
EXPECT_THROW_MSG(auto st = fp.v_u(1, -1), "Negative internal energy");
}

TEST(HelmholtzTest, ideal_gas_lead)
Expand Down
Loading

0 comments on commit 4d99b75

Please sign in to comment.