k8s.io/test-infra/triage@v0.0.0-20240520184403-27c6b4c223d8/summarize/cluster_test.go (about)

     1  /*
     2  Copyright 2020 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 summarize
    18  
    19  import (
    20  	"os"
    21  	"strings"
    22  	"testing"
    23  )
    24  
    25  func TestClusterTest(t *testing.T) {
    26  	type testCase struct {
    27  		name      string
    28  		arguments []failure
    29  		want      failuresGroup
    30  	}
    31  	testCases := make([]testCase, 0, 3)
    32  
    33  	// Make sure small strings aren't equal, even with tiny differences
    34  	f1 := failure{FailureText: "exit 1"}
    35  	f2 := failure{FailureText: "exit 2"}
    36  	testCases = append(testCases, testCase{
    37  		"Small strings, slight difference",
    38  		[]failure{f1, f2},
    39  		failuresGroup{
    40  			f1.FailureText: []failure{
    41  				f1,
    42  			},
    43  			f2.FailureText: []failure{
    44  				f2,
    45  			},
    46  		},
    47  	})
    48  
    49  	// Longer strings with tiny differences should be equal, however
    50  	f3 := failure{FailureText: "long message immediately preceding exit code 1"}
    51  	f4 := failure{FailureText: "long message immediately preceding exit code 2"}
    52  	testCases = append(testCases, testCase{
    53  		"Long strings, slight diference",
    54  		[]failure{f3, f4},
    55  		failuresGroup{
    56  			f3.FailureText: []failure{
    57  				f3,
    58  				f4,
    59  			},
    60  		},
    61  	})
    62  
    63  	// Generate some very long strings
    64  	var builder strings.Builder
    65  	builder.Grow(4 * 399) // Allocate enough memory (4 characters in "1 2 ")
    66  	for i := 0; i < 399; i++ {
    67  		builder.WriteString("1 2 ")
    68  	}
    69  	generatedString := builder.String()
    70  
    71  	// Test these new failures together with f1
    72  	f5 := failure{FailureText: generatedString + "1 2 "}
    73  	f6 := failure{FailureText: generatedString + "3 4 "}
    74  	testCases = append(testCases, testCase{
    75  		"Huge strings, slight diference",
    76  		[]failure{f1, f5, f6},
    77  		failuresGroup{
    78  			f1.FailureText: []failure{
    79  				f1,
    80  			},
    81  			f5.FailureText: []failure{
    82  				f5,
    83  				f6,
    84  			},
    85  		},
    86  	})
    87  
    88  	// Run the tests
    89  	for _, tc := range testCases {
    90  		t.Run(tc.name, func(t *testing.T) {
    91  			got := clusterTest(tc.arguments, defaultMaxClusterTextLength)
    92  
    93  			if !tc.want.equal(&got) {
    94  				t.Errorf("clusterTest(%#v) = %#v, wanted %#v", tc.arguments, got, tc.want)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func TestClusterGlobal(t *testing.T) {
   101  	t.Run("Normal", func(t *testing.T) {
   102  		f1 := failure{FailureText: "exit 1"}
   103  		f2 := failure{FailureText: "exit 1"}
   104  		f3 := failure{FailureText: "exit 1"}
   105  
   106  		argument := nestedFailuresGroups{
   107  			"test a": failuresGroup{
   108  				"exit 1": []failure{f1, f2},
   109  			},
   110  			"test b": failuresGroup{
   111  				"exit 1": []failure{f3},
   112  			},
   113  		}
   114  
   115  		want := nestedFailuresGroups{
   116  			"exit 1": failuresGroup{
   117  				"test a": []failure{f1, f2},
   118  				"test b": []failure{f3},
   119  			},
   120  		}
   121  
   122  		got := clusterGlobal(argument, nil, false, defaultMaxClusterTextLength)
   123  
   124  		if !want.equal(&got) {
   125  			t.Errorf("clusterGlobal(%#v) = %#v, wanted %#v", argument, got, want)
   126  		}
   127  	})
   128  
   129  	// Make sure clusters are stable when provided with previous seeds
   130  	t.Run("With previous seed", func(t *testing.T) {
   131  		// Remove any memoization files after the test is done so as not to taint future tests
   132  		defer os.Remove("memo_cluster_global.json")
   133  
   134  		textOld := "some long failure message that changes occasionally foo"
   135  		textNew := strings.Replace(textOld, "foo", "bar", -1)
   136  
   137  		f1 := failure{FailureText: textNew}
   138  
   139  		argument := nestedFailuresGroups{"test a": failuresGroup{textNew: []failure{f1}}}
   140  		previous := []jsonCluster{{Key: textOld}}
   141  
   142  		want := nestedFailuresGroups{textOld: failuresGroup{"test a": []failure{f1}}}
   143  
   144  		got := clusterGlobal(argument, previous, true, defaultMaxClusterTextLength)
   145  
   146  		if !want.equal(&got) {
   147  			t.Errorf("clusterGlobal(%#v, %#v) = %#v, wanted %#v", argument, previous, got, want)
   148  		}
   149  	})
   150  }