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  }