github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/config/resolve/dep_graph_test.go (about) 1 package resolve 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/replicatedhq/libyaml" 8 "github.com/replicatedhq/ship/pkg/templates" 9 "github.com/replicatedhq/ship/pkg/testing/logger" 10 "github.com/spf13/viper" 11 "github.com/stretchr/testify/require" 12 ) 13 14 type depGraphTestCase struct { 15 dependencies map[string][]string 16 resolveOrder []string 17 expectError bool //expect an error fetching head nodes 18 expectNotFound string //expect this dependency not to be part of the head nodes 19 20 name string 21 } 22 23 func TestDepGraph(t *testing.T) { 24 tests := []depGraphTestCase{ 25 { 26 dependencies: map[string][]string{ 27 "alpha": {}, 28 "bravo": {"alpha"}, 29 "charlie": {"bravo"}, 30 "delta": {"alpha", "charlie"}, 31 "echo": {}, 32 }, 33 resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo"}, 34 name: "basic_dependency_chain", 35 }, 36 { 37 dependencies: map[string][]string{ 38 "alpha": {"bravo"}, 39 "bravo": {"alpha"}, 40 }, 41 resolveOrder: []string{"alpha", "bravo"}, 42 expectError: true, 43 name: "basic_circle", 44 }, 45 { 46 dependencies: map[string][]string{ 47 "alpha": {}, 48 "bravo": {"alpha"}, 49 "charlie": {"alpha"}, 50 "delta": {"bravo", "charlie"}, 51 "echo": {"delta"}, 52 }, 53 resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo"}, 54 name: "basic_forked_chain", 55 }, 56 { 57 dependencies: map[string][]string{ 58 "alpha": {}, 59 "bravo": {"alpha"}, 60 "charlie": {"alpha"}, 61 "delta": {"bravo", "charlie", "foxtrot"}, 62 "echo": {"delta"}, 63 "foxtrot": {}, 64 }, 65 resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot"}, 66 expectNotFound: "delta", 67 name: "unresolved_dependency", 68 }, 69 { 70 dependencies: map[string][]string{ 71 "alpha": {}, 72 "bravo": {}, 73 "charlie": {"alpha"}, 74 "delta": {"bravo"}, 75 "echo": {"delta"}, 76 }, 77 resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo"}, 78 name: "two_chains", 79 }, 80 { 81 dependencies: map[string][]string{ 82 "alpha": {}, 83 "bravo": {"alpha"}, 84 "charlie": {"alpha", "bravo"}, 85 "delta": {"alpha", "bravo", "charlie"}, 86 "echo": {"alpha", "bravo", "charlie", "delta"}, 87 "foxtrot": {"alpha", "bravo", "charlie", "delta", "echo"}, 88 "golf": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot"}, 89 "hotel": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf"}, 90 "india": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"}, 91 "juliet": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india"}, 92 "kilo": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet"}, 93 "lima": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo"}, 94 "mike": {"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima"}, 95 }, 96 resolveOrder: []string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima", "mike"}, 97 name: "pyramid", 98 }, 99 } 100 for _, test := range tests { 101 t.Run(test.name, func(t *testing.T) { 102 103 builderBuilder := &templates.BuilderBuilder{ 104 Logger: &logger.TestLogger{T: t}, 105 Viper: viper.New(), 106 } 107 graph := depGraph{ 108 BuilderBuilder: builderBuilder, 109 } 110 for source, deps := range test.dependencies { 111 graph.AddNode(source) 112 for _, dep := range deps { 113 graph.AddDep(source, dep) 114 } 115 } 116 runGraphTests(t, test, graph) 117 }) 118 119 t.Run(test.name+"+parse", func(t *testing.T) { 120 builderBuilder := &templates.BuilderBuilder{ 121 Logger: &logger.TestLogger{T: t}, 122 Viper: viper.New(), 123 } 124 125 graph := depGraph{ 126 BuilderBuilder: builderBuilder, 127 } 128 129 groups := buildTestConfigGroups(test.dependencies, "templateStringStart", "templateStringEnd", true) 130 131 err := graph.ParseConfigGroup(groups) 132 require.NoError(t, err) 133 134 runGraphTests(t, test, graph) 135 }) 136 } 137 } 138 139 func buildTestConfigGroups(dependencies map[string][]string, prefix string, suffix string, rotate bool) []libyaml.ConfigGroup { 140 group := libyaml.ConfigGroup{} 141 group.Items = make([]*libyaml.ConfigItem, 0) 142 counter := 0 143 144 templateFuncs := []string{ 145 "{{repl ConfigOption \"%s\" }}", 146 "{{repl ConfigOptionIndex \"%s\" }}", 147 "{{repl ConfigOptionData \"%s\" }}", 148 "{{repl ConfigOptionEquals \"%s\" \"abc\" }}", 149 "{{repl ConfigOptionNotEquals \"%s\" \"xyz\" }}{{repl DoesNotExistFunc }}", 150 } 151 152 if !rotate { 153 //use only ConfigOption, not all 5 154 templateFuncs = []string{ 155 "{{repl ConfigOption \"%s\" }}", 156 } 157 } 158 159 for source, deps := range dependencies { 160 newItem := libyaml.ConfigItem{Type: "text", Name: source} 161 depString := prefix 162 for i, dep := range deps { 163 depString += fmt.Sprintf(templateFuncs[i%len(templateFuncs)], dep) 164 } 165 depString += suffix 166 167 if counter%2 == 0 { 168 newItem.Value = depString 169 } else { 170 newItem.Default = depString 171 } 172 counter++ 173 174 group.Items = append(group.Items, &newItem) 175 } 176 177 return []libyaml.ConfigGroup{group} 178 } 179 180 func runGraphTests(t *testing.T, test depGraphTestCase, graph depGraph) { 181 depLen := len(graph.Dependencies) 182 graphCopy, err := graph.Copy() 183 require.NoError(t, err) 184 185 for _, toResolve := range test.resolveOrder { 186 available, err := graph.GetHeadNodes() 187 if err != nil && test.expectError { 188 return 189 } 190 191 require.NoError(t, err, "toResolve: %s", toResolve) 192 193 if test.expectNotFound != "" && toResolve == test.expectNotFound { 194 require.NotContains(t, available, toResolve) 195 return 196 } 197 198 require.Contains(t, available, toResolve) 199 200 graph.ResolveDep(toResolve) 201 } 202 203 available, err := graph.GetHeadNodes() 204 require.NoError(t, err) 205 require.Empty(t, available) 206 207 require.False(t, test.expectError, "Did not find expected error") 208 209 require.Equal(t, depLen, len(graphCopy.Dependencies)) 210 }