12946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
22946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
32946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
410ab2aceSGeorge Karpenkov
510ab2aceSGeorge Karpenkov // Avoid ODR violations (LibFuzzer is built without ASan and this test is built
610ab2aceSGeorge Karpenkov // with ASan) involving C++ standard library types when using libcxx.
710ab2aceSGeorge Karpenkov #define _LIBCPP_HAS_NO_ASAN
810ab2aceSGeorge Karpenkov
9a451156bSSam McCall // Do not attempt to use LLVM ostream etc from gtest.
10a451156bSSam McCall #define GTEST_NO_LLVM_SUPPORT 1
1110ab2aceSGeorge Karpenkov
1210ab2aceSGeorge Karpenkov #include "FuzzerCorpus.h"
13c5d72517SMarco Vanotti #include "FuzzerDictionary.h"
1410ab2aceSGeorge Karpenkov #include "FuzzerInternal.h"
1510ab2aceSGeorge Karpenkov #include "FuzzerMerge.h"
1610ab2aceSGeorge Karpenkov #include "FuzzerMutate.h"
1710ab2aceSGeorge Karpenkov #include "FuzzerRandom.h"
1810ab2aceSGeorge Karpenkov #include "FuzzerTracePC.h"
1910ab2aceSGeorge Karpenkov #include "gtest/gtest.h"
2010ab2aceSGeorge Karpenkov #include <memory>
2110ab2aceSGeorge Karpenkov #include <set>
2210ab2aceSGeorge Karpenkov #include <sstream>
2310ab2aceSGeorge Karpenkov
2410ab2aceSGeorge Karpenkov using namespace fuzzer;
2510ab2aceSGeorge Karpenkov
2610ab2aceSGeorge Karpenkov // For now, have LLVMFuzzerTestOneInput just to make it link.
277c921753SKostya Serebryany // Later we may want to make unittests that actually call
287c921753SKostya Serebryany // LLVMFuzzerTestOneInput.
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)2910ab2aceSGeorge Karpenkov extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
3010ab2aceSGeorge Karpenkov abort();
3110ab2aceSGeorge Karpenkov }
3210ab2aceSGeorge Karpenkov
TEST(Fuzzer,Basename)331fd005f5SKostya Serebryany TEST(Fuzzer, Basename) {
341fd005f5SKostya Serebryany EXPECT_EQ(Basename("foo/bar"), "bar");
351fd005f5SKostya Serebryany EXPECT_EQ(Basename("bar"), "bar");
361fd005f5SKostya Serebryany EXPECT_EQ(Basename("/bar"), "bar");
371fd005f5SKostya Serebryany EXPECT_EQ(Basename("foo/x"), "x");
381fd005f5SKostya Serebryany EXPECT_EQ(Basename("foo/"), "");
397e042bb1SMatt Morehouse #if LIBFUZZER_WINDOWS
407e042bb1SMatt Morehouse EXPECT_EQ(Basename("foo\\bar"), "bar");
417e042bb1SMatt Morehouse EXPECT_EQ(Basename("foo\\bar/baz"), "baz");
427e042bb1SMatt Morehouse EXPECT_EQ(Basename("\\bar"), "bar");
437e042bb1SMatt Morehouse EXPECT_EQ(Basename("foo\\x"), "x");
447e042bb1SMatt Morehouse EXPECT_EQ(Basename("foo\\"), "");
457e042bb1SMatt Morehouse #endif
461fd005f5SKostya Serebryany }
471fd005f5SKostya Serebryany
TEST(Fuzzer,CrossOver)48c5d72517SMarco Vanotti TEST(Fuzzer, CrossOver) {
49c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
50c5d72517SMarco Vanotti fuzzer::EF = t.get();
51c5d72517SMarco Vanotti Random Rand(0);
52c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
53c5d72517SMarco Vanotti Unit A({0, 1, 2}), B({5, 6, 7});
54c5d72517SMarco Vanotti Unit C;
55c5d72517SMarco Vanotti Unit Expected[] = {
56c5d72517SMarco Vanotti { 0 },
57c5d72517SMarco Vanotti { 0, 1 },
58c5d72517SMarco Vanotti { 0, 5 },
59c5d72517SMarco Vanotti { 0, 1, 2 },
60c5d72517SMarco Vanotti { 0, 1, 5 },
61c5d72517SMarco Vanotti { 0, 5, 1 },
62c5d72517SMarco Vanotti { 0, 5, 6 },
63c5d72517SMarco Vanotti { 0, 1, 2, 5 },
64c5d72517SMarco Vanotti { 0, 1, 5, 2 },
65c5d72517SMarco Vanotti { 0, 1, 5, 6 },
66c5d72517SMarco Vanotti { 0, 5, 1, 2 },
67c5d72517SMarco Vanotti { 0, 5, 1, 6 },
68c5d72517SMarco Vanotti { 0, 5, 6, 1 },
69c5d72517SMarco Vanotti { 0, 5, 6, 7 },
70c5d72517SMarco Vanotti { 0, 1, 2, 5, 6 },
71c5d72517SMarco Vanotti { 0, 1, 5, 2, 6 },
72c5d72517SMarco Vanotti { 0, 1, 5, 6, 2 },
73c5d72517SMarco Vanotti { 0, 1, 5, 6, 7 },
74c5d72517SMarco Vanotti { 0, 5, 1, 2, 6 },
75c5d72517SMarco Vanotti { 0, 5, 1, 6, 2 },
76c5d72517SMarco Vanotti { 0, 5, 1, 6, 7 },
77c5d72517SMarco Vanotti { 0, 5, 6, 1, 2 },
78c5d72517SMarco Vanotti { 0, 5, 6, 1, 7 },
79c5d72517SMarco Vanotti { 0, 5, 6, 7, 1 },
80c5d72517SMarco Vanotti { 0, 1, 2, 5, 6, 7 },
81c5d72517SMarco Vanotti { 0, 1, 5, 2, 6, 7 },
82c5d72517SMarco Vanotti { 0, 1, 5, 6, 2, 7 },
83c5d72517SMarco Vanotti { 0, 1, 5, 6, 7, 2 },
84c5d72517SMarco Vanotti { 0, 5, 1, 2, 6, 7 },
85c5d72517SMarco Vanotti { 0, 5, 1, 6, 2, 7 },
86c5d72517SMarco Vanotti { 0, 5, 1, 6, 7, 2 },
87c5d72517SMarco Vanotti { 0, 5, 6, 1, 2, 7 },
88c5d72517SMarco Vanotti { 0, 5, 6, 1, 7, 2 },
89c5d72517SMarco Vanotti { 0, 5, 6, 7, 1, 2 }
90c5d72517SMarco Vanotti };
91c5d72517SMarco Vanotti for (size_t Len = 1; Len < 8; Len++) {
927c921753SKostya Serebryany std::set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
93c5d72517SMarco Vanotti for (int Iter = 0; Iter < 3000; Iter++) {
94c5d72517SMarco Vanotti C.resize(Len);
95c5d72517SMarco Vanotti size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(),
96c5d72517SMarco Vanotti C.data(), C.size());
97c5d72517SMarco Vanotti C.resize(NewSize);
98c5d72517SMarco Vanotti FoundUnits.insert(C);
99c5d72517SMarco Vanotti }
100c5d72517SMarco Vanotti for (const Unit &U : Expected)
101c5d72517SMarco Vanotti if (U.size() <= Len)
102c5d72517SMarco Vanotti ExpectedUnitsWitThisLength.insert(U);
103c5d72517SMarco Vanotti EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
104c5d72517SMarco Vanotti }
105c5d72517SMarco Vanotti }
106c5d72517SMarco Vanotti
TEST(Fuzzer,Hash)10710ab2aceSGeorge Karpenkov TEST(Fuzzer, Hash) {
10810ab2aceSGeorge Karpenkov uint8_t A[] = {'a', 'b', 'c'};
10910ab2aceSGeorge Karpenkov fuzzer::Unit U(A, A + sizeof(A));
11010ab2aceSGeorge Karpenkov EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U));
11110ab2aceSGeorge Karpenkov U.push_back('d');
11210ab2aceSGeorge Karpenkov EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
11310ab2aceSGeorge Karpenkov }
11410ab2aceSGeorge Karpenkov
115c5d72517SMarco Vanotti typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
116c5d72517SMarco Vanotti size_t MaxSize);
117c5d72517SMarco Vanotti
TestEraseBytes(Mutator M,int NumIter)118c5d72517SMarco Vanotti void TestEraseBytes(Mutator M, int NumIter) {
119c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
120c5d72517SMarco Vanotti fuzzer::EF = t.get();
121c5d72517SMarco Vanotti uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
122c5d72517SMarco Vanotti uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
123c5d72517SMarco Vanotti uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
124c5d72517SMarco Vanotti uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
125c5d72517SMarco Vanotti uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
126c5d72517SMarco Vanotti uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
127c5d72517SMarco Vanotti uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
128c5d72517SMarco Vanotti uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
129c5d72517SMarco Vanotti
130c5d72517SMarco Vanotti uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
131c5d72517SMarco Vanotti uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
132c5d72517SMarco Vanotti uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
133c5d72517SMarco Vanotti
134c5d72517SMarco Vanotti uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
135c5d72517SMarco Vanotti uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
136c5d72517SMarco Vanotti uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
137c5d72517SMarco Vanotti
138c5d72517SMarco Vanotti
139c5d72517SMarco Vanotti Random Rand(0);
140c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
141c5d72517SMarco Vanotti int FoundMask = 0;
142c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
143c5d72517SMarco Vanotti uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
144c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T));
145c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
146c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
147c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
148c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
149c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
150c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
151c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
152c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
153c5d72517SMarco Vanotti
154c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
155c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
156c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
157c5d72517SMarco Vanotti
158c5d72517SMarco Vanotti if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
159c5d72517SMarco Vanotti if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
160c5d72517SMarco Vanotti if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
161c5d72517SMarco Vanotti }
162c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, (1 << 14) - 1);
163c5d72517SMarco Vanotti }
164c5d72517SMarco Vanotti
TEST(FuzzerMutate,EraseBytes1)165c5d72517SMarco Vanotti TEST(FuzzerMutate, EraseBytes1) {
166c5d72517SMarco Vanotti TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
167c5d72517SMarco Vanotti }
TEST(FuzzerMutate,EraseBytes2)168c5d72517SMarco Vanotti TEST(FuzzerMutate, EraseBytes2) {
169c5d72517SMarco Vanotti TestEraseBytes(&MutationDispatcher::Mutate, 2000);
170c5d72517SMarco Vanotti }
171c5d72517SMarco Vanotti
TestInsertByte(Mutator M,int NumIter)172c5d72517SMarco Vanotti void TestInsertByte(Mutator M, int NumIter) {
173c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
174c5d72517SMarco Vanotti fuzzer::EF = t.get();
175c5d72517SMarco Vanotti Random Rand(0);
176c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
177c5d72517SMarco Vanotti int FoundMask = 0;
178c5d72517SMarco Vanotti uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
179c5d72517SMarco Vanotti uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
180c5d72517SMarco Vanotti uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
181c5d72517SMarco Vanotti uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
182c5d72517SMarco Vanotti uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
183c5d72517SMarco Vanotti uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
184c5d72517SMarco Vanotti uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
185c5d72517SMarco Vanotti uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
186c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
187c5d72517SMarco Vanotti uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
188c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 7, 8);
189c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0;
190c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1;
191c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2;
192c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3;
193c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4;
194c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
195c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
196c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
197c5d72517SMarco Vanotti }
198c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 255);
199c5d72517SMarco Vanotti }
200c5d72517SMarco Vanotti
TEST(FuzzerMutate,InsertByte1)201c5d72517SMarco Vanotti TEST(FuzzerMutate, InsertByte1) {
202c5d72517SMarco Vanotti TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
203c5d72517SMarco Vanotti }
TEST(FuzzerMutate,InsertByte2)204c5d72517SMarco Vanotti TEST(FuzzerMutate, InsertByte2) {
205c5d72517SMarco Vanotti TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
206c5d72517SMarco Vanotti }
207c5d72517SMarco Vanotti
TestInsertRepeatedBytes(Mutator M,int NumIter)208c5d72517SMarco Vanotti void TestInsertRepeatedBytes(Mutator M, int NumIter) {
209c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
210c5d72517SMarco Vanotti fuzzer::EF = t.get();
211c5d72517SMarco Vanotti Random Rand(0);
212c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
213c5d72517SMarco Vanotti int FoundMask = 0;
214c5d72517SMarco Vanotti uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
215c5d72517SMarco Vanotti uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
216c5d72517SMarco Vanotti uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
217c5d72517SMarco Vanotti uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
218c5d72517SMarco Vanotti uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
219c5d72517SMarco Vanotti
220c5d72517SMarco Vanotti uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
221c5d72517SMarco Vanotti uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
222c5d72517SMarco Vanotti uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
223c5d72517SMarco Vanotti uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
224c5d72517SMarco Vanotti uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
225c5d72517SMarco Vanotti
226c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
227c5d72517SMarco Vanotti uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
228c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 4, 8);
229c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
230c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
231c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
232c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
233c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
234c5d72517SMarco Vanotti
235c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
236c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
237c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
238c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
239c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
240c5d72517SMarco Vanotti
241c5d72517SMarco Vanotti }
242c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, (1 << 10) - 1);
243c5d72517SMarco Vanotti }
244c5d72517SMarco Vanotti
TEST(FuzzerMutate,InsertRepeatedBytes1)245c5d72517SMarco Vanotti TEST(FuzzerMutate, InsertRepeatedBytes1) {
2467c921753SKostya Serebryany TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes,
2477c921753SKostya Serebryany 10000);
248c5d72517SMarco Vanotti }
TEST(FuzzerMutate,InsertRepeatedBytes2)249c5d72517SMarco Vanotti TEST(FuzzerMutate, InsertRepeatedBytes2) {
250c5d72517SMarco Vanotti TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
251c5d72517SMarco Vanotti }
252c5d72517SMarco Vanotti
TestChangeByte(Mutator M,int NumIter)253c5d72517SMarco Vanotti void TestChangeByte(Mutator M, int NumIter) {
254c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
255c5d72517SMarco Vanotti fuzzer::EF = t.get();
256c5d72517SMarco Vanotti Random Rand(0);
257c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
258c5d72517SMarco Vanotti int FoundMask = 0;
259c5d72517SMarco Vanotti uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
260c5d72517SMarco Vanotti uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
261c5d72517SMarco Vanotti uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
262c5d72517SMarco Vanotti uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
263c5d72517SMarco Vanotti uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
264c5d72517SMarco Vanotti uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
265c5d72517SMarco Vanotti uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
266c5d72517SMarco Vanotti uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
267c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
268c5d72517SMarco Vanotti uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
269c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 8, 9);
270c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
271c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
272c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
273c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
274c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
275c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
276c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
277c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
278c5d72517SMarco Vanotti }
279c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 255);
280c5d72517SMarco Vanotti }
281c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeByte1)282c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeByte1) {
283c5d72517SMarco Vanotti TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
284c5d72517SMarco Vanotti }
TEST(FuzzerMutate,ChangeByte2)285c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeByte2) {
286c5d72517SMarco Vanotti TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
287c5d72517SMarco Vanotti }
288c5d72517SMarco Vanotti
TestChangeBit(Mutator M,int NumIter)289c5d72517SMarco Vanotti void TestChangeBit(Mutator M, int NumIter) {
290c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
291c5d72517SMarco Vanotti fuzzer::EF = t.get();
292c5d72517SMarco Vanotti Random Rand(0);
293c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
294c5d72517SMarco Vanotti int FoundMask = 0;
295c5d72517SMarco Vanotti uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
296c5d72517SMarco Vanotti uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
297c5d72517SMarco Vanotti uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
298c5d72517SMarco Vanotti uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
299c5d72517SMarco Vanotti uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
300c5d72517SMarco Vanotti uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
301c5d72517SMarco Vanotti uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
302c5d72517SMarco Vanotti uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
303c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
304c5d72517SMarco Vanotti uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
305c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 8, 9);
306c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
307c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
308c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
309c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
310c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
311c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
312c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
313c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
314c5d72517SMarco Vanotti }
315c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 255);
316c5d72517SMarco Vanotti }
317c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeBit1)318c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeBit1) {
319c5d72517SMarco Vanotti TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
320c5d72517SMarco Vanotti }
TEST(FuzzerMutate,ChangeBit2)321c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeBit2) {
322c5d72517SMarco Vanotti TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
323c5d72517SMarco Vanotti }
324c5d72517SMarco Vanotti
TestShuffleBytes(Mutator M,int NumIter)325c5d72517SMarco Vanotti void TestShuffleBytes(Mutator M, int NumIter) {
326c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
327c5d72517SMarco Vanotti fuzzer::EF = t.get();
328c5d72517SMarco Vanotti Random Rand(0);
329c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
330c5d72517SMarco Vanotti int FoundMask = 0;
331c5d72517SMarco Vanotti uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
332c5d72517SMarco Vanotti uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
333c5d72517SMarco Vanotti uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
334c5d72517SMarco Vanotti uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
335c5d72517SMarco Vanotti uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
336c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
337c5d72517SMarco Vanotti uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
338c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 7, 7);
339c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
340c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
341c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
342c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
343c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
344c5d72517SMarco Vanotti }
345c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 31);
346c5d72517SMarco Vanotti }
347c5d72517SMarco Vanotti
TEST(FuzzerMutate,ShuffleBytes1)348c5d72517SMarco Vanotti TEST(FuzzerMutate, ShuffleBytes1) {
349c5d72517SMarco Vanotti TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17);
350c5d72517SMarco Vanotti }
TEST(FuzzerMutate,ShuffleBytes2)351c5d72517SMarco Vanotti TEST(FuzzerMutate, ShuffleBytes2) {
352c5d72517SMarco Vanotti TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
353c5d72517SMarco Vanotti }
354c5d72517SMarco Vanotti
TestCopyPart(Mutator M,int NumIter)355c5d72517SMarco Vanotti void TestCopyPart(Mutator M, int NumIter) {
356c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
357c5d72517SMarco Vanotti fuzzer::EF = t.get();
358c5d72517SMarco Vanotti Random Rand(0);
359c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
360c5d72517SMarco Vanotti int FoundMask = 0;
361c5d72517SMarco Vanotti uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
362c5d72517SMarco Vanotti uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
363c5d72517SMarco Vanotti uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
364c5d72517SMarco Vanotti uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
365c5d72517SMarco Vanotti uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
366c5d72517SMarco Vanotti
367c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
368c5d72517SMarco Vanotti uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
369c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 7, 7);
370c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
371c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
372c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
373c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
374c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
375c5d72517SMarco Vanotti }
376c5d72517SMarco Vanotti
377c5d72517SMarco Vanotti uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
378c5d72517SMarco Vanotti uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
379c5d72517SMarco Vanotti uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
380c5d72517SMarco Vanotti uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
381c5d72517SMarco Vanotti uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
382c5d72517SMarco Vanotti
383c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
384c5d72517SMarco Vanotti uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
385c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 5, 8);
386c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
387c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
388c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
389c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
390c5d72517SMarco Vanotti if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
391c5d72517SMarco Vanotti }
392c5d72517SMarco Vanotti
393c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 1023);
394c5d72517SMarco Vanotti }
395c5d72517SMarco Vanotti
TEST(FuzzerMutate,CopyPart1)396c5d72517SMarco Vanotti TEST(FuzzerMutate, CopyPart1) {
397c5d72517SMarco Vanotti TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
398c5d72517SMarco Vanotti }
TEST(FuzzerMutate,CopyPart2)399c5d72517SMarco Vanotti TEST(FuzzerMutate, CopyPart2) {
400c5d72517SMarco Vanotti TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
401c5d72517SMarco Vanotti }
TEST(FuzzerMutate,CopyPartNoInsertAtMaxSize)402c5d72517SMarco Vanotti TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) {
403c5d72517SMarco Vanotti // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an
404c5d72517SMarco Vanotti // insert on an input of size `MaxSize`. Performing an insert in this case
405c5d72517SMarco Vanotti // will lead to the mutation failing.
406c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
407c5d72517SMarco Vanotti fuzzer::EF = t.get();
408c5d72517SMarco Vanotti Random Rand(0);
409c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
410c5d72517SMarco Vanotti uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
411c5d72517SMarco Vanotti size_t MaxSize = sizeof(Data);
412c5d72517SMarco Vanotti for (int count = 0; count < (1 << 18); ++count) {
413c5d72517SMarco Vanotti size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize);
414c5d72517SMarco Vanotti ASSERT_EQ(NewSize, MaxSize);
415c5d72517SMarco Vanotti }
416c5d72517SMarco Vanotti }
417c5d72517SMarco Vanotti
TestAddWordFromDictionary(Mutator M,int NumIter)418c5d72517SMarco Vanotti void TestAddWordFromDictionary(Mutator M, int NumIter) {
419c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
420c5d72517SMarco Vanotti fuzzer::EF = t.get();
421c5d72517SMarco Vanotti Random Rand(0);
422c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
423c5d72517SMarco Vanotti uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
424c5d72517SMarco Vanotti uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
425c5d72517SMarco Vanotti MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
426c5d72517SMarco Vanotti MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
427c5d72517SMarco Vanotti int FoundMask = 0;
428c5d72517SMarco Vanotti uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
429c5d72517SMarco Vanotti uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
430c5d72517SMarco Vanotti uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
431c5d72517SMarco Vanotti uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
432c5d72517SMarco Vanotti uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
433c5d72517SMarco Vanotti uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
434c5d72517SMarco Vanotti uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
435c5d72517SMarco Vanotti uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
436c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
437c5d72517SMarco Vanotti uint8_t T[7] = {0x00, 0x11, 0x22};
438c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 3, 7);
439c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
440c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
441c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
442c5d72517SMarco Vanotti if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
443c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
444c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
445c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
446c5d72517SMarco Vanotti if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
447c5d72517SMarco Vanotti }
448c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 255);
449c5d72517SMarco Vanotti }
450c5d72517SMarco Vanotti
TEST(FuzzerMutate,AddWordFromDictionary1)451c5d72517SMarco Vanotti TEST(FuzzerMutate, AddWordFromDictionary1) {
452c5d72517SMarco Vanotti TestAddWordFromDictionary(
453c5d72517SMarco Vanotti &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
454c5d72517SMarco Vanotti }
455c5d72517SMarco Vanotti
TEST(FuzzerMutate,AddWordFromDictionary2)456c5d72517SMarco Vanotti TEST(FuzzerMutate, AddWordFromDictionary2) {
457c5d72517SMarco Vanotti TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
458c5d72517SMarco Vanotti }
459c5d72517SMarco Vanotti
TestChangeASCIIInteger(Mutator M,int NumIter)460c5d72517SMarco Vanotti void TestChangeASCIIInteger(Mutator M, int NumIter) {
461c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
462c5d72517SMarco Vanotti fuzzer::EF = t.get();
463c5d72517SMarco Vanotti Random Rand(0);
464c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
465c5d72517SMarco Vanotti
466c5d72517SMarco Vanotti uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
467c5d72517SMarco Vanotti uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
468c5d72517SMarco Vanotti uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
469c5d72517SMarco Vanotti uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
470c5d72517SMarco Vanotti int FoundMask = 0;
471c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
472c5d72517SMarco Vanotti uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
473c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 8, 8);
474c5d72517SMarco Vanotti /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
475c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
476c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
477c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
478c5d72517SMarco Vanotti else if (NewSize == 8) FoundMask |= 1 << 4;
479c5d72517SMarco Vanotti }
480c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 31);
481c5d72517SMarco Vanotti }
482c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeASCIIInteger1)483c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeASCIIInteger1) {
484c5d72517SMarco Vanotti TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
485c5d72517SMarco Vanotti 1 << 15);
486c5d72517SMarco Vanotti }
487c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeASCIIInteger2)488c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeASCIIInteger2) {
489c5d72517SMarco Vanotti TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
490c5d72517SMarco Vanotti }
491c5d72517SMarco Vanotti
TestChangeBinaryInteger(Mutator M,int NumIter)492c5d72517SMarco Vanotti void TestChangeBinaryInteger(Mutator M, int NumIter) {
493c5d72517SMarco Vanotti std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
494c5d72517SMarco Vanotti fuzzer::EF = t.get();
495c5d72517SMarco Vanotti Random Rand(0);
496c5d72517SMarco Vanotti std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {}));
497c5d72517SMarco Vanotti
498c5d72517SMarco Vanotti uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
499c5d72517SMarco Vanotti uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
500c5d72517SMarco Vanotti uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
501c5d72517SMarco Vanotti uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
502c5d72517SMarco Vanotti uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
503c5d72517SMarco Vanotti uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
504c5d72517SMarco Vanotti uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
505c5d72517SMarco Vanotti uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
506c5d72517SMarco Vanotti
507c5d72517SMarco Vanotti int FoundMask = 0;
508c5d72517SMarco Vanotti for (int i = 0; i < NumIter; i++) {
509c5d72517SMarco Vanotti uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
510c5d72517SMarco Vanotti size_t NewSize = (*MD.*M)(T, 8, 8);
511c5d72517SMarco Vanotti /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
512c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
513c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
514c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
515c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
516c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
517c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
518c5d72517SMarco Vanotti else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
519c5d72517SMarco Vanotti }
520c5d72517SMarco Vanotti EXPECT_EQ(FoundMask, 255);
521c5d72517SMarco Vanotti }
522c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeBinaryInteger1)523c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeBinaryInteger1) {
524c5d72517SMarco Vanotti TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
525c5d72517SMarco Vanotti 1 << 12);
526c5d72517SMarco Vanotti }
527c5d72517SMarco Vanotti
TEST(FuzzerMutate,ChangeBinaryInteger2)528c5d72517SMarco Vanotti TEST(FuzzerMutate, ChangeBinaryInteger2) {
529c5d72517SMarco Vanotti TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
530c5d72517SMarco Vanotti }
531c5d72517SMarco Vanotti
532c5d72517SMarco Vanotti
TEST(FuzzerDictionary,ParseOneDictionaryEntry)53310ab2aceSGeorge Karpenkov TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
53410ab2aceSGeorge Karpenkov Unit U;
53510ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry("", &U));
53610ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U));
53710ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U));
53810ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U));
53910ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U));
54010ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U));
54110ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U));
54210ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U));
54310ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'a'}));
54410ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U));
54510ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
54610ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U));
54710ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
54810ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U));
54910ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U));
55010ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'\\'}));
55110ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U));
55210ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({0xAB}));
55310ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U));
55410ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE}));
55510ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U));
55610ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'#'}));
55710ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U));
55810ab2aceSGeorge Karpenkov EXPECT_EQ(U, Unit({'"'}));
55910ab2aceSGeorge Karpenkov }
56010ab2aceSGeorge Karpenkov
TEST(FuzzerDictionary,ParseDictionaryFile)56110ab2aceSGeorge Karpenkov TEST(FuzzerDictionary, ParseDictionaryFile) {
5627c921753SKostya Serebryany std::vector<Unit> Units;
56310ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units));
56410ab2aceSGeorge Karpenkov EXPECT_FALSE(ParseDictionaryFile("", &Units));
56510ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseDictionaryFile("\n", &Units));
56610ab2aceSGeorge Karpenkov EXPECT_EQ(Units.size(), 0U);
56710ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units));
56810ab2aceSGeorge Karpenkov EXPECT_EQ(Units.size(), 0U);
56910ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
57010ab2aceSGeorge Karpenkov EXPECT_EQ(Units.size(), 0U);
57110ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
57210ab2aceSGeorge Karpenkov EXPECT_EQ(Units.size(), 0U);
57310ab2aceSGeorge Karpenkov EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units));
5747c921753SKostya Serebryany EXPECT_EQ(Units, std::vector<Unit>({Unit({'a', 'a'})}));
57510ab2aceSGeorge Karpenkov EXPECT_TRUE(
57610ab2aceSGeorge Karpenkov ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units));
57710ab2aceSGeorge Karpenkov EXPECT_EQ(Units,
5787c921753SKostya Serebryany std::vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})}));
57910ab2aceSGeorge Karpenkov }
58010ab2aceSGeorge Karpenkov
TEST(FuzzerUtil,Base64)58110ab2aceSGeorge Karpenkov TEST(FuzzerUtil, Base64) {
58210ab2aceSGeorge Karpenkov EXPECT_EQ("", Base64({}));
58310ab2aceSGeorge Karpenkov EXPECT_EQ("YQ==", Base64({'a'}));
58410ab2aceSGeorge Karpenkov EXPECT_EQ("eA==", Base64({'x'}));
58510ab2aceSGeorge Karpenkov EXPECT_EQ("YWI=", Base64({'a', 'b'}));
58610ab2aceSGeorge Karpenkov EXPECT_EQ("eHk=", Base64({'x', 'y'}));
58710ab2aceSGeorge Karpenkov EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'}));
58810ab2aceSGeorge Karpenkov EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'}));
58910ab2aceSGeorge Karpenkov EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'}));
59010ab2aceSGeorge Karpenkov EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'}));
59110ab2aceSGeorge Karpenkov EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'}));
59210ab2aceSGeorge Karpenkov }
59310ab2aceSGeorge Karpenkov
594c7bd6435SHans Wennborg #ifdef __GLIBC__
595c7bd6435SHans Wennborg class PrintfCapture {
596c7bd6435SHans Wennborg public:
PrintfCapture()597c7bd6435SHans Wennborg PrintfCapture() {
598c7bd6435SHans Wennborg OldOutputFile = GetOutputFile();
599c7bd6435SHans Wennborg SetOutputFile(open_memstream(&Buffer, &Size));
600c7bd6435SHans Wennborg }
~PrintfCapture()601c7bd6435SHans Wennborg ~PrintfCapture() {
602c7bd6435SHans Wennborg fclose(GetOutputFile());
603c7bd6435SHans Wennborg SetOutputFile(OldOutputFile);
604c7bd6435SHans Wennborg free(Buffer);
605c7bd6435SHans Wennborg }
str()606c7bd6435SHans Wennborg std::string str() { return std::string(Buffer, Size); }
607c7bd6435SHans Wennborg
608c7bd6435SHans Wennborg private:
609c7bd6435SHans Wennborg char *Buffer;
610c7bd6435SHans Wennborg size_t Size;
611c7bd6435SHans Wennborg FILE *OldOutputFile;
612c7bd6435SHans Wennborg };
613c7bd6435SHans Wennborg
TEST(FuzzerUtil,PrintASCII)614c7bd6435SHans Wennborg TEST(FuzzerUtil, PrintASCII) {
615c7bd6435SHans Wennborg auto f = [](const char *Str, const char *PrintAfter = "") {
616c7bd6435SHans Wennborg PrintfCapture Capture;
617c7bd6435SHans Wennborg PrintASCII(reinterpret_cast<const uint8_t*>(Str), strlen(Str), PrintAfter);
618c7bd6435SHans Wennborg return Capture.str();
619c7bd6435SHans Wennborg };
620c7bd6435SHans Wennborg EXPECT_EQ("hello", f("hello"));
621c7bd6435SHans Wennborg EXPECT_EQ("c:\\\\", f("c:\\"));
622c7bd6435SHans Wennborg EXPECT_EQ("\\\"hi\\\"", f("\"hi\""));
623c7bd6435SHans Wennborg EXPECT_EQ("\\011a", f("\ta"));
624c7bd6435SHans Wennborg EXPECT_EQ("\\0111", f("\t1"));
625c7bd6435SHans Wennborg EXPECT_EQ("hello\\012", f("hello\n"));
626c7bd6435SHans Wennborg EXPECT_EQ("hello\n", f("hello", "\n"));
627c7bd6435SHans Wennborg }
628c7bd6435SHans Wennborg #endif
629c7bd6435SHans Wennborg
TEST(Corpus,Distribution)63010ab2aceSGeorge Karpenkov TEST(Corpus, Distribution) {
63167af9923SKostya Serebryany DataFlowTrace DFT;
63210ab2aceSGeorge Karpenkov Random Rand(0);
633dde16ef0SHubert Tong struct EntropicOptions Entropic = {false, 0xFF, 100, false};
634e2e38fcaSMatt Morehouse std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
63510ab2aceSGeorge Karpenkov size_t N = 10;
63610ab2aceSGeorge Karpenkov size_t TriesPerUnit = 1<<16;
63710ab2aceSGeorge Karpenkov for (size_t i = 0; i < N; i++)
63862673c43SDokyung Song C->AddToCorpus(Unit{static_cast<uint8_t>(i)}, /*NumFeatures*/ 1,
63962673c43SDokyung Song /*MayDeleteFile*/ false, /*HasFocusFunction*/ false,
6405cda4dc7SDokyung Song /*ForceAddToCorpus*/ false,
6415cda4dc7SDokyung Song /*TimeOfUnit*/ std::chrono::microseconds(0),
6425cda4dc7SDokyung Song /*FeatureSet*/ {}, DFT,
64362673c43SDokyung Song /*BaseII*/ nullptr);
64410ab2aceSGeorge Karpenkov
6457c921753SKostya Serebryany std::vector<size_t> Hist(N);
64610ab2aceSGeorge Karpenkov for (size_t i = 0; i < N * TriesPerUnit; i++) {
64710ab2aceSGeorge Karpenkov Hist[C->ChooseUnitIdxToMutate(Rand)]++;
64810ab2aceSGeorge Karpenkov }
64910ab2aceSGeorge Karpenkov for (size_t i = 0; i < N; i++) {
65010ab2aceSGeorge Karpenkov // A weak sanity check that every unit gets invoked.
65110ab2aceSGeorge Karpenkov EXPECT_GT(Hist[i], TriesPerUnit / N / 3);
65210ab2aceSGeorge Karpenkov }
65310ab2aceSGeorge Karpenkov }
65410ab2aceSGeorge Karpenkov
TEST(Corpus,Replace)6559e7b7303SPZ Read TEST(Corpus, Replace) {
6569e7b7303SPZ Read DataFlowTrace DFT;
6579e7b7303SPZ Read struct EntropicOptions Entropic = {false, 0xFF, 100, false};
6589e7b7303SPZ Read std::unique_ptr<InputCorpus> C(
6599e7b7303SPZ Read new InputCorpus(/*OutputCorpus*/ "", Entropic));
6609e7b7303SPZ Read InputInfo *FirstII =
6619e7b7303SPZ Read C->AddToCorpus(Unit{0x01, 0x00}, /*NumFeatures*/ 1,
6629e7b7303SPZ Read /*MayDeleteFile*/ false, /*HasFocusFunction*/ false,
6639e7b7303SPZ Read /*ForceAddToCorpus*/ false,
6649e7b7303SPZ Read /*TimeOfUnit*/ std::chrono::microseconds(1234),
6659e7b7303SPZ Read /*FeatureSet*/ {}, DFT,
6669e7b7303SPZ Read /*BaseII*/ nullptr);
6679e7b7303SPZ Read InputInfo *SecondII =
6689e7b7303SPZ Read C->AddToCorpus(Unit{0x02}, /*NumFeatures*/ 1,
6699e7b7303SPZ Read /*MayDeleteFile*/ false, /*HasFocusFunction*/ false,
6709e7b7303SPZ Read /*ForceAddToCorpus*/ false,
6719e7b7303SPZ Read /*TimeOfUnit*/ std::chrono::microseconds(5678),
6729e7b7303SPZ Read /*FeatureSet*/ {}, DFT,
6739e7b7303SPZ Read /*BaseII*/ nullptr);
6749e7b7303SPZ Read Unit ReplacedU = Unit{0x03};
6759e7b7303SPZ Read
6769e7b7303SPZ Read C->Replace(FirstII, ReplacedU,
6779e7b7303SPZ Read /*TimeOfUnit*/ std::chrono::microseconds(321));
6789e7b7303SPZ Read
679*082d2ad0SMatt Morehouse // FirstII should be replaced.
6809e7b7303SPZ Read EXPECT_EQ(FirstII->U, Unit{0x03});
6819e7b7303SPZ Read EXPECT_EQ(FirstII->Reduced, true);
6829e7b7303SPZ Read EXPECT_EQ(FirstII->TimeOfUnit, std::chrono::microseconds(321));
6839e7b7303SPZ Read std::vector<uint8_t> ExpectedSha1(kSHA1NumBytes);
6849e7b7303SPZ Read ComputeSHA1(ReplacedU.data(), ReplacedU.size(), ExpectedSha1.data());
6859e7b7303SPZ Read std::vector<uint8_t> IISha1(FirstII->Sha1, FirstII->Sha1 + kSHA1NumBytes);
6869e7b7303SPZ Read EXPECT_EQ(IISha1, ExpectedSha1);
687*082d2ad0SMatt Morehouse
688*082d2ad0SMatt Morehouse // SecondII should not be replaced.
689*082d2ad0SMatt Morehouse EXPECT_EQ(SecondII->U, Unit{0x02});
690*082d2ad0SMatt Morehouse EXPECT_EQ(SecondII->Reduced, false);
691*082d2ad0SMatt Morehouse EXPECT_EQ(SecondII->TimeOfUnit, std::chrono::microseconds(5678));
6929e7b7303SPZ Read }
6939e7b7303SPZ Read
6947c921753SKostya Serebryany template <typename T>
EQ(const std::vector<T> & A,const std::vector<T> & B)6957c921753SKostya Serebryany void EQ(const std::vector<T> &A, const std::vector<T> &B) {
69610ab2aceSGeorge Karpenkov EXPECT_EQ(A, B);
69710ab2aceSGeorge Karpenkov }
69810ab2aceSGeorge Karpenkov
EQ(const std::set<T> & A,const std::vector<T> & B)6997c921753SKostya Serebryany template <typename T> void EQ(const std::set<T> &A, const std::vector<T> &B) {
7007c921753SKostya Serebryany EXPECT_EQ(A, std::set<T>(B.begin(), B.end()));
7010fe4701eSMarco Vanotti }
7020fe4701eSMarco Vanotti
EQ(const std::vector<MergeFileInfo> & A,const std::vector<std::string> & B)7037c921753SKostya Serebryany void EQ(const std::vector<MergeFileInfo> &A,
7047c921753SKostya Serebryany const std::vector<std::string> &B) {
7057c921753SKostya Serebryany std::set<std::string> a;
7060fe4701eSMarco Vanotti for (const auto &File : A)
7070fe4701eSMarco Vanotti a.insert(File.Name);
7087c921753SKostya Serebryany std::set<std::string> b(B.begin(), B.end());
70910ab2aceSGeorge Karpenkov EXPECT_EQ(a, b);
71010ab2aceSGeorge Karpenkov }
71110ab2aceSGeorge Karpenkov
7120fe4701eSMarco Vanotti #define TRACED_EQ(A, ...) \
7130fe4701eSMarco Vanotti { \
7140fe4701eSMarco Vanotti SCOPED_TRACE(#A); \
7150fe4701eSMarco Vanotti EQ(A, __VA_ARGS__); \
71610ab2aceSGeorge Karpenkov }
71710ab2aceSGeorge Karpenkov
TEST(Merger,Parse)7180fe4701eSMarco Vanotti TEST(Merger, Parse) {
71910ab2aceSGeorge Karpenkov Merger M;
72010ab2aceSGeorge Karpenkov
7210fe4701eSMarco Vanotti const char *kInvalidInputs[] = {
7220fe4701eSMarco Vanotti // Bad file numbers
7230fe4701eSMarco Vanotti "",
7240fe4701eSMarco Vanotti "x",
7250fe4701eSMarco Vanotti "0\n0",
7260fe4701eSMarco Vanotti "3\nx",
7270fe4701eSMarco Vanotti "2\n3",
7280fe4701eSMarco Vanotti "2\n2",
7290fe4701eSMarco Vanotti // Bad file names
7300fe4701eSMarco Vanotti "2\n2\nA\n",
7310fe4701eSMarco Vanotti "2\n2\nA\nB\nC\n",
7320fe4701eSMarco Vanotti // Unknown markers
7330fe4701eSMarco Vanotti "2\n1\nA\nSTARTED 0\nBAD 0 0x0",
7340fe4701eSMarco Vanotti // Bad file IDs
7350fe4701eSMarco Vanotti "1\n1\nA\nSTARTED 1",
7360fe4701eSMarco Vanotti "2\n1\nA\nSTARTED 0\nFT 1 0x0",
7370fe4701eSMarco Vanotti };
7380fe4701eSMarco Vanotti for (auto S : kInvalidInputs) {
7390fe4701eSMarco Vanotti SCOPED_TRACE(S);
7400fe4701eSMarco Vanotti EXPECT_FALSE(M.Parse(S, false));
7410fe4701eSMarco Vanotti }
7420fe4701eSMarco Vanotti
7430fe4701eSMarco Vanotti // Parse initial control file
74410ab2aceSGeorge Karpenkov EXPECT_TRUE(M.Parse("1\n0\nAA\n", false));
7450fe4701eSMarco Vanotti ASSERT_EQ(M.Files.size(), 1U);
74610ab2aceSGeorge Karpenkov EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
74710ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[0].Name, "AA");
74810ab2aceSGeorge Karpenkov EXPECT_TRUE(M.LastFailure.empty());
74910ab2aceSGeorge Karpenkov EXPECT_EQ(M.FirstNotProcessedFile, 0U);
75010ab2aceSGeorge Karpenkov
7510fe4701eSMarco Vanotti // Parse control file that failed on first attempt
75210ab2aceSGeorge Karpenkov EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false));
7530fe4701eSMarco Vanotti ASSERT_EQ(M.Files.size(), 2U);
75410ab2aceSGeorge Karpenkov EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
75510ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[0].Name, "AA");
75610ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[1].Name, "BB");
75710ab2aceSGeorge Karpenkov EXPECT_EQ(M.LastFailure, "AA");
75810ab2aceSGeorge Karpenkov EXPECT_EQ(M.FirstNotProcessedFile, 1U);
75910ab2aceSGeorge Karpenkov
7600fe4701eSMarco Vanotti // Parse control file that failed on later attempt
76110ab2aceSGeorge Karpenkov EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
76210ab2aceSGeorge Karpenkov "STARTED 0 1000\n"
76396f81bc6SKostya Serebryany "FT 0 1 2 3\n"
76410ab2aceSGeorge Karpenkov "STARTED 1 1001\n"
76596f81bc6SKostya Serebryany "FT 1 4 5 6 \n"
76610ab2aceSGeorge Karpenkov "STARTED 2 1002\n"
7670fe4701eSMarco Vanotti "",
7680fe4701eSMarco Vanotti true));
7690fe4701eSMarco Vanotti ASSERT_EQ(M.Files.size(), 3U);
77010ab2aceSGeorge Karpenkov EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
77110ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[0].Name, "AA");
77210ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[0].Size, 1000U);
77310ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[1].Name, "BB");
77410ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[1].Size, 1001U);
77510ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[2].Name, "C");
77610ab2aceSGeorge Karpenkov EXPECT_EQ(M.Files[2].Size, 1002U);
77710ab2aceSGeorge Karpenkov EXPECT_EQ(M.LastFailure, "C");
77810ab2aceSGeorge Karpenkov EXPECT_EQ(M.FirstNotProcessedFile, 3U);
7790fe4701eSMarco Vanotti TRACED_EQ(M.Files[0].Features, {1, 2, 3});
7800fe4701eSMarco Vanotti TRACED_EQ(M.Files[1].Features, {4, 5, 6});
78110ab2aceSGeorge Karpenkov
7820fe4701eSMarco Vanotti // Parse control file without features or PCs
7830fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("2\n0\nAA\nBB\n"
7840fe4701eSMarco Vanotti "STARTED 0 1000\n"
7850fe4701eSMarco Vanotti "FT 0\n"
7860fe4701eSMarco Vanotti "COV 0\n"
7870fe4701eSMarco Vanotti "STARTED 1 1001\n"
7880fe4701eSMarco Vanotti "FT 1\n"
7890fe4701eSMarco Vanotti "COV 1\n"
7900fe4701eSMarco Vanotti "",
7910fe4701eSMarco Vanotti true));
7920fe4701eSMarco Vanotti ASSERT_EQ(M.Files.size(), 2U);
7930fe4701eSMarco Vanotti EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
7940fe4701eSMarco Vanotti EXPECT_TRUE(M.LastFailure.empty());
7950fe4701eSMarco Vanotti EXPECT_EQ(M.FirstNotProcessedFile, 2U);
7960fe4701eSMarco Vanotti EXPECT_TRUE(M.Files[0].Features.empty());
7970fe4701eSMarco Vanotti EXPECT_TRUE(M.Files[0].Cov.empty());
7980fe4701eSMarco Vanotti EXPECT_TRUE(M.Files[1].Features.empty());
7990fe4701eSMarco Vanotti EXPECT_TRUE(M.Files[1].Cov.empty());
80010ab2aceSGeorge Karpenkov
8010fe4701eSMarco Vanotti // Parse features and PCs
80210ab2aceSGeorge Karpenkov EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
8030fe4701eSMarco Vanotti "STARTED 0 1000\n"
8040fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8050fe4701eSMarco Vanotti "COV 0 11 12 13\n"
8060fe4701eSMarco Vanotti "STARTED 1 1001\n"
8070fe4701eSMarco Vanotti "FT 1 4 5 6\n"
8080fe4701eSMarco Vanotti "COV 1 7 8 9\n"
8090fe4701eSMarco Vanotti "STARTED 2 1002\n"
8100fe4701eSMarco Vanotti "FT 2 6 1 3\n"
8110fe4701eSMarco Vanotti "COV 2 16 11 13\n"
8120fe4701eSMarco Vanotti "",
8130fe4701eSMarco Vanotti true));
8140fe4701eSMarco Vanotti ASSERT_EQ(M.Files.size(), 3U);
81510ab2aceSGeorge Karpenkov EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
81610ab2aceSGeorge Karpenkov EXPECT_TRUE(M.LastFailure.empty());
81710ab2aceSGeorge Karpenkov EXPECT_EQ(M.FirstNotProcessedFile, 3U);
8180fe4701eSMarco Vanotti TRACED_EQ(M.Files[0].Features, {1, 2, 3});
8190fe4701eSMarco Vanotti TRACED_EQ(M.Files[0].Cov, {11, 12, 13});
8200fe4701eSMarco Vanotti TRACED_EQ(M.Files[1].Features, {4, 5, 6});
8210fe4701eSMarco Vanotti TRACED_EQ(M.Files[1].Cov, {7, 8, 9});
8220fe4701eSMarco Vanotti TRACED_EQ(M.Files[2].Features, {1, 3, 6});
8230fe4701eSMarco Vanotti TRACED_EQ(M.Files[2].Cov, {16});
8240fe4701eSMarco Vanotti }
82510ab2aceSGeorge Karpenkov
TEST(Merger,Merge)8260fe4701eSMarco Vanotti TEST(Merger, Merge) {
8270fe4701eSMarco Vanotti Merger M;
8287c921753SKostya Serebryany std::set<uint32_t> Features, NewFeatures;
8297c921753SKostya Serebryany std::set<uint32_t> Cov, NewCov;
8307c921753SKostya Serebryany std::vector<std::string> NewFiles;
8310fe4701eSMarco Vanotti
8320fe4701eSMarco Vanotti // Adds new files and features
8330fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
8340fe4701eSMarco Vanotti "STARTED 0 1000\n"
8350fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8360fe4701eSMarco Vanotti "STARTED 1 1001\n"
8370fe4701eSMarco Vanotti "FT 1 4 5 6 \n"
8380fe4701eSMarco Vanotti "STARTED 2 1002\n"
8390fe4701eSMarco Vanotti "FT 2 6 1 3\n"
8400fe4701eSMarco Vanotti "",
8410fe4701eSMarco Vanotti true));
8420fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
8430fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B", "C"});
8440fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"A", "B"});
8450fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
8460fe4701eSMarco Vanotti
8470fe4701eSMarco Vanotti // Doesn't return features or files in the initial corpus.
84810ab2aceSGeorge Karpenkov EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
8490fe4701eSMarco Vanotti "STARTED 0 1000\n"
8500fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8510fe4701eSMarco Vanotti "STARTED 1 1001\n"
8520fe4701eSMarco Vanotti "FT 1 4 5 6 \n"
8530fe4701eSMarco Vanotti "STARTED 2 1002\n"
8540fe4701eSMarco Vanotti "FT 2 6 1 3\n"
8550fe4701eSMarco Vanotti "",
8560fe4701eSMarco Vanotti true));
8570fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
8580fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B", "C"});
8590fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"B"});
8600fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {4, 5, 6});
86110ab2aceSGeorge Karpenkov
8620fe4701eSMarco Vanotti // No new features, so no new files
8630fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n"
8640fe4701eSMarco Vanotti "STARTED 0 1000\n"
8650fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8660fe4701eSMarco Vanotti "STARTED 1 1001\n"
8670fe4701eSMarco Vanotti "FT 1 4 5 6 \n"
8680fe4701eSMarco Vanotti "STARTED 2 1002\n"
8690fe4701eSMarco Vanotti "FT 2 6 1 3\n"
8700fe4701eSMarco Vanotti "",
8710fe4701eSMarco Vanotti true));
8720fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 0U);
8730fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B", "C"});
8740fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {});
8750fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {});
8760fe4701eSMarco Vanotti
8770fe4701eSMarco Vanotti // Can pass initial features and coverage.
8780fe4701eSMarco Vanotti Features = {1, 2, 3};
8790fe4701eSMarco Vanotti Cov = {};
8800fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("2\n0\nA\nB\n"
8810fe4701eSMarco Vanotti "STARTED 0 1000\n"
8820fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8830fe4701eSMarco Vanotti "STARTED 1 1001\n"
8840fe4701eSMarco Vanotti "FT 1 4 5 6\n"
8850fe4701eSMarco Vanotti "",
8860fe4701eSMarco Vanotti true));
8870fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
8880fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B"});
8890fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"B"});
8900fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {4, 5, 6});
8910fe4701eSMarco Vanotti Features.clear();
8920fe4701eSMarco Vanotti Cov.clear();
8930fe4701eSMarco Vanotti
8940fe4701eSMarco Vanotti // Parse smaller files first
8950fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
8960fe4701eSMarco Vanotti "STARTED 0 2000\n"
8970fe4701eSMarco Vanotti "FT 0 1 2 3\n"
8980fe4701eSMarco Vanotti "STARTED 1 1001\n"
8990fe4701eSMarco Vanotti "FT 1 4 5 6 \n"
9000fe4701eSMarco Vanotti "STARTED 2 1002\n"
9010fe4701eSMarco Vanotti "FT 2 6 1 3 \n"
9020fe4701eSMarco Vanotti "",
9030fe4701eSMarco Vanotti true));
9040fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
9050fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"B", "C", "A"});
9060fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"B", "C", "A"});
9070fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
9080fe4701eSMarco Vanotti
9090fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n"
9100fe4701eSMarco Vanotti "STARTED 0 2000\n"
9110fe4701eSMarco Vanotti "FT 0 1 2 3\n"
9120fe4701eSMarco Vanotti "STARTED 1 1101\n"
9130fe4701eSMarco Vanotti "FT 1 4 5 6 \n"
9140fe4701eSMarco Vanotti "STARTED 2 1102\n"
9150fe4701eSMarco Vanotti "FT 2 6 1 3 100 \n"
9160fe4701eSMarco Vanotti "STARTED 3 1000\n"
9170fe4701eSMarco Vanotti "FT 3 1 \n"
9180fe4701eSMarco Vanotti "",
9190fe4701eSMarco Vanotti true));
9200fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 7U);
9210fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B", "C", "D"});
9220fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"D", "B", "C", "A"});
9230fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6, 100});
9240fe4701eSMarco Vanotti
9250fe4701eSMarco Vanotti // For same sized file, parse more features first
9260fe4701eSMarco Vanotti EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n"
9270fe4701eSMarco Vanotti "STARTED 0 2000\n"
9280fe4701eSMarco Vanotti "FT 0 4 5 6 7 8\n"
9290fe4701eSMarco Vanotti "STARTED 1 1100\n"
9300fe4701eSMarco Vanotti "FT 1 1 2 3 \n"
9310fe4701eSMarco Vanotti "STARTED 2 1100\n"
9320fe4701eSMarco Vanotti "FT 2 2 3 \n"
9330fe4701eSMarco Vanotti "STARTED 3 1000\n"
9340fe4701eSMarco Vanotti "FT 3 1 \n"
9350fe4701eSMarco Vanotti "",
9360fe4701eSMarco Vanotti true));
9370fe4701eSMarco Vanotti EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
9380fe4701eSMarco Vanotti TRACED_EQ(M.Files, {"A", "B", "C", "D"});
9390fe4701eSMarco Vanotti TRACED_EQ(NewFiles, {"D", "B"});
9400fe4701eSMarco Vanotti TRACED_EQ(NewFeatures, {1, 2, 3});
94110ab2aceSGeorge Karpenkov }
94210ab2aceSGeorge Karpenkov
TEST(Merger,SetCoverMerge)943e6597dbaSaristotelis TEST(Merger, SetCoverMerge) {
944e6597dbaSaristotelis Merger M;
945e6597dbaSaristotelis std::set<uint32_t> Features, NewFeatures;
946e6597dbaSaristotelis std::set<uint32_t> Cov, NewCov;
947e6597dbaSaristotelis std::vector<std::string> NewFiles;
948e6597dbaSaristotelis
949e6597dbaSaristotelis // Adds new files and features
950e6597dbaSaristotelis EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
951e6597dbaSaristotelis "STARTED 0 1000\n"
952e6597dbaSaristotelis "FT 0 1 2 3\n"
953e6597dbaSaristotelis "STARTED 1 1001\n"
954e6597dbaSaristotelis "FT 1 4 5 6 \n"
955e6597dbaSaristotelis "STARTED 2 1002\n"
956e6597dbaSaristotelis "FT 2 6 1 3\n"
957e6597dbaSaristotelis "",
958e6597dbaSaristotelis true));
959e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
960e6597dbaSaristotelis 6U);
961e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C"});
962e6597dbaSaristotelis TRACED_EQ(NewFiles, {"A", "B"});
963e6597dbaSaristotelis TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
964e6597dbaSaristotelis
965e6597dbaSaristotelis // Doesn't return features or files in the initial corpus.
966e6597dbaSaristotelis EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
967e6597dbaSaristotelis "STARTED 0 1000\n"
968e6597dbaSaristotelis "FT 0 1 2 3\n"
969e6597dbaSaristotelis "STARTED 1 1001\n"
970e6597dbaSaristotelis "FT 1 4 5 6 \n"
971e6597dbaSaristotelis "STARTED 2 1002\n"
972e6597dbaSaristotelis "FT 2 6 1 3\n"
973e6597dbaSaristotelis "",
974e6597dbaSaristotelis true));
975e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
976e6597dbaSaristotelis 3U);
977e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C"});
978e6597dbaSaristotelis TRACED_EQ(NewFiles, {"B"});
979e6597dbaSaristotelis TRACED_EQ(NewFeatures, {4, 5, 6});
980e6597dbaSaristotelis
981e6597dbaSaristotelis // No new features, so no new files
982e6597dbaSaristotelis EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n"
983e6597dbaSaristotelis "STARTED 0 1000\n"
984e6597dbaSaristotelis "FT 0 1 2 3\n"
985e6597dbaSaristotelis "STARTED 1 1001\n"
986e6597dbaSaristotelis "FT 1 4 5 6 \n"
987e6597dbaSaristotelis "STARTED 2 1002\n"
988e6597dbaSaristotelis "FT 2 6 1 3\n"
989e6597dbaSaristotelis "",
990e6597dbaSaristotelis true));
991e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
992e6597dbaSaristotelis 0U);
993e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C"});
994e6597dbaSaristotelis TRACED_EQ(NewFiles, {});
995e6597dbaSaristotelis TRACED_EQ(NewFeatures, {});
996e6597dbaSaristotelis
997e6597dbaSaristotelis // Can pass initial features and coverage.
998e6597dbaSaristotelis Features = {1, 2, 3};
999e6597dbaSaristotelis Cov = {};
1000e6597dbaSaristotelis EXPECT_TRUE(M.Parse("2\n0\nA\nB\n"
1001e6597dbaSaristotelis "STARTED 0 1000\n"
1002e6597dbaSaristotelis "FT 0 1 2 3\n"
1003e6597dbaSaristotelis "STARTED 1 1001\n"
1004e6597dbaSaristotelis "FT 1 4 5 6\n"
1005e6597dbaSaristotelis "",
1006e6597dbaSaristotelis true));
1007e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
1008e6597dbaSaristotelis 3U);
1009e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B"});
1010e6597dbaSaristotelis TRACED_EQ(NewFiles, {"B"});
1011e6597dbaSaristotelis TRACED_EQ(NewFeatures, {4, 5, 6});
1012e6597dbaSaristotelis Features.clear();
1013e6597dbaSaristotelis Cov.clear();
1014e6597dbaSaristotelis
1015e6597dbaSaristotelis // Prefer files with a lot of features first (C has 4 features)
1016e6597dbaSaristotelis // Then prefer B over A due to the smaller size. After choosing C and B,
1017e6597dbaSaristotelis // A and D have no new features to contribute.
1018e6597dbaSaristotelis EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n"
1019e6597dbaSaristotelis "STARTED 0 2000\n"
1020e6597dbaSaristotelis "FT 0 3 5 6\n"
1021e6597dbaSaristotelis "STARTED 1 1000\n"
1022e6597dbaSaristotelis "FT 1 4 5 6 \n"
1023e6597dbaSaristotelis "STARTED 2 1000\n"
1024e6597dbaSaristotelis "FT 2 1 2 3 4 \n"
1025e6597dbaSaristotelis "STARTED 3 500\n"
1026e6597dbaSaristotelis "FT 3 1 \n"
1027e6597dbaSaristotelis "",
1028e6597dbaSaristotelis true));
1029e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
1030e6597dbaSaristotelis 6U);
1031e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C", "D"});
1032e6597dbaSaristotelis TRACED_EQ(NewFiles, {"C", "B"});
1033e6597dbaSaristotelis TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
1034e6597dbaSaristotelis
1035e6597dbaSaristotelis // Only 1 file covers all features.
1036e6597dbaSaristotelis EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n"
1037e6597dbaSaristotelis "STARTED 0 2000\n"
1038e6597dbaSaristotelis "FT 0 4 5 6 7 8\n"
1039e6597dbaSaristotelis "STARTED 1 1100\n"
1040e6597dbaSaristotelis "FT 1 1 2 3 \n"
1041e6597dbaSaristotelis "STARTED 2 1100\n"
1042e6597dbaSaristotelis "FT 2 2 3 \n"
1043e6597dbaSaristotelis "STARTED 3 1000\n"
1044e6597dbaSaristotelis "FT 3 1 \n"
1045e6597dbaSaristotelis "",
1046e6597dbaSaristotelis true));
1047e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
1048e6597dbaSaristotelis 3U);
1049e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C", "D"});
1050e6597dbaSaristotelis TRACED_EQ(NewFiles, {"B"});
1051e6597dbaSaristotelis TRACED_EQ(NewFeatures, {1, 2, 3});
1052e6597dbaSaristotelis
1053e6597dbaSaristotelis // A Feature has a value greater than (1 << 21) and hence
1054e6597dbaSaristotelis // there are collisions in the underlying `covered features`
1055e6597dbaSaristotelis // bitvector.
1056e6597dbaSaristotelis EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
1057e6597dbaSaristotelis "STARTED 0 2000\n"
1058e6597dbaSaristotelis "FT 0 1 2 3\n"
1059e6597dbaSaristotelis "STARTED 1 1000\n"
1060e6597dbaSaristotelis "FT 1 3 4 5 \n"
1061e6597dbaSaristotelis "STARTED 2 1000\n"
1062e6597dbaSaristotelis "FT 2 3 2097153 \n" // Last feature is (2^21 + 1).
1063e6597dbaSaristotelis "",
1064e6597dbaSaristotelis true));
1065e6597dbaSaristotelis EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles),
1066e6597dbaSaristotelis 5U);
1067e6597dbaSaristotelis TRACED_EQ(M.Files, {"A", "B", "C"});
1068e6597dbaSaristotelis // File 'C' is not added because it's last feature is considered
1069e6597dbaSaristotelis // covered due to collision with feature 1.
1070e6597dbaSaristotelis TRACED_EQ(NewFiles, {"B", "A"});
1071e6597dbaSaristotelis TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5});
1072e6597dbaSaristotelis }
1073e6597dbaSaristotelis
10740fe4701eSMarco Vanotti #undef TRACED_EQ
107510ab2aceSGeorge Karpenkov
TEST(DFT,BlockCoverage)1076e9aaa558SKostya Serebryany TEST(DFT, BlockCoverage) {
1077e9aaa558SKostya Serebryany BlockCoverage Cov;
1078e9aaa558SKostya Serebryany // Assuming C0 has 5 instrumented blocks,
1079e9aaa558SKostya Serebryany // C1: 7 blocks, C2: 4, C3: 9, C4 never covered, C5: 15,
1080e9aaa558SKostya Serebryany
1081e9aaa558SKostya Serebryany // Add C0
1082e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
1083e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 1U);
1084e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 1), 0U); // not seen this BB yet.
1085e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 5), 0U); // BB ID out of bounds.
1086e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(1, 0), 0U); // not seen this function yet.
1087e9aaa558SKostya Serebryany
1088e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetNumberOfBlocks(0), 5U);
1089e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 1U);
1090e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetNumberOfBlocks(1), 0U);
1091e9aaa558SKostya Serebryany
1092e9aaa558SKostya Serebryany // Various errors.
1093e9aaa558SKostya Serebryany EXPECT_FALSE(Cov.AppendCoverage("C0\n")); // No total number.
1094e9aaa558SKostya Serebryany EXPECT_FALSE(Cov.AppendCoverage("C0 7\n")); // No total number.
1095e9aaa558SKostya Serebryany EXPECT_FALSE(Cov.AppendCoverage("CZ\n")); // Wrong function number.
1096e9aaa558SKostya Serebryany EXPECT_FALSE(Cov.AppendCoverage("C1 7 7")); // BB ID is too big.
1097e9aaa558SKostya Serebryany EXPECT_FALSE(Cov.AppendCoverage("C1 100 7")); // BB ID is too big.
1098e9aaa558SKostya Serebryany
1099e9aaa558SKostya Serebryany // Add C0 more times.
1100e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
1101e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 2U);
1102e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 5\n"));
1103e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 3U);
1104e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 1), 1U);
1105e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 2), 1U);
1106e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 3), 0U);
1107e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 4), 0U);
1108e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 3U);
1109e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 1 3 4 5\n"));
1110e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 4U);
1111e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 1), 2U);
1112e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 2), 1U);
1113e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 3), 1U);
1114e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 4), 1U);
1115e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetNumberOfCoveredBlocks(0), 5U);
1116e9aaa558SKostya Serebryany
1117e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C1 7\nC2 4\nC3 9\nC5 15\nC0 5\n"));
1118e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 5U);
1119e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(1, 0), 1U);
1120e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(2, 0), 1U);
1121e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(3, 0), 1U);
1122e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(4, 0), 0U);
1123e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(5, 0), 1U);
1124e9aaa558SKostya Serebryany
1125e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C3 4 5 9\nC5 11 12 15"));
1126e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(0, 0), 5U);
1127e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(1, 0), 1U);
1128e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(2, 0), 1U);
1129e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(3, 0), 2U);
1130e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(3, 4), 1U);
1131e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(3, 5), 1U);
1132e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(3, 6), 0U);
1133e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(4, 0), 0U);
1134e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(5, 0), 2U);
1135e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(5, 10), 0U);
1136e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(5, 11), 1U);
1137e9aaa558SKostya Serebryany EXPECT_EQ(Cov.GetCounter(5, 12), 1U);
1138e9aaa558SKostya Serebryany }
1139e9aaa558SKostya Serebryany
TEST(DFT,FunctionWeights)1140e9aaa558SKostya Serebryany TEST(DFT, FunctionWeights) {
1141e9aaa558SKostya Serebryany BlockCoverage Cov;
1142e9aaa558SKostya Serebryany // unused function gets zero weight.
1143e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 5\n"));
1144e9aaa558SKostya Serebryany auto Weights = Cov.FunctionWeights(2);
1145e9aaa558SKostya Serebryany EXPECT_GT(Weights[0], 0.);
1146e9aaa558SKostya Serebryany EXPECT_EQ(Weights[1], 0.);
1147e9aaa558SKostya Serebryany
1148e9aaa558SKostya Serebryany // Less frequently used function gets less weight.
1149e9aaa558SKostya Serebryany Cov.clear();
1150e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 5\nC1 5\nC1 5\n"));
1151e9aaa558SKostya Serebryany Weights = Cov.FunctionWeights(2);
1152e9aaa558SKostya Serebryany EXPECT_GT(Weights[0], Weights[1]);
1153e9aaa558SKostya Serebryany
11540feed5d5SKostya Serebryany // A function with more uncovered blocks gets more weight.
1155e9aaa558SKostya Serebryany Cov.clear();
1156e9aaa558SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("C0 1 2 3 5\nC1 2 4\n"));
1157e9aaa558SKostya Serebryany Weights = Cov.FunctionWeights(2);
1158e9aaa558SKostya Serebryany EXPECT_GT(Weights[1], Weights[0]);
11590feed5d5SKostya Serebryany
11600feed5d5SKostya Serebryany // A function with DFT gets more weight than the function w/o DFT.
11610feed5d5SKostya Serebryany Cov.clear();
11620feed5d5SKostya Serebryany EXPECT_TRUE(Cov.AppendCoverage("F1 111\nC0 3\nC1 1 2 3\n"));
11630feed5d5SKostya Serebryany Weights = Cov.FunctionWeights(2);
11640feed5d5SKostya Serebryany EXPECT_GT(Weights[1], Weights[0]);
1165e9aaa558SKostya Serebryany }
1166e9aaa558SKostya Serebryany
1167e9aaa558SKostya Serebryany
TEST(Fuzzer,ForEachNonZeroByte)116810ab2aceSGeorge Karpenkov TEST(Fuzzer, ForEachNonZeroByte) {
116910ab2aceSGeorge Karpenkov const size_t N = 64;
117010ab2aceSGeorge Karpenkov alignas(64) uint8_t Ar[N + 8] = {
117110ab2aceSGeorge Karpenkov 0, 0, 0, 0, 0, 0, 0, 0,
117210ab2aceSGeorge Karpenkov 1, 2, 0, 0, 0, 0, 0, 0,
117310ab2aceSGeorge Karpenkov 0, 0, 3, 0, 4, 0, 0, 0,
117410ab2aceSGeorge Karpenkov 0, 0, 0, 0, 0, 0, 0, 0,
117510ab2aceSGeorge Karpenkov 0, 0, 0, 5, 0, 6, 0, 0,
117610ab2aceSGeorge Karpenkov 0, 0, 0, 0, 0, 0, 7, 0,
117710ab2aceSGeorge Karpenkov 0, 0, 0, 0, 0, 0, 0, 0,
117810ab2aceSGeorge Karpenkov 0, 0, 0, 0, 0, 0, 0, 8,
117910ab2aceSGeorge Karpenkov 9, 9, 9, 9, 9, 9, 9, 9,
118010ab2aceSGeorge Karpenkov };
11817c921753SKostya Serebryany typedef std::vector<std::pair<size_t, uint8_t>> Vec;
118210ab2aceSGeorge Karpenkov Vec Res, Expected;
118310ab2aceSGeorge Karpenkov auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) {
118410ab2aceSGeorge Karpenkov Res.push_back({FirstFeature + Idx, V});
118510ab2aceSGeorge Karpenkov };
118610ab2aceSGeorge Karpenkov ForEachNonZeroByte(Ar, Ar + N, 100, CB);
118710ab2aceSGeorge Karpenkov Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4},
118810ab2aceSGeorge Karpenkov {135, 5}, {137, 6}, {146, 7}, {163, 8}};
118910ab2aceSGeorge Karpenkov EXPECT_EQ(Res, Expected);
119010ab2aceSGeorge Karpenkov
119110ab2aceSGeorge Karpenkov Res.clear();
119210ab2aceSGeorge Karpenkov ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB);
119310ab2aceSGeorge Karpenkov Expected = { {109, 2}, {118, 3}, {120, 4},
119410ab2aceSGeorge Karpenkov {135, 5}, {137, 6}, {146, 7}, {163, 8}};
119510ab2aceSGeorge Karpenkov EXPECT_EQ(Res, Expected);
119610ab2aceSGeorge Karpenkov
119710ab2aceSGeorge Karpenkov Res.clear();
119810ab2aceSGeorge Karpenkov ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB);
119910ab2aceSGeorge Karpenkov Expected = { {109, 2}, {118, 3}, {120, 4},
120010ab2aceSGeorge Karpenkov {135, 5}, {137, 6}, {146, 7}};
120110ab2aceSGeorge Karpenkov EXPECT_EQ(Res, Expected);
120210ab2aceSGeorge Karpenkov }
120310ab2aceSGeorge Karpenkov
120404304d12SMatt Morehouse // FuzzerCommand unit tests. The arguments in the two helper methods below must
120504304d12SMatt Morehouse // match.
makeCommandArgs(std::vector<std::string> * ArgsToAdd)12067c921753SKostya Serebryany static void makeCommandArgs(std::vector<std::string> *ArgsToAdd) {
120704304d12SMatt Morehouse assert(ArgsToAdd);
120804304d12SMatt Morehouse ArgsToAdd->clear();
120904304d12SMatt Morehouse ArgsToAdd->push_back("foo");
121004304d12SMatt Morehouse ArgsToAdd->push_back("-bar=baz");
121104304d12SMatt Morehouse ArgsToAdd->push_back("qux");
121204304d12SMatt Morehouse ArgsToAdd->push_back(Command::ignoreRemainingArgs());
121304304d12SMatt Morehouse ArgsToAdd->push_back("quux");
121404304d12SMatt Morehouse ArgsToAdd->push_back("-grault=garply");
121504304d12SMatt Morehouse }
121604304d12SMatt Morehouse
makeCmdLine(const char * separator,const char * suffix)121704304d12SMatt Morehouse static std::string makeCmdLine(const char *separator, const char *suffix) {
121804304d12SMatt Morehouse std::string CmdLine("foo -bar=baz qux ");
121904304d12SMatt Morehouse if (strlen(separator) != 0) {
122004304d12SMatt Morehouse CmdLine += separator;
122104304d12SMatt Morehouse CmdLine += " ";
122204304d12SMatt Morehouse }
122304304d12SMatt Morehouse CmdLine += Command::ignoreRemainingArgs();
122404304d12SMatt Morehouse CmdLine += " quux -grault=garply";
122504304d12SMatt Morehouse if (strlen(suffix) != 0) {
122604304d12SMatt Morehouse CmdLine += " ";
122704304d12SMatt Morehouse CmdLine += suffix;
122804304d12SMatt Morehouse }
122904304d12SMatt Morehouse return CmdLine;
123004304d12SMatt Morehouse }
123104304d12SMatt Morehouse
TEST(FuzzerCommand,Create)123204304d12SMatt Morehouse TEST(FuzzerCommand, Create) {
123304304d12SMatt Morehouse std::string CmdLine;
123404304d12SMatt Morehouse
123504304d12SMatt Morehouse // Default constructor
123604304d12SMatt Morehouse Command DefaultCmd;
123704304d12SMatt Morehouse
123804304d12SMatt Morehouse CmdLine = DefaultCmd.toString();
123904304d12SMatt Morehouse EXPECT_EQ(CmdLine, "");
124004304d12SMatt Morehouse
124104304d12SMatt Morehouse // Explicit constructor
12427c921753SKostya Serebryany std::vector<std::string> ArgsToAdd;
124304304d12SMatt Morehouse makeCommandArgs(&ArgsToAdd);
124404304d12SMatt Morehouse Command InitializedCmd(ArgsToAdd);
124504304d12SMatt Morehouse
124604304d12SMatt Morehouse CmdLine = InitializedCmd.toString();
124704304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
124804304d12SMatt Morehouse
124904304d12SMatt Morehouse // Compare each argument
125004304d12SMatt Morehouse auto InitializedArgs = InitializedCmd.getArguments();
125104304d12SMatt Morehouse auto i = ArgsToAdd.begin();
125204304d12SMatt Morehouse auto j = InitializedArgs.begin();
125304304d12SMatt Morehouse while (i != ArgsToAdd.end() && j != InitializedArgs.end()) {
125404304d12SMatt Morehouse EXPECT_EQ(*i++, *j++);
125504304d12SMatt Morehouse }
125604304d12SMatt Morehouse EXPECT_EQ(i, ArgsToAdd.end());
125704304d12SMatt Morehouse EXPECT_EQ(j, InitializedArgs.end());
125804304d12SMatt Morehouse
125904304d12SMatt Morehouse // Copy constructor
126004304d12SMatt Morehouse Command CopiedCmd(InitializedCmd);
126104304d12SMatt Morehouse
126204304d12SMatt Morehouse CmdLine = CopiedCmd.toString();
126304304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
126404304d12SMatt Morehouse
126504304d12SMatt Morehouse // Assignment operator
126604304d12SMatt Morehouse Command AssignedCmd;
126704304d12SMatt Morehouse AssignedCmd = CopiedCmd;
126804304d12SMatt Morehouse
126904304d12SMatt Morehouse CmdLine = AssignedCmd.toString();
127004304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
127104304d12SMatt Morehouse }
127204304d12SMatt Morehouse
TEST(FuzzerCommand,ModifyArguments)127304304d12SMatt Morehouse TEST(FuzzerCommand, ModifyArguments) {
12747c921753SKostya Serebryany std::vector<std::string> ArgsToAdd;
127504304d12SMatt Morehouse makeCommandArgs(&ArgsToAdd);
127604304d12SMatt Morehouse Command Cmd;
127704304d12SMatt Morehouse std::string CmdLine;
127804304d12SMatt Morehouse
127904304d12SMatt Morehouse Cmd.addArguments(ArgsToAdd);
128004304d12SMatt Morehouse CmdLine = Cmd.toString();
128104304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
128204304d12SMatt Morehouse
128304304d12SMatt Morehouse Cmd.addArgument("waldo");
128404304d12SMatt Morehouse EXPECT_TRUE(Cmd.hasArgument("waldo"));
128504304d12SMatt Morehouse
128604304d12SMatt Morehouse CmdLine = Cmd.toString();
128704304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("waldo", ""));
128804304d12SMatt Morehouse
128904304d12SMatt Morehouse Cmd.removeArgument("waldo");
129004304d12SMatt Morehouse EXPECT_FALSE(Cmd.hasArgument("waldo"));
129104304d12SMatt Morehouse
129204304d12SMatt Morehouse CmdLine = Cmd.toString();
129304304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
129404304d12SMatt Morehouse }
129504304d12SMatt Morehouse
TEST(FuzzerCommand,ModifyFlags)129604304d12SMatt Morehouse TEST(FuzzerCommand, ModifyFlags) {
12977c921753SKostya Serebryany std::vector<std::string> ArgsToAdd;
129804304d12SMatt Morehouse makeCommandArgs(&ArgsToAdd);
129904304d12SMatt Morehouse Command Cmd(ArgsToAdd);
130004304d12SMatt Morehouse std::string Value, CmdLine;
130104304d12SMatt Morehouse ASSERT_FALSE(Cmd.hasFlag("fred"));
130204304d12SMatt Morehouse
130304304d12SMatt Morehouse Value = Cmd.getFlagValue("fred");
130404304d12SMatt Morehouse EXPECT_EQ(Value, "");
130504304d12SMatt Morehouse
130604304d12SMatt Morehouse CmdLine = Cmd.toString();
130704304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
130804304d12SMatt Morehouse
130904304d12SMatt Morehouse Cmd.addFlag("fred", "plugh");
131004304d12SMatt Morehouse EXPECT_TRUE(Cmd.hasFlag("fred"));
131104304d12SMatt Morehouse
131204304d12SMatt Morehouse Value = Cmd.getFlagValue("fred");
131304304d12SMatt Morehouse EXPECT_EQ(Value, "plugh");
131404304d12SMatt Morehouse
131504304d12SMatt Morehouse CmdLine = Cmd.toString();
131604304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("-fred=plugh", ""));
131704304d12SMatt Morehouse
131804304d12SMatt Morehouse Cmd.removeFlag("fred");
131904304d12SMatt Morehouse EXPECT_FALSE(Cmd.hasFlag("fred"));
132004304d12SMatt Morehouse
132104304d12SMatt Morehouse Value = Cmd.getFlagValue("fred");
132204304d12SMatt Morehouse EXPECT_EQ(Value, "");
132304304d12SMatt Morehouse
132404304d12SMatt Morehouse CmdLine = Cmd.toString();
132504304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ""));
132604304d12SMatt Morehouse }
132704304d12SMatt Morehouse
TEST(FuzzerCommand,SetOutput)132804304d12SMatt Morehouse TEST(FuzzerCommand, SetOutput) {
13297c921753SKostya Serebryany std::vector<std::string> ArgsToAdd;
133004304d12SMatt Morehouse makeCommandArgs(&ArgsToAdd);
133104304d12SMatt Morehouse Command Cmd(ArgsToAdd);
133204304d12SMatt Morehouse std::string CmdLine;
133304304d12SMatt Morehouse ASSERT_FALSE(Cmd.hasOutputFile());
133404304d12SMatt Morehouse ASSERT_FALSE(Cmd.isOutAndErrCombined());
133504304d12SMatt Morehouse
133604304d12SMatt Morehouse Cmd.combineOutAndErr(true);
133704304d12SMatt Morehouse EXPECT_TRUE(Cmd.isOutAndErrCombined());
133804304d12SMatt Morehouse
133904304d12SMatt Morehouse CmdLine = Cmd.toString();
134004304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", "2>&1"));
134104304d12SMatt Morehouse
134204304d12SMatt Morehouse Cmd.combineOutAndErr(false);
134304304d12SMatt Morehouse EXPECT_FALSE(Cmd.isOutAndErrCombined());
134404304d12SMatt Morehouse
134504304d12SMatt Morehouse Cmd.setOutputFile("xyzzy");
134604304d12SMatt Morehouse EXPECT_TRUE(Cmd.hasOutputFile());
134704304d12SMatt Morehouse
134804304d12SMatt Morehouse CmdLine = Cmd.toString();
134904304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ">xyzzy"));
135004304d12SMatt Morehouse
135104304d12SMatt Morehouse Cmd.setOutputFile("thud");
135204304d12SMatt Morehouse EXPECT_TRUE(Cmd.hasOutputFile());
135304304d12SMatt Morehouse
135404304d12SMatt Morehouse CmdLine = Cmd.toString();
135504304d12SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ">thud"));
135604304d12SMatt Morehouse
135704304d12SMatt Morehouse Cmd.combineOutAndErr();
135804304d12SMatt Morehouse EXPECT_TRUE(Cmd.isOutAndErrCombined());
135904304d12SMatt Morehouse
136004304d12SMatt Morehouse CmdLine = Cmd.toString();
1361056774d1SMatt Morehouse EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1"));
136204304d12SMatt Morehouse }
136304304d12SMatt Morehouse
TEST(Entropic,UpdateFrequency)1364e2e38fcaSMatt Morehouse TEST(Entropic, UpdateFrequency) {
1365e2e38fcaSMatt Morehouse const size_t One = 1, Two = 2;
1366e2e38fcaSMatt Morehouse const size_t FeatIdx1 = 0, FeatIdx2 = 42, FeatIdx3 = 12, FeatIdx4 = 26;
1367e2e38fcaSMatt Morehouse size_t Index;
1368e2e38fcaSMatt Morehouse // Create input corpus with default entropic configuration
1369dde16ef0SHubert Tong struct EntropicOptions Entropic = {true, 0xFF, 100, false};
1370e2e38fcaSMatt Morehouse std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
1371353e5aa4SMatt Morehouse std::unique_ptr<InputInfo> II(new InputInfo());
1372e2e38fcaSMatt Morehouse
1373e2e38fcaSMatt Morehouse C->AddRareFeature(FeatIdx1);
1374353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx1);
1375e2e38fcaSMatt Morehouse EXPECT_EQ(II->FeatureFreqs.size(), One);
1376e2e38fcaSMatt Morehouse C->AddRareFeature(FeatIdx2);
1377353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx1);
1378353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx2);
1379e2e38fcaSMatt Morehouse EXPECT_EQ(II->FeatureFreqs.size(), Two);
1380e2e38fcaSMatt Morehouse EXPECT_EQ(II->FeatureFreqs[0].second, 2);
1381e2e38fcaSMatt Morehouse EXPECT_EQ(II->FeatureFreqs[1].second, 1);
1382e2e38fcaSMatt Morehouse
1383e2e38fcaSMatt Morehouse C->AddRareFeature(FeatIdx3);
1384e2e38fcaSMatt Morehouse C->AddRareFeature(FeatIdx4);
1385353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1386353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1387353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx3);
1388353e5aa4SMatt Morehouse C->UpdateFeatureFrequency(II.get(), FeatIdx4);
1389e2e38fcaSMatt Morehouse
1390e2e38fcaSMatt Morehouse for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
1391e2e38fcaSMatt Morehouse EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first);
1392e2e38fcaSMatt Morehouse
1393e2e38fcaSMatt Morehouse II->DeleteFeatureFreq(FeatIdx3);
1394e2e38fcaSMatt Morehouse for (Index = 1; Index < II->FeatureFreqs.size(); Index++)
1395e2e38fcaSMatt Morehouse EXPECT_LT(II->FeatureFreqs[Index - 1].first, II->FeatureFreqs[Index].first);
1396e2e38fcaSMatt Morehouse }
1397e2e38fcaSMatt Morehouse
SubAndSquare(double X,double Y)1398e2e38fcaSMatt Morehouse double SubAndSquare(double X, double Y) {
1399e2e38fcaSMatt Morehouse double R = X - Y;
1400e2e38fcaSMatt Morehouse R = R * R;
1401e2e38fcaSMatt Morehouse return R;
1402e2e38fcaSMatt Morehouse }
1403e2e38fcaSMatt Morehouse
TEST(Entropic,ComputeEnergy)1404e2e38fcaSMatt Morehouse TEST(Entropic, ComputeEnergy) {
1405e2e38fcaSMatt Morehouse const double Precision = 0.01;
1406dde16ef0SHubert Tong struct EntropicOptions Entropic = {true, 0xFF, 100, false};
1407e2e38fcaSMatt Morehouse std::unique_ptr<InputCorpus> C(new InputCorpus("", Entropic));
1408353e5aa4SMatt Morehouse std::unique_ptr<InputInfo> II(new InputInfo());
14097c921753SKostya Serebryany std::vector<std::pair<uint32_t, uint16_t>> FeatureFreqs = {
14107c921753SKostya Serebryany {1, 3}, {2, 3}, {3, 3}};
1411e2e38fcaSMatt Morehouse II->FeatureFreqs = FeatureFreqs;
1412e2e38fcaSMatt Morehouse II->NumExecutedMutations = 0;
14135cda4dc7SDokyung Song II->UpdateEnergy(4, false, std::chrono::microseconds(0));
1414e2e38fcaSMatt Morehouse EXPECT_LT(SubAndSquare(II->Energy, 1.450805), Precision);
1415e2e38fcaSMatt Morehouse
1416e2e38fcaSMatt Morehouse II->NumExecutedMutations = 9;
14175cda4dc7SDokyung Song II->UpdateEnergy(5, false, std::chrono::microseconds(0));
1418e2e38fcaSMatt Morehouse EXPECT_LT(SubAndSquare(II->Energy, 1.525496), Precision);
1419e2e38fcaSMatt Morehouse
1420e2e38fcaSMatt Morehouse II->FeatureFreqs[0].second++;
1421e2e38fcaSMatt Morehouse II->FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(42, 6));
1422e2e38fcaSMatt Morehouse II->NumExecutedMutations = 20;
14235cda4dc7SDokyung Song II->UpdateEnergy(10, false, std::chrono::microseconds(0));
1424e2e38fcaSMatt Morehouse EXPECT_LT(SubAndSquare(II->Energy, 1.792831), Precision);
1425e2e38fcaSMatt Morehouse }
1426e2e38fcaSMatt Morehouse
main(int argc,char ** argv)142710ab2aceSGeorge Karpenkov int main(int argc, char **argv) {
142810ab2aceSGeorge Karpenkov testing::InitGoogleTest(&argc, argv);
142910ab2aceSGeorge Karpenkov return RUN_ALL_TESTS();
143010ab2aceSGeorge Karpenkov }
1431