diff --git a/Project.toml b/Project.toml index fec7d53..2e2d8fc 100644 --- a/Project.toml +++ b/Project.toml @@ -3,7 +3,14 @@ uuid = "ad2ac648-372e-45be-9d57-a550431b71c3" authors = ["JuliaGraphs contributors"] version = "0.1.0-DEV" +[deps] +DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + [compat] +DocStringExtensions = "0.9" +SimpleTraits = "0.9" julia = "1.6" [extras] diff --git a/docs/make.jl b/docs/make.jl index b6f0a3a..7ce6ca4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -12,7 +12,11 @@ makedocs(; canonical="https://juliagraphs.org/GraphsBase.jl", assets=String[], ), - pages=["Home" => "index.md"], + pages=[ + "Home" => "index.md", + "Interface" => "interface.md", + "Implementations" => "implementations.md", + ], ) deploydocs(; diff --git a/docs/src/implementations.md b/docs/src/implementations.md new file mode 100644 index 0000000..e89bce8 --- /dev/null +++ b/docs/src/implementations.md @@ -0,0 +1,13 @@ +# Concrete implementations + +## `SimpleGraphs` + +```@autodocs +Modules = [GraphsBase.SimpleGraphs] +``` + +## `SimpleWeightedGraphs` + +```@autodocs +Modules = [GraphsBase.SimpleWeightedGraphs] +``` diff --git a/docs/src/index.md b/docs/src/index.md index 4b327a0..f5c88d7 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -6,10 +6,8 @@ CurrentModule = GraphsBase Documentation for [GraphsBase](https://github.com/JuliaGraphs/GraphsBase.jl). -## API reference - -```@autodocs -Modules = [GraphsBase] +```@docs +GraphsBase ``` ## Index diff --git a/docs/src/interface.md b/docs/src/interface.md new file mode 100644 index 0000000..8e4dcfa --- /dev/null +++ b/docs/src/interface.md @@ -0,0 +1,61 @@ +# Interface + +## Edge + +```@docs +AbstractEdge +src +dst +weight +Base.reverse +``` + +## Graph (required) + +```@docs +AbstractGraph +is_directed +vertices +out_edges +in_edges +``` + +## Graph (optional) + +```@docs +nv +ne +has_vertex +has_edge +has_self_loops +edges +out_neighbors +in_neighbors +create_vertex_container +create_edge_container +``` + +## Graph (modification) + +```@docs +add_vertex! +rm_vertex! +add_edge! +rm_edge! +``` + +## Element types + +```@docs +Base.eltype +edgetype +weighttype +``` + +## Checks + +```@docs +GraphsBase.check_comparable_interface +GraphsBase.check_edge_interface +GraphsBase.check_graph_interface +``` diff --git a/src/GraphsBase.jl b/src/GraphsBase.jl index 45fcbd6..a8dce34 100644 --- a/src/GraphsBase.jl +++ b/src/GraphsBase.jl @@ -5,4 +5,33 @@ The basic interface and graph types for the JuliaGraphs ecosystem. """ module GraphsBase +using DocStringExtensions +using SimpleTraits +using SparseArrays + +export AbstractEdge, check_edge_interface +export eltype, weighttype +export src, dst, weight + +export AbstractGraph, check_graph_interface +export edgetype +export is_directed +export vertices +export edges, out_edges, in_edges +export nv, ne +export has_vertex, has_edge, has_self_loops +export out_neighbors, in_neighbors +export create_vertex_container, create_edge_container +export add_vertex!, rm_vertex!, add_edge!, rm_edge! + +include("interface/utils.jl") +include("interface/abstractedge.jl") +include("interface/abstractgraph.jl") +include("interface/optional.jl") +include("interface/modification.jl") + +include("SimpleGraphs/SimpleGraphs.jl") + +include("SimpleWeightedGraphs/SimpleWeightedGraphs.jl") + end diff --git a/src/SimpleGraphs/SimpleGraphs.jl b/src/SimpleGraphs/SimpleGraphs.jl new file mode 100644 index 0000000..b421894 --- /dev/null +++ b/src/SimpleGraphs/SimpleGraphs.jl @@ -0,0 +1,14 @@ +module SimpleGraphs + +using DocStringExtensions +using GraphsBase + +export SimpleEdge +export SimpleGraph +export SimpleDiGraph + +include("simpleedge.jl") +include("simplegraph.jl") +include("simpledigraph.jl") + +end diff --git a/src/SimpleGraphs/simpledigraph.jl b/src/SimpleGraphs/simpledigraph.jl new file mode 100644 index 0000000..c30840f --- /dev/null +++ b/src/SimpleGraphs/simpledigraph.jl @@ -0,0 +1,29 @@ +""" +$(TYPEDEF) + +A type representing a directed graph with unweighted, non-multiple edges. + +# Fields + +$(TYPEDFIELDS) +""" +mutable struct SimpleDiGraph{T<:Integer} <: AbstractGraph{T,SimpleEdge{T}} + "Number of edges" + ne::Int + "Forward adjacency list such that `F[v]` contains the out-neighbors of vertex `v`" + fadjlist::Vector{Vector{T}} + "Backward adjacency list such that `B[u]` contains the in-neighbors of vertex `v`" + badjlist::Vector{Vector{T}} +end + +GraphsBase.is_directed(::Type{<:SimpleDiGraph}) = true + +GraphsBase.vertices(g::SimpleDiGraph{T}) where {T} = one(T):T(length(g.fadjlist)) + +function GraphsBase.out_edges(g::SimpleDiGraph{T}, u) where {T} + return (SimpleEdge{T}(u, v) for v in g.fadjlist[u]) +end + +function GraphsBase.in_edges(g::SimpleDiGraph{T}, v) where {T} + return (SimpleEdge{T}(u, v) for u in g.badjlist[v]) +end diff --git a/src/SimpleGraphs/simpleedge.jl b/src/SimpleGraphs/simpleedge.jl new file mode 100644 index 0000000..0c6161b --- /dev/null +++ b/src/SimpleGraphs/simpleedge.jl @@ -0,0 +1,24 @@ +""" +$(TYPEDEF) + +A type representing an unweighted directed edge. + +# Fields + +$(TYPEDFIELDS) +""" +struct SimpleEdge{T<:Integer} <: AbstractEdge{T,Int} + "Source of the edge" + src::T + "Destination of the edge" + dst::T +end + +Base.Tuple(e::SimpleEdge) = (e.src, e.dst) +Base.isless(e1::SimpleEdge, e2::SimpleEdge) = isless(Tuple(e1), Tuple(e2)) +Base.:(==)(e1::SimpleEdge, e2::SimpleEdge) = Tuple(e1) == Tuple(e2) + +GraphsBase.src(e::SimpleEdge) = e.src +GraphsBase.dst(e::SimpleEdge) = e.dst +GraphsBase.weight(e::SimpleEdge) = 1 +Base.reverse(e::SimpleEdge) = SimpleEdge(e.dst, e.src) diff --git a/src/SimpleGraphs/simplegraph.jl b/src/SimpleGraphs/simplegraph.jl new file mode 100644 index 0000000..21f6310 --- /dev/null +++ b/src/SimpleGraphs/simplegraph.jl @@ -0,0 +1,25 @@ +""" +$(TYPEDEF) + +A type representing an undirected graph with unweighted, non-multiple edges. + +# Fields + +$(TYPEDFIELDS) +""" +mutable struct SimpleGraph{T<:Integer} <: AbstractGraph{T,SimpleEdge{T}} + """Number of edges""" + ne::Int + "Adjacency list such that `L[v]` contains the neighbors of vertex `v`" + adjlist::Vector{Vector{T}} +end + +GraphsBase.is_directed(::Type{<:SimpleGraph}) = false + +GraphsBase.vertices(g::SimpleGraph{T}) where {T} = one(T):T(length(g.adjlist)) + +function GraphsBase.out_edges(g::SimpleGraph{T}, u) where {T} + return (SimpleEdge{T}(u, v) for v in g.adjlist[u]) +end + +GraphsBase.in_edges(g::SimpleGraph, v) = out_edges(g, v) diff --git a/src/SimpleWeightedGraphs/SimpleWeightedGraphs.jl b/src/SimpleWeightedGraphs/SimpleWeightedGraphs.jl new file mode 100644 index 0000000..91729ca --- /dev/null +++ b/src/SimpleWeightedGraphs/SimpleWeightedGraphs.jl @@ -0,0 +1,15 @@ +module SimpleWeightedGraphs + +using DocStringExtensions +using SparseArrays +using GraphsBase + +export SimpleWeightedEdge +export SimpleWeightedGraph +export SimpleWeightedDiGraph + +include("simpleweightededge.jl") +include("simpleweightedgraph.jl") +include("simpleweighteddigraph.jl") + +end diff --git a/src/SimpleWeightedGraphs/simpleweighteddigraph.jl b/src/SimpleWeightedGraphs/simpleweighteddigraph.jl new file mode 100644 index 0000000..c68542d --- /dev/null +++ b/src/SimpleWeightedGraphs/simpleweighteddigraph.jl @@ -0,0 +1,27 @@ +""" +$(TYPEDEF) + +A type representing a directed graph with weighted, non-multiple edges. + +# Fields + +$(TYPEDFIELDS) +""" +struct SimpleWeightedDiGraph{T<:Integer,W} <: AbstractGraph{T,SimpleWeightedEdge{T,W}} + "Transposed weighted adjacency matrix: `weights[v, u]` contains the weight of edge `(u, v)`" + weights::SparseMatrixCSC{W,T} +end + +GraphsBase.is_directed(::Type{<:SimpleWeightedDiGraph}) = true +GraphsBase.vertices(g::SimpleWeightedDiGraph{T}) where {T} = one(T):T(size(g.weights, 1)) + +function GraphsBase.out_edges(g::SimpleWeightedDiGraph{T}, u) where {T} + A = g.weights + return (SimpleWeightedEdge{T}(u, A.rowval[i], A.nzval[i]) for i in nzrange(A, u)) +end + +function GraphsBase.in_edges(g::SimpleWeightedDiGraph, v) + A = g.weights + a = A[v, :] + return (SimpleWeightedEdge{T}(u, v, a[u]) for u in a.nzind) +end diff --git a/src/SimpleWeightedGraphs/simpleweightededge.jl b/src/SimpleWeightedGraphs/simpleweightededge.jl new file mode 100644 index 0000000..b27bd43 --- /dev/null +++ b/src/SimpleWeightedGraphs/simpleweightededge.jl @@ -0,0 +1,26 @@ +""" +$(TYPEDEF) + +A type representing a weighted directed edge. + +# Fields + +$(TYPEDFIELDS) +""" +struct SimpleWeightedEdge{T<:Integer,W} <: AbstractEdge{T,W} + "Source of the edge" + src::T + "Destination of the edge" + dst::T + "Weight of the edge" + weight::W +end + +Base.Tuple(e::SimpleWeightedEdge) = (e.src, e.dst, e.weight) +Base.isless(e1::SimpleWeightedEdge, e2::SimpleWeightedEdge) = isless(Tuple(e1), Tuple(e2)) +Base.:(==)(e1::SimpleWeightedEdge, e2::SimpleWeightedEdge) = Tuple(e1) == Tuple(e2) + +GraphsBase.src(e::SimpleWeightedEdge) = e.src +GraphsBase.dst(e::SimpleWeightedEdge) = e.dst +GraphsBase.weight(e::SimpleWeightedEdge) = e.weight +Base.reverse(e::SimpleWeightedEdge) = SimpleEdge(e.dst, e.src, e.weight) diff --git a/src/SimpleWeightedGraphs/simpleweightedgraph.jl b/src/SimpleWeightedGraphs/simpleweightedgraph.jl new file mode 100644 index 0000000..f5bc16f --- /dev/null +++ b/src/SimpleWeightedGraphs/simpleweightedgraph.jl @@ -0,0 +1,23 @@ +""" +$(TYPEDEF) + +A type representing an undirected graph with weighted, non-multiple edges. + +# Fields + +$(TYPEDFIELDS) +""" +struct SimpleWeightedGraph{T<:Integer,W} <: AbstractGraph{T,SimpleWeightedEdge{T,W}} + "Symmetric weighted adjacency matrix: `weights[u, v]` and `weights[v, u]` both contain the weight of edge `{u, v}`" + weights::SparseMatrixCSC{W,T} +end + +GraphsBase.is_directed(::Type{<:SimpleWeightedGraph}) = false +GraphsBase.vertices(g::SimpleWeightedGraph{T}) where {T} = one(T):T(size(g.weights, 1)) + +function GraphsBase.out_edges(g::SimpleWeightedGraph{T}, u) where {T} + A = g.weights + return (SimpleWeightedEdge{T}(u, A.rowval[i], A.nzval[i]) for i in nzrange(A, u)) +end + +GraphsBase.in_edges(g::SimpleWeightedGraph, v) = out_edges(g, v) diff --git a/src/interface/abstractedge.jl b/src/interface/abstractedge.jl new file mode 100644 index 0000000..a884d99 --- /dev/null +++ b/src/interface/abstractedge.jl @@ -0,0 +1,98 @@ +""" + AbstractEdge{V,W} + +Abstract type for graph edges with vertices of type `V` and a weight of type `W`. + +A subtype `E` satisfies this interface if both `V` and `E` can be hashed and compared, and if the following methods are implemented: + +- `src(e::E)` +- `dst(e::E)` +- `weight(e::E)` +- `Base.reverse(e::E)` +""" +abstract type AbstractEdge{V,W} end + +## Element types + +""" + eltype(e) + eltype(E) + +Return the type of the vertices of an edge `e` / an edge type `E`. +""" +Base.eltype(::Type{<:AbstractEdge{V}}) where {V} = V +Base.eltype(::E) where {E<:AbstractEdge} = eltype(E) + +""" + weighttype(e) + weighttype(E) + +Return the type of the weights of an edge `e` / an edge type `E`. +""" +weighttype(::Type{<:AbstractEdge{V,W}}) where {V,W} = W +weighttype(::E) where {E<:AbstractEdge} = weighttype(E) + +## Interface functions + +""" + src(e) + +Return the source vertex of edge `e`. +""" +function src end + +""" + dst(e) + +Return the destination vertex of edge `e`. +""" +function dst end + +""" + weight(e) + +Return the weight of edge `e`. +""" +function weight end + +""" + reverse(e) + +Return a new edge with the same data as edge `e` but inverted source and destination. +""" +Base.reverse + +## Interface test + +""" + check_edge_interface(E) + +Check that objects of type `E` can be used as edges of a graph. +""" +function check_edge_interface(::Type{E}) where {E<:AbstractEdge} + V = eltype(E) + if !check_comparable_interface(V) + return false + elseif !check_comparable_interface(E) + return false + elseif !hasmethod(src, (E,)) + @warn "Missing method GraphsBase.src(::$E)" + return false + elseif !hasmethod(dst, (E,)) + @warn "Missing method GraphsBase.dst(::$E)" + return false + elseif !hasmethod(weight, (E,)) + @warn "Missing method GraphsBase.weight(::$E)" + return false + elseif !hasmethod(Base.reverse, (E,)) + @warn "Missing method Base.reverse(::$E)" + return false + else + return true + end +end + +function check_edge_interface(::Type{E}) where {E} + @warn "$E must be a subtype of AbstractEdge" + return false +end diff --git a/src/interface/abstractgraph.jl b/src/interface/abstractgraph.jl new file mode 100644 index 0000000..7514f83 --- /dev/null +++ b/src/interface/abstractgraph.jl @@ -0,0 +1,108 @@ +""" + AbstractGraph{V,E} + +An abstract type representing a graph with vertices of type `V` and edges of type `E`. + +A subtype `G <: AbstractGraph` satisfies this interface if `E` satisfies the `AbstractEdge` interface, and if the following methods are implemented: + +- `is_directed(::Type{G})` +- `vertices(g::G)` +- `out_edges(g::G, v)` +- `in_edges(g::G, v)` +""" +abstract type AbstractGraph{V,E<:AbstractEdge} end + +## Element types + +""" + eltype(g) + eltype(G) + +Return the type of the vertices of a graph `g` / a graph type `G`. +""" +Base.eltype(::Type{<:AbstractGraph{V,E}}) where {V,E} = V +Base.eltype(::G) where {G<:AbstractGraph} = eltype(G) + +""" + edgetype(g) + edgetype(G) + +Return the type of the edges of a graph `g` / a graph type `G`. +""" +edgetype(::Type{<:AbstractGraph{V,E}}) where {V,E} = E +edgetype(::G) where {G<:AbstractGraph} = edgetype(G) + +""" + weighttype(g) + weighttype(G) + +Return the type of the edge weights of a graph `g` / a graph type `G`. +""" +weighttype(::Type{<:AbstractGraph{V,E}}) where {V,E} = weighttype(E) +weighttype(::G) where {G<:AbstractGraph} = weighttype(G) + +## Interface functions + +""" + is_directed(g) + is_directed(G) + +Return `true` if the graph `g` / graph type `G` is a directed graph. +""" +function is_directed end + +is_directed(::G) where {G<:AbstractGraph} = is_directed(G) + +@traitdef IsDirected{G<:AbstractGraph} +@traitimpl IsDirected{G} < -is_directed(G) + +""" + vertices(g) + +Return an iterable containing the vertices of `g`. +""" +function vertices end + +""" + out_edges(g, u) + +Return an iterable containing the edges of a graph `g` going out of vertex `u`. +""" +function out_edges end + +""" + in_edges(g, v) + +Return an iterable containing the edges of a graph `g` going into vertex `v`. +""" +function in_edges end + +## Interface test + +""" + check_graph_interface(G) + +Check that objects of type `G` can be used as graphs. +""" +function check_graph_interface(::Type{G}) where {G<:AbstractGraph} + V, E = eltype(G), edgetype(G) + if !check_edge_interface(E) + return false + elseif !hasmethod(vertices, (G,)) + @warn "Missing method `GraphsBase.vertices(::$E)`" + return false + elseif !hasmethod(out_edges, (G, V)) + @warn "Missing method `GraphsBase.out_edges(::$E, ::$V)`" + return false + elseif !hasmethod(in_edges, (G, V)) + @warn "Missing method `GraphsBase.in_edges(::$E, ::$V)`" + return false + else + return true + end +end + +function check_graph_interface(::Type{G}) where {G} + @warn "$G must be a subtype of AbstractGraph" + return false +end diff --git a/src/interface/modification.jl b/src/interface/modification.jl new file mode 100644 index 0000000..55c33c9 --- /dev/null +++ b/src/interface/modification.jl @@ -0,0 +1,27 @@ +""" + add_vertex!(g, v) + +Add the vertex `v` to the graph `g`. +""" +function add_vertex! end + +""" + rm_vertex!(g, v) + +Remove the vertex `v` from the graph `g`. +""" +function rm_vertex! end + +""" + add_edge!(g, e) + +Add the edge `e` to the graph `g`. +""" +function add_edge! end + +""" + rm_edge!(g, e) + +Remove the edge `e` from the graph `g`. +""" +function rm_edge! end diff --git a/src/interface/optional.jl b/src/interface/optional.jl new file mode 100644 index 0000000..1c6db3d --- /dev/null +++ b/src/interface/optional.jl @@ -0,0 +1,96 @@ +## Counting + +""" + nv(g) + +Count the number of vertices in `g`. +""" +nv(g::AbstractGraph) = length(vertices(g)) + +""" + ne(g) + +Count the number of edges in `g`. +""" +ne(g::AbstractGraph) = length(edges(g)) + +## Has stuff + +""" + has_vertex(g, v) + +Return `true` if the graph `g` contains the vertex `v`. +""" +has_vertex(g::AbstractGraph, v) = v in vertices(g) + +""" + has_edge(g, e) + +Return `true` if the graph `g` contains the edge `e` (not just an edge with the same source and destination). +""" +has_edge(g::AbstractGraph, e::AbstractEdge) = e in edges(g) + +""" + has_edge(g, u, v) + +Return `true` if the graph `g` contains an edge from vertex `u` to vertex `v`. +""" +has_edge(g::AbstractGraph, u, v) = v in outneighbors(g, u) + +""" + has_self_loops(g) + +Return `true` if `g` has any edge from a vertex to itself. +""" +function has_self_loops(g::AbstractGraph) + return nv(g) == 0 ? false : any(v -> has_edge(g, v, v), vertices(g)) +end + +## Edge iterators + +""" + edges(g) + +Return an iterable containing the edges of `g`. +""" +edges(g::AbstractGraph) = (e for v in vertices(g) for e in out_edges(g, v)) + +""" + edges(g, u, v) + +Return an iterable containing the edges of a graph `g` +going our of `u` and into `v`. +""" +edges(g::AbstractGraph, u, v) = (e for e in outedges(g, u) if dst(e) == v) + +## Neighbor iterators + +""" + in_neighbors(g, v) + +Return an iterable containing all neighbors connected to vertex `v` by an incoming edge. +""" +in_neighbors(g::AbstractGraph, v) = unique(src(e) for e in inedges(g, v)) + +""" + out_neighbors(g, u) + +Return an iterable containing all neighbors connected to vertex `u` by an outgoing edge. +""" +out_neighbors(g::AbstractGraph, u) = unique(dst(e) for e in outedges(g, u)) + +## Containers + +""" + create_vertex_container(g, ::Type{K}) + +Return a new container with element type `K` that can be indexed by the vertices of 'g'. +""" +create_vertex_container(::AbstractGraph{V}, ::Type{K}) where {V,K} = Dict{V,K}() + +""" + create_edge_container(g, ::Type{K}) + +Return a new container with element type `K` that can be indexed by the edges of 'g'. +""" +create_edge_container(::AbstractGraph{V,E}, ::Type{K}) where {V,E,K} = Dict{E,K}() diff --git a/src/interface/utils.jl b/src/interface/utils.jl new file mode 100644 index 0000000..4c739a4 --- /dev/null +++ b/src/interface/utils.jl @@ -0,0 +1,25 @@ +""" + check_comparable_interface(T) + +Check that objects of type `T` can be hashed and compared. + +This is true if the following methods are implemented: + +- `Base.hash(t::T, h::UInt)` +- `Base.isless(t1::T, t2::T)` +- `Base.:(==)(t1::T, t2::T)` +""" +function check_comparable_interface(::Type{T}) where {T} + if !hasmethod(Base.hash, (T, UInt)) + @warn "Missing method `Base.hash(::$T, ::UInt)`" + return false + elseif !hasmethod(Base.isless, (T, T)) + @warn "Missing method `Base.isless(::$T, ::$T)`" + return false + elseif !hasmethod(Base.:(==), (T, T)) + @warn "Missing method `Base.:(==)(::$T, ::$T)`" + return false + else + return true + end +end diff --git a/test/SimpleGraphs/SimpleGraphs.jl b/test/SimpleGraphs/SimpleGraphs.jl new file mode 100644 index 0000000..dca2e04 --- /dev/null +++ b/test/SimpleGraphs/SimpleGraphs.jl @@ -0,0 +1,6 @@ +using GraphsBase +using GraphsBase.SimpleGraphs +using Test + +@test check_graph_interface(SimpleGraph{Int}) +@test check_graph_interface(SimpleDiGraph{Int}) diff --git a/test/SimpleWeightedGraphs/SimpleWeightedGraphs.jl b/test/SimpleWeightedGraphs/SimpleWeightedGraphs.jl new file mode 100644 index 0000000..28b9559 --- /dev/null +++ b/test/SimpleWeightedGraphs/SimpleWeightedGraphs.jl @@ -0,0 +1,6 @@ +using GraphsBase +using GraphsBase.SimpleWeightedGraphs +using Test + +@test check_graph_interface(SimpleWeightedGraph{Int,Float64}) +@test check_graph_interface(SimpleWeightedDiGraph{Int,Float64}) diff --git a/test/interface/abstractedge.jl b/test/interface/abstractedge.jl new file mode 100644 index 0000000..8e06c82 --- /dev/null +++ b/test/interface/abstractedge.jl @@ -0,0 +1,6 @@ +using GraphsBase +using GraphsBase.SimpleGraphs +using Test + +@test check_edge_interface(SimpleEdge{Int}) +@test !check_edge_interface(Tuple{Int,Int}) diff --git a/test/interface/abstractgraph.jl b/test/interface/abstractgraph.jl new file mode 100644 index 0000000..4287777 --- /dev/null +++ b/test/interface/abstractgraph.jl @@ -0,0 +1,5 @@ +using GraphsBase +using GraphsBase.SimpleGraphs +using Test + +@test !check_graph_interface(Any) diff --git a/test/interface/utils.jl b/test/interface/utils.jl new file mode 100644 index 0000000..2fb0a15 --- /dev/null +++ b/test/interface/utils.jl @@ -0,0 +1,7 @@ +using GraphsBase: check_comparable_interface +using Test + +@test check_comparable_interface(Int) +@test check_comparable_interface(Symbol) +@test check_comparable_interface(String) +@test !check_comparable_interface(Any) diff --git a/test/runtests.jl b/test/runtests.jl index 8b9306f..a25375f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,5 +22,21 @@ DocMeta.setdocmeta!(GraphsBase, :DocTestSetup, :(using GraphsBase); recursive=tr JET.test_package(GraphsBase; target_modules=(GraphsBase,)) end end - # Put the actual tests here + @testset "Interface" begin + @testset "Utils" begin + include("interface/utils.jl") + end + @testset "AbstractEdge" begin + include("interface/abstractedge.jl") + end + @testset "AbstractGraph" begin + include("interface/abstractgraph.jl") + end + end + @testset "SimpleGraphs" begin + include("SimpleGraphs/SimpleGraphs.jl") + end + @testset "SimpleWeightedGraphs" begin + include("SimpleWeightedGraphs/SimpleWeightedGraphs.jl") + end end