@@ -54,6 +54,9 @@ enum class Mutation : uint8_t {
54
54
55
55
using MutationBitset = std::bitset<static_cast <size_t >(Mutation::Last)>;
56
56
57
+ using Messages = std::vector<Message*>;
58
+ using ConstMessages = std::vector<const Message*>;
59
+
57
60
// Return random integer from [0, count)
58
61
size_t GetRandomIndex (RandomEngine* random, size_t count) {
59
62
assert (count > 0 );
@@ -173,25 +176,27 @@ class CanCopyAndDifferentField
173
176
class MutationSampler {
174
177
public:
175
178
MutationSampler (bool keep_initialized, MutationBitset allowed_mutations,
176
- RandomEngine* random, Message* message )
179
+ RandomEngine* random)
177
180
: keep_initialized_(keep_initialized),
178
181
allowed_mutations_ (allowed_mutations),
179
182
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) {}
186
184
187
185
// Returns selected field.
188
186
const FieldInstance& field () const { return sampler_.selected ().field ; }
189
187
190
188
// Returns selected mutation.
191
189
Mutation mutation () const { return sampler_.selected ().mutation ; }
192
190
193
- private:
194
191
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) {
195
200
const Descriptor* descriptor = message->GetDescriptor ();
196
201
const Reflection* reflection = message->GetReflection ();
197
202
@@ -256,9 +261,9 @@ class MutationSampler {
256
261
if (field->is_repeated ()) {
257
262
const int field_size = reflection->FieldSize (*message, field);
258
263
for (int j = 0 ; j < field_size; ++j)
259
- Sample (reflection->MutableRepeatedMessage (message, field, j));
264
+ SampleImpl (reflection->MutableRepeatedMessage (message, field, j));
260
265
} else if (reflection->HasField (*message, field)) {
261
- Sample (reflection->MutableMessage (message, field));
266
+ SampleImpl (reflection->MutableMessage (message, field));
262
267
}
263
268
}
264
269
}
@@ -289,13 +294,13 @@ class MutationSampler {
289
294
class DataSourceSampler {
290
295
public:
291
296
DataSourceSampler (const ConstFieldInstance& match, RandomEngine* random,
292
- int size_increase_hint, const Message& message )
297
+ int size_increase_hint)
293
298
: match_(match),
294
299
random_ (random),
295
300
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); }
299
304
300
305
// Returns selected field.
301
306
const ConstFieldInstance& field () const {
@@ -306,7 +311,7 @@ class DataSourceSampler {
306
311
bool IsEmpty () const { return sampler_.IsEmpty (); }
307
312
308
313
private:
309
- void Sample (const Message& message) {
314
+ void SampleImpl (const Message& message) {
310
315
const Descriptor* descriptor = message.GetDescriptor ();
311
316
const Reflection* reflection = message.GetReflection ();
312
317
@@ -317,10 +322,10 @@ class DataSourceSampler {
317
322
if (field->is_repeated ()) {
318
323
const int field_size = reflection->FieldSize (message, field);
319
324
for (int j = 0 ; j < field_size; ++j) {
320
- Sample (reflection->GetRepeatedMessage (message, field, j));
325
+ SampleImpl (reflection->GetRepeatedMessage (message, field, j));
321
326
}
322
327
} else if (reflection->HasField (message, field)) {
323
- Sample (reflection->GetMessage (message, field));
328
+ SampleImpl (reflection->GetMessage (message, field));
324
329
}
325
330
}
326
331
@@ -357,8 +362,8 @@ class DataSourceSampler {
357
362
358
363
class PostProcessing {
359
364
public:
360
- using PostProcessors = std::unordered_multimap< const protobuf::Descriptor*,
361
- Mutator::PostProcess>;
365
+ using PostProcessors =
366
+ std::unordered_multimap< const Descriptor*, Mutator::PostProcess>;
362
367
363
368
PostProcessing (bool keep_initialized, const PostProcessors& post_processors,
364
369
RandomEngine* random)
@@ -421,12 +426,12 @@ class PostProcessing {
421
426
class FieldMutator {
422
427
public:
423
428
FieldMutator (int size_increase_hint, bool enforce_changes,
424
- bool enforce_utf8_strings, const Message& source ,
429
+ bool enforce_utf8_strings, const ConstMessages& sources ,
425
430
Mutator* mutator)
426
431
: size_increase_hint_(size_increase_hint),
427
432
enforce_changes_ (enforce_changes),
428
433
enforce_utf8_strings_(enforce_utf8_strings),
429
- source_(source ),
434
+ sources_(sources ),
430
435
mutator_(mutator) {}
431
436
432
437
void Mutate (int32_t * value) const {
@@ -478,7 +483,8 @@ class FieldMutator {
478
483
assert (*message);
479
484
if (GetRandomBool (mutator_->random (), mutator_->random_to_default_ratio_ ))
480
485
return ;
481
- mutator_->MutateImpl (source_, message->get (), false , size_increase_hint_);
486
+ mutator_->MutateImpl (sources_, {message->get ()}, false ,
487
+ size_increase_hint_);
482
488
}
483
489
484
490
private:
@@ -498,7 +504,7 @@ class FieldMutator {
498
504
int size_increase_hint_;
499
505
size_t enforce_changes_;
500
506
bool enforce_utf8_strings_;
501
- const Message& source_ ;
507
+ const ConstMessages& sources_ ;
502
508
Mutator* mutator_;
503
509
};
504
510
@@ -507,10 +513,11 @@ namespace {
507
513
struct MutateField : public FieldFunction <MutateField> {
508
514
template <class T >
509
515
void ForType (const FieldInstance& field, int size_increase_hint,
510
- const Message& source , Mutator* mutator) const {
516
+ const ConstMessages& sources , Mutator* mutator) const {
511
517
T value;
512
518
field.Load (&value);
513
- FieldMutator (size_increase_hint, true , field.EnforceUtf8 (), source, mutator)
519
+ FieldMutator (size_increase_hint, true , field.EnforceUtf8 (), sources,
520
+ mutator)
514
521
.Mutate (&value);
515
522
field.Store (value);
516
523
}
@@ -520,12 +527,12 @@ struct CreateField : public FieldFunction<CreateField> {
520
527
public:
521
528
template <class T >
522
529
void ForType (const FieldInstance& field, int size_increase_hint,
523
- const Message& source , Mutator* mutator) const {
530
+ const ConstMessages& sources , Mutator* mutator) const {
524
531
T value;
525
532
field.GetDefault (&value);
526
533
FieldMutator field_mutator (size_increase_hint,
527
534
false /* defaults could be useful */ ,
528
- field.EnforceUtf8 (), source , mutator);
535
+ field.EnforceUtf8 (), sources , mutator);
529
536
field_mutator.Mutate (&value);
530
537
field.Create (value);
531
538
}
@@ -536,7 +543,10 @@ struct CreateField : public FieldFunction<CreateField> {
536
543
void Mutator::Seed (uint32_t value) { random_.seed (value); }
537
544
538
545
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 ,
540
550
static_cast <int >(max_size_hint) -
541
551
static_cast <int >(message->ByteSizeLong ()));
542
552
@@ -547,10 +557,13 @@ void Mutator::Mutate(Message* message, size_t max_size_hint) {
547
557
548
558
void Mutator::CrossOver (const Message& message1, Message* message2,
549
559
size_t max_size_hint) {
560
+ Messages messages;
561
+ messages.push_back (message2);
562
+ ConstMessages sources;
563
+ sources.push_back (&message1);
550
564
int size_increase_hint = static_cast <int >(max_size_hint) -
551
565
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);
554
567
555
568
PostProcessing (keep_initialized_, post_processors_, &random_)
556
569
.Run (message2, kMaxInitializeDepth );
@@ -562,7 +575,7 @@ void Mutator::RegisterPostProcessor(const Descriptor* desc,
562
575
post_processors_.emplace (desc, callback);
563
576
}
564
577
565
- bool Mutator::MutateImpl (const Message& source, Message* message ,
578
+ bool Mutator::MutateImpl (const ConstMessages& sources, const Messages& messages ,
566
579
bool copy_clone_only, int size_increase_hint) {
567
580
if (size_increase_hint > 0 ) size_increase_hint /= 2 ;
568
581
MutationBitset mutations;
@@ -575,32 +588,36 @@ bool Mutator::MutateImpl(const Message& source, Message* message,
575
588
mutations.set ();
576
589
}
577
590
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
+
579
594
// Don't try same mutation next time.
580
595
mutations[static_cast <size_t >(mutation.mutation ())] = false ;
581
596
switch (mutation.mutation ()) {
582
597
case Mutation::None:
583
598
return true ;
584
599
case Mutation::Add:
585
- CreateField ()(mutation.field (), size_increase_hint, source , this );
600
+ CreateField ()(mutation.field (), size_increase_hint, sources , this );
586
601
return true ;
587
602
case Mutation::Mutate:
588
- MutateField ()(mutation.field (), size_increase_hint, source , this );
603
+ MutateField ()(mutation.field (), size_increase_hint, sources , this );
589
604
return true ;
590
605
case Mutation::Delete:
591
606
DeleteField ()(mutation.field ());
592
607
return true ;
593
608
case Mutation::Clone: {
594
609
CreateDefaultField ()(mutation.field ());
595
610
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);
597
613
if (source_sampler.IsEmpty ()) return true ; // CreateField is enough.
598
614
CopyField ()(source_sampler.field (), mutation.field ());
599
615
return true ;
600
616
}
601
617
case Mutation::Copy: {
602
618
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);
604
621
if (source_sampler.IsEmpty ()) break ;
605
622
CopyField ()(source_sampler.field (), mutation.field ());
606
623
return true ;
0 commit comments