Skip to content

Commit f62086c

Browse files
committed
Accept arrays of messages in MutateImpl
For #151
1 parent 74afb61 commit f62086c

File tree

2 files changed

+55
-37
lines changed

2 files changed

+55
-37
lines changed

src/mutator.cc

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ enum class Mutation : uint8_t {
5454

5555
using MutationBitset = std::bitset<static_cast<size_t>(Mutation::Last)>;
5656

57+
using Messages = std::vector<Message*>;
58+
using ConstMessages = std::vector<const Message*>;
59+
5760
// Return random integer from [0, count)
5861
size_t GetRandomIndex(RandomEngine* random, size_t count) {
5962
assert(count > 0);
@@ -173,25 +176,27 @@ class CanCopyAndDifferentField
173176
class MutationSampler {
174177
public:
175178
MutationSampler(bool keep_initialized, MutationBitset allowed_mutations,
176-
RandomEngine* random, Message* message)
179+
RandomEngine* random)
177180
: keep_initialized_(keep_initialized),
178181
allowed_mutations_(allowed_mutations),
179182
random_(random),
180-
sampler_(random) {
181-
Sample(message);
182-
assert(mutation() != Mutation::None ||
183-
!allowed_mutations_[static_cast<size_t>(Mutation::Mutate)] ||
184-
message->GetDescriptor()->field_count() == 0);
185-
}
183+
sampler_(random) {}
186184

187185
// Returns selected field.
188186
const FieldInstance& field() const { return sampler_.selected().field; }
189187

190188
// Returns selected mutation.
191189
Mutation mutation() const { return sampler_.selected().mutation; }
192190

193-
private:
194191
void Sample(Message* message) {
192+
SampleImpl(message);
193+
assert(mutation() != Mutation::None ||
194+
!allowed_mutations_[static_cast<size_t>(Mutation::Mutate)] ||
195+
message->GetDescriptor()->field_count() == 0);
196+
}
197+
198+
private:
199+
void SampleImpl(Message* message) {
195200
const Descriptor* descriptor = message->GetDescriptor();
196201
const Reflection* reflection = message->GetReflection();
197202

@@ -256,9 +261,9 @@ class MutationSampler {
256261
if (field->is_repeated()) {
257262
const int field_size = reflection->FieldSize(*message, field);
258263
for (int j = 0; j < field_size; ++j)
259-
Sample(reflection->MutableRepeatedMessage(message, field, j));
264+
SampleImpl(reflection->MutableRepeatedMessage(message, field, j));
260265
} else if (reflection->HasField(*message, field)) {
261-
Sample(reflection->MutableMessage(message, field));
266+
SampleImpl(reflection->MutableMessage(message, field));
262267
}
263268
}
264269
}
@@ -289,13 +294,13 @@ class MutationSampler {
289294
class DataSourceSampler {
290295
public:
291296
DataSourceSampler(const ConstFieldInstance& match, RandomEngine* random,
292-
int size_increase_hint, const Message& message)
297+
int size_increase_hint)
293298
: match_(match),
294299
random_(random),
295300
size_increase_hint_(size_increase_hint),
296-
sampler_(random) {
297-
Sample(message);
298-
}
301+
sampler_(random) {}
302+
303+
void Sample(const Message& message) { SampleImpl(message); }
299304

300305
// Returns selected field.
301306
const ConstFieldInstance& field() const {
@@ -306,7 +311,7 @@ class DataSourceSampler {
306311
bool IsEmpty() const { return sampler_.IsEmpty(); }
307312

308313
private:
309-
void Sample(const Message& message) {
314+
void SampleImpl(const Message& message) {
310315
const Descriptor* descriptor = message.GetDescriptor();
311316
const Reflection* reflection = message.GetReflection();
312317

@@ -317,10 +322,10 @@ class DataSourceSampler {
317322
if (field->is_repeated()) {
318323
const int field_size = reflection->FieldSize(message, field);
319324
for (int j = 0; j < field_size; ++j) {
320-
Sample(reflection->GetRepeatedMessage(message, field, j));
325+
SampleImpl(reflection->GetRepeatedMessage(message, field, j));
321326
}
322327
} else if (reflection->HasField(message, field)) {
323-
Sample(reflection->GetMessage(message, field));
328+
SampleImpl(reflection->GetMessage(message, field));
324329
}
325330
}
326331

@@ -357,8 +362,8 @@ class DataSourceSampler {
357362

358363
class PostProcessing {
359364
public:
360-
using PostProcessors = std::unordered_multimap<const protobuf::Descriptor*,
361-
Mutator::PostProcess>;
365+
using PostProcessors =
366+
std::unordered_multimap<const Descriptor*, Mutator::PostProcess>;
362367

363368
PostProcessing(bool keep_initialized, const PostProcessors& post_processors,
364369
RandomEngine* random)
@@ -421,12 +426,12 @@ class PostProcessing {
421426
class FieldMutator {
422427
public:
423428
FieldMutator(int size_increase_hint, bool enforce_changes,
424-
bool enforce_utf8_strings, const Message& source,
429+
bool enforce_utf8_strings, const ConstMessages& sources,
425430
Mutator* mutator)
426431
: size_increase_hint_(size_increase_hint),
427432
enforce_changes_(enforce_changes),
428433
enforce_utf8_strings_(enforce_utf8_strings),
429-
source_(source),
434+
sources_(sources),
430435
mutator_(mutator) {}
431436

432437
void Mutate(int32_t* value) const {
@@ -478,7 +483,8 @@ class FieldMutator {
478483
assert(*message);
479484
if (GetRandomBool(mutator_->random(), mutator_->random_to_default_ratio_))
480485
return;
481-
mutator_->MutateImpl(source_, message->get(), false, size_increase_hint_);
486+
mutator_->MutateImpl(sources_, {message->get()}, false,
487+
size_increase_hint_);
482488
}
483489

484490
private:
@@ -498,7 +504,7 @@ class FieldMutator {
498504
int size_increase_hint_;
499505
size_t enforce_changes_;
500506
bool enforce_utf8_strings_;
501-
const Message& source_;
507+
const ConstMessages& sources_;
502508
Mutator* mutator_;
503509
};
504510

@@ -507,10 +513,11 @@ namespace {
507513
struct MutateField : public FieldFunction<MutateField> {
508514
template <class T>
509515
void ForType(const FieldInstance& field, int size_increase_hint,
510-
const Message& source, Mutator* mutator) const {
516+
const ConstMessages& sources, Mutator* mutator) const {
511517
T value;
512518
field.Load(&value);
513-
FieldMutator(size_increase_hint, true, field.EnforceUtf8(), source, mutator)
519+
FieldMutator(size_increase_hint, true, field.EnforceUtf8(), sources,
520+
mutator)
514521
.Mutate(&value);
515522
field.Store(value);
516523
}
@@ -520,12 +527,12 @@ struct CreateField : public FieldFunction<CreateField> {
520527
public:
521528
template <class T>
522529
void ForType(const FieldInstance& field, int size_increase_hint,
523-
const Message& source, Mutator* mutator) const {
530+
const ConstMessages& sources, Mutator* mutator) const {
524531
T value;
525532
field.GetDefault(&value);
526533
FieldMutator field_mutator(size_increase_hint,
527534
false /* defaults could be useful */,
528-
field.EnforceUtf8(), source, mutator);
535+
field.EnforceUtf8(), sources, mutator);
529536
field_mutator.Mutate(&value);
530537
field.Create(value);
531538
}
@@ -536,7 +543,10 @@ struct CreateField : public FieldFunction<CreateField> {
536543
void Mutator::Seed(uint32_t value) { random_.seed(value); }
537544

538545
void Mutator::Mutate(Message* message, size_t max_size_hint) {
539-
MutateImpl(*message, message, false,
546+
Messages messages;
547+
messages.push_back(message);
548+
ConstMessages sources(messages.begin(), messages.end());
549+
MutateImpl(sources, messages, false,
540550
static_cast<int>(max_size_hint) -
541551
static_cast<int>(message->ByteSizeLong()));
542552

@@ -547,10 +557,13 @@ void Mutator::Mutate(Message* message, size_t max_size_hint) {
547557

548558
void Mutator::CrossOver(const Message& message1, Message* message2,
549559
size_t max_size_hint) {
560+
Messages messages;
561+
messages.push_back(message2);
562+
ConstMessages sources;
563+
sources.push_back(&message1);
550564
int size_increase_hint = static_cast<int>(max_size_hint) -
551565
static_cast<int>(message2->ByteSizeLong());
552-
MutateImpl(message1, message2, true, size_increase_hint) ||
553-
MutateImpl(*message2, message2, true, size_increase_hint);
566+
MutateImpl(sources, messages, true, size_increase_hint);
554567

555568
PostProcessing(keep_initialized_, post_processors_, &random_)
556569
.Run(message2, kMaxInitializeDepth);
@@ -562,7 +575,7 @@ void Mutator::RegisterPostProcessor(const Descriptor* desc,
562575
post_processors_.emplace(desc, callback);
563576
}
564577

565-
bool Mutator::MutateImpl(const Message& source, Message* message,
578+
bool Mutator::MutateImpl(const ConstMessages& sources, const Messages& messages,
566579
bool copy_clone_only, int size_increase_hint) {
567580
if (size_increase_hint > 0) size_increase_hint /= 2;
568581
MutationBitset mutations;
@@ -575,32 +588,36 @@ bool Mutator::MutateImpl(const Message& source, Message* message,
575588
mutations.set();
576589
}
577590
while (mutations.any()) {
578-
MutationSampler mutation(keep_initialized_, mutations, &random_, message);
591+
MutationSampler mutation(keep_initialized_, mutations, &random_);
592+
for (Message* message : messages) mutation.Sample(message);
593+
579594
// Don't try same mutation next time.
580595
mutations[static_cast<size_t>(mutation.mutation())] = false;
581596
switch (mutation.mutation()) {
582597
case Mutation::None:
583598
return true;
584599
case Mutation::Add:
585-
CreateField()(mutation.field(), size_increase_hint, source, this);
600+
CreateField()(mutation.field(), size_increase_hint, sources, this);
586601
return true;
587602
case Mutation::Mutate:
588-
MutateField()(mutation.field(), size_increase_hint, source, this);
603+
MutateField()(mutation.field(), size_increase_hint, sources, this);
589604
return true;
590605
case Mutation::Delete:
591606
DeleteField()(mutation.field());
592607
return true;
593608
case Mutation::Clone: {
594609
CreateDefaultField()(mutation.field());
595610
DataSourceSampler source_sampler(mutation.field(), &random_,
596-
size_increase_hint, source);
611+
size_increase_hint);
612+
for (const Message* source : sources) source_sampler.Sample(*source);
597613
if (source_sampler.IsEmpty()) return true; // CreateField is enough.
598614
CopyField()(source_sampler.field(), mutation.field());
599615
return true;
600616
}
601617
case Mutation::Copy: {
602618
DataSourceSampler source_sampler(mutation.field(), &random_,
603-
size_increase_hint, source);
619+
size_increase_hint);
620+
for (const Message* source : sources) source_sampler.Sample(*source);
604621
if (source_sampler.IsEmpty()) break;
605622
CopyField()(source_sampler.field(), mutation.field());
606623
return true;

src/mutator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ class Mutator {
8989
private:
9090
friend class FieldMutator;
9191
friend class TestMutator;
92-
bool MutateImpl(const protobuf::Message& source, protobuf::Message* message,
92+
bool MutateImpl(const std::vector<const protobuf::Message*>& sources,
93+
const std::vector<protobuf::Message*>& messages,
9394
bool copy_clone_only, int size_increase_hint);
9495
std::string MutateUtf8String(const std::string& value,
9596
int size_increase_hint);

0 commit comments

Comments
 (0)