@@ -114,7 +114,9 @@ TEST(Corpus, Prune) {
114114 Add ({{2 }, {30 , 40 }});
115115 Add ({{3 }, {40 , 50 }});
116116 Add ({{4 }, {10 , 20 }});
117- corpus.UpdateWeights (fs, coverage_frontier, /* scale_by_exec_time=*/ false );
117+ corpus.UpdateWeights (fs, coverage_frontier,
118+ Corpus::WeightMethod::FeatureRarity,
119+ /* scale_by_exec_time=*/ false );
118120
119121 // Prune. Features 20 and 40 are frequent => input {0} will be removed.
120122 EXPECT_EQ (corpus.NumActive (), 5 );
@@ -124,7 +126,9 @@ TEST(Corpus, Prune) {
124126 VerifyActiveInputs ({{1 }, {2 }, {3 }, {4 }});
125127
126128 Add ({{5 }, {30 , 60 }});
127- corpus.UpdateWeights (fs, coverage_frontier, /* scale_by_exec_time=*/ false );
129+ corpus.UpdateWeights (fs, coverage_frontier,
130+ Corpus::WeightMethod::FeatureRarity,
131+ /* scale_by_exec_time=*/ false );
128132
129133 EXPECT_EQ (corpus.NumTotal (), 6 );
130134 // Prune. Feature 30 is now frequent => inputs {1} and {2} will be removed.
@@ -145,6 +149,64 @@ TEST(Corpus, Prune) {
145149 EXPECT_EQ (corpus.NumTotal (), 6 );
146150}
147151
152+ TEST (Corpus, WeightMethodsWorkAsExpected) {
153+ PCTable pc_table (100 );
154+ CFTable cf_table (100 );
155+ BinaryInfo bin_info{pc_table, {}, cf_table, {}, {}, {}};
156+ CoverageFrontier coverage_frontier (bin_info);
157+ FeatureSet fs (3 , {});
158+ Corpus corpus;
159+
160+ auto Add = [&](const CorpusRecord& record) {
161+ fs.MergeFeatures (record.features );
162+ corpus.Add (record.data , record.features , /* metadata=*/ {}, /* stats=*/ {}, fs,
163+ coverage_frontier);
164+ };
165+
166+ Add ({/* data=*/ {0 }, /* features=*/ {30 , 20 }});
167+ Add ({/* data=*/ {1 }, /* features=*/ {10 , 20 }});
168+ Add ({/* data=*/ {2 }, /* features=*/ {10 }});
169+
170+ constexpr int kNumIter = 10000 ;
171+ std::vector<uint64_t > freq;
172+
173+ Rng rng;
174+ auto ComputeFreq = [&]() {
175+ freq.clear ();
176+ freq.resize (corpus.NumActive ());
177+ for (int i = 0 ; i < kNumIter ; i++) {
178+ const auto & record = corpus.WeightedRandom (rng);
179+ const auto id = record.data [0 ];
180+ ASSERT_LT (id, freq.size ());
181+ freq[id]++;
182+ }
183+ };
184+
185+ // The weights should be equal with the uniform method
186+ corpus.UpdateWeights (fs, coverage_frontier, Corpus::WeightMethod::Uniform,
187+ /* scale_by_exec_time=*/ false );
188+ ComputeFreq ();
189+ EXPECT_NEAR (freq[0 ], kNumIter / 3 , 100 );
190+ EXPECT_NEAR (freq[1 ], kNumIter / 3 , 100 );
191+ EXPECT_NEAR (freq[2 ], kNumIter / 3 , 100 );
192+
193+ // The weights should favor {2} over {1} over {0} with the recency method.
194+ corpus.UpdateWeights (fs, coverage_frontier, Corpus::WeightMethod::Recency,
195+ /* scale_by_exec_time=*/ false );
196+ ComputeFreq ();
197+ EXPECT_GT (freq[2 ], freq[1 ] + 100 );
198+ EXPECT_GT (freq[1 ], freq[0 ] + 100 );
199+
200+ // The weights should favor {0} over {1} over {2} with the feature rarity
201+ // method.
202+ corpus.UpdateWeights (fs, coverage_frontier,
203+ Corpus::WeightMethod::FeatureRarity,
204+ /* scale_by_exec_time=*/ false );
205+ ComputeFreq ();
206+ EXPECT_GT (freq[0 ], freq[1 ] + 100 );
207+ EXPECT_GT (freq[1 ], freq[2 ] + 100 );
208+ }
209+
148210TEST (Corpus, ScalesWeightsWithExecTime) {
149211 PCTable pc_table (100 );
150212 CFTable cf_table (100 );
@@ -181,14 +243,18 @@ TEST(Corpus, ScalesWeightsWithExecTime) {
181243 };
182244
183245 // The weights should be equal without exec time scaling.
184- corpus.UpdateWeights (fs, coverage_frontier, /* scale_by_exec_time=*/ false );
246+ corpus.UpdateWeights (fs, coverage_frontier,
247+ Corpus::WeightMethod::FeatureRarity,
248+ /* scale_by_exec_time=*/ false );
185249 ComputeFreq ();
186250 EXPECT_NEAR (freq[0 ], kNumIter / 3 , 100 );
187251 EXPECT_NEAR (freq[1 ], kNumIter / 3 , 100 );
188252 EXPECT_NEAR (freq[2 ], kNumIter / 3 , 100 );
189253
190254 // The weights should favor {0} over {1} over {2} with exec time scaling.
191- corpus.UpdateWeights (fs, coverage_frontier, /* scale_by_exec_time=*/ true );
255+ corpus.UpdateWeights (fs, coverage_frontier,
256+ Corpus::WeightMethod::FeatureRarity,
257+ /* scale_by_exec_time=*/ true );
192258 ComputeFreq ();
193259 EXPECT_GT (freq[0 ], freq[1 ] + 100 );
194260 EXPECT_GT (freq[1 ], freq[2 ] + 100 );
@@ -208,6 +274,9 @@ TEST(Corpus, PruneCorpusWithAllEmptyFeatureInputs) {
208274 coverage_frontier);
209275 corpus.Add (/* data=*/ {2 }, /* fv=*/ {}, /* metadata=*/ {}, /* stats=*/ {}, fs,
210276 coverage_frontier);
277+ corpus.UpdateWeights (fs, coverage_frontier,
278+ Corpus::WeightMethod::FeatureRarity,
279+ /* scale_by_exec_time=*/ false );
211280 // Should not crash.
212281 corpus.Prune (fs, coverage_frontier, max_corpus_size, rng);
213282}
@@ -231,6 +300,9 @@ TEST(Corpus, PruneRegressionTest1) {
231300
232301 Add ({{1 }, {10 , 20 }});
233302 Add ({{2 }, {10 }});
303+ corpus.UpdateWeights (fs, coverage_frontier,
304+ Corpus::WeightMethod::FeatureRarity,
305+ /* scale_by_exec_time=*/ false );
234306 corpus.Prune (fs, coverage_frontier, max_corpus_size, rng);
235307}
236308
0 commit comments