diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ff367c..0a5ccab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## v3.0.0-rc.4 + +### Fixed + +- A runtime arithmetic fault during evaluation, division by zero being the + canonical case, now surfaces as an `Expression.Error` instead of crashing the + caller. `evaluate_block!/4` and `evaluate!/4` already reraised a `RuntimeError` + this way (how a non-numeric operand surfaces); `ArithmeticError` was simply the + missing case. + ## v3.0.0-rc.3 ### Fixed diff --git a/lib/expression.ex b/lib/expression.ex index e50ea59..0a333eb 100644 --- a/lib/expression.ex +++ b/lib/expression.ex @@ -169,9 +169,9 @@ defmodule Expression do e in Expression.Error -> reraise e, __STACKTRACE__ - e in RuntimeError -> + e in [RuntimeError, ArithmeticError] -> reraise Expression.Error, - [type: :eval, message: e.message, expression: expression], + [type: :eval, message: Exception.message(e), expression: expression], __STACKTRACE__ end @@ -192,9 +192,9 @@ defmodule Expression do e in Expression.Error -> reraise e, __STACKTRACE__ - e in RuntimeError -> + e in [RuntimeError, ArithmeticError] -> reraise Expression.Error, - [type: :eval, message: e.message, expression: expression], + [type: :eval, message: Exception.message(e), expression: expression], __STACKTRACE__ end diff --git a/mix.exs b/mix.exs index 4e9015c..85a0c50 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Expression.MixProject do use Mix.Project - @version "3.0.0-rc.3" + @version "3.0.0-rc.4" def project do [ diff --git a/test/expression_test.exs b/test/expression_test.exs index eb0765e..a9fd15c 100644 --- a/test/expression_test.exs +++ b/test/expression_test.exs @@ -190,6 +190,10 @@ defmodule ExpressionTest do assert_raise Expression.Error, "expression is not a number: `\"NaN\"`", fn -> Expression.evaluate_as_boolean!("@(\"NaN\" * 0.2 == 0.02)") end + + assert_raise Expression.Error, "bad argument in arithmetic expression", fn -> + Expression.evaluate_as_boolean!("@(1 / 0 == 2)") + end end test "list with indices" do @@ -725,6 +729,17 @@ defmodule ExpressionTest do end end + test "a division by zero returns an error tuple instead of crashing" do + assert {:error, %Expression.Error{message: "bad argument in arithmetic expression"}} = + Expression.evaluate_block("score / total", %{"score" => 10, "total" => 0}) + end + + test "a division by zero raises Expression.Error from the bang variant" do + assert_raise Expression.Error, "bad argument in arithmetic expression", fn -> + Expression.evaluate_block!("score / total", %{"score" => 10, "total" => 0}) + end + end + test "fixed/2 with a numeric string still formats the number" do assert {:ok, "4.21"} == Expression.evaluate_block("fixed(value, 2)", %{"value" => "4.209"}) end