github.com/metasources/buildx@v0.0.0-20230418141019-7aa1459cedea/test/cli/trait_assertions_test.go (about)

     1  package cli
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"regexp"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/acarl005/stripansi"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  type traitAssertion func(tb testing.TB, stdout, stderr string, rc int)
    17  
    18  func assertFileOutput(tb testing.TB, path string, assertions ...traitAssertion) traitAssertion {
    19  	tb.Helper()
    20  
    21  	return func(tb testing.TB, _, stderr string, rc int) {
    22  		content, err := os.ReadFile(path)
    23  		require.NoError(tb, err)
    24  		contentStr := string(content)
    25  
    26  		for _, assertion := range assertions {
    27  			// treat the file content as stdout
    28  			assertion(tb, contentStr, stderr, rc)
    29  		}
    30  	}
    31  }
    32  
    33  func assertJsonReport(tb testing.TB, stdout, _ string, _ int) {
    34  	tb.Helper()
    35  	var data interface{}
    36  
    37  	if err := json.Unmarshal([]byte(stdout), &data); err != nil {
    38  		tb.Errorf("expected to find a JSON report, but was unmarshalable: %+v", err)
    39  	}
    40  }
    41  
    42  func assertTableReport(tb testing.TB, stdout, _ string, _ int) {
    43  	tb.Helper()
    44  	if !strings.Contains(stdout, "NAME") || !strings.Contains(stdout, "VERSION") || !strings.Contains(stdout, "TYPE") {
    45  		tb.Errorf("expected to find a table report, but did not")
    46  	}
    47  }
    48  
    49  //func assertScope(scope source.Scope) traitAssertion {
    50  //	return func(tb testing.TB, stdout, stderr string, rc int) {
    51  //		tb.Helper()
    52  //		// we can only verify source with the json report
    53  //		assertJsonReport(tb, stdout, stderr, rc)
    54  //
    55  //		if !strings.Contains(stdout, fmt.Sprintf(`"scope": "%s"`, scope.String())) {
    56  //			tb.Errorf("JSON report did not indicate the %q scope", scope)
    57  //		}
    58  //	}
    59  //}
    60  
    61  func assertLoggingLevel(level string) traitAssertion {
    62  	// match examples:
    63  	//  "[0000]  INFO"
    64  	//  "[0012] DEBUG"
    65  	logPattern := regexp.MustCompile(`(?m)^\[\d\d\d\d\]\s+` + strings.ToUpper(level))
    66  	return func(tb testing.TB, _, stderr string, _ int) {
    67  		tb.Helper()
    68  		if !logPattern.MatchString(stripansi.Strip(stderr)) {
    69  			tb.Errorf("output did not indicate the %q logging level", level)
    70  		}
    71  	}
    72  }
    73  
    74  func assertNotInOutput(data string) traitAssertion {
    75  	return func(tb testing.TB, stdout, stderr string, _ int) {
    76  		tb.Helper()
    77  		if strings.Contains(stripansi.Strip(stderr), data) {
    78  			tb.Errorf("data=%q was found in stderr, but should not have been there", data)
    79  		}
    80  		if strings.Contains(stripansi.Strip(stdout), data) {
    81  			tb.Errorf("data=%q was found in stdout, but should not have been there", data)
    82  		}
    83  	}
    84  }
    85  
    86  func assertInOutput(data string) traitAssertion {
    87  	return func(tb testing.TB, stdout, stderr string, _ int) {
    88  		tb.Helper()
    89  		if !strings.Contains(stripansi.Strip(stderr), data) && !strings.Contains(stripansi.Strip(stdout), data) {
    90  			tb.Errorf("data=%q was NOT found in any output, but should have been there", data)
    91  		}
    92  	}
    93  }
    94  
    95  func assertStdoutLengthGreaterThan(length uint) traitAssertion {
    96  	return func(tb testing.TB, stdout, _ string, _ int) {
    97  		tb.Helper()
    98  		if uint(len(stdout)) < length {
    99  			tb.Errorf("not enough output (expected at least %d, got %d)", length, len(stdout))
   100  		}
   101  	}
   102  }
   103  
   104  func assertPackageCount(length uint) traitAssertion {
   105  	return func(tb testing.TB, stdout, _ string, _ int) {
   106  		tb.Helper()
   107  		type partial struct {
   108  			Artifacts []interface{} `json:"artifacts"`
   109  		}
   110  		var data partial
   111  
   112  		if err := json.Unmarshal([]byte(stdout), &data); err != nil {
   113  			tb.Errorf("expected to find a JSON report, but was unmarshalable: %+v", err)
   114  		}
   115  
   116  		if uint(len(data.Artifacts)) != length {
   117  			tb.Errorf("expected package count of %d, but found %d", length, len(data.Artifacts))
   118  
   119  		}
   120  	}
   121  }
   122  
   123  func assertFailingReturnCode(tb testing.TB, _, _ string, rc int) {
   124  	tb.Helper()
   125  	if rc == 0 {
   126  		tb.Errorf("expected a failure but got rc=%d", rc)
   127  	}
   128  }
   129  
   130  func assertSuccessfulReturnCode(tb testing.TB, _, _ string, rc int) {
   131  	tb.Helper()
   132  	if rc != 0 {
   133  		tb.Errorf("expected no failure but got rc=%d", rc)
   134  	}
   135  }
   136  
   137  func assertVerifyAttestation(coverageImage string) traitAssertion {
   138  	return func(tb testing.TB, stdout, _ string, _ int) {
   139  		tb.Helper()
   140  		cosignPath := filepath.Join(repoRoot(tb), ".tmp/cosign")
   141  		err := os.WriteFile("attestation.json", []byte(stdout), 0664)
   142  		if err != nil {
   143  			tb.Errorf("could not write attestation to disk")
   144  		}
   145  		defer os.Remove("attestation.json")
   146  		attachCmd := exec.Command(
   147  			cosignPath,
   148  			"attach",
   149  			"attestation",
   150  			"--attestation",
   151  			"attestation.json",
   152  			coverageImage, // TODO which remote image to use?
   153  		)
   154  
   155  		stdout, stderr, _ := runCommand(attachCmd, nil)
   156  		if attachCmd.ProcessState.ExitCode() != 0 {
   157  			tb.Log("STDOUT", stdout)
   158  			tb.Log("STDERR", stderr)
   159  			tb.Fatalf("could not attach image")
   160  		}
   161  
   162  		verifyCmd := exec.Command(
   163  			cosignPath,
   164  			"verify-attestation",
   165  			coverageImage, // TODO which remote image to use?
   166  		)
   167  
   168  		stdout, stderr, _ = runCommand(verifyCmd, nil)
   169  		if attachCmd.ProcessState.ExitCode() != 0 {
   170  			tb.Log("STDOUT", stdout)
   171  			tb.Log("STDERR", stderr)
   172  			tb.Fatalf("could not verify attestation")
   173  		}
   174  	}
   175  }
   176  
   177  func assertFileExists(file string) traitAssertion {
   178  	return func(tb testing.TB, _, _ string, _ int) {
   179  		tb.Helper()
   180  		if _, err := os.Stat(file); err != nil {
   181  			tb.Errorf("expected file to exist %s", file)
   182  		}
   183  	}
   184  }