github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/spyglass/podlogartifact_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 spyglass 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "testing" 24 25 "k8s.io/test-infra/prow/kube" 26 "k8s.io/test-infra/prow/spyglass/lenses" 27 ) 28 29 // fakePodLogJAgent used for pod log artifact dependency injection 30 type fakePodLogJAgent struct { 31 } 32 33 func (j *fakePodLogJAgent) GetProwJob(job, id string) (kube.ProwJob, error) { 34 return kube.ProwJob{}, nil 35 } 36 37 func (j *fakePodLogJAgent) GetJobLog(job, id string) ([]byte, error) { 38 if job == "BFG" && id == "435" { 39 return []byte("frobscottle"), nil 40 } else if job == "Fantastic Mr. Fox" && id == "4" { 41 return []byte("a hundred smoked hams and fifty sides of bacon"), nil 42 } 43 return nil, fmt.Errorf("could not find job %s, id %s", job, id) 44 } 45 46 func (j *fakePodLogJAgent) GetJobLogTail(job, id string, n int64) ([]byte, error) { 47 log, err := j.GetJobLog(job, id) 48 if err != nil { 49 return nil, fmt.Errorf("error getting log tail: %v", err) 50 } 51 logLen := int64(len(log)) 52 if n > logLen { 53 return log, nil 54 } 55 return log[logLen-n:], nil 56 57 } 58 59 func TestNewPodLogArtifact(t *testing.T) { 60 testCases := []struct { 61 name string 62 jobName string 63 buildID string 64 sizeLimit int64 65 expectedErr error 66 expectedLink string 67 }{ 68 { 69 name: "Create pod log with valid fields", 70 jobName: "job", 71 buildID: "123", 72 sizeLimit: 500e6, 73 expectedErr: nil, 74 expectedLink: "/log?id=123&job=job", 75 }, 76 { 77 name: "Create pod log with no jobName", 78 jobName: "", 79 buildID: "123", 80 sizeLimit: 500e6, 81 expectedErr: errInsufficientJobInfo, 82 expectedLink: "", 83 }, 84 { 85 name: "Create pod log with no buildID", 86 jobName: "job", 87 buildID: "", 88 sizeLimit: 500e6, 89 expectedErr: errInsufficientJobInfo, 90 expectedLink: "", 91 }, 92 { 93 name: "Create pod log with negative sizeLimit", 94 jobName: "job", 95 buildID: "123", 96 sizeLimit: -4, 97 expectedErr: errInvalidSizeLimit, 98 expectedLink: "", 99 }, 100 } 101 for _, tc := range testCases { 102 t.Run(tc.name, func(t *testing.T) { 103 artifact, err := NewPodLogArtifact(tc.jobName, tc.buildID, tc.sizeLimit, &fakePodLogJAgent{}) 104 if err != nil { 105 if err != tc.expectedErr { 106 t.Fatalf("failed creating artifact. err: %v", err) 107 } 108 return 109 } 110 link := artifact.CanonicalLink() 111 if link != tc.expectedLink { 112 t.Errorf("Unexpected link, expected %s, got %q", tc.expectedLink, link) 113 } 114 }) 115 } 116 } 117 118 func TestReadTail_PodLog(t *testing.T) { 119 testCases := []struct { 120 name string 121 jobName string 122 buildID string 123 artifact *PodLogArtifact 124 n int64 125 expected []byte 126 expectErr bool 127 }{ 128 { 129 name: "Podlog ReadTail longer than contents", 130 jobName: "BFG", 131 buildID: "435", 132 n: 50, 133 expected: []byte("frobscottle"), 134 }, 135 { 136 name: "Podlog ReadTail shorter than contents", 137 jobName: "Fantastic Mr. Fox", 138 buildID: "4", 139 n: 3, 140 expected: []byte("con"), 141 }, 142 { 143 name: "Podlog ReadTail nonexistent pod", 144 jobName: "Fax", 145 buildID: "4", 146 n: 3, 147 expectErr: true, 148 }, 149 } 150 for _, tc := range testCases { 151 t.Run(tc.name, func(t *testing.T) { 152 artifact, err := NewPodLogArtifact(tc.jobName, tc.buildID, 500e6, &fakePodLogJAgent{}) 153 if err != nil { 154 t.Fatalf("Pod Log Tests failed to create pod log artifact, err %v", err) 155 } 156 res, err := artifact.ReadTail(tc.n) 157 if err != nil && !tc.expectErr { 158 t.Fatalf("failed reading bytes of log. did not expect err, got err: %v", err) 159 } 160 if err == nil && tc.expectErr { 161 t.Errorf("expected an error, got none") 162 } 163 if !bytes.Equal(tc.expected, res) { 164 t.Errorf("Unexpected result of reading pod logs, expected %q, got %q", tc.expected, res) 165 } 166 }) 167 } 168 169 } 170 func TestReadAt_PodLog(t *testing.T) { 171 testCases := []struct { 172 name string 173 jobName string 174 buildID string 175 n int64 176 offset int64 177 expectedErr error 178 expected []byte 179 }{ 180 { 181 name: "Podlog ReadAt range longer than contents", 182 n: 100, 183 jobName: "BFG", 184 buildID: "435", 185 offset: 3, 186 expectedErr: io.EOF, 187 expected: []byte("bscottle"), 188 }, 189 { 190 name: "Podlog ReadAt range within contents", 191 n: 4, 192 jobName: "Fantastic Mr. Fox", 193 buildID: "4", 194 offset: 2, 195 expectedErr: nil, 196 expected: []byte("hund"), 197 }, 198 } 199 for _, tc := range testCases { 200 t.Run(tc.name, func(t *testing.T) { 201 artifact, err := NewPodLogArtifact(tc.jobName, tc.buildID, 500e6, &fakePodLogJAgent{}) 202 if err != nil { 203 t.Fatalf("Pod Log Tests failed to create pod log artifact, err %v", err) 204 } 205 res := make([]byte, tc.n) 206 readBytes, err := artifact.ReadAt(res, tc.offset) 207 if err != tc.expectedErr { 208 t.Fatalf("failed reading bytes of log. err: %v, expected err: %v", err, tc.expectedErr) 209 } 210 if !bytes.Equal(tc.expected, res[:readBytes]) { 211 t.Errorf("Unexpected result of reading pod logs, expected %q, got %q", tc.expected, res) 212 } 213 }) 214 } 215 216 } 217 func TestReadAtMost_PodLog(t *testing.T) { 218 testCases := []struct { 219 name string 220 n int64 221 jobName string 222 buildID string 223 expectedErr error 224 expected []byte 225 }{ 226 { 227 name: "Podlog ReadAtMost longer than contents", 228 jobName: "BFG", 229 buildID: "435", 230 n: 100, 231 expectedErr: io.EOF, 232 expected: []byte("frobscottle"), 233 }, 234 { 235 name: "Podlog ReadAtMost shorter than contents", 236 n: 3, 237 jobName: "BFG", 238 buildID: "435", 239 expectedErr: nil, 240 expected: []byte("fro"), 241 }, 242 } 243 for _, tc := range testCases { 244 t.Run(tc.name, func(t *testing.T) { 245 artifact, err := NewPodLogArtifact(tc.jobName, tc.buildID, 500e6, &fakePodLogJAgent{}) 246 if err != nil { 247 t.Fatalf("Pod Log Tests failed to create pod log artifact, err %v", err) 248 } 249 res, err := artifact.ReadAtMost(tc.n) 250 if err != tc.expectedErr { 251 t.Fatalf("failed reading bytes of log. err: %v, expected err: %v", err, tc.expectedErr) 252 } 253 if !bytes.Equal(tc.expected, res) { 254 t.Errorf("Unexpected result of reading pod logs, expected %q, got %q", tc.expected, res) 255 } 256 }) 257 } 258 259 } 260 261 func TestReadAll_PodLog(t *testing.T) { 262 fakePodLogAgent := &fakePodLogJAgent{} 263 testCases := []struct { 264 name string 265 jobName string 266 buildID string 267 sizeLimit int64 268 expectedErr error 269 expected []byte 270 }{ 271 { 272 name: "Podlog readall not found", 273 jobName: "job", 274 buildID: "123", 275 sizeLimit: 500e6, 276 expectedErr: fmt.Errorf("error getting pod log size: error getting size of pod log: could not find job job, id 123"), 277 expected: nil, 278 }, 279 { 280 name: "Simple \"BFG\" Podlog readall", 281 jobName: "BFG", 282 buildID: "435", 283 sizeLimit: 500e6, 284 expectedErr: nil, 285 expected: []byte("frobscottle"), 286 }, 287 { 288 name: "\"Fantastic Mr. Fox\" Podlog readall", 289 jobName: "Fantastic Mr. Fox", 290 buildID: "4", 291 sizeLimit: 500e6, 292 expectedErr: nil, 293 expected: []byte("a hundred smoked hams and fifty sides of bacon"), 294 }, 295 { 296 name: "Podlog readall over size limit", 297 jobName: "Fantastic Mr. Fox", 298 buildID: "4", 299 sizeLimit: 5, 300 expectedErr: lenses.ErrFileTooLarge, 301 expected: nil, 302 }, 303 } 304 for _, tc := range testCases { 305 artifact, err := NewPodLogArtifact(tc.jobName, tc.buildID, tc.sizeLimit, fakePodLogAgent) 306 if err != nil { 307 t.Fatalf("Pod Log Tests failed to create pod log artifact, err %v", err) 308 } 309 res, err := artifact.ReadAll() 310 if err != nil && err.Error() != tc.expectedErr.Error() { 311 t.Fatalf("%s failed reading bytes of log. got err: %v, expected err: %v", tc.name, err, tc.expectedErr) 312 } 313 if err != nil { 314 continue 315 } 316 if !bytes.Equal(tc.expected, res) { 317 t.Errorf("Unexpected result of reading pod logs, expected %q, got %q", tc.expected, res) 318 } 319 320 } 321 322 }