blob: d3a71dabf5e5aac778bb4b9a92cc86ac13fdad82 [file] [log] [blame]
Vitaly Buka00b61072016-10-19 16:22:51 -07001// 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 Bukaf90698f2017-03-01 15:46:58 -080015#include "src/mutator.h"
Vitaly Buka00b61072016-10-19 16:22:51 -070016
Vitaly Buka781853c2016-11-21 23:09:35 -080017#include <algorithm>
Vitaly Buka0e17fd72016-11-18 10:02:46 -080018#include <iostream>
19#include <map>
Vitaly Buka781853c2016-11-21 23:09:35 -080020#include <random>
Vitaly Buka0e17fd72016-11-18 10:02:46 -080021#include <string>
Vitaly Buka00b61072016-10-19 16:22:51 -070022
Vitaly Buka9dd2f8e2017-01-13 00:48:31 -080023#include "src/field_instance.h"
24#include "src/weighted_reservoir_sampler.h"
Vitaly Buka00b61072016-10-19 16:22:51 -070025
Vitaly Bukaf86815c2017-02-27 14:19:19 -080026namespace protobuf_mutator {
27
Vitaly Buka6c6dbbe2017-02-22 13:58:24 -080028using protobuf::Descriptor;
29using protobuf::EnumDescriptor;
30using protobuf::EnumValueDescriptor;
31using protobuf::FieldDescriptor;
Vitaly Buka796b1122017-03-03 14:42:02 -080032using protobuf::FileDescriptor;
Vitaly Buka6c6dbbe2017-02-22 13:58:24 -080033using protobuf::Message;
34using protobuf::OneofDescriptor;
35using protobuf::Reflection;
Vitaly Buka4782c142017-03-04 00:12:32 -080036using protobuf::util::MessageDifferencer;
Vitaly Buka796b1122017-03-03 14:42:02 -080037using std::placeholders::_1;
Vitaly Buka0e17fd72016-11-18 10:02:46 -080038
39namespace {
40
Vitaly Buka72019dc2016-12-14 19:17:24 -080041const size_t kMaxInitializeDepth = 32;
42const size_t kDeletionThreshold = 128;
43const uint64_t kMutateWeight = 1000000;
Vitaly Buka0e17fd72016-11-18 10:02:46 -080044
45enum class Mutation {
Vitaly Buka30de3092016-11-18 11:39:07 -080046 None,
Vitaly Buka4af611d2016-12-03 18:57:32 -080047 Add, // Adds new field with default value.
48 Mutate, // Mutates field contents.
49 Delete, // Deletes field.
Vitaly Bukaa3e59c72016-12-06 16:53:56 -080050 Copy, // Copy values copied from another field.
Vitaly Buka4af611d2016-12-03 18:57:32 -080051
Vitaly Buka432b5452016-12-09 14:42:09 -080052 // TODO(vitalybuka):
53 // Clone, // Adds new field with value copied from another field.
Vitaly Buka0e17fd72016-11-18 10:02:46 -080054};
55
Vitaly Bukab592ff02017-03-03 14:35:52 -080056// Return random integer from [0, count)
Vitaly Bukae79e0182017-03-01 16:02:14 -080057size_t GetRandomIndex(Mutator::RandomEngine* random, size_t count) {
Vitaly Bukab592ff02017-03-03 14:35:52 -080058 assert(count > 0);
59 if (count == 1) return 0;
60 return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
61}
62
Vitaly Buka4af611d2016-12-03 18:57:32 -080063// Flips random bit in the buffer.
Vitaly Bukae79e0182017-03-01 16:02:14 -080064void FlipBit(size_t size, uint8_t* bytes, Mutator::RandomEngine* random) {
Vitaly Bukab592ff02017-03-03 14:35:52 -080065 size_t bit = GetRandomIndex(random, size * 8);
Vitaly Buka4af611d2016-12-03 18:57:32 -080066 bytes[bit / 8] ^= (1u << (bit % 8));
67}
Vitaly Buka781853c2016-11-21 23:09:35 -080068
Vitaly Buka4af611d2016-12-03 18:57:32 -080069// Flips random bit in the value.
70template <class T>
Vitaly Bukae79e0182017-03-01 16:02:14 -080071T FlipBit(T value, Mutator::RandomEngine* random) {
Vitaly Buka4af611d2016-12-03 18:57:32 -080072 FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
73 return value;
74}
Vitaly Buka781853c2016-11-21 23:09:35 -080075
Vitaly Bukabeb90802017-02-28 15:28:10 -080076// Return true with probability about 1-of-n.
Vitaly Bukae79e0182017-03-01 16:02:14 -080077bool GetRandomBool(Mutator::RandomEngine* random, size_t n = 2) {
Vitaly Bukabeb90802017-02-28 15:28:10 -080078 return GetRandomIndex(random, n) == 0;
79}
80
Vitaly Buka28ca0ee2017-03-04 21:35:42 -080081bool IsProto3SimpleField(const FieldDescriptor& field) {
82 assert(field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ||
83 field.file()->syntax() == FileDescriptor::SYNTAX_PROTO2);
84 return field.file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
85 field.cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
86 !field.containing_oneof() && !field.is_repeated();
87}
88
Vitaly Bukad4ab1e72017-03-03 23:51:19 -080089struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
Vitaly Buka91ad7b02016-12-12 15:41:41 -080090 template <class T>
Vitaly Bukad4ab1e72017-03-03 23:51:19 -080091 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 15:41:41 -080092 T value;
93 field.GetDefault(&value);
94 field.Create(value);
Vitaly Bukabec52222016-12-09 14:29:32 -080095 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -080096};
Vitaly Bukabec52222016-12-09 14:29:32 -080097
Vitaly Bukad4ab1e72017-03-03 23:51:19 -080098struct DeleteField : public FieldFunction<DeleteField> {
Vitaly Buka91ad7b02016-12-12 15:41:41 -080099 template <class T>
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800100 void ForType(const FieldInstance& field) const {
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800101 field.Delete();
Vitaly Bukabec52222016-12-09 14:29:32 -0800102 }
Vitaly Bukabec52222016-12-09 14:29:32 -0800103};
104
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800105struct CopyField : public FieldFunction<CopyField> {
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800106 template <class T>
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800107 void ForType(const ConstFieldInstance& source,
108 const FieldInstance& field) const {
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800109 T value;
110 source.Load(&value);
111 field.Store(value);
112 }
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800113};
114
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800115struct AppendField : public FieldFunction<AppendField> {
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800116 template <class T>
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800117 void ForType(const ConstFieldInstance& source,
118 const FieldInstance& field) const {
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800119 T value;
120 source.Load(&value);
121 field.Create(value);
122 }
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800123};
124
Vitaly Buka4782c142017-03-04 00:12:32 -0800125class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
126 public:
127 template <class T>
128 bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
129 T aa;
130 a.Load(&aa);
131 T bb;
132 b.Load(&bb);
133 return IsEqual(aa, bb);
134 }
135
136 private:
137 bool IsEqual(const ConstFieldInstance::Enum& a,
138 const ConstFieldInstance::Enum& b) const {
139 assert(a.count == b.count);
140 return a.index == b.index;
141 }
142
143 bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
144 const std::unique_ptr<protobuf::Message>& b) const {
145 return MessageDifferencer::Equals(*a, *b);
146 }
147
148 template <class T>
149 bool IsEqual(const T& a, const T& b) const {
150 return a == b;
151 }
152};
153
Vitaly Buka4af611d2016-12-03 18:57:32 -0800154// Selects random field and mutation from the given proto message.
Vitaly Buka781853c2016-11-21 23:09:35 -0800155class MutationSampler {
Vitaly Bukac9d22482016-11-21 13:29:17 -0800156 public:
Vitaly Buka72019dc2016-12-14 19:17:24 -0800157 MutationSampler(bool keep_initialized, size_t size_increase_hint,
Vitaly Bukae79e0182017-03-01 16:02:14 -0800158 Mutator::RandomEngine* random, Message* message)
Vitaly Buka4af611d2016-12-03 18:57:32 -0800159 : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
Vitaly Buka72019dc2016-12-14 19:17:24 -0800160 if (size_increase_hint < kDeletionThreshold) {
Vitaly Buka4af611d2016-12-03 18:57:32 -0800161 // Avoid adding new field and prefer deleting fields if we getting close
162 // to the limit.
Vitaly Buka72019dc2016-12-14 19:17:24 -0800163 float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
164 add_weight_ *= adjustment;
165 delete_weight_ *= 1 - adjustment;
Vitaly Buka781853c2016-11-21 23:09:35 -0800166 }
167 Sample(message);
Vitaly Buka142e08b2017-03-05 16:26:15 -0800168 assert(mutation() != Mutation::None || !size_increase_hint);
Vitaly Bukac9d22482016-11-21 13:29:17 -0800169 }
170
Vitaly Buka4af611d2016-12-03 18:57:32 -0800171 // Returns selected field.
Vitaly Bukabec52222016-12-09 14:29:32 -0800172 const FieldInstance& field() const { return sampler_.selected().field; }
Vitaly Buka4af611d2016-12-03 18:57:32 -0800173
174 // Returns selected mutation.
Vitaly Buka432b5452016-12-09 14:42:09 -0800175 Mutation mutation() const { return sampler_.selected().mutation; }
Vitaly Buka4af611d2016-12-03 18:57:32 -0800176
177 private:
Vitaly Buka781853c2016-11-21 23:09:35 -0800178 void Sample(Message* message) {
179 const Descriptor* descriptor = message->GetDescriptor();
180 const Reflection* reflection = message->GetReflection();
181
182 int field_count = descriptor->field_count();
183 for (int i = 0; i < field_count; ++i) {
184 const FieldDescriptor* field = descriptor->field(i);
185 if (const OneofDescriptor* oneof = field->containing_oneof()) {
186 // Handle entire oneof group on the first field.
187 if (field->index_in_oneof() == 0) {
Vitaly Buka2f660a52017-03-03 19:46:14 -0800188 assert(oneof->field_count());
189 const FieldDescriptor* current_field =
190 reflection->GetOneofFieldDescriptor(*message, oneof);
191 for (;;) {
192 const FieldDescriptor* add_field =
193 oneof->field(GetRandomIndex(random_, oneof->field_count()));
194 if (add_field != current_field) {
195 sampler_.Try(add_weight_, {{message, add_field}, Mutation::Add});
196 break;
197 }
198 if (oneof->field_count() < 2) break;
199 }
200 if (current_field) {
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800201 if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2f660a52017-03-03 19:46:14 -0800202 sampler_.Try(kMutateWeight,
203 {{message, current_field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800204 }
Vitaly Buka2f660a52017-03-03 19:46:14 -0800205 sampler_.Try(delete_weight_,
206 {{message, current_field}, Mutation::Delete});
Vitaly Buka72019dc2016-12-14 19:17:24 -0800207 sampler_.Try(GetCopyWeight(field),
Vitaly Buka2f660a52017-03-03 19:46:14 -0800208 {{message, current_field}, Mutation::Copy});
Vitaly Buka781853c2016-11-21 23:09:35 -0800209 }
210 }
211 } else {
212 if (field->is_repeated()) {
Vitaly Bukabec52222016-12-09 14:29:32 -0800213 int field_size = reflection->FieldSize(*message, field);
214 sampler_.Try(add_weight_, {{message, field,
215 GetRandomIndex(random_, field_size + 1)},
216 Mutation::Add});
Vitaly Buka781853c2016-11-21 23:09:35 -0800217
Vitaly Bukabec52222016-12-09 14:29:32 -0800218 if (field_size) {
219 size_t random_index = GetRandomIndex(random_, field_size);
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800220 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Bukabec52222016-12-09 14:29:32 -0800221 sampler_.Try(kMutateWeight,
222 {{message, field, random_index}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800223 }
Vitaly Bukabec52222016-12-09 14:29:32 -0800224 sampler_.Try(delete_weight_,
225 {{message, field, random_index}, Mutation::Delete});
Vitaly Buka72019dc2016-12-14 19:17:24 -0800226 sampler_.Try(GetCopyWeight(field),
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800227 {{message, field, random_index}, Mutation::Copy});
Vitaly Buka781853c2016-11-21 23:09:35 -0800228 }
229 } else {
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800230 if (reflection->HasField(*message, field) ||
231 IsProto3SimpleField(*field)) {
Vitaly Buka4af611d2016-12-03 18:57:32 -0800232 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
Vitaly Bukabec52222016-12-09 14:29:32 -0800233 sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800234 if (!IsProto3SimpleField(*field) &&
235 (!field->is_required() || !keep_initialized_)) {
Vitaly Bukabec52222016-12-09 14:29:32 -0800236 sampler_.Try(delete_weight_,
237 {{message, field}, Mutation::Delete});
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800238 }
Vitaly Buka72019dc2016-12-14 19:17:24 -0800239 sampler_.Try(GetCopyWeight(field),
240 {{message, field}, Mutation::Copy});
Vitaly Buka781853c2016-11-21 23:09:35 -0800241 } else {
Vitaly Bukabec52222016-12-09 14:29:32 -0800242 sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
Vitaly Buka781853c2016-11-21 23:09:35 -0800243 }
244 }
245 }
246
247 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
248 if (field->is_repeated()) {
249 const int field_size = reflection->FieldSize(*message, field);
250 for (int j = 0; j < field_size; ++j)
251 Sample(reflection->MutableRepeatedMessage(message, field, j));
252 } else if (reflection->HasField(*message, field)) {
253 Sample(reflection->MutableMessage(message, field));
254 }
255 }
256 }
257 }
258
Vitaly Buka72019dc2016-12-14 19:17:24 -0800259 uint64_t GetCopyWeight(const FieldDescriptor* field) const {
260 // Coping sub-messages can increase size significantly.
261 return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
262 ? add_weight_
263 : kMutateWeight;
264 }
265
Vitaly Buka781853c2016-11-21 23:09:35 -0800266 bool keep_initialized_ = false;
Vitaly Buka4af611d2016-12-03 18:57:32 -0800267
268 // Adding and deleting are intrusive and expensive mutations, we'd like to do
Vitaly Buka432b5452016-12-09 14:42:09 -0800269 // them less often than field mutations.
Vitaly Buka781853c2016-11-21 23:09:35 -0800270 uint64_t add_weight_ = kMutateWeight / 10;
271 uint64_t delete_weight_ = kMutateWeight / 10;
Vitaly Buka781853c2016-11-21 23:09:35 -0800272
Vitaly Bukae79e0182017-03-01 16:02:14 -0800273 Mutator::RandomEngine* random_;
Vitaly Buka4af611d2016-12-03 18:57:32 -0800274
275 struct Result {
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800276 Result() = default;
Vitaly Bukabec52222016-12-09 14:29:32 -0800277 Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800278
Vitaly Bukabec52222016-12-09 14:29:32 -0800279 FieldInstance field;
280 Mutation mutation = Mutation::None;
Vitaly Buka4af611d2016-12-03 18:57:32 -0800281 };
Vitaly Bukae79e0182017-03-01 16:02:14 -0800282 WeightedReservoirSampler<Result, Mutator::RandomEngine> sampler_;
Vitaly Bukac9d22482016-11-21 13:29:17 -0800283};
284
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800285// Selects random field of compatible type to use for clone mutations.
286class DataSourceSampler {
287 public:
Vitaly Buka88712862017-02-26 22:21:30 -0800288 DataSourceSampler(const ConstFieldInstance& match,
Vitaly Bukae79e0182017-03-01 16:02:14 -0800289 Mutator::RandomEngine* random, Message* message)
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800290 : match_(match), random_(random), sampler_(random) {
291 Sample(message);
292 }
293
294 // Returns selected field.
Vitaly Buka88712862017-02-26 22:21:30 -0800295 const ConstFieldInstance& field() const {
Vitaly Buka72019dc2016-12-14 19:17:24 -0800296 assert(!IsEmpty());
297 return sampler_.selected();
298 }
299
300 bool IsEmpty() const { return sampler_.IsEmpty(); }
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800301
302 private:
303 void Sample(Message* message) {
304 const Descriptor* descriptor = message->GetDescriptor();
305 const Reflection* reflection = message->GetReflection();
306
307 int field_count = descriptor->field_count();
308 for (int i = 0; i < field_count; ++i) {
309 const FieldDescriptor* field = descriptor->field(i);
310 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
311 if (field->is_repeated()) {
312 const int field_size = reflection->FieldSize(*message, field);
313 for (int j = 0; j < field_size; ++j) {
314 Sample(reflection->MutableRepeatedMessage(message, field, j));
315 }
316 } else if (reflection->HasField(*message, field)) {
317 Sample(reflection->MutableMessage(message, field));
318 }
319 }
320
321 if (field->cpp_type() != match_.cpp_type()) continue;
322 if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
323 if (field->enum_type() != match_.enum_type()) continue;
324 } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
325 if (field->message_type() != match_.message_type()) continue;
326 }
327
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800328 if (field->is_repeated()) {
329 if (int field_size = reflection->FieldSize(*message, field)) {
Vitaly Buka4782c142017-03-04 00:12:32 -0800330 ConstFieldInstance source(message, field,
331 GetRandomIndex(random_, field_size));
332 if (!IsEqualValueField()(match_, source))
333 sampler_.Try(field_size, source);
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800334 }
335 } else {
336 if (reflection->HasField(*message, field)) {
Vitaly Buka4782c142017-03-04 00:12:32 -0800337 ConstFieldInstance source(message, field);
338 if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800339 }
340 }
341 }
342 }
343
Vitaly Buka88712862017-02-26 22:21:30 -0800344 ConstFieldInstance match_;
Vitaly Bukae79e0182017-03-01 16:02:14 -0800345 Mutator::RandomEngine* random_;
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800346
Vitaly Bukae79e0182017-03-01 16:02:14 -0800347 WeightedReservoirSampler<ConstFieldInstance, Mutator::RandomEngine> sampler_;
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800348};
349
Vitaly Buka0e17fd72016-11-18 10:02:46 -0800350} // namespace
351
Vitaly Buka5d013202017-02-24 16:50:11 -0800352class FieldMutator {
Vitaly Buka432b5452016-12-09 14:42:09 -0800353 public:
Vitaly Bukae79e0182017-03-01 16:02:14 -0800354 FieldMutator(size_t size_increase_hint, Mutator* mutator)
Vitaly Buka5d013202017-02-24 16:50:11 -0800355 : size_increase_hint_(size_increase_hint), mutator_(mutator) {}
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800356
Vitaly Buka796b1122017-03-03 14:42:02 -0800357 void Mutate(int32_t* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800358 RepeatMutate(value, std::bind(&Mutator::MutateInt32, mutator_, _1));
Vitaly Buka796b1122017-03-03 14:42:02 -0800359 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800360
Vitaly Buka796b1122017-03-03 14:42:02 -0800361 void Mutate(int64_t* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800362 RepeatMutate(value, std::bind(&Mutator::MutateInt64, mutator_, _1));
Vitaly Buka796b1122017-03-03 14:42:02 -0800363 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800364
365 void Mutate(uint32_t* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800366 RepeatMutate(value, std::bind(&Mutator::MutateUInt32, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800367 }
368
369 void Mutate(uint64_t* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800370 RepeatMutate(value, std::bind(&Mutator::MutateUInt64, mutator_, _1));
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800371 }
372
Vitaly Buka796b1122017-03-03 14:42:02 -0800373 void Mutate(float* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800374 RepeatMutate(value, std::bind(&Mutator::MutateFloat, mutator_, _1));
Vitaly Buka796b1122017-03-03 14:42:02 -0800375 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800376
Vitaly Buka796b1122017-03-03 14:42:02 -0800377 void Mutate(double* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800378 RepeatMutate(value, std::bind(&Mutator::MutateDouble, mutator_, _1));
Vitaly Buka796b1122017-03-03 14:42:02 -0800379 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800380
Vitaly Buka796b1122017-03-03 14:42:02 -0800381 void Mutate(bool* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800382 RepeatMutate(value, std::bind(&Mutator::MutateBool, mutator_, _1));
Vitaly Buka796b1122017-03-03 14:42:02 -0800383 }
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800384
385 void Mutate(FieldInstance::Enum* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800386 RepeatMutate(&value->index,
387 std::bind(&Mutator::MutateEnum, mutator_, _1, value->count));
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800388 assert(value->index < value->count);
389 }
390
391 void Mutate(std::string* value) const {
Vitaly Bukae79e0182017-03-01 16:02:14 -0800392 RepeatMutate(value, std::bind(&Mutator::MutateString, mutator_, _1,
Vitaly Buka796b1122017-03-03 14:42:02 -0800393 size_increase_hint_));
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800394 }
395
Vitaly Buka5f7dfbd2017-03-04 21:38:13 -0800396 void Mutate(std::unique_ptr<Message>*) const {}
Vitaly Buka432b5452016-12-09 14:42:09 -0800397
Vitaly Buka5d013202017-02-24 16:50:11 -0800398 private:
Vitaly Buka796b1122017-03-03 14:42:02 -0800399 template <class T, class F>
400 void RepeatMutate(T* value, F mutate) const {
401 T tmp = *value;
402 for (int i = 0; i < 10; ++i) {
403 *value = mutate(*value);
404 if (*value != tmp) return;
405 }
406 }
407
Vitaly Buka5d013202017-02-24 16:50:11 -0800408 size_t size_increase_hint_;
Vitaly Bukae79e0182017-03-01 16:02:14 -0800409 Mutator* mutator_;
Vitaly Buka432b5452016-12-09 14:42:09 -0800410};
411
Vitaly Buka5d013202017-02-24 16:50:11 -0800412namespace {
413
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800414struct MutateField : public FieldFunction<MutateField> {
Vitaly Buka5d013202017-02-24 16:50:11 -0800415 template <class T>
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800416 void ForType(const FieldInstance& field, size_t size_increase_hint,
Vitaly Bukae79e0182017-03-01 16:02:14 -0800417 Mutator* mutator) const {
Vitaly Buka5d013202017-02-24 16:50:11 -0800418 T value;
419 field.Load(&value);
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800420 FieldMutator(size_increase_hint, mutator).Mutate(&value);
Vitaly Buka5d013202017-02-24 16:50:11 -0800421 field.Store(value);
422 }
Vitaly Buka5d013202017-02-24 16:50:11 -0800423};
424
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800425struct CreateField : public FieldFunction<CreateField> {
Vitaly Buka5d013202017-02-24 16:50:11 -0800426 public:
Vitaly Buka5d013202017-02-24 16:50:11 -0800427 template <class T>
Vitaly Bukae79e0182017-03-01 16:02:14 -0800428 void ForType(const FieldInstance& field, Mutator* mutator) const {
Vitaly Buka5d013202017-02-24 16:50:11 -0800429 T value;
430 field.GetDefault(&value);
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800431 FieldMutator(0, mutator).Mutate(&value);
Vitaly Buka5d013202017-02-24 16:50:11 -0800432 field.Create(value);
433 }
Vitaly Buka5d013202017-02-24 16:50:11 -0800434};
435
436} // namespace
437
Vitaly Bukae79e0182017-03-01 16:02:14 -0800438Mutator::Mutator(uint32_t seed) : random_(seed) {}
Vitaly Buka432b5452016-12-09 14:42:09 -0800439
Vitaly Bukae79e0182017-03-01 16:02:14 -0800440void Mutator::Mutate(Message* message, size_t size_increase_hint) {
Vitaly Buka66d06c72017-03-04 01:22:34 -0800441 bool repeat;
442 do {
443 repeat = false;
444 MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
445 message);
446 switch (mutation.mutation()) {
447 case Mutation::None:
448 break;
449 case Mutation::Add:
450 if (GetRandomBool(&random_)) {
Vitaly Buka28ca0ee2017-03-04 21:35:42 -0800451 CreateField()(mutation.field(), this);
Vitaly Buka66d06c72017-03-04 01:22:34 -0800452 } else {
453 CreateDefaultField()(mutation.field());
454 }
455 break;
456 case Mutation::Mutate:
457 MutateField()(mutation.field(), size_increase_hint / 2, this);
458 break;
459 case Mutation::Delete:
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800460 DeleteField()(mutation.field());
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800461 break;
Vitaly Buka66d06c72017-03-04 01:22:34 -0800462 case Mutation::Copy: {
463 DataSourceSampler source(mutation.field(), &random_, message);
464 if (source.IsEmpty()) {
465 repeat = true;
466 break;
467 }
468 CopyField()(source.field(), mutation.field());
469 break;
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800470 }
Vitaly Buka66d06c72017-03-04 01:22:34 -0800471 default:
472 assert(false && "unexpected mutation");
Vitaly Bukaa3e59c72016-12-06 16:53:56 -0800473 }
Vitaly Buka66d06c72017-03-04 01:22:34 -0800474 } while (repeat);
Vitaly Buka0e17fd72016-11-18 10:02:46 -0800475
Vitaly Buka781853c2016-11-21 23:09:35 -0800476 if (keep_initialized_ && !message->IsInitialized()) {
477 InitializeMessage(message, kMaxInitializeDepth);
478 assert(message->IsInitialized());
Vitaly Buka0e17fd72016-11-18 10:02:46 -0800479 }
Vitaly Buka00b61072016-10-19 16:22:51 -0700480}
481
Vitaly Bukae79e0182017-03-01 16:02:14 -0800482void Mutator::CrossOver(const protobuf::Message& message1,
483 protobuf::Message* message2) {
Vitaly Buka142e08b2017-03-05 16:26:15 -0800484 // CrossOver can produce result which still equals to inputs. So we backup
485 // message2 to later comparison. message1 is already constant.
486 std::unique_ptr<protobuf::Message> message2_copy(message2->New());
487 message2_copy->CopyFrom(*message2);
488
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800489 CrossOverImpl(message1, message2);
490
491 if (keep_initialized_ && !message2->IsInitialized()) {
492 InitializeMessage(message2, kMaxInitializeDepth);
493 assert(message2->IsInitialized());
494 }
Vitaly Buka142e08b2017-03-05 16:26:15 -0800495
496 if (MessageDifferencer::Equals(*message2_copy, *message2) ||
497 MessageDifferencer::Equals(message1, *message2)) {
498 Mutate(message2, 0);
499 }
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800500}
501
Vitaly Bukae79e0182017-03-01 16:02:14 -0800502void Mutator::CrossOverImpl(const protobuf::Message& message1,
503 protobuf::Message* message2) {
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800504 const Descriptor* descriptor = message2->GetDescriptor();
505 const Reflection* reflection = message2->GetReflection();
506 assert(message1.GetDescriptor() == descriptor);
507 assert(message1.GetReflection() == reflection);
508
509 for (int i = 0; i < descriptor->field_count(); ++i) {
510 const FieldDescriptor* field = descriptor->field(i);
511
512 if (field->is_repeated()) {
513 const int field_size1 = reflection->FieldSize(message1, field);
514 int field_size2 = reflection->FieldSize(*message2, field);
515 for (int j = 0; j < field_size1; ++j) {
516 ConstFieldInstance source(&message1, field, j);
517 FieldInstance destination(message2, field, field_size2++);
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800518 AppendField()(source, destination);
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800519 }
520
521 assert(field_size2 == reflection->FieldSize(*message2, field));
522
523 // Shuffle
524 for (int j = 0; j < field_size2; ++j) {
525 if (int k = GetRandomIndex(&random_, field_size2 - j)) {
526 reflection->SwapElements(message2, field, j, j + k);
527 }
528 }
529
530 int keep = GetRandomIndex(&random_, field_size2 + 1);
531
532 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
533 int remove = field_size2 - keep;
534 // Cross some message to keep with messages to remove.
535 int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
536 for (int j = 0; j < cross; ++j) {
537 int k = GetRandomIndex(&random_, keep);
538 int r = keep + GetRandomIndex(&random_, remove);
539 assert(k != r);
540 CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
541 reflection->MutableRepeatedMessage(message2, field, k));
542 }
543 }
544
545 for (int j = keep; j < field_size2; ++j)
546 reflection->RemoveLast(message2, field);
547 assert(keep == reflection->FieldSize(*message2, field));
548
549 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
550 if (!reflection->HasField(message1, field)) {
Vitaly Bukabeb90802017-02-28 15:28:10 -0800551 if (GetRandomBool(&random_))
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800552 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800553 } else if (!reflection->HasField(*message2, field)) {
Vitaly Bukabeb90802017-02-28 15:28:10 -0800554 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800555 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800556 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800557 }
558 } else {
559 CrossOverImpl(reflection->GetMessage(message1, field),
560 reflection->MutableMessage(message2, field));
561 }
562 } else {
Vitaly Bukabeb90802017-02-28 15:28:10 -0800563 if (GetRandomBool(&random_)) {
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800564 if (reflection->HasField(message1, field)) {
565 ConstFieldInstance source(&message1, field);
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800566 CopyField()(source, FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800567 } else {
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800568 DeleteField()(FieldInstance(message2, field));
Vitaly Bukaadfc27c2017-02-26 22:36:36 -0800569 }
570 }
571 }
572 }
573}
574
Vitaly Bukae79e0182017-03-01 16:02:14 -0800575void Mutator::InitializeMessage(Message* message, size_t max_depth) {
Vitaly Buka781853c2016-11-21 23:09:35 -0800576 assert(keep_initialized_);
Vitaly Buka432b5452016-12-09 14:42:09 -0800577 // It's pointless but possible to have infinite recursion of required
578 // messages.
579 assert(max_depth);
Vitaly Buka13245af2016-11-18 13:20:12 -0800580 const Descriptor* descriptor = message->GetDescriptor();
581 const Reflection* reflection = message->GetReflection();
Vitaly Buka13245af2016-11-18 13:20:12 -0800582 for (int i = 0; i < descriptor->field_count(); ++i) {
583 const FieldDescriptor* field = descriptor->field(i);
Vitaly Buka91ad7b02016-12-12 15:41:41 -0800584 if (field->is_required() && !reflection->HasField(*message, field))
Vitaly Bukad4ab1e72017-03-03 23:51:19 -0800585 CreateDefaultField()(FieldInstance(message, field));
Vitaly Buka13245af2016-11-18 13:20:12 -0800586
Vitaly Buka781853c2016-11-21 23:09:35 -0800587 if (max_depth > 0 &&
588 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Vitaly Buka2cfe02b2016-11-18 16:34:09 -0800589 if (field->is_repeated()) {
590 const int field_size = reflection->FieldSize(*message, field);
591 for (int j = 0; j < field_size; ++j) {
592 Message* nested_message =
593 reflection->MutableRepeatedMessage(message, field, j);
Vitaly Buka781853c2016-11-21 23:09:35 -0800594 if (!nested_message->IsInitialized())
595 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka2cfe02b2016-11-18 16:34:09 -0800596 }
597 } else if (reflection->HasField(*message, field)) {
598 Message* nested_message = reflection->MutableMessage(message, field);
Vitaly Buka781853c2016-11-21 23:09:35 -0800599 if (!nested_message->IsInitialized())
600 InitializeMessage(nested_message, max_depth - 1);
Vitaly Buka13245af2016-11-18 13:20:12 -0800601 }
602 }
603 }
604}
Vitaly Buka4af611d2016-12-03 18:57:32 -0800605
Vitaly Bukae79e0182017-03-01 16:02:14 -0800606int32_t Mutator::MutateInt32(int32_t value) { return FlipBit(value, &random_); }
607
608int64_t Mutator::MutateInt64(int64_t value) { return FlipBit(value, &random_); }
609
610uint32_t Mutator::MutateUInt32(uint32_t value) {
Vitaly Buka4af611d2016-12-03 18:57:32 -0800611 return FlipBit(value, &random_);
612}
613
Vitaly Bukae79e0182017-03-01 16:02:14 -0800614uint64_t Mutator::MutateUInt64(uint64_t value) {
Vitaly Buka4af611d2016-12-03 18:57:32 -0800615 return FlipBit(value, &random_);
616}
617
Vitaly Bukae79e0182017-03-01 16:02:14 -0800618float Mutator::MutateFloat(float value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-03 18:57:32 -0800619
Vitaly Bukae79e0182017-03-01 16:02:14 -0800620double Mutator::MutateDouble(double value) { return FlipBit(value, &random_); }
Vitaly Buka4af611d2016-12-03 18:57:32 -0800621
Vitaly Bukae79e0182017-03-01 16:02:14 -0800622bool Mutator::MutateBool(bool value) { return !value; }
Vitaly Buka4af611d2016-12-03 18:57:32 -0800623
Vitaly Bukae79e0182017-03-01 16:02:14 -0800624size_t Mutator::MutateEnum(size_t index, size_t item_count) {
Vitaly Bukabeb90802017-02-28 15:28:10 -0800625 return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
Vitaly Buka4af611d2016-12-03 18:57:32 -0800626}
627
Vitaly Bukae79e0182017-03-01 16:02:14 -0800628std::string Mutator::MutateString(const std::string& value,
629 size_t size_increase_hint) {
Vitaly Buka4af611d2016-12-03 18:57:32 -0800630 std::string result = value;
Vitaly Buka5d013202017-02-24 16:50:11 -0800631
Vitaly Bukabeb90802017-02-28 15:28:10 -0800632 while (!result.empty() && GetRandomBool(&random_)) {
Vitaly Buka432b5452016-12-09 14:42:09 -0800633 result.erase(GetRandomIndex(&random_, result.size()), 1);
Vitaly Buka432b5452016-12-09 14:42:09 -0800634 }
635
Vitaly Bukabeb90802017-02-28 15:28:10 -0800636 while (result.size() < size_increase_hint && GetRandomBool(&random_)) {
Vitaly Buka432b5452016-12-09 14:42:09 -0800637 size_t index = GetRandomIndex(&random_, result.size() + 1);
Vitaly Buka5d013202017-02-24 16:50:11 -0800638 result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
Vitaly Buka432b5452016-12-09 14:42:09 -0800639 }
640
Vitaly Bukac020de12017-03-03 19:36:23 -0800641 if (result != value) return result;
642
643 if (result.empty()) {
644 result.push_back(GetRandomIndex(&random_, 1 << 8));
645 return result;
646 }
647
Vitaly Buka4af611d2016-12-03 18:57:32 -0800648 if (!result.empty())
649 FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
650 return result;
651}
Vitaly Buka432b5452016-12-09 14:42:09 -0800652
653} // namespace protobuf_mutator