Add RDF.Term.equal?/2 and RDF.Term.equal_value?/2
This commit is contained in:
parent
389dec6c6b
commit
d838424478
11 changed files with 383 additions and 10 deletions
|
@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
|
||||||
- `RDF.Numeric` with a list of all numeric datatypes
|
- `RDF.Numeric` with a list of all numeric datatypes
|
||||||
- the logical operators and the Effective Boolean Value (EBV) coercion algorithm
|
- the logical operators and the Effective Boolean Value (EBV) coercion algorithm
|
||||||
from the XPath and SPARQL specs on `RDF.Boolean`
|
from the XPath and SPARQL specs on `RDF.Boolean`
|
||||||
|
- `RDF.Term.equal?/2` and `RDF.Term.equal_value?/2`
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -36,6 +36,20 @@ defmodule RDF.BlankNode do
|
||||||
do: id |> to_string |> new
|
do: id |> to_string |> new
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tests for value equality of blank nodes.
|
||||||
|
|
||||||
|
Returns `nil` when the given arguments are not comparable as blank nodes.
|
||||||
|
"""
|
||||||
|
def equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(%RDF.BlankNode{id: left}, %RDF.BlankNode{id: right}),
|
||||||
|
do: left == right
|
||||||
|
|
||||||
|
def equal_value?(_, _),
|
||||||
|
do: nil
|
||||||
|
|
||||||
|
|
||||||
defimpl String.Chars do
|
defimpl String.Chars do
|
||||||
def to_string(%RDF.BlankNode{id: id}), do: "_:#{id}"
|
def to_string(%RDF.BlankNode{id: id}), do: "_:#{id}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -56,6 +56,16 @@ defmodule RDF.Datatype do
|
||||||
"""
|
"""
|
||||||
@callback valid?(literal :: RDF.Literal.t) :: boolean
|
@callback valid?(literal :: RDF.Literal.t) :: boolean
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Checks if the value of two `RDF.Literal`s of this datatype are equal.
|
||||||
|
|
||||||
|
Returns `nil` when the given arguments are not comparable as literals of this datatype.
|
||||||
|
|
||||||
|
The default implementation of the `_using__` macro compares the values of the
|
||||||
|
`canonical/1` forms of the given literals of this datatype.
|
||||||
|
"""
|
||||||
|
@callback equal_value?(literal1 :: RDF.Literal.t, literal2 :: RDF.Literal.t) :: boolean | nil
|
||||||
|
|
||||||
|
|
||||||
@lang_string RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString")
|
@lang_string RDF.iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#langString")
|
||||||
|
|
||||||
|
@ -183,6 +193,12 @@ defmodule RDF.Datatype do
|
||||||
def valid?(_), do: false
|
def valid?(_), do: false
|
||||||
|
|
||||||
|
|
||||||
|
def equal_value?(%Literal{datatype: @id} = literal1, %Literal{datatype: @id} = literal2) do
|
||||||
|
canonical(literal1).value == canonical(literal2).value
|
||||||
|
end
|
||||||
|
|
||||||
|
def equal_value?(_, _), do: nil
|
||||||
|
|
||||||
defoverridable [
|
defoverridable [
|
||||||
build_literal_by_value: 2,
|
build_literal_by_value: 2,
|
||||||
build_literal_by_lexical: 2,
|
build_literal_by_lexical: 2,
|
||||||
|
@ -192,6 +208,7 @@ defmodule RDF.Datatype do
|
||||||
invalid_lexical: 1,
|
invalid_lexical: 1,
|
||||||
convert: 2,
|
convert: 2,
|
||||||
valid?: 1,
|
valid?: 1,
|
||||||
|
equal_value?: 2,
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule RDF.Datatype.NS do
|
defmodule RDF.Datatype.NS do
|
||||||
@moduledoc false
|
@moduledoc !"""
|
||||||
|
Since the capability of RDF.Vocabulary.Namespaces requires the compilation
|
||||||
# Since the capability of RDF.Vocabulary.Namespaces requires the compilation
|
of the RDF.NTriples.Decoder and the RDF.NTriples.Decoder depends on RDF.Literals,
|
||||||
# of the RDF.NTriples.Decoder and the RDF.NTriples.Decoder depends on RDF.Literals,
|
we can't define the XSD namespace in RDF.NS.
|
||||||
# we can't define the XSD namespace in RDF.NS.
|
"""
|
||||||
|
|
||||||
use RDF.Vocabulary.Namespace
|
use RDF.Vocabulary.Namespace
|
||||||
|
|
||||||
|
|
|
@ -82,4 +82,7 @@ defmodule RDF.Double do
|
||||||
"#{i}.#{f}E#{e}"
|
"#{i}.#{f}E#{e}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def equal_value?(left, right), do: RDF.Numeric.equal_value?(left, right)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,5 +18,6 @@ defmodule RDF.Integer do
|
||||||
|
|
||||||
def convert(value, opts), do: super(value, opts)
|
def convert(value, opts), do: super(value, opts)
|
||||||
|
|
||||||
|
def equal_value?(left, right), do: RDF.Numeric.equal_value?(left, right)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,10 @@ defmodule RDF.Numeric do
|
||||||
The set of all numeric datatypes.
|
The set of all numeric datatypes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
alias RDF.Literal
|
||||||
alias RDF.Datatype.NS.XSD
|
alias RDF.Datatype.NS.XSD
|
||||||
|
|
||||||
@types [
|
@types MapSet.new [
|
||||||
XSD.integer,
|
XSD.integer,
|
||||||
XSD.decimal,
|
XSD.decimal,
|
||||||
XSD.float,
|
XSD.float,
|
||||||
|
@ -27,11 +28,38 @@ defmodule RDF.Numeric do
|
||||||
@doc """
|
@doc """
|
||||||
The list of all numeric datatypes.
|
The list of all numeric datatypes.
|
||||||
"""
|
"""
|
||||||
def types(), do: @types
|
def types(), do: MapSet.to_list(@types)
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns if a given datatype is numeric.
|
Returns if a given datatype is a numeric datatype.
|
||||||
"""
|
"""
|
||||||
def type?(type), do: type in @types
|
def type?(type), do: MapSet.member?(@types, type)
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tests for numeric value equality of two numeric literals.
|
||||||
|
|
||||||
|
Returns `nil` when the given arguments are not comparable as numeric literals.
|
||||||
|
|
||||||
|
see:
|
||||||
|
|
||||||
|
- <https://www.w3.org/TR/sparql11-query/#OperatorMapping>
|
||||||
|
- <https://www.w3.org/TR/xpath-functions/#func-numeric-equal>
|
||||||
|
"""
|
||||||
|
def equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(%Literal{datatype: left_datatype} = left,
|
||||||
|
%Literal{datatype: right_datatype} = right) do
|
||||||
|
if type?(left_datatype) and type?(right_datatype) do
|
||||||
|
# We rely here on Elixirs numeric equality comparison.
|
||||||
|
# TODO: There are probably problematic edge-case, which might require an
|
||||||
|
# TODO: implementation of XPath type promotion and subtype substitution
|
||||||
|
# - https://www.w3.org/TR/xpath-functions/#op.numeric
|
||||||
|
# - https://www.w3.org/TR/xpath20/#id-type-promotion-and-operator-mapping
|
||||||
|
Literal.canonical(left).value == Literal.canonical(right).value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def equal_value?(_, _), do: nil
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -186,6 +186,30 @@ defmodule RDF.IRI do
|
||||||
def parse(%URI{} = uri), do: uri
|
def parse(%URI{} = uri), do: uri
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tests for value equality of IRIs.
|
||||||
|
|
||||||
|
Returns `nil` when the given arguments are not comparable as IRIs.
|
||||||
|
|
||||||
|
see <https://www.w3.org/TR/rdf-concepts/#section-Graph-URIref>
|
||||||
|
"""
|
||||||
|
def equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(%RDF.IRI{value: left}, %RDF.IRI{value: right}),
|
||||||
|
do: left == right
|
||||||
|
|
||||||
|
@xsd_any_uri "http://www.w3.org/2001/XMLSchema#anyURI"
|
||||||
|
|
||||||
|
def equal_value?(%RDF.Literal{datatype: %RDF.IRI{value: @xsd_any_uri}, value: left}, right),
|
||||||
|
do: equal_value?(new(left), right)
|
||||||
|
|
||||||
|
def equal_value?(left, %RDF.Literal{datatype: %RDF.IRI{value: @xsd_any_uri}, value: right}),
|
||||||
|
do: equal_value?(left, new(right))
|
||||||
|
|
||||||
|
def equal_value?(_, _),
|
||||||
|
do: nil
|
||||||
|
|
||||||
|
|
||||||
defimpl String.Chars do
|
defimpl String.Chars do
|
||||||
def to_string(%RDF.IRI{value: value}) do
|
def to_string(%RDF.IRI{value: value}) do
|
||||||
value
|
value
|
||||||
|
|
|
@ -128,7 +128,7 @@ defmodule RDF.Literal do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the given literal with the canonical lexical representation according to its datatype.
|
Returns the lexical representation of the given literal according to its datatype.
|
||||||
"""
|
"""
|
||||||
def lexical(%RDF.Literal{value: value, uncanonical_lexical: nil, datatype: id} = literal) do
|
def lexical(%RDF.Literal{value: value, uncanonical_lexical: nil, datatype: id} = literal) do
|
||||||
case RDF.Datatype.get(id) do
|
case RDF.Datatype.get(id) do
|
||||||
|
@ -215,6 +215,38 @@ defmodule RDF.Literal do
|
||||||
|
|
||||||
def typed?(literal), do: not plain?(literal)
|
def typed?(literal), do: not plain?(literal)
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Checks if two `RDF.Literal`s of this datatype are equal.
|
||||||
|
|
||||||
|
Returns `nil` when the given arguments are not comparable as Literals.
|
||||||
|
|
||||||
|
see <https://www.w3.org/TR/rdf-concepts/#section-Literal-Equality>
|
||||||
|
"""
|
||||||
|
def equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(%RDF.Literal{datatype: id1} = literal1, %RDF.Literal{datatype: id2} = literal2) do
|
||||||
|
case RDF.Datatype.get(id1) do
|
||||||
|
nil ->
|
||||||
|
if id1 == id2 do
|
||||||
|
literal1.value == literal2.value
|
||||||
|
end
|
||||||
|
datatype ->
|
||||||
|
datatype.equal_value?(literal1, literal2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: Handle AnyURI in its own RDF.Datatype implementation
|
||||||
|
@xsd_any_uri "http://www.w3.org/2001/XMLSchema#anyURI"
|
||||||
|
|
||||||
|
def equal_value?(%RDF.Literal{datatype: %RDF.IRI{value: @xsd_any_uri}} = left, right),
|
||||||
|
do: RDF.IRI.equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(left, %RDF.Literal{datatype: %RDF.IRI{value: @xsd_any_uri}} = right),
|
||||||
|
do: RDF.IRI.equal_value?(left, right)
|
||||||
|
|
||||||
|
def equal_value?(_, _), do: nil
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl String.Chars, for: RDF.Literal do
|
defimpl String.Chars, for: RDF.Literal do
|
||||||
|
|
55
lib/rdf/term.ex
Normal file
55
lib/rdf/term.ex
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
defprotocol RDF.Term do
|
||||||
|
@moduledoc """
|
||||||
|
Shared behaviour for all RDF terms.
|
||||||
|
|
||||||
|
A `RDF.Term` is anything which can be an element of RDF statements of a RDF graph:
|
||||||
|
|
||||||
|
- `RDF.IRI`s
|
||||||
|
- `RDF.BlankNode`s
|
||||||
|
- `RDF.Literal`s
|
||||||
|
|
||||||
|
see <https://www.w3.org/TR/sparql11-query/#defn_RDFTerm>
|
||||||
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tests for term equality.
|
||||||
|
|
||||||
|
see <http://www.w3.org/TR/rdf-sparql-query/#func-sameTerm>
|
||||||
|
"""
|
||||||
|
@fallback_to_any true
|
||||||
|
def equal?(term1, term2)
|
||||||
|
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tests for equality of values.
|
||||||
|
|
||||||
|
Returns `nil` if the given terms are not comparable.
|
||||||
|
|
||||||
|
see <http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal>
|
||||||
|
and the value equality semantics of the different literal datatypes here:
|
||||||
|
<https://www.w3.org/TR/sparql11-query/#OperatorMapping>
|
||||||
|
"""
|
||||||
|
@fallback_to_any true
|
||||||
|
def equal_value?(term1, term2)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
defimpl RDF.Term, for: RDF.IRI do
|
||||||
|
def equal?(term1, term2), do: term1 == term2
|
||||||
|
def equal_value?(term1, term2), do: RDF.IRI.equal_value?(term1, term2)
|
||||||
|
end
|
||||||
|
|
||||||
|
defimpl RDF.Term, for: RDF.BlankNode do
|
||||||
|
def equal?(term1, term2), do: term1 == term2
|
||||||
|
def equal_value?(term1, term2), do: RDF.BlankNode.equal_value?(term1, term2)
|
||||||
|
end
|
||||||
|
|
||||||
|
defimpl RDF.Term, for: RDF.Literal do
|
||||||
|
def equal?(term1, term2), do: term1 == term2
|
||||||
|
def equal_value?(term1, term2), do: RDF.Literal.equal_value?(term1, term2)
|
||||||
|
end
|
||||||
|
|
||||||
|
defimpl RDF.Term, for: Any do
|
||||||
|
def equal?(term1, term2), do: term1 == term2
|
||||||
|
def equal_value?(_, _), do: nil
|
||||||
|
end
|
198
test/unit/equality_test.exs
Normal file
198
test/unit/equality_test.exs
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
defmodule RDF.EqualityTest do
|
||||||
|
use RDF.Test.Case
|
||||||
|
|
||||||
|
alias RDF.NS.XSD
|
||||||
|
|
||||||
|
|
||||||
|
describe "RDF.IRI" do
|
||||||
|
@term_equal_iris [
|
||||||
|
{RDF.iri("http://example.com/"), RDF.iri("http://example.com/")},
|
||||||
|
]
|
||||||
|
@term_unequal_iris [
|
||||||
|
{RDF.iri("http://example.com/foo"), RDF.iri("http://example.com/bar")},
|
||||||
|
]
|
||||||
|
@value_equal_iris [
|
||||||
|
{RDF.iri("http://example.com/"),
|
||||||
|
RDF.literal("http://example.com/", datatype: XSD.anyURI)},
|
||||||
|
|
||||||
|
{RDF.literal("http://example.com/", datatype: XSD.anyURI),
|
||||||
|
RDF.iri("http://example.com/")},
|
||||||
|
|
||||||
|
{RDF.literal("http://example.com/", datatype: XSD.anyURI),
|
||||||
|
RDF.literal("http://example.com/", datatype: XSD.anyURI)},
|
||||||
|
]
|
||||||
|
@value_unequal_iris [
|
||||||
|
{RDF.iri("http://example.com/foo"),
|
||||||
|
RDF.literal("http://example.com/bar", datatype: XSD.anyURI)},
|
||||||
|
]
|
||||||
|
@incomparable_iris [
|
||||||
|
{RDF.iri("http://example.com/"), RDF.string("http://example.com/")},
|
||||||
|
]
|
||||||
|
|
||||||
|
test "term equality", do: assert_term_equal @term_equal_iris
|
||||||
|
test "term inequality", do: assert_term_unequal @term_unequal_iris
|
||||||
|
test "value equality", do: assert_value_equal @value_equal_iris
|
||||||
|
test "value inequality", do: assert_value_unequal @value_unequal_iris
|
||||||
|
test "incomparability", do: assert_incomparable @incomparable_iris
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "RDF.BlankNode" do
|
||||||
|
@term_equal_bnodes [
|
||||||
|
{RDF.bnode("foo"), RDF.bnode("foo")},
|
||||||
|
]
|
||||||
|
@term_unequal_bnodes [
|
||||||
|
{RDF.bnode("foo"), RDF.bnode("bar")},
|
||||||
|
]
|
||||||
|
@value_equal_bnodes [
|
||||||
|
]
|
||||||
|
@value_unequal_bnodes [
|
||||||
|
]
|
||||||
|
@incomparable_bnodes [
|
||||||
|
{RDF.bnode("foo"), RDF.string("foo")},
|
||||||
|
{RDF.string("foo"), RDF.bnode("foo")},
|
||||||
|
]
|
||||||
|
|
||||||
|
test "term equality", do: assert_term_equal @term_equal_bnodes
|
||||||
|
test "term inequality", do: assert_term_unequal @term_unequal_bnodes
|
||||||
|
test "value equality", do: assert_value_equal @value_equal_bnodes
|
||||||
|
test "value inequality", do: assert_value_unequal @value_unequal_bnodes
|
||||||
|
test "incomparability", do: assert_incomparable @incomparable_bnodes
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "RDF.Boolean" do
|
||||||
|
@term_equal_booleans [
|
||||||
|
{RDF.true, RDF.true},
|
||||||
|
{RDF.false, RDF.false},
|
||||||
|
]
|
||||||
|
@term_unequal_booleans [
|
||||||
|
{RDF.true, RDF.false},
|
||||||
|
{RDF.false, RDF.true},
|
||||||
|
]
|
||||||
|
@value_equal_booleans [
|
||||||
|
{RDF.true, RDF.boolean("TRUE")},
|
||||||
|
{RDF.boolean(1), RDF.true},
|
||||||
|
]
|
||||||
|
@value_unequal_booleans [
|
||||||
|
{RDF.true, RDF.boolean("FALSE")},
|
||||||
|
{RDF.boolean(0), RDF.true},
|
||||||
|
]
|
||||||
|
@incomparable_booleans [
|
||||||
|
{RDF.true, nil},
|
||||||
|
{nil, RDF.true},
|
||||||
|
{RDF.true, RDF.string("FALSE")},
|
||||||
|
{RDF.integer(0), RDF.true},
|
||||||
|
]
|
||||||
|
|
||||||
|
test "term equality", do: assert_term_equal @term_equal_booleans
|
||||||
|
test "term inequality", do: assert_term_unequal @term_unequal_booleans
|
||||||
|
test "value equality", do: assert_value_equal @value_equal_booleans
|
||||||
|
test "value inequality", do: assert_value_unequal @value_unequal_booleans
|
||||||
|
test "incomparability", do: assert_incomparable @incomparable_booleans
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "RDF.Numeric" do
|
||||||
|
@term_equal_numerics [
|
||||||
|
{RDF.integer(42), RDF.integer(42)},
|
||||||
|
{RDF.integer("042"), RDF.integer("042")},
|
||||||
|
]
|
||||||
|
@term_unequal_numerics [
|
||||||
|
{RDF.integer(1), RDF.integer(2)},
|
||||||
|
]
|
||||||
|
@value_equal_numerics [
|
||||||
|
{RDF.integer("42"), RDF.integer("042")},
|
||||||
|
{RDF.double("+0"), RDF.double("-0")},
|
||||||
|
{RDF.integer("42"), RDF.double("42")},
|
||||||
|
{RDF.integer(42), RDF.double(42.0)},
|
||||||
|
]
|
||||||
|
@value_unequal_numerics [
|
||||||
|
{RDF.integer("1"), RDF.double("1.1")},
|
||||||
|
]
|
||||||
|
@incomparable_numerics [
|
||||||
|
{RDF.string("42"), RDF.integer(42)},
|
||||||
|
{RDF.integer("42"), RDF.string("42")},
|
||||||
|
]
|
||||||
|
|
||||||
|
test "term equality", do: assert_term_equal @term_equal_numerics
|
||||||
|
test "term inequality", do: assert_term_unequal @term_unequal_numerics
|
||||||
|
test "value equality", do: assert_value_equal @value_equal_numerics
|
||||||
|
test "value inequality", do: assert_value_unequal @value_unequal_numerics
|
||||||
|
test "incomparability", do: assert_incomparable @incomparable_numerics
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "RDF.DateTime" do
|
||||||
|
@term_equal_datetimes [
|
||||||
|
{RDF.date_time("2002-04-02T12:00:00-01:00"), RDF.date_time("2002-04-02T12:00:00-01:00")},
|
||||||
|
{RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T12:00:00")},
|
||||||
|
]
|
||||||
|
@term_unequal_datetimes [
|
||||||
|
{RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T17:00:00")},
|
||||||
|
]
|
||||||
|
@value_equal_datetimes [
|
||||||
|
{RDF.date_time("2002-04-02T12:00:00-01:00"), RDF.date_time("2002-04-02T17:00:00+04:00")},
|
||||||
|
{RDF.date_time("2002-04-02T23:00:00-04:00"), RDF.date_time("2002-04-03T02:00:00-01:00")},
|
||||||
|
{RDF.date_time("1999-12-31T24:00:00"), RDF.date_time("2000-01-01T00:00:00")},
|
||||||
|
# TODO: Assume that the dynamic context provides an implicit timezone value of -05:00
|
||||||
|
# {RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T23:00:00+06:00")},
|
||||||
|
]
|
||||||
|
@value_unequal_datetimes [
|
||||||
|
{RDF.date_time("2005-04-04T24:00:00"), RDF.date_time("2005-04-04T00:00:00")},
|
||||||
|
]
|
||||||
|
@incomparable_datetimes [
|
||||||
|
{RDF.string("2002-04-02T12:00:00-01:00"), RDF.date_time("2002-04-02T12:00:00-01:00")},
|
||||||
|
{RDF.date_time("2002-04-02T12:00:00-01:00"), RDF.string("2002-04-02T12:00:00-01:00")},
|
||||||
|
]
|
||||||
|
|
||||||
|
test "term equality", do: assert_term_equal @term_equal_datetimes
|
||||||
|
test "term inequality", do: assert_term_unequal @term_unequal_datetimes
|
||||||
|
test "value equality", do: assert_value_equal @value_equal_datetimes
|
||||||
|
test "value inequality", do: assert_value_unequal @value_unequal_datetimes
|
||||||
|
test "incomparability", do: assert_incomparable @incomparable_datetimes
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
defp assert_term_equal(examples) do
|
||||||
|
Enum.each examples, fn example -> assert_term_equality(example, true) end
|
||||||
|
Enum.each examples, fn example -> assert_value_equality(example, true) end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_term_unequal(examples) do
|
||||||
|
Enum.each examples, fn example -> assert_term_equality(example, false) end
|
||||||
|
Enum.each examples, fn example -> assert_value_equality(example, false) end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_value_equal(examples) do
|
||||||
|
Enum.each examples, fn example -> assert_value_equality(example, true) end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_value_unequal(examples) do
|
||||||
|
Enum.each examples, fn example -> assert_value_equality(example, false) end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_incomparable(examples) do
|
||||||
|
Enum.each examples, fn example -> assert_term_equality(example, false) end
|
||||||
|
Enum.each examples, fn example -> assert_value_equality(example, nil) end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_term_equality({left, right}, expected) do
|
||||||
|
result = RDF.Term.equal?(left, right)
|
||||||
|
assert result == expected, """
|
||||||
|
expected RDF.Term.equal?(
|
||||||
|
#{inspect left},
|
||||||
|
#{inspect right})
|
||||||
|
to be: #{inspect expected}
|
||||||
|
but got: #{inspect result}
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
defp assert_value_equality({left, right}, expected) do
|
||||||
|
result = RDF.Term.equal_value?(left, right)
|
||||||
|
assert result == expected, """
|
||||||
|
expected RDF.Term.equal_value?(
|
||||||
|
#{inspect left},
|
||||||
|
#{inspect right})
|
||||||
|
to be: #{inspect expected}
|
||||||
|
but got: #{inspect result}
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue