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