1 // 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
15 #include "src/mutator.h"
16
17 #include <algorithm>
18 #include <set>
19 #include <string>
20 #include <tuple>
21 #include <utility>
22 #include <vector>
23
24 #include "port/gtest.h"
25 #include "src/binary_format.h"
26 #include "src/mutator_test_proto2.pb.h"
27 #include "src/mutator_test_proto3.pb.h"
28 #include "src/text_format.h"
29
30 namespace protobuf_mutator {
31
32 using protobuf::util::MessageDifferencer;
33 using testing::TestWithParam;
34 using testing::ValuesIn;
35
36 const char kMessages[] = R"(
37 required_msg {}
38 optional_msg {}
39 repeated_msg {}
40 repeated_msg {required_sint32: 56}
41 repeated_msg {}
42 repeated_msg {
43 required_msg {}
44 optional_msg {}
45 repeated_msg {}
46 repeated_msg { required_int32: 67 }
47 repeated_msg {}
48 }
49 )";
50
51 const char kMessagesProto3[] = R"(
52 optional_msg {}
53 repeated_msg {}
54 repeated_msg {optional_sint32: 56}
55 repeated_msg {}
56 repeated_msg {
57 optional_msg {}
58 repeated_msg {}
59 repeated_msg { optional_int32: 67 }
60 repeated_msg {}
61 }
62 )";
63
64 const char kRequiredFields[] = R"(
65 required_double: 1.26685288449177e-313
66 required_float: 5.9808638e-39
67 required_int32: 67
68 required_int64: 5285068
69 required_uint32: 14486213
70 required_uint64: 520229415
71 required_sint32: 56
72 required_sint64: -6057486163525532641
73 required_fixed32: 8812173
74 required_fixed64: 273731277756
75 required_sfixed32: 43142
76 required_sfixed64: 132
77 required_bool: false
78 required_string: "qwert"
79 required_bytes: "asdf"
80 )";
81
82 const char kOptionalFields[] = R"(
83 optional_double: 1.93177850152856e-314
84 optional_float: 4.7397519e-41
85 optional_int32: 40020
86 optional_int64: 10
87 optional_uint32: 40
88 optional_uint64: 159
89 optional_sint32: 44015
90 optional_sint64: 17493625000076
91 optional_fixed32: 193
92 optional_fixed64: 8542688694448488723
93 optional_sfixed32: 4926
94 optional_sfixed64: 60
95 optional_bool: true
96 optional_string: "QWERT"
97 optional_bytes: "ASDF"
98 optional_enum: ENUM_5
99 )";
100
101 const char kRepeatedFields[] = R"(
102 repeated_double: 1.93177850152856e-314
103 repeated_double: 1.26685288449177e-313
104 repeated_float: 4.7397519e-41
105 repeated_float: 5.9808638e-39
106 repeated_int32: 40020
107 repeated_int32: 67
108 repeated_int64: 10
109 repeated_int64: 5285068
110 repeated_uint32: 40
111 repeated_uint32: 14486213
112 repeated_uint64: 159
113 repeated_uint64: 520229415
114 repeated_sint32: 44015
115 repeated_sint32: 56
116 repeated_sint64: 17493625000076
117 repeated_sint64: -6057486163525532641
118 repeated_fixed32: 193
119 repeated_fixed32: 8812173
120 repeated_fixed64: 8542688694448488723
121 repeated_fixed64: 273731277756
122 repeated_sfixed32: 4926
123 repeated_sfixed32: 43142
124 repeated_sfixed64: 60
125 repeated_sfixed64: 132
126 repeated_bool: false
127 repeated_bool: true
128 repeated_string: "QWERT"
129 repeated_string: "qwert"
130 repeated_bytes: "ASDF"
131 repeated_bytes: "asdf"
132 repeated_enum: ENUM_5
133 repeated_enum: ENUM_4
134 )";
135
136 const char kRequiredNestedFields[] = R"(
137 required_int32: 123
138 optional_msg {
139 required_double: 1.26685288449177e-313
140 required_float: 5.9808638e-39
141 required_int32: 67
142 required_int64: 5285068
143 required_uint32: 14486213
144 required_uint64: 520229415
145 required_sint32: 56
146 required_sint64: -6057486163525532641
147 required_fixed32: 8812173
148 required_fixed64: 273731277756
149 required_sfixed32: 43142
150 required_sfixed64: 132
151 required_bool: false
152 required_string: "qwert"
153 required_bytes: "asdf"
154 }
155 )";
156
157 const char kOptionalNestedFields[] = R"(
158 optional_int32: 123
159 optional_msg {
160 optional_double: 1.93177850152856e-314
161 optional_float: 4.7397519e-41
162 optional_int32: 40020
163 optional_int64: 10
164 optional_uint32: 40
165 optional_uint64: 159
166 optional_sint32: 44015
167 optional_sint64: 17493625000076
168 optional_fixed32: 193
169 optional_fixed64: 8542688694448488723
170 optional_sfixed32: 4926
171 optional_sfixed64: 60
172 optional_bool: true
173 optional_string: "QWERT"
174 optional_bytes: "ASDF"
175 optional_enum: ENUM_5
176 }
177 )";
178
179 const char kRepeatedNestedFields[] = R"(
180 optional_int32: 123
181 optional_msg {
182 repeated_double: 1.93177850152856e-314
183 repeated_double: 1.26685288449177e-313
184 repeated_float: 4.7397519e-41
185 repeated_float: 5.9808638e-39
186 repeated_int32: 40020
187 repeated_int32: 67
188 repeated_int64: 10
189 repeated_int64: 5285068
190 repeated_uint32: 40
191 repeated_uint32: 14486213
192 repeated_uint64: 159
193 repeated_uint64: 520229415
194 repeated_sint32: 44015
195 repeated_sint32: 56
196 repeated_sint64: 17493625000076
197 repeated_sint64: -6057486163525532641
198 repeated_fixed32: 193
199 repeated_fixed32: 8812173
200 repeated_fixed64: 8542688694448488723
201 repeated_fixed64: 273731277756
202 repeated_sfixed32: 4926
203 repeated_sfixed32: 43142
204 repeated_sfixed64: 60
205 repeated_sfixed64: 132
206 repeated_bool: false
207 repeated_bool: true
208 repeated_string: "QWERT"
209 repeated_string: "qwert"
210 repeated_bytes: "ASDF"
211 repeated_bytes: "asdf"
212 repeated_enum: ENUM_5
213 repeated_enum: ENUM_4
214 }
215 )";
216
217 class TestMutator : public Mutator {
218 public:
TestMutator(bool keep_initialized)219 explicit TestMutator(bool keep_initialized) : Mutator(&random_), random_(17) {
220 keep_initialized_ = keep_initialized;
221 }
222
223 // Avoids dedup logic for some tests.
NoDeDupCrossOver(const protobuf::Message & message1,protobuf::Message * message2)224 void NoDeDupCrossOver(const protobuf::Message& message1,
225 protobuf::Message* message2) {
226 CrossOverImpl(message1, message2);
227 }
228
229 private:
230 RandomEngine random_;
231 };
232
233 class ReducedTestMutator : public TestMutator {
234 public:
ReducedTestMutator()235 ReducedTestMutator() : TestMutator(false) {
236 for (float i = 1000; i > 0.1; i /= 7) {
237 values_.push_back(i);
238 values_.push_back(-i);
239 }
240 values_.push_back(-1.0);
241 values_.push_back(0.0);
242 values_.push_back(1.0);
243 }
244
245 protected:
MutateInt32(int32_t value)246 int32_t MutateInt32(int32_t value) override { return GetRandomValue(); }
MutateInt64(int64_t value)247 int64_t MutateInt64(int64_t value) override { return GetRandomValue(); }
MutateUInt32(uint32_t value)248 uint32_t MutateUInt32(uint32_t value) override {
249 return fabs(GetRandomValue());
250 }
MutateUInt64(uint64_t value)251 uint64_t MutateUInt64(uint64_t value) override {
252 return fabs(GetRandomValue());
253 }
MutateFloat(float value)254 float MutateFloat(float value) override { return GetRandomValue(); }
MutateDouble(double value)255 double MutateDouble(double value) override { return GetRandomValue(); }
MutateString(const std::string & value,size_t size_increase_hint)256 std::string MutateString(const std::string& value,
257 size_t size_increase_hint) override {
258 return strings_[std::uniform_int_distribution<uint8_t>(
259 0, strings_.size() - 1)(*random())];
260 }
261
262 private:
GetRandomValue()263 float GetRandomValue() {
264 return values_[std::uniform_int_distribution<uint8_t>(
265 0, values_.size() - 1)(*random())];
266 }
267
268 std::vector<float> values_;
269 std::vector<std::string> strings_ = {
270 "", "\001", "\000", "a", "b", "ab",
271 };
272 };
273
Split(const std::string & str)274 std::vector<std::string> Split(const std::string& str) {
275 std::istringstream iss(str);
276 std::vector<std::string> result;
277 for (std::string line; std::getline(iss, line, '\n');) result.push_back(line);
278 return result;
279 }
280
281 using TestParams = std::tuple<const protobuf::Message*, const char*, size_t>;
282
283 template <class T>
GetFieldTestParams(const std::vector<const char * > & tests)284 std::vector<TestParams> GetFieldTestParams(
285 const std::vector<const char*>& tests) {
286 std::vector<TestParams> results;
287 for (auto t : tests) {
288 auto lines = Split(t);
289 for (size_t i = 0; i != lines.size(); ++i) {
290 if (lines[i].find(':') != std::string::npos)
291 results.push_back(std::make_tuple(&T::default_instance(), t, i));
292 }
293 }
294 return results;
295 }
296
297 template <class T>
GetMessageTestParams(const std::vector<const char * > & tests)298 std::vector<TestParams> GetMessageTestParams(
299 const std::vector<const char*>& tests) {
300 std::vector<TestParams> results;
301 for (auto t : tests) {
302 auto lines = Split(t);
303 for (size_t i = 0; i != lines.size(); ++i) {
304 if (lines[i].find("{}") != std::string::npos)
305 results.push_back(std::make_tuple(&T::default_instance(), t, i));
306 }
307 }
308 return results;
309 }
310
Mutate(const protobuf::Message & from,const protobuf::Message & to)311 bool Mutate(const protobuf::Message& from, const protobuf::Message& to) {
312 EXPECT_FALSE(MessageDifferencer::Equals(from, to));
313 ReducedTestMutator mutator;
314 std::unique_ptr<protobuf::Message> message(from.New());
315 for (int j = 0; j < 1000000; ++j) {
316 message->CopyFrom(from);
317 mutator.Mutate(message.get(), 1000);
318 if (MessageDifferencer::Equals(*message, to)) return true;
319 }
320
321 ADD_FAILURE() << "Failed to get from:\n"
322 << SaveMessageAsText(from) << "\nto:\n"
323 << SaveMessageAsText(to);
324 return false;
325 }
326
327 class MutatorTest : public TestWithParam<TestParams> {
328 protected:
SetUp()329 void SetUp() override {
330 m1_.reset(std::get<0>(GetParam())->New());
331 m2_.reset(std::get<0>(GetParam())->New());
332 text_ = std::get<1>(GetParam());
333 line_ = std::get<2>(GetParam());
334 }
335
LoadMessage(protobuf::Message * message)336 void LoadMessage(protobuf::Message* message) {
337 EXPECT_TRUE(ParseTextMessage(text_, message));
338 }
339
LoadWithoutLine(protobuf::Message * message)340 bool LoadWithoutLine(protobuf::Message* message) {
341 std::ostringstream oss;
342 auto lines = Split(text_);
343 for (size_t i = 0; i != lines.size(); ++i) {
344 if (i != line_) oss << lines[i] << '\n';
345 }
346 return ParseTextMessage(oss.str(), message);
347 }
348
LoadWithChangedLine(protobuf::Message * message,int value)349 bool LoadWithChangedLine(protobuf::Message* message, int value) {
350 auto lines = Split(text_);
351 std::ostringstream oss;
352 for (size_t i = 0; i != lines.size(); ++i) {
353 if (i != line_) {
354 oss << lines[i] << '\n';
355 } else {
356 std::string s = lines[i];
357 s.resize(s.find(':') + 2);
358
359 if (lines[i].back() == '\"') {
360 // strings
361 s += value ? "\"\\" + std::to_string(value) + "\"" : "\"\"";
362 } else if (lines[i].back() == 'e') {
363 // bools
364 s += value ? "true" : "false";
365 } else {
366 s += std::to_string(value);
367 }
368 oss << s << '\n';
369 }
370 }
371 return ParseTextMessage(oss.str(), message);
372 }
373
374 std::string text_;
375 size_t line_;
376 std::unique_ptr<protobuf::Message> m1_;
377 std::unique_ptr<protobuf::Message> m2_;
378 };
379
380 // These tests are irrelevant for Proto3 as it has no required fields and
381 // insertion/deletion.
382
383 class MutatorFieldInsDelTest : public MutatorTest {};
384 INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldInsDelTest,
385 ValuesIn(GetFieldTestParams<Msg>(
386 {kRequiredFields, kOptionalFields, kRepeatedFields,
387 kRequiredNestedFields, kOptionalNestedFields,
388 kRepeatedNestedFields})));
389
TEST_P(MutatorFieldInsDelTest,DeleteField)390 TEST_P(MutatorFieldInsDelTest, DeleteField) {
391 LoadMessage(m1_.get());
392 LoadWithoutLine(m2_.get());
393 EXPECT_TRUE(Mutate(*m1_, *m2_));
394 }
395
TEST_P(MutatorFieldInsDelTest,InsertField)396 TEST_P(MutatorFieldInsDelTest, InsertField) {
397 LoadWithoutLine(m1_.get());
398 LoadWithChangedLine(m2_.get(), 0);
399 EXPECT_TRUE(Mutate(*m1_, *m2_));
400 }
401
402 class MutatorFieldTest : public MutatorTest {
403 public:
404 template <class Msg>
405 void TestCopyField();
406 };
407 INSTANTIATE_TEST_CASE_P(Proto2, MutatorFieldTest,
408 ValuesIn(GetFieldTestParams<Msg>(
409 {kRequiredFields, kOptionalFields, kRepeatedFields,
410 kRequiredNestedFields, kOptionalNestedFields,
411 kRepeatedNestedFields})));
412 INSTANTIATE_TEST_CASE_P(Proto3, MutatorFieldTest,
413 ValuesIn(GetFieldTestParams<Msg3>(
414 {kOptionalFields, kRepeatedFields,
415 kOptionalNestedFields, kRepeatedNestedFields})));
416
TEST_P(MutatorFieldTest,Initialized)417 TEST_P(MutatorFieldTest, Initialized) {
418 LoadWithoutLine(m1_.get());
419 TestMutator mutator(true);
420 mutator.Mutate(m1_.get(), 1000);
421 EXPECT_TRUE(m1_->IsInitialized());
422 }
423
TEST_P(MutatorFieldTest,ChangeField)424 TEST_P(MutatorFieldTest, ChangeField) {
425 LoadWithChangedLine(m1_.get(), 0);
426 LoadWithChangedLine(m2_.get(), 1);
427 EXPECT_TRUE(Mutate(*m1_, *m2_));
428 EXPECT_TRUE(Mutate(*m2_, *m1_));
429 }
430
431 template <class Msg>
TestCopyField()432 void MutatorFieldTest::TestCopyField() {
433 LoadWithChangedLine(m1_.get(), 7);
434 LoadWithChangedLine(m2_.get(), 0);
435
436 Msg from;
437 from.add_repeated_msg()->CopyFrom(*m1_);
438 from.add_repeated_msg()->CopyFrom(*m2_);
439
440 Msg to;
441 to.add_repeated_msg()->CopyFrom(*m1_);
442 to.add_repeated_msg()->CopyFrom(*m1_);
443 EXPECT_TRUE(Mutate(from, to));
444
445 to.Clear();
446 to.add_repeated_msg()->CopyFrom(*m2_);
447 to.add_repeated_msg()->CopyFrom(*m2_);
448 EXPECT_TRUE(Mutate(from, to));
449 }
450
TEST_P(MutatorFieldTest,CopyField)451 TEST_P(MutatorFieldTest, CopyField) {
452 if (m1_->GetDescriptor() == Msg::descriptor())
453 TestCopyField<Msg>();
454 else
455 TestCopyField<Msg3>();
456 }
457
458 class MutatorSingleFieldTest : public MutatorTest {};
459 INSTANTIATE_TEST_CASE_P(Proto2, MutatorSingleFieldTest,
460 ValuesIn(GetFieldTestParams<Msg>({
461 kRequiredFields, kOptionalFields,
462 kRequiredNestedFields, kOptionalNestedFields,
463 })));
464 INSTANTIATE_TEST_CASE_P(Proto3, MutatorSingleFieldTest,
465 ValuesIn(GetFieldTestParams<Msg3>({
466 kOptionalFields, kOptionalNestedFields,
467 })));
468
TEST_P(MutatorSingleFieldTest,CrossOver)469 TEST_P(MutatorSingleFieldTest, CrossOver) {
470 LoadWithoutLine(m1_.get());
471 LoadMessage(m2_.get());
472
473 EXPECT_FALSE(MessageDifferencer::Equals(*m1_, *m2_));
474 TestMutator mutator(false);
475
476 int match_m1_ = 0;
477 int match_m2_ = 0;
478 int iterations = 1000;
479 std::unique_ptr<protobuf::Message> message(m1_->New());
480 for (int j = 0; j < iterations; ++j) {
481 message->CopyFrom(*m1_);
482 mutator.NoDeDupCrossOver(*m2_, message.get());
483 if (MessageDifferencer::Equals(*message, *m2_)) ++match_m2_;
484 if (MessageDifferencer::Equals(*message, *m1_)) ++match_m1_;
485 }
486
487 EXPECT_LT(iterations * .4, match_m1_);
488 EXPECT_GE(iterations * .6, match_m1_);
489 EXPECT_LT(iterations * .4, match_m2_);
490 EXPECT_GE(iterations * .6, match_m2_);
491 }
492
493 template <typename T>
494 class MutatorTypedTest : public ::testing::Test {
495 public:
496 using Message = T;
497 };
498
499 using MutatorTypedTestTypes = testing::Types<Msg, Msg3>;
500 TYPED_TEST_CASE(MutatorTypedTest, MutatorTypedTestTypes);
501
TYPED_TEST(MutatorTypedTest,CrossOverRepeated)502 TYPED_TEST(MutatorTypedTest, CrossOverRepeated) {
503 typename TestFixture::Message m1;
504 m1.add_repeated_int32(1);
505 m1.add_repeated_int32(2);
506 m1.add_repeated_int32(3);
507
508 typename TestFixture::Message m2;
509 m2.add_repeated_int32(4);
510 m2.add_repeated_int32(5);
511 m2.add_repeated_int32(6);
512
513 int iterations = 10000;
514 std::set<std::set<int>> sets;
515 TestMutator mutator(false);
516 for (int j = 0; j < iterations; ++j) {
517 typename TestFixture::Message message;
518 message.CopyFrom(m1);
519 mutator.NoDeDupCrossOver(m2, &message);
520 sets.insert(
521 {message.repeated_int32().begin(), message.repeated_int32().end()});
522 }
523
524 EXPECT_EQ(1u << 6, sets.size());
525 }
526
TYPED_TEST(MutatorTypedTest,CrossOverRepeatedMessages)527 TYPED_TEST(MutatorTypedTest, CrossOverRepeatedMessages) {
528 typename TestFixture::Message m1;
529 auto* rm1 = m1.add_repeated_msg();
530 rm1->add_repeated_int32(1);
531 rm1->add_repeated_int32(2);
532
533 typename TestFixture::Message m2;
534 auto* rm2 = m2.add_repeated_msg();
535 rm2->add_repeated_int32(3);
536 rm2->add_repeated_int32(4);
537 rm2->add_repeated_int32(5);
538 rm2->add_repeated_int32(6);
539
540 int iterations = 10000;
541 std::set<std::set<int>> sets;
542 TestMutator mutator(false);
543 for (int j = 0; j < iterations; ++j) {
544 typename TestFixture::Message message;
545 message.CopyFrom(m1);
546 mutator.NoDeDupCrossOver(m2, &message);
547 for (const auto& msg : message.repeated_msg())
548 sets.insert({msg.repeated_int32().begin(), msg.repeated_int32().end()});
549 }
550
551 EXPECT_EQ(1u << 6, sets.size());
552 }
553
TYPED_TEST(MutatorTypedTest,FailedMutations)554 TYPED_TEST(MutatorTypedTest, FailedMutations) {
555 TestMutator mutator(false);
556 size_t crossovers = 0;
557 for (int i = 0; i < 10000; ++i) {
558 typename TestFixture::Message messages[2];
559 typename TestFixture::Message tmp;
560 for (int j = 0; j < 20; ++j) {
561 for (auto& m : messages) {
562 tmp.CopyFrom(m);
563 mutator.Mutate(&m, 1000);
564 // Mutate must not produce the same result.
565 EXPECT_FALSE(MessageDifferencer::Equals(m, tmp));
566 }
567 }
568
569 tmp.CopyFrom(messages[1]);
570 mutator.CrossOver(messages[0], &tmp);
571 if (MessageDifferencer::Equals(tmp, messages[1]) ||
572 MessageDifferencer::Equals(tmp, messages[0]))
573 ++crossovers;
574 }
575
576 // CrossOver may fail but very rare.
577 EXPECT_LT(crossovers, 100u);
578 }
579
TYPED_TEST(MutatorTypedTest,Serialization)580 TYPED_TEST(MutatorTypedTest, Serialization) {
581 TestMutator mutator(false);
582 for (int i = 0; i < 10000; ++i) {
583 typename TestFixture::Message message;
584 for (int j = 0; j < 5; ++j) {
585 mutator.Mutate(&message, 1000);
586 typename TestFixture::Message parsed;
587
588 EXPECT_TRUE(ParseTextMessage(SaveMessageAsText(message), &parsed));
589 EXPECT_TRUE(MessageDifferencer::Equals(parsed, message));
590
591 EXPECT_TRUE(ParseBinaryMessage(SaveMessageAsBinary(message), &parsed));
592 EXPECT_TRUE(MessageDifferencer::Equals(parsed, message));
593 }
594 }
595 }
596
597 class MutatorMessagesTest : public MutatorTest {};
598 INSTANTIATE_TEST_CASE_P(Proto2, MutatorMessagesTest,
599 ValuesIn(GetMessageTestParams<Msg>({kMessages})));
600 INSTANTIATE_TEST_CASE_P(
601 Proto3, MutatorMessagesTest,
602 ValuesIn(GetMessageTestParams<Msg3>({kMessagesProto3})));
603
TEST_P(MutatorMessagesTest,DeletedMessage)604 TEST_P(MutatorMessagesTest, DeletedMessage) {
605 LoadMessage(m1_.get());
606 LoadWithoutLine(m2_.get());
607 EXPECT_TRUE(Mutate(*m1_, *m2_));
608 }
609
TEST_P(MutatorMessagesTest,InsertMessage)610 TEST_P(MutatorMessagesTest, InsertMessage) {
611 LoadWithoutLine(m1_.get());
612 LoadMessage(m2_.get());
613 EXPECT_TRUE(Mutate(*m1_, *m2_));
614 }
615
616 // TODO(vitalybuka): Special tests for oneof.
617
TEST(MutatorMessagesTest,UsageExample)618 TEST(MutatorMessagesTest, UsageExample) {
619 SmallMessage message;
620 TestMutator mutator(false);
621
622 // Test that we can generate all variation of the message.
623 std::set<std::string> mutations;
624 for (int j = 0; j < 1000; ++j) {
625 mutator.Mutate(&message, 1000);
626 std::string str = SaveMessageAsText(message);
627 mutations.insert(str);
628 }
629
630 // 3 states for boolean and 5 for enum, including missing fields.
631 EXPECT_EQ(3u * 5u, mutations.size());
632 }
633
TEST(MutatorMessagesTest,EmptyMessage)634 TEST(MutatorMessagesTest, EmptyMessage) {
635 EmptyMessage message;
636 TestMutator mutator(false);
637 for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
638 }
639
640
TEST(MutatorMessagesTest,Regressions)641 TEST(MutatorMessagesTest, Regressions) {
642 RegressionMessage message;
643 TestMutator mutator(false);
644 for (int j = 0; j < 10000; ++j) mutator.Mutate(&message, 1000);
645 }
646
647 } // namespace protobuf_mutator
648