xref: /aosp_15_r20/external/cronet/testing/clusterfuzz/common/utils.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2016 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import copy
6import functools
7import math
8import random
9
10
11def RandomLowInteger(low, high, beta=31.0):
12  """Like random.randint, but heavily skewed toward the low end"""
13  assert low <= high
14  return low + int(math.floor(random.betavariate(1.0, beta) * (high - low)))
15
16
17def UniformExpoInteger(low, high, base=2):
18  """Returns base to a power uniformly distributed between low and high.
19
20  This is useful for exploring large ranges of integers while ensuring that
21  values of all different sizes are represented.
22  """
23  return int(math.floor(math.pow(base, random.uniform(low, high))))
24
25
26def WeightedChoice(choices): # pylint: disable=inconsistent-return-statements
27  """Chooses an item given a sequence of (choice, weight) tuples"""
28  total = sum(w for c, w in choices)
29  r = random.uniform(0, total)
30  upto = 0
31  for c, w in choices:
32    upto += w
33    if upto >= r:
34      return c
35  assert False
36
37
38def Pipeline(*funcs):
39  """Given a number of single-argument functions, returns a single-argument
40  function which computes their composition. Each of the functions are applied
41  to the input in order from left to right, with the result of each function
42  passed as the argument to the next function."""
43  return reduce(lambda f, g: lambda x: g(f(x)), funcs)
44
45
46def DeepMemoize(obj):
47  """A memoizing decorator that returns deep copies of the function results."""
48  cache = obj.cache = {}
49  @functools.wraps(obj)
50  def Memoize(*args):
51    if args not in cache:
52      cache[args] = copy.deepcopy(obj(*args))
53    return copy.deepcopy(cache[args])
54  return Memoize
55