Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation type to NimbleOptions.ValidationError #134

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions lib/nimble_options.ex
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,8 @@ defmodule NimbleOptions do
end
end

defp validate_type(:integer, key, value, redact) when not is_integer(value) do
structured_error_tuple(key, value, "integer", redact)
defp validate_type(:integer = type, key, value, redact) when not is_integer(value) do
structured_error_tuple(key, value, {:type, type}, "integer", redact)
end

defp validate_type(:non_neg_integer, key, value, redact)
Expand Down Expand Up @@ -1019,19 +1019,31 @@ defmodule NimbleOptions do
{:error, %ValidationError{key: key, message: message, redact: redact, value: value}}
end

# FIX: remove after error types are implemented
defp structured_error_tuple(key, value, expected, redact?) do
structured_error_tuple(key, value, expected, inspect(value), redact?)
structured_error_tuple(key, value, false, expected, redact?)
end

defp structured_error_tuple(key, value, expected, got, redact?) do
defp structured_error_tuple(key, value, type, expected, redact?) do
structured_error_tuple(key, value, type, expected, inspect(value), redact?)
end

defp structured_error_tuple(key, value, validation, expected, got, redact?) do
message =
if redact? do
"invalid value for #{render_key(key)}: expected #{expected}"
else
"invalid value for #{render_key(key)}: expected #{expected}, got: #{got}"
end

{:error, %ValidationError{key: key, message: message, redact: redact?, value: value}}
{:error,
%ValidationError{
key: key,
message: message,
redact: redact?,
value: value,
validation: validation
}}
end

defp render_key({__MODULE__, :key}), do: "map key"
Expand Down
5 changes: 4 additions & 1 deletion lib/nimble_options/validation_error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule NimbleOptions.ValidationError do
key: atom(),
keys_path: [atom()],
redact: boolean,
validation: :required | {:type, term()},
value: term()
}

Expand All @@ -28,8 +29,10 @@ defmodule NimbleOptions.ValidationError do
* `:value` (`t:term/0`) - The value that failed to validate. This field is `nil` if there
was no value provided.

* `:validation` (`:required` or `{:type, type}`) - The validation that failed.

"""
defexception [:message, :key, :value, keys_path: [], redact: false]
defexception [:message, :key, :validation, :value, keys_path: [], redact: false]

@impl true
def message(%__MODULE__{message: message, keys_path: keys_path}) do
Expand Down
5 changes: 4 additions & 1 deletion test/nimble_options_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
}
end

test "is redacted" do

Check failure on line 136 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test default value is redacted (NimbleOptionsTest)
schema = [
processors: [
type: :keyword_list,
Expand Down Expand Up @@ -264,7 +264,7 @@
}}
end

test "redacted invalid positive integer" do

Check failure on line 267 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation redacted invalid positive integer (NimbleOptionsTest)
schema = [stages: [type: :pos_integer, redact: true]]

assert NimbleOptions.validate([stages: 0], schema) ==
Expand Down Expand Up @@ -292,6 +292,7 @@
%ValidationError{
key: :min_demand,
value: 1.5,
validation: {:type, :integer},
message: "invalid value for :min_demand option: expected integer, got: 1.5"
}}

Expand All @@ -300,6 +301,7 @@
%ValidationError{
key: :min_demand,
value: :an_atom,
validation: {:type, :integer},
message: "invalid value for :min_demand option: expected integer, got: :an_atom"
}}
end
Expand All @@ -312,6 +314,7 @@
%ValidationError{
key: :min_demand,
value: 1.5,
validation: {:type, :integer},
message: "invalid value for :min_demand option: expected integer",
redact: true
}}
Expand All @@ -324,7 +327,7 @@
assert NimbleOptions.validate(opts, schema) == {:ok, opts}
end

test "invalid non negative integer" do

Check failure on line 330 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation invalid non negative integer (NimbleOptionsTest)
schema = [min_demand: [type: :non_neg_integer]]

assert NimbleOptions.validate([min_demand: -1], schema) ==
Expand All @@ -346,7 +349,7 @@
}}
end

test "redacted invalid non negative integer" do

Check failure on line 352 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation redacted invalid non negative integer (NimbleOptionsTest)
schema = [min_demand: [type: :non_neg_integer, redact: true]]

assert NimbleOptions.validate([min_demand: -1], schema) ==
Expand Down Expand Up @@ -386,7 +389,7 @@
}}
end

test "redacted invalid float" do

Check failure on line 392 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation redacted invalid float (NimbleOptionsTest)
schema = [certainty: [type: :float, redact: true]]

assert NimbleOptions.validate([certainty: 1], schema) ==
Expand Down Expand Up @@ -495,7 +498,7 @@
assert NimbleOptions.validate(opts, schema) == {:ok, opts}
end

test "invalid timeout" do

Check failure on line 501 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation invalid timeout (NimbleOptionsTest)
schema = [timeout: [type: :timeout]]

opts = [timeout: -1]
Expand Down Expand Up @@ -574,7 +577,7 @@
assert NimbleOptions.validate(opts, schema) == {:ok, opts}
end

test "invalid reference" do

Check failure on line 580 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation invalid reference (NimbleOptionsTest)
schema = [name: [type: :reference]]

assert NimbleOptions.validate([name: 1], schema) ==
Expand All @@ -586,7 +589,7 @@
}}
end

test "redacted invalid reference" do

Check failure on line 592 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation redacted invalid reference (NimbleOptionsTest)
schema = [name: [type: :reference, redact: true]]

assert NimbleOptions.validate([name: 1], schema) ==
Expand All @@ -609,7 +612,7 @@
assert NimbleOptions.validate(opts, schema) == {:ok, opts}
end

test "invalid mfa" do

Check failure on line 615 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation invalid mfa (NimbleOptionsTest)
schema = [transformer: [type: :mfa]]

opts = [transformer: {"not_a_module", :func, []}]
Expand Down Expand Up @@ -742,7 +745,7 @@
assert NimbleOptions.validate(opts, schema) == {:ok, opts}
end

test "invalid {:fun, arity}" do

Check failure on line 748 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation invalid {:fun, arity} (NimbleOptionsTest)
schema = [partition_by: [type: {:fun, 1}]]

opts = [partition_by: :not_a_fun]
Expand Down Expand Up @@ -770,7 +773,7 @@
}
end

test "redacted invalid {:fun, arity}" do

Check failure on line 776 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation redacted invalid {:fun, arity} (NimbleOptionsTest)
schema = [partition_by: [type: {:fun, 1}, redact: true]]

opts = [partition_by: :not_a_fun]
Expand Down Expand Up @@ -819,7 +822,7 @@
}}
end

test "redacted invalid nil" do

Check failure on line 825 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation redacted invalid nil (NimbleOptionsTest)
schema = [name: [type: nil, required: true, redact: true]]
opts = [name: :not_nil]

Expand Down Expand Up @@ -1760,7 +1763,7 @@
)
end

test "redacted invalid {:struct, struct_name}" do

Check failure on line 1766 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test type validation redacted invalid {:struct, struct_name} (NimbleOptionsTest)

Check failure on line 1766 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test type validation redacted invalid {:struct, struct_name} (NimbleOptionsTest)
schema = [struct: [type: {:struct, URI}, redact: true]]

opts = [struct: %NimbleOptions{}]
Expand Down Expand Up @@ -1905,7 +1908,7 @@
end

for type <- [:keyword_list, :map] do
test "nested options types for #{type}" do

Check failure on line 1911 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.9.4, 20.3.8)

test nested options with predefined keys nested options types for map (NimbleOptionsTest)
schema = [
processors: [
type: unquote(type),
Expand Down Expand Up @@ -2218,7 +2221,7 @@

describe "nested options show up in error messages" do
for type <- [:keyword_list, :map] do
test "for options that we validate for #{type}" do

Check failure on line 2224 in test/nimble_options_test.exs

View workflow job for this annotation

GitHub Actions / test (1.17, 27.0, lint, true)

test nested options show up in error messages for options that we validate for map (NimbleOptionsTest)
schema = [
socket_options: [
type: unquote(type),
Expand Down Expand Up @@ -2250,7 +2253,7 @@
end

# No other test is passing in `opts` as a map, so these are just some white box tests for sanity checking
describe "can use a map for validate/2" do
test "can use a map for validate/2" do
schema = []
opts = %{}
assert NimbleOptions.validate(opts, schema) == {:ok, %{}}
Expand Down
Loading