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  }