@@ -37,6 +37,8 @@ a copy of this software and associated documentation files (the
3737import edu .illinois .nondex .common .Logger ;
3838import edu .illinois .nondex .common .Utils ;
3939
40+ import org .apache .commons .lang3 .tuple .Pair ;
41+
4042import org .apache .maven .execution .MavenSession ;
4143import org .apache .maven .model .Plugin ;
4244import org .apache .maven .plugin .BuildPluginManager ;
@@ -92,26 +94,43 @@ public String debug() throws MojoExecutionException {
9294 }
9395
9496 private String tryDebugSeeds () {
95- Configuration failingOne = this .debugWithConfigurations (this .failingConfigurations );
97+ List < Configuration > debuggedOnes = this .debugWithConfigurations (this .failingConfigurations );
9698
97- if (failingOne != null ) {
98- return failingOne .toArgLine () + String .format ("%n" ) + "DEBUG RESULTS FOR " + failingOne .testName + " AT: "
99- + failingOne .getDebugPath ();
99+ if (debuggedOnes .size () > 0 ) {
100+ return makeResultString (debuggedOnes );
100101 }
101102
102103 // The seeds that failed with the full test-suite no longer fail
103104 // Searching for different seeds
105+ Logger .getGlobal ().log (Level .FINE , "TRYING NEW SEEDS" );
104106 List <Configuration > retryWOtherSeeds = this .createNewSeedsToRetry ();
105- failingOne = this .debugWithConfigurations (retryWOtherSeeds );
107+ debuggedOnes = this .debugWithConfigurations (retryWOtherSeeds );
106108
107- if (failingOne != null ) {
108- return failingOne .toArgLine () + String .format ("%n" ) + "DEBUG RESULTS FOR " + failingOne .testName + " AT: "
109- + failingOne .getDebugPath ();
109+ if (debuggedOnes .size () > 0 ) {
110+ return makeResultString (debuggedOnes );
110111 }
111112
112113 return null ;
113114 }
114115
116+ private String makeResultString (List <Configuration > debuggedOnes ) {
117+ StringBuilder sb = new StringBuilder ();
118+ for (Configuration config : debuggedOnes ) {
119+ if (config == null ) {
120+ continue ;
121+ }
122+ sb .append (config .toArgLine ());
123+ sb .append ("\n DEBUG RESULTS FOR " );
124+ sb .append (config .testName );
125+ sb .append (" AND SEED: " );
126+ sb .append (config .seed );
127+ sb .append (" AT: " );
128+ sb .append (config .getDebugPath ());
129+ sb .append ('\n' );
130+ }
131+ return sb .toString ();
132+ }
133+
115134 private List <Configuration > createNewSeedsToRetry () {
116135 Configuration someFailingConfig = this .failingConfigurations .iterator ().next ();
117136 int newSeed = someFailingConfig .seed * ConfigurationDefaults .SEED_FACTOR ;
@@ -128,85 +147,114 @@ private List<Configuration> createNewSeedsToRetry() {
128147 return retryWOtherSeeds ;
129148 }
130149
131- private Configuration debugWithConfigurations (List <Configuration > failingConfigurations ) {
132- Configuration debConfig = null ;
150+ private List < Configuration > debugWithConfigurations (List <Configuration > failingConfigurations ) {
151+ List < Configuration > allDebuggedConfigs = new LinkedList < Configuration >() ;
133152 for (Configuration config : failingConfigurations ) {
134153 Configuration dryConfig ;
135154 if ((dryConfig = this .failsOnDry (config )) != null ) {
136- Configuration failingConfig = this .startDebugBinary (dryConfig );
137-
138- // If debugged down to single choice point, then go ahead and return that
139- if (failingConfig != null && failingConfig .numChoices () == 0 ) {
140- return failingConfig ;
141- }
142- // Otherwise should go on until finding better one
143- if (debConfig == null || failingConfig .hasFewerChoicePoints (debConfig )) {
144- debConfig = failingConfig ;
145- }
155+ // Get all debugged points and just add them to the full list
156+ List <Configuration > debuggedConfigs = this .startDebugBinary (dryConfig );
157+ allDebuggedConfigs .addAll (debuggedConfigs );
146158 }
147159 }
148160
149- return debConfig ;
161+ return allDebuggedConfigs ;
150162 }
151163
152164 private Configuration failsOnDry (Configuration config ) {
153165 return this .failsWithConfig (config , Integer .MIN_VALUE , Integer .MAX_VALUE );
154166 }
155167
156- public Configuration startDebugBinary (Configuration config ) {
157- long start = 0 ;
158- long end = config .getInvocationCount ();
168+ public List <Configuration > startDebugBinary (Configuration config ) {
169+ List <Configuration > allFailingConfigurations = new LinkedList <Configuration >();
170+
171+ List <Pair <Pair <Long , Long >, Configuration >> pairs = new LinkedList <Pair <Pair <Long , Long >, Configuration >>();
172+ pairs .add ((Pair <Pair <Long , Long >, Configuration >)Pair .of ((Pair <Long , Long >)Pair .of (0L ,
173+ (long )config .getInvocationCount ()), config ));
174+
159175 Configuration failingConfiguration = null ;
160- while (start < end ) {
161- Logger .getGlobal ().log (Level .INFO , "Debugging binary for " + this .test + " " + start + " : " + end );
176+ while (pairs .size () > 0 ) {
177+ Pair <Pair <Long , Long >, Configuration > pair = pairs .remove (0 );
178+ Pair <Long , Long > range = pair .getLeft ();
179+ failingConfiguration = pair .getRight ();
180+ long start = range .getLeft ();
181+ long end = range .getRight ();
182+
183+ if (start < end ) {
184+ Logger .getGlobal ().log (Level .INFO , "Debugging binary for " + this .test + " " + start + " : " + end );
185+
186+ boolean binarySuccess = false ;
187+ long midPoint = (start + end ) / 2 ;
188+ if ((failingConfiguration = this .failsWithConfig (config , start , midPoint )) != null ) {
189+ pairs .add (Pair .of ((Pair <Long , Long >)Pair .of (start , midPoint ), failingConfiguration ));
190+ binarySuccess = true ;
191+ }
192+ if ((failingConfiguration = this .failsWithConfig (config , midPoint + 1 , end )) != null ) {
193+ pairs .add (Pair .of ((Pair <Long , Long >)Pair .of (midPoint + 1 , end ), failingConfiguration ));
194+ binarySuccess = true ;
195+ }
162196
163- long midPoint = (start + end ) / 2 ;
164- if ((failingConfiguration = this .failsWithConfig (config , start , midPoint )) != null ) {
165- end = midPoint ;
166- continue ;
167- } else if ((failingConfiguration = this .failsWithConfig (config , midPoint + 1 , end )) != null ) {
168- start = midPoint + 1 ;
169- continue ;
197+ // If both halves fail, try the entire range
198+ if (!binarySuccess ) {
199+ Logger .getGlobal ().log (Level .SEVERE , "Binary splitting did not work. Going to linear" );
200+ allFailingConfigurations .addAll (this .startDebugLinear (config , start , end ));
201+ }
170202 } else {
171- Logger .getGlobal ().log (Level .FINE , "Binary splitting did not work. Going to linear" );
172- failingConfiguration = this .startDebugLinear (config , start , end );
173- break ;
203+ // Since start <= end is always true, this branch means start == end, so reached end
204+ if (failingConfiguration != null ) {
205+ allFailingConfigurations .add (this .reportDebugInfo (failingConfiguration ));
206+ }
174207 }
175208 }
176- if (failingConfiguration != null ) {
177- return this .reportDebugInfo (failingConfiguration );
178- }
179- return failingConfiguration ;
209+
210+ return allFailingConfigurations ;
180211 }
181212
182213 private Configuration reportDebugInfo (Configuration failingConfiguration ) {
183214 return this .failsWithConfig (failingConfiguration , failingConfiguration .start , failingConfiguration .end , true );
184215 }
185216
186- public Configuration startDebugLinear (Configuration config , long start , long end ) {
217+ public List <Configuration > startDebugLinear (Configuration config , long start , long end ) {
218+ List <Configuration > allFailingConfigurations = new LinkedList <Configuration >();
219+
220+ List <Pair <Pair <Long , Long >, Configuration >> pairs = new LinkedList <Pair <Pair <Long , Long >, Configuration >>();
221+ pairs .add ((Pair <Pair <Long , Long >, Configuration >)Pair .of ((Pair <Long , Long >)Pair .of (start , end ),
222+ config ));
223+
187224 Configuration failingConfiguration = null ;
188- long localStart = start ;
189- long localEnd = end ;
190- // Give up if range too large
191- if (localEnd - localStart > 50 ) {
192- return null ;
193- }
194- while (localStart < localEnd ) {
195- Logger .getGlobal ().log (Level .INFO ,
196- "Debugging linear for " + this .test + " " + localStart + " : " + localEnd );
225+ while (pairs .size () > 0 ) {
226+ Pair <Pair <Long , Long >, Configuration > pair = pairs .remove (0 );
227+ Pair <Long , Long > range = pair .getLeft ();
228+ failingConfiguration = pair .getRight ();
229+ long localStart = range .getLeft ();
230+ long localEnd = range .getRight ();
231+
232+ if (localStart < localEnd ) {
233+ Logger .getGlobal ().log (Level .INFO , "Debugging linear for " + this .test + " "
234+ + localStart + " : " + localEnd );
235+
236+ boolean found = false ;
237+ if ((failingConfiguration = this .failsWithConfig (config , localStart , localEnd - 1 )) != null ) {
238+ pairs .add (Pair .of ((Pair <Long , Long >)Pair .of (localStart , localEnd - 1 ), failingConfiguration ));
239+ found = true ;
240+ }
241+ if ((failingConfiguration = this .failsWithConfig (config , localStart + 1 , localEnd )) != null ) {
242+ pairs .add (Pair .of ((Pair <Long , Long >)Pair .of (localStart + 1 , localEnd ), failingConfiguration ));
243+ found = true ;
244+ }
197245
198- if ((failingConfiguration = this .failsWithConfig (config , localStart , localEnd - 1 )) != null ) {
199- localEnd = localEnd - 1 ;
200- continue ;
201- } else if ((failingConfiguration = this .failsWithConfig (config , localStart + 1 , localEnd )) != null ) {
202- localStart = localStart + 1 ;
203- continue ;
246+ if (!found ) {
247+ Logger .getGlobal ().log (Level .FINE , "Refining did not work. Does not fail with linear on range "
248+ + localStart + " : " + localEnd + "." );
249+ }
204250 } else {
205- Logger .getGlobal ().log (Level .FINE , "Refining did not work. Does not fail with linear." );
206- break ;
251+ // Since start <= end is always true, this branch means start == end, so reached end
252+ if (failingConfiguration != null ) {
253+ allFailingConfigurations .add (this .reportDebugInfo (failingConfiguration ));
254+ }
207255 }
208256 }
209- return failingConfiguration ;
257+ return allFailingConfigurations ;
210258 }
211259
212260 private Configuration failsWithConfig (Configuration config , long start , long end ) {
0 commit comments