github.com/whiteboxio/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/util/data/topology_test.go (about)

     1  package data
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"testing"
     7  )
     8  
     9  type testNode struct {
    10  	name string
    11  }
    12  
    13  func (tn *testNode) GetName() string {
    14  	return tn.name
    15  }
    16  
    17  func newNode(name string) *testNode {
    18  	return &testNode{name}
    19  }
    20  
    21  func TestTopology_SortEmpty(t *testing.T) {
    22  	nodes := []TopologyNode{}
    23  	top := NewTopology(nodes...)
    24  	sorted, err := top.Sort()
    25  	if err != nil {
    26  		t.Errorf("Unexpected error: %s", err)
    27  	}
    28  	if l := len(sorted); l != 0 {
    29  		t.Errorf("Unexpected length of sorted arr: %d (want 0)", l)
    30  	}
    31  }
    32  
    33  func TestTopology_SortSingle(t *testing.T) {
    34  	nodes := []TopologyNode{
    35  		newNode("1"),
    36  	}
    37  	top := NewTopology(nodes...)
    38  	sorted, err := top.Sort()
    39  	if err != nil {
    40  		t.Errorf("Unexpected error: %s", err)
    41  	}
    42  	if l := len(sorted); l != 1 {
    43  		t.Errorf("Unexpected length of sorted arr: %d (want 0)", l)
    44  	}
    45  	if !reflect.DeepEqual(sorted[0], nodes[0]) {
    46  		t.Errorf("Unexpected element in sorted list: %+v", sorted[0])
    47  	}
    48  }
    49  
    50  type StringerNode string
    51  
    52  func TestTopology_SortUnresolvable(t *testing.T) {
    53  	nodes := []TopologyNode{
    54  		StringerNode("1"),
    55  		StringerNode("2"),
    56  		StringerNode("3"),
    57  	}
    58  
    59  	top := NewTopology(nodes...)
    60  	top.Connect(nodes[0], nodes[1])
    61  	top.Connect(nodes[1], nodes[2])
    62  	top.Connect(nodes[2], nodes[0])
    63  
    64  	sorted, err := top.Sort()
    65  	if err == nil {
    66  		t.Errorf("Expected an error from a cycled graph")
    67  	}
    68  	if l := len(sorted); l != 0 {
    69  		t.Errorf("Unexpected length of the sorted result: %d (want 0)", l)
    70  	}
    71  	res := make([]string, 0, len(sorted))
    72  	for _, node := range sorted {
    73  		res = append(res, string(node.(StringerNode)))
    74  	}
    75  	t.Log(strings.Join(res, " -> "))
    76  }
    77  
    78  /*
    79  https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/Directed_acyclic_graph_2.svg/1280px-Directed_acyclic_graph_2.svg.png
    80  
    81     (5)  (7) (3)
    82      |  / |  /
    83      v /  v /
    84     (11) (8)
    85  	| \ \|
    86  	v  \ v \
    87     (2)  (9) (10)
    88  
    89  */
    90  func TestTopology_SortExample(t *testing.T) {
    91  	node2, node3, node5, node7, node8, node9, node10, node11 :=
    92  		StringerNode("2"),
    93  		StringerNode("3"),
    94  		StringerNode("5"),
    95  		StringerNode("7"),
    96  		StringerNode("8"),
    97  		StringerNode("9"),
    98  		StringerNode("10"),
    99  		StringerNode("11")
   100  
   101  	connections := map[StringerNode][]StringerNode{
   102  		node5:  {node11},
   103  		node7:  {node11, node8},
   104  		node3:  {node8, node10},
   105  		node11: {node2, node9, node10},
   106  		node8:  {node9},
   107  	}
   108  
   109  	top := NewTopology(node2, node3, node5, node7, node8, node9, node10, node11)
   110  
   111  	for from, tos := range connections {
   112  		for _, to := range tos {
   113  			if err := top.Connect(from, to); err != nil {
   114  				t.Fatalf(err.Error())
   115  			}
   116  		}
   117  	}
   118  
   119  	sorted, err := top.Sort()
   120  	if err != nil {
   121  		t.Fatalf("Failed to perform topological sort of the graph: %s", err)
   122  	}
   123  
   124  	visited := make(map[StringerNode]bool)
   125  	for _, node := range sorted {
   126  		if deps, ok := connections[node.(StringerNode)]; ok {
   127  			for _, dep := range deps {
   128  				if _, ok := visited[dep]; !ok {
   129  					t.Fatalf(
   130  						"Node %#v was expected to be visited after %#v. Full order: %#v\n",
   131  						node,
   132  						dep,
   133  						sorted)
   134  				}
   135  			}
   136  		}
   137  		visited[node.(StringerNode)] = true
   138  	}
   139  }