main_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package main
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/hex"
  6. "net/http/httptest"
  7. "strings"
  8. "testing"
  9. "time"
  10. )
  11. const secret = "test-secret"
  12. func sign(body string) string {
  13. mac := hmac.New(sha256.New, []byte(secret))
  14. mac.Write([]byte(body))
  15. return hex.EncodeToString(mac.Sum(nil))
  16. }
  17. type call struct{ repo, sha, by string }
  18. func TestHandler(t *testing.T) {
  19. merged := `{"action":"closed","pull_request":{"merged":true,"base_branch":"main","merge_commit_sha":"abc123"},"repository":{"full_name":"bajdev/posts"},"sender":{"username":"bajdev"}}`
  20. tests := []struct {
  21. name, method, event, body, sig string
  22. status int
  23. released bool
  24. }{
  25. {"merged into main", "POST", "pull_request", merged, "", 202, true},
  26. {"bad signature", "POST", "pull_request", merged, "deadbeef", 401, false},
  27. {"missing signature", "POST", "pull_request", merged, "-", 401, false},
  28. {"GET", "GET", "pull_request", merged, "", 405, false},
  29. {"push event", "POST", "push", merged, "", 204, false},
  30. {"opened", "POST", "pull_request", strings.Replace(merged, `"closed"`, `"opened"`, 1), "", 204, false},
  31. {"closed without merge", "POST", "pull_request", strings.Replace(merged, `"merged":true`, `"merged":false`, 1), "", 204, false},
  32. {"merged into another branch", "POST", "pull_request", strings.Replace(merged, `"main"`, `"dev"`, 1), "", 204, false},
  33. {"no merge commit", "POST", "pull_request", strings.Replace(merged, `"abc123"`, `""`, 1), "", 204, false},
  34. {"no repository", "POST", "pull_request", strings.Replace(merged, `"bajdev/posts"`, `""`, 1), "", 204, false},
  35. {"not JSON", "POST", "pull_request", "not json", "", 204, false},
  36. }
  37. for _, tt := range tests {
  38. t.Run(tt.name, func(t *testing.T) {
  39. calls := make(chan call, 1)
  40. h := handler([]byte(secret), func(repo, sha, by string) { calls <- call{repo, sha, by} })
  41. req := httptest.NewRequest(tt.method, "/deploy", strings.NewReader(tt.body))
  42. req.Header.Set("X-Gogs-Event", tt.event)
  43. switch tt.sig {
  44. case "":
  45. req.Header.Set("X-Gogs-Signature", sign(tt.body))
  46. case "-":
  47. default:
  48. req.Header.Set("X-Gogs-Signature", tt.sig)
  49. }
  50. rec := httptest.NewRecorder()
  51. h.ServeHTTP(rec, req)
  52. if rec.Code != tt.status {
  53. t.Fatalf("status = %d, want %d", rec.Code, tt.status)
  54. }
  55. select {
  56. case c := <-calls:
  57. if !tt.released {
  58. t.Fatalf("unexpected release %+v", c)
  59. }
  60. if c != (call{"bajdev/posts", "abc123", "PR merged by bajdev"}) {
  61. t.Errorf("release called with %+v", c)
  62. }
  63. case <-time.After(200 * time.Millisecond):
  64. if tt.released {
  65. t.Fatal("release was not called")
  66. }
  67. }
  68. })
  69. }
  70. }
  71. func TestReleasesRunOneAtATime(t *testing.T) {
  72. body := `{"action":"closed","pull_request":{"merged":true,"base_branch":"main","merge_commit_sha":"x"},"repository":{"full_name":"a/b"}}`
  73. running, maxRunning := 0, 0
  74. done := make(chan struct{}, 3)
  75. h := handler([]byte(secret), func(repo, sha, by string) {
  76. // The handler's mutex is held here, so these updates don't race.
  77. running++
  78. if running > maxRunning {
  79. maxRunning = running
  80. }
  81. time.Sleep(20 * time.Millisecond)
  82. running--
  83. done <- struct{}{}
  84. })
  85. for i := 0; i < 3; i++ {
  86. req := httptest.NewRequest("POST", "/deploy", strings.NewReader(body))
  87. req.Header.Set("X-Gogs-Event", "pull_request")
  88. req.Header.Set("X-Gogs-Signature", sign(body))
  89. h.ServeHTTP(httptest.NewRecorder(), req)
  90. }
  91. for i := 0; i < 3; i++ {
  92. <-done
  93. }
  94. if maxRunning != 1 {
  95. t.Errorf("max concurrent releases = %d, want 1", maxRunning)
  96. }
  97. }