Skip to content

Commit

Permalink
Move Groups conformance tests to TestExt
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens committed Jan 10, 2025
1 parent c4a492a commit 8031e79
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 332 deletions.
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
2 changes: 1 addition & 1 deletion ext/TestExt/TestExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ module TestExt
using AbstractAlgebra
isdefined(Base, :get_extension) ? (using Test) : (using ..Test)


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

end # module
8 changes: 5 additions & 3 deletions src/AbstractAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,13 @@ getindex(S::Set, i::Int) = gen(S, i)

include("error.jl")

###############################################################################
################################################################################
#
# Load Groups/Rings/Fields etc.
# Conformance tests (function stubs for TestExt)
#
###############################################################################
################################################################################

include("ConformanceTests.jl")


# Generic functions to be defined after all rings
Expand Down
10 changes: 10 additions & 0 deletions src/ConformanceTests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module ConformanceTests

# This file only contains function stubs.
# The actual implementation are in the folder `ext/TestExt/`.

# Groups-conformance-tests.jl
function test_Group_interface end
function test_GroupElem_interface end

end # module
1 change: 1 addition & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export AbsPowerSeriesRingElem
export AdditiveGroupElem
export AllParts
export AllPerms
export ConformanceTests
export ErrorConstrDimMismatch
export EuclideanRingResidueField
export EuclideanRingResidueFieldElem
Expand Down
2 changes: 1 addition & 1 deletion test/AbstractAlgebra-test.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("conformance-tests.jl")
include("Rings-conformance-tests.jl")

include("error-test.jl")
include("AliasMacro-test.jl")
Expand Down
Loading

0 comments on commit 8031e79

Please sign in to comment.