github.com/9elements/firmware-action/action@v0.0.0-20240514065043-044ed91c9ed8/recipes/recipes_test.go (about)

     1  // SPDX-License-Identifier: MIT
     2  package recipes
     3  
     4  import (
     5  	"context"
     6  	"os"
     7  	"testing"
     8  
     9  	"dagger.io/dagger"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestExecute(t *testing.T) {
    14  	const interactive = false
    15  	ctx := context.Background()
    16  	client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stdout))
    17  	assert.NoError(t, err)
    18  	defer client.Close()
    19  
    20  	testCases := []struct {
    21  		name       string
    22  		wantErr    error
    23  		target     string
    24  		targetType string
    25  		config     Config
    26  	}{
    27  		{
    28  			name:    "empty target string",
    29  			wantErr: ErrTargetMissing,
    30  			target:  "",
    31  			config:  Config{},
    32  		},
    33  		{
    34  			name:    "invalid target",
    35  			wantErr: ErrTargetMissing,
    36  			target:  "dummy",
    37  			config:  Config{},
    38  		},
    39  	}
    40  	for _, tc := range testCases {
    41  		t.Run(tc.name, func(t *testing.T) {
    42  			err = Execute(ctx, tc.target, &tc.config, interactive)
    43  			assert.ErrorIs(t, err, tc.wantErr)
    44  		})
    45  	}
    46  }
    47  
    48  func executeDummy(_ context.Context, _ string, _ *Config, _ bool) error {
    49  	return nil
    50  }
    51  
    52  func TestBuild(t *testing.T) {
    53  	ctx := context.Background()
    54  
    55  	testConfig := Config{
    56  		Coreboot: map[string]CorebootOpts{
    57  			"coreboot-0": {Depends: []string{}},
    58  			"coreboot-A": {Depends: []string{"linux-A"}},
    59  			"coreboot-B": {Depends: []string{"edk2-B"}},
    60  			"coreboot-C": {Depends: []string{"linux-C", "edk2-C"}},
    61  		},
    62  		Linux: map[string]LinuxOpts{
    63  			"linux-A": {Depends: []string{}},
    64  			"linux-C": {Depends: []string{}},
    65  		},
    66  		Edk2: map[string]Edk2Opts{
    67  			"edk2-B": {Depends: []string{}},
    68  			"edk2-C": {Depends: []string{}},
    69  		},
    70  	}
    71  
    72  	testConfigDependencyHell := Config{
    73  		// Please keep everything in coreboot for simplicity sake
    74  		// There is a test which checks order of builds, and it would explode in complexity
    75  		Coreboot: map[string]CorebootOpts{
    76  			"pizza":  {Depends: []string{"dough", "cheese"}},
    77  			"dough":  {Depends: []string{"flour", "water"}},
    78  			"cheese": {Depends: []string{"milk"}},
    79  			"flour":  {Depends: []string{}},
    80  			"water":  {Depends: []string{}},
    81  			"milk":   {Depends: []string{"water"}},
    82  		},
    83  		Linux: map[string]LinuxOpts{},
    84  		Edk2:  map[string]Edk2Opts{},
    85  	}
    86  	//  Pizza
    87  	//    |
    88  	//    +------+
    89  	//    |      |
    90  	//  dough  cheese
    91  	//    |      |
    92  	//    +---+  |
    93  	//    |   |  |
    94  	//  flour | milk
    95  	//        |  |
    96  	//       water
    97  
    98  	testCases := []struct {
    99  		name      string
   100  		wantErr   error
   101  		target    string
   102  		recursive bool
   103  		config    Config
   104  	}{
   105  		{
   106  			name:      "unknown dependency",
   107  			wantErr:   ErrDependencyTreeUndefDep,
   108  			target:    "",
   109  			recursive: false,
   110  			config: Config{
   111  				Coreboot: map[string]CorebootOpts{
   112  					"coreboot-A": {Depends: []string{"dummy"}},
   113  				},
   114  			},
   115  		},
   116  		{
   117  			name:      "circular self-dependency",
   118  			wantErr:   ErrDependencyTreeUndefDep,
   119  			target:    "",
   120  			recursive: false,
   121  			config: Config{
   122  				Coreboot: map[string]CorebootOpts{
   123  					"coreboot-A": {Depends: []string{"coreboot-A"}},
   124  				},
   125  			},
   126  		},
   127  		{
   128  			name:      "circular dependency",
   129  			wantErr:   ErrDependencyTreeUndefDep,
   130  			target:    "",
   131  			recursive: false,
   132  			config: Config{
   133  				Coreboot: map[string]CorebootOpts{
   134  					"coreboot-A": {Depends: []string{"coreboot-B"}},
   135  					"coreboot-B": {Depends: []string{"coreboot-A"}},
   136  				},
   137  			},
   138  		},
   139  		{
   140  			name:      "unknown target",
   141  			wantErr:   ErrDependencyTreeUnderTarget,
   142  			target:    "",
   143  			recursive: false,
   144  			config:    testConfig,
   145  		},
   146  		{
   147  			name:      "dependency clusterfuck",
   148  			wantErr:   nil,
   149  			target:    "pizza",
   150  			recursive: false,
   151  			config:    testConfigDependencyHell,
   152  		},
   153  	}
   154  
   155  	const interactive = false
   156  	for _, tc := range testCases {
   157  		t.Run(tc.name, func(t *testing.T) {
   158  			_, err := Build(
   159  				ctx,
   160  				tc.target,
   161  				tc.recursive,
   162  				interactive,
   163  				&tc.config,
   164  				executeDummy,
   165  			)
   166  			assert.ErrorIs(t, err, tc.wantErr)
   167  		})
   168  	}
   169  	const recursive = true
   170  	t.Run("recursive", func(t *testing.T) {
   171  		builds, err := Build(
   172  			ctx,
   173  			"pizza",
   174  			recursive,
   175  			interactive,
   176  			&testConfigDependencyHell,
   177  			executeDummy,
   178  		)
   179  		assert.ErrorIs(t, err, nil)
   180  
   181  		// Check for length
   182  		assert.Equal(t, len(testConfigDependencyHell.Coreboot), len(builds))
   183  
   184  		// Go though 'builds' and check if for each builds, the dependencies are already complete
   185  		done := []string{}
   186  		for _, item := range builds {
   187  			for _, i := range testConfigDependencyHell.Coreboot[item].Depends {
   188  				assert.Contains(t, done, i)
   189  			}
   190  			done = append(done, item)
   191  		}
   192  	})
   193  }