github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/pkg/model/target_test.go (about)

     1  package model
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	"github.com/tilt-dev/tilt/internal/container"
    11  )
    12  
    13  type topSortCase struct {
    14  	inputs  []TargetSpec
    15  	outputs []string
    16  	err     string
    17  }
    18  
    19  func TestTopSort(t *testing.T) {
    20  	cases := []topSortCase{
    21  		topSortCase{
    22  			inputs: []TargetSpec{newDepTarget("a", "b")},
    23  			err:    "Missing target dependency: b",
    24  		},
    25  		topSortCase{
    26  			inputs: []TargetSpec{
    27  				newDepTarget("a", "b"),
    28  				newDepTarget("b", "a"),
    29  			},
    30  			err: "Found a cycle at target: a",
    31  		},
    32  		topSortCase{
    33  			inputs: []TargetSpec{
    34  				newDepTarget("a", "b"),
    35  				newDepTarget("b", "c"),
    36  				newDepTarget("c", "a"),
    37  			},
    38  			err: "Found a cycle at target: a",
    39  		},
    40  		topSortCase{
    41  			inputs: []TargetSpec{
    42  				newDepTarget("a", "b"),
    43  				newDepTarget("b", "c"),
    44  				newDepTarget("c"),
    45  			},
    46  			outputs: []string{"c", "b", "a"},
    47  		},
    48  		topSortCase{
    49  			inputs: []TargetSpec{
    50  				newDepTarget("a", "b", "d"),
    51  				newDepTarget("b", "d"),
    52  				newDepTarget("c", "d"),
    53  				newDepTarget("d"),
    54  			},
    55  			outputs: []string{"d", "b", "a", "c"},
    56  		},
    57  		topSortCase{
    58  			inputs: []TargetSpec{
    59  				newDepTarget("a", "b", "d"),
    60  				newDepTarget("c", "d"),
    61  				newDepTarget("b", "d"),
    62  				newDepTarget("d"),
    63  			},
    64  			outputs: []string{"d", "b", "a", "c"},
    65  		},
    66  		topSortCase{
    67  			inputs: []TargetSpec{
    68  				newDepTarget("c", "d"),
    69  				newDepTarget("b", "d"),
    70  				newDepTarget("a", "b", "d"),
    71  				newDepTarget("d"),
    72  			},
    73  			outputs: []string{"d", "c", "b", "a"},
    74  		},
    75  	}
    76  
    77  	for i, c := range cases {
    78  		t.Run(fmt.Sprintf("TopSort%d", i), func(t *testing.T) {
    79  			sorted, err := TopologicalSort(c.inputs)
    80  			if err != nil {
    81  				if c.err == "" {
    82  					t.Fatalf("Unexpected error: %v", err)
    83  					return
    84  				}
    85  
    86  				assert.Contains(t, err.Error(), c.err)
    87  				return
    88  			}
    89  
    90  			if c.err != "" {
    91  				t.Fatalf("Expected error: %s. Actual nil", c.err)
    92  			}
    93  
    94  			sortedIDs := make([]string, len(sorted))
    95  			for i, t := range sorted {
    96  				sortedIDs[i] = path.Base(t.ID().Name.String())
    97  			}
    98  			assert.Equal(t, c.outputs, sortedIDs)
    99  		})
   100  	}
   101  }
   102  
   103  func newDepTarget(name string, deps ...string) ImageTarget {
   104  	ref := container.MustParseSelector(name)
   105  	depIDs := make([]string, len(deps))
   106  	for i, dep := range deps {
   107  		depIDs[i] = string(ImageID(container.MustParseSelector(dep)).Name)
   108  	}
   109  	return MustNewImageTarget(ref).
   110  		WithBuildDetails(DockerBuild{}).
   111  		WithImageMapDeps(depIDs)
   112  }
   113  
   114  func newK8sTarget(name string, deps ...string) K8sTarget {
   115  	depIDs := make([]string, len(deps))
   116  	for i, dep := range deps {
   117  		depIDs[i] = string(ImageID(container.MustParseSelector(dep)).Name)
   118  	}
   119  	return K8sTarget{Name: TargetName(name)}.WithImageDependencies(depIDs)
   120  }