structutil_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 structutil
  7. import (
  8. "testing"
  9. )
  10. type Defaulter struct {
  11. Value string
  12. }
  13. func (d *Defaulter) ParseDefault(v string) error {
  14. *d = Defaulter{Value: v}
  15. return nil
  16. }
  17. func TestSetDefaults(t *testing.T) {
  18. x := &struct {
  19. A string `default:"string"`
  20. B int `default:"2"`
  21. C float64 `default:"2.2"`
  22. D bool `default:"true"`
  23. E Defaulter `default:"defaulter"`
  24. }{}
  25. if x.A != "" {
  26. t.Error("string failed")
  27. } else if x.B != 0 {
  28. t.Error("int failed")
  29. } else if x.C != 0 {
  30. t.Errorf("float failed")
  31. } else if x.D {
  32. t.Errorf("bool failed")
  33. } else if x.E.Value != "" {
  34. t.Errorf("defaulter failed")
  35. }
  36. SetDefaults(x)
  37. if x.A != "string" {
  38. t.Error("string failed")
  39. } else if x.B != 2 {
  40. t.Error("int failed")
  41. } else if x.C != 2.2 {
  42. t.Errorf("float failed")
  43. } else if !x.D {
  44. t.Errorf("bool failed")
  45. } else if x.E.Value != "defaulter" {
  46. t.Errorf("defaulter failed")
  47. }
  48. }
  49. func TestFillNillSlices(t *testing.T) {
  50. // Nil
  51. x := &struct {
  52. A []string `default:"a,b"`
  53. }{}
  54. if x.A != nil {
  55. t.Error("not nil")
  56. }
  57. if err := FillNilSlices(x); err != nil {
  58. t.Error(err)
  59. }
  60. if len(x.A) != 2 {
  61. t.Error("length")
  62. }
  63. // Already provided
  64. y := &struct {
  65. A []string `default:"c,d,e"`
  66. }{[]string{"a", "b"}}
  67. if len(y.A) != 2 {
  68. t.Error("length")
  69. }
  70. if err := FillNilSlices(y); err != nil {
  71. t.Error(err)
  72. }
  73. if len(y.A) != 2 {
  74. t.Error("length")
  75. }
  76. // Non-nil but empty
  77. z := &struct {
  78. A []string `default:"c,d,e"`
  79. }{[]string{}}
  80. if len(z.A) != 0 {
  81. t.Error("length")
  82. }
  83. if err := FillNilSlices(z); err != nil {
  84. t.Error(err)
  85. }
  86. if len(z.A) != 0 {
  87. t.Error("length")
  88. }
  89. }
  90. func TestFillNil(t *testing.T) {
  91. type A struct {
  92. Slice []int
  93. Map map[string]string
  94. Chan chan int
  95. }
  96. type B struct {
  97. Slice *[]int
  98. Map *map[string]string
  99. Chan *chan int
  100. }
  101. type C struct {
  102. A A
  103. B *B
  104. D *****[]int
  105. }
  106. c := C{}
  107. FillNil(&c)
  108. if c.A.Slice == nil {
  109. t.Error("c.A.Slice")
  110. }
  111. if c.A.Map == nil {
  112. t.Error("c.A.Slice")
  113. }
  114. if c.A.Chan == nil {
  115. t.Error("c.A.Chan")
  116. }
  117. if c.B == nil {
  118. t.Error("c.B")
  119. }
  120. if c.B.Slice == nil {
  121. t.Error("c.B.Slice")
  122. }
  123. if c.B.Map == nil {
  124. t.Error("c.B.Slice")
  125. }
  126. if c.B.Chan == nil {
  127. t.Error("c.B.Chan")
  128. }
  129. if *c.B.Slice == nil {
  130. t.Error("*c.B.Slice")
  131. }
  132. if *c.B.Map == nil {
  133. t.Error("*c.B.Slice")
  134. }
  135. if *c.B.Chan == nil {
  136. t.Error("*c.B.Chan")
  137. }
  138. if *****c.D == nil {
  139. t.Error("c.D")
  140. }
  141. }
  142. func TestFillNilDoesNotBulldozeSetFields(t *testing.T) {
  143. type A struct {
  144. Slice []int
  145. Map map[string]string
  146. Chan chan int
  147. }
  148. type B struct {
  149. Slice *[]int
  150. Map *map[string]string
  151. Chan *chan int
  152. }
  153. type C struct {
  154. A A
  155. B *B
  156. D **[]int
  157. }
  158. ch := make(chan int, 10)
  159. d := make([]int, 10)
  160. dd := &d
  161. c := C{
  162. A: A{
  163. Slice: []int{1},
  164. Map: map[string]string{
  165. "k": "v",
  166. },
  167. Chan: make(chan int, 10),
  168. },
  169. B: &B{
  170. Slice: &[]int{1},
  171. Map: &map[string]string{
  172. "k": "v",
  173. },
  174. Chan: &ch,
  175. },
  176. D: &dd,
  177. }
  178. FillNil(&c)
  179. if len(c.A.Slice) != 1 {
  180. t.Error("c.A.Slice")
  181. }
  182. if len(c.A.Map) != 1 {
  183. t.Error("c.A.Slice")
  184. }
  185. if cap(c.A.Chan) != 10 {
  186. t.Error("c.A.Chan")
  187. }
  188. if c.B == nil {
  189. t.Error("c.B")
  190. }
  191. if len(*c.B.Slice) != 1 {
  192. t.Error("c.B.Slice")
  193. }
  194. if len(*c.B.Map) != 1 {
  195. t.Error("c.B.Slice")
  196. }
  197. if cap(*c.B.Chan) != 10 {
  198. t.Error("c.B.Chan")
  199. }
  200. if cap(**c.D) != 10 {
  201. t.Error("c.D")
  202. }
  203. }