locked_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. //go:build go1.13 && !go1.19
  4. package syncs
  5. import (
  6. "sync"
  7. "testing"
  8. "time"
  9. )
  10. func wantPanic(t *testing.T, fn func()) {
  11. t.Helper()
  12. defer func() {
  13. recover()
  14. }()
  15. fn()
  16. t.Fatal("failed to panic")
  17. }
  18. func TestAssertLocked(t *testing.T) {
  19. m := new(sync.Mutex)
  20. wantPanic(t, func() { AssertLocked(m) })
  21. m.Lock()
  22. AssertLocked(m)
  23. m.Unlock()
  24. wantPanic(t, func() { AssertLocked(m) })
  25. // Test correct handling of mutex with waiter.
  26. m.Lock()
  27. AssertLocked(m)
  28. go func() {
  29. m.Lock()
  30. m.Unlock()
  31. }()
  32. // Give the goroutine above a few moments to get started.
  33. // The test will pass whether or not we win the race,
  34. // but we want to run sometimes, to get the test coverage.
  35. time.Sleep(10 * time.Millisecond)
  36. AssertLocked(m)
  37. }
  38. func TestAssertWLocked(t *testing.T) {
  39. m := new(sync.RWMutex)
  40. wantPanic(t, func() { AssertWLocked(m) })
  41. m.Lock()
  42. AssertWLocked(m)
  43. m.Unlock()
  44. wantPanic(t, func() { AssertWLocked(m) })
  45. // Test correct handling of mutex with waiter.
  46. m.Lock()
  47. AssertWLocked(m)
  48. go func() {
  49. m.Lock()
  50. m.Unlock()
  51. }()
  52. // Give the goroutine above a few moments to get started.
  53. // The test will pass whether or not we win the race,
  54. // but we want to run sometimes, to get the test coverage.
  55. time.Sleep(10 * time.Millisecond)
  56. AssertWLocked(m)
  57. }
  58. func TestAssertRLocked(t *testing.T) {
  59. m := new(sync.RWMutex)
  60. wantPanic(t, func() { AssertRLocked(m) })
  61. m.Lock()
  62. AssertRLocked(m)
  63. m.Unlock()
  64. m.RLock()
  65. AssertRLocked(m)
  66. m.RUnlock()
  67. wantPanic(t, func() { AssertRLocked(m) })
  68. // Test correct handling of mutex with waiter.
  69. m.RLock()
  70. AssertRLocked(m)
  71. go func() {
  72. m.RLock()
  73. m.RUnlock()
  74. }()
  75. // Give the goroutine above a few moments to get started.
  76. // The test will pass whether or not we win the race,
  77. // but we want to run sometimes, to get the test coverage.
  78. time.Sleep(10 * time.Millisecond)
  79. AssertRLocked(m)
  80. m.RUnlock()
  81. // Test correct handling of rlock with write waiter.
  82. m.RLock()
  83. AssertRLocked(m)
  84. go func() {
  85. m.Lock()
  86. m.Unlock()
  87. }()
  88. // Give the goroutine above a few moments to get started.
  89. // The test will pass whether or not we win the race,
  90. // but we want to run sometimes, to get the test coverage.
  91. time.Sleep(10 * time.Millisecond)
  92. AssertRLocked(m)
  93. m.RUnlock()
  94. // Test correct handling of rlock with other rlocks.
  95. // This is a bit racy, but losing the race hurts nothing,
  96. // and winning the race means correct test coverage.
  97. m.RLock()
  98. AssertRLocked(m)
  99. go func() {
  100. m.RLock()
  101. time.Sleep(10 * time.Millisecond)
  102. m.RUnlock()
  103. }()
  104. time.Sleep(5 * time.Millisecond)
  105. AssertRLocked(m)
  106. m.RUnlock()
  107. }