github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/spyglass/lenses/lenses_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 lenses
    18  
    19  import (
    20  	"encoding/json"
    21  	"testing"
    22  
    23  	"github.com/sirupsen/logrus"
    24  
    25  	"sigs.k8s.io/prow/pkg/config"
    26  	"sigs.k8s.io/prow/pkg/spyglass/api"
    27  	"sigs.k8s.io/prow/pkg/spyglass/lenses/fake"
    28  )
    29  
    30  type FakeArtifact = fake.Artifact
    31  
    32  type dumpLens struct{}
    33  
    34  func (dumpLens) Config() LensConfig {
    35  	return LensConfig{
    36  		Name:  "dump",
    37  		Title: "Dump Lens",
    38  	}
    39  }
    40  
    41  func (dumpLens) Header(artifacts []api.Artifact, resourceDir string, config json.RawMessage, spyglassConfig config.Spyglass) string {
    42  	return ""
    43  }
    44  
    45  func (dumpLens) Body(artifacts []api.Artifact, resourceDir string, data string, config json.RawMessage, spyglassConfig config.Spyglass) string {
    46  	var view []byte
    47  	for _, a := range artifacts {
    48  		data, err := a.ReadAll()
    49  		if err != nil {
    50  			logrus.WithError(err).Error("Error reading artifact")
    51  			continue
    52  		}
    53  		view = append(view, data...)
    54  	}
    55  	return string(view)
    56  }
    57  
    58  func (dumpLens) Callback(artifacts []api.Artifact, resourceDir string, data string, config json.RawMessage, spyglassConfig config.Spyglass) string {
    59  	return ""
    60  }
    61  
    62  // Tests getting a view from a viewer
    63  func TestView(t *testing.T) {
    64  	err := RegisterLens(dumpLens{})
    65  	if err != nil {
    66  		t.Fatal("Failed to register viewer for testing View")
    67  	}
    68  	fakeLog := &FakeArtifact{
    69  		Path:    "log.txt",
    70  		Content: []byte("Oh wow\nlogs\nthis is\ncrazy"),
    71  	}
    72  	testCases := []struct {
    73  		name      string
    74  		lensName  string
    75  		artifacts []api.Artifact
    76  		raw       string
    77  		expected  string
    78  		err       error
    79  	}{
    80  		{
    81  			name:     "simple view",
    82  			lensName: "dump",
    83  			artifacts: []api.Artifact{
    84  				fakeLog, fakeLog,
    85  			},
    86  			raw: "",
    87  			expected: `Oh wow
    88  logs
    89  this is
    90  crazyOh wow
    91  logs
    92  this is
    93  crazy`,
    94  			err: nil,
    95  		},
    96  		{
    97  			name:      "fail on unregistered view name",
    98  			lensName:  "MicroverseBattery",
    99  			artifacts: []api.Artifact{},
   100  			raw:       "",
   101  			expected:  "",
   102  			err:       ErrInvalidLensName,
   103  		},
   104  	}
   105  	for _, tc := range testCases {
   106  		lens, err := GetLens(tc.lensName)
   107  		if tc.err != err {
   108  			t.Errorf("%s expected error %v but got error %v", tc.name, tc.err, err)
   109  			continue
   110  		}
   111  		if tc.err == nil && lens == nil {
   112  			t.Fatalf("Expected lens %s but got nil.", tc.lensName)
   113  		}
   114  		if lens != nil && lens.Body(tc.artifacts, "", tc.raw, nil, config.Spyglass{}) != tc.expected {
   115  			t.Errorf("%s expected view to be %s but got %s", tc.name, tc.expected, lens)
   116  		}
   117  	}
   118  	UnregisterLens("DumpView")
   119  
   120  }
   121  
   122  // Tests reading last N Lines from files in GCS
   123  func TestLastNLines_GCS(t *testing.T) {
   124  	fakeGCSServerChunkSize := int64(3500)
   125  	var longLog string
   126  	for i := 0; i < 300; i++ {
   127  		longLog += "here a log\nthere a log\neverywhere a log log\n"
   128  	}
   129  	testCases := []struct {
   130  		name     string
   131  		path     string
   132  		contents []byte
   133  		n        int64
   134  		a        api.Artifact
   135  		expected []string
   136  	}{
   137  		{
   138  			name:     "Read last 2 lines of a 4-line file",
   139  			n:        2,
   140  			path:     "log.txt",
   141  			contents: []byte("Oh wow\nlogs\nthis is\ncrazy"),
   142  			expected: []string{"this is", "crazy"},
   143  		},
   144  		{
   145  			name:     "Read last 5 lines of a 4-line file",
   146  			n:        5,
   147  			path:     "log.txt",
   148  			contents: []byte("Oh wow\nlogs\nthis is\ncrazy"),
   149  			expected: []string{"Oh wow", "logs", "this is", "crazy"},
   150  		},
   151  		{
   152  			name:     "Read last 2 lines of a long log file",
   153  			n:        2,
   154  			path:     "long-log.txt",
   155  			contents: []byte(longLog),
   156  			expected: []string{
   157  				"there a log",
   158  				"everywhere a log log",
   159  			},
   160  		},
   161  	}
   162  	for _, tc := range testCases {
   163  		t.Run(tc.name, func(t *testing.T) {
   164  			artifact := &FakeArtifact{
   165  				Path:    tc.path,
   166  				Content: tc.contents,
   167  			}
   168  			actual, err := LastNLinesChunked(artifact, tc.n, fakeGCSServerChunkSize)
   169  			if err != nil {
   170  				t.Fatalf("failed with error: %v", err)
   171  			}
   172  			if len(actual) != len(tc.expected) {
   173  				t.Fatalf("Expected length:\n%d\nActual length:\n%d", len(tc.expected), len(actual))
   174  			}
   175  			for ix, line := range tc.expected {
   176  				if line != actual[ix] {
   177  					t.Errorf("Line %d expected:\n%s\nActual line %d:\n%s", ix, line, ix, actual[ix])
   178  					break
   179  				}
   180  			}
   181  			for ix, line := range actual {
   182  				if line != tc.expected[ix] {
   183  					t.Errorf("Line %d expected:\n%s\nActual line %d:\n%s", ix, tc.expected[ix], ix, line)
   184  					break
   185  				}
   186  			}
   187  		})
   188  	}
   189  }