"""Random protobuf message generator."""
import random
import string
import functools
from google.protobuf.descriptor import FieldDescriptor
def _rand_float():
return random.random() * 2 - 1
def _rand_int_factory(a=0, b=(1 << 128)):
def get_random_int():
"""Get random int."""
return random.randint(a, b - 1)
return get_random_int
def _rand_signed_int_factory(bits=32):
max_abs = 1 << (bits // 2)
return _rand_int_factory(a=-max_abs, b=max_abs)
def _rand_unsigned_int_factory(bits=32):
return _rand_int_factory(a=0, b=(1 << bits))
def _rand_bool():
return random.randint(0, 1) == 1
def _rand_str():
n = random.randint(0, 2)
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for _ in range(n))
def _rand_bytes():
s = _rand_str()
return s.encode('utf-8')
_FIELD_RANDOM_GENERATOR = {
FieldDescriptor.TYPE_DOUBLE: _rand_float,
FieldDescriptor.TYPE_FLOAT: _rand_float,
FieldDescriptor.TYPE_INT32: _rand_signed_int_factory(32),
FieldDescriptor.TYPE_INT64: _rand_signed_int_factory(64),
FieldDescriptor.TYPE_UINT32: _rand_unsigned_int_factory(32),
FieldDescriptor.TYPE_UINT64: _rand_unsigned_int_factory(64),
FieldDescriptor.TYPE_SINT32: _rand_signed_int_factory(32),
FieldDescriptor.TYPE_SINT64: _rand_signed_int_factory(64),
FieldDescriptor.TYPE_FIXED32: _rand_unsigned_int_factory(32),
FieldDescriptor.TYPE_FIXED64: _rand_unsigned_int_factory(64),
FieldDescriptor.TYPE_SFIXED32: _rand_signed_int_factory(32),
FieldDescriptor.TYPE_SFIXED64: _rand_signed_int_factory(64),
FieldDescriptor.TYPE_BOOL: _rand_bool,
FieldDescriptor.TYPE_STRING: _rand_str,
FieldDescriptor.TYPE_BYTES: _rand_bytes,
}
def _fill_random(msg, desc):
"""Fill all fields of ``msg`` with random values."""
for field in desc.fields:
is_message = field.type == FieldDescriptor.TYPE_MESSAGE
is_repeated = field.label == FieldDescriptor.LABEL_REPEATED
if is_message:
msg_field = getattr(msg, field.name)
if is_repeated:
num = random.randint(0, 2)
for _ in range(num):
element = msg_field.add()
_fill_random(element, field.message_type)
else:
_fill_random(msg_field, field.message_type)
else:
if field.type == FieldDescriptor.TYPE_ENUM:
enum_values = [x.number for x in field.enum_type.values]
generator = functools.partial(random.choice, enum_values)
else:
generator = _FIELD_RANDOM_GENERATOR.get(field.type)
if is_repeated:
num = random.randint(0, 2)
msg_field = getattr(msg, field.name)
for _ in range(num):
msg_field.append(generator())
else:
setattr(msg, field.name, generator())
[docs]def randproto(proto):
"""Generate random protobuf message object.
Args:
proto: The protobuf message class.
Returns:
google.protobuf.message: Generated massage object.
"""
msg = proto()
_fill_random(msg, proto.DESCRIPTOR)
return msg