fuzz_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /*
  2. Copyright 2014 Google Inc. All rights reserved.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package fuzz
  14. import (
  15. "reflect"
  16. "testing"
  17. "time"
  18. )
  19. func TestFuzz_basic(t *testing.T) {
  20. obj := &struct {
  21. I int
  22. I8 int8
  23. I16 int16
  24. I32 int32
  25. I64 int64
  26. U uint
  27. U8 uint8
  28. U16 uint16
  29. U32 uint32
  30. U64 uint64
  31. Uptr uintptr
  32. S string
  33. B bool
  34. T time.Time
  35. }{}
  36. failed := map[string]int{}
  37. for i := 0; i < 10; i++ {
  38. New().Fuzz(obj)
  39. if n, v := "i", obj.I; v == 0 {
  40. failed[n] = failed[n] + 1
  41. }
  42. if n, v := "i8", obj.I8; v == 0 {
  43. failed[n] = failed[n] + 1
  44. }
  45. if n, v := "i16", obj.I16; v == 0 {
  46. failed[n] = failed[n] + 1
  47. }
  48. if n, v := "i32", obj.I32; v == 0 {
  49. failed[n] = failed[n] + 1
  50. }
  51. if n, v := "i64", obj.I64; v == 0 {
  52. failed[n] = failed[n] + 1
  53. }
  54. if n, v := "u", obj.U; v == 0 {
  55. failed[n] = failed[n] + 1
  56. }
  57. if n, v := "u8", obj.U8; v == 0 {
  58. failed[n] = failed[n] + 1
  59. }
  60. if n, v := "u16", obj.U16; v == 0 {
  61. failed[n] = failed[n] + 1
  62. }
  63. if n, v := "u32", obj.U32; v == 0 {
  64. failed[n] = failed[n] + 1
  65. }
  66. if n, v := "u64", obj.U64; v == 0 {
  67. failed[n] = failed[n] + 1
  68. }
  69. if n, v := "uptr", obj.Uptr; v == 0 {
  70. failed[n] = failed[n] + 1
  71. }
  72. if n, v := "s", obj.S; v == "" {
  73. failed[n] = failed[n] + 1
  74. }
  75. if n, v := "b", obj.B; v == false {
  76. failed[n] = failed[n] + 1
  77. }
  78. if n, v := "t", obj.T; v.IsZero() {
  79. failed[n] = failed[n] + 1
  80. }
  81. }
  82. checkFailed(t, failed)
  83. }
  84. func checkFailed(t *testing.T, failed map[string]int) {
  85. for k, v := range failed {
  86. if v > 8 {
  87. t.Errorf("%v seems to not be getting set, was zero value %v times", k, v)
  88. }
  89. }
  90. }
  91. func TestFuzz_structptr(t *testing.T) {
  92. obj := &struct {
  93. A *struct {
  94. S string
  95. }
  96. }{}
  97. f := New().NilChance(.5)
  98. failed := map[string]int{}
  99. for i := 0; i < 10; i++ {
  100. f.Fuzz(obj)
  101. if n, v := "a not nil", obj.A; v == nil {
  102. failed[n] = failed[n] + 1
  103. }
  104. if n, v := "a nil", obj.A; v != nil {
  105. failed[n] = failed[n] + 1
  106. }
  107. if n, v := "as", obj.A; v == nil || v.S == "" {
  108. failed[n] = failed[n] + 1
  109. }
  110. }
  111. checkFailed(t, failed)
  112. }
  113. // tryFuzz tries fuzzing up to 20 times. Fail if check() never passes, report the highest
  114. // stage it ever got to.
  115. func tryFuzz(t *testing.T, f *Fuzzer, obj interface{}, check func() (stage int, passed bool)) {
  116. maxStage := 0
  117. for i := 0; i < 20; i++ {
  118. f.Fuzz(obj)
  119. stage, passed := check()
  120. if stage > maxStage {
  121. maxStage = stage
  122. }
  123. if passed {
  124. return
  125. }
  126. }
  127. t.Errorf("Only ever got to stage %v", maxStage)
  128. }
  129. func TestFuzz_structmap(t *testing.T) {
  130. obj := &struct {
  131. A map[struct {
  132. S string
  133. }]struct {
  134. S2 string
  135. }
  136. B map[string]string
  137. }{}
  138. tryFuzz(t, New(), obj, func() (int, bool) {
  139. if obj.A == nil {
  140. return 1, false
  141. }
  142. if len(obj.A) == 0 {
  143. return 2, false
  144. }
  145. for k, v := range obj.A {
  146. if k.S == "" {
  147. return 3, false
  148. }
  149. if v.S2 == "" {
  150. return 4, false
  151. }
  152. }
  153. if obj.B == nil {
  154. return 5, false
  155. }
  156. if len(obj.B) == 0 {
  157. return 6, false
  158. }
  159. for k, v := range obj.B {
  160. if k == "" {
  161. return 7, false
  162. }
  163. if v == "" {
  164. return 8, false
  165. }
  166. }
  167. return 9, true
  168. })
  169. }
  170. func TestFuzz_structslice(t *testing.T) {
  171. obj := &struct {
  172. A []struct {
  173. S string
  174. }
  175. B []string
  176. }{}
  177. tryFuzz(t, New(), obj, func() (int, bool) {
  178. if obj.A == nil {
  179. return 1, false
  180. }
  181. if len(obj.A) == 0 {
  182. return 2, false
  183. }
  184. for _, v := range obj.A {
  185. if v.S == "" {
  186. return 3, false
  187. }
  188. }
  189. if obj.B == nil {
  190. return 4, false
  191. }
  192. if len(obj.B) == 0 {
  193. return 5, false
  194. }
  195. for _, v := range obj.B {
  196. if v == "" {
  197. return 6, false
  198. }
  199. }
  200. return 7, true
  201. })
  202. }
  203. func TestFuzz_structarray(t *testing.T) {
  204. obj := &struct {
  205. A [3]struct {
  206. S string
  207. }
  208. B [2]int
  209. }{}
  210. tryFuzz(t, New(), obj, func() (int, bool) {
  211. for _, v := range obj.A {
  212. if v.S == "" {
  213. return 1, false
  214. }
  215. }
  216. for _, v := range obj.B {
  217. if v == 0 {
  218. return 2, false
  219. }
  220. }
  221. return 3, true
  222. })
  223. }
  224. func TestFuzz_custom(t *testing.T) {
  225. obj := &struct {
  226. A string
  227. B *string
  228. C map[string]string
  229. D *map[string]string
  230. }{}
  231. testPhrase := "gotcalled"
  232. testMap := map[string]string{"C": "D"}
  233. f := New().Funcs(
  234. func(s *string, c Continue) {
  235. *s = testPhrase
  236. },
  237. func(m map[string]string, c Continue) {
  238. m["C"] = "D"
  239. },
  240. )
  241. tryFuzz(t, f, obj, func() (int, bool) {
  242. if obj.A != testPhrase {
  243. return 1, false
  244. }
  245. if obj.B == nil {
  246. return 2, false
  247. }
  248. if *obj.B != testPhrase {
  249. return 3, false
  250. }
  251. if e, a := testMap, obj.C; !reflect.DeepEqual(e, a) {
  252. return 4, false
  253. }
  254. if obj.D == nil {
  255. return 5, false
  256. }
  257. if e, a := testMap, *obj.D; !reflect.DeepEqual(e, a) {
  258. return 6, false
  259. }
  260. return 7, true
  261. })
  262. }
  263. type SelfFuzzer string
  264. // Implement fuzz.Interface.
  265. func (sf *SelfFuzzer) Fuzz(c Continue) {
  266. *sf = selfFuzzerTestPhrase
  267. }
  268. const selfFuzzerTestPhrase = "was fuzzed"
  269. func TestFuzz_interface(t *testing.T) {
  270. f := New()
  271. var obj1 SelfFuzzer
  272. tryFuzz(t, f, &obj1, func() (int, bool) {
  273. if obj1 != selfFuzzerTestPhrase {
  274. return 1, false
  275. }
  276. return 1, true
  277. })
  278. var obj2 map[int]SelfFuzzer
  279. tryFuzz(t, f, &obj2, func() (int, bool) {
  280. for _, v := range obj2 {
  281. if v != selfFuzzerTestPhrase {
  282. return 1, false
  283. }
  284. }
  285. return 1, true
  286. })
  287. }
  288. func TestFuzz_interfaceAndFunc(t *testing.T) {
  289. const privateTestPhrase = "private phrase"
  290. f := New().Funcs(
  291. // This should take precedence over SelfFuzzer.Fuzz().
  292. func(s *SelfFuzzer, c Continue) {
  293. *s = privateTestPhrase
  294. },
  295. )
  296. var obj1 SelfFuzzer
  297. tryFuzz(t, f, &obj1, func() (int, bool) {
  298. if obj1 != privateTestPhrase {
  299. return 1, false
  300. }
  301. return 1, true
  302. })
  303. var obj2 map[int]SelfFuzzer
  304. tryFuzz(t, f, &obj2, func() (int, bool) {
  305. for _, v := range obj2 {
  306. if v != privateTestPhrase {
  307. return 1, false
  308. }
  309. }
  310. return 1, true
  311. })
  312. }
  313. func TestFuzz_noCustom(t *testing.T) {
  314. type Inner struct {
  315. Str string
  316. }
  317. type Outer struct {
  318. Str string
  319. In Inner
  320. }
  321. testPhrase := "gotcalled"
  322. f := New().Funcs(
  323. func(outer *Outer, c Continue) {
  324. outer.Str = testPhrase
  325. c.Fuzz(&outer.In)
  326. },
  327. func(inner *Inner, c Continue) {
  328. inner.Str = testPhrase
  329. },
  330. )
  331. c := Continue{f: f, Rand: f.r}
  332. // Fuzzer.Fuzz()
  333. obj1 := Outer{}
  334. f.Fuzz(&obj1)
  335. if obj1.Str != testPhrase {
  336. t.Errorf("expected Outer custom function to have been called")
  337. }
  338. if obj1.In.Str != testPhrase {
  339. t.Errorf("expected Inner custom function to have been called")
  340. }
  341. // Continue.Fuzz()
  342. obj2 := Outer{}
  343. c.Fuzz(&obj2)
  344. if obj2.Str != testPhrase {
  345. t.Errorf("expected Outer custom function to have been called")
  346. }
  347. if obj2.In.Str != testPhrase {
  348. t.Errorf("expected Inner custom function to have been called")
  349. }
  350. // Fuzzer.FuzzNoCustom()
  351. obj3 := Outer{}
  352. f.FuzzNoCustom(&obj3)
  353. if obj3.Str == testPhrase {
  354. t.Errorf("expected Outer custom function to not have been called")
  355. }
  356. if obj3.In.Str != testPhrase {
  357. t.Errorf("expected Inner custom function to have been called")
  358. }
  359. // Continue.FuzzNoCustom()
  360. obj4 := Outer{}
  361. c.FuzzNoCustom(&obj4)
  362. if obj4.Str == testPhrase {
  363. t.Errorf("expected Outer custom function to not have been called")
  364. }
  365. if obj4.In.Str != testPhrase {
  366. t.Errorf("expected Inner custom function to have been called")
  367. }
  368. }