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