github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/grub/echo_test.go (about)

     1  // Copyright 2017-2020 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 grub
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"flag"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"net/url"
    14  	"os"
    15  	"os/exec"
    16  	"path/filepath"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/u-root/u-root/pkg/curl"
    21  )
    22  
    23  var update = flag.Bool("run-bash", false, "run bash and update golden file")
    24  
    25  // TestMain is used to warp a go utility in the same test binary
    26  // when the environment variable BE_ECHO is set to 1, the binary will echo its
    27  // parameters using the %#v format string, so the parameters are escaped and can
    28  // be recovered.
    29  func TestMain(m *testing.M) {
    30  	if os.Getenv("BE_ECHO") == "1" {
    31  		fmt.Printf("echo:%#v\n", os.Args[1:])
    32  		return
    33  	} // call flag.Parse() here if TestMain uses flags
    34  	os.Exit(m.Run())
    35  }
    36  
    37  // TestHelperEcho tests the echo wrapper in TestMain
    38  func TestHelperEcho(t *testing.T) {
    39  	cmd := exec.Command(os.Args[0], "echothis")
    40  	cmd.Env = append(os.Environ(), "BE_ECHO=1")
    41  	out, err := cmd.Output()
    42  	t.Logf("%q\n", out)
    43  	if err != nil {
    44  		t.Fatalf("process ran with err %v", err)
    45  	}
    46  	want := "echo:[]string{\"echothis\"}\n"
    47  	if string(out) != want {
    48  		t.Fatalf("wrong process output got `%s` want `%s`", out, want)
    49  	}
    50  }
    51  
    52  // TestBashWrapper tests that the "./testdata/bash_wrapper.sh" works as expected
    53  // bash_wrapper.sh is a script that replace the internal command echo with its
    54  // first argument and source its second argument.
    55  // The goal is to be able to run grub's tests scripts, see TestGrubTests
    56  func TestBashWrapper(t *testing.T) {
    57  	if !*update {
    58  		t.Skip("use -run-bash flag to run this")
    59  	}
    60  	cmd := exec.Command("./testdata/bash_wrapper.sh", os.Args[0], "./testdata/test_bash_wrapper.sh")
    61  	cmd.Env = append(os.Environ(), "BE_ECHO=1")
    62  	out, err := cmd.Output()
    63  	t.Logf("%q\n", out)
    64  	if err != nil {
    65  		t.Fatalf("process ran with err %v", err)
    66  	}
    67  	want := "echo:[]string{\"param1\", \"param2\"}\n"
    68  	if string(out) != want {
    69  		t.Fatalf("wrong process output got `%s` want `%s`", out, want)
    70  	}
    71  }
    72  
    73  // TestGrubTests run tests imported from grub source to check our parser
    74  // grub has tests in for of scripts that are run both by grub and bash, they
    75  // mostly use echo and the test then compare the output of both runs.
    76  // In our case we don't want to compare the output of echo, but get the token
    77  // passed to echo. So we replace the echo command in bash with the wrapper (see
    78  // above). We can then compare the bash output to our parser output.
    79  // Also to avoid keeping the dependency on bash, the output are saved in the
    80  // golden files. One must run the test with '-run-bash' to update the golden
    81  // files in case new tests are added or the echo format is changed.
    82  func TestGrubTests(t *testing.T) {
    83  	files, err := filepath.Glob("testdata/*.in")
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	for _, file := range files {
    88  		name := strings.TrimSuffix(filepath.Base(file), ".in")
    89  		t.Run(name, func(t *testing.T) {
    90  			golden := strings.TrimSuffix(file, ".in") + ".out"
    91  			var out []byte
    92  			if *update {
    93  				cmd := exec.Command("./testdata/bash_wrapper.sh", os.Args[0], file)
    94  				cmd.Env = append(os.Environ(), "BE_ECHO=1")
    95  				out, err = cmd.Output()
    96  				//t.Logf("%s\n", out)
    97  				if err != nil {
    98  					t.Fatalf("process ran with err %v", err)
    99  				}
   100  			} else {
   101  				out, err = ioutil.ReadFile(golden)
   102  				if err != nil {
   103  					t.Fatalf("error loading file `%s`, %v", golden, err)
   104  				}
   105  			}
   106  			// parse with our parser and compare
   107  			var b bytes.Buffer
   108  			wd := &url.URL{
   109  				Scheme: "file",
   110  				Path:   "./testdata",
   111  			}
   112  			c := newParser(wd, curl.DefaultSchemes)
   113  			c.W = &b
   114  
   115  			script, err := ioutil.ReadFile(file)
   116  			if err != nil {
   117  				t.Fatalf("error loading file `%s`, %v", file, err)
   118  			}
   119  			err = c.append(context.Background(), string(script))
   120  			if err != nil {
   121  				t.Fatalf("error parsing file `%s`, %v", file, err)
   122  			}
   123  
   124  			if b.String() != string(out) {
   125  				t.Fatalf("wrong script parsing output got `%s` want `%s`", b.String(), string(out))
   126  			}
   127  			// update/create golden file on success
   128  			if *update {
   129  				err := ioutil.WriteFile(golden, out, 0644)
   130  				if err != nil {
   131  					t.Fatalf("error writing file `%s`, %v", file, err)
   132  				}
   133  			}
   134  		})
   135  
   136  	}
   137  }