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  }