bitbucket.org/number571/tendermint@v0.8.14/test/e2e/generator/random.go (about)

     1  package main
     2  
     3  import (
     4  	"math/rand"
     5  	"sort"
     6  )
     7  
     8  // combinations takes input in the form of a map of item lists, and returns a
     9  // list of all combinations of each item for each key. E.g.:
    10  //
    11  // {"foo": [1, 2, 3], "bar": [4, 5, 6]}
    12  //
    13  // Will return the following maps:
    14  //
    15  // {"foo": 1, "bar": 4}
    16  // {"foo": 1, "bar": 5}
    17  // {"foo": 1, "bar": 6}
    18  // {"foo": 2, "bar": 4}
    19  // {"foo": 2, "bar": 5}
    20  // {"foo": 2, "bar": 6}
    21  // {"foo": 3, "bar": 4}
    22  // {"foo": 3, "bar": 5}
    23  // {"foo": 3, "bar": 6}
    24  func combinations(items map[string][]interface{}) []map[string]interface{} {
    25  	keys := []string{}
    26  	for key := range items {
    27  		keys = append(keys, key)
    28  	}
    29  	sort.Strings(keys)
    30  	return combiner(map[string]interface{}{}, keys, items)
    31  }
    32  
    33  // combiner is a utility function for combinations.
    34  func combiner(head map[string]interface{}, pending []string, items map[string][]interface{}) []map[string]interface{} {
    35  	if len(pending) == 0 {
    36  		return []map[string]interface{}{head}
    37  	}
    38  	key, pending := pending[0], pending[1:]
    39  
    40  	result := []map[string]interface{}{}
    41  	for _, value := range items[key] {
    42  		path := map[string]interface{}{}
    43  		for k, v := range head {
    44  			path[k] = v
    45  		}
    46  		path[key] = value
    47  		result = append(result, combiner(path, pending, items)...)
    48  	}
    49  	return result
    50  }
    51  
    52  // uniformChoice chooses a single random item from the argument list, uniformly weighted.
    53  type uniformChoice []interface{}
    54  
    55  func (uc uniformChoice) Choose(r *rand.Rand) interface{} {
    56  	return uc[r.Intn(len(uc))]
    57  }
    58  
    59  // probSetChoice picks a set of strings based on each string's probability (0-1).
    60  type probSetChoice map[string]float64
    61  
    62  func (pc probSetChoice) Choose(r *rand.Rand) []string {
    63  	choices := []string{}
    64  	for item, prob := range pc {
    65  		if r.Float64() <= prob {
    66  			choices = append(choices, item)
    67  		}
    68  	}
    69  	return choices
    70  }
    71  
    72  // uniformSetChoice picks a set of strings with uniform probability, picking at least one.
    73  type uniformSetChoice []string
    74  
    75  func (usc uniformSetChoice) Choose(r *rand.Rand) []string {
    76  	choices := []string{}
    77  	indexes := r.Perm(len(usc))
    78  	if len(indexes) > 1 {
    79  		indexes = indexes[:1+r.Intn(len(indexes)-1)]
    80  	}
    81  	for _, i := range indexes {
    82  		choices = append(choices, usc[i])
    83  	}
    84  	return choices
    85  }