github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/json/random.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package json 12 13 import ( 14 "encoding/json" 15 "fmt" 16 "math/rand" 17 ) 18 19 // Some issues will only be revealed if we have duplicate strings, so we 20 // include a pool of common strings that we occasionally pull from rather than 21 // generating a completely random string. 22 var staticStrings = []string{ 23 "a", 24 "b", 25 "c", 26 "foo", 27 "bar", 28 "baz", 29 "foobar", 30 } 31 32 // Random generates a random JSON value. 33 func Random(complexity int, rng *rand.Rand) (JSON, error) { 34 return MakeJSON(doRandomJSON(complexity, rng)) 35 } 36 37 func randomJSONString(rng *rand.Rand) interface{} { 38 if rng.Intn(2) == 0 { 39 return staticStrings[rng.Intn(len(staticStrings))] 40 } 41 result := make([]byte, 0) 42 l := rng.Intn(10) + 3 43 for i := 0; i < l; i++ { 44 result = append(result, byte(rng.Intn(0x7f-0x20)+0x20)) 45 } 46 return string(result) 47 } 48 49 func randomJSONNumber(rng *rand.Rand) interface{} { 50 return json.Number(fmt.Sprintf("%v", rng.ExpFloat64())) 51 } 52 53 func doRandomJSON(complexity int, rng *rand.Rand) interface{} { 54 if complexity <= 0 || rng.Intn(10) == 0 { 55 switch rng.Intn(5) { 56 case 0: 57 return randomJSONString(rng) 58 case 1: 59 return randomJSONNumber(rng) 60 case 2: 61 return true 62 case 3: 63 return false 64 case 4: 65 return nil 66 } 67 } 68 complexity-- 69 switch rng.Intn(3) { 70 case 0: 71 result := make([]interface{}, 0) 72 for complexity > 0 { 73 amount := 1 + rng.Intn(complexity) 74 complexity -= amount 75 result = append(result, doRandomJSON(amount, rng)) 76 } 77 return result 78 case 1: 79 result := make(map[string]interface{}) 80 for complexity > 0 { 81 amount := 1 + rng.Intn(complexity) 82 complexity -= amount 83 result[randomJSONString(rng).(string)] = doRandomJSON(amount, rng) 84 } 85 return result 86 default: 87 j, _ := Random(complexity, rng) 88 encoding, _ := EncodeJSON(nil, j) 89 encoded, _ := newEncodedFromRoot(encoding) 90 return encoded 91 } 92 }