From c1bdb46623e3f613d52076dbc6a13461749b11fe Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Sat, 18 Aug 2018 13:51:38 -0400 Subject: [PATCH] graph: implement SubGraph and Equal --- graph/graph.go | 29 +++++++++++++++++ graph/graph_test.go | 77 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/graph/graph.go b/graph/graph.go index 7f04060..ec1ae4c 100644 --- a/graph/graph.go +++ b/graph/graph.go @@ -204,3 +204,32 @@ func (g Graph) Traverse(start Value, next func(v Value, in, out []Edge) (Value, } } } + +func (g Graph) edgesShared(g2 Graph) bool { + for id := range g2.m { + if _, ok := g.m[id]; !ok { + return false + } + } + return true +} + +// SubGraph returns true if the given Graph shares all of its Edges with this +// Graph. +func (g Graph) SubGraph(g2 Graph) bool { + // as a quick check before iterating through the edges, if g has fewer edges + // than g2 then g2 can't possibly be a sub-graph of it + if len(g.m) < len(g2.m) { + return false + } + return g.edgesShared(g2) +} + +// Equal returns true if the given Graph and this Graph have exactly the same +// Edges. +func (g Graph) Equal(g2 Graph) bool { + if len(g.m) != len(g2.m) { + return false + } + return g.edgesShared(g2) +} diff --git a/graph/graph_test.go b/graph/graph_test.go index 111c871..a9b0e0b 100644 --- a/graph/graph_test.go +++ b/graph/graph_test.go @@ -1,6 +1,7 @@ package graph import ( + "fmt" . "testing" "time" @@ -9,7 +10,12 @@ import ( "github.com/mediocregopher/mediocre-go-lib/mtest/mchk" ) +func strV(s string) Value { + return Value{ID: s, V: s} +} + func TestGraph(t *T) { + t.Parallel() type state struct { Graph @@ -21,10 +27,6 @@ func TestGraph(t *T) { del Edge } - strV := func(s string) Value { - return Value{ID: s, V: s} - } - chk := mchk.Checker{ Init: func() mchk.State { return state{ @@ -118,15 +120,64 @@ func TestGraph(t *T) { return s, nil }, - MaxLength: 10, - } - - err := chk.RunCase( - params{add: Edge{Tail: strV("4"), Val: strV("d"), Head: strV("4")}}, - params{del: Edge{Tail: strV("4"), Val: strV("d"), Head: strV("4")}}, - ) - if err != nil { - t.Fatal(err) + } + + if err := chk.RunFor(5 * time.Second); err != nil { + t.Fatal(err) + } +} + +func TestSubGraphAndEqual(t *T) { + t.Parallel() + type state struct { + g1, g2 Graph + expEqual, expSubGraph bool + } + + type params struct { + e Edge + add1, add2 bool + } + + chk := mchk.Checker{ + Init: func() mchk.State { + return state{expEqual: true, expSubGraph: true} + }, + Next: func(ss mchk.State) mchk.Action { + i := mrand.Intn(10) + p := params{ + e: Edge{ + Tail: strV(mrand.Hex(1)), + Val: strV(mrand.Hex(8)), + Head: strV(mrand.Hex(1)), + }, + add1: i != 0, + add2: i != 1, + } + return mchk.Action{Params: p} + }, + Apply: func(ss mchk.State, a mchk.Action) (mchk.State, error) { + s, p := ss.(state), a.Params.(params) + if p.add1 { + s.g1 = s.g1.AddEdge(p.e) + } + if p.add2 { + s.g2 = s.g2.AddEdge(p.e) + } + s.expSubGraph = s.expSubGraph && p.add1 + s.expEqual = s.expEqual && p.add1 && p.add2 + + if s.g1.SubGraph(s.g2) != s.expSubGraph { + return nil, fmt.Errorf("SubGraph expected to return %v", s.expSubGraph) + } + + if s.g1.Equal(s.g2) != s.expEqual { + return nil, fmt.Errorf("Equal expected to return %v", s.expEqual) + } + + return s, nil + }, + MaxLength: 100, } if err := chk.RunFor(5 * time.Second); err != nil {