1/*
2Copyright 2014 Google Inc. All rights reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package fuzz_test
18
19import (
20	"encoding/json"
21	"fmt"
22	"math/rand"
23
24	"github.com/google/gofuzz"
25)
26
27func ExampleSimple() {
28	type MyType struct {
29		A string
30		B string
31		C int
32		D struct {
33			E float64
34		}
35	}
36
37	f := fuzz.New()
38	object := MyType{}
39
40	uniqueObjects := map[MyType]int{}
41
42	for i := 0; i < 1000; i++ {
43		f.Fuzz(&object)
44		uniqueObjects[object]++
45	}
46	fmt.Printf("Got %v unique objects.\n", len(uniqueObjects))
47	// Output:
48	// Got 1000 unique objects.
49}
50
51func ExampleCustom() {
52	type MyType struct {
53		A int
54		B string
55	}
56
57	counter := 0
58	f := fuzz.New().Funcs(
59		func(i *int, c fuzz.Continue) {
60			*i = counter
61			counter++
62		},
63	)
64	object := MyType{}
65
66	uniqueObjects := map[MyType]int{}
67
68	for i := 0; i < 100; i++ {
69		f.Fuzz(&object)
70		if object.A != i {
71			fmt.Printf("Unexpected value: %#v\n", object)
72		}
73		uniqueObjects[object]++
74	}
75	fmt.Printf("Got %v unique objects.\n", len(uniqueObjects))
76	// Output:
77	// Got 100 unique objects.
78}
79
80func ExampleComplex() {
81	type OtherType struct {
82		A string
83		B string
84	}
85	type MyType struct {
86		Pointer             *OtherType
87		Map                 map[string]OtherType
88		PointerMap          *map[string]OtherType
89		Slice               []OtherType
90		SlicePointer        []*OtherType
91		PointerSlicePointer *[]*OtherType
92	}
93
94	f := fuzz.New().RandSource(rand.NewSource(0)).NilChance(0).NumElements(1, 1).Funcs(
95		func(o *OtherType, c fuzz.Continue) {
96			o.A = "Foo"
97			o.B = "Bar"
98		},
99		func(op **OtherType, c fuzz.Continue) {
100			*op = &OtherType{"A", "B"}
101		},
102		func(m map[string]OtherType, c fuzz.Continue) {
103			m["Works Because"] = OtherType{
104				"Fuzzer",
105				"Preallocated",
106			}
107		},
108	)
109	object := MyType{}
110	f.Fuzz(&object)
111	bytes, err := json.MarshalIndent(&object, "", "    ")
112	if err != nil {
113		fmt.Printf("error: %v\n", err)
114	}
115	fmt.Printf("%s\n", string(bytes))
116	// Output:
117	// {
118	//     "Pointer": {
119	//         "A": "A",
120	//         "B": "B"
121	//     },
122	//     "Map": {
123	//         "Works Because": {
124	//             "A": "Fuzzer",
125	//             "B": "Preallocated"
126	//         }
127	//     },
128	//     "PointerMap": {
129	//         "Works Because": {
130	//             "A": "Fuzzer",
131	//             "B": "Preallocated"
132	//         }
133	//     },
134	//     "Slice": [
135	//         {
136	//             "A": "Foo",
137	//             "B": "Bar"
138	//         }
139	//     ],
140	//     "SlicePointer": [
141	//         {
142	//             "A": "A",
143	//             "B": "B"
144	//         }
145	//     ],
146	//     "PointerSlicePointer": [
147	//         {
148	//             "A": "A",
149	//             "B": "B"
150	//         }
151	//     ]
152	// }
153}
154
155func ExampleMap() {
156	f := fuzz.New().NilChance(0).NumElements(1, 1)
157	var myMap map[struct{ A, B, C int }]string
158	f.Fuzz(&myMap)
159	fmt.Printf("myMap has %v element(s).\n", len(myMap))
160	// Output:
161	// myMap has 1 element(s).
162}
163
164func ExampleSingle() {
165	f := fuzz.New()
166	var i int
167	f.Fuzz(&i)
168
169	// Technically, we'd expect this to fail one out of 2 billion attempts...
170	fmt.Printf("(i == 0) == %v", i == 0)
171	// Output:
172	// (i == 0) == false
173}
174
175func ExampleEnum() {
176	type MyEnum string
177	const (
178		A MyEnum = "A"
179		B MyEnum = "B"
180	)
181	type MyInfo struct {
182		Type  MyEnum
183		AInfo *string
184		BInfo *string
185	}
186
187	f := fuzz.New().NilChance(0).Funcs(
188		func(e *MyInfo, c fuzz.Continue) {
189			// Note c's embedded Rand allows for direct use.
190			// We could also use c.RandBool() here.
191			switch c.Intn(2) {
192			case 0:
193				e.Type = A
194				c.Fuzz(&e.AInfo)
195			case 1:
196				e.Type = B
197				c.Fuzz(&e.BInfo)
198			}
199		},
200	)
201
202	for i := 0; i < 100; i++ {
203		var myObject MyInfo
204		f.Fuzz(&myObject)
205		switch myObject.Type {
206		case A:
207			if myObject.AInfo == nil {
208				fmt.Println("AInfo should have been set!")
209			}
210			if myObject.BInfo != nil {
211				fmt.Println("BInfo should NOT have been set!")
212			}
213		case B:
214			if myObject.BInfo == nil {
215				fmt.Println("BInfo should have been set!")
216			}
217			if myObject.AInfo != nil {
218				fmt.Println("AInfo should NOT have been set!")
219			}
220		default:
221			fmt.Println("Invalid enum value!")
222		}
223	}
224	// Output:
225}
226