From adb1c126348712b1a6aacf8a60613a5939fef665 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Sat, 18 Apr 2020 21:38:21 +0200 Subject: [PATCH] Restore equality tests --- test/unit/equality_test.exs | 490 ++++++++++++++++++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 test/unit/equality_test.exs diff --git a/test/unit/equality_test.exs b/test/unit/equality_test.exs new file mode 100644 index 0000000..54bf75a --- /dev/null +++ b/test/unit/equality_test.exs @@ -0,0 +1,490 @@ +defmodule RDF.EqualityTest do + use RDF.Test.Case + + alias Decimal, as: D + + 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.anyURI("http://example.com/")}, + + {RDF.anyURI("http://example.com/"), + RDF.iri("http://example.com/")}, + + {RDF.anyURI("http://example.com/"), + RDF.anyURI("http://example.com/")}, + ] + @value_unequal_iris [ + {RDF.iri("http://example.com/foo"), + RDF.anyURI("http://example.com/bar")}, + ] + @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 + @tag skip: "TODO: finish equality extension of XSD.AnyURI" + test "value equality", do: assert_value_equal @value_equal_iris + @tag skip: "TODO: finish equality extension of XSD.AnyURI" + 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.String and RDF.LangString" do + @term_equal_strings [ + {RDF.string("foo"), RDF.string("foo")}, + {RDF.lang_string("foo", language: "de"), RDF.lang_string("foo", language: "de")}, + ] + @term_unequal_strings [ + {RDF.string("foo"), RDF.string("bar")}, + {RDF.lang_string("foo", language: "de"), RDF.lang_string("bar", language: "de")}, + ] + @value_equal_strings [ + ] + @value_unequal_strings [ + ] + @value_equal_strings_by_coercion [ + {RDF.string("foo"), "foo"}, + ] + @value_unequal_strings_by_coercion [ + {RDF.string("foo"), "bar"}, + ] + @incomparable_strings [ + {RDF.string("42"), 42}, + {RDF.lang_string("foo", language: "de"), "foo"}, + {RDF.string("foo"), RDF.lang_string("foo", language: "de")}, + {RDF.lang_string("foo", language: "de"), RDF.string("foo")}, + {RDF.string("foo"), RDF.bnode("foo")}, + ] + + test "term equality", do: assert_term_equal @term_equal_strings + test "term inequality", do: assert_term_unequal @term_unequal_strings + test "value equality", do: assert_value_equal @value_equal_strings + test "value inequality", do: assert_value_unequal @value_unequal_strings + test "coerced value equality", do: assert_value_equal @value_equal_strings_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_strings_by_coercion + test "incomparability", do: assert_incomparable @incomparable_strings + end + + describe "RDF.Boolean" do + @term_equal_booleans [ + {RDF.true, RDF.true}, + {RDF.false, RDF.false}, + # invalid literals + {RDF.boolean("foo"), RDF.boolean("foo")}, + ] + @term_unequal_booleans [ + {RDF.true, RDF.false}, + {RDF.false, RDF.true}, + # invalid literals + {RDF.boolean("foo"), RDF.boolean("bar")}, + ] + @value_equal_booleans [ + {RDF.true, RDF.boolean("1")}, + {RDF.boolean(0), RDF.false}, + # invalid literals + {RDF.boolean("foo"), RDF.boolean("foo")}, + ] + @value_unequal_booleans [ + {RDF.true, RDF.boolean("false")}, + {RDF.boolean(0), RDF.true}, + # invalid literals + {RDF.boolean("foo"), RDF.boolean("bar")}, + ] + @value_equal_booleans_by_coercion [ + {RDF.true, true}, + {RDF.false, false}, + ] + @value_unequal_booleans_by_coercion [ + {RDF.true, false}, + {RDF.false, true}, + ] + @incomparable_booleans [ + {RDF.false, nil}, + {RDF.true, 42}, + {RDF.true, RDF.string("FALSE")}, + {RDF.true, RDF.integer(0)}, + ] + + 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 "coerced value equality", do: assert_value_equal @value_equal_booleans_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_booleans_by_coercion + 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")}, + # invalid literals + {RDF.integer("foo"), RDF.integer("foo")}, + {RDF.decimal("foo"), RDF.decimal("foo")}, + {RDF.double("foo"), RDF.double("foo")}, + ] + @term_unequal_numerics [ + {RDF.integer(1), RDF.integer(2)}, + # invalid literals + {RDF.integer("foo"), RDF.integer("bar")}, + {RDF.decimal("foo"), RDF.decimal("bar")}, + {RDF.double("foo"), RDF.double("bar")}, + ] + @value_equal_numerics [ + {RDF.integer("42"), RDF.integer("042")}, + {RDF.integer("42"), RDF.double("42")}, + {RDF.integer(42), RDF.double(42.0)}, + {RDF.integer("42"), RDF.decimal("42")}, + {RDF.integer(42), RDF.decimal(42.0)}, + {RDF.double(3.14), RDF.decimal(3.14)}, + {RDF.double("+0"), RDF.double("-0")}, + {RDF.decimal("+0"), RDF.decimal("-0")}, + # invalid literals + {RDF.integer("foo"), RDF.integer("foo")}, + {RDF.decimal("foo"), RDF.decimal("foo")}, + {RDF.double("foo"), RDF.double("foo")}, + ] + @value_unequal_numerics [ + {RDF.integer("1"), RDF.double("1.1")}, + {RDF.integer("1"), RDF.decimal("1.1")}, + # invalid literals + {RDF.integer("foo"), RDF.integer("bar")}, + {RDF.decimal("foo"), RDF.decimal("bar")}, + {RDF.double("foo"), RDF.double("bar")}, + ] + @value_equal_numerics_by_coercion [ + {RDF.integer(42), 42}, + {RDF.integer(42), 42.0}, + {RDF.integer(42), D.new(42)}, + {RDF.decimal(42), 42}, + {RDF.decimal(3.14), 3.14}, + {RDF.decimal(3.14), D.from_float(3.14)}, + {RDF.double(42), 42}, + {RDF.double(3.14), 3.14}, + {RDF.double(3.14), D.from_float(3.14)}, + ] + @value_unequal_numerics_by_coercion [ + {RDF.integer(3), 3.14}, + {RDF.integer(3), D.from_float(3.14)}, + {RDF.double(3.14), 3}, + {RDF.decimal(3.14), 3}, + ] + @incomparable_numerics [ + {RDF.integer("42"), nil}, + {RDF.integer("42"), true}, + {RDF.integer("42"), "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 "coerced value equality", do: assert_value_equal @value_equal_numerics_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_numerics_by_coercion + 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")}, + # invalid literals + {RDF.date_time("foo"), RDF.date_time("foo")}, + ] + @term_unequal_datetimes [ + {RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T17:00:00")}, + # invalid literals + {RDF.date_time("foo"), RDF.date_time("bar")}, + ] + @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")}, + + {RDF.date_time("2002-04-02T23:00:00Z"), RDF.date_time("2002-04-02T23:00:00+00:00")}, + {RDF.date_time("2002-04-02T23:00:00Z"), RDF.date_time("2002-04-02T23:00:00-00:00")}, + {RDF.date_time("2002-04-02T23:00:00+00:00"), RDF.date_time("2002-04-02T23:00:00-00:00")}, + + # invalid literals + {RDF.date_time("foo"), RDF.date_time("foo")}, + ] + @value_unequal_datetimes [ + {RDF.date_time("2005-04-04T24:00:00"), RDF.date_time("2005-04-04T00:00:00")}, + # invalid literals + {RDF.date_time("foo"), RDF.date_time("bar")}, + ] + @value_equal_datetimes_by_coercion [ + {RDF.date_time("2002-04-02T12:00:00-01:00"), elem(DateTime.from_iso8601("2002-04-02T12:00:00-01:00"), 1)}, + {RDF.date_time("2002-04-02T12:00:00"), ~N"2002-04-02T12:00:00"}, + {RDF.date_time("2002-04-02T23:00:00Z"), elem(DateTime.from_iso8601("2002-04-02T23:00:00+00:00"), 1)}, + {RDF.date_time("2002-04-02T23:00:00+00:00"), elem(DateTime.from_iso8601("2002-04-02T23:00:00Z"), 1)}, + {RDF.date_time("2002-04-02T23:00:00-00:00"), elem(DateTime.from_iso8601("2002-04-02T23:00:00Z"), 1)}, + {RDF.date_time("2002-04-02T23:00:00-00:00"), elem(DateTime.from_iso8601("2002-04-02T23:00:00+00:00"), 1)}, + ] + @value_unequal_datetimes_by_coercion [ + {RDF.date_time("2002-04-02T12:00:00-01:00"), elem(DateTime.from_iso8601("2002-04-02T12:00:00+00:00"), 1)}, + ] + @incomparable_datetimes [ + {RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T12:00:00Z")}, + {RDF.string("2002-04-02T12:00:00-01:00"), RDF.date_time("2002-04-02T12:00:00-01:00")}, + # These are incomparable because of indeterminacy due to missing timezone + {RDF.date_time("2002-04-02T12:00:00"), RDF.date_time("2002-04-02T23:00:00+00: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 "coerced value equality", do: assert_value_equal @value_equal_datetimes_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_datetimes_by_coercion + test "incomparability", do: assert_incomparable @incomparable_datetimes + end + + describe "RDF.Date" do + @term_equal_dates [ + {RDF.date("2002-04-02-01:00"), RDF.date("2002-04-02-01:00")}, + {RDF.date("2002-04-02"), RDF.date("2002-04-02")}, + # invalid literals + {RDF.date("foo"), RDF.date("foo")}, + ] + @term_unequal_dates [ + {RDF.date("2002-04-01"), RDF.date("2002-04-02")}, + # invalid literals + {RDF.date("foo"), RDF.date("bar")}, + ] + @value_equal_dates [ + {RDF.date("2002-04-02-00:00"), RDF.date("2002-04-02+00:00")}, + {RDF.date("2002-04-02Z"), RDF.date("2002-04-02+00:00")}, + {RDF.date("2002-04-02Z"), RDF.date("2002-04-02-00:00")}, + ] + @value_unequal_dates [ + {RDF.date("2002-04-03Z"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-03Z"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-03"), RDF.date("2002-04-02Z")}, + {RDF.date("2002-04-03+00:00"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-03-00:00"), RDF.date("2002-04-02")}, + # invalid literals + {RDF.date("2002.04.02"), RDF.date("2002-04-02")}, + ] + @value_equal_dates_by_coercion [ + {RDF.date("2002-04-02"), Date.from_iso8601!("2002-04-02")}, + ] + @value_unequal_dates_by_coercion [ + {RDF.date("2002-04-02"), Date.from_iso8601!("2002-04-03")}, + {RDF.date("2002-04-03+01:00"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-03Z"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-03+00:00"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-03-00:00"), Date.from_iso8601!("2002-04-02")}, + ] + @incomparable_dates [ + {RDF.date("2002-04-02"), RDF.string("2002-04-02")}, + # These are incomparable because of indeterminacy due to missing timezone + {RDF.date("2002-04-02Z"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-02"), RDF.date("2002-04-02Z")}, + {RDF.date("2002-04-02+00:00"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-02-00:00"), RDF.date("2002-04-02")}, + {RDF.date("2002-04-02+01:00"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-02Z"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-02+00:00"), Date.from_iso8601!("2002-04-02")}, + {RDF.date("2002-04-02-00:00"), Date.from_iso8601!("2002-04-02")}, + ] + + test "term equality", do: assert_term_equal @term_equal_dates + test "term inequality", do: assert_term_unequal @term_unequal_dates + test "value equality", do: assert_value_equal @value_equal_dates + test "value inequality", do: assert_value_unequal @value_unequal_dates + test "coerced value equality", do: assert_value_equal @value_equal_dates_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_dates_by_coercion + test "incomparability", do: assert_incomparable @incomparable_dates + end + + describe "equality between RDF.Date and RDF.DateTime" do + # It seems quite strange that open-world test date-2 from the SPARQL 1.0 test suite + # allows for equality comparisons between dates and datetimes, but disallows + # ordering comparisons in the date-3 test. + # + # @value_equal_dates_and_datetimes [ + # {RDF.date("2002-04-02"), RDF.datetime("2002-04-02T00:00:00")}, + # {RDF.datetime("2002-04-02T00:00:00"), RDF.date("2002-04-02")}, + # {RDF.date("2002-04-02Z"), RDF.datetime("2002-04-02T00:00:00Z")}, + # {RDF.datetime("2002-04-02T00:00:00Z"), RDF.date("2002-04-02Z")}, + # {RDF.date("2002-04-02Z"), RDF.datetime("2002-04-02T00:00:00+00:00")}, + # {RDF.datetime("2002-04-02T00:00:00-00:00"), RDF.date("2002-04-02Z")}, + # ] + # @value_unequal_dates_and_datetimes [ + # {RDF.date("2002-04-01"), RDF.datetime("2002-04-02T00:00:00")}, + # {RDF.datetime("2002-04-01T00:00:00"), RDF.date("2002-04-02")}, + # {RDF.date("2002-04-01Z"), RDF.datetime("2002-04-02T00:00:00Z")}, + # {RDF.datetime("2002-04-01T00:00:00Z"), RDF.date("2002-04-02Z")}, + # {RDF.date("2002-04-01Z"), RDF.datetime("2002-04-02T00:00:00+00:00")}, + # {RDF.datetime("2002-04-01T00:00:00-00:00"), RDF.date("2002-04-02Z")}, + # ] + # @incomparable_dates_and_datetimes [ + # {RDF.date("2002-04-02Z"), RDF.datetime("2002-04-02T00:00:00")}, + # {RDF.datetime("2002-04-02T00:00:00Z"), RDF.date("2002-04-02")}, + # {RDF.date("2002-04-02"), RDF.datetime("2002-04-02T00:00:00Z")}, + # {RDF.datetime("2002-04-02T00:00:00"), RDF.date("2002-04-02Z")}, + # ] + # + # test "value equality", do: assert_value_equal @value_equal_dates_and_datetimes + # test "value inequality", do: assert_value_unequal @value_unequal_dates_and_datetimes + # test "incomparability", do: assert_incomparable @incomparable_dates_and_datetimes + + @value_unequal_dates_and_datetimes [ + {RDF.datetime("2002-04-02T00:00:00"), RDF.date("2002-04-02")}, + {RDF.datetime("2002-04-02T00:00:00"), RDF.date("2002-04-01")}, + ] + + test "value inequality", do: assert_value_unequal @value_unequal_dates_and_datetimes + end + + describe "RDF.Time" do + @term_equal_times [ + {RDF.time("12:00:00+01:00"), RDF.time("12:00:00+01:00")}, + {RDF.time("12:00:00"), RDF.time("12:00:00")}, + # invalid literals + {RDF.time("foo"), RDF.time("foo")}, + ] + @term_unequal_times [ + {RDF.time("12:00:00"), RDF.time("13:00:00")}, + # invalid literals + {RDF.time("foo"), RDF.time("bar")}, + ] + @value_equal_times [ + ] + @value_unequal_times [ + ] + @value_equal_times_by_coercion [ + {RDF.time("12:00:00"), Time.from_iso8601!("12:00:00")}, + ] + @value_unequal_times_by_coercion [ + {RDF.time("12:00:00"), Time.from_iso8601!("13:00:00")}, + ] + @incomparable_times [ + {RDF.time("12:00:00"), RDF.string("12:00:00")}, + ] + + test "term equality", do: assert_term_equal @term_equal_times + test "term inequality", do: assert_term_unequal @term_unequal_times + test "value equality", do: assert_value_equal @value_equal_times + test "value inequality", do: assert_value_unequal @value_unequal_times + test "coerced value equality", do: assert_value_equal @value_equal_times_by_coercion + test "coerced value inequality", do: assert_value_unequal @value_unequal_times_by_coercion + test "incomparability", do: assert_incomparable @incomparable_times + end + + describe "RDF.Literals with unsupported types" do + @equal_literals [ + {RDF.literal("foo", datatype: "http://example.com/datatype"), + RDF.literal("foo", datatype: "http://example.com/datatype")}, + ] + @unequal_literals [ + {RDF.literal("foo", datatype: "http://example.com/datatype"), + RDF.literal("bar", datatype: "http://example.com/datatype")}, + ] + @incomparable_literals [ + {RDF.literal("foo", datatype: "http://example.com/datatype1"), + RDF.literal("foo", datatype: "http://example.com/datatype2")}, + ] + + test "term equality", do: assert_term_equal @equal_literals + test "term inequality", do: assert_value_unequal @unequal_literals + test "incomparability", do: assert_incomparable @incomparable_literals + 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} + """ + + result = RDF.Term.equal?(right, left) + assert result == expected, """ + expected RDF.Term.equal?( + #{inspect right}, + #{inspect left}) + 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} + """ + + result = RDF.Term.equal_value?(right, left) + assert result == expected, """ + expected RDF.Term.equal_value?( + #{inspect right}, + #{inspect left}) + to be: #{inspect expected} + but got: #{inspect result} + """ + end +end