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