onceper_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2019 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package android
  15. import (
  16. "testing"
  17. "time"
  18. )
  19. func TestOncePer_Once(t *testing.T) {
  20. once := OncePer{}
  21. key := NewOnceKey("key")
  22. a := once.Once(key, func() interface{} { return "a" }).(string)
  23. b := once.Once(key, func() interface{} { return "b" }).(string)
  24. if a != "a" {
  25. t.Errorf(`first call to Once should return "a": %q`, a)
  26. }
  27. if b != "a" {
  28. t.Errorf(`second call to Once with the same key should return "a": %q`, b)
  29. }
  30. }
  31. func TestOncePer_Once_wait(t *testing.T) {
  32. once := OncePer{}
  33. key := NewOnceKey("key")
  34. ch := make(chan bool)
  35. go once.Once(key, func() interface{} { close(ch); time.Sleep(100 * time.Millisecond); return "foo" })
  36. <-ch
  37. a := once.Once(key, func() interface{} { return "bar" }).(string)
  38. if a != "foo" {
  39. t.Errorf("expect %q, got %q", "foo", a)
  40. }
  41. }
  42. func TestOncePer_Get(t *testing.T) {
  43. once := OncePer{}
  44. key := NewOnceKey("key")
  45. a := once.Once(key, func() interface{} { return "a" }).(string)
  46. b := once.Get(key).(string)
  47. if a != "a" {
  48. t.Errorf(`first call to Once should return "a": %q`, a)
  49. }
  50. if b != "a" {
  51. t.Errorf(`Get with the same key should return "a": %q`, b)
  52. }
  53. }
  54. func TestOncePer_Get_panic(t *testing.T) {
  55. once := OncePer{}
  56. key := NewOnceKey("key")
  57. defer func() {
  58. p := recover()
  59. if p == nil {
  60. t.Error("call to Get for unused key should panic")
  61. }
  62. }()
  63. once.Get(key)
  64. }
  65. func TestOncePer_Get_wait(t *testing.T) {
  66. once := OncePer{}
  67. key := NewOnceKey("key")
  68. ch := make(chan bool)
  69. go once.Once(key, func() interface{} { close(ch); time.Sleep(100 * time.Millisecond); return "foo" })
  70. <-ch
  71. a := once.Get(key).(string)
  72. if a != "foo" {
  73. t.Errorf("expect %q, got %q", "foo", a)
  74. }
  75. }
  76. func TestOncePer_OnceStringSlice(t *testing.T) {
  77. once := OncePer{}
  78. key := NewOnceKey("key")
  79. a := once.OnceStringSlice(key, func() []string { return []string{"a"} })
  80. b := once.OnceStringSlice(key, func() []string { return []string{"a"} })
  81. if a[0] != "a" {
  82. t.Errorf(`first call to OnceStringSlice should return ["a"]: %q`, a)
  83. }
  84. if b[0] != "a" {
  85. t.Errorf(`second call to OnceStringSlice with the same key should return ["a"]: %q`, b)
  86. }
  87. }
  88. func TestOncePer_Once2StringSlice(t *testing.T) {
  89. once := OncePer{}
  90. key := NewOnceKey("key")
  91. a, b := once.Once2StringSlice(key, func() ([]string, []string) { return []string{"a"}, []string{"b"} })
  92. c, d := once.Once2StringSlice(key, func() ([]string, []string) { return []string{"c"}, []string{"d"} })
  93. if a[0] != "a" || b[0] != "b" {
  94. t.Errorf(`first call to Once2StringSlice should return ["a"], ["b"]: %q, %q`, a, b)
  95. }
  96. if c[0] != "a" || d[0] != "b" {
  97. t.Errorf(`second call to Once2StringSlice with the same key should return ["a"], ["b"]: %q, %q`, c, d)
  98. }
  99. }
  100. func TestNewOnceKey(t *testing.T) {
  101. once := OncePer{}
  102. key1 := NewOnceKey("key")
  103. key2 := NewOnceKey("key")
  104. a := once.Once(key1, func() interface{} { return "a" }).(string)
  105. b := once.Once(key2, func() interface{} { return "b" }).(string)
  106. if a != "a" {
  107. t.Errorf(`first call to Once should return "a": %q`, a)
  108. }
  109. if b != "b" {
  110. t.Errorf(`second call to Once with the NewOnceKey from same string should return "b": %q`, b)
  111. }
  112. }
  113. func TestNewCustomOnceKey(t *testing.T) {
  114. type key struct {
  115. key string
  116. }
  117. once := OncePer{}
  118. key1 := NewCustomOnceKey(key{"key"})
  119. key2 := NewCustomOnceKey(key{"key"})
  120. a := once.Once(key1, func() interface{} { return "a" }).(string)
  121. b := once.Once(key2, func() interface{} { return "b" }).(string)
  122. if a != "a" {
  123. t.Errorf(`first call to Once should return "a": %q`, a)
  124. }
  125. if b != "a" {
  126. t.Errorf(`second call to Once with the NewCustomOnceKey from equal key should return "a": %q`, b)
  127. }
  128. }
  129. func TestOncePerReentrant(t *testing.T) {
  130. once := OncePer{}
  131. key1 := NewOnceKey("key")
  132. key2 := NewOnceKey("key")
  133. a := once.Once(key1, func() interface{} { return once.Once(key2, func() interface{} { return "a" }) })
  134. if a != "a" {
  135. t.Errorf(`reentrant Once should return "a": %q`, a)
  136. }
  137. }
  138. // Test that a recovered panic in a Once function doesn't deadlock
  139. func TestOncePerPanic(t *testing.T) {
  140. once := OncePer{}
  141. key := NewOnceKey("key")
  142. ch := make(chan interface{})
  143. var a interface{}
  144. go func() {
  145. defer func() {
  146. ch <- recover()
  147. }()
  148. a = once.Once(key, func() interface{} {
  149. panic("foo")
  150. })
  151. }()
  152. p := <-ch
  153. if p.(string) != "foo" {
  154. t.Errorf(`expected panic with "foo", got %#v`, p)
  155. }
  156. if a != nil {
  157. t.Errorf(`expected a to be nil, got %#v`, a)
  158. }
  159. // If the call to Once that panicked leaves the key in a bad state this will deadlock
  160. b := once.Once(key, func() interface{} {
  161. return "bar"
  162. })
  163. // The second call to Once should return nil inserted by the first call that panicked.
  164. if b != nil {
  165. t.Errorf(`expected b to be nil, got %#v`, b)
  166. }
  167. }