github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/spyglass/lenses/lenses_test.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package lenses 18 19 import ( 20 "encoding/json" 21 "testing" 22 23 "github.com/sirupsen/logrus" 24 25 "sigs.k8s.io/prow/pkg/config" 26 "sigs.k8s.io/prow/pkg/spyglass/api" 27 "sigs.k8s.io/prow/pkg/spyglass/lenses/fake" 28 ) 29 30 type FakeArtifact = fake.Artifact 31 32 type dumpLens struct{} 33 34 func (dumpLens) Config() LensConfig { 35 return LensConfig{ 36 Name: "dump", 37 Title: "Dump Lens", 38 } 39 } 40 41 func (dumpLens) Header(artifacts []api.Artifact, resourceDir string, config json.RawMessage, spyglassConfig config.Spyglass) string { 42 return "" 43 } 44 45 func (dumpLens) Body(artifacts []api.Artifact, resourceDir string, data string, config json.RawMessage, spyglassConfig config.Spyglass) string { 46 var view []byte 47 for _, a := range artifacts { 48 data, err := a.ReadAll() 49 if err != nil { 50 logrus.WithError(err).Error("Error reading artifact") 51 continue 52 } 53 view = append(view, data...) 54 } 55 return string(view) 56 } 57 58 func (dumpLens) Callback(artifacts []api.Artifact, resourceDir string, data string, config json.RawMessage, spyglassConfig config.Spyglass) string { 59 return "" 60 } 61 62 // Tests getting a view from a viewer 63 func TestView(t *testing.T) { 64 err := RegisterLens(dumpLens{}) 65 if err != nil { 66 t.Fatal("Failed to register viewer for testing View") 67 } 68 fakeLog := &FakeArtifact{ 69 Path: "log.txt", 70 Content: []byte("Oh wow\nlogs\nthis is\ncrazy"), 71 } 72 testCases := []struct { 73 name string 74 lensName string 75 artifacts []api.Artifact 76 raw string 77 expected string 78 err error 79 }{ 80 { 81 name: "simple view", 82 lensName: "dump", 83 artifacts: []api.Artifact{ 84 fakeLog, fakeLog, 85 }, 86 raw: "", 87 expected: `Oh wow 88 logs 89 this is 90 crazyOh wow 91 logs 92 this is 93 crazy`, 94 err: nil, 95 }, 96 { 97 name: "fail on unregistered view name", 98 lensName: "MicroverseBattery", 99 artifacts: []api.Artifact{}, 100 raw: "", 101 expected: "", 102 err: ErrInvalidLensName, 103 }, 104 } 105 for _, tc := range testCases { 106 lens, err := GetLens(tc.lensName) 107 if tc.err != err { 108 t.Errorf("%s expected error %v but got error %v", tc.name, tc.err, err) 109 continue 110 } 111 if tc.err == nil && lens == nil { 112 t.Fatalf("Expected lens %s but got nil.", tc.lensName) 113 } 114 if lens != nil && lens.Body(tc.artifacts, "", tc.raw, nil, config.Spyglass{}) != tc.expected { 115 t.Errorf("%s expected view to be %s but got %s", tc.name, tc.expected, lens) 116 } 117 } 118 UnregisterLens("DumpView") 119 120 } 121 122 // Tests reading last N Lines from files in GCS 123 func TestLastNLines_GCS(t *testing.T) { 124 fakeGCSServerChunkSize := int64(3500) 125 var longLog string 126 for i := 0; i < 300; i++ { 127 longLog += "here a log\nthere a log\neverywhere a log log\n" 128 } 129 testCases := []struct { 130 name string 131 path string 132 contents []byte 133 n int64 134 a api.Artifact 135 expected []string 136 }{ 137 { 138 name: "Read last 2 lines of a 4-line file", 139 n: 2, 140 path: "log.txt", 141 contents: []byte("Oh wow\nlogs\nthis is\ncrazy"), 142 expected: []string{"this is", "crazy"}, 143 }, 144 { 145 name: "Read last 5 lines of a 4-line file", 146 n: 5, 147 path: "log.txt", 148 contents: []byte("Oh wow\nlogs\nthis is\ncrazy"), 149 expected: []string{"Oh wow", "logs", "this is", "crazy"}, 150 }, 151 { 152 name: "Read last 2 lines of a long log file", 153 n: 2, 154 path: "long-log.txt", 155 contents: []byte(longLog), 156 expected: []string{ 157 "there a log", 158 "everywhere a log log", 159 }, 160 }, 161 } 162 for _, tc := range testCases { 163 t.Run(tc.name, func(t *testing.T) { 164 artifact := &FakeArtifact{ 165 Path: tc.path, 166 Content: tc.contents, 167 } 168 actual, err := LastNLinesChunked(artifact, tc.n, fakeGCSServerChunkSize) 169 if err != nil { 170 t.Fatalf("failed with error: %v", err) 171 } 172 if len(actual) != len(tc.expected) { 173 t.Fatalf("Expected length:\n%d\nActual length:\n%d", len(tc.expected), len(actual)) 174 } 175 for ix, line := range tc.expected { 176 if line != actual[ix] { 177 t.Errorf("Line %d expected:\n%s\nActual line %d:\n%s", ix, line, ix, actual[ix]) 178 break 179 } 180 } 181 for ix, line := range actual { 182 if line != tc.expected[ix] { 183 t.Errorf("Line %d expected:\n%s\nActual line %d:\n%s", ix, tc.expected[ix], ix, line) 184 break 185 } 186 } 187 }) 188 } 189 }