rdf-ex/test/support/rdf_datatype_case.ex

184 lines
6.5 KiB
Elixir

defmodule RDF.Datatype.Test.Case do
use ExUnit.CaseTemplate
use RDF.Vocabulary.Namespace
defvocab EX,
base_iri: "http://example.com/",
terms: [], strict: false
alias RDF.{Literal, Datatype}
def dt(value) do
RDF.DateTime.convert(value, %{})
end
using(opts) do
datatype = Keyword.fetch!(opts, :datatype)
datatype_id = Keyword.fetch!(opts, :id)
valid = Keyword.get(opts, :valid)
invalid = Keyword.get(opts, :invalid)
allow_language = Keyword.get(opts, :allow_language, false)
quote do
alias RDF.{Literal, Datatype}
alias RDF.NS.XSD
alias unquote(datatype)
alias unquote(__MODULE__).EX
import unquote(__MODULE__)
doctest unquote(datatype)
@moduletag datatype: unquote(datatype)
if unquote(valid) do
@valid unquote(valid)
@invalid unquote(invalid)
test "RDF.Datatype mapping" do
assert RDF.Datatype.mapping[unquote(datatype_id)] == unquote(datatype)
end
describe "general new" do
Enum.each @valid, fn {input, {value, lexical, _}} ->
expected_literal =
%Literal{value: value, uncanonical_lexical: lexical, datatype: unquote(datatype_id), language: nil}
@tag example: %{input: input, output: expected_literal}
test "valid: #{unquote(datatype)}.new(#{inspect input})",
%{example: example} do
assert unquote(datatype).new(example.input) == example.output
end
end
Enum.each @invalid, fn value ->
expected_literal =
%Literal{uncanonical_lexical: to_string(value), datatype: unquote(datatype_id), language: nil}
@tag example: %{input: value, output: expected_literal}
test "invalid: #{unquote(datatype)}.new(#{inspect value})",
%{example: example} do
assert unquote(datatype).new(example.input) == example.output
end
end
test "canonicalize option" do
Enum.each @valid, fn {input, _} ->
assert unquote(datatype).new(input, canonicalize: true) ==
(unquote(datatype).new(input) |> Literal.canonical)
end
Enum.each @invalid, fn input ->
assert unquote(datatype).new(input, canonicalize: true) ==
(unquote(datatype).new(input) |> Literal.canonical)
end
end
test "datatype option is ignored" do
Enum.each Datatype.ids, fn id ->
Enum.each @valid, fn {input, _} ->
assert unquote(datatype).new(input, datatype: id) == unquote(datatype).new(input)
end
end
end
unless unquote(allow_language) do
test "language option is ignored" do
Enum.each @valid, fn {input, _} ->
assert unquote(datatype).new(input, language: "en") == unquote(datatype).new(input)
end
end
end
end
describe "general new!" do
test "with valid values, it behaves the same as new" do
Enum.each @valid, fn {input, _} ->
assert unquote(datatype).new!(input) == unquote(datatype).new(input)
assert unquote(datatype).new!(input, datatype: unquote(datatype_id)) == unquote(datatype).new(input)
assert unquote(datatype).new!(input, canonicalize: true) == unquote(datatype).new(input, canonicalize: true)
end
end
test "with invalid values, it raises an error" do
Enum.each @invalid, fn value ->
assert_raise ArgumentError, fn -> unquote(datatype).new!(value) end
assert_raise ArgumentError, fn -> unquote(datatype).new!(value, canonicalize: true) end
end
end
end
describe "general lexical" do
Enum.each @valid, fn {input, {_, lexical, canonicalized}} ->
lexical = lexical || canonicalized
@tag example: %{input: input, lexical: lexical}
test "of valid #{unquote(datatype)}.new(#{inspect input})",
%{example: example} do
assert (unquote(datatype).new(example.input) |> Literal.lexical) == example.lexical
end
end
Enum.each @invalid, fn value ->
lexical = to_string(value)
@tag example: %{input: value, lexical: lexical}
test "of invalid #{unquote(datatype)}.new(#{inspect value}) == #{inspect lexical}",
%{example: example} do
assert (unquote(datatype).new(example.input) |> Literal.lexical) == example.lexical
end
end
end
describe "general canonicalization" do
Enum.each @valid, fn {input, {value, _, _}} ->
expected_literal = %Literal{value: value, datatype: unquote(datatype_id)}
@tag example: %{input: input, output: expected_literal}
test "#{unquote(datatype)} #{inspect input}",
%{example: example} do
assert (unquote(datatype).new(example.input) |> Literal.canonical) == example.output
end
end
Enum.each @valid, fn {input, {_, _, canonicalized}} ->
@tag example: %{input: input, canonicalized: canonicalized}
test "lexical of canonicalized #{unquote(datatype)} #{inspect input, limit: 9} is #{inspect canonicalized}",
%{example: example} do
assert (unquote(datatype).new(example.input) |> Literal.canonical |> Literal.lexical) ==
example.canonicalized
end
end
test "does not change the Literal when it is invalid" do
Enum.each @invalid, fn value ->
assert (unquote(datatype).new(value) |> Literal.canonical) == unquote(datatype).new(value)
end
end
end
describe "general validation" do
Enum.each Map.keys(@valid), fn value ->
@tag value: value
test "#{inspect value} as a #{unquote(datatype)} is valid", %{value: value} do
assert Literal.valid? unquote(datatype).new(value)
end
end
Enum.each @invalid, fn value ->
@tag value: value
test "#{inspect value} as a #{unquote(datatype)} is invalid", %{value: value} do
refute Literal.valid? unquote(datatype).new(value)
end
end
end
end
end
end
end