def test_permuted_generators(self): 'Test basic Product() permuter' values1 = gen.IterValueGenerator('a', [1, 2]) values2 = gen.IterValueGenerator('b', [1, 2]) produced_vals = [] for x in gen.Product('name', values1, values2): x = tuple(map(lambda e: e[1], x)) produced_vals.append(x) self.assertEqual(produced_vals, [(1, 1), (1, 2), (2, 1), (2, 2)])
def test_limited_product(self): 'Test limits on a Product iterator' source_vals = [1, 2, 3, 4] vals1 = gen.IterValueGenerator('key', source_vals) vals2 = gen.IterValueGenerator('values', source_vals) produced_vals = [] for v1, v2 in gen.Product('name', vals1, vals2, limit=4): produced_vals.append((v1[1], v2[1])) self.assertEqual(produced_vals, [(1, 1), (1, 2), (1, 3), (1, 4)])
def test_permuted_generators_with_via_make_dep(self): 'Test creation of dependencies via Permuter.make_dependent()' names = gen.IterValueGenerator('name', ['alice', 'bob']) lengths = gen.IterValueGenerator('len', ['one', 'two']) permuter = gen.Zip('Permute', names, lengths) permuter.make_dependent('len', 'name', len) for tuples in permuter: values = dict(tuples) self.assertEqual(len(values['name']), values['len'])
def test_zip(self): 'Test a basic Zip permuter' source_vals = [1, 2, 3, 4] vals1 = gen.IterValueGenerator('key', source_vals) vals2 = gen.IterValueGenerator('val', source_vals) produced_via_zips = [] for x, y in gen.Zip('name', vals1, vals2): produced_via_zips.append((x[1], y[1])) expected = list(zip(source_vals, source_vals)) self.assertEqual(produced_via_zips, expected)
def test_make_dependent(self): source_vals = [1, 2, 3, 4] vals1 = gen.IterValueGenerator('key', source_vals) vals2 = gen.IterValueGenerator('values', source_vals) def increment_by_one(val): return val + 1 permuter = gen.Zip('test', vals1, vals2) permuter.make_dependent('key', 'values', increment_by_one) for values in permuter: res = dict(values) self.assertEqual(res['key'], increment_by_one(res['values']))
def test_name(self): 'Test setting a name' name = 'A Name' generator = gen.IterValueGenerator('name', []) generator.set_name(name) self.assertEqual(generator.name(), name)
def test_permuted_generators_with_dependent_values(self): 'Test that Product permuter works with dependent values' def is_even(x): return x % 2 == 0 values1 = gen.IterValueGenerator('a', [1, 2, 3]) values2 = gen.IterValueGenerator('b', [1, 2, 3]) values3 = gen.IterValueGenerator('c', [1, 2, 3]) dependent = gen.DependentValueGenerator('v1', target=values1, action=is_even) for x in gen.Product('name', values1, values2, values3, dependent): v1, v2, v3, dep = x self.assertEqual(is_even(values1.get()), dependent.get())
def test_limited_gen(self): source_vals = list(range(4)) limit = 3 values = gen.IterValueGenerator('name', source_vals) values.set_limit(limit) produced_vals = [val for val in values] self.assertEqual(source_vals[:limit], produced_vals)
def test_dual_permuters(self): 'Test nested permuters' source_vals = [1, 2] vals1 = gen.IterValueGenerator('key', source_vals) vals2 = gen.IterValueGenerator('val', source_vals) produced_via_zips = [] produced_via_product = [] for x in gen.Zip('name', vals1): for y in gen.Zip('name', vals2): produced_via_zips.append(x + y) for x in gen.Product('name', vals1, vals2): produced_via_product.append(x) self.assertEqual(produced_via_zips, produced_via_product)
def test_basic_gen(self): 'Test a basic generator' source_vals = [1, 2, 3, 4] numbers = gen.IterValueGenerator('iter', source_vals) produced_vals = [] for x in numbers: produced_vals.append(x) self.assertEqual(produced_vals, source_vals)
def test_limited_zip(self): 'Test limits on a basic Zip iterator' source_vals = [1, 2, 3, 4] values = gen.IterValueGenerator('name', source_vals) produced_vals = [] for x in gen.Zip('name', values, limit=len(source_vals) - 1): produced_vals.append(x[0][1]) self.assertEqual(source_vals[:-1], produced_vals)
def test_dependent_values(self): 'Make sure dependent values are correctly resolved' def is_even(x): return x % 2 == 0 values = gen.IterValueGenerator('name', [1, 2, 3, 4]) dependent = gen.DependentValueGenerator('depends', target=values, action=is_even) for x in values: generated_val, generated_dependency = values.get(), dependent.get() self.assertEqual(generated_dependency, is_even(generated_val))
def test_repeated_gets(self): 'Make sure that calling get() twice on a generator does not advance it' def plus_one(x): return x + 1 values = gen.IterValueGenerator('name', [1, 2, 3, 4]) dependent = gen.DependentValueGenerator('dependent', target=values, action=plus_one) # Request an actual item next(iter(values)) values.get() first = dependent.get() second = dependent.get() self.assertEqual(first, second)
def _prototype_to_generator(descriptor, cls): 'Helper to map a descriptor to a protofuzz generator' _fd = D.FieldDescriptor generator = None ints32 = [ _fd.TYPE_INT32, _fd.TYPE_UINT32, _fd.TYPE_FIXED32, _fd.TYPE_SFIXED32, _fd.TYPE_SINT32 ] ints64 = [ _fd.TYPE_INT64, _fd.TYPE_UINT64, _fd.TYPE_FIXED64, _fd.TYPE_SFIXED64, _fd.TYPE_SINT64 ] ints_signed = [ _fd.TYPE_INT32, _fd.TYPE_SFIXED32, _fd.TYPE_SINT32, _fd.TYPE_INT64, _fd.TYPE_SFIXED64, _fd.TYPE_SINT64 ] if descriptor.type in ints32 + ints64: bitwidth = [32, 64][descriptor.type in ints64] unsigned = descriptor.type not in ints_signed generator = _int_generator(descriptor, bitwidth, unsigned) elif descriptor.type == _fd.TYPE_DOUBLE: generator = _float_generator(descriptor, 64) elif descriptor.type == _fd.TYPE_FLOAT: generator = _float_generator(descriptor, 32) elif descriptor.type == _fd.TYPE_STRING: generator = _string_generator(descriptor) elif descriptor.type == _fd.TYPE_BYTES: generator = _bytes_generator(descriptor) elif descriptor.type == _fd.TYPE_BOOL: generator = gen.IterValueGenerator(descriptor.name, [True, False]) elif descriptor.type == _fd.TYPE_ENUM: generator = _enum_generator(descriptor) elif descriptor.type == _fd.TYPE_MESSAGE: generator = descriptor_to_generator(descriptor.message_type, cls) generator.set_name(descriptor.name) else: raise RuntimeError("type {} unsupported".format(descriptor.type)) return generator
def _int_generator(descriptor, bitwidth, unsigned): 'Helper to create a basic integer value generator' vals = list(values.get_integers(bitwidth, unsigned)) return gen.IterValueGenerator(descriptor.name, vals)
def _bytes_generator(descriptor, max_length=0, limit=0): 'Helper to create bytes values. (Derived from string generator)' strs = values.get_strings(max_length, limit) vals = [bytes(_, 'utf-8') for _ in strs] return gen.IterValueGenerator(descriptor.name, vals)
def _float_generator(descriptor, bitwidth): 'Helper to create floating point values' return gen.IterValueGenerator(descriptor.name, values.get_floats(bitwidth))
def _enum_generator(descriptor): 'Helper to create protobuf enums' vals = descriptor.enum_type.values_by_number.keys() return gen.IterValueGenerator(descriptor.name, vals)
def test_gen_init(self): "Test that we can't get a value from a non-iterated generator" values = gen.IterValueGenerator('iter', [1, 2, 3, 4]) with self.assertRaises(RuntimeError): values.get()
def _string_generator(descriptor, max_length=0, limit=0): 'Helper to create a string generator' vals = list(values.get_strings(max_length, limit)) return gen.IterValueGenerator(descriptor.name, vals)