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

WIP: Move conformance tests to a package extension #1954

Draft
wants to merge 5 commits into
base: master
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
11 changes: 11 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,26 @@ MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RandomExtensions = "fb686558-2515-59ef-acaa-46db3789a887"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[weakdeps]
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[extensions]
TestExt = "Test"

[compat]
LinearAlgebra = "1.6"
MacroTools = "0.5"
Preferences = "1"
Random = "1.6"
RandomExtensions = "0.4.2"
Requires = "1.3.0"
SparseArrays = "1.6"
Test = "1.6"
julia = "1.6"
328 changes: 328 additions & 0 deletions ext/TestExt/Groups-conformance-tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
###############################################################################
#
# Conformance tests for the group and group element interfaces.
#
#
# The code in this file is based on v0.4 of the GroupsCore.jl package, which
# is copyright (c) 2021 Marek Kaluba <[email protected]> and contributors,
# and licensed under the MIT license <https://spdx.org/licenses/MIT.html>.
#
# The interfaces have since then diverged, with several breaking changes.
# Function and type names differ (e.g. `istrivial` vs. `is_trivial`), and
# also semantics (e.g. definition of equality for group elements in
# GroupsCore allows returning false for mathematically equal elements when it
# is "too hard" to prove equality; we don't).
#
###############################################################################


function ConformanceTests.test_Group_interface(G::Group)
@testset "Group interface" begin
# @testset "Iteration protocol" begin
# IS = Base.IteratorSize(typeof(G))
# if IS isa Base.IsInfinite
# @test is_finite(G) == false
# else
# isfiniteG = false
# if IS isa Base.HasLength || IS isa Base.HasShape
# @test is_finite(G) == true
# isfiniteG = true
# else
# @test IS isa Base.SizeUnknown
# try
# @test is_finite(G) isa Bool
# isfiniteG = is_finite(G)
# catch e
# @test e isa AbstractAlgebra.InfiniteOrderError
# isfiniteG = false
# end
# end
#
# if isfiniteG
# @test length(G) isa Int
# @test length(G) > 0
#
# @test elem_type(G) <: GroupElem
# @test one(G) isa elem_type(G)
#
# if has_gens(G)
# @test first(iterate(G)) isa elem_type(G)
# _, s = iterate(G)
# @test first(iterate(G, s)) isa elem_type(G)
# @test isone(first(G))
# end
# end
# end
# end

@testset "Group generators" begin
@test has_gens(G) isa Bool

if has_gens(G)
@test ngens(G) isa Int
@test gens(G) isa AbstractVector{elem_type(G)}
@test length(gens(G)) == ngens(G)
if ngens(G) > 0
@test first(gens(G)) == gen(G, 1)
@test last(gens(G)) == gen(G, ngens(G))
end
else
# TODO: throw something more specific
@test_throws ErrorException gens(G)
@test_throws ErrorException ngens(G)

Check warning on line 72 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L71-L72

Added lines #L71 - L72 were not covered by tests
end
end

@testset "order, rand" begin

Check warning on line 76 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L76

Added line #L76 was not covered by tests
if is_finite(G)
ord = order(BigInt, G)
@test ord isa BigInt
if ord < typemax(Int16)
@test order(Int16, G) isa Int16
else
@test_throws InexactError order(Int16, G)
end
@test order(G) >= 1
@test is_trivial(G) == (order(G) == 1)
else
@test_throws AbstractAlgebra.InfiniteOrderError order(G)
@test !is_trivial(G)

Check warning on line 89 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L88-L89

Added lines #L88 - L89 were not covered by tests
end

@test rand(G) isa GroupElem
@test rand(G, 2) isa AbstractVector{elem_type(G)}
g, h = rand(G, 2)
@test parent(g) === parent(h) === G

# @test GroupsCore.rand_pseudo(G) isa elem_type(G)
# @test GroupsCore.rand_pseudo(G, 2, 2) isa AbstractMatrix{elem_type(G)}
#
# g, h = GroupsCore.rand_pseudo(G, 2)
# @test parent(g) === parent(h) === G
end
end
end

function ConformanceTests.test_GroupElem_interface(g::GEl, h::GEl) where {GEl<:GroupElem}

@testset "GroupElem interface" begin

@testset "Parent methods" begin
@test parent(g) isa Group
@test parent(g) === parent(h)
G = parent(g)

@test elem_type(G) == typeof(g)

@test one(g) isa elem_type(G)

@test one(G) == one(g) == one(h)

@test isone(one(G))
end

@testset "Equality, deepcopy && hash" begin

Check warning on line 124 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L124

Added line #L124 was not covered by tests
@test (g == h) isa Bool
@test isequal(g, h) isa Bool

@test g == g
@test isequal(g, g)

if g != h
@test !isequal(g, h)
end

@test deepcopy(g) isa typeof(g)
@test deepcopy(g) == g
k = deepcopy(g)
@test parent(k) === parent(g)
@test hash(g) isa UInt
@test hash(g) == hash(k)

if isequal(g, h)
@test hash(g) == hash(h)
end
end

@testset "Group operations" begin

Check warning on line 147 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L147

Added line #L147 was not covered by tests
old_g, old_h = deepcopy(g), deepcopy(h)

# check that the default operations don't mutate their arguments
@test inv(g) isa typeof(g)
@test (g, h) == (old_g, old_h)

@test g * h isa typeof(g)
@test (g, h) == (old_g, old_h)

@test g^2 == g * g
@test (g, h) == (old_g, old_h)

@test g^-3 == inv(g) * inv(g) * inv(g)
@test (g, h) == (old_g, old_h)

@test (g * h)^-1 == inv(h) * inv(g)
@test (g, h) == (old_g, old_h)

@test conj(g, h) == inv(h) * g * h
@test (g, h) == (old_g, old_h)

@test ^(g, h) == inv(h) * g * h
@test (g, h) == (old_g, old_h)

@test comm(g, h) == g^-1 * h^-1 * g * h
@test (g, h) == (old_g, old_h)

@test comm(g, h, g) == conj(inv(g), h) * conj(conj(g, h), g)
@test (g, h) == (old_g, old_h)

@test isone(g * inv(g)) && isone(inv(g) * g)
@test (g, h) == (old_g, old_h)

@test g / h == g * inv(h)
@test (g, h) == (old_g, old_h)

@test div_right(g, h) == g * inv(h)
@test (g, h) == (old_g, old_h)

@test g \ h == inv(g) * h
@test (g, h) == (old_g, old_h)

@test div_left(g, h) == inv(h) * g
@test (g, h) == (old_g, old_h)
end

@testset "Misc GroupElem methods" begin

Check warning on line 194 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L194

Added line #L194 was not covered by tests
@test one(g) isa typeof(g)
@test isone(g) isa Bool
@test isone(one(g))

@test is_finite_order(g) isa Bool

if is_finite_order(g)
@test order(Int16, g) isa Int16
@test order(BigInt, g) isa BigInt
@test order(g) >= 1
if is_finite(parent(g))
@test iszero(order(parent(g)) % order(g))
end
if !isone(g) && !isone(g^2)
@test order(g) > 2
end
@test order(inv(g)) == order(g)
@test order(one(g)) == 1
else
@test_throws AbstractAlgebra.InfiniteOrderError order(g)

Check warning on line 214 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L214

Added line #L214 was not covered by tests
end

@test similar(g) isa typeof(g)
end

@testset "In-place operations" begin

Check warning on line 220 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L220

Added line #L220 was not covered by tests
old_g, old_h = deepcopy(g), deepcopy(h)
out = similar(g)

@test isone(one!(g))
g = deepcopy(old_g)

@test inv!(out, g) == inv(old_g)
@test g == old_g
@test inv!(out, g) == inv(old_g)
g = deepcopy(old_g)

@testset "mul!" begin

Check warning on line 232 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L232

Added line #L232 was not covered by tests
@test mul!(out, g, h) == old_g * old_h
@test (g, h) == (old_g, old_h)

@test mul!(out, g, h) == old_g * old_h
@test (g, h) == (old_g, old_h)

@test mul!(g, g, h) == old_g * old_h
@test h == old_h
g = deepcopy(old_g)

@test mul!(h, g, h) == old_g * old_h
@test g == old_g
h = deepcopy(old_h)

@test mul!(g, g, g) == old_g * old_g
g = deepcopy(old_g)
end

@testset "conj!" begin

Check warning on line 251 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L251

Added line #L251 was not covered by tests
res = old_h^-1 * old_g * old_h
@test conj!(out, g, h) == res
@test (g, h) == (old_g, old_h)

@test conj!(g, g, h) == res
@test h == old_h
g = deepcopy(old_g)

@test conj!(h, g, h) == res
@test g == old_g
h = deepcopy(old_h)

@test conj!(g, g, g) == old_g
g = deepcopy(old_g)
end

@testset "comm!" begin

Check warning on line 268 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L268

Added line #L268 was not covered by tests
res = old_g^-1 * old_h^-1 * old_g * old_h

@test comm!(out, g, h) == res
@test (g, h) == (old_g, old_h)

@test comm!(out, g, h) == res
@test (g, h) == (old_g, old_h)

@test comm!(g, g, h) == res
@test h == old_h
g = deepcopy(old_g)

@test comm!(h, g, h) == res
@test g == old_g
h = deepcopy(old_h)
end

@testset "div_[left|right]!" begin

Check warning on line 286 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L286

Added line #L286 was not covered by tests
res = g * h^-1
@test div_right!(out, g, h) == res
@test (g, h) == (old_g, old_h)

@test div_right!(g, g, h) == res
@test h == old_h
g = deepcopy(old_g)

@test div_right!(h, g, h) == res
@test g == old_g
h = deepcopy(old_h)

@test div_right!(g, g, g) == one(g)
g = deepcopy(old_g)


res = h^-1 * g
@test div_left!(out, g, h) == res
@test (g, h) == (old_g, old_h)

@test div_left!(g, g, h) == res
@test h == old_h
g = deepcopy(old_g)

@test div_left!(h, g, h) == res
@test g == old_g
h = deepcopy(old_h)

@test div_left!(g, g, g) == one(g)
g = deepcopy(old_g)
end
end

@testset "Broadcasting" begin

Check warning on line 320 in ext/TestExt/Groups-conformance-tests.jl

View check run for this annotation

Codecov / codecov/patch

ext/TestExt/Groups-conformance-tests.jl#L320

Added line #L320 was not covered by tests
@test g .* [g, h] == [g * g, g * h]
G = parent(g)
if has_gens(G)
@test g .* gens(G) == [g * x for x in gens(G)]
end
end
end
end
24 changes: 24 additions & 0 deletions ext/TestExt/TestExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module TestExt

using AbstractAlgebra
isdefined(Base, :get_extension) ? (using Test) : (using ..Test)


include("Groups-conformance-tests.jl")


function ConformanceTests.test_iterate(F::FinField)
elts = collect(Iterators.take(F, 20))
@test elts isa Vector{elem_type(F)}
@test allunique(elts)
@test length(elts) == min(order(F), 20)
if order(F) < 100
elts = collect(F)
@test elts isa Vector{elem_type(F)}
@test allunique(elts)
@test length(elts) == order(F)
end
return elts
end

end # module
Loading
Loading