github.com/fugue/regula/v2@v2.10.0/pkg/topsort/topsort_test.go (about) 1 // Copyright 2021 Fugue, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package topsort 16 17 import ( 18 "testing" 19 ) 20 21 func Test_topsort(t *testing.T) { 22 type Test struct { 23 name string 24 entries []Key 25 dependencies [][]Key 26 expectError bool 27 } 28 29 tests := []Test{ 30 { 31 name: "Simple", 32 entries: []Key{"one", "two", "three"}, 33 dependencies: [][]Key{ 34 {"one", "two"}, 35 {"two", "three"}, 36 }, 37 }, 38 { 39 name: "Cycle", 40 entries: []Key{"one", "two", "three"}, 41 dependencies: [][]Key{ 42 {"one", "two"}, 43 {"two", "three"}, 44 {"three", "one"}, 45 }, 46 expectError: true, 47 }, 48 { 49 name: "Cliques", 50 entries: []Key{"one", "two", "three", "four", "five"}, 51 dependencies: [][]Key{ 52 {"one", "two"}, 53 {"two", "three"}, 54 {"five", "four"}, 55 }, 56 }, 57 { 58 name: "Non-existing dependencies", 59 entries: []Key{"one", "two", "three"}, 60 dependencies: [][]Key{ 61 {"one", "een"}, 62 {"two", "twee"}, 63 {"three", "one"}, 64 }, 65 }, 66 } 67 68 for _, tc := range tests { 69 t.Run(tc.name, func(t *testing.T) { 70 // Build graph 71 g := make(Graph) 72 for _, k := range tc.entries { 73 g[k] = []Key{} 74 } 75 for _, dependency := range tc.dependencies { 76 k := dependency[0] 77 g[k] = append(g[k], dependency[1]) 78 } 79 80 // Run topsort 81 sorted, err := Topsort(g) 82 83 // Check error 84 if tc.expectError { 85 if err == nil { 86 t.Fatal("Expected error but succeeded") 87 } 88 } else { 89 // Check that every item appears after all its dependencies 90 indices := map[string]int{} 91 for i, k := range sorted { 92 indices[k] = i 93 } 94 for _, dependency := range tc.dependencies { 95 k := dependency[0] 96 l := dependency[1] 97 i := indices[k] 98 if j, ok := indices[l]; ok { 99 if i <= j { 100 t.Fatalf("Expected '%s' after '%s' but they have indices %d and %d", k, l, i, j) 101 } 102 } 103 } 104 } 105 }) 106 } 107 }