gitea源码

globallock_test.go 1.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package globallock
  4. import (
  5. "context"
  6. "os"
  7. "sync"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. )
  12. func TestLockAndDo(t *testing.T) {
  13. t.Run("redis", func(t *testing.T) {
  14. url := "redis://127.0.0.1:6379/0"
  15. if os.Getenv("CI") == "" {
  16. // Make it possible to run tests against a local redis instance
  17. url = os.Getenv("TEST_REDIS_URL")
  18. if url == "" {
  19. t.Skip("TEST_REDIS_URL not set and not running in CI")
  20. return
  21. }
  22. }
  23. oldDefaultLocker := defaultLocker
  24. oldInitFunc := initFunc
  25. defer func() {
  26. defaultLocker = oldDefaultLocker
  27. initFunc = oldInitFunc
  28. if defaultLocker == nil {
  29. initOnce = sync.Once{}
  30. }
  31. }()
  32. initOnce = sync.Once{}
  33. initFunc = func() {
  34. defaultLocker = NewRedisLocker(url)
  35. }
  36. testLockAndDo(t)
  37. require.NoError(t, defaultLocker.(*redisLocker).Close())
  38. })
  39. t.Run("memory", func(t *testing.T) {
  40. oldDefaultLocker := defaultLocker
  41. oldInitFunc := initFunc
  42. defer func() {
  43. defaultLocker = oldDefaultLocker
  44. initFunc = oldInitFunc
  45. if defaultLocker == nil {
  46. initOnce = sync.Once{}
  47. }
  48. }()
  49. initOnce = sync.Once{}
  50. initFunc = func() {
  51. defaultLocker = NewMemoryLocker()
  52. }
  53. testLockAndDo(t)
  54. })
  55. }
  56. func testLockAndDo(t *testing.T) {
  57. const concurrency = 50
  58. ctx := t.Context()
  59. count := 0
  60. wg := sync.WaitGroup{}
  61. wg.Add(concurrency)
  62. for range concurrency {
  63. go func() {
  64. defer wg.Done()
  65. err := LockAndDo(ctx, "test", func(ctx context.Context) error {
  66. count++
  67. // It's impossible to acquire the lock inner the function
  68. ok, err := TryLockAndDo(ctx, "test", func(ctx context.Context) error {
  69. assert.Fail(t, "should not acquire the lock")
  70. return nil
  71. })
  72. assert.False(t, ok)
  73. assert.NoError(t, err)
  74. return nil
  75. })
  76. require.NoError(t, err)
  77. }()
  78. }
  79. wg.Wait()
  80. assert.Equal(t, concurrency, count)
  81. }