k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/experiment/bumpmonitoring/main_test.go (about)

     1  /*
     2  Copyright 2021 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  	"os"
    21  	"path"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  )
    27  
    28  func TestFindConfigToUpdate(t *testing.T) {
    29  	tests := []struct {
    30  		name     string
    31  		desc     string
    32  		srcNodes []node
    33  		dstNodes []node
    34  		want     []string
    35  		wantErr  bool
    36  	}{
    37  		{
    38  			name: "base",
    39  			dstNodes: []node{
    40  				{Path: "mixins/grafana_dashboards/a.jsonnet"},
    41  				{Path: "mixins/prometheus/a.libsonnet"},
    42  			},
    43  			want: []string{
    44  				"mixins/grafana_dashboards/a.jsonnet",
    45  				"mixins/prometheus/a.libsonnet",
    46  			},
    47  			wantErr: false,
    48  		},
    49  		{
    50  			name: "multiple-files",
    51  			dstNodes: []node{
    52  				{Path: "mixins/grafana_dashboards/a.jsonnet"},
    53  				{Path: "mixins/grafana_dashboards/b.jsonnet"},
    54  			},
    55  			want: []string{
    56  				"mixins/grafana_dashboards/a.jsonnet",
    57  				"mixins/grafana_dashboards/b.jsonnet",
    58  			},
    59  			wantErr: false,
    60  		},
    61  		{
    62  			name: "wrong-extension",
    63  			dstNodes: []node{
    64  				{Path: "mixins/grafana_dashboards/a.somethingelse"},
    65  			},
    66  			wantErr: false,
    67  		},
    68  		{
    69  			name: "excluded-file",
    70  			dstNodes: []node{
    71  				{Path: "mixins/grafana_dashboards/prometheus.libsonnet"},
    72  			},
    73  			wantErr: false,
    74  		},
    75  		{
    76  			name: "empty",
    77  		},
    78  		{
    79  			name: "empty dir",
    80  			dstNodes: []node{
    81  				{Path: "mixins/grafana_dashboards", IsDir: true},
    82  			},
    83  			wantErr: false,
    84  		},
    85  	}
    86  
    87  	for _, tc := range tests {
    88  		t.Run(tc.name, func(t *testing.T) {
    89  			tmpDir := t.TempDir()
    90  			srcRootDir, dstRootDir := seedTempDir(t, tmpDir, tc.srcNodes, tc.dstNodes)
    91  			c := client{
    92  				srcPath: srcRootDir,
    93  				dstPath: dstRootDir,
    94  			}
    95  			if wantErr, gotErr := tc.wantErr, c.findConfigToUpdate(); (wantErr && (gotErr == nil)) || (!wantErr && (gotErr != nil)) {
    96  				t.Fatalf("Error mismatch. want: %v, got: %v", wantErr, gotErr)
    97  			}
    98  			if diff := cmp.Diff(tc.want, c.paths, cmpopts.SortSlices(func(a, b string) bool {
    99  				return a < b
   100  			})); diff != "" {
   101  				t.Fatalf("Config files mismatch. want(-), got(+):\n%s", diff)
   102  			}
   103  		})
   104  	}
   105  }
   106  
   107  func TestCopyFiles(t *testing.T) {
   108  	tests := []struct {
   109  		name     string
   110  		desc     string
   111  		srcNodes []node
   112  		dstNodes []node
   113  		paths    []string
   114  		want     []node
   115  		wantErr  bool
   116  	}{
   117  		{
   118  			name: "base",
   119  			srcNodes: []node{
   120  				{Path: "mixins/grafana_dashboards/a.jsonnet", Content: "123"},
   121  				{Path: "mixins/prometheus/a.libsonnet", Content: "123"},
   122  			},
   123  			dstNodes: []node{
   124  				{Path: "mixins/grafana_dashboards/a.jsonnet", Content: "456"},
   125  				{Path: "mixins/prometheus/a.libsonnet", Content: "456"},
   126  			},
   127  			paths: []string{
   128  				"mixins/grafana_dashboards/a.jsonnet",
   129  				"mixins/prometheus/a.libsonnet",
   130  			},
   131  			want: []node{
   132  				{Path: "mixins/grafana_dashboards/a.jsonnet", Content: "123"},
   133  				{Path: "mixins/prometheus/a.libsonnet", Content: "123"},
   134  			},
   135  			wantErr: false,
   136  		},
   137  		{
   138  			name: "not exist upstream",
   139  			srcNodes: []node{
   140  				{Path: "mixins/grafana_dashboards/b.jsonnet"},
   141  			},
   142  			dstNodes: []node{
   143  				{Path: "mixins/grafana_dashboards/a.jsonnet"},
   144  			},
   145  			paths: []string{
   146  				"mixins/grafana_dashboards/a.jsonnet",
   147  			},
   148  			want: []node{
   149  				{Path: "mixins/grafana_dashboards/a.jsonnet"},
   150  			},
   151  			wantErr: true,
   152  		},
   153  	}
   154  
   155  	for _, tc := range tests {
   156  		t.Run(tc.name, func(t *testing.T) {
   157  			tmpDir := t.TempDir()
   158  			srcRootDir, dstRootDir := seedTempDir(t, tmpDir, tc.srcNodes, tc.dstNodes)
   159  			c := client{
   160  				srcPath: srcRootDir,
   161  				dstPath: dstRootDir,
   162  				paths:   tc.paths,
   163  			}
   164  			if wantErr, gotErr := tc.wantErr, c.copyFiles(); (wantErr && (gotErr == nil)) || (!wantErr && (gotErr != nil)) {
   165  				t.Fatalf("Error mismatch. want: %v, got: %v", wantErr, gotErr)
   166  			}
   167  			var got []node
   168  			for _, p := range tc.paths {
   169  				got = append(got, pathToNode(t, dstRootDir, p))
   170  			}
   171  			if diff := cmp.Diff(tc.want, got, cmpopts.SortSlices(func(a, b string) bool {
   172  				return a < b
   173  			})); diff != "" {
   174  				t.Fatalf("Config files mismatch. want(-), got(+):\n%s", diff)
   175  			}
   176  		})
   177  	}
   178  }
   179  
   180  type node struct {
   181  	Path    string
   182  	Content string
   183  	IsDir   bool
   184  }
   185  
   186  func pathToNode(t *testing.T, root, p string) node {
   187  	n := node{Path: p}
   188  
   189  	p = path.Join(root, p)
   190  	info, err := os.Lstat(p)
   191  	if err != nil {
   192  		t.Fatalf("Failed stats %q: %v", p, err)
   193  	}
   194  	if info.IsDir() {
   195  		n.IsDir = true
   196  	} else {
   197  		bs, err := os.ReadFile(p)
   198  		if err != nil {
   199  			t.Fatalf("Failed to read %q: %v", p, err)
   200  		}
   201  		n.Content = string(bs)
   202  	}
   203  
   204  	return n
   205  }
   206  
   207  func seedTempDir(t *testing.T, root string, srcNodes, dstNodes []node) (string, string) {
   208  	srcRootDir := path.Join(root, "src")
   209  	dstRootDir := path.Join(root, "dst")
   210  
   211  	create := func(t *testing.T, root string, ns []node) {
   212  		for _, n := range ns {
   213  			p := path.Join(root, n.Path)
   214  			if n.IsDir {
   215  				if err := os.MkdirAll(p, 0755); err != nil {
   216  					t.Fatalf("Failed creating dir %q: %v", p, err)
   217  				}
   218  			} else {
   219  				dir := path.Dir(p)
   220  				if err := os.MkdirAll(dir, 0755); err != nil {
   221  					t.Fatalf("Failed creating dir %q: %v", dir, err)
   222  				}
   223  				if err := os.WriteFile(p, []byte(n.Content), 0777); err != nil {
   224  					t.Fatalf("Failed creating file %q: %v", p, err)
   225  				}
   226  			}
   227  		}
   228  	}
   229  
   230  	create(t, srcRootDir, srcNodes)
   231  	create(t, dstRootDir, dstNodes)
   232  
   233  	return srcRootDir, dstRootDir
   234  }