github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/tot/main_test.go (about) 1 /* 2 Copyright 2016 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 main 18 19 import ( 20 "fmt" 21 "net/http" 22 "net/http/httptest" 23 "os" 24 "path" 25 "reflect" 26 "strings" 27 "testing" 28 29 "sigs.k8s.io/prow/pkg/config" 30 ) 31 32 func expectEqual(t *testing.T, msg string, have interface{}, want interface{}) { 33 if !reflect.DeepEqual(have, want) { 34 t.Errorf("bad %s: got %v, wanted %v", 35 msg, have, want) 36 } 37 } 38 39 func makeStore(t *testing.T) *store { 40 tmp, err := os.CreateTemp("", "tot_test_") 41 if err != nil { 42 t.Fatal(err) 43 } 44 os.Remove(tmp.Name()) // json decoding an empty file throws an error 45 46 store, err := newStore(tmp.Name()) 47 if err != nil { 48 t.Fatal(err) 49 } 50 51 return store 52 } 53 54 func TestVend(t *testing.T) { 55 store := makeStore(t) 56 defer os.Remove(store.storagePath) 57 58 expectEqual(t, "empty vend", store.vend("a"), 1) 59 expectEqual(t, "second vend", store.vend("a"), 2) 60 expectEqual(t, "third vend", store.vend("a"), 3) 61 expectEqual(t, "second empty", store.vend("b"), 1) 62 63 store2, err := newStore(store.storagePath) 64 if err != nil { 65 t.Fatal(err) 66 } 67 expectEqual(t, "fourth vend, different instance", store2.vend("a"), 4) 68 } 69 70 func TestSet(t *testing.T) { 71 store := makeStore(t) 72 defer os.Remove(store.storagePath) 73 74 store.set("foo", 300) 75 expectEqual(t, "peek", store.peek("foo"), 300) 76 store.set("foo2", 300) 77 expectEqual(t, "vend", store.vend("foo2"), 301) 78 expectEqual(t, "vend", store.vend("foo2"), 302) 79 } 80 81 func expectResponse(t *testing.T, handler http.Handler, req *http.Request, msg, value string) { 82 rr := httptest.NewRecorder() 83 84 handler.ServeHTTP(rr, req) 85 86 expectEqual(t, "http status OK", rr.Code, 200) 87 88 expectEqual(t, msg, rr.Body.String(), value) 89 } 90 91 func TestHandler(t *testing.T) { 92 store := makeStore(t) 93 defer os.Remove(store.storagePath) 94 95 handler := http.HandlerFunc(store.handle) 96 97 req, err := http.NewRequest("GET", "/vend/foo", nil) 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 expectResponse(t, handler, req, "http vend", "1") 103 expectResponse(t, handler, req, "http vend", "2") 104 105 req, err = http.NewRequest("HEAD", "/vend/foo", nil) 106 if err != nil { 107 t.Fatal(err) 108 } 109 110 expectResponse(t, handler, req, "http peek", "2") 111 112 req, err = http.NewRequest("POST", "/vend/bar", strings.NewReader("40")) 113 if err != nil { 114 t.Fatal(err) 115 } 116 117 expectResponse(t, handler, req, "http post", "") 118 119 req, err = http.NewRequest("HEAD", "/vend/bar", nil) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 expectResponse(t, handler, req, "http vend", "40") 125 } 126 127 type mapHandler map[string]string 128 129 func (h mapHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 130 fmt.Fprintf(w, "%s", h[r.URL.Path]) 131 } 132 133 func TestFallback(t *testing.T) { 134 serv := httptest.NewServer(mapHandler(map[string]string{ 135 "/logs/foo/latest-build.txt": "200", 136 "/logs/bar/latest-build.txt": "\t300 \n", 137 "/logs/baz/latest-build.txt": "asdf", 138 })) 139 defer serv.Close() 140 141 store := makeStore(t) 142 defer os.Remove(store.storagePath) 143 store.fallbackFunc = fallbackHandler{template: serv.URL + "/logs/%s/latest-build.txt"}.get 144 145 expectEqual(t, "vend foo 1", store.vend("foo"), 201) 146 expectEqual(t, "vend foo 2", store.vend("foo"), 202) 147 148 expectEqual(t, "vend bar", store.vend("bar"), 301) 149 expectEqual(t, "vend baz", store.vend("baz"), 1) 150 expectEqual(t, "vend quux", store.vend("quux"), 1) 151 } 152 153 func TestGetURL(t *testing.T) { 154 configs := map[string]string{ 155 "config.yaml": "", 156 "job-config.yaml": ` 157 periodics: 158 - name: periodics-foo 159 interval: 1m 160 spec: 161 containers: 162 - image: localhost:5001/alpine 163 presubmits: 164 some-org: 165 - name: presubmit-foo 166 spec: 167 containers: 168 - image: localhost:5001/alpine 169 postsubmits: 170 some-org: 171 - name: postsubmit-foo 172 spec: 173 containers: 174 - image: localhost:5001/alpine 175 `, 176 } 177 tmpDir := t.TempDir() 178 for fp, content := range configs { 179 if err := os.WriteFile(path.Join(tmpDir, fp), []byte(content), 0644); err != nil { 180 t.Fatal(err) 181 } 182 } 183 c, err := config.Load(path.Join(tmpDir, "config.yaml"), path.Join(tmpDir, "job-config.yaml"), nil, "") 184 if err != nil { 185 t.Fatalf("Could not load config: %v", err) 186 } 187 tests := []struct { 188 name string 189 190 jobName string 191 template string 192 c *config.Config 193 bucket string 194 195 expected string 196 }{ 197 { 198 name: "fallback template", 199 200 jobName: "pull-community-verify", 201 template: "https://storage.googleapis.com/kubernetes-jenkins/logs/%s/latest-build.txt", 202 203 expected: "https://storage.googleapis.com/kubernetes-jenkins/logs/pull-community-verify/latest-build.txt", 204 }, 205 { 206 name: "fallback bucket - presubmit", 207 208 jobName: "presubmit-foo", 209 c: c, 210 bucket: "https://storage.googleapis.com/kubernetes-jenkins", 211 212 expected: "https://storage.googleapis.com/kubernetes-jenkins/pr-logs/directory/presubmit-foo/latest-build.txt", 213 }, 214 { 215 name: "fallback bucket - postsubmit", 216 217 jobName: "postsubmit-foo", 218 c: c, 219 bucket: "https://storage.googleapis.com/kubernetes-jenkins", 220 221 expected: "https://storage.googleapis.com/kubernetes-jenkins/logs/postsubmit-foo/latest-build.txt", 222 }, 223 { 224 name: "fallback bucket - periodic", 225 226 jobName: "periodics-foo", 227 c: c, 228 bucket: "https://storage.googleapis.com/kubernetes-jenkins", 229 230 expected: "https://storage.googleapis.com/kubernetes-jenkins/logs/periodics-foo/latest-build.txt", 231 }, 232 { 233 name: "fallback bucket - unknown", 234 235 jobName: "a-name-that-is-what-it-is", 236 c: c, 237 bucket: "https://storage.googleapis.com/kubernetes-jenkins", 238 239 expected: "", 240 }, 241 { 242 name: "fallback bucket with trailing slash", 243 244 jobName: "presubmit-foo", 245 c: c, 246 bucket: "https://storage.googleapis.com/kubernetes-jenkins/", 247 248 expected: "https://storage.googleapis.com/kubernetes-jenkins/pr-logs/directory/presubmit-foo/latest-build.txt", 249 }, 250 } 251 252 for _, tc := range tests { 253 tc := tc 254 t.Run(tc.name, func(t *testing.T) { 255 t.Logf("running scenario %q", tc.name) 256 257 var configAgent *config.Agent 258 if tc.c != nil { 259 configAgent = new(config.Agent) 260 configAgent.Set(tc.c) 261 } 262 f := fallbackHandler{ 263 template: tc.template, 264 configAgent: configAgent, 265 bucket: tc.bucket, 266 } 267 268 if got := f.getURL(tc.jobName); got != tc.expected { 269 t.Errorf("unexpected URL:\n%s\nexpected:\n%s", got, tc.expected) 270 } 271 }) 272 } 273 }