github.com/gopherd/gonum@v0.0.4/graph/testgraph/testgraph.go (about)

     1  // Copyright ©2018 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package testgraph provides a set of testing helper functions
     6  // that test Gonum graph interface implementations.
     7  package testgraph // import "github.com/gopherd/gonum/graph/testgraph"
     8  
     9  import (
    10  	"fmt"
    11  	"reflect"
    12  	"sort"
    13  	"testing"
    14  
    15  	"math/rand"
    16  
    17  	"github.com/gopherd/gonum/floats/scalar"
    18  	"github.com/gopherd/gonum/graph"
    19  	"github.com/gopherd/gonum/graph/internal/ordered"
    20  	"github.com/gopherd/gonum/graph/internal/set"
    21  	"github.com/gopherd/gonum/mat"
    22  )
    23  
    24  // BUG(kortschak): Edge equality is tested in part with reflect.DeepEqual and
    25  // direct equality of weight values. This means that edges returned by graphs
    26  // must not contain NaN values. Weights returned by the Weight method are
    27  // compared with NaN-awareness, so they may be NaN when there is no edge
    28  // associated with the Weight call.
    29  
    30  func isValidIterator(it graph.Iterator) bool {
    31  	return it != nil
    32  }
    33  
    34  func checkEmptyIterator(t *testing.T, it graph.Iterator, useEmpty bool) {
    35  	t.Helper()
    36  
    37  	if it.Len() != 0 {
    38  		return
    39  	}
    40  	if it != graph.Empty {
    41  		if useEmpty {
    42  			t.Errorf("unexpected empty iterator: got:%T", it)
    43  			return
    44  		}
    45  		// Only log this since we say that a graph should
    46  		// return a graph.Empty when it is empty.
    47  		t.Logf("unexpected empty iterator: got:%T", it)
    48  	}
    49  }
    50  
    51  func hasEnds(x, y graph.Node, e Edge) bool {
    52  	return (e.From().ID() == x.ID() && e.To().ID() == y.ID()) ||
    53  		(e.From().ID() == y.ID() && e.To().ID() == x.ID())
    54  }
    55  
    56  // Edge supports basic edge operations.
    57  type Edge interface {
    58  	// From returns the from node of the edge.
    59  	From() graph.Node
    60  
    61  	// To returns the to node of the edge.
    62  	To() graph.Node
    63  }
    64  
    65  // WeightedLine is a generalized graph edge that supports all graph
    66  // edge operations except reversal.
    67  type WeightedLine interface {
    68  	Edge
    69  
    70  	// ID returns the unique ID for the Line.
    71  	ID() int64
    72  
    73  	// Weight returns the weight of the edge.
    74  	Weight() float64
    75  }
    76  
    77  // A Builder function returns a graph constructed from the nodes, edges and
    78  // default weights passed in, potentially altering the nodes and edges to
    79  // conform to the requirements of the graph. The graph is returned along with
    80  // the nodes, edges and default weights used to construct the graph.
    81  // The returned edges may be any of graph.Edge, graph.WeightedEdge, graph.Line
    82  // or graph.WeightedLine depending on what the graph requires.
    83  // The client may skip a test case by returning ok=false when the input is not
    84  // a valid graph construction.
    85  type Builder func(nodes []graph.Node, edges []WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []Edge, s, a float64, ok bool)
    86  
    87  // edgeLister is a graph that can return all its edges.
    88  type edgeLister interface {
    89  	// Edges returns all the edges of a graph.
    90  	Edges() graph.Edges
    91  }
    92  
    93  // weightedEdgeLister is a graph that can return all its weighted edges.
    94  type weightedEdgeLister interface {
    95  	// WeightedEdges returns all the weighted edges of a graph.
    96  	WeightedEdges() graph.WeightedEdges
    97  }
    98  
    99  // matrixer is a graph that can return an adjacency matrix.
   100  type matrixer interface {
   101  	// Matrix returns the graph's adjacency matrix.
   102  	Matrix() mat.Matrix
   103  }
   104  
   105  // ReturnAllNodes tests the constructed graph for the ability to return all
   106  // the nodes it claims it has used in its construction. This is a check of
   107  // the Nodes method of graph.Graph and the iterator that is returned.
   108  // If useEmpty is true, graph iterators will be checked for the use of
   109  // graph.Empty if they are empty.
   110  func ReturnAllNodes(t *testing.T, b Builder, useEmpty bool) {
   111  	for _, test := range testCases {
   112  		g, want, _, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   113  		if !ok {
   114  			t.Logf("skipping test case: %q", test.name)
   115  			continue
   116  		}
   117  
   118  		it := g.Nodes()
   119  		if !isValidIterator(it) {
   120  			t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   121  			continue
   122  		}
   123  		checkEmptyIterator(t, it, useEmpty)
   124  		var got []graph.Node
   125  		for it.Next() {
   126  			got = append(got, it.Node())
   127  		}
   128  
   129  		ordered.ByID(got)
   130  		ordered.ByID(want)
   131  
   132  		if !reflect.DeepEqual(got, want) {
   133  			t.Errorf("unexpected nodes result for test %q:\ngot: %v\nwant:%v", test.name, got, want)
   134  		}
   135  	}
   136  }
   137  
   138  // ReturnNodeSlice tests the constructed graph for the ability to return all
   139  // the nodes it claims it has used in its construction using the NodeSlicer
   140  // interface. This is a check of the Nodes method of graph.Graph and the
   141  // iterator that is returned.
   142  // If useEmpty is true, graph iterators will be checked for the use of
   143  // graph.Empty if they are empty.
   144  func ReturnNodeSlice(t *testing.T, b Builder, useEmpty bool) {
   145  	for _, test := range testCases {
   146  		g, want, _, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   147  		if !ok {
   148  			t.Logf("skipping test case: %q", test.name)
   149  			continue
   150  		}
   151  
   152  		it := g.Nodes()
   153  		if !isValidIterator(it) {
   154  			t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   155  			continue
   156  		}
   157  		checkEmptyIterator(t, it, useEmpty)
   158  		if it == nil {
   159  			continue
   160  		}
   161  		s, ok := it.(graph.NodeSlicer)
   162  		if !ok {
   163  			t.Errorf("invalid type for test %q: %T cannot return node slicer", test.name, g)
   164  			continue
   165  		}
   166  		got := s.NodeSlice()
   167  
   168  		ordered.ByID(got)
   169  		ordered.ByID(want)
   170  
   171  		if !reflect.DeepEqual(got, want) {
   172  			t.Errorf("unexpected nodes result for test %q:\ngot: %v\nwant:%v", test.name, got, want)
   173  		}
   174  	}
   175  }
   176  
   177  // NodeExistence tests the constructed graph for the ability to correctly
   178  // return the existence of nodes within the graph. This is a check of the
   179  // Node method of graph.Graph.
   180  func NodeExistence(t *testing.T, b Builder) {
   181  	for _, test := range testCases {
   182  		g, want, _, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   183  		if !ok {
   184  			t.Logf("skipping test case: %q", test.name)
   185  			continue
   186  		}
   187  
   188  		seen := set.NewNodes()
   189  		for _, exist := range want {
   190  			seen.Add(exist)
   191  			if g.Node(exist.ID()) == nil {
   192  				t.Errorf("missing node for test %q: %v", test.name, exist)
   193  			}
   194  		}
   195  		for _, ghost := range test.nonexist {
   196  			if g.Node(ghost.ID()) != nil {
   197  				if seen.Has(ghost) {
   198  					// Do not fail nodes that the graph builder says can exist
   199  					// even if the test case input thinks they should not.
   200  					t.Logf("builder has modified non-exist node set: %v is now allowed and present", ghost)
   201  					continue
   202  				}
   203  				t.Errorf("unexpected node for test %q: %v", test.name, ghost)
   204  			}
   205  		}
   206  	}
   207  }
   208  
   209  // ReturnAllEdges tests the constructed graph for the ability to return all
   210  // the edges it claims it has used in its construction. This is a check of
   211  // the Edges method of graph.Graph and the iterator that is returned.
   212  // ReturnAllEdges  also checks that the edge end nodes exist within the graph,
   213  // checking the Node method of graph.Graph.
   214  // If useEmpty is true, graph iterators will be checked for the use of
   215  // graph.Empty if they are empty.
   216  func ReturnAllEdges(t *testing.T, b Builder, useEmpty bool) {
   217  	for _, test := range testCases {
   218  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   219  		if !ok {
   220  			t.Logf("skipping test case: %q", test.name)
   221  			continue
   222  		}
   223  
   224  		var got []Edge
   225  		switch eg := g.(type) {
   226  		case edgeLister:
   227  			it := eg.Edges()
   228  			if !isValidIterator(it) {
   229  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   230  				continue
   231  			}
   232  			checkEmptyIterator(t, it, useEmpty)
   233  			for it.Next() {
   234  				e := it.Edge()
   235  				got = append(got, e)
   236  				qe := g.Edge(e.From().ID(), e.To().ID())
   237  				if qe == nil {
   238  					t.Errorf("missing edge for test %q: %v", test.name, e)
   239  				} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   240  					t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   241  						test.name, e.From().ID(), e.To().ID(), qe)
   242  				}
   243  				if g.Node(e.From().ID()) == nil {
   244  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   245  				}
   246  				if g.Node(e.To().ID()) == nil {
   247  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   248  				}
   249  			}
   250  
   251  		default:
   252  			t.Errorf("invalid type for test %q: %T cannot return edge iterator", test.name, g)
   253  			continue
   254  		}
   255  
   256  		checkEdges(t, test.name, g, got, want)
   257  	}
   258  }
   259  
   260  // ReturnEdgeSlice tests the constructed graph for the ability to return all
   261  // the edges it claims it has used in its construction using the EdgeSlicer
   262  // interface. This is a check of the Edges method of graph.Graph and the
   263  // iterator that is returned. ReturnEdgeSlice also checks that the edge end
   264  // nodes exist within the graph, checking the Node method of graph.Graph.
   265  // If useEmpty is true, graph iterators will be checked for the use of
   266  // graph.Empty if they are empty.
   267  func ReturnEdgeSlice(t *testing.T, b Builder, useEmpty bool) {
   268  	for _, test := range testCases {
   269  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   270  		if !ok {
   271  			t.Logf("skipping test case: %q", test.name)
   272  			continue
   273  		}
   274  
   275  		var got []Edge
   276  		switch eg := g.(type) {
   277  		case edgeLister:
   278  			it := eg.Edges()
   279  			if !isValidIterator(it) {
   280  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   281  				continue
   282  			}
   283  			checkEmptyIterator(t, it, useEmpty)
   284  			if it == nil {
   285  				continue
   286  			}
   287  			s, ok := it.(graph.EdgeSlicer)
   288  			if !ok {
   289  				t.Errorf("invalid type for test %q: %T cannot return edge slicer", test.name, g)
   290  				continue
   291  			}
   292  			gotNative := s.EdgeSlice()
   293  			if len(gotNative) != 0 {
   294  				got = make([]Edge, len(gotNative))
   295  			}
   296  			for i, e := range gotNative {
   297  				got[i] = e
   298  
   299  				qe := g.Edge(e.From().ID(), e.To().ID())
   300  				if qe == nil {
   301  					t.Errorf("missing edge for test %q: %v", test.name, e)
   302  				} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   303  					t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   304  						test.name, e.From().ID(), e.To().ID(), qe)
   305  				}
   306  				if g.Node(e.From().ID()) == nil {
   307  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   308  				}
   309  				if g.Node(e.To().ID()) == nil {
   310  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   311  				}
   312  			}
   313  
   314  		default:
   315  			t.Errorf("invalid type for test %T: cannot return edge iterator", g)
   316  			continue
   317  		}
   318  
   319  		checkEdges(t, test.name, g, got, want)
   320  	}
   321  }
   322  
   323  // ReturnAllLines tests the constructed graph for the ability to return all
   324  // the edges it claims it has used in its construction and then recover all
   325  // the lines that contribute to those edges. This is a check of the Edges
   326  // method of graph.Graph and the iterator that is returned and the graph.Lines
   327  // implementation of those edges. ReturnAllLines also checks that the edge
   328  // end nodes exist within the graph, checking the Node method of graph.Graph.
   329  //
   330  // The edges used within and returned by the Builder function should be
   331  // graph.Line. The edge parameter passed to b will contain only graph.Line.
   332  // If useEmpty is true, graph iterators will be checked for the use of
   333  // graph.Empty if they are empty.
   334  func ReturnAllLines(t *testing.T, b Builder, useEmpty bool) {
   335  	for _, test := range testCases {
   336  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   337  		if !ok {
   338  			t.Logf("skipping test case: %q", test.name)
   339  			continue
   340  		}
   341  
   342  		var got []Edge
   343  		switch eg := g.(type) {
   344  		case edgeLister:
   345  			it := eg.Edges()
   346  			if !isValidIterator(it) {
   347  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   348  				continue
   349  			}
   350  			checkEmptyIterator(t, it, useEmpty)
   351  			for _, e := range graph.EdgesOf(it) {
   352  				qe := g.Edge(e.From().ID(), e.To().ID())
   353  				if qe == nil {
   354  					t.Errorf("missing edge for test %q: %v", test.name, e)
   355  				} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   356  					t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   357  						test.name, e.From().ID(), e.To().ID(), qe)
   358  				}
   359  
   360  				// FIXME(kortschak): This would not be necessary
   361  				// if graph.WeightedLines (and by symmetry)
   362  				// graph.WeightedEdges also were graph.Lines
   363  				// and graph.Edges.
   364  				switch lit := e.(type) {
   365  				case graph.Lines:
   366  					if !isValidIterator(lit) {
   367  						t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   368  						continue
   369  					}
   370  					checkEmptyIterator(t, lit, useEmpty)
   371  					for lit.Next() {
   372  						got = append(got, lit.Line())
   373  					}
   374  				case graph.WeightedLines:
   375  					if !isValidIterator(lit) {
   376  						t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   377  						continue
   378  					}
   379  					checkEmptyIterator(t, lit, useEmpty)
   380  					for lit.Next() {
   381  						got = append(got, lit.WeightedLine())
   382  					}
   383  				default:
   384  					continue
   385  				}
   386  
   387  				if g.Node(e.From().ID()) == nil {
   388  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   389  				}
   390  				if g.Node(e.To().ID()) == nil {
   391  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   392  				}
   393  			}
   394  
   395  		default:
   396  			t.Errorf("invalid type for test: %T cannot return edge iterator", g)
   397  			continue
   398  		}
   399  
   400  		checkEdges(t, test.name, g, got, want)
   401  	}
   402  }
   403  
   404  // ReturnAllWeightedEdges tests the constructed graph for the ability to return
   405  // all the edges it claims it has used in its construction. This is a check of
   406  // the Edges method of graph.Graph and the iterator that is returned.
   407  // ReturnAllWeightedEdges also checks that the edge end nodes exist within the
   408  // graph, checking the Node method of graph.Graph.
   409  //
   410  // The edges used within and returned by the Builder function should be
   411  // graph.WeightedEdge. The edge parameter passed to b will contain only
   412  // graph.WeightedEdge.
   413  // If useEmpty is true, graph iterators will be checked for the use of
   414  // graph.Empty if they are empty.
   415  func ReturnAllWeightedEdges(t *testing.T, b Builder, useEmpty bool) {
   416  	for _, test := range testCases {
   417  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   418  		if !ok {
   419  			t.Logf("skipping test case: %q", test.name)
   420  			continue
   421  		}
   422  
   423  		var got []Edge
   424  		switch eg := g.(type) {
   425  		case weightedEdgeLister:
   426  			it := eg.WeightedEdges()
   427  			if !isValidIterator(it) {
   428  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   429  				continue
   430  			}
   431  			checkEmptyIterator(t, it, useEmpty)
   432  			for it.Next() {
   433  				e := it.WeightedEdge()
   434  				got = append(got, e)
   435  				switch g := g.(type) {
   436  				case graph.Weighted:
   437  					qe := g.WeightedEdge(e.From().ID(), e.To().ID())
   438  					if qe == nil {
   439  						t.Errorf("missing edge for test %q: %v", test.name, e)
   440  					} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   441  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   442  							test.name, e.From().ID(), e.To().ID(), qe)
   443  					}
   444  				default:
   445  					t.Logf("weighted edge lister is not a weighted graph - are you sure?: %T", g)
   446  					qe := g.Edge(e.From().ID(), e.To().ID())
   447  					if qe == nil {
   448  						t.Errorf("missing edge for test %q: %v", test.name, e)
   449  					} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   450  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   451  							test.name, e.From().ID(), e.To().ID(), qe)
   452  					}
   453  				}
   454  				if g.Node(e.From().ID()) == nil {
   455  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   456  				}
   457  				if g.Node(e.To().ID()) == nil {
   458  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   459  				}
   460  			}
   461  
   462  		default:
   463  			t.Errorf("invalid type for test: %T cannot return weighted edge iterator", g)
   464  			continue
   465  		}
   466  
   467  		checkEdges(t, test.name, g, got, want)
   468  	}
   469  }
   470  
   471  // ReturnWeightedEdgeSlice tests the constructed graph for the ability to
   472  // return all the edges it claims it has used in its construction using the
   473  // WeightedEdgeSlicer interface. This is a check of the Edges method of
   474  // graph.Graph and the iterator that is returned. ReturnWeightedEdgeSlice
   475  // also checks that the edge end nodes exist within the graph, checking
   476  // the Node method of graph.Graph.
   477  //
   478  // The edges used within and returned by the Builder function should be
   479  // graph.WeightedEdge. The edge parameter passed to b will contain only
   480  // graph.WeightedEdge.
   481  // If useEmpty is true, graph iterators will be checked for the use of
   482  // graph.Empty if they are empty.
   483  func ReturnWeightedEdgeSlice(t *testing.T, b Builder, useEmpty bool) {
   484  	for _, test := range testCases {
   485  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   486  		if !ok {
   487  			t.Logf("skipping test case: %q", test.name)
   488  			continue
   489  		}
   490  
   491  		var got []Edge
   492  		switch eg := g.(type) {
   493  		case weightedEdgeLister:
   494  			it := eg.WeightedEdges()
   495  			if !isValidIterator(it) {
   496  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   497  				continue
   498  			}
   499  			checkEmptyIterator(t, it, useEmpty)
   500  			s, ok := it.(graph.WeightedEdgeSlicer)
   501  			if !ok {
   502  				t.Errorf("invalid type for test %T: cannot return weighted edge slice", g)
   503  				continue
   504  			}
   505  			for _, e := range s.WeightedEdgeSlice() {
   506  				got = append(got, e)
   507  				qe := g.Edge(e.From().ID(), e.To().ID())
   508  				if qe == nil {
   509  					t.Errorf("missing edge for test %q: %v", test.name, e)
   510  				} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   511  					t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   512  						test.name, e.From().ID(), e.To().ID(), qe)
   513  				}
   514  				if g.Node(e.From().ID()) == nil {
   515  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   516  				}
   517  				if g.Node(e.To().ID()) == nil {
   518  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   519  				}
   520  			}
   521  
   522  		default:
   523  			t.Errorf("invalid type for test: %T cannot return weighted edge iterator", g)
   524  			continue
   525  		}
   526  
   527  		checkEdges(t, test.name, g, got, want)
   528  	}
   529  }
   530  
   531  // ReturnAllWeightedLines tests the constructed graph for the ability to return
   532  // all the edges it claims it has used in its construction and then recover all
   533  // the lines that contribute to those edges. This is a check of the Edges
   534  // method of graph.Graph and the iterator that is returned and the graph.Lines
   535  // implementation of those edges. ReturnAllWeightedLines also checks that the
   536  // edge end nodes exist within the graph, checking the Node method of
   537  // graph.Graph.
   538  //
   539  // The edges used within and returned by the Builder function should be
   540  // graph.WeightedLine. The edge parameter passed to b will contain only
   541  // graph.WeightedLine.
   542  // If useEmpty is true, graph iterators will be checked for the use of
   543  // graph.Empty if they are empty.
   544  func ReturnAllWeightedLines(t *testing.T, b Builder, useEmpty bool) {
   545  	for _, test := range testCases {
   546  		g, _, want, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   547  		if !ok {
   548  			t.Logf("skipping test case: %q", test.name)
   549  			continue
   550  		}
   551  
   552  		var got []Edge
   553  		switch eg := g.(type) {
   554  		case weightedEdgeLister:
   555  			it := eg.WeightedEdges()
   556  			if !isValidIterator(it) {
   557  				t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   558  				continue
   559  			}
   560  			checkEmptyIterator(t, it, useEmpty)
   561  			for _, e := range graph.WeightedEdgesOf(it) {
   562  				qe := g.Edge(e.From().ID(), e.To().ID())
   563  				if qe == nil {
   564  					t.Errorf("missing edge for test %q: %v", test.name, e)
   565  				} else if qe.From().ID() != e.From().ID() || qe.To().ID() != e.To().ID() {
   566  					t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   567  						test.name, e.From().ID(), e.To().ID(), qe)
   568  				}
   569  
   570  				// FIXME(kortschak): This would not be necessary
   571  				// if graph.WeightedLines (and by symmetry)
   572  				// graph.WeightedEdges also were graph.Lines
   573  				// and graph.Edges.
   574  				switch lit := e.(type) {
   575  				case graph.Lines:
   576  					if !isValidIterator(lit) {
   577  						t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   578  						continue
   579  					}
   580  					checkEmptyIterator(t, lit, useEmpty)
   581  					for lit.Next() {
   582  						got = append(got, lit.Line())
   583  					}
   584  				case graph.WeightedLines:
   585  					if !isValidIterator(lit) {
   586  						t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   587  						continue
   588  					}
   589  					checkEmptyIterator(t, lit, useEmpty)
   590  					for lit.Next() {
   591  						got = append(got, lit.WeightedLine())
   592  					}
   593  				default:
   594  					continue
   595  				}
   596  
   597  				if g.Node(e.From().ID()) == nil {
   598  					t.Errorf("missing from node for test %q: %v", test.name, e.From().ID())
   599  				}
   600  				if g.Node(e.To().ID()) == nil {
   601  					t.Errorf("missing to node for test %q: %v", test.name, e.To().ID())
   602  				}
   603  			}
   604  
   605  		default:
   606  			t.Errorf("invalid type for test: %T cannot return edge iterator", g)
   607  			continue
   608  		}
   609  
   610  		checkEdges(t, test.name, g, got, want)
   611  	}
   612  }
   613  
   614  // checkEdges compares got and want for the given graph type.
   615  func checkEdges(t *testing.T, name string, g graph.Graph, got, want []Edge) {
   616  	t.Helper()
   617  	switch g.(type) {
   618  	case graph.Undirected:
   619  		sort.Sort(lexicalUndirectedEdges(got))
   620  		sort.Sort(lexicalUndirectedEdges(want))
   621  		if !undirectedEdgeSetEqual(got, want) {
   622  			t.Errorf("unexpected edges result for test %q:\ngot: %#v\nwant:%#v", name, got, want)
   623  		}
   624  	default:
   625  		sort.Sort(lexicalEdges(got))
   626  		sort.Sort(lexicalEdges(want))
   627  		if !reflect.DeepEqual(got, want) {
   628  			t.Errorf("unexpected edges result for test %q:\ngot: %#v\nwant:%#v", name, got, want)
   629  		}
   630  	}
   631  }
   632  
   633  // EdgeExistence tests the constructed graph for the ability to correctly
   634  // return the existence of edges within the graph. This is a check of the
   635  // Edge methods of graph.Graph, the EdgeBetween method of graph.Undirected
   636  // and the EdgeFromTo method of graph.Directed. EdgeExistence also checks
   637  // that the nodes and traversed edges exist within the graph, checking the
   638  // Node, Edge, EdgeBetween and HasEdgeBetween methods of graph.Graph, the
   639  // EdgeBetween method of graph.Undirected and the HasEdgeFromTo method of
   640  // graph.Directed. If reversedEdge is true, edges will be checked to make
   641  // sure edges returned match the orientation of an Edge or WeightedEdge
   642  // call.
   643  func EdgeExistence(t *testing.T, b Builder, reversedEdge bool) {
   644  	for _, test := range testCases {
   645  		g, nodes, edges, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   646  		if !ok {
   647  			t.Logf("skipping test case: %q", test.name)
   648  			continue
   649  		}
   650  
   651  		want := make(map[edge]bool)
   652  		for _, e := range edges {
   653  			want[edge{f: e.From().ID(), t: e.To().ID()}] = true
   654  		}
   655  		for _, x := range nodes {
   656  			for _, y := range nodes {
   657  				between := want[edge{f: x.ID(), t: y.ID()}] || want[edge{f: y.ID(), t: x.ID()}]
   658  
   659  				if has := g.HasEdgeBetween(x.ID(), y.ID()); has != between {
   660  					if has {
   661  						t.Errorf("unexpected edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   662  					} else {
   663  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   664  					}
   665  				} else {
   666  					if want[edge{f: x.ID(), t: y.ID()}] {
   667  						e := g.Edge(x.ID(), y.ID())
   668  						if e == nil || !hasEnds(x, y, e) {
   669  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   670  						} else if reversedEdge && (e.From().ID() != x.ID() || e.To().ID() != y.ID()) {
   671  							t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   672  								test.name, x.ID(), y.ID(), e)
   673  						}
   674  					}
   675  					if between && !g.HasEdgeBetween(x.ID(), y.ID()) {
   676  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   677  					}
   678  					if g.Node(x.ID()) == nil {
   679  						t.Errorf("missing from node for test %q: %v", test.name, x.ID())
   680  					}
   681  					if g.Node(y.ID()) == nil {
   682  						t.Errorf("missing to node for test %q: %v", test.name, y.ID())
   683  					}
   684  				}
   685  
   686  				switch g := g.(type) {
   687  				case graph.Directed:
   688  					u := x
   689  					v := y
   690  					if has := g.HasEdgeFromTo(u.ID(), v.ID()); has != want[edge{f: u.ID(), t: v.ID()}] {
   691  						if has {
   692  							t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   693  						} else {
   694  							t.Errorf("missing edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   695  						}
   696  						continue
   697  					}
   698  					// Edge has already been tested above.
   699  					if g.Node(u.ID()) == nil {
   700  						t.Errorf("missing from node for test %q: %v", test.name, u.ID())
   701  					}
   702  					if g.Node(v.ID()) == nil {
   703  						t.Errorf("missing to node for test %q: %v", test.name, v.ID())
   704  					}
   705  
   706  				case graph.Undirected:
   707  					// HasEdgeBetween is already tested above.
   708  					if between && g.Edge(x.ID(), y.ID()) == nil {
   709  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   710  					}
   711  					if between && g.EdgeBetween(x.ID(), y.ID()) == nil {
   712  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   713  					}
   714  				}
   715  
   716  				switch g := g.(type) {
   717  				case graph.WeightedDirected:
   718  					u := x
   719  					v := y
   720  					if has := g.WeightedEdge(u.ID(), v.ID()) != nil; has != want[edge{f: u.ID(), t: v.ID()}] {
   721  						if has {
   722  							t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   723  						} else {
   724  							t.Errorf("missing edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   725  						}
   726  						continue
   727  					}
   728  
   729  				case graph.WeightedUndirected:
   730  					// HasEdgeBetween is already tested above.
   731  					if between && g.WeightedEdge(x.ID(), y.ID()) == nil {
   732  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   733  					}
   734  					if between && g.WeightedEdgeBetween(x.ID(), y.ID()) == nil {
   735  						t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   736  					}
   737  				}
   738  			}
   739  		}
   740  	}
   741  }
   742  
   743  // LineExistence tests the constructed graph for the ability to correctly
   744  // return the existence of lines within the graph. This is a check of the
   745  // Line methods of graph.MultiGraph, the EdgeBetween method of graph.Undirected
   746  // and the EdgeFromTo method of graph.Directed. LineExistence also checks
   747  // that the nodes and traversed edges exist within the graph, checking the
   748  // Node, Edge, EdgeBetween and HasEdgeBetween methods of graph.Graph, the
   749  // EdgeBetween method of graph.Undirected and the HasEdgeFromTo method of
   750  // graph.Directed. If reversedLine is true, lines will be checked to make
   751  // sure lines returned match the orientation of an Line or WeightedLine
   752  // call.
   753  func LineExistence(t *testing.T, b Builder, useEmpty, reversedLine bool) {
   754  	for _, test := range testCases {
   755  		g, nodes, edges, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   756  		if !ok {
   757  			t.Logf("skipping test case: %q", test.name)
   758  			continue
   759  		}
   760  
   761  		switch mg := g.(type) {
   762  		case graph.Multigraph:
   763  			want := make(map[edge]bool)
   764  			for _, e := range edges {
   765  				want[edge{f: e.From().ID(), t: e.To().ID()}] = true
   766  			}
   767  			for _, x := range nodes {
   768  				for _, y := range nodes {
   769  					between := want[edge{f: x.ID(), t: y.ID()}] || want[edge{f: y.ID(), t: x.ID()}]
   770  
   771  					if has := g.HasEdgeBetween(x.ID(), y.ID()); has != between {
   772  						if has {
   773  							t.Errorf("unexpected edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   774  						} else {
   775  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   776  						}
   777  					} else {
   778  						if want[edge{f: x.ID(), t: y.ID()}] {
   779  							lit := mg.Lines(x.ID(), y.ID())
   780  							if !isValidIterator(lit) {
   781  								t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   782  								continue
   783  							}
   784  							checkEmptyIterator(t, lit, useEmpty)
   785  							if lit.Len() == 0 {
   786  								t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   787  							} else {
   788  								for lit.Next() {
   789  									l := lit.Line()
   790  									if l == nil || !hasEnds(x, y, l) {
   791  										t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   792  									} else if reversedLine && (l.From().ID() != x.ID() || l.To().ID() != y.ID()) {
   793  										t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   794  											test.name, x.ID(), y.ID(), l)
   795  									}
   796  								}
   797  							}
   798  						}
   799  						if between && !g.HasEdgeBetween(x.ID(), y.ID()) {
   800  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   801  						}
   802  						if g.Node(x.ID()) == nil {
   803  							t.Errorf("missing from node for test %q: %v", test.name, x.ID())
   804  						}
   805  						if g.Node(y.ID()) == nil {
   806  							t.Errorf("missing to node for test %q: %v", test.name, y.ID())
   807  						}
   808  					}
   809  
   810  					switch g := g.(type) {
   811  					case graph.DirectedMultigraph:
   812  						u := x
   813  						v := y
   814  						if has := g.HasEdgeFromTo(u.ID(), v.ID()); has != want[edge{f: u.ID(), t: v.ID()}] {
   815  							if has {
   816  								t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   817  							} else {
   818  								t.Errorf("missing edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   819  							}
   820  							continue
   821  						}
   822  						// Edge has already been tested above.
   823  						if g.Node(u.ID()) == nil {
   824  							t.Errorf("missing from node for test %q: %v", test.name, u.ID())
   825  						}
   826  						if g.Node(v.ID()) == nil {
   827  							t.Errorf("missing to node for test %q: %v", test.name, v.ID())
   828  						}
   829  
   830  					case graph.UndirectedMultigraph:
   831  						// HasEdgeBetween is already tested above.
   832  						lit := g.Lines(x.ID(), y.ID())
   833  						if !isValidIterator(lit) {
   834  							t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   835  							continue
   836  						}
   837  						checkEmptyIterator(t, lit, useEmpty)
   838  						if between && lit.Len() == 0 {
   839  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   840  						} else {
   841  							for lit.Next() {
   842  								l := lit.Line()
   843  								if l == nil || !hasEnds(x, y, l) {
   844  									t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   845  								} else if reversedLine && (l.From().ID() != x.ID() || l.To().ID() != y.ID()) {
   846  									t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   847  										test.name, x.ID(), y.ID(), l)
   848  								}
   849  							}
   850  						}
   851  						lit = g.LinesBetween(x.ID(), y.ID())
   852  						if !isValidIterator(lit) {
   853  							t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   854  							continue
   855  						}
   856  						checkEmptyIterator(t, lit, useEmpty)
   857  						if between && lit.Len() == 0 {
   858  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   859  						} else {
   860  							for lit.Next() {
   861  								l := lit.Line()
   862  								if l == nil || !hasEnds(x, y, l) {
   863  									t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   864  								} else if reversedLine && (l.From().ID() != x.ID() || l.To().ID() != y.ID()) {
   865  									t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   866  										test.name, x.ID(), y.ID(), l)
   867  								}
   868  							}
   869  						}
   870  					}
   871  
   872  					switch g := g.(type) {
   873  					case graph.WeightedDirectedMultigraph:
   874  						u := x
   875  						v := y
   876  						lit := g.WeightedLines(u.ID(), v.ID())
   877  						if !isValidIterator(lit) {
   878  							t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   879  							continue
   880  						}
   881  						checkEmptyIterator(t, lit, useEmpty)
   882  						if has := lit != graph.Empty; has != want[edge{f: u.ID(), t: v.ID()}] {
   883  							if has {
   884  								t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   885  							} else {
   886  								t.Errorf("missing edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   887  							}
   888  							continue
   889  						}
   890  						for lit.Next() {
   891  							l := lit.WeightedLine()
   892  							if l.From().ID() != x.ID() || l.To().ID() != y.ID() {
   893  								t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   894  									test.name, x.ID(), y.ID(), l)
   895  							}
   896  						}
   897  						// Edge has already been tested above.
   898  						if g.Node(u.ID()) == nil {
   899  							t.Errorf("missing from node for test %q: %v", test.name, u.ID())
   900  						}
   901  						if g.Node(v.ID()) == nil {
   902  							t.Errorf("missing to node for test %q: %v", test.name, v.ID())
   903  						}
   904  
   905  					case graph.WeightedUndirectedMultigraph:
   906  						// HasEdgeBetween is already tested above.
   907  						lit := g.WeightedLines(x.ID(), y.ID())
   908  						if !isValidIterator(lit) {
   909  							t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   910  							continue
   911  						}
   912  						checkEmptyIterator(t, lit, useEmpty)
   913  						if between && lit.Len() == 0 {
   914  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   915  						} else {
   916  							for lit.Next() {
   917  								l := lit.WeightedLine()
   918  								if reversedLine && (l.From().ID() != x.ID() || l.To().ID() != y.ID()) {
   919  									t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   920  										test.name, x.ID(), y.ID(), l)
   921  								}
   922  							}
   923  						}
   924  						lit = g.WeightedLinesBetween(x.ID(), y.ID())
   925  						if !isValidIterator(lit) {
   926  							t.Errorf("invalid iterator for test %q: got:%#v", test.name, lit)
   927  							continue
   928  						}
   929  						checkEmptyIterator(t, lit, useEmpty)
   930  						if between && lit.Len() == 0 {
   931  							t.Errorf("missing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
   932  						} else {
   933  							for lit.Next() {
   934  								l := lit.WeightedLine()
   935  								if reversedLine && (l.From().ID() != x.ID() || l.To().ID() != y.ID()) {
   936  									t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
   937  										test.name, x.ID(), y.ID(), l)
   938  								}
   939  							}
   940  						}
   941  					}
   942  				}
   943  			}
   944  		default:
   945  			t.Errorf("invalid type for test: %T not a multigraph", g)
   946  			continue
   947  		}
   948  	}
   949  }
   950  
   951  // ReturnAdjacentNodes tests the constructed graph for the ability to correctly
   952  // return the nodes reachable from each node within the graph. This is a check
   953  // of the From method of graph.Graph and the To method of graph.Directed.
   954  // ReturnAdjacentNodes also checks that the nodes and traversed edges exist
   955  // within the graph, checking the Node, Edge, EdgeBetween and HasEdgeBetween
   956  // methods of graph.Graph, the EdgeBetween method of graph.Undirected and the
   957  // HasEdgeFromTo method of graph.Directed.
   958  // If useEmpty is true, graph iterators will be checked for the use of
   959  // graph.Empty if they are empty. If reversedEdge is true, edges will be checked
   960  // to make sure edges returned match the orientation of an Edge or WeightedEdge
   961  // call.
   962  func ReturnAdjacentNodes(t *testing.T, b Builder, useEmpty, reversedEdge bool) {
   963  	for _, test := range testCases {
   964  		g, nodes, edges, _, _, ok := b(test.nodes, test.edges, test.self, test.absent)
   965  		if !ok {
   966  			t.Logf("skipping test case: %q", test.name)
   967  			continue
   968  		}
   969  
   970  		want := make(map[edge]bool)
   971  		for _, e := range edges {
   972  			want[edge{f: e.From().ID(), t: e.To().ID()}] = true
   973  			if g.From(e.From().ID()).Len() == 0 {
   974  				t.Errorf("missing path from node %v with outbound edge %v", e.From().ID(), e)
   975  			}
   976  		}
   977  		for _, x := range nodes {
   978  			switch g := g.(type) {
   979  			case graph.Directed:
   980  				// Test forward.
   981  				u := x
   982  				it := g.From(u.ID())
   983  				if !isValidIterator(it) {
   984  					t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
   985  					continue
   986  				}
   987  				checkEmptyIterator(t, it, useEmpty)
   988  				for i := 0; it.Next(); i++ {
   989  					v := it.Node()
   990  					if i == 0 && g.Node(u.ID()) == nil {
   991  						t.Errorf("missing from node for test %q: %v", test.name, u.ID())
   992  					}
   993  					if g.Node(v.ID()) == nil {
   994  						t.Errorf("missing to node for test %q: %v", test.name, v.ID())
   995  					}
   996  					qe := g.Edge(u.ID(), v.ID())
   997  					if qe == nil {
   998  						t.Errorf("missing from edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
   999  					} else if qe.From().ID() != u.ID() || qe.To().ID() != v.ID() {
  1000  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
  1001  							test.name, u.ID(), v.ID(), qe)
  1002  					}
  1003  					if !g.HasEdgeBetween(u.ID(), v.ID()) {
  1004  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1005  					}
  1006  					if !g.HasEdgeFromTo(u.ID(), v.ID()) {
  1007  						t.Errorf("missing from edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1008  					}
  1009  					if !want[edge{f: u.ID(), t: v.ID()}] {
  1010  						t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1011  					}
  1012  				}
  1013  
  1014  				// Test backward.
  1015  				v := x
  1016  				it = g.To(v.ID())
  1017  				if !isValidIterator(it) {
  1018  					t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
  1019  					continue
  1020  				}
  1021  				checkEmptyIterator(t, it, useEmpty)
  1022  				for i := 0; it.Next(); i++ {
  1023  					u := it.Node()
  1024  					if i == 0 && g.Node(v.ID()) == nil {
  1025  						t.Errorf("missing to node for test %q: %v", test.name, v.ID())
  1026  					}
  1027  					if g.Node(u.ID()) == nil {
  1028  						t.Errorf("missing from node for test %q: %v", test.name, u.ID())
  1029  					}
  1030  					qe := g.Edge(u.ID(), v.ID())
  1031  					if qe == nil {
  1032  						t.Errorf("missing from edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1033  						continue
  1034  					}
  1035  					if qe.From().ID() != u.ID() || qe.To().ID() != v.ID() {
  1036  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
  1037  							test.name, u.ID(), v.ID(), qe)
  1038  					}
  1039  					if !g.HasEdgeBetween(u.ID(), v.ID()) {
  1040  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1041  						continue
  1042  					}
  1043  					if !g.HasEdgeFromTo(u.ID(), v.ID()) {
  1044  						t.Errorf("missing from edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1045  						continue
  1046  					}
  1047  					if !want[edge{f: u.ID(), t: v.ID()}] {
  1048  						t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1049  					}
  1050  				}
  1051  				for _, e := range edges {
  1052  					if g.To(e.To().ID()).Len() == 0 {
  1053  						t.Errorf("missing path to node %v with inbound edge %v", e.To().ID(), e)
  1054  					}
  1055  				}
  1056  
  1057  			case graph.Undirected:
  1058  				u := x
  1059  				it := g.From(u.ID())
  1060  				if !isValidIterator(it) {
  1061  					t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
  1062  					continue
  1063  				}
  1064  				checkEmptyIterator(t, it, useEmpty)
  1065  				for i := 0; it.Next(); i++ {
  1066  					v := it.Node()
  1067  					if i == 0 && g.Node(u.ID()) == nil {
  1068  						t.Errorf("missing from node for test %q: %v", test.name, u.ID())
  1069  					}
  1070  					qe := g.Edge(u.ID(), v.ID())
  1071  					if qe == nil || !hasEnds(u, v, qe) {
  1072  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1073  						continue
  1074  					}
  1075  					if reversedEdge && (qe.From().ID() != u.ID() || qe.To().ID() != v.ID()) {
  1076  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
  1077  							test.name, u.ID(), v.ID(), qe)
  1078  					}
  1079  					qe = g.EdgeBetween(u.ID(), v.ID())
  1080  					if qe == nil || !hasEnds(u, v, qe) {
  1081  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1082  						continue
  1083  					}
  1084  					if reversedEdge && (qe.From().ID() != u.ID() || qe.To().ID() != v.ID()) {
  1085  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
  1086  							test.name, u.ID(), v.ID(), qe)
  1087  					}
  1088  					if !g.HasEdgeBetween(u.ID(), v.ID()) {
  1089  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1090  						continue
  1091  					}
  1092  					between := want[edge{f: u.ID(), t: v.ID()}] || want[edge{f: v.ID(), t: u.ID()}]
  1093  					if !between {
  1094  						t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1095  					}
  1096  				}
  1097  
  1098  			default:
  1099  				u := x
  1100  				it := g.From(u.ID())
  1101  				if !isValidIterator(it) {
  1102  					t.Errorf("invalid iterator for test %q: got:%#v", test.name, it)
  1103  					continue
  1104  				}
  1105  				checkEmptyIterator(t, it, useEmpty)
  1106  				for i := 0; it.Next(); i++ {
  1107  					v := it.Node()
  1108  					if i == 0 && g.Node(u.ID()) == nil {
  1109  						t.Errorf("missing from node for test %q: %v", test.name, u.ID())
  1110  					}
  1111  					qe := g.Edge(u.ID(), v.ID())
  1112  					if qe == nil {
  1113  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1114  						continue
  1115  					}
  1116  					if qe.From().ID() != u.ID() || qe.To().ID() != v.ID() {
  1117  						t.Errorf("inverted edge for test %q query with F=%d T=%d: got:%#v",
  1118  							test.name, u.ID(), v.ID(), qe)
  1119  					}
  1120  					if !g.HasEdgeBetween(u.ID(), v.ID()) {
  1121  						t.Errorf("missing from edge for test %q: (%v)--(%v)", test.name, u.ID(), v.ID())
  1122  						continue
  1123  					}
  1124  					between := want[edge{f: u.ID(), t: v.ID()}] || want[edge{f: v.ID(), t: u.ID()}]
  1125  					if !between {
  1126  						t.Errorf("unexpected edge for test %q: (%v)->(%v)", test.name, u.ID(), v.ID())
  1127  					}
  1128  				}
  1129  			}
  1130  		}
  1131  	}
  1132  }
  1133  
  1134  // Weight tests the constructed graph for the ability to correctly return
  1135  // the weight between to nodes, checking the Weight method of graph.Weighted.
  1136  //
  1137  // The self and absent values returned by the Builder should match the values
  1138  // used by the Weight method.
  1139  func Weight(t *testing.T, b Builder) {
  1140  	for _, test := range testCases {
  1141  		g, nodes, _, self, absent, ok := b(test.nodes, test.edges, test.self, test.absent)
  1142  		if !ok {
  1143  			t.Logf("skipping test case: %q", test.name)
  1144  			continue
  1145  		}
  1146  		wg, ok := g.(graph.Weighted)
  1147  		if !ok {
  1148  			t.Errorf("invalid graph type for test %q: %T is not graph.Weighted", test.name, g)
  1149  		}
  1150  		_, multi := g.(graph.Multigraph)
  1151  
  1152  		for _, x := range nodes {
  1153  			for _, y := range nodes {
  1154  				w, ok := wg.Weight(x.ID(), y.ID())
  1155  				e := wg.WeightedEdge(x.ID(), y.ID())
  1156  				switch {
  1157  				case !ok:
  1158  					if e != nil {
  1159  						t.Errorf("missing edge weight for existing edge for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
  1160  					}
  1161  					if !scalar.Same(w, absent) {
  1162  						t.Errorf("unexpected absent weight for test %q: got:%v want:%v", test.name, w, absent)
  1163  					}
  1164  
  1165  				case !multi && x.ID() == y.ID():
  1166  					if !scalar.Same(w, self) {
  1167  						t.Errorf("unexpected self weight for test %q: got:%v want:%v", test.name, w, self)
  1168  					}
  1169  
  1170  				case e == nil:
  1171  					t.Errorf("missing edge for existing non-self weight for test %q: (%v)--(%v)", test.name, x.ID(), y.ID())
  1172  
  1173  				case e.Weight() != w:
  1174  					t.Errorf("weight mismatch for test %q: edge=%v graph=%v", test.name, e.Weight(), w)
  1175  				}
  1176  			}
  1177  		}
  1178  	}
  1179  }
  1180  
  1181  // AdjacencyMatrix tests the constructed graph for the ability to correctly
  1182  // return an adjacency matrix that matches the weights returned by the graphs
  1183  // Weight method.
  1184  //
  1185  // The self and absent values returned by the Builder should match the values
  1186  // used by the Weight method.
  1187  func AdjacencyMatrix(t *testing.T, b Builder) {
  1188  	for _, test := range testCases {
  1189  		g, nodes, _, self, absent, ok := b(test.nodes, test.edges, test.self, test.absent)
  1190  		if !ok {
  1191  			t.Logf("skipping test case: %q", test.name)
  1192  			continue
  1193  		}
  1194  		wg, ok := g.(graph.Weighted)
  1195  		if !ok {
  1196  			t.Errorf("invalid graph type for test %q: %T is not graph.Weighted", test.name, g)
  1197  		}
  1198  		mg, ok := g.(matrixer)
  1199  		if !ok {
  1200  			t.Errorf("invalid graph type for test %q: %T cannot return adjacency matrix", test.name, g)
  1201  		}
  1202  		m := mg.Matrix()
  1203  
  1204  		r, c := m.Dims()
  1205  		if r != c || r != len(nodes) {
  1206  			t.Errorf("dimension mismatch for test %q: r=%d c=%d order=%d", test.name, r, c, len(nodes))
  1207  		}
  1208  
  1209  		for _, x := range nodes {
  1210  			i := int(x.ID())
  1211  			for _, y := range nodes {
  1212  				j := int(y.ID())
  1213  				w, ok := wg.Weight(x.ID(), y.ID())
  1214  				switch {
  1215  				case !ok:
  1216  					if !scalar.Same(m.At(i, j), absent) {
  1217  						t.Errorf("weight mismatch for test %q: (%v)--(%v) matrix=%v graph=%v", test.name, x.ID(), y.ID(), m.At(i, j), w)
  1218  					}
  1219  				case x.ID() == y.ID():
  1220  					if !scalar.Same(m.At(i, j), self) {
  1221  						t.Errorf("weight mismatch for test %q: (%v)--(%v) matrix=%v graph=%v", test.name, x.ID(), y.ID(), m.At(i, j), w)
  1222  					}
  1223  				default:
  1224  					if !scalar.Same(m.At(i, j), w) {
  1225  						t.Errorf("weight mismatch for test %q: (%v)--(%v) matrix=%v graph=%v", test.name, x.ID(), y.ID(), m.At(i, j), w)
  1226  					}
  1227  				}
  1228  			}
  1229  		}
  1230  	}
  1231  }
  1232  
  1233  // lexicalEdges sorts a collection of edges lexically on the
  1234  // keys: from.ID > to.ID > [line.ID] > [weight].
  1235  type lexicalEdges []Edge
  1236  
  1237  func (e lexicalEdges) Len() int { return len(e) }
  1238  func (e lexicalEdges) Less(i, j int) bool {
  1239  	if e[i].From().ID() < e[j].From().ID() {
  1240  		return true
  1241  	}
  1242  	sf := e[i].From().ID() == e[j].From().ID()
  1243  	if sf && e[i].To().ID() < e[j].To().ID() {
  1244  		return true
  1245  	}
  1246  	st := e[i].To().ID() == e[j].To().ID()
  1247  	li, oki := e[i].(graph.Line)
  1248  	lj, okj := e[j].(graph.Line)
  1249  	if oki != okj {
  1250  		panic(fmt.Sprintf("testgraph: mismatched types %T != %T", e[i], e[j]))
  1251  	}
  1252  	if !oki {
  1253  		return sf && st && lessWeight(e[i], e[j])
  1254  	}
  1255  	if sf && st && li.ID() < lj.ID() {
  1256  		return true
  1257  	}
  1258  	return sf && st && li.ID() == lj.ID() && lessWeight(e[i], e[j])
  1259  }
  1260  func (e lexicalEdges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
  1261  
  1262  // lexicalUndirectedEdges sorts a collection of edges lexically on the
  1263  // keys: lo.ID > hi.ID > [line.ID] > [weight].
  1264  type lexicalUndirectedEdges []Edge
  1265  
  1266  func (e lexicalUndirectedEdges) Len() int { return len(e) }
  1267  func (e lexicalUndirectedEdges) Less(i, j int) bool {
  1268  	lidi, hidi, _ := undirectedIDs(e[i])
  1269  	lidj, hidj, _ := undirectedIDs(e[j])
  1270  
  1271  	if lidi < lidj {
  1272  		return true
  1273  	}
  1274  	sl := lidi == lidj
  1275  	if sl && hidi < hidj {
  1276  		return true
  1277  	}
  1278  	sh := hidi == hidj
  1279  	li, oki := e[i].(graph.Line)
  1280  	lj, okj := e[j].(graph.Line)
  1281  	if oki != okj {
  1282  		panic(fmt.Sprintf("testgraph: mismatched types %T != %T", e[i], e[j]))
  1283  	}
  1284  	if !oki {
  1285  		return sl && sh && lessWeight(e[i], e[j])
  1286  	}
  1287  	if sl && sh && li.ID() < lj.ID() {
  1288  		return true
  1289  	}
  1290  	return sl && sh && li.ID() == lj.ID() && lessWeight(e[i], e[j])
  1291  }
  1292  func (e lexicalUndirectedEdges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
  1293  
  1294  func lessWeight(ei, ej Edge) bool {
  1295  	wei, oki := ei.(graph.WeightedEdge)
  1296  	wej, okj := ej.(graph.WeightedEdge)
  1297  	if oki != okj {
  1298  		panic(fmt.Sprintf("testgraph: mismatched types %T != %T", ei, ej))
  1299  	}
  1300  	if !oki {
  1301  		return false
  1302  	}
  1303  	return wei.Weight() < wej.Weight()
  1304  }
  1305  
  1306  // undirectedEdgeSetEqual returned whether a pair of undirected edge
  1307  // slices sorted by lexicalUndirectedEdges are equal.
  1308  func undirectedEdgeSetEqual(a, b []Edge) bool {
  1309  	if len(a) == 0 && len(b) == 0 {
  1310  		return true
  1311  	}
  1312  	if len(a) == 0 || len(b) == 0 {
  1313  		return false
  1314  	}
  1315  	if !undirectedEdgeEqual(a[0], b[0]) {
  1316  		return false
  1317  	}
  1318  	i, j := 0, 0
  1319  	for {
  1320  		switch {
  1321  		case i == len(a)-1 && j == len(b)-1:
  1322  			return true
  1323  
  1324  		case i < len(a)-1 && undirectedEdgeEqual(a[i+1], b[j]):
  1325  			i++
  1326  
  1327  		case j < len(b)-1 && undirectedEdgeEqual(a[i], b[j+1]):
  1328  			j++
  1329  
  1330  		case i < len(a)-1 && j < len(b)-1 && undirectedEdgeEqual(a[i+1], b[j+1]):
  1331  			i++
  1332  			j++
  1333  
  1334  		default:
  1335  			return false
  1336  		}
  1337  	}
  1338  }
  1339  
  1340  // undirectedEdgeEqual returns whether a pair of undirected edges are equal
  1341  // after canonicalising from and to IDs by numerical sort order.
  1342  func undirectedEdgeEqual(a, b Edge) bool {
  1343  	loa, hia, inva := undirectedIDs(a)
  1344  	lob, hib, invb := undirectedIDs(b)
  1345  	// Use reflect.DeepEqual if the edges are parallel
  1346  	// rather anti-parallel.
  1347  	if inva == invb {
  1348  		return reflect.DeepEqual(a, b)
  1349  	}
  1350  	if loa != lob || hia != hib {
  1351  		return false
  1352  	}
  1353  	la, oka := a.(graph.Line)
  1354  	lb, okb := b.(graph.Line)
  1355  	if !oka && !okb {
  1356  		return true
  1357  	}
  1358  	if la.ID() != lb.ID() {
  1359  		return false
  1360  	}
  1361  	wea, oka := a.(graph.WeightedEdge)
  1362  	web, okb := b.(graph.WeightedEdge)
  1363  	if !oka && !okb {
  1364  		return true
  1365  	}
  1366  	return wea.Weight() == web.Weight()
  1367  }
  1368  
  1369  // NodeAdder is a graph.NodeAdder graph.
  1370  type NodeAdder interface {
  1371  	graph.Graph
  1372  	graph.NodeAdder
  1373  }
  1374  
  1375  // AddNodes tests whether g correctly implements the graph.NodeAdder interface.
  1376  // AddNodes gets a new node from g and adds it to the graph, repeating this pair
  1377  // of operations n times. The existence of added nodes is confirmed in the graph.
  1378  // AddNodes also checks that re-adding each of the added nodes causes a panic.
  1379  // If g satisfies NodeWithIDer, the NodeWithID method is tested for an additional
  1380  // n rounds of node addition using NodeWithID to create new nodes as well as
  1381  // confirming that NodeWithID returns existing nodes.
  1382  func AddNodes(t *testing.T, g NodeAdder, n int) {
  1383  	defer func() {
  1384  		r := recover()
  1385  		if r != nil {
  1386  			t.Errorf("unexpected panic: %v", r)
  1387  		}
  1388  	}()
  1389  
  1390  	var addedNodes []graph.Node
  1391  	for i := 0; i < n; i++ {
  1392  		node := g.NewNode()
  1393  		prev := len(graph.NodesOf(g.Nodes()))
  1394  		if g.Node(node.ID()) != nil {
  1395  			curr := g.Nodes().Len()
  1396  			if curr != prev {
  1397  				t.Fatalf("NewNode mutated graph: prev graph order != curr graph order, %d != %d", prev, curr)
  1398  			}
  1399  			t.Fatalf("NewNode returned existing: %#v", node)
  1400  		}
  1401  		g.AddNode(node)
  1402  		addedNodes = append(addedNodes, node)
  1403  		curr := len(graph.NodesOf(g.Nodes()))
  1404  		if curr != prev+1 {
  1405  			t.Fatalf("AddNode failed to mutate graph: curr graph order != prev graph order+1, %d != %d", curr, prev+1)
  1406  		}
  1407  		if g.Node(node.ID()) == nil {
  1408  			t.Fatalf("AddNode failed to add node to graph trying to add %#v", node)
  1409  		}
  1410  	}
  1411  
  1412  	ordered.ByID(addedNodes)
  1413  	graphNodes := graph.NodesOf(g.Nodes())
  1414  	ordered.ByID(graphNodes)
  1415  	if !reflect.DeepEqual(addedNodes, graphNodes) {
  1416  		if n > 20 {
  1417  			t.Errorf("unexpected node set after node addition: got len:%v want len:%v", len(graphNodes), len(addedNodes))
  1418  		} else {
  1419  			t.Errorf("unexpected node set after node addition: got:\n %v\nwant:\n%v", graphNodes, addedNodes)
  1420  		}
  1421  	}
  1422  
  1423  	it := g.Nodes()
  1424  	for it.Next() {
  1425  		panicked := panics(func() {
  1426  			g.AddNode(it.Node())
  1427  		})
  1428  		if !panicked {
  1429  			t.Fatalf("expected panic adding existing node: %v", it.Node())
  1430  		}
  1431  	}
  1432  
  1433  	if gwi, ok := g.(graph.NodeWithIDer); ok {
  1434  		// Test existing nodes.
  1435  		it := g.Nodes()
  1436  		for it.Next() {
  1437  			id := it.Node().ID()
  1438  			n, new := gwi.NodeWithID(id)
  1439  			if n == nil {
  1440  				t.Errorf("unexpected nil node for existing node with ID=%d", id)
  1441  			}
  1442  			if new {
  1443  				t.Errorf("unexpected new node for existing node with ID=%d", id)
  1444  			}
  1445  		}
  1446  		// Run n rounds of ID-specified node addition.
  1447  		for i := 0; i < n; i++ {
  1448  			id := g.NewNode().ID() // Get a guaranteed non-existing node.
  1449  			n, new := gwi.NodeWithID(id)
  1450  			if n == nil {
  1451  				// Could not create a node, valid behaviour.
  1452  				continue
  1453  			}
  1454  			if !new {
  1455  				t.Errorf("unexpected old node for non-existing node with ID=%d", id)
  1456  			}
  1457  			g.AddNode(n) // Use the node to advance to a new non-existing node.
  1458  		}
  1459  	}
  1460  }
  1461  
  1462  // AddArbitraryNodes tests whether g correctly implements the AddNode method. Not all
  1463  // graph.NodeAdder graphs are expected to implement the semantics of this test.
  1464  // AddArbitraryNodes iterates over add, adding each node to the graph. The existence
  1465  // of each added node in the graph is confirmed.
  1466  func AddArbitraryNodes(t *testing.T, g NodeAdder, add graph.Nodes) {
  1467  	defer func() {
  1468  		r := recover()
  1469  		if r != nil {
  1470  			t.Errorf("unexpected panic: %v", r)
  1471  		}
  1472  	}()
  1473  
  1474  	for add.Next() {
  1475  		node := add.Node()
  1476  		prev := len(graph.NodesOf(g.Nodes()))
  1477  		g.AddNode(node)
  1478  		curr := len(graph.NodesOf(g.Nodes()))
  1479  		if curr != prev+1 {
  1480  			t.Fatalf("AddNode failed to mutate graph: curr graph order != prev graph order+1, %d != %d", curr, prev+1)
  1481  		}
  1482  		if g.Node(node.ID()) == nil {
  1483  			t.Fatalf("AddNode failed to add node to graph trying to add %#v", node)
  1484  		}
  1485  	}
  1486  
  1487  	add.Reset()
  1488  	addedNodes := graph.NodesOf(add)
  1489  	ordered.ByID(addedNodes)
  1490  	graphNodes := graph.NodesOf(g.Nodes())
  1491  	ordered.ByID(graphNodes)
  1492  	if !reflect.DeepEqual(addedNodes, graphNodes) {
  1493  		t.Errorf("unexpected node set after node addition: got:\n %v\nwant:\n%v", graphNodes, addedNodes)
  1494  	}
  1495  
  1496  	it := g.Nodes()
  1497  	for it.Next() {
  1498  		panicked := panics(func() {
  1499  			g.AddNode(it.Node())
  1500  		})
  1501  		if !panicked {
  1502  			t.Fatalf("expected panic adding existing node: %v", it.Node())
  1503  		}
  1504  	}
  1505  }
  1506  
  1507  // NodeRemover is a graph.NodeRemover graph.
  1508  type NodeRemover interface {
  1509  	graph.Graph
  1510  	graph.NodeRemover
  1511  }
  1512  
  1513  // RemoveNodes tests whether g correctly implements the graph.NodeRemover interface.
  1514  // The input graph g must contain a set of nodes with some edges between them.
  1515  func RemoveNodes(t *testing.T, g NodeRemover) {
  1516  	defer func() {
  1517  		r := recover()
  1518  		if r != nil {
  1519  			t.Errorf("unexpected panic: %v", r)
  1520  		}
  1521  	}()
  1522  
  1523  	it := g.Nodes()
  1524  	first := true
  1525  	for it.Next() {
  1526  		u := it.Node()
  1527  
  1528  		seen := make(map[edge]struct{})
  1529  
  1530  		// Collect all incident edges.
  1531  		var incident []graph.Edge
  1532  		to := g.From(u.ID())
  1533  		for to.Next() {
  1534  			v := to.Node()
  1535  			e := g.Edge(u.ID(), v.ID())
  1536  			if e == nil {
  1537  				t.Fatalf("bad graph: neighbors not connected: u=%#v v=%#v", u, v)
  1538  			}
  1539  			if _, ok := g.(graph.Undirected); ok {
  1540  				seen[edge{f: e.To().ID(), t: e.From().ID()}] = struct{}{}
  1541  			}
  1542  			seen[edge{f: e.From().ID(), t: e.To().ID()}] = struct{}{}
  1543  			incident = append(incident, e)
  1544  		}
  1545  
  1546  		// Collect all other edges.
  1547  		var others []graph.Edge
  1548  		currit := g.Nodes()
  1549  		for currit.Next() {
  1550  			u := currit.Node()
  1551  			to := g.From(u.ID())
  1552  			for to.Next() {
  1553  				v := to.Node()
  1554  				e := g.Edge(u.ID(), v.ID())
  1555  				if e == nil {
  1556  					t.Fatalf("bad graph: neighbors not connected: u=%#v v=%#v", u, v)
  1557  				}
  1558  				seen[edge{f: e.From().ID(), t: e.To().ID()}] = struct{}{}
  1559  				others = append(others, e)
  1560  			}
  1561  		}
  1562  
  1563  		if first && len(seen) == 0 {
  1564  			t.Fatal("incomplete test: no edges in graph")
  1565  		}
  1566  		first = false
  1567  
  1568  		prev := len(graph.NodesOf(g.Nodes()))
  1569  		g.RemoveNode(u.ID())
  1570  		curr := len(graph.NodesOf(g.Nodes()))
  1571  		if curr != prev-1 {
  1572  			t.Fatalf("RemoveNode failed to mutate graph: curr graph order != prev graph order-1, %d != %d", curr, prev-1)
  1573  		}
  1574  		if g.Node(u.ID()) != nil {
  1575  			t.Fatalf("failed to remove node: %#v", u)
  1576  		}
  1577  
  1578  		for _, e := range incident {
  1579  			if g.HasEdgeBetween(e.From().ID(), e.To().ID()) {
  1580  				t.Fatalf("RemoveNode failed to remove connected edge: %#v", e)
  1581  			}
  1582  		}
  1583  
  1584  		for _, e := range others {
  1585  			if e.From().ID() == u.ID() || e.To().ID() == u.ID() {
  1586  				continue
  1587  			}
  1588  			if g.Edge(e.From().ID(), e.To().ID()) == nil {
  1589  				t.Fatalf("RemoveNode %v removed unconnected edge: %#v", u, e)
  1590  			}
  1591  		}
  1592  	}
  1593  }
  1594  
  1595  // EdgeAdder is a graph.EdgeAdder graph.
  1596  type EdgeAdder interface {
  1597  	graph.Graph
  1598  	graph.EdgeAdder
  1599  }
  1600  
  1601  // AddEdges tests whether g correctly implements the graph.EdgeAdder interface.
  1602  // AddEdges creates n pairs of nodes with random IDs in [0,n) and joins edges
  1603  // each node in the pair using SetEdge. AddEdges confirms that the end point
  1604  // nodes are added to the graph and that the edges are stored in the graph.
  1605  // If canLoop is true, self edges may be created. If canSet is true, a second
  1606  // call to SetEdge is made for each edge to confirm that the nodes corresponding
  1607  // the end points are updated.
  1608  func AddEdges(t *testing.T, n int, g EdgeAdder, newNode func(id int64) graph.Node, canLoop, canSetNode bool) {
  1609  	defer func() {
  1610  		r := recover()
  1611  		if r != nil {
  1612  			t.Errorf("unexpected panic: %v", r)
  1613  		}
  1614  	}()
  1615  
  1616  	type altNode struct {
  1617  		graph.Node
  1618  	}
  1619  
  1620  	rnd := rand.New(rand.NewSource(1))
  1621  	for i := 0; i < n; i++ {
  1622  		u := newNode(rnd.Int63n(int64(n)))
  1623  		var v graph.Node
  1624  		for {
  1625  			v = newNode(rnd.Int63n(int64(n)))
  1626  			if canLoop || u.ID() != v.ID() {
  1627  				break
  1628  			}
  1629  		}
  1630  		e := g.NewEdge(u, v)
  1631  		if g.Edge(u.ID(), v.ID()) != nil {
  1632  			t.Fatalf("NewEdge returned existing: %#v", e)
  1633  		}
  1634  		g.SetEdge(e)
  1635  		if g.Edge(u.ID(), v.ID()) == nil {
  1636  			t.Fatalf("SetEdge failed to add edge: %#v", e)
  1637  		}
  1638  		if g.Node(u.ID()) == nil {
  1639  			t.Fatalf("SetEdge failed to add from node: %#v", u)
  1640  		}
  1641  		if g.Node(v.ID()) == nil {
  1642  			t.Fatalf("SetEdge failed to add to node: %#v", v)
  1643  		}
  1644  
  1645  		if !canSetNode {
  1646  			continue
  1647  		}
  1648  
  1649  		g.SetEdge(g.NewEdge(altNode{u}, altNode{v}))
  1650  		if nu := g.Node(u.ID()); nu == u {
  1651  			t.Fatalf("SetEdge failed to update from node: u=%#v nu=%#v", u, nu)
  1652  		}
  1653  		if nv := g.Node(v.ID()); nv == v {
  1654  			t.Fatalf("SetEdge failed to update to node: v=%#v nv=%#v", v, nv)
  1655  		}
  1656  	}
  1657  }
  1658  
  1659  // WeightedEdgeAdder is a graph.EdgeAdder graph.
  1660  type WeightedEdgeAdder interface {
  1661  	graph.Graph
  1662  	graph.WeightedEdgeAdder
  1663  }
  1664  
  1665  // AddWeightedEdges tests whether g correctly implements the graph.WeightedEdgeAdder
  1666  // interface. AddWeightedEdges creates n pairs of nodes with random IDs in [0,n) and
  1667  // joins edges each node in the pair using SetWeightedEdge with weight w.
  1668  // AddWeightedEdges confirms that the end point nodes are added to the graph and that
  1669  // the edges are stored in the graph. If canLoop is true, self edges may be created.
  1670  // If canSet is true, a second call to SetWeightedEdge is made for each edge to
  1671  // confirm that the nodes corresponding the end points are updated.
  1672  func AddWeightedEdges(t *testing.T, n int, g WeightedEdgeAdder, w float64, newNode func(id int64) graph.Node, canLoop, canSetNode bool) {
  1673  	defer func() {
  1674  		r := recover()
  1675  		if r != nil {
  1676  			t.Errorf("unexpected panic: %v", r)
  1677  		}
  1678  	}()
  1679  
  1680  	type altNode struct {
  1681  		graph.Node
  1682  	}
  1683  
  1684  	rnd := rand.New(rand.NewSource(1))
  1685  	for i := 0; i < n; i++ {
  1686  		u := newNode(rnd.Int63n(int64(n)))
  1687  		var v graph.Node
  1688  		for {
  1689  			v = newNode(rnd.Int63n(int64(n)))
  1690  			if canLoop || u.ID() != v.ID() {
  1691  				break
  1692  			}
  1693  		}
  1694  		e := g.NewWeightedEdge(u, v, w)
  1695  		if g.Edge(u.ID(), v.ID()) != nil {
  1696  			t.Fatalf("NewEdge returned existing: %#v", e)
  1697  		}
  1698  		g.SetWeightedEdge(e)
  1699  		ne := g.Edge(u.ID(), v.ID())
  1700  		if ne == nil {
  1701  			t.Fatalf("SetWeightedEdge failed to add edge: %#v", e)
  1702  		}
  1703  		we, ok := ne.(graph.WeightedEdge)
  1704  		if !ok {
  1705  			t.Fatalf("SetWeightedEdge failed to add weighted edge: %#v", e)
  1706  		}
  1707  		if we.Weight() != w {
  1708  			t.Fatalf("edge weight mismatch: got:%f want:%f", we.Weight(), w)
  1709  		}
  1710  
  1711  		if g.Node(u.ID()) == nil {
  1712  			t.Fatalf("SetWeightedEdge failed to add from node: %#v", u)
  1713  		}
  1714  		if g.Node(v.ID()) == nil {
  1715  			t.Fatalf("SetWeightedEdge failed to add to node: %#v", v)
  1716  		}
  1717  
  1718  		if !canSetNode {
  1719  			continue
  1720  		}
  1721  
  1722  		g.SetWeightedEdge(g.NewWeightedEdge(altNode{u}, altNode{v}, w))
  1723  		if nu := g.Node(u.ID()); nu == u {
  1724  			t.Fatalf("SetWeightedEdge failed to update from node: u=%#v nu=%#v", u, nu)
  1725  		}
  1726  		if nv := g.Node(v.ID()); nv == v {
  1727  			t.Fatalf("SetWeightedEdge failed to update to node: v=%#v nv=%#v", v, nv)
  1728  		}
  1729  	}
  1730  }
  1731  
  1732  // NoLoopAddEdges tests whether g panics for self-loop addition. NoLoopAddEdges
  1733  // adds n nodes with IDs in [0,n) and creates an edge from the graph with NewEdge.
  1734  // NoLoopAddEdges confirms that this does not panic and then adds the edge to the
  1735  // graph to ensure that SetEdge will panic when adding a self-loop.
  1736  func NoLoopAddEdges(t *testing.T, n int, g EdgeAdder, newNode func(id int64) graph.Node) {
  1737  	defer func() {
  1738  		r := recover()
  1739  		if r != nil {
  1740  			t.Errorf("unexpected panic: %v", r)
  1741  		}
  1742  	}()
  1743  
  1744  	for id := 0; id < n; id++ {
  1745  		node := newNode(int64(id))
  1746  		e := g.NewEdge(node, node)
  1747  		panicked := panics(func() {
  1748  			g.SetEdge(e)
  1749  		})
  1750  		if !panicked {
  1751  			t.Errorf("expected panic for self-edge: %#v", e)
  1752  		}
  1753  	}
  1754  }
  1755  
  1756  // NoLoopAddWeightedEdges tests whether g panics for self-loop addition. NoLoopAddWeightedEdges
  1757  // adds n nodes with IDs in [0,n) and creates an edge from the graph with NewWeightedEdge.
  1758  // NoLoopAddWeightedEdges confirms that this does not panic and then adds the edge to the
  1759  // graph to ensure that SetWeightedEdge will panic when adding a self-loop.
  1760  func NoLoopAddWeightedEdges(t *testing.T, n int, g WeightedEdgeAdder, w float64, newNode func(id int64) graph.Node) {
  1761  	defer func() {
  1762  		r := recover()
  1763  		if r != nil {
  1764  			t.Errorf("unexpected panic: %v", r)
  1765  		}
  1766  	}()
  1767  
  1768  	for id := 0; id < n; id++ {
  1769  		node := newNode(int64(id))
  1770  		e := g.NewWeightedEdge(node, node, w)
  1771  		panicked := panics(func() {
  1772  			g.SetWeightedEdge(e)
  1773  		})
  1774  		if !panicked {
  1775  			t.Errorf("expected panic for self-edge: %#v", e)
  1776  		}
  1777  	}
  1778  }
  1779  
  1780  // LineAdder is a graph.LineAdder multigraph.
  1781  type LineAdder interface {
  1782  	graph.Multigraph
  1783  	graph.LineAdder
  1784  }
  1785  
  1786  // AddLines tests whether g correctly implements the graph.LineAdder interface.
  1787  // AddLines creates n pairs of nodes with random IDs in [0,n) and joins edges
  1788  // each node in the pair using SetLine. AddLines confirms that the end point
  1789  // nodes are added to the graph and that the edges are stored in the graph.
  1790  // If canSet is true, a second call to SetLine is made for each edge to confirm
  1791  // that the nodes corresponding the end points are updated.
  1792  func AddLines(t *testing.T, n int, g LineAdder, newNode func(id int64) graph.Node, canSetNode bool) {
  1793  	defer func() {
  1794  		r := recover()
  1795  		if r != nil {
  1796  			t.Errorf("unexpected panic: %v", r)
  1797  		}
  1798  	}()
  1799  
  1800  	type altNode struct {
  1801  		graph.Node
  1802  	}
  1803  
  1804  	rnd := rand.New(rand.NewSource(1))
  1805  	seen := make(tripleInt64s)
  1806  	for i := 0; i < n; i++ {
  1807  		u := newNode(rnd.Int63n(int64(n)))
  1808  		v := newNode(rnd.Int63n(int64(n)))
  1809  		prev := g.Lines(u.ID(), v.ID())
  1810  		l := g.NewLine(u, v)
  1811  		if seen.has(u.ID(), v.ID(), l.ID()) {
  1812  			t.Fatalf("NewLine returned an existing line: %#v", l)
  1813  		}
  1814  		if g.Lines(u.ID(), v.ID()).Len() != prev.Len() {
  1815  			t.Fatalf("NewLine added a line: %#v", l)
  1816  		}
  1817  		g.SetLine(l)
  1818  		seen.add(u.ID(), v.ID(), l.ID())
  1819  		if g.Lines(u.ID(), v.ID()).Len() != prev.Len()+1 {
  1820  			t.Fatalf("SetLine failed to add line: %#v", l)
  1821  		}
  1822  		if g.Node(u.ID()) == nil {
  1823  			t.Fatalf("SetLine failed to add from node: %#v", u)
  1824  		}
  1825  		if g.Node(v.ID()) == nil {
  1826  			t.Fatalf("SetLine failed to add to node: %#v", v)
  1827  		}
  1828  
  1829  		if !canSetNode {
  1830  			continue
  1831  		}
  1832  
  1833  		g.SetLine(g.NewLine(altNode{u}, altNode{v}))
  1834  		if nu := g.Node(u.ID()); nu == u {
  1835  			t.Fatalf("SetLine failed to update from node: u=%#v nu=%#v", u, nu)
  1836  		}
  1837  		if nv := g.Node(v.ID()); nv == v {
  1838  			t.Fatalf("SetLine failed to update to node: v=%#v nv=%#v", v, nv)
  1839  		}
  1840  	}
  1841  }
  1842  
  1843  // WeightedLineAdder is a graph.WeightedLineAdder multigraph.
  1844  type WeightedLineAdder interface {
  1845  	graph.Multigraph
  1846  	graph.WeightedLineAdder
  1847  }
  1848  
  1849  // AddWeightedLines tests whether g correctly implements the graph.WeightedEdgeAdder
  1850  // interface. AddWeightedLines creates n pairs of nodes with random IDs in [0,n) and
  1851  // joins edges each node in the pair using SetWeightedLine with weight w.
  1852  // AddWeightedLines confirms that the end point nodes are added to the graph and that
  1853  // the edges are stored in the graph. If canSet is true, a second call to SetWeightedLine
  1854  // is made for each edge to confirm that the nodes corresponding the end points are
  1855  // updated.
  1856  func AddWeightedLines(t *testing.T, n int, g WeightedLineAdder, w float64, newNode func(id int64) graph.Node, canSetNode bool) {
  1857  	defer func() {
  1858  		r := recover()
  1859  		if r != nil {
  1860  			t.Errorf("unexpected panic: %v", r)
  1861  		}
  1862  	}()
  1863  
  1864  	type altNode struct {
  1865  		graph.Node
  1866  	}
  1867  
  1868  	rnd := rand.New(rand.NewSource(1))
  1869  	seen := make(tripleInt64s)
  1870  	for i := 0; i < n; i++ {
  1871  		u := newNode(rnd.Int63n(int64(n)))
  1872  		v := newNode(rnd.Int63n(int64(n)))
  1873  		prev := g.Lines(u.ID(), v.ID())
  1874  		l := g.NewWeightedLine(u, v, w)
  1875  		if seen.has(u.ID(), v.ID(), l.ID()) {
  1876  			t.Fatalf("NewWeightedLine returned an existing line: %#v", l)
  1877  		}
  1878  		if g.Lines(u.ID(), v.ID()).Len() != prev.Len() {
  1879  			t.Fatalf("NewWeightedLine added a line: %#v", l)
  1880  		}
  1881  		g.SetWeightedLine(l)
  1882  		seen.add(u.ID(), v.ID(), l.ID())
  1883  		curr := g.Lines(u.ID(), v.ID())
  1884  		if curr.Len() != prev.Len()+1 {
  1885  			t.Fatalf("SetWeightedLine failed to add line: %#v", l)
  1886  		}
  1887  		var found bool
  1888  		for curr.Next() {
  1889  			if curr.Line().ID() == l.ID() {
  1890  				found = true
  1891  				wl, ok := curr.Line().(graph.WeightedLine)
  1892  				if !ok {
  1893  					t.Fatalf("SetWeightedLine failed to add weighted line: %#v", l)
  1894  				}
  1895  				if wl.Weight() != w {
  1896  					t.Fatalf("line weight mismatch: got:%f want:%f", wl.Weight(), w)
  1897  				}
  1898  				break
  1899  			}
  1900  		}
  1901  		if !found {
  1902  			t.Fatalf("SetWeightedLine failed to add line: %#v", l)
  1903  		}
  1904  		if g.Node(u.ID()) == nil {
  1905  			t.Fatalf("SetWeightedLine failed to add from node: %#v", u)
  1906  		}
  1907  		if g.Node(v.ID()) == nil {
  1908  			t.Fatalf("SetWeightedLine failed to add to node: %#v", v)
  1909  		}
  1910  
  1911  		if !canSetNode {
  1912  			continue
  1913  		}
  1914  
  1915  		g.SetWeightedLine(g.NewWeightedLine(altNode{u}, altNode{v}, w))
  1916  		if nu := g.Node(u.ID()); nu == u {
  1917  			t.Fatalf("SetWeightedLine failed to update from node: u=%#v nu=%#v", u, nu)
  1918  		}
  1919  		if nv := g.Node(v.ID()); nv == v {
  1920  			t.Fatalf("SetWeightedLine failed to update to node: v=%#v nv=%#v", v, nv)
  1921  		}
  1922  	}
  1923  }
  1924  
  1925  // EdgeRemover is a graph.EdgeRemover graph.
  1926  type EdgeRemover interface {
  1927  	graph.Graph
  1928  	graph.EdgeRemover
  1929  }
  1930  
  1931  // RemoveEdges tests whether g correctly implements the graph.EdgeRemover interface.
  1932  // The input graph g must contain a set of nodes with some edges between them.
  1933  // RemoveEdges iterates over remove, which must contain edges in g, removing each
  1934  // edge. RemoveEdges confirms that the edge is removed, leaving its end-point nodes
  1935  // and all other edges in the graph.
  1936  func RemoveEdges(t *testing.T, g EdgeRemover, remove graph.Edges) {
  1937  	edges := make(map[edge]struct{})
  1938  	nodes := g.Nodes()
  1939  	for nodes.Next() {
  1940  		u := nodes.Node()
  1941  		uid := u.ID()
  1942  		to := g.From(uid)
  1943  		for to.Next() {
  1944  			v := to.Node()
  1945  			edges[edge{f: u.ID(), t: v.ID()}] = struct{}{}
  1946  		}
  1947  	}
  1948  
  1949  	for remove.Next() {
  1950  		e := remove.Edge()
  1951  		if g.Edge(e.From().ID(), e.To().ID()) == nil {
  1952  			t.Fatalf("bad tests: missing edge: %#v", e)
  1953  		}
  1954  		if g.Node(e.From().ID()) == nil {
  1955  			t.Fatalf("bad tests: missing from node: %#v", e.From())
  1956  		}
  1957  		if g.Node(e.To().ID()) == nil {
  1958  			t.Fatalf("bad tests: missing to node: %#v", e.To())
  1959  		}
  1960  
  1961  		g.RemoveEdge(e.From().ID(), e.To().ID())
  1962  
  1963  		if _, ok := g.(graph.Undirected); ok {
  1964  			delete(edges, edge{f: e.To().ID(), t: e.From().ID()})
  1965  		}
  1966  		delete(edges, edge{f: e.From().ID(), t: e.To().ID()})
  1967  		for ge := range edges {
  1968  			if g.Edge(ge.f, ge.t) == nil {
  1969  				t.Fatalf("unexpected missing edge after removing edge %#v: %#v", e, ge)
  1970  			}
  1971  		}
  1972  
  1973  		if ne := g.Edge(e.From().ID(), e.To().ID()); ne != nil {
  1974  			t.Fatalf("expected nil edge: got:%#v", ne)
  1975  		}
  1976  		if g.Node(e.From().ID()) == nil {
  1977  			t.Fatalf("unexpected deletion of from node: %#v", e.From())
  1978  		}
  1979  		if g.Node(e.To().ID()) == nil {
  1980  			t.Fatalf("unexpected deletion  to node: %#v", e.To())
  1981  		}
  1982  	}
  1983  }
  1984  
  1985  // LineRemover is a graph.EdgeRemove graph.
  1986  type LineRemover interface {
  1987  	graph.Multigraph
  1988  	graph.LineRemover
  1989  }
  1990  
  1991  // RemoveLines tests whether g correctly implements the graph.LineRemover interface.
  1992  // The input graph g must contain a set of nodes with some lines between them.
  1993  // RemoveLines iterates over remove, which must contain lines in g, removing each
  1994  // line. RemoveLines confirms that the line is removed, leaving its end-point nodes
  1995  // and all other lines in the graph.
  1996  func RemoveLines(t *testing.T, g LineRemover, remove graph.Lines) {
  1997  	// lines is the set of lines in the graph.
  1998  	// The presence of a key indicates that the
  1999  	// line should exist in the graph. The value
  2000  	// for each key is used to indicate whether
  2001  	// it has been found during testing.
  2002  	lines := make(map[edge]bool)
  2003  	nodes := g.Nodes()
  2004  	for nodes.Next() {
  2005  		u := nodes.Node()
  2006  		uid := u.ID()
  2007  		to := g.From(uid)
  2008  		for to.Next() {
  2009  			v := to.Node()
  2010  			lit := g.Lines(u.ID(), v.ID())
  2011  			for lit.Next() {
  2012  				lines[edge{f: u.ID(), t: v.ID(), id: lit.Line().ID()}] = true
  2013  			}
  2014  		}
  2015  	}
  2016  
  2017  	for remove.Next() {
  2018  		l := remove.Line()
  2019  		if g.Lines(l.From().ID(), l.To().ID()) == graph.Empty {
  2020  			t.Fatalf("bad tests: missing line: %#v", l)
  2021  		}
  2022  		if g.Node(l.From().ID()) == nil {
  2023  			t.Fatalf("bad tests: missing from node: %#v", l.From())
  2024  		}
  2025  		if g.Node(l.To().ID()) == nil {
  2026  			t.Fatalf("bad tests: missing to node: %#v", l.To())
  2027  		}
  2028  
  2029  		prev := g.Lines(l.From().ID(), l.To().ID())
  2030  
  2031  		g.RemoveLine(l.From().ID(), l.To().ID(), l.ID())
  2032  
  2033  		if _, ok := g.(graph.Undirected); ok {
  2034  			delete(lines, edge{f: l.To().ID(), t: l.From().ID(), id: l.ID()})
  2035  		}
  2036  		delete(lines, edge{f: l.From().ID(), t: l.To().ID(), id: l.ID()})
  2037  
  2038  		// Mark all lines as not found.
  2039  		for gl := range lines {
  2040  			lines[gl] = false
  2041  		}
  2042  
  2043  		// Mark found lines. This could be done far more efficiently.
  2044  		for gl := range lines {
  2045  			lit := g.Lines(gl.f, gl.t)
  2046  			for lit.Next() {
  2047  				lid := lit.Line().ID()
  2048  				if lid == gl.id {
  2049  					lines[gl] = true
  2050  					break
  2051  				}
  2052  			}
  2053  		}
  2054  		for gl, found := range lines {
  2055  			if !found {
  2056  				t.Fatalf("unexpected missing line after removing line %#v: %#v", l, gl)
  2057  			}
  2058  		}
  2059  
  2060  		if curr := g.Lines(l.From().ID(), l.To().ID()); curr.Len() != prev.Len()-1 {
  2061  			t.Fatalf("RemoveLine failed to mutate graph: curr edge size != prev edge size-1, %d != %d", curr.Len(), prev.Len()-1)
  2062  		}
  2063  		if g.Node(l.From().ID()) == nil {
  2064  			t.Fatalf("unexpected deletion of from node: %#v", l.From())
  2065  		}
  2066  		if g.Node(l.To().ID()) == nil {
  2067  			t.Fatalf("unexpected deletion  to node: %#v", l.To())
  2068  		}
  2069  	}
  2070  }
  2071  
  2072  // undirectedIDs returns a numerical sort ordered canonicalisation of the
  2073  // IDs of e.
  2074  func undirectedIDs(e Edge) (lo, hi int64, inverted bool) {
  2075  	lid := e.From().ID()
  2076  	hid := e.To().ID()
  2077  	if hid < lid {
  2078  		inverted = true
  2079  		hid, lid = lid, hid
  2080  	}
  2081  	return lid, hid, inverted
  2082  }
  2083  
  2084  type edge struct {
  2085  	f, t, id int64
  2086  }
  2087  
  2088  func panics(fn func()) (ok bool) {
  2089  	defer func() {
  2090  		ok = recover() != nil
  2091  	}()
  2092  	fn()
  2093  	return
  2094  }
  2095  
  2096  // RandomNodes implements the graph.Nodes interface for a set of random nodes.
  2097  type RandomNodes struct {
  2098  	n       int
  2099  	seed    uint64
  2100  	newNode func(int64) graph.Node
  2101  
  2102  	curr int64
  2103  
  2104  	state *rand.Rand
  2105  	seen  set.Int64s
  2106  	count int
  2107  }
  2108  
  2109  var _ graph.Nodes = (*RandomNodes)(nil)
  2110  
  2111  // NewRandomNodes returns a new implicit node iterator containing a set of n nodes
  2112  // with IDs generated from a PRNG seeded by the given seed.
  2113  // The provided new func maps the id to a graph.Node.
  2114  func NewRandomNodes(n int, seed uint64, new func(id int64) graph.Node) *RandomNodes {
  2115  	return &RandomNodes{
  2116  		n:       n,
  2117  		seed:    seed,
  2118  		newNode: new,
  2119  
  2120  		state: rand.New(rand.NewSource(int64(seed))),
  2121  		seen:  make(set.Int64s),
  2122  		count: 0,
  2123  	}
  2124  }
  2125  
  2126  // Len returns the remaining number of nodes to be iterated over.
  2127  func (n *RandomNodes) Len() int {
  2128  	return n.n - n.count
  2129  }
  2130  
  2131  // Next returns whether the next call of Node will return a valid node.
  2132  func (n *RandomNodes) Next() bool {
  2133  	if n.count >= n.n {
  2134  		return false
  2135  	}
  2136  	n.count++
  2137  	for {
  2138  		sign := int64(1)
  2139  		if n.state.Float64() < 0.5 {
  2140  			sign *= -1
  2141  		}
  2142  		n.curr = sign * n.state.Int63()
  2143  		if !n.seen.Has(n.curr) {
  2144  			n.seen.Add(n.curr)
  2145  			return true
  2146  		}
  2147  	}
  2148  }
  2149  
  2150  // Node returns the current node of the iterator. Next must have been
  2151  // called prior to a call to Node.
  2152  func (n *RandomNodes) Node() graph.Node {
  2153  	if n.Len() == -1 || n.count == 0 {
  2154  		return nil
  2155  	}
  2156  	return n.newNode(n.curr)
  2157  }
  2158  
  2159  // Reset returns the iterator to its initial state.
  2160  func (n *RandomNodes) Reset() {
  2161  	n.state = rand.New(rand.NewSource(int64(n.seed)))
  2162  	n.seen = make(set.Int64s)
  2163  	n.count = 0
  2164  }
  2165  
  2166  // tripleInt64s is a set of [3]int64 identifiers.
  2167  type tripleInt64s map[[3]int64]struct{}
  2168  
  2169  // add inserts an element into the set.
  2170  func (s tripleInt64s) add(x, y, z int64) {
  2171  	s[[3]int64{x, y, z}] = struct{}{}
  2172  }
  2173  
  2174  // has reports the existence of the element in the set.
  2175  func (s tripleInt64s) has(x, y, z int64) bool {
  2176  	_, ok := s[[3]int64{x, y, z}]
  2177  	return ok
  2178  }