github.com/rliebz/tusk@v0.6.5-0.20240416035353-dd5a98e9a5fb/runner/dependencies_test.go (about)

     1  package runner
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/rliebz/ghost"
     7  	"github.com/rliebz/ghost/be"
     8  )
     9  
    10  func TestFindAllOptions(t *testing.T) {
    11  	tests := []struct {
    12  		name            string
    13  		taskOptions     []*Option
    14  		cfgOptions      []*Option
    15  		wantTaskIndices []int
    16  		wantCfgIndices  []int
    17  	}{
    18  		{
    19  			name: "no dependencies",
    20  			cfgOptions: []*Option{
    21  				createOption(
    22  					withOptionName("foo"),
    23  				),
    24  			},
    25  		},
    26  		{
    27  			name: "fake dependencies",
    28  			taskOptions: []*Option{
    29  				createOption(
    30  					withOptionName("foo"),
    31  					withOptionDependency("fake"),
    32  				),
    33  			},
    34  			wantTaskIndices: []int{0},
    35  		},
    36  		{
    37  			name: "multiple dependencies per option",
    38  			taskOptions: []*Option{
    39  				createOption(
    40  					withOptionName("foo"),
    41  					withOptionDependency("one"),
    42  					withOptionDependency("two"),
    43  					withOptionDependency("three"),
    44  				),
    45  			},
    46  			cfgOptions: []*Option{
    47  				createOption(
    48  					withOptionName("one"),
    49  				),
    50  				createOption(
    51  					withOptionName("two"),
    52  				),
    53  				createOption(
    54  					withOptionName("three"),
    55  				),
    56  				createOption(
    57  					withOptionName("wrong"),
    58  				),
    59  			},
    60  			wantTaskIndices: []int{0},
    61  			wantCfgIndices:  []int{0, 1, 2},
    62  		},
    63  		{
    64  			name: "only task dependencies",
    65  			taskOptions: []*Option{
    66  				createOption(
    67  					withOptionName("foo"),
    68  				),
    69  				createOption(
    70  					withOptionName("bar"),
    71  					withOptionDependency("foo"),
    72  				),
    73  			},
    74  			wantTaskIndices: []int{0, 1},
    75  		},
    76  		{
    77  			name: "overridden global dependencies",
    78  			taskOptions: []*Option{
    79  				createOption(
    80  					withOptionName("foo"),
    81  				),
    82  				createOption(
    83  					withOptionName("bar"),
    84  					withOptionDependency("foo"),
    85  				),
    86  			},
    87  			cfgOptions: []*Option{
    88  				createOption(
    89  					withOptionName("foo"),
    90  				),
    91  			},
    92  			wantTaskIndices: []int{0, 1},
    93  		},
    94  		{
    95  			name: "when dependencies",
    96  			taskOptions: []*Option{
    97  				createOption(
    98  					withOptionName("foo"),
    99  				),
   100  				createOption(
   101  					withOptionName("bar"),
   102  					withOptionWhenDependency("foo"),
   103  				),
   104  			},
   105  			wantTaskIndices: []int{0, 1},
   106  		},
   107  		{
   108  			name: "task requires global",
   109  			taskOptions: []*Option{
   110  				createOption(
   111  					withOptionName("bar"),
   112  					withOptionDependency("foo"),
   113  				),
   114  			},
   115  			cfgOptions: []*Option{
   116  				createOption(
   117  					withOptionName("foo"),
   118  				),
   119  			},
   120  			wantTaskIndices: []int{0},
   121  			wantCfgIndices:  []int{0},
   122  		},
   123  		{
   124  			name: "global requires task (false positive)",
   125  			taskOptions: []*Option{
   126  				createOption(
   127  					withOptionName("foo"),
   128  				),
   129  			},
   130  			cfgOptions: []*Option{
   131  				createOption(
   132  					withOptionName("bar"),
   133  					withOptionDependency("foo"),
   134  				),
   135  			},
   136  			wantTaskIndices: []int{0},
   137  		},
   138  		{
   139  			name: "nested depdendencies",
   140  			taskOptions: []*Option{
   141  				createOption(
   142  					withOptionName("foo"),
   143  					withOptionDependency("bar"),
   144  				),
   145  				createOption(
   146  					withOptionName("bar"),
   147  					withOptionDependency("baz"),
   148  				),
   149  			},
   150  			cfgOptions: []*Option{
   151  				createOption(
   152  					withOptionName("baz"),
   153  					withOptionDependency("qux"),
   154  				),
   155  				createOption(
   156  					withOptionName("qux"),
   157  				),
   158  			},
   159  			wantTaskIndices: []int{0, 1},
   160  			wantCfgIndices:  []int{0, 1},
   161  		},
   162  		{
   163  			name: "nested depdendencies with ignored globals",
   164  			taskOptions: []*Option{
   165  				createOption(
   166  					withOptionName("foo"),
   167  					withOptionDependency("bar"),
   168  				),
   169  				createOption(
   170  					withOptionName("bar"),
   171  					withOptionDependency("baz"),
   172  				),
   173  			},
   174  			cfgOptions: []*Option{
   175  				createOption(
   176  					withOptionName("qux"),
   177  				),
   178  				createOption(
   179  					withOptionName("skiptwo"),
   180  				),
   181  				createOption(
   182  					withOptionName("baz"),
   183  					withOptionDependency("qux"),
   184  				),
   185  				createOption(
   186  					withOptionName("skipone"),
   187  					withOptionDependency("skiptwo"),
   188  				),
   189  			},
   190  			wantTaskIndices: []int{0, 1},
   191  			wantCfgIndices:  []int{0, 2},
   192  		},
   193  	}
   194  
   195  	for _, tt := range tests {
   196  		t.Run(tt.name, func(t *testing.T) {
   197  			g := ghost.New(t)
   198  
   199  			var tsk Task
   200  			for _, opt := range tt.taskOptions {
   201  				tsk.Options = append(tsk.Options, opt)
   202  			}
   203  
   204  			var cfg Config
   205  			for _, opt := range tt.cfgOptions {
   206  				cfg.Options = append(cfg.Options, opt)
   207  			}
   208  
   209  			got, err := FindAllOptions(&tsk, &cfg)
   210  			g.NoError(err)
   211  
   212  			var want []*Option
   213  			for _, i := range tt.wantTaskIndices {
   214  				want = append(want, tt.taskOptions[i])
   215  			}
   216  			for _, i := range tt.wantCfgIndices {
   217  				want = append(want, tt.cfgOptions[i])
   218  			}
   219  
   220  			assertOptionsEqualUnordered(t, want, got)
   221  		})
   222  	}
   223  }
   224  
   225  func assertOptionsEqualUnordered(t *testing.T, a, b []*Option) {
   226  	t.Helper()
   227  
   228  	g := ghost.New(t)
   229  
   230  	if !g.Should(be.SliceLen(b, len(a))) {
   231  		return
   232  	}
   233  
   234  	bMap := make(map[*Option]interface{})
   235  	for _, val := range b {
   236  		bMap[val] = struct{}{}
   237  	}
   238  
   239  	for _, item := range a {
   240  		_, ok := bMap[item]
   241  		if !g.Should(be.True(ok)) {
   242  			t.Log("missing item:", item)
   243  		}
   244  	}
   245  }