github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/test/cli/trait_assertions_test.go (about) 1 package cli 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "regexp" 8 "sort" 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 assertNoStderr(tb testing.TB, _, stderr string, _ int) { 87 tb.Helper() 88 if len(stderr) > 0 { 89 tb.Errorf("expected stderr to be empty, but got %q", stderr) 90 } 91 } 92 93 func assertInOutput(data string) traitAssertion { 94 return func(tb testing.TB, stdout, stderr string, _ int) { 95 tb.Helper() 96 stdout = stripansi.Strip(stdout) 97 stderr = stripansi.Strip(stderr) 98 if !strings.Contains(stdout, data) && !strings.Contains(stderr, data) { 99 tb.Errorf("data=%q was NOT found in any output, but should have been there\nSTDOUT:%s\nSTDERR:%s", data, stdout, stderr) 100 } 101 } 102 } 103 104 func assertStdoutLengthGreaterThan(length uint) traitAssertion { 105 return func(tb testing.TB, stdout, _ string, _ int) { 106 tb.Helper() 107 if uint(len(stdout)) < length { 108 tb.Errorf("not enough output (expected at least %d, got %d)", length, len(stdout)) 109 } 110 } 111 } 112 113 func assertPackageCount(length uint) traitAssertion { 114 return func(tb testing.TB, stdout, _ string, _ int) { 115 tb.Helper() 116 type NameAndVersion struct { 117 Name string `json:"name"` 118 Version string `json:"version"` 119 } 120 type partial struct { 121 Artifacts []NameAndVersion `json:"artifacts"` 122 } 123 var data partial 124 125 if err := json.Unmarshal([]byte(stdout), &data); err != nil { 126 tb.Errorf("expected to find a JSON report, but was unmarshalable: %+v", err) 127 } 128 129 if uint(len(data.Artifacts)) != length { 130 tb.Errorf("expected package count of %d, but found %d", length, len(data.Artifacts)) 131 debugArtifacts := make([]string, len(data.Artifacts)) 132 for i, a := range data.Artifacts { 133 debugArtifacts[i] = fmt.Sprintf("%s:%s", a.Name, a.Version) 134 } 135 sort.Strings(debugArtifacts) 136 for i, a := range debugArtifacts { 137 tb.Errorf("package %d: %s", i+1, a) 138 } 139 140 } 141 } 142 } 143 144 func assertFailingReturnCode(tb testing.TB, _, _ string, rc int) { 145 tb.Helper() 146 if rc == 0 { 147 tb.Errorf("expected a failure but got rc=%d", rc) 148 } 149 } 150 151 func assertSuccessfulReturnCode(tb testing.TB, _, _ string, rc int) { 152 tb.Helper() 153 if rc != 0 { 154 tb.Errorf("expected no failure but got rc=%d", rc) 155 } 156 } 157 158 func assertFileExists(file string) traitAssertion { 159 return func(tb testing.TB, _, _ string, _ int) { 160 tb.Helper() 161 if _, err := os.Stat(file); err != nil { 162 tb.Errorf("expected file to exist %s", file) 163 } 164 } 165 }