github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/kubernetes/logger/formatter_test.go (about) 1 /* 2 Copyright 2021 The Skaffold 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 logger 18 19 import ( 20 "bytes" 21 "strings" 22 "sync" 23 "testing" 24 25 v1 "k8s.io/api/core/v1" 26 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 29 "github.com/GoogleContainerTools/skaffold/testutil" 30 ) 31 32 type mockColorPicker struct{} 33 34 func (m *mockColorPicker) Pick(image string) output.Color { 35 return output.Default 36 } 37 38 func (m *mockColorPicker) AddImage(string) {} 39 40 type mockConfig struct { 41 log latest.LogsConfig 42 } 43 44 func (c *mockConfig) Tail() bool { 45 return true 46 } 47 48 func (c *mockConfig) PipelineForImage(string) (latest.Pipeline, bool) { 49 var pipeline latest.Pipeline 50 pipeline.Deploy.Logs = c.log 51 return pipeline, true 52 } 53 54 func (c *mockConfig) DefaultPipeline() latest.Pipeline { 55 var pipeline latest.Pipeline 56 pipeline.Deploy.Logs = c.log 57 return pipeline 58 } 59 60 func (c *mockConfig) JSONParseConfig() latest.JSONParseConfig { 61 return c.log.JSONParse 62 } 63 64 func TestPrintLogLine(t *testing.T) { 65 testutil.Run(t, "verify lines are not intermixed", func(t *testutil.T) { 66 var ( 67 buf bytes.Buffer 68 wg sync.WaitGroup 69 70 linesPerGroup = 100 71 groups = 5 72 ) 73 74 f := newKubernetesLogFormatter(&mockConfig{log: latest.LogsConfig{Prefix: "none"}}, &mockColorPicker{}, func() bool { return false }, &v1.Pod{}, v1.ContainerStatus{}) 75 76 for i := 0; i < groups; i++ { 77 wg.Add(1) 78 79 go func() { 80 for i := 0; i < linesPerGroup; i++ { 81 f.PrintLine(&buf, "TEXT\n") 82 } 83 wg.Done() 84 }() 85 } 86 wg.Wait() 87 88 lines := strings.Split(buf.String(), "\n") 89 for i := 0; i < groups*linesPerGroup; i++ { 90 t.CheckDeepEqual("TEXT", lines[i]) 91 } 92 }) 93 } 94 95 func TestColorForPod(t *testing.T) { 96 tests := []struct { 97 description string 98 pod *v1.Pod 99 expectedColor output.Color 100 }{ 101 { 102 description: "not found", 103 pod: &v1.Pod{}, 104 expectedColor: output.None, 105 }, 106 { 107 description: "found", 108 pod: &v1.Pod{ 109 Spec: v1.PodSpec{ 110 Containers: []v1.Container{ 111 {Image: "image"}, 112 }, 113 }, 114 }, 115 expectedColor: output.DefaultColorCodes[0], 116 }, 117 { 118 description: "ignore tag", 119 pod: &v1.Pod{ 120 Spec: v1.PodSpec{ 121 Containers: []v1.Container{ 122 {Image: "image:tag"}, 123 }, 124 }, 125 }, 126 expectedColor: output.DefaultColorCodes[0], 127 }, 128 { 129 description: "second image", 130 pod: &v1.Pod{ 131 Spec: v1.PodSpec{ 132 Containers: []v1.Container{ 133 {Image: "second:tag"}, 134 }, 135 }, 136 }, 137 expectedColor: output.DefaultColorCodes[1], 138 }, 139 { 140 description: "accept image with digest", 141 pod: &v1.Pod{ 142 Spec: v1.PodSpec{ 143 Containers: []v1.Container{ 144 {Image: "second:tag@sha256:d3f4dd1541ee34b96850efc46955bada1a415b0594dc9948607c0197d2d16749"}, 145 }, 146 }, 147 }, 148 expectedColor: output.DefaultColorCodes[1], 149 }, 150 } 151 152 // artifacts are registered using their tag, since these have default repo substitutions applied 153 p := output.NewColorPicker() 154 p.AddImage("image") 155 p.AddImage("second") 156 157 for _, test := range tests { 158 f := newKubernetesLogFormatter(&mockConfig{log: latest.LogsConfig{Prefix: "none"}}, p, func() bool { return false }, test.pod, v1.ContainerStatus{}) 159 160 testutil.Run(t, test.description, func(t *testutil.T) { 161 color := f.color() 162 163 t.CheckTrue(test.expectedColor == color) 164 }) 165 } 166 } 167 168 func TestPrefix(t *testing.T) { 169 tests := []struct { 170 description string 171 prefix string 172 pod v1.Pod 173 container v1.ContainerStatus 174 expectedPrefix string 175 }{ 176 { 177 description: "auto (different names)", 178 prefix: "auto", 179 pod: podWithName("pod"), 180 container: containerWithName("container"), 181 expectedPrefix: "[pod container]", 182 }, 183 { 184 description: "auto (same names)", 185 prefix: "auto", 186 pod: podWithName("hello"), 187 container: containerWithName("hello"), 188 expectedPrefix: "[hello]", 189 }, 190 { 191 description: "container", 192 prefix: "container", 193 pod: podWithName("pod"), 194 container: containerWithName("container"), 195 expectedPrefix: "[container]", 196 }, 197 { 198 description: "podAndContainer (different names)", 199 prefix: "podAndContainer", 200 pod: podWithName("pod"), 201 container: containerWithName("container"), 202 expectedPrefix: "[pod container]", 203 }, 204 { 205 description: "podAndContainer (same names)", 206 prefix: "podAndContainer", 207 pod: podWithName("hello"), 208 container: containerWithName("hello"), 209 expectedPrefix: "[hello hello]", 210 }, 211 { 212 description: "none", 213 prefix: "none", 214 pod: podWithName("hello"), 215 container: containerWithName("hello"), 216 expectedPrefix: "", 217 }, 218 } 219 for _, test := range tests { 220 testutil.Run(t, test.description, func(t *testutil.T) { 221 f := newKubernetesLogFormatter(&mockConfig{log: latest.LogsConfig{ 222 Prefix: test.prefix, 223 }}, &mockColorPicker{}, func() bool { return false }, &test.pod, test.container) 224 225 t.CheckDeepEqual(test.expectedPrefix, f.prefix) 226 }) 227 } 228 } 229 230 func TestPrintline(t *testing.T) { 231 tests := []struct { 232 description string 233 isMuted bool 234 expected string 235 }{ 236 { 237 description: "muted", 238 isMuted: true, 239 }, 240 { 241 description: "unmuted", 242 expected: "[hello container]test line", 243 }, 244 } 245 for _, test := range tests { 246 testutil.Run(t, test.description, func(t *testutil.T) { 247 pod := podWithName("hello") 248 f := newKubernetesLogFormatter(&mockConfig{log: latest.LogsConfig{ 249 Prefix: "auto", 250 }}, &mockColorPicker{}, func() bool { return test.isMuted }, &pod, 251 containerWithName("container")) 252 var out bytes.Buffer 253 f.PrintLine(&out, "test line") 254 t.CheckDeepEqual(test.expected, out.String()) 255 }) 256 } 257 }