atomicrunstate_test.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package atomic
  2. import (
  3. "testing"
  4. "time"
  5. )
  6. // NOTE: This test uses time.Sleep() in an attempt to specifically schedule concurrent actions for testing
  7. // NOTE: Testing concurrency is hard, so if there are inconsistent results, make sure it's not just the timing
  8. // NOTE: of the test on the testing hardware.
  9. func TestRunState(t *testing.T) {
  10. var ars AtomicRunState
  11. if !ars.Start() {
  12. t.Fatalf("Failed to Start() AtomicRunState")
  13. }
  14. if ars.Start() {
  15. t.Fatalf("Started AtomicRunState a second time")
  16. }
  17. success := make(chan bool)
  18. go func() {
  19. cycles := 0
  20. for {
  21. // Our test expects exactly 1 cycle, so if we exceed that, we fail!
  22. if cycles >= 2 {
  23. success <- false
  24. return
  25. }
  26. // create a "work" time before the select
  27. time.Sleep(1 * time.Second)
  28. select {
  29. case <-ars.OnStop():
  30. t.Logf("Stopped\n")
  31. ars.Reset()
  32. success <- true
  33. return
  34. case <-time.After(2 * time.Second):
  35. t.Logf("Tick\n")
  36. }
  37. cycles++
  38. }
  39. }()
  40. // Wait for one full work cycle (3 seconds), attempt Stop during "work" phase
  41. time.Sleep(3500 * time.Millisecond)
  42. ars.Stop()
  43. result := <-success
  44. if !result {
  45. t.Fatalf("Executed too many work cycles, expected 1 cycle")
  46. }
  47. }