github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/uroot/uroot_test.go (about)

     1  // Copyright 2018 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package uroot
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"syscall"
    12  	"testing"
    13  
    14  	"github.com/mvdan/u-root-coreutils/pkg/cpio"
    15  	"github.com/mvdan/u-root-coreutils/pkg/ulog/ulogtest"
    16  	"github.com/mvdan/u-root-coreutils/pkg/uroot/builder"
    17  	itest "github.com/mvdan/u-root-coreutils/pkg/uroot/initramfs/test"
    18  )
    19  
    20  type inMemArchive struct {
    21  	*cpio.Archive
    22  }
    23  
    24  // Finish implements initramfs.Writer.Finish.
    25  func (inMemArchive) Finish() error { return nil }
    26  
    27  func TestCreateInitramfs(t *testing.T) {
    28  	dir := t.TempDir()
    29  	syscall.Umask(0)
    30  
    31  	urootpath, err := filepath.Abs("../../")
    32  	if err != nil {
    33  		t.Fatalf("failure to set up test: %v", err)
    34  	}
    35  
    36  	tmp777 := filepath.Join(dir, "tmp777")
    37  	if err := os.MkdirAll(tmp777, 0o777); err != nil {
    38  		t.Error(err)
    39  	}
    40  
    41  	l := ulogtest.Logger{TB: t}
    42  
    43  	for i, tt := range []struct {
    44  		name       string
    45  		opts       Opts
    46  		want       string
    47  		validators []itest.ArchiveValidator
    48  	}{
    49  		{
    50  			name: "BB archive with ls and init",
    51  			opts: Opts{
    52  				TempDir:         dir,
    53  				ExtraFiles:      nil,
    54  				UseExistingInit: false,
    55  				InitCmd:         "init",
    56  				DefaultShell:    "ls",
    57  				UrootSource:     urootpath,
    58  				Commands: []Commands{
    59  					{
    60  						Builder: builder.BusyBox,
    61  						Packages: []string{
    62  							"github.com/mvdan/u-root-coreutils/cmds/core/init",
    63  							"github.com/mvdan/u-root-coreutils/cmds/core/ls",
    64  						},
    65  					},
    66  				},
    67  			},
    68  			want: "",
    69  			validators: []itest.ArchiveValidator{
    70  				itest.HasFile{"bbin/bb"},
    71  				itest.HasRecord{cpio.Symlink("bbin/init", "bb")},
    72  				itest.HasRecord{cpio.Symlink("bbin/ls", "bb")},
    73  				itest.HasRecord{cpio.Symlink("bin/defaultsh", "../bbin/ls")},
    74  				itest.HasRecord{cpio.Symlink("bin/sh", "../bbin/ls")},
    75  			},
    76  		},
    77  		{
    78  			name: "no temp dir",
    79  			opts: Opts{
    80  				InitCmd:      "init",
    81  				DefaultShell: "",
    82  			},
    83  			want: "temp dir \"\" must exist: stat : no such file or directory",
    84  			validators: []itest.ArchiveValidator{
    85  				itest.IsEmpty{},
    86  			},
    87  		},
    88  		{
    89  			name: "no commands",
    90  			opts: Opts{
    91  				TempDir: dir,
    92  			},
    93  			want: "",
    94  			validators: []itest.ArchiveValidator{
    95  				itest.MissingFile{"bbin/bb"},
    96  			},
    97  		},
    98  		{
    99  			name: "init specified, but not in commands",
   100  			opts: Opts{
   101  				TempDir:      dir,
   102  				DefaultShell: "zoocar",
   103  				InitCmd:      "foobar",
   104  				UrootSource:  urootpath,
   105  				Commands: []Commands{
   106  					{
   107  						Builder: builder.Binary,
   108  						Packages: []string{
   109  							"github.com/mvdan/u-root-coreutils/cmds/core/ls",
   110  						},
   111  					},
   112  				},
   113  			},
   114  			want: "could not create symlink from \"init\" to \"foobar\": command or path \"foobar\" not included in u-root build: specify -initcmd=\"\" to ignore this error and build without an init (or, did you specify a list, and are you missing github.com/mvdan/u-root-coreutils/cmds/core/init?)",
   115  			validators: []itest.ArchiveValidator{
   116  				itest.IsEmpty{},
   117  			},
   118  		},
   119  		{
   120  			name: "init symlinked to absolute path",
   121  			opts: Opts{
   122  				TempDir: dir,
   123  				InitCmd: "/bin/systemd",
   124  			},
   125  			want: "",
   126  			validators: []itest.ArchiveValidator{
   127  				itest.HasRecord{cpio.Symlink("init", "bin/systemd")},
   128  			},
   129  		},
   130  		{
   131  			name: "multi-mode archive",
   132  			opts: Opts{
   133  				TempDir:         dir,
   134  				ExtraFiles:      nil,
   135  				UseExistingInit: false,
   136  				InitCmd:         "init",
   137  				DefaultShell:    "ls",
   138  				UrootSource:     urootpath,
   139  				Commands: []Commands{
   140  					{
   141  						Builder: builder.BusyBox,
   142  						Packages: []string{
   143  							"github.com/mvdan/u-root-coreutils/cmds/core/init",
   144  							"github.com/mvdan/u-root-coreutils/cmds/core/ls",
   145  						},
   146  					},
   147  					{
   148  						Builder: builder.Binary,
   149  						Packages: []string{
   150  							"github.com/mvdan/u-root-coreutils/cmds/core/cp",
   151  							"github.com/mvdan/u-root-coreutils/cmds/core/dd",
   152  						},
   153  					},
   154  				},
   155  			},
   156  			want: "",
   157  			validators: []itest.ArchiveValidator{
   158  				itest.HasRecord{cpio.Symlink("init", "bbin/init")},
   159  
   160  				// bb mode.
   161  				itest.HasFile{"bbin/bb"},
   162  				itest.HasRecord{cpio.Symlink("bbin/init", "bb")},
   163  				itest.HasRecord{cpio.Symlink("bbin/ls", "bb")},
   164  				itest.HasRecord{cpio.Symlink("bin/defaultsh", "../bbin/ls")},
   165  				itest.HasRecord{cpio.Symlink("bin/sh", "../bbin/ls")},
   166  
   167  				// binary mode.
   168  				itest.HasFile{"bin/cp"},
   169  				itest.HasFile{"bin/dd"},
   170  			},
   171  		},
   172  	} {
   173  		t.Run(fmt.Sprintf("Test %d [%s]", i, tt.name), func(t *testing.T) {
   174  			archive := inMemArchive{cpio.InMemArchive()}
   175  			tt.opts.OutputFile = archive
   176  			// Compare error type or error string.
   177  			if err := CreateInitramfs(l, tt.opts); (err != nil && err.Error() != tt.want) || (len(tt.want) > 0 && err == nil) {
   178  				t.Errorf("CreateInitramfs(%v) = %v, want %v", tt.opts, err, tt.want)
   179  			}
   180  
   181  			for _, v := range tt.validators {
   182  				if err := v.Validate(archive.Archive); err != nil {
   183  					t.Errorf("validator failed: %v / archive:\n%s", err, archive)
   184  				}
   185  			}
   186  		})
   187  	}
   188  }