utils_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (C) 2016 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 https://mozilla.org/MPL/2.0/.
  6. package util
  7. import (
  8. "strings"
  9. "testing"
  10. )
  11. type Defaulter struct {
  12. Value string
  13. }
  14. func (d *Defaulter) ParseDefault(v string) error {
  15. *d = Defaulter{Value: v}
  16. return nil
  17. }
  18. func TestSetDefaults(t *testing.T) {
  19. x := &struct {
  20. A string `default:"string"`
  21. B int `default:"2"`
  22. C float64 `default:"2.2"`
  23. D bool `default:"true"`
  24. E Defaulter `default:"defaulter"`
  25. }{}
  26. if x.A != "" {
  27. t.Error("string failed")
  28. } else if x.B != 0 {
  29. t.Error("int failed")
  30. } else if x.C != 0 {
  31. t.Errorf("float failed")
  32. } else if x.D {
  33. t.Errorf("bool failed")
  34. } else if x.E.Value != "" {
  35. t.Errorf("defaulter failed")
  36. }
  37. SetDefaults(x)
  38. if x.A != "string" {
  39. t.Error("string failed")
  40. } else if x.B != 2 {
  41. t.Error("int failed")
  42. } else if x.C != 2.2 {
  43. t.Errorf("float failed")
  44. } else if !x.D {
  45. t.Errorf("bool failed")
  46. } else if x.E.Value != "defaulter" {
  47. t.Errorf("defaulter failed")
  48. }
  49. }
  50. func TestUniqueStrings(t *testing.T) {
  51. tests := []struct {
  52. input []string
  53. expected []string
  54. }{
  55. {
  56. []string{"a", "b"},
  57. []string{"a", "b"},
  58. },
  59. {
  60. []string{"a", "a"},
  61. []string{"a"},
  62. },
  63. {
  64. []string{"a", "a", "a", "a"},
  65. []string{"a"},
  66. },
  67. {
  68. nil,
  69. nil,
  70. },
  71. {
  72. []string{" a ", " a ", "b ", " b"},
  73. []string{"a", "b"},
  74. },
  75. }
  76. for _, test := range tests {
  77. result := UniqueTrimmedStrings(test.input)
  78. if len(result) != len(test.expected) {
  79. t.Errorf("%s != %s", result, test.expected)
  80. }
  81. for i := range result {
  82. if test.expected[i] != result[i] {
  83. t.Errorf("%s != %s", result, test.expected)
  84. }
  85. }
  86. }
  87. }
  88. func TestFillNillSlices(t *testing.T) {
  89. // Nil
  90. x := &struct {
  91. A []string `default:"a,b"`
  92. }{}
  93. if x.A != nil {
  94. t.Error("not nil")
  95. }
  96. if err := FillNilSlices(x); err != nil {
  97. t.Error(err)
  98. }
  99. if len(x.A) != 2 {
  100. t.Error("length")
  101. }
  102. // Already provided
  103. y := &struct {
  104. A []string `default:"c,d,e"`
  105. }{[]string{"a", "b"}}
  106. if len(y.A) != 2 {
  107. t.Error("length")
  108. }
  109. if err := FillNilSlices(y); err != nil {
  110. t.Error(err)
  111. }
  112. if len(y.A) != 2 {
  113. t.Error("length")
  114. }
  115. // Non-nil but empty
  116. z := &struct {
  117. A []string `default:"c,d,e"`
  118. }{[]string{}}
  119. if len(z.A) != 0 {
  120. t.Error("length")
  121. }
  122. if err := FillNilSlices(z); err != nil {
  123. t.Error(err)
  124. }
  125. if len(z.A) != 0 {
  126. t.Error("length")
  127. }
  128. }
  129. func TestAddress(t *testing.T) {
  130. tests := []struct {
  131. network string
  132. host string
  133. result string
  134. }{
  135. {"tcp", "google.com", "tcp://google.com"},
  136. {"foo", "google", "foo://google"},
  137. {"123", "456", "123://456"},
  138. }
  139. for _, test := range tests {
  140. result := Address(test.network, test.host)
  141. if result != test.result {
  142. t.Errorf("%s != %s", result, test.result)
  143. }
  144. }
  145. }
  146. func TestCopyMatching(t *testing.T) {
  147. type Nested struct {
  148. A int
  149. }
  150. type Test struct {
  151. CopyA int
  152. CopyB []string
  153. CopyC Nested
  154. CopyD *Nested
  155. NoCopy int `restart:"true"`
  156. }
  157. from := Test{
  158. CopyA: 1,
  159. CopyB: []string{"friend", "foe"},
  160. CopyC: Nested{
  161. A: 2,
  162. },
  163. CopyD: &Nested{
  164. A: 3,
  165. },
  166. NoCopy: 4,
  167. }
  168. to := Test{
  169. CopyA: 11,
  170. CopyB: []string{"foot", "toe"},
  171. CopyC: Nested{
  172. A: 22,
  173. },
  174. CopyD: &Nested{
  175. A: 33,
  176. },
  177. NoCopy: 44,
  178. }
  179. // Copy empty fields
  180. CopyMatchingTag(&from, &to, "restart", func(v string) bool {
  181. return v != "true"
  182. })
  183. if to.CopyA != 1 {
  184. t.Error("CopyA")
  185. }
  186. if len(to.CopyB) != 2 || to.CopyB[0] != "friend" || to.CopyB[1] != "foe" {
  187. t.Error("CopyB")
  188. }
  189. if to.CopyC.A != 2 {
  190. t.Error("CopyC")
  191. }
  192. if to.CopyD.A != 3 {
  193. t.Error("CopyC")
  194. }
  195. if to.NoCopy != 44 {
  196. t.Error("NoCopy")
  197. }
  198. }
  199. func TestUtilStopTwicePanic(t *testing.T) {
  200. s := AsService(func(stop chan struct{}) {
  201. <-stop
  202. })
  203. go s.Serve()
  204. s.Stop()
  205. defer func() {
  206. expected := "lib/util.TestUtilStopTwicePanic"
  207. if r := recover(); r == nil || !strings.Contains(r.(string), expected) {
  208. t.Fatalf(`expected panic containing "%v", got "%v"`, expected, r)
  209. }
  210. }()
  211. s.Stop()
  212. }