// Mgmt // Copyright (C) James Shubin and the project contributors // Written by James Shubin and the project contributors // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // Additional permission under GNU GPL version 3 section 7 // // If you modify this program, or any covered work, by linking or combining it // with embedded mcl code and modules (and that the embedded mcl code and // modules which link with this program, contain a copy of their source code in // the authoritative form) containing parts covered by the terms of any other // license, the licensors of this program grant you additional permission to // convey the resulting work. Furthermore, the licensors of this program grant // the original author, James Shubin, additional permission to update this // additional permission if he deems it necessary to achieve the goals of this // additional permission. //go:build !root package pgraph import ( "reflect" "testing" ) func TestCount1(t *testing.T) { G := &Graph{} if i := G.NumVertices(); i != 0 { t.Errorf("should have 0 vertices instead of: %d", i) } if i := G.NumEdges(); i != 0 { t.Errorf("should have 0 edges instead of: %d", i) } v1 := NV("v1") v2 := NV("v2") e1 := NE("e1") G.AddEdge(v1, v2, e1) if i := G.NumVertices(); i != 2 { t.Errorf("should have 2 vertices instead of: %d", i) } if i := G.NumEdges(); i != 1 { t.Errorf("should have 1 edges instead of: %d", i) } } func TestAddVertex1(t *testing.T) { G := &Graph{Name: "g2"} v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") //e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) if i := G.NumVertices(); i != 6 { t.Errorf("should have 6 vertices instead of: %d", i) } } func TestAddEdge1(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") g.AddVertex(v1) g.AddVertex(v2) if i := g.NumEdges(); i != 0 { t.Errorf("should have 0 edges but got %d", i) } e1 := NE("e1") g.AddEdge(v1, v2, e1) if i := g.NumEdges(); i != 1 { t.Errorf("should have 1 edge but got %d", i) } } func TestDFS1(t *testing.T) { G, _ := NewGraph("g3") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") //e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) //G.AddEdge(v6, v4, e6) out1 := G.DFS(v1) if i := len(out1); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) t.Errorf("found: %v", out1) for _, v := range out1 { t.Errorf("value: %s", v) } } out2 := G.DFS(v4) if i := len(out2); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) t.Errorf("found: %v", out1) for _, v := range out1 { t.Errorf("value: %s", v) } } } func TestDFS2(t *testing.T) { G, _ := NewGraph("g4") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) out := G.DFS(v1) if i := len(out); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) t.Errorf("found: %v", out) for _, v := range out { t.Errorf("value: %s", v) } } } func TestFilterGraph1(t *testing.T) { G, _ := NewGraph("g5") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") //e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) //G.AddEdge(v6, v4, e6) save := []Vertex{v1, v2, v3} out, err := G.FilterGraph(save) if err != nil { t.Errorf("failed with: %v", err) } if i := out.NumVertices(); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) } } func TestFilterGraph2(t *testing.T) { G, _ := NewGraph("g5") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") e1 := NE("e1") G.AddEdge(v1, v2, e1) G.AddVertex(v3) G.AddVertex(v4) save := []Vertex{v1, v2, v3} out, err := G.FilterGraph(save) if err != nil { t.Errorf("failed with: %v", err) } if c, i := len(save), out.NumVertices(); c != i { t.Errorf("should have %d vertices instead of: %d", c, i) } } func TestFilterGraph3(t *testing.T) { G, _ := NewGraph("g5") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") e1 := NE("e1") e2 := NE("e2") G.AddEdge(v1, v2, e1) G.AddEdge(v3, v4, e2) G.AddVertex(v5) save := []Vertex{v1, v2, v3} out, err := G.FilterGraph(save) if err != nil { t.Errorf("failed with: %v", err) } if c, i := len(save), out.NumVertices(); c != i { t.Errorf("should have %d vertices instead of: %d", c, i) } if c, i := 1, out.NumEdges(); c != i { t.Errorf("should have %d edges instead of: %d", c, i) } } func TestDisconnectedGraphs1(t *testing.T) { G, _ := NewGraph("g6") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") //e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) //G.AddEdge(v6, v4, e6) graphs, err := G.DisconnectedGraphs() if err != nil { t.Errorf("failed with: %v", err) } if i := len(graphs); i != 2 { t.Errorf("should have 2 graphs instead of: %d", i) } } func TestDeleteVertex1(t *testing.T) { G, _ := NewGraph("g7") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v1, e3) if i := G.NumVertices(); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) } G.DeleteVertex(v2) if i := G.NumVertices(); i != 2 { t.Errorf("should have 2 vertices instead of: %d", i) } G.DeleteVertex(v1) if i := G.NumVertices(); i != 1 { t.Errorf("should have 1 vertices instead of: %d", i) } G.DeleteVertex(v3) if i := G.NumVertices(); i != 0 { t.Errorf("should have 0 vertices instead of: %d", i) } G.DeleteVertex(v2) // duplicate deletes don't error... if i := G.NumVertices(); i != 0 { t.Errorf("should have 0 vertices instead of: %d", i) } } func TestDeleteVertex2(t *testing.T) { G := &Graph{} v1 := NV("v1") G.DeleteVertex(v1) // check this doesn't panic if i := G.NumVertices(); i != 0 { t.Errorf("should have 0 vertices instead of: %d", i) } } func TestVertexContains1(t *testing.T) { v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") if VertexContains(v1, []Vertex{v1, v2, v3}) != true { t.Errorf("should be true instead of false.") } v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") if VertexContains(v4, []Vertex{v5, v6}) != false { t.Errorf("should be false instead of true.") } v7 := NV("v7") v8 := NV("v8") v9 := NV("v9") if VertexContains(v8, []Vertex{v7, v8, v9}) != true { t.Errorf("should be true instead of false.") } v1b := NV("v1") // same value, different objects if VertexContains(v1b, []Vertex{v1, v2, v3}) != false { t.Errorf("should be false instead of true.") } } func TestTopoSort1(t *testing.T) { G, _ := NewGraph("g9") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v1, v3, e2) G.AddEdge(v2, v4, e3) G.AddEdge(v3, v4, e4) G.AddEdge(v4, v5, e5) G.AddEdge(v5, v6, e6) indegree := G.InDegree() // map[Vertex]int if i := indegree[v1]; i != 0 { t.Errorf("indegree of v1 should be 0 instead of: %d", i) } if i := indegree[v2]; i != 1 { t.Errorf("indegree of v2 should be 1 instead of: %d", i) } if i := indegree[v3]; i != 1 { t.Errorf("indegree of v3 should be 1 instead of: %d", i) } if i := indegree[v4]; i != 2 { t.Errorf("indegree of v4 should be 2 instead of: %d", i) } if i := indegree[v5]; i != 1 { t.Errorf("indegree of v5 should be 1 instead of: %d", i) } if i := indegree[v6]; i != 1 { t.Errorf("indegree of v6 should be 1 instead of: %d", i) } outdegree := G.OutDegree() // map[Vertex]int if i := outdegree[v1]; i != 2 { t.Errorf("outdegree of v1 should be 2 instead of: %d", i) } if i := outdegree[v2]; i != 1 { t.Errorf("outdegree of v2 should be 1 instead of: %d", i) } if i := outdegree[v3]; i != 1 { t.Errorf("outdegree of v3 should be 1 instead of: %d", i) } if i := outdegree[v4]; i != 1 { t.Errorf("outdegree of v4 should be 1 instead of: %d", i) } if i := outdegree[v5]; i != 1 { t.Errorf("outdegree of v5 should be 1 instead of: %d", i) } if i := outdegree[v6]; i != 0 { t.Errorf("outdegree of v6 should be 0 instead of: %d", i) } s, err := G.TopologicalSort() // either possibility is a valid toposort match := reflect.DeepEqual(s, []Vertex{v1, v2, v3, v4, v5, v6}) || reflect.DeepEqual(s, []Vertex{v1, v3, v2, v4, v5, v6}) if err != nil || !match { t.Errorf("topological sort failed, error: %v", err) str := "Found:" for _, v := range s { str += " " + v.String() } t.Errorf(str) } } func TestTopoSort2(t *testing.T) { G, _ := NewGraph("g10") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v4, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) G.AddEdge(v4, v2, e6) // cycle if _, err := G.TopologicalSort(); err == nil { t.Errorf("topological sort passed, but graph is cyclic") } } func TestTopoSort3(t *testing.T) { G, _ := NewGraph("g11") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v4, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) G.AddEdge(v4, v2, e6) // cycle G.ExecGraphviz("/tmp/g.dot") _, err := G.TopologicalSort() if err == nil { t.Errorf("topological sort passed, but graph is cyclic") return } errNotAcyclic, ok := err.(*ErrNotAcyclic) if !ok { t.Errorf("wrong kind of error, got: %v", err) return } cycle := errNotAcyclic.Cycle t.Logf("cycle: %v", cycle) if len(cycle) < 2 { t.Errorf("cycle is too short") } cycle1 := []Vertex{v2, v3, v4, v2} cycle2 := []Vertex{v3, v4, v2, v3} cycle3 := []Vertex{v4, v2, v3, v4} b1 := reflect.DeepEqual(cycle, cycle1) b2 := reflect.DeepEqual(cycle, cycle2) b3 := reflect.DeepEqual(cycle, cycle3) if !b1 && !b2 && !b3 { t.Errorf("cycle didn't match") } } // empty func TestReachability0(t *testing.T) { { G, _ := NewGraph("g") result, err := G.Reachability(nil, nil) if err != nil { t.Logf("reachability failed: %+v", err) if result != nil { str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } } { G, _ := NewGraph("g") v1 := NV("v1") v6 := NV("v6") result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected := []Vertex{} if !reflect.DeepEqual(result, expected) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } { G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v1, v4, e3) G.AddEdge(v3, v4, e4) G.AddEdge(v3, v5, e5) result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected := []Vertex{} if !reflect.DeepEqual(result, expected) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } } // simple linear path func TestReachability1(t *testing.T) { G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") //e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v4, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected := []Vertex{v1, v2, v3, v4, v5, v6} if !reflect.DeepEqual(result, expected) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } // pick one of two correct paths func TestReachability2(t *testing.T) { G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v1, v3, e2) G.AddEdge(v2, v4, e3) G.AddEdge(v3, v4, e4) G.AddEdge(v4, v5, e5) G.AddEdge(v5, v6, e6) result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected1 := []Vertex{v1, v2, v4, v5, v6} expected2 := []Vertex{v1, v3, v4, v5, v6} // !xor test if reflect.DeepEqual(result, expected1) == reflect.DeepEqual(result, expected2) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } // pick shortest path func TestReachability3(t *testing.T) { G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v4, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v1, v5, e5) G.AddEdge(v5, v6, e6) result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected := []Vertex{v1, v5, v6} if !reflect.DeepEqual(result, expected) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } // direct path func TestReachability4(t *testing.T) { G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") G.AddEdge(v1, v2, e1) G.AddEdge(v2, v3, e2) G.AddEdge(v3, v4, e3) G.AddEdge(v4, v5, e4) G.AddEdge(v5, v6, e5) G.AddEdge(v1, v6, e6) result, err := G.Reachability(v1, v6) if err != nil { t.Logf("reachability failed: %+v", err) return } expected := []Vertex{v1, v6} if !reflect.DeepEqual(result, expected) { t.Logf("reachability failed") str := "Got:" for _, v := range result { str += " " + v.String() } t.Errorf(str) } } func TestReverse1(t *testing.T) { v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") if rev := Reverse([]Vertex{}); !reflect.DeepEqual(rev, []Vertex{}) { t.Errorf("reverse of vertex slice failed (empty)") } if rev := Reverse([]Vertex{v1}); !reflect.DeepEqual(rev, []Vertex{v1}) { t.Errorf("reverse of vertex slice failed (single)") } if rev := Reverse([]Vertex{v1, v2, v3, v4, v5, v6}); !reflect.DeepEqual(rev, []Vertex{v6, v5, v4, v3, v2, v1}) { t.Errorf("reverse of vertex slice failed (1..6)") } if rev := Reverse([]Vertex{v6, v5, v4, v3, v2, v1}); !reflect.DeepEqual(rev, []Vertex{v1, v2, v3, v4, v5, v6}) { t.Errorf("reverse of vertex slice failed (6..1)") } } func TestCopy1(t *testing.T) { g1 := &Graph{} g2 := g1.Copy() // check this doesn't panic if !reflect.DeepEqual(g1.String(), g2.String()) { t.Errorf("graph copy failed") } } func TestGraphCmp1(t *testing.T) { g1 := &Graph{} g2 := &Graph{} g3 := &Graph{} g3.AddVertex(NV("v1")) g4 := &Graph{} g4.AddVertex(NV("v2")) if err := g1.GraphCmp(g2, strVertexCmpFn, strEdgeCmpFn); err != nil { t.Errorf("should have no error during GraphCmp, but got: %v", err) } if err := g1.GraphCmp(g3, strVertexCmpFn, strEdgeCmpFn); err == nil { t.Errorf("should have error during GraphCmp, but got nil") } if err := g3.GraphCmp(g4, strVertexCmpFn, strEdgeCmpFn); err == nil { t.Errorf("should have error during GraphCmp, but got nil") } } // FIXME: i think we should allow equivalent elements in the graph to compare... // FIXME: currently this fails :( //func TestGraphCmp2(t *testing.T) { // g1 := &Graph{} // g2 := &Graph{} // g1.AddVertex(NV("v1"), NV("v1")) // g2.AddVertex(NV("v1"), NV("v1")) // // if err := g1.GraphCmp(g2, strVertexCmpFn, strEdgeCmpFn); err != nil { // t.Errorf("should have no error during GraphCmp, but got: %v", err) // } //} func TestSort0(t *testing.T) { vs := []Vertex{} s := Sort(vs) if !reflect.DeepEqual(s, []Vertex{}) { t.Errorf("sort failed!") if s == nil { t.Logf("output is nil!") } else { str := "Got:" for _, v := range s { str += " " + v.String() } t.Errorf(str) } } } func TestSort1(t *testing.T) { v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") vs := []Vertex{v3, v2, v6, v1, v5, v4} s := Sort(vs) if !reflect.DeepEqual(s, []Vertex{v1, v2, v3, v4, v5, v6}) { t.Errorf("sort failed!") str := "Got:" for _, v := range s { str += " " + v.String() } t.Errorf(str) } if !reflect.DeepEqual(vs, []Vertex{v3, v2, v6, v1, v5, v4}) { t.Errorf("sort modified input!") str := "Got:" for _, v := range vs { str += " " + v.String() } t.Errorf(str) } } func TestSprint1(t *testing.T) { g, _ := NewGraph("graph1") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") g.AddEdge(v1, v2, e1) g.AddEdge(v2, v3, e2) g.AddEdge(v3, v4, e3) g.AddEdge(v4, v5, e4) g.AddEdge(v5, v6, e5) str := g.Sprint() t.Logf("graph is:\n%s", str) count := 0 for count < 100000 { // about one second x := g.Sprint() if str != x { t.Errorf("graph sprint is not consistent") return } count++ } } func TestDeleteEdge1(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") g.AddEdge(v1, v2, e1) g.AddEdge(v2, v3, e2) g.AddEdge(v1, v3, e3) g.AddEdge(v2, v1, e4) g.AddEdge(v3, v2, e5) g.AddEdge(v3, v1, e6) g.DeleteEdge(e1) g.DeleteEdge(e2) g.DeleteEdge(e3) g.DeleteEdge(e3) if g.NumEdges() != 3 { t.Errorf("expected number of edges: 3, instead of: %d", g.NumEdges()) } } func TestDeleteEdge2(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") e7 := NE("e7") g.AddEdge(v1, v2, e1) g.AddEdge(v1, v2, e2) g.AddEdge(v1, v3, e3) g.AddEdge(v1, v4, e4) g.AddEdge(v2, v1, e5) g.AddEdge(v3, v1, e6) g.AddEdge(v4, v1, e7) g.DeleteEdge(e1) g.DeleteEdge(e2) g.DeleteEdge(e3) g.DeleteEdge(e5) g.DeleteEdge(e6) ie := g.IncomingGraphEdges(v1) oe := g.OutgoingGraphEdges(v1) if !reflect.DeepEqual(ie, []Edge{e7}) { res := "" for _, e := range ie { res += e.String() + " " } t.Errorf("expected incoming graph edges for vertex v1: e7, instead of: %s", res) } if !reflect.DeepEqual(oe, []Edge{e4}) { res := "" for _, e := range oe { res += e.String() + " " } t.Errorf("expected outgoing graph edges for vertex v1: e4, instead of: %s", res) } } func TestFindEdge1(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") v7 := NV("v7") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") e7 := NE("e7") e8 := NE("e8") e9 := NE("e9") e10 := NE("e10") g.AddEdge(v1, v2, e1) g.AddEdge(v1, v4, e2) g.AddEdge(v1, v3, e3) g.AddEdge(v2, v3, e4) g.AddEdge(v2, v4, e5) g.AddEdge(v2, v6, e6) g.AddEdge(v2, v5, e7) g.AddEdge(v3, v6, e8) g.AddEdge(v4, v7, e9) g.AddEdge(v5, v7, e10) if !(g.HasVertex(v1) && g.HasVertex(v4) && g.HasVertex(v7)) { t.Errorf("graph expected to have vertices v1, v4, and v7") } if g.FindEdge(v1, v4) != e2 { t.Errorf("edge e2 was not returned") } if g.FindEdge(v1, v7) != nil { t.Errorf("an edge was found although it did not exist") } } func TestFindEdge2(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") g.AddEdge(v1, v4, e1) g.AddEdge(v2, v5, e2) g.AddEdge(v3, v6, e3) if g.FindEdge(v1, v4) != e1 { t.Errorf("edge e1 was not returned") } if g.FindEdge(v2, v5) != e2 { t.Errorf("edge e1 was not returned") } if g.FindEdge(v3, v6) != e3 { t.Errorf("edge e1 was not returned") } if g.FindEdge(v2, v6) != nil { t.Errorf("an edge was found although it did not exist") } } func TestLookupEdge1(t *testing.T) { g, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") v4 := NV("v4") v5 := NV("v5") v6 := NV("v6") v7 := NV("v7") e1 := NE("e1") e2 := NE("e2") e3 := NE("e3") e4 := NE("e4") e5 := NE("e5") e6 := NE("e6") e7 := NE("e7") e8 := NE("e8") e9 := NE("e9") e10 := NE("e10") g.AddEdge(v1, v2, e1) g.AddEdge(v1, v4, e2) g.AddEdge(v1, v3, e3) g.AddEdge(v2, v3, e4) g.AddEdge(v2, v4, e5) g.AddEdge(v2, v6, e6) g.AddEdge(v2, v5, e7) g.AddEdge(v3, v6, e8) g.AddEdge(v4, v7, e9) g.AddEdge(v5, v7, e10) if x, y, found := g.LookupEdge(e1); !found || x != v1 || y != v2 { t.Errorf("vertices v1, v2 were not returned") } if x, y, found := g.LookupEdge(e2); !found || x != v1 || y != v4 { t.Errorf("vertices v1, v4 were not returned") } if x, y, found := g.LookupEdge(e3); !found || x != v1 || y != v3 { t.Errorf("vertices v1, v3 were not returned") } if x, y, found := g.LookupEdge(e4); !found || x != v2 || y != v3 { t.Errorf("vertices v2, v3 were not returned") } if x, y, found := g.LookupEdge(e5); !found || x != v2 || y != v4 { t.Errorf("vertices v2, v4 were not returned") } if x, y, found := g.LookupEdge(e6); !found || x != v2 || y != v6 { t.Errorf("vertices v2, v6 were not returned") } if x, y, found := g.LookupEdge(e7); !found || x != v2 || y != v5 { t.Errorf("vertices v2, v5 were not returned") } if x, y, found := g.LookupEdge(e8); !found || x != v3 || y != v6 { t.Errorf("vertices v3, v6 were not returned") } if x, y, found := g.LookupEdge(e9); !found || x != v4 || y != v7 { t.Errorf("vertices v4, v7 were not returned") } if x, y, found := g.LookupEdge(e10); !found || x != v5 || y != v7 { t.Errorf("vertices v5, v7 were not returned") } e99 := NE("e99") if _, _, found := g.LookupEdge(e99); found { t.Errorf("unexpected vertices were found") } } func TestSetValue(t *testing.T) { g, _ := NewGraph("SetValue") key := "k1" value := "v1" g.SetValue(key, value) if g.kv[key] != value { t.Errorf("expecting value of %s at %s position, got %v", value, key, g.kv[key]) } if v, ok := g.Value(key); !ok { t.Errorf("key %s doesn't exist", key) } else if v != value { t.Errorf("expecting value of %s at %s position, got %v", value, key, v) } }