sync_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package sync
  7. import (
  8. "strings"
  9. "sync"
  10. "testing"
  11. "time"
  12. "github.com/syncthing/syncthing/lib/logger"
  13. )
  14. const (
  15. logThreshold = 100 * time.Millisecond
  16. shortWait = 5 * time.Millisecond
  17. longWait = 125 * time.Millisecond
  18. )
  19. var skipTimingTests = false
  20. func init() {
  21. // Check a few times that a short sleep does not in fact overrun the log
  22. // threshold. If it does, the timer accuracy is crap or the host is
  23. // overloaded and we can't reliably run the tests in here. In the normal
  24. // case this takes just 25*5 = 125 ms.
  25. for i := 0; i < 25; i++ {
  26. t0 := time.Now()
  27. time.Sleep(shortWait)
  28. if time.Since(t0) > logThreshold {
  29. skipTimingTests = true
  30. return
  31. }
  32. }
  33. }
  34. func TestTypes(t *testing.T) {
  35. debug = false
  36. l.SetDebug("sync", false)
  37. if _, ok := NewMutex().(*sync.Mutex); !ok {
  38. t.Error("Wrong type")
  39. }
  40. if _, ok := NewRWMutex().(*sync.RWMutex); !ok {
  41. t.Error("Wrong type")
  42. }
  43. if _, ok := NewWaitGroup().(*sync.WaitGroup); !ok {
  44. t.Error("Wrong type")
  45. }
  46. debug = true
  47. l.SetDebug("sync", true)
  48. if _, ok := NewMutex().(*loggedMutex); !ok {
  49. t.Error("Wrong type")
  50. }
  51. if _, ok := NewRWMutex().(*loggedRWMutex); !ok {
  52. t.Error("Wrong type")
  53. }
  54. if _, ok := NewWaitGroup().(*loggedWaitGroup); !ok {
  55. t.Error("Wrong type")
  56. }
  57. debug = false
  58. l.SetDebug("sync", false)
  59. }
  60. func TestMutex(t *testing.T) {
  61. if skipTimingTests {
  62. t.Skip("insufficient timer accuracy")
  63. return
  64. }
  65. debug = true
  66. l.SetDebug("sync", true)
  67. threshold = logThreshold
  68. msgmut := sync.Mutex{}
  69. var messages []string
  70. l.AddHandler(logger.LevelDebug, func(_ logger.LogLevel, message string) {
  71. msgmut.Lock()
  72. messages = append(messages, message)
  73. msgmut.Unlock()
  74. })
  75. mut := NewMutex()
  76. mut.Lock()
  77. time.Sleep(shortWait)
  78. mut.Unlock()
  79. if len(messages) > 0 {
  80. t.Errorf("Unexpected message count")
  81. }
  82. mut.Lock()
  83. time.Sleep(longWait)
  84. mut.Unlock()
  85. if len(messages) != 1 {
  86. t.Errorf("Unexpected message count")
  87. }
  88. debug = false
  89. l.SetDebug("sync", false)
  90. }
  91. func TestRWMutex(t *testing.T) {
  92. if skipTimingTests {
  93. t.Skip("insufficient timer accuracy")
  94. return
  95. }
  96. debug = true
  97. l.SetDebug("sync", true)
  98. threshold = logThreshold
  99. msgmut := sync.Mutex{}
  100. var messages []string
  101. l.AddHandler(logger.LevelDebug, func(_ logger.LogLevel, message string) {
  102. msgmut.Lock()
  103. messages = append(messages, message)
  104. msgmut.Unlock()
  105. })
  106. mut := NewRWMutex()
  107. mut.Lock()
  108. time.Sleep(shortWait)
  109. mut.Unlock()
  110. if len(messages) > 0 {
  111. t.Errorf("Unexpected message count")
  112. }
  113. mut.Lock()
  114. time.Sleep(longWait)
  115. mut.Unlock()
  116. if len(messages) != 1 {
  117. t.Errorf("Unexpected message count")
  118. }
  119. // Testing rlocker logging
  120. mut.RLock()
  121. go func() {
  122. time.Sleep(longWait)
  123. mut.RUnlock()
  124. }()
  125. mut.Lock()
  126. _ = 1 // skip empty critical section check
  127. mut.Unlock()
  128. if len(messages) != 2 {
  129. t.Errorf("Unexpected message count")
  130. }
  131. if !strings.Contains(messages[1], "RUnlockers while locking:\nat sync") || !strings.Contains(messages[1], "sync_test.go:") {
  132. t.Error("Unexpected message")
  133. }
  134. // Testing multiple rlockers
  135. mut.RLock()
  136. mut.RLock()
  137. mut.RLock()
  138. _ = 1 // skip empty critical section check
  139. mut.RUnlock()
  140. mut.RUnlock()
  141. mut.RUnlock()
  142. debug = false
  143. l.SetDebug("sync", false)
  144. }
  145. func TestWaitGroup(t *testing.T) {
  146. if skipTimingTests {
  147. t.Skip("insufficient timer accuracy")
  148. return
  149. }
  150. debug = true
  151. l.SetDebug("sync", true)
  152. threshold = logThreshold
  153. msgmut := sync.Mutex{}
  154. var messages []string
  155. l.AddHandler(logger.LevelDebug, func(_ logger.LogLevel, message string) {
  156. msgmut.Lock()
  157. messages = append(messages, message)
  158. msgmut.Unlock()
  159. })
  160. wg := NewWaitGroup()
  161. wg.Add(1)
  162. go func() {
  163. time.Sleep(shortWait)
  164. wg.Done()
  165. }()
  166. wg.Wait()
  167. if len(messages) > 0 {
  168. t.Errorf("Unexpected message count")
  169. }
  170. wg = NewWaitGroup()
  171. wg.Add(1)
  172. go func() {
  173. time.Sleep(longWait)
  174. wg.Done()
  175. }()
  176. wg.Wait()
  177. if len(messages) != 1 {
  178. t.Errorf("Unexpected message count")
  179. }
  180. debug = false
  181. l.SetDebug("sync", false)
  182. }