github.com/khulnasoft/codebase@v0.0.0-20231214144635-a707781cbb24/project/run_test.go (about) 1 package project 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "os" 8 "strings" 9 "testing" 10 11 "github.com/khulnasoft/codebase" 12 "github.com/khulnasoft/codebase/filter" 13 ) 14 15 type fakeDiffService struct { 16 codebase.DiffService 17 FakeDiff func() ([]byte, error) 18 } 19 20 func (f *fakeDiffService) Diff(_ context.Context) ([]byte, error) { 21 return f.FakeDiff() 22 } 23 24 func (f *fakeDiffService) Strip() int { 25 return 0 26 } 27 28 type fakeCommentService struct { 29 codebase.CommentService 30 FakePost func(*codebase.Comment) error 31 } 32 33 func (f *fakeCommentService) Post(_ context.Context, c *codebase.Comment) error { 34 return f.FakePost(c) 35 } 36 37 func TestRun(t *testing.T) { 38 ctx := context.Background() 39 40 t.Run("empty", func(t *testing.T) { 41 conf := &Config{} 42 if err := Run(ctx, conf, nil, nil, nil, false, filter.ModeAdded, false); err != nil { 43 t.Error(err) 44 } 45 }) 46 47 t.Run("errorformat error", func(t *testing.T) { 48 conf := &Config{ 49 Runner: map[string]*Runner{ 50 "test": {}, 51 }, 52 } 53 if err := Run(ctx, conf, nil, nil, nil, false, filter.ModeAdded, false); err == nil { 54 t.Error("want error, got nil") 55 } else { 56 t.Log(err) 57 } 58 }) 59 60 t.Run("diff error", func(t *testing.T) { 61 ds := &fakeDiffService{ 62 FakeDiff: func() ([]byte, error) { 63 return nil, errors.New("err!") 64 }, 65 } 66 conf := &Config{ 67 Runner: map[string]*Runner{ 68 "test": { 69 Cmd: "echo 'hi'", 70 Errorformat: []string{`%f:%l:%c:%m`}, 71 }, 72 }, 73 } 74 if err := Run(ctx, conf, nil, nil, ds, false, filter.ModeAdded, false); err == nil { 75 t.Error("want error, got nil") 76 } else { 77 t.Log(err) 78 } 79 }) 80 81 t.Run("cmd error with findings (not for codebase to exit with error)", func(t *testing.T) { 82 buf := new(bytes.Buffer) 83 defaultTeeStderr = buf 84 ds := &fakeDiffService{ 85 FakeDiff: func() ([]byte, error) { 86 return []byte(""), nil 87 }, 88 } 89 cs := &fakeCommentService{ 90 FakePost: func(c *codebase.Comment) error { 91 return nil 92 }, 93 } 94 conf := &Config{ 95 Runner: map[string]*Runner{ 96 "test": { 97 Cmd: "echo 'file:14:14:message'; exit 1", 98 Errorformat: []string{`%f:%l:%c:%m`}, 99 }, 100 }, 101 } 102 if err := Run(ctx, conf, nil, cs, ds, false, filter.ModeAdded, false); err != nil { 103 t.Error(err) 104 } 105 want := "" 106 if got := buf.String(); got != want { 107 t.Errorf("got stderr %q, want %q", got, want) 108 } 109 }) 110 111 t.Run("unexpected cmd error (codebase exits with error)", func(t *testing.T) { 112 buf := new(bytes.Buffer) 113 defaultTeeStderr = buf 114 ds := &fakeDiffService{ 115 FakeDiff: func() ([]byte, error) { 116 return []byte(""), nil 117 }, 118 } 119 cs := &fakeCommentService{ 120 FakePost: func(c *codebase.Comment) error { 121 return nil 122 }, 123 } 124 conf := &Config{ 125 Runner: map[string]*Runner{ 126 "test": { 127 Cmd: "not found", 128 Errorformat: []string{`%f:%l:%c:%m`}, 129 }, 130 }, 131 } 132 if err := Run(ctx, conf, nil, cs, ds, false, filter.ModeAdded, false); err == nil { 133 t.Error("want error, got nil") 134 } else { 135 t.Log(err) 136 } 137 }) 138 139 t.Run("cmd error with tee", func(t *testing.T) { 140 buf := new(bytes.Buffer) 141 defaultTeeStderr = buf 142 ds := &fakeDiffService{ 143 FakeDiff: func() ([]byte, error) { 144 return []byte(""), nil 145 }, 146 } 147 cs := &fakeCommentService{ 148 FakePost: func(c *codebase.Comment) error { 149 return nil 150 }, 151 } 152 conf := &Config{ 153 Runner: map[string]*Runner{ 154 "test": { 155 Cmd: "not-found", 156 Errorformat: []string{`%f:%l:%c:%m`}, 157 }, 158 }, 159 } 160 if err := Run(ctx, conf, nil, cs, ds, true, filter.ModeAdded, false); err == nil { 161 t.Error("want error, got nil") 162 } else { 163 t.Log(err) 164 } 165 want := "sh: 1: not-found: not found\n" 166 if got := buf.String(); got != want { 167 t.Errorf("got stderr %q, want %q", got, want) 168 } 169 }) 170 171 t.Run("success", func(t *testing.T) { 172 ds := &fakeDiffService{ 173 FakeDiff: func() ([]byte, error) { 174 return []byte(""), nil 175 }, 176 } 177 cs := &fakeCommentService{ 178 FakePost: func(c *codebase.Comment) error { 179 return nil 180 }, 181 } 182 conf := &Config{ 183 Runner: map[string]*Runner{ 184 "test": { 185 Cmd: "echo 'hi'", 186 Errorformat: []string{`%f:%l:%c:%m`}, 187 }, 188 }, 189 } 190 if err := Run(ctx, conf, nil, cs, ds, false, filter.ModeAdded, false); err != nil { 191 t.Error(err) 192 } 193 }) 194 195 t.Run("success with tee", func(t *testing.T) { 196 buf := new(bytes.Buffer) 197 defaultTeeStdout = buf 198 ds := &fakeDiffService{ 199 FakeDiff: func() ([]byte, error) { 200 return []byte(""), nil 201 }, 202 } 203 cs := &fakeCommentService{ 204 FakePost: func(c *codebase.Comment) error { 205 return nil 206 }, 207 } 208 conf := &Config{ 209 Runner: map[string]*Runner{ 210 "test": { 211 Cmd: "echo 'hi'", 212 Errorformat: []string{`%f:%l:%c:%m`}, 213 }, 214 }, 215 } 216 if err := Run(ctx, conf, nil, cs, ds, true, filter.ModeAdded, false); err != nil { 217 t.Error(err) 218 } 219 want := "hi\n" 220 if got := buf.String(); got != want { 221 t.Errorf("got stdout %q, want %q", got, want) 222 } 223 }) 224 225 t.Run("runners", func(t *testing.T) { 226 called := 0 227 ds := &fakeDiffService{ 228 FakeDiff: func() ([]byte, error) { 229 called++ 230 return []byte(""), nil 231 }, 232 } 233 cs := &fakeCommentService{ 234 FakePost: func(c *codebase.Comment) error { 235 return nil 236 }, 237 } 238 conf := &Config{ 239 Runner: map[string]*Runner{ 240 "test1": { 241 Name: "test1", 242 Cmd: "echo 'test1'", 243 Errorformat: []string{`%f:%l:%c:%m`}, 244 }, 245 "test2": { 246 Name: "test2", 247 Cmd: "echo 'test2'", 248 Errorformat: []string{`%f:%l:%c:%m`}, 249 }, 250 }, 251 } 252 if err := Run(ctx, conf, map[string]bool{"test2": true}, cs, ds, false, filter.ModeAdded, false); err != nil { 253 t.Error(err) 254 } 255 if called != 1 { 256 t.Errorf("Diff service called %d times, want 1 time", called) 257 } 258 }) 259 260 t.Run("unknown runners", func(t *testing.T) { 261 ds := &fakeDiffService{ 262 FakeDiff: func() ([]byte, error) { 263 return []byte(""), nil 264 }, 265 } 266 cs := &fakeCommentService{ 267 FakePost: func(c *codebase.Comment) error { 268 return nil 269 }, 270 } 271 conf := &Config{ 272 Runner: map[string]*Runner{ 273 "test1": { 274 Name: "test1", 275 Cmd: "echo 'test1'", 276 Errorformat: []string{`%f:%l:%c:%m`}, 277 }, 278 "test2": { 279 Name: "test2", 280 Cmd: "echo 'test2'", 281 Errorformat: []string{`%f:%l:%c:%m`}, 282 }, 283 }, 284 } 285 if err := Run(ctx, conf, map[string]bool{"hoge": true}, cs, ds, false, filter.ModeAdded, false); err == nil { 286 t.Error("got no error but want runner not found error") 287 } 288 }) 289 } 290 291 func TestFilteredEnviron(t *testing.T) { 292 names := [...]string{ 293 "CODEBASE_GITHUB_API_TOKEN", 294 "CODEBASE_GITLAB_API_TOKEN", 295 "CODEBASE_TOKEN", 296 } 297 298 for _, name := range names { 299 defer func(name, value string) { 300 os.Setenv(name, value) 301 }(name, os.Getenv(name)) 302 os.Setenv(name, "value") 303 } 304 305 filtered := filteredEnviron() 306 if len(filtered) != len(os.Environ())-len(names) { 307 t.Errorf("len(filtered) != len(os.Environ())-%d, %v != %v-%d", len(names), len(filtered), len(os.Environ()), len(names)) 308 } 309 310 for _, kv := range filtered { 311 for _, name := range names { 312 if strings.HasPrefix(kv, name) && kv != name+"=" { 313 t.Errorf("filtered: %v, want %v=", kv, name) 314 } 315 } 316 } 317 318 for _, kv := range os.Environ() { 319 for _, name := range names { 320 if strings.HasPrefix(kv, name) && kv != name+"=value" { 321 t.Errorf("envs: %v, want %v=value", kv, name) 322 } 323 } 324 } 325 }