blob: b7cf7e01019506fc5348d5e1eb43b1b340421e22 [file] [log] [blame]
Vitaly Buka00b61072016-10-19 23:22:511// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Vitaly Buka9dd2f8e2017-01-13 08:48:3115#include "src/protobuf_mutator.h"
Vitaly Buka00b61072016-10-19 23:22:5116
Vitaly Buka781853c2016-11-22 07:09:3517#include <algorithm>
Vitaly Buka0e17fd72016-11-18 18:02:4618#include <iostream>
19#include <map>
Vitaly Buka781853c2016-11-22 07:09:3520#include <random>
Vitaly Buka0e17fd72016-11-18 18:02:4621#include <string>
Vitaly Buka00b61072016-10-19 23:22:5122
Vitaly Buka9dd2f8e2017-01-13 08:48:3123#include "src/field_instance.h"
24#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 23:22:5125
Vitaly Bukaf86815c2017-02-27 22:19:1926namespace protobuf_mutator {
27
Vitaly Buka6c6dbbe2017-02-22 21:58:2428using protobuf::Descriptor;
29using protobuf::EnumDescriptor;
30using protobuf::EnumValueDescriptor;
31using protobuf::FieldDescriptor;
32using protobuf::Message;
33using protobuf::OneofDescriptor;
34using protobuf::Reflection;
Vitaly Buka0e17fd72016-11-18 18:02:4635
36namespace {
37
Vitaly Buka72019dc2016-12-15 03:17:2438const size_t kMaxInitializeDepth = 32;
39const size_t kDeletionThreshold = 128;
40const uint64_t kMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 18:02:4641
42enum class Mutation {
Vitaly Buka30de3092016-11-18 19:39:0743 None,
Vitaly Buka4af611d2016-12-04 02:57:3244 Add, // Adds new field with default value.
45 Mutate, // Mutates field contents.
46 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-07 00:53:5647 Copy, // Copy values copied from another field.
Vitaly Buka4af611d2016-12-04 02:57:3248
Vitaly Buka432b5452016-12-09 22:42:0949 // TODO(vitalybuka):
50 // Clone, // Adds new field with value copied from another field.
Vitaly Buka0e17fd72016-11-18 18:02:4651};
52
Vitaly Bukab592ff02017-03-03 22:35:5253// Return random integer from [0, count)
54size_t GetRandomIndex(ProtobufMutator::RandomEngine* random, size_t count) {
55 assert(count > 0);
56 if (count == 1) return 0;
57 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
58}
59
Vitaly Buka4af611d2016-12-04 02:57:3260// Flips random bit in the buffer.
61void FlipBit(size_t size, uint8_t* bytes,
62 ProtobufMutator::RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 22:35:5263 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-04 02:57:3264 bytes[bit / 8] ^= (1u << (bit % 8));
65}
Vitaly Buka781853c2016-11-22 07:09:3566
Vitaly Buka4af611d2016-12-04 02:57:3267// Flips random bit in the value.
68template <class T>
69T FlipBit(T value, ProtobufMutator::RandomEngine* random) {
70 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
71 return value;
72}
Vitaly Buka781853c2016-11-22 07:09:3573
Vitaly Bukabeb90802017-02-28 23:28:1074// Return true with probability about 1-of-n.
75bool GetRandomBool(ProtobufMutator::RandomEngine* random, size_t n = 2) {
76 return GetRandomIndex(random, n) == 0;
77}
78
Vitaly Buka91ad7b02016-12-12 23:41:4179struct CreateDefaultFieldTransformation {
80 template <class T>
81 void Apply(const FieldInstance& field) const {
82 T value;
83 field.GetDefault(&value);
84 field.Create(value);
Vitaly Bukabec52222016-12-09 22:29:3285 }
Vitaly Buka91ad7b02016-12-12 23:41:4186};
Vitaly Bukabec52222016-12-09 22:29:3287
Vitaly Buka91ad7b02016-12-12 23:41:4188struct DeleteFieldTransformation {
89 template <class T>
90 void Apply(const FieldInstance& field) const {
91 field.Delete();
Vitaly Bukabec52222016-12-09 22:29:3292 }
Vitaly Bukabec52222016-12-09 22:29:3293};
94
Vitaly Bukaa3e59c72016-12-07 00:53:5695struct CopyFieldTransformation {
Vitaly Buka88712862017-02-27 06:21:3096 explicit CopyFieldTransformation(const ConstFieldInstance& field)
Vitaly Buka72019dc2016-12-15 03:17:2497 : source(field) {}
Vitaly Bukaa3e59c72016-12-07 00:53:5698
99 template <class T>
Vitaly Buka72019dc2016-12-15 03:17:24100 void Apply(const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-07 00:53:56101 T value;
102 source.Load(&value);
103 field.Store(value);
104 }
105
Vitaly Buka88712862017-02-27 06:21:30106 ConstFieldInstance source;
Vitaly Bukaa3e59c72016-12-07 00:53:56107};
108
Vitaly Bukaadfc27c2017-02-27 06:36:36109struct AppendFieldTransformation {
110 explicit AppendFieldTransformation(const ConstFieldInstance& field)
111 : source(field) {}
112
113 template <class T>
114 void Apply(const FieldInstance& field) const {
115 T value;
116 source.Load(&value);
117 field.Create(value);
118 }
119
120 ConstFieldInstance source;
121};
122
Vitaly Buka4af611d2016-12-04 02:57:32123// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-22 07:09:35124class MutationSampler {
Vitaly Bukac9d22482016-11-21 21:29:17125 public:
Vitaly Buka72019dc2016-12-15 03:17:24126 MutationSampler(bool keep_initialized, size_t size_increase_hint,
Vitaly Buka781853c2016-11-22 07:09:35127 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-04 02:57:32128 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka72019dc2016-12-15 03:17:24129 if (size_increase_hint < kDeletionThreshold) {
Vitaly Buka4af611d2016-12-04 02:57:32130 // Avoid adding new field and prefer deleting fields if we getting close
131 // to the limit.
Vitaly Buka72019dc2016-12-15 03:17:24132 float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
133 add_weight_ *= adjustment;
134 delete_weight_ *= 1 - adjustment;
Vitaly Buka781853c2016-11-22 07:09:35135 }
136 Sample(message);
Vitaly Bukabec52222016-12-09 22:29:32137 assert(mutation() != Mutation::None);
Vitaly Bukac9d22482016-11-21 21:29:17138 }
139
Vitaly Buka4af611d2016-12-04 02:57:32140 // Returns selected field.
Vitaly Bukabec52222016-12-09 22:29:32141 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-04 02:57:32142
143 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 22:42:09144 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-04 02:57:32145
146 private:
Vitaly Buka781853c2016-11-22 07:09:35147 void Sample(Message* message) {
148 const Descriptor* descriptor = message->GetDescriptor();
149 const Reflection* reflection = message->GetReflection();
150
151 int field_count = descriptor->field_count();
152 for (int i = 0; i < field_count; ++i) {
153 const FieldDescriptor* field = descriptor->field(i);
154 if (const OneofDescriptor* oneof = field->containing_oneof()) {
155 // Handle entire oneof group on the first field.
156 if (field->index_in_oneof() == 0) {
Vitaly Buka4af611d2016-12-04 02:57:32157 sampler_.Try(
158 add_weight_,
Vitaly Bukabec52222016-12-09 22:29:32159 {{message,
160 oneof->field(GetRandomIndex(random_, oneof->field_count()))},
Vitaly Buka4af611d2016-12-04 02:57:32161 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35162 if (const FieldDescriptor* field =
163 reflection->GetOneofFieldDescriptor(*message, oneof)) {
Vitaly Buka4af611d2016-12-04 02:57:32164 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32165 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
166 sampler_.Try(delete_weight_, {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24167 sampler_.Try(GetCopyWeight(field),
168 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35169 }
170 }
171 } else {
172 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 22:29:32173 int field_size = reflection->FieldSize(*message, field);
174 sampler_.Try(add_weight_, {{message, field,
175 GetRandomIndex(random_, field_size + 1)},
176 Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35177
Vitaly Bukabec52222016-12-09 22:29:32178 if (field_size) {
179 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka4af611d2016-12-04 02:57:32180 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32181 sampler_.Try(kMutateWeight,
182 {{message, field, random_index}, Mutation::Mutate});
183 sampler_.Try(delete_weight_,
184 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24185 sampler_.Try(GetCopyWeight(field),
Vitaly Bukaa3e59c72016-12-07 00:53:56186 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35187 }
188 } else {
189 if (reflection->HasField(*message, field)) {
Vitaly Buka4af611d2016-12-04 02:57:32190 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 22:29:32191 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
Vitaly Buka4af611d2016-12-04 02:57:32192 if ((!field->is_required() || !keep_initialized_))
Vitaly Bukabec52222016-12-09 22:29:32193 sampler_.Try(delete_weight_,
194 {{message, field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-15 03:17:24195 sampler_.Try(GetCopyWeight(field),
196 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-22 07:09:35197 } else {
Vitaly Bukabec52222016-12-09 22:29:32198 sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-22 07:09:35199 }
200 }
201 }
202
203 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
204 if (field->is_repeated()) {
205 const int field_size = reflection->FieldSize(*message, field);
206 for (int j = 0; j < field_size; ++j)
207 Sample(reflection->MutableRepeatedMessage(message, field, j));
208 } else if (reflection->HasField(*message, field)) {
209 Sample(reflection->MutableMessage(message, field));
210 }
211 }
212 }
213 }
214
Vitaly Buka72019dc2016-12-15 03:17:24215 uint64_t GetCopyWeight(const FieldDescriptor* field) const {
216 // Coping sub-messages can increase size significantly.
217 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
218 ? add_weight_
219 : kMutateWeight;
220 }
221
Vitaly Buka781853c2016-11-22 07:09:35222 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-04 02:57:32223
224 // Adding and deleting are intrusive and expensive mutations, we'd like to do
Vitaly Buka432b5452016-12-09 22:42:09225 // them less often than field mutations.
Vitaly Buka781853c2016-11-22 07:09:35226 uint64_t add_weight_ = kMutateWeight / 10;
227 uint64_t delete_weight_ = kMutateWeight / 10;
Vitaly Buka781853c2016-11-22 07:09:35228
Vitaly Buka4af611d2016-12-04 02:57:32229 ProtobufMutator::RandomEngine* random_;
230
231 struct Result {
Vitaly Buka91ad7b02016-12-12 23:41:41232 Result() = default;
Vitaly Bukabec52222016-12-09 22:29:32233 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 23:41:41234
Vitaly Bukabec52222016-12-09 22:29:32235 FieldInstance field;
236 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-04 02:57:32237 };
238 WeightedReservoirSampler<Result, ProtobufMutator::RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 21:29:17239};
240
Vitaly Bukaa3e59c72016-12-07 00:53:56241// Selects random field of compatible type to use for clone mutations.
242class DataSourceSampler {
243 public:
Vitaly Buka88712862017-02-27 06:21:30244 DataSourceSampler(const ConstFieldInstance& match,
Vitaly Buka72019dc2016-12-15 03:17:24245 ProtobufMutator::RandomEngine* random, Message* message)
Vitaly Bukaa3e59c72016-12-07 00:53:56246 : match_(match), random_(random), sampler_(random) {
247 Sample(message);
248 }
249
250 // Returns selected field.
Vitaly Buka88712862017-02-27 06:21:30251 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-15 03:17:24252 assert(!IsEmpty());
253 return sampler_.selected();
254 }
255
256 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-07 00:53:56257
258 private:
259 void Sample(Message* message) {
260 const Descriptor* descriptor = message->GetDescriptor();
261 const Reflection* reflection = message->GetReflection();
262
263 int field_count = descriptor->field_count();
264 for (int i = 0; i < field_count; ++i) {
265 const FieldDescriptor* field = descriptor->field(i);
266 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
267 if (field->is_repeated()) {
268 const int field_size = reflection->FieldSize(*message, field);
269 for (int j = 0; j < field_size; ++j) {
270 Sample(reflection->MutableRepeatedMessage(message, field, j));
271 }
272 } else if (reflection->HasField(*message, field)) {
273 Sample(reflection->MutableMessage(message, field));
274 }
275 }
276
277 if (field->cpp_type() != match_.cpp_type()) continue;
278 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
279 if (field->enum_type() != match_.enum_type()) continue;
280 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
281 if (field->message_type() != match_.message_type()) continue;
282 }
283
284 // TODO(vitalybuka) : make sure that values are different
285 if (field->is_repeated()) {
286 if (int field_size = reflection->FieldSize(*message, field)) {
287 sampler_.Try(field_size,
288 {message, field, GetRandomIndex(random_, field_size)});
289 }
290 } else {
291 if (reflection->HasField(*message, field)) {
292 sampler_.Try(1, {message, field});
293 }
294 }
295 }
296 }
297
Vitaly Buka88712862017-02-27 06:21:30298 ConstFieldInstance match_;
Vitaly Bukaa3e59c72016-12-07 00:53:56299 ProtobufMutator::RandomEngine* random_;
300
Vitaly Buka88712862017-02-27 06:21:30301 WeightedReservoirSampler<ConstFieldInstance, ProtobufMutator::RandomEngine>
Vitaly Buka72019dc2016-12-15 03:17:24302 sampler_;
Vitaly Bukaa3e59c72016-12-07 00:53:56303};
304
Vitaly Buka0e17fd72016-11-18 18:02:46305} // namespace
306
Vitaly Buka5d013202017-02-25 00:50:11307class FieldMutator {
Vitaly Buka432b5452016-12-09 22:42:09308 public:
Vitaly Buka5d013202017-02-25 00:50:11309 FieldMutator(size_t size_increase_hint, ProtobufMutator* mutator)
310 : size_increase_hint_(size_increase_hint), mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 23:41:41311
Vitaly Buka91ad7b02016-12-12 23:41:41312 void Mutate(int32_t* value) const { *value = mutator_->MutateInt32(*value); }
313
314 void Mutate(int64_t* value) const { *value = mutator_->MutateInt64(*value); }
315
316 void Mutate(uint32_t* value) const {
317 *value = mutator_->MutateUInt32(*value);
318 }
319
320 void Mutate(uint64_t* value) const {
321 *value = mutator_->MutateUInt64(*value);
322 }
323
324 void Mutate(float* value) const { *value = mutator_->MutateFloat(*value); }
325
326 void Mutate(double* value) const { *value = mutator_->MutateDouble(*value); }
327
328 void Mutate(bool* value) const { *value = mutator_->MutateBool(*value); }
329
330 void Mutate(FieldInstance::Enum* value) const {
331 value->index = mutator_->MutateEnum(value->index, value->count);
332 assert(value->index < value->count);
333 }
334
335 void Mutate(std::string* value) const {
Vitaly Buka5d013202017-02-25 00:50:11336 *value = mutator_->MutateString(*value, size_increase_hint_);
Vitaly Buka91ad7b02016-12-12 23:41:41337 }
338
Vitaly Buka6c6dbbe2017-02-22 21:58:24339 void Mutate(std::unique_ptr<Message>*) const {
Vitaly Buka6c6dbbe2017-02-22 21:58:24340 }
Vitaly Buka432b5452016-12-09 22:42:09341
Vitaly Buka5d013202017-02-25 00:50:11342 private:
343 size_t size_increase_hint_;
Vitaly Buka432b5452016-12-09 22:42:09344 ProtobufMutator* mutator_;
Vitaly Buka432b5452016-12-09 22:42:09345};
346
Vitaly Buka5d013202017-02-25 00:50:11347namespace {
348
349class MutateTransformation {
350 public:
351 MutateTransformation(size_t size_increase_hint, ProtobufMutator* mutator)
352 : mutator_(size_increase_hint, mutator) {}
353
354 template <class T>
355 void Apply(const FieldInstance& field) const {
356 T value;
357 field.Load(&value);
358 mutator_.Mutate(&value);
359 field.Store(value);
360 }
361
362 private:
363 FieldMutator mutator_;
364};
365
366class CreateFieldTransformation {
367 public:
368 CreateFieldTransformation(size_t size_increase_hint, ProtobufMutator* mutator)
369 : mutator_(size_increase_hint, mutator) {}
370
371 template <class T>
372 void Apply(const FieldInstance& field) const {
373 T value;
374 field.GetDefault(&value);
375 mutator_.Mutate(&value);
376 field.Create(value);
377 }
378
379 private:
380 FieldMutator mutator_;
381};
382
383} // namespace
384
Vitaly Bukaba129722016-12-15 01:29:15385ProtobufMutator::ProtobufMutator(uint32_t seed) : random_(seed) {}
Vitaly Buka432b5452016-12-09 22:42:09386
Vitaly Buka72019dc2016-12-15 03:17:24387void ProtobufMutator::Mutate(Message* message, size_t size_increase_hint) {
388 MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
389 message);
Vitaly Buka781853c2016-11-22 07:09:35390 switch (mutation.mutation()) {
391 case Mutation::None:
392 break;
393 case Mutation::Add:
Vitaly Bukabeb90802017-02-28 23:28:10394 if (GetRandomBool(&random_)) {
Vitaly Buka5d013202017-02-25 00:50:11395 mutation.field().Apply(
Vitaly Buka35df2e42017-02-25 09:17:25396 CreateFieldTransformation(size_increase_hint / 2, this));
Vitaly Buka5d013202017-02-25 00:50:11397 } else {
398 mutation.field().Apply(CreateDefaultFieldTransformation());
399 }
Vitaly Buka781853c2016-11-22 07:09:35400 break;
401 case Mutation::Mutate:
Vitaly Buka72019dc2016-12-15 03:17:24402 mutation.field().Apply(
Vitaly Buka35df2e42017-02-25 09:17:25403 MutateTransformation(size_increase_hint / 2, this));
Vitaly Buka781853c2016-11-22 07:09:35404 break;
405 case Mutation::Delete:
Vitaly Buka91ad7b02016-12-12 23:41:41406 mutation.field().Apply(DeleteFieldTransformation());
Vitaly Buka781853c2016-11-22 07:09:35407 break;
Vitaly Bukaa3e59c72016-12-07 00:53:56408 case Mutation::Copy: {
409 DataSourceSampler source(mutation.field(), &random_, message);
Vitaly Buka72019dc2016-12-15 03:17:24410 if (source.IsEmpty()) {
Vitaly Bukaa3e59c72016-12-07 00:53:56411 // Fallback to message deletion.
412 mutation.field().Apply(DeleteFieldTransformation());
413 break;
414 }
Vitaly Bukaa3e59c72016-12-07 00:53:56415 mutation.field().Apply(CopyFieldTransformation(source.field()));
416 break;
417 }
Vitaly Buka781853c2016-11-22 07:09:35418 default:
Vitaly Buka6c6dbbe2017-02-22 21:58:24419 assert(false && "unexpected mutation");
Vitaly Buka0e17fd72016-11-18 18:02:46420 }
421
Vitaly Buka781853c2016-11-22 07:09:35422 if (keep_initialized_ && !message->IsInitialized()) {
423 InitializeMessage(message, kMaxInitializeDepth);
424 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 18:02:46425 }
Vitaly Buka00b61072016-10-19 23:22:51426}
427
Vitaly Bukaadfc27c2017-02-27 06:36:36428void ProtobufMutator::CrossOver(const protobuf::Message& message1,
429 protobuf::Message* message2) {
430 CrossOverImpl(message1, message2);
431
432 if (keep_initialized_ && !message2->IsInitialized()) {
433 InitializeMessage(message2, kMaxInitializeDepth);
434 assert(message2->IsInitialized());
435 }
436}
437
438void ProtobufMutator::CrossOverImpl(const protobuf::Message& message1,
439 protobuf::Message* message2) {
440 const Descriptor* descriptor = message2->GetDescriptor();
441 const Reflection* reflection = message2->GetReflection();
442 assert(message1.GetDescriptor() == descriptor);
443 assert(message1.GetReflection() == reflection);
444
445 for (int i = 0; i < descriptor->field_count(); ++i) {
446 const FieldDescriptor* field = descriptor->field(i);
447
448 if (field->is_repeated()) {
449 const int field_size1 = reflection->FieldSize(message1, field);
450 int field_size2 = reflection->FieldSize(*message2, field);
451 for (int j = 0; j < field_size1; ++j) {
452 ConstFieldInstance source(&message1, field, j);
453 FieldInstance destination(message2, field, field_size2++);
454 destination.Apply(AppendFieldTransformation(source));
455 }
456
457 assert(field_size2 == reflection->FieldSize(*message2, field));
458
459 // Shuffle
460 for (int j = 0; j < field_size2; ++j) {
461 if (int k = GetRandomIndex(&random_, field_size2 - j)) {
462 reflection->SwapElements(message2, field, j, j + k);
463 }
464 }
465
466 int keep = GetRandomIndex(&random_, field_size2 + 1);
467
468 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
469 int remove = field_size2 - keep;
470 // Cross some message to keep with messages to remove.
471 int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
472 for (int j = 0; j < cross; ++j) {
473 int k = GetRandomIndex(&random_, keep);
474 int r = keep + GetRandomIndex(&random_, remove);
475 assert(k != r);
476 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
477 reflection->MutableRepeatedMessage(message2, field, k));
478 }
479 }
480
481 for (int j = keep; j < field_size2; ++j)
482 reflection->RemoveLast(message2, field);
483 assert(keep == reflection->FieldSize(*message2, field));
484
485 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
486 if (!reflection->HasField(message1, field)) {
Vitaly Bukabeb90802017-02-28 23:28:10487 if (GetRandomBool(&random_))
Vitaly Bukaadfc27c2017-02-27 06:36:36488 FieldInstance(message2, field).Apply(DeleteFieldTransformation());
489 } else if (!reflection->HasField(*message2, field)) {
Vitaly Bukabeb90802017-02-28 23:28:10490 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36491 ConstFieldInstance source(&message1, field);
492 FieldInstance(message2, field).Apply(CopyFieldTransformation(source));
493 }
494 } else {
495 CrossOverImpl(reflection->GetMessage(message1, field),
496 reflection->MutableMessage(message2, field));
497 }
498 } else {
Vitaly Bukabeb90802017-02-28 23:28:10499 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-27 06:36:36500 if (reflection->HasField(message1, field)) {
501 ConstFieldInstance source(&message1, field);
502 FieldInstance(message2, field).Apply(CopyFieldTransformation(source));
503 } else {
504 FieldInstance(message2, field).Apply(DeleteFieldTransformation());
505 }
506 }
507 }
508 }
509}
510
Vitaly Buka72019dc2016-12-15 03:17:24511void ProtobufMutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-22 07:09:35512 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 22:42:09513 // It's pointless but possible to have infinite recursion of required
514 // messages.
515 assert(max_depth);
Vitaly Buka13245af2016-11-18 21:20:12516 const Descriptor* descriptor = message->GetDescriptor();
517 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 21:20:12518 for (int i = 0; i < descriptor->field_count(); ++i) {
519 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 23:41:41520 if (field->is_required() && !reflection->HasField(*message, field))
521 FieldInstance(message, field).Apply(CreateDefaultFieldTransformation());
Vitaly Buka13245af2016-11-18 21:20:12522
Vitaly Buka781853c2016-11-22 07:09:35523 if (max_depth > 0 &&
524 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-19 00:34:09525 if (field->is_repeated()) {
526 const int field_size = reflection->FieldSize(*message, field);
527 for (int j = 0; j < field_size; ++j) {
528 Message* nested_message =
529 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-22 07:09:35530 if (!nested_message->IsInitialized())
531 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-19 00:34:09532 }
533 } else if (reflection->HasField(*message, field)) {
534 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-22 07:09:35535 if (!nested_message->IsInitialized())
536 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 21:20:12537 }
538 }
539 }
540}
Vitaly Buka4af611d2016-12-04 02:57:32541
542int32_t ProtobufMutator::MutateInt32(int32_t value) {
543 return FlipBit(value, &random_);
544}
545
546int64_t ProtobufMutator::MutateInt64(int64_t value) {
547 return FlipBit(value, &random_);
548}
549
550uint32_t ProtobufMutator::MutateUInt32(uint32_t value) {
551 return FlipBit(value, &random_);
552}
553
554uint64_t ProtobufMutator::MutateUInt64(uint64_t value) {
555 return FlipBit(value, &random_);
556}
557
558float ProtobufMutator::MutateFloat(float value) {
559 return FlipBit(value, &random_);
560}
561
562double ProtobufMutator::MutateDouble(double value) {
563 return FlipBit(value, &random_);
564}
565
Vitaly Bukabeb90802017-02-28 23:28:10566bool ProtobufMutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-04 02:57:32567
568size_t ProtobufMutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukabeb90802017-02-28 23:28:10569 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-04 02:57:32570}
571
572std::string ProtobufMutator::MutateString(const std::string& value,
Vitaly Buka5d013202017-02-25 00:50:11573 size_t size_increase_hint) {
Vitaly Buka4af611d2016-12-04 02:57:32574 std::string result = value;
Vitaly Buka5d013202017-02-25 00:50:11575
Vitaly Bukabeb90802017-02-28 23:28:10576 while (!result.empty() && GetRandomBool(&random_)) {
Vitaly Buka432b5452016-12-09 22:42:09577 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 22:42:09578 }
579
Vitaly Bukabeb90802017-02-28 23:28:10580 while (result.size() < size_increase_hint && GetRandomBool(&random_)) {
Vitaly Buka432b5452016-12-09 22:42:09581 size_t index = GetRandomIndex(&random_, result.size() + 1);
Vitaly Buka5d013202017-02-25 00:50:11582 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 22:42:09583 }
584
Vitaly Buka4af611d2016-12-04 02:57:32585 if (!result.empty())
586 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
587 return result;
588}
Vitaly Buka432b5452016-12-09 22:42:09589
590} // namespace protobuf_mutator