1 /*
2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package nsk.share.jdi.sde;
24 
25 import java.io.*;
26 import java.nio.channels.FileChannel;
27 import java.util.*;
28 import com.sun.jdi.*;
29 import com.sun.jdi.event.BreakpointEvent;
30 import com.sun.jdi.event.Event;
31 import com.sun.jdi.event.StepEvent;
32 import nsk.share.ClassFileFinder;
33 import nsk.share.TestBug;
34 import nsk.share.jdi.EventHandler;
35 import nsk.share.jdi.TestDebuggerType2;
36 
37 /*
38  * Class is used as base debugger for SDE tests.
39  *
40  * This class contains several methods called 'prepareDefaultPatchedClassFile_TypeXXX' which create
41  * class file with added SourceDebugExtension attribute and return debug information about created file.
42  * (this methods was moved in SDEDebugger class if similar generated class files were used in 2 or more tests)
43  *
44  *
45  */
46 public class SDEDebugger extends TestDebuggerType2 {
47     protected static final int INIT_LINE = 32;    // n.s.j.sde.TestClass1::<init>
48     protected static final int METHOD1_LINE = 43; // n.s.j.sde.TestClass1::sde_testMethod1
49     protected static final int METHOD2_LINE = 54; // n.s.j.sde.TestClass1::sde_testMethod2
50     public static String javaStratumName = "Java";
51 
52     // Set debug data for "Java" stratum for TestClass1
53     public static List<DebugLocation> javaStratumLocations_TestClass1 = new ArrayList<DebugLocation>();
54 
55     public static String javaSourceName_TestClass1 = "TestClass1.java";
56 
57     public static String javaSourcePath_TestClass1 = "nsk" + File.separator + "share" + File.separator + "jdi"
58             + File.separator + "sde" + File.separator + "TestClass1.java";
59 
60     static {
61         for (int i = 0; i < 8; i++) {
javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1, R, INIT_LINE + i, INIT_LINE + i))62             javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
63                     "<init>", INIT_LINE + i, INIT_LINE + i));
javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1, R, METHOD1_LINE + i, METHOD1_LINE + i))64             javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
65                     "sde_testMethod1", METHOD1_LINE + i, METHOD1_LINE + i));
javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1, R, METHOD2_LINE + i, METHOD2_LINE + i))66             javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
67                     "sde_testMethod2", METHOD2_LINE + i, METHOD2_LINE + i));
68         }
69     }
70 
71     // insert debug information about "Java" stratum in the given Map<String,
72     // LocationsData>
addJavaLocations(Map<String, LocationsData> testStratumData, boolean setJavaStratumDefault)73     static protected void addJavaLocations(Map<String, LocationsData> testStratumData, boolean setJavaStratumDefault) {
74         LocationsData locationsData = new LocationsData(javaStratumName);
75 
76         if (setJavaStratumDefault)
77             locationsData.isDefault = true;
78 
79         locationsData.paths.add(javaSourcePath_TestClass1);
80         locationsData.allLocations.addAll(javaStratumLocations_TestClass1);
81         locationsData.sourceLocations.put(javaSourceName_TestClass1, javaStratumLocations_TestClass1);
82 
83         testStratumData.put(javaStratumName, locationsData);
84 
85     }
86 
87     // common base names for test stratum, stratum source name and stratum
88     // source path
89     public static final String testStratumName = "TestStratum";
90 
91     public static final String testStratumSourceName = "testSource";
92 
93     public static final String testStratumSourcePath = "testSourcePath";
94 
95     // Event listener thread which saves all received StepEvents
96     public class StepEventListener extends EventHandler.EventListener {
97         // is BreakpointEvent was received (debuggee should stop at breakpoint
98         // after StepEvents generation)
99         private volatile boolean breakpointEventReceived;
100 
101         private List<Location> stepLocations = new ArrayList<Location>();
102 
stepLocations()103         public List<Location> stepLocations() {
104             return stepLocations;
105         }
106 
clearLocations()107         public void clearLocations() {
108             stepLocations.clear();
109         }
110 
eventReceived(Event event)111         public boolean eventReceived(Event event) {
112             if (event instanceof StepEvent) {
113                 StepEvent stepEvent = (StepEvent) event;
114 
115                 stepLocations.add(stepEvent.location());
116 
117                 vm.resume();
118 
119                 return true;
120             }
121             // debuggee should stop after event generation
122             else if (event instanceof BreakpointEvent) {
123                 breakpointEventReceived = true;
124                 vm.resume();
125 
126                 return true;
127             }
128 
129             return false;
130         }
131 
waitBreakpointEvent()132         public void waitBreakpointEvent() {
133             while (!breakpointEventReceived)
134                 Thread.yield();
135         }
136     }
137 
138     // debug information about location (implements Comparable to make possible
139     // using DebugLocation with java.util.Set)
140     public static class DebugLocation implements Comparable<DebugLocation> {
DebugLocation(String sourceName, String sourcePath, String methodName, int inputLine, int outputLine)141         public DebugLocation(String sourceName, String sourcePath, String methodName, int inputLine, int outputLine) {
142             this.sourceName = sourceName;
143             this.sourcePath = sourcePath;
144             this.inputLine = inputLine;
145             this.outputLine = outputLine;
146             this.methodName = methodName;
147         }
148 
149         public String sourceName;
150 
151         public String sourcePath;
152 
153         public String methodName;
154 
155         public int inputLine;
156 
157         public int outputLine;
158 
toString()159         public String toString() {
160             return "Line number: " + inputLine + " SourceName: " + sourceName + " SourcePath: " + sourcePath;
161         }
162 
163         // compare DebugLocation with com.sun.jdi.Location
compare(Location location, String stratum)164         public boolean compare(Location location, String stratum) {
165             try {
166                 if (stratum == null) {
167                     return (location.lineNumber() == inputLine) && location.sourceName().equals(sourceName)
168                             && location.sourcePath().equals(sourcePath);
169                 } else {
170                     return (location.lineNumber(stratum) == inputLine)
171                             && location.sourceName(stratum).equals(sourceName)
172                             && location.sourcePath(stratum).equals(sourcePath);
173                 }
174             } catch (AbsentInformationException e) {
175                 return false;
176             }
177         }
178 
179         // used to find locations for given line
isConform(String sourceName, int lineNumber)180         public boolean isConform(String sourceName, int lineNumber) {
181             boolean sourceConform = (sourceName == null ? true : this.sourceName.equals(sourceName));
182 
183             return sourceConform && (this.inputLine == lineNumber);
184         }
185 
186         // implements this method to make possible using DebugLocation with java.util.Set
compareTo(DebugLocation location)187         public int compareTo(DebugLocation location) {
188             return (this.sourceName.equals(location.sourceName) && this.inputLine == location.inputLine) ? 0 : 1;
189         }
190     }
191 
192     // Class contains debug information about sources, paths, locations
193     // available for class
194     public static class LocationsData {
LocationsData(String stratumName)195         public LocationsData(String stratumName) {
196             this.stratumName = stratumName;
197         }
198 
sourceNames()199         public List<String> sourceNames() {
200             List<String> sourceNames = new ArrayList<String>();
201             sourceNames.addAll(sourceLocations.keySet());
202 
203             return sourceNames;
204         }
205 
206         public String stratumName;
207 
208         // is stratum default for ReferenceType
209         public boolean isDefault;
210 
211         // locations for source files
212         public Map<String, List<DebugLocation>> sourceLocations = new TreeMap<String, List<DebugLocation>>();
213 
214         // all locations for stratum
215         public List<DebugLocation> allLocations = new ArrayList<DebugLocation>();
216 
217         // all paths for stratum
218         public List<String> paths = new ArrayList<String>();
219     }
220 
locationToString(Location location, String stratum)221     static protected String locationToString(Location location, String stratum) {
222         String result;
223 
224         result = "Line number: " + (stratum == null ? location.lineNumber() : location.lineNumber(stratum));
225 
226         try {
227             result += (" Source name: " + (stratum == null ? location.sourceName() : location.sourceName(stratum)));
228         } catch (AbsentInformationException e) {
229             result += (" Source name: " + " INFORMATION IS ABSENT");
230         }
231 
232         try {
233             result += (" Source path: " + (stratum == null ? location.sourcePath() : location.sourcePath(stratum)));
234         } catch (AbsentInformationException e) {
235             result += (" Source path: " + " INFORMATION IS ABSENT");
236         }
237 
238         return result;
239     }
240 
241     // seach class file for given class and create copy of this class file in
242     // 'testWorkDir' directory
createLocalClassfileCopy(String className)243     protected File createLocalClassfileCopy(String className) throws IOException {
244         int index = className.lastIndexOf(".");
245 
246         String path;
247 
248         if (index < 0)
249             path = "";
250         else
251             path = className.substring(0, index).replace(".", "/");
252 
253         File dirs = new File(testWorkDir + "/" + path);
254         dirs.mkdirs();
255 
256         File oldFile = null;
257         {
258             java.nio.file.Path tmp = ClassFileFinder.findClassFile(className, classpath);
259             oldFile = tmp == null ? null : tmp.toFile();
260         }
261         File newFile = copyFile(oldFile,
262                 testWorkDir + "/" + className.replace(".", "/") + ".class");
263 
264         return newFile;
265     }
266 
267     // create class file with multiple strata
savePathcedClassFile(String className, SmapGenerator smapGenerator, String smapFileName)268     protected void savePathcedClassFile(String className, SmapGenerator smapGenerator, String smapFileName) {
269         File patchedClassFile = null;
270 
271         try {
272             patchedClassFile = createLocalClassfileCopy(className);
273         } catch (IOException e) {
274             e.printStackTrace(log.getOutStream());
275             throw new TestBug("Unexpected IO exception: " + e);
276         }
277 
278         smapFileName = testWorkDir + "/" + smapFileName;
279         smapGenerator.setOutputFileName(smapFileName);
280 
281         File smapFile = null;
282 
283         try {
284             smapFile = smapGenerator.saveToFile(smapFileName);
285         } catch (IOException e) {
286             e.printStackTrace(log.getOutStream());
287             throw new TestBug("Unexpected IO exception: " + e);
288         }
289 
290         log.display("Add for class " + className + " following SDE: ");
291         log.display(smapGenerator.getString());
292 
293         try {
294             InstallSDE.install(patchedClassFile, smapFile, false);
295         } catch (IOException e) {
296             e.printStackTrace(log.getOutStream());
297             throw new TestBug("Unexpected IO exception: " + e);
298         }
299     }
300 
301     // common for SDE tests debuggee name
debuggeeClassName()302     protected String debuggeeClassName() {
303         if (classpath == null) {
304             throw new TestBug("Debugger requires 'testClassPath' parameter");
305         }
306 
307         return SDEDebuggee.class.getName() + " -testClassPath " + testWorkDir;
308     }
309 
310     // parses common for all SDE - tests parameters
doInit(String args[], PrintStream out)311     protected String[] doInit(String args[], PrintStream out) {
312         args = super.doInit(args, out);
313 
314         if (classpath == null) {
315             throw new TestBug("Debugger requires 'testClassPath' parameter");
316         }
317         if (testWorkDir == null) {
318             throw new TestBug("Debugger requires 'testWorkDir' parameter");
319         }
320 
321         return args;
322     }
323 
324     // single input line is mapped to the single output line, test stratum has
325     // single source
prepareDefaultPatchedClassFile_Type1(String className, int testStratumCount, boolean setJavaStratumDefault)326     protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type1(String className, int testStratumCount,
327             boolean setJavaStratumDefault) {
328         /*
329          * "Java" "TestStratum"
330          *
331          * <init>
332          * 32 --> 1000, source1
333          * 33 --> 1001, source1
334          * ...
335          * ...
336          * 39 --> 1007, source1
337          *
338          * sde_testMethod1
339          *
340          * 43 --> 1100, source1
341          * 44 --> 1101, source1
342          * ...
343          * ...
344          * 50 --> 1107, source1
345          *
346          * sde_testMethod1
347          * 54 --> 1200, source1
348          * 55 --> 1201, source1
349          * ...
350          * ...
351          * 61 --> 1207, source1
352          */
353 
354         Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
355 
356         String smapFileName = "TestSMAP.smap";
357         SmapGenerator smapGenerator = new SmapGenerator();
358 
359         for (int i = 0; i < testStratumCount; i++) {
360             String stratumName = testStratumName + (i + 1);
361 
362             LocationsData locationsData = new LocationsData(stratumName);
363 
364             String sourceName = testStratumSourceName + (i + 1);
365             String sourcePath = testStratumSourcePath + (i + 1);
366 
367             locationsData.paths.add(sourcePath);
368 
369             SmapStratum smapStratum = new SmapStratum(stratumName);
370 
371             List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
372 
373             int baseLineNumber = 1000 * (i + 1);
374 
375             for (int j = 0; j < 8; j++) {
376                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
377                         "<init>", baseLineNumber + j, INIT_LINE + j));
378                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
379                         "sde_testMethod1", baseLineNumber + 100 + j, METHOD1_LINE + j));
380                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
381                         "sde_testMethod2", baseLineNumber + 200 + j, METHOD2_LINE + j));
382             }
383 
384             locationsData.sourceLocations.put(sourceName, sourceLocations);
385             locationsData.allLocations.addAll(sourceLocations);
386 
387             testStratumData.put(stratumName, locationsData);
388 
389             smapStratum.addFile(sourceName, sourcePath);
390 
391             for (DebugLocation debugLocation : sourceLocations) {
392                 smapStratum.addLineData(debugLocation.inputLine, sourceName, 1, debugLocation.outputLine, 1);
393             }
394 
395             // if setJavaStratumDefault == false do first test stratum default
396             if (!(setJavaStratumDefault) && (i == 0)) {
397                 locationsData.isDefault = true;
398                 smapGenerator.addStratum(smapStratum, true);
399             } else
400                 smapGenerator.addStratum(smapStratum, false);
401         }
402 
403         savePathcedClassFile(className, smapGenerator, smapFileName);
404 
405         addJavaLocations(testStratumData, setJavaStratumDefault);
406 
407         return testStratumData;
408     }
409 
410     // single input line is mapped to the single output line, test stratum has 3
411     // sources
prepareDefaultPatchedClassFile_Type2(String className, int testStratumCount)412     protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type2(String className, int testStratumCount) {
413         /*
414          * "Java" "TestStratum"
415          *
416          * <init>
417          * 32 --> 1000, source1, path1
418          * 33 --> 1001, source2, path2
419          * 34 --> 1002, source3, path3
420          * ...
421          * ...
422          *
423          * sde_testMethod1
424          * 43 --> 1100, source1, path1
425          * 44 --> 1101, source2, path2
426          * 45 --> 1102, source3, path3
427          * ...
428          * ...
429          *
430          * sde_testMethod2
431          * 54 --> 1200, source1, path1
432          * 55 --> 1201, source2, path2
433          * 56 --> 1207, source3, path3
434          * ...
435          * ...
436          */
437 
438         Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
439 
440         String smapFileName = "TestSMAP.smap";
441         SmapGenerator smapGenerator = new SmapGenerator();
442 
443         for (int i = 0; i < testStratumCount; i++) {
444             String stratumName = testStratumName + (i + 1);
445             SmapStratum smapStratum = new SmapStratum(stratumName);
446 
447             LocationsData locationsData = new LocationsData(stratumName);
448 
449             String sourceName1 = testStratumSourceName + (i + 1) + "_1";
450             String sourcePath1 = testStratumSourcePath + (i + 1) + "_1";
451             locationsData.paths.add(sourcePath1);
452             smapStratum.addFile(sourceName1, sourcePath1);
453 
454             String sourceName2 = testStratumSourceName + (i + 1) + "_2";
455             String sourcePath2 = testStratumSourcePath + (i + 1) + "_2";
456             locationsData.paths.add(sourcePath2);
457             smapStratum.addFile(sourceName2, sourcePath2);
458 
459             String sourceName3 = testStratumSourceName + (i + 1) + "_3";
460             String sourcePath3 = testStratumSourcePath + (i + 1) + "_3";
461             locationsData.paths.add(sourcePath3);
462             smapStratum.addFile(sourceName3, sourcePath3);
463 
464             List<DebugLocation> source1Locations = new ArrayList<DebugLocation>();
465             List<DebugLocation> source2Locations = new ArrayList<DebugLocation>();
466             List<DebugLocation> source3Locations = new ArrayList<DebugLocation>();
467 
468             for (int j = 0; j < 8; j++) {
469                 if (j % 3 == 0) {
470                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
471                             "<init>", 1000 + j, INIT_LINE + j));
472                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
473                             "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
474                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
475                             "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
476                 } else if (j % 3 == 1) {
477                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
478                             "<init>", 1000 + j, INIT_LINE + j));
479                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
480                             "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
481                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
482                             "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
483                 } else {
484                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
485                             "<init>", 1000 + j, INIT_LINE + j));
486                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
487                             "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
488                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
489                             "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
490                 }
491             }
492 
493             locationsData.sourceLocations.put(sourceName1, source1Locations);
494             locationsData.sourceLocations.put(sourceName2, source2Locations);
495             locationsData.sourceLocations.put(sourceName3, source3Locations);
496 
497             locationsData.allLocations.addAll(source1Locations);
498             locationsData.allLocations.addAll(source2Locations);
499             locationsData.allLocations.addAll(source3Locations);
500 
501             for (DebugLocation debugLocation : locationsData.allLocations) {
502                 smapStratum.addLineData(
503                         debugLocation.inputLine,
504                         debugLocation.sourceName,
505                         1,
506                         debugLocation.outputLine,
507                         1);
508             }
509 
510             smapGenerator.addStratum(smapStratum, false);
511 
512             testStratumData.put(stratumName, locationsData);
513         }
514 
515         savePathcedClassFile(className, smapGenerator, smapFileName);
516 
517         addJavaLocations(testStratumData, true);
518 
519         return testStratumData;
520     }
521 
522     // single input line is mapped to two output lines
prepareDefaultPatchedClassFile_Type3(String className, int testStratumCount, boolean setJavaStratumDefault)523     protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type3(String className, int testStratumCount,
524             boolean setJavaStratumDefault) {
525         /*
526          * "Java" "TestStratum"
527          *
528          * <init>
529          * 32 --> 1001, source1
530          * 34 --> 1002, source1
531          * 36 --> 1003, source1
532          * 38 --> 1004, source1
533          *
534          * sde_testMethod1
535          * 43 --> 1101, source1
536          * 45 --> 1102, source1
537          * 47 --> 1103, source1
538          * 49 --> 1104, source1
539          *
540          * sde_testMethod2
541          * 54 --> 1201, source1
542          * 56 --> 1202, source1
543          * 58 --> 1203, source1
544          * 60 --> 1204, source1
545          */
546 
547         Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
548 
549         String smapFileName = "TestSMAP.smap";
550         SmapGenerator smapGenerator = new SmapGenerator();
551 
552         for (int i = 0; i < testStratumCount; i++) {
553             String stratumName = testStratumName + (i + 1);
554             LocationsData locationsData = new LocationsData(stratumName);
555 
556             String sourceName = testStratumSourceName + (i + 1);
557             String sourcePath = testStratumSourcePath + (i + 1);
558             locationsData.paths.add(sourcePath);
559 
560             SmapStratum smapStratum = new SmapStratum(stratumName);
561 
562             List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
563 
564             int baseLineNumber = 1000 * (i + 1);
565 
566             for (int j = 0; j < 4; j++) {
567                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
568                         "<init>", baseLineNumber + j, INIT_LINE + j * 2));
569                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
570                         "sde_testMethod1", baseLineNumber + 100 + j, METHOD1_LINE + j * 2));
571                 sourceLocations.add(new DebugLocation(sourceName, sourcePath,
572                         "sde_testMethod2", baseLineNumber + 200 + j, METHOD2_LINE + j * 2));
573             }
574 
575             locationsData.allLocations.addAll(sourceLocations);
576             locationsData.sourceLocations.put(sourceName, sourceLocations);
577 
578             testStratumData.put(stratumName, locationsData);
579 
580             smapStratum.addFile(sourceName, sourcePath);
581 
582             for (DebugLocation debugLocation : locationsData.allLocations) {
583                 smapStratum.addLineData(debugLocation.inputLine, sourceName, 1, debugLocation.outputLine, 1);
584             }
585 
586             // if setJavaStratumDefault == false do first stratum default
587             if (!setJavaStratumDefault && (i == 0)) {
588                 locationsData.isDefault = true;
589                 smapGenerator.addStratum(smapStratum, true);
590             } else
591                 smapGenerator.addStratum(smapStratum, false);
592         }
593 
594         savePathcedClassFile(className, smapGenerator, smapFileName);
595 
596         addJavaLocations(testStratumData, setJavaStratumDefault);
597 
598         return testStratumData;
599     }
600 
601     // 3 different test stratums define disjoint locations sets
prepareDefaultPatchedClassFile_Type4(String className)602     protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type4(String className) {
603         /*
604          * "Java" "TestStratum1" "TestStratum2" "TestStratum3"
605          *
606          * <init>
607          * 32 --> 1000
608          * ...
609          * ...
610          * 39 --> 1007
611          *
612          * sde_testMethod1
613          * 43 --> 1100
614          * ...
615          * ...
616          * 50 --> 1107
617          *
618          * sde_testMethod2
619          * 54 --> 1200
620          * ...
621          * ...
622          * 61 --> 1207
623          */
624         Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
625 
626         String smapFileName = "TestSMAP.smap";
627 
628         SmapGenerator smapGenerator = new SmapGenerator();
629 
630         String stratumName = testStratumName + "1";
631         LocationsData locationsData = new LocationsData(stratumName);
632         List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
633         String methodName = "<init>";
634         for (int i = 0; i < 8; i++) {
635             sourceLocations.add(new DebugLocation(
636                     testStratumSourceName, testStratumSourcePath, methodName,
637                     1000 + i, INIT_LINE + i));
638         }
639         locationsData.allLocations.addAll(sourceLocations);
640         locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
641         testStratumData.put(stratumName, locationsData);
642 
643         stratumName = testStratumName + "2";
644         locationsData = new LocationsData(stratumName);
645         sourceLocations = new ArrayList<DebugLocation>();
646         methodName = "sde_testMethod1";
647         for (int i = 0; i < 8; i++) {
648             sourceLocations.add(new DebugLocation(
649                     testStratumSourceName, testStratumSourcePath, methodName,
650                     1100 + i, METHOD1_LINE + i));
651         }
652         locationsData.allLocations.addAll(sourceLocations);
653         locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
654         testStratumData.put(stratumName, locationsData);
655 
656         stratumName = testStratumName + "3";
657         locationsData = new LocationsData(stratumName);
658         sourceLocations = new ArrayList<DebugLocation>();
659         methodName = "sde_testMethod2";
660         for (int i = 0; i < 8; i++) {
661             sourceLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath,
662                     methodName, 1200 + i, METHOD2_LINE + i));
663         }
664         locationsData.allLocations.addAll(sourceLocations);
665         locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
666         testStratumData.put(stratumName, locationsData);
667 
668         for (String stratum : testStratumData.keySet()) {
669             SmapStratum smapStratum = new SmapStratum(stratum);
670             smapStratum.addFile(testStratumSourceName, testStratumSourcePath);
671 
672             for (DebugLocation debugLocation : testStratumData.get(stratum).allLocations)
673                 smapStratum.addLineData(
674                         debugLocation.inputLine,
675                         debugLocation.sourceName,
676                         1,
677                         debugLocation.outputLine,
678                         1);
679 
680             smapGenerator.addStratum(smapStratum, false);
681         }
682 
683         savePathcedClassFile(className, smapGenerator, smapFileName);
684 
685         return testStratumData;
686     }
687 
688     // single input line is mapped to the single output line, test stratum has 3
689     // sources,
690     // lines in each method has same numbers, each method has locations in 3
691     // sources
prepareDefaultPatchedClassFile_Type5(String className, int testStratumCount)692     protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type5(String className, int testStratumCount) {
693         /*
694          * "Java" "TestStratum"
695          *
696          * <init>
697          * 32 --> 1000, source1, path1
698          * 33 --> 1000, source2, path2
699          * 34 --> 1000, source3, path3
700          * ...
701          * ...
702          *
703          * sde_testMethod1
704          * 43 --> 1100, source1, path1
705          * 44 --> 1100, source2, path2
706          * 45 --> 1100, source3, path3
707          * ...
708          * ...
709          *
710          * sde_testMethod2
711          * 54 --> 1200, source1, path1
712          * 55 --> 1200, source2, path2
713          * 56 --> 1200, source3, path3
714          * ...
715          * ...
716          */
717 
718         Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
719 
720         String smapFileName = "TestSMAP.smap";
721         SmapGenerator smapGenerator = new SmapGenerator();
722 
723         for (int i = 0; i < testStratumCount; i++) {
724             String stratumName = testStratumName + (i + 1);
725             SmapStratum smapStratum = new SmapStratum(stratumName);
726 
727             LocationsData locationsData = new LocationsData(stratumName);
728 
729             String sourceName1 = testStratumSourceName + (i + 1) + "_1";
730             String sourcePath1 = testStratumSourcePath + (i + 1) + "_1";
731             locationsData.paths.add(sourcePath1);
732             smapStratum.addFile(sourceName1, sourcePath1);
733 
734             String sourceName2 = testStratumSourceName + (i + 1) + "_2";
735             String sourcePath2 = testStratumSourcePath + (i + 1) + "_2";
736             locationsData.paths.add(sourcePath2);
737             smapStratum.addFile(sourceName2, sourcePath2);
738 
739             String sourceName3 = testStratumSourceName + (i + 1) + "_3";
740             String sourcePath3 = testStratumSourcePath + (i + 1) + "_3";
741             locationsData.paths.add(sourcePath3);
742             smapStratum.addFile(sourceName3, sourcePath3);
743 
744             List<DebugLocation> source1Locations = new ArrayList<DebugLocation>();
745             List<DebugLocation> source2Locations = new ArrayList<DebugLocation>();
746             List<DebugLocation> source3Locations = new ArrayList<DebugLocation>();
747 
748             for (int j = 0; j < 8; j++) {
749                 if (j % 3 == 0) {
750                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
751                             "<init>", 1000, INIT_LINE + j));
752                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
753                             "sde_testMethod1", 1100, METHOD1_LINE + j));
754                     source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
755                             "sde_testMethod2", 1200, METHOD2_LINE + j));
756                 } else if (j % 3 == 1) {
757                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
758                             "<init>", 1000, INIT_LINE + j));
759                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
760                             "sde_testMethod1", 1100, METHOD1_LINE + j));
761                     source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
762                             "sde_testMethod2", 1200, METHOD2_LINE + j));
763                 } else {
764                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
765                             "<init>", 1000, INIT_LINE + j));
766                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
767                             "sde_testMethod1", 1100, METHOD1_LINE + j));
768                     source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
769                             "sde_testMethod2", 1200, METHOD2_LINE + j));
770                 }
771             }
772 
773             locationsData.sourceLocations.put(sourceName1, source1Locations);
774             locationsData.sourceLocations.put(sourceName2, source2Locations);
775             locationsData.sourceLocations.put(sourceName3, source3Locations);
776 
777             locationsData.allLocations.addAll(source1Locations);
778             locationsData.allLocations.addAll(source2Locations);
779             locationsData.allLocations.addAll(source3Locations);
780 
781             for (DebugLocation debugLocation : locationsData.allLocations) {
782                 smapStratum.addLineData(
783                         debugLocation.inputLine,
784                         debugLocation.sourceName,
785                         1,
786                         debugLocation.outputLine,
787                         1);
788             }
789 
790             smapGenerator.addStratum(smapStratum, false);
791 
792             testStratumData.put(stratumName, locationsData);
793         }
794 
795         savePathcedClassFile(className, smapGenerator, smapFileName);
796 
797         return testStratumData;
798     }
799 
copyFile(File srcFile, String newFileName)800     public static File copyFile(File srcFile, String newFileName) throws IOException {
801         FileChannel inChannel = new FileInputStream(srcFile).getChannel();
802 
803         File newFile = new File(newFileName);
804         newFile.createNewFile();
805         FileChannel outChannel = new FileOutputStream(newFile).getChannel();
806 
807         outChannel.transferFrom(inChannel, 0, inChannel.size());
808 
809         outChannel.close();
810         inChannel.close();
811 
812         return newFile;
813     }
814 
815     // find all locations of method with given name
816     // (used to check result of 'Method.allLineLocations()')
locationsOfMethod(List<DebugLocation> debugLocations, String methodName)817     static protected List<DebugLocation> locationsOfMethod(List<DebugLocation> debugLocations, String methodName) {
818         List<DebugLocation> result = new ArrayList<DebugLocation>();
819 
820         for (DebugLocation debugLocation : debugLocations) {
821             if (debugLocation.methodName.equals(methodName))
822                 result.add(debugLocation);
823         }
824 
825         return result;
826     }
827 
828     // find all locations for given line and source name
829     // (used to check result of 'Method.locationsOfLine()' and
830     // 'ReferenceType.locationsOfLine()')
locationsOfLine(List<DebugLocation> debugLocations, String sourceName, int lineNumber)831     static protected List<DebugLocation> locationsOfLine(List<DebugLocation> debugLocations, String sourceName,
832             int lineNumber) {
833         List<DebugLocation> result = new ArrayList<DebugLocation>();
834 
835         for (DebugLocation debugLocation : debugLocations) {
836             if (debugLocation.isConform(sourceName, lineNumber))
837                 result.add(debugLocation);
838         }
839 
840         return result;
841     }
842 
843     // find locations unique by line number and source name
844     // (used in 'check_ReferenceType_locationsOfLine' and
845     // 'check_Method_locationsOfLine' to find all line numbers available for
846     // ReferenceType or Method)
allUniqueLocations(List<DebugLocation> debugLocations)847     static protected Set<DebugLocation> allUniqueLocations(List<DebugLocation> debugLocations) {
848         Set<DebugLocation> result = new TreeSet<DebugLocation>();
849 
850         for (DebugLocation debugLocation : debugLocations) {
851             if (!result.contains(debugLocation)) {
852                 result.add(debugLocation);
853             }
854         }
855 
856         return result;
857     }
858 
859     // check is list of Locations contains only expected locations
compareLocations(List<Location> locations, List<DebugLocation> expectedLocations, String stratum)860     protected void compareLocations(List<Location> locations, List<DebugLocation> expectedLocations, String stratum) {
861         boolean success = true;
862 
863         List<Location> tempLocations = new LinkedList<Location>(locations);
864 
865         List<DebugLocation> tempExpectedLocations = new LinkedList<DebugLocation>(expectedLocations);
866 
867         for(Iterator<Location> locationsIterator = tempLocations.iterator(); locationsIterator.hasNext();) {
868             boolean isExpected = false;
869             Location location = locationsIterator.next();
870 
871             for(Iterator<DebugLocation> expectedLocationsIterator = tempExpectedLocations.iterator(); expectedLocationsIterator.hasNext();) {
872                 DebugLocation expectedLocation = expectedLocationsIterator.next();
873                 if (expectedLocation.compare(location, stratum)) {
874                     isExpected = true;
875                     locationsIterator.remove();
876                     expectedLocationsIterator.remove();
877                     break;
878                 }
879             }
880             if (!isExpected) {
881                 success = false;
882                 log.complain("Location " + location + " were not found in expected locations");
883             }
884         }
885 
886         if (tempLocations.size() != 0) {
887             success = false;
888             setSuccess(false);
889             log.complain("Not all locations were found in expected");
890         }
891 
892         if (tempExpectedLocations.size() != 0) {
893             success = false;
894             setSuccess(false);
895             log.complain("Following expected locations were not found in received");
896             for (DebugLocation expectedLocation : tempExpectedLocations) {
897                 log.complain(expectedLocation.toString());
898             }
899         }
900 
901         if (!success) {
902             setSuccess(false);
903             log.complain("Expected and actual locations differ");
904 
905             log.complain("Actual locations: ");
906             for (Location location : locations) {
907                 log.complain(locationToString(location, stratum));
908             }
909 
910             log.complain("Expected locations: ");
911             for (DebugLocation expectedLocation : expectedLocations) {
912                 log.complain(expectedLocation.toString());
913             }
914         }
915     }
916 
917     // test all SDE related methods of ReferenceType
checkReferenceType(String stratum, ReferenceType referenceType, List<String> expectedSourceNames, List<String> expectedSourcePaths, List<DebugLocation> expectedLocations)918     protected void checkReferenceType(String stratum, ReferenceType referenceType, List<String> expectedSourceNames,
919             List<String> expectedSourcePaths, List<DebugLocation> expectedLocations) {
920         log.display("Check sourceNames");
921         check_ReferenceType_sourceNames(referenceType, stratum, expectedSourceNames);
922         log.display("Check sourcePaths");
923         check_ReferenceType_sourcePaths(referenceType, stratum, expectedSourcePaths);
924         log.display("Check allLocations");
925         check_ReferenceType_allLineLocations(referenceType, stratum, expectedLocations);
926         log.display("Check locationsOfLine");
927         check_ReferenceType_locationsOfLine(referenceType, stratum, false, expectedLocations);
928 
929         for (Method method : referenceType.methods()) {
930             List<DebugLocation> expectedLocationsOfMethod = locationsOfMethod(expectedLocations, method.name());
931 
932             log.display("Check allLineLocations for method '" + method.name() + "'");
933             check_Method_allLineLocations(method, stratum, expectedLocationsOfMethod);
934             log.display("Check locationsOfLine for method '" + method.name() + "'");
935             check_Method_locationsOfLine(method, stratum, false, expectedLocationsOfMethod);
936         }
937     }
938 
939     // check is 'ReferenceType.sourceNames' returns only expected sources
check_ReferenceType_sourceNames(ReferenceType referenceType, String stratum, List<String> expectedSourceNames)940     protected void check_ReferenceType_sourceNames(ReferenceType referenceType, String stratum,
941             List<String> expectedSourceNames) {
942         try {
943             if (stratum == null) {
944                 String sourceName = referenceType.sourceName();
945                 String expectedSourceName = expectedSourceNames.get(0);
946 
947                 if (!sourceName.equals(expectedSourceName)) {
948                     setSuccess(false);
949                     log.complain("Unexpected result of ReferenceType.sourceName(): " + sourceName + ", expected is "
950                             + expectedSourceName);
951                 }
952             } else {
953                 boolean success = true;
954 
955                 List<String> sourceNames = referenceType.sourceNames(stratum);
956 
957                 if (!expectedSourceNames.containsAll(sourceNames)) {
958                     success = false;
959                     log.complain("ReferenceType.sourceNames() returns unexpected names");
960                 }
961 
962                 if (!sourceNames.containsAll(expectedSourceNames)) {
963                     success = false;
964                     log.complain("Not all expected source names was returned by ReferenceType.sourceNames()");
965                 }
966 
967                 if (!success) {
968                     log.complain("Expected source names:");
969                     for (String name : expectedSourceNames)
970                         log.complain(name);
971                     log.complain("Actual source names:");
972                     for (String name : sourceNames)
973                         log.complain(name);
974                 }
975             }
976         } catch (AbsentInformationException e) {
977             setSuccess(false);
978             log.complain("Unexpected exception: " + e);
979             e.printStackTrace(log.getOutStream());
980         }
981     }
982 
983     // check is 'ReferenceType.sourcePaths' returns only expected paths
check_ReferenceType_sourcePaths(ReferenceType referenceType, String stratum, List<String> expectedSourcePaths)984     protected void check_ReferenceType_sourcePaths(ReferenceType referenceType, String stratum,
985             List<String> expectedSourcePaths) {
986         try {
987             boolean success = true;
988 
989             List<String> sourcePaths = referenceType.sourcePaths(stratum);
990 
991             if (!expectedSourcePaths.containsAll(sourcePaths)) {
992                 success = false;
993                 log.complain("ReferenceType.sourcePaths() returns unexpected paths");
994             }
995 
996             if (!sourcePaths.containsAll(expectedSourcePaths)) {
997                 success = false;
998                 log.complain("Not all expected paths was returned by ReferenceType.sourcePaths()");
999             }
1000 
1001             if (!success) {
1002                 log.complain("Expected paths:");
1003                 for (String path : expectedSourcePaths)
1004                     log.complain(path);
1005                 log.complain("Actual paths:");
1006                 for (String path : sourcePaths)
1007                     log.complain(path);
1008             }
1009         } catch (AbsentInformationException e) {
1010             setSuccess(false);
1011             log.complain("Unexpected exception: " + e);
1012             e.printStackTrace(log.getOutStream());
1013         }
1014     }
1015 
1016     // check that method 'ReferenceType.allLineLocations' returns only expected
1017     // locations
check_ReferenceType_allLineLocations(ReferenceType referenceType, String stratum, List<DebugLocation> expectedLocations)1018     protected void check_ReferenceType_allLineLocations(ReferenceType referenceType, String stratum,
1019             List<DebugLocation> expectedLocations) {
1020         try {
1021             List<Location> locations = referenceType.allLineLocations();
1022             compareLocations(locations, expectedLocations, stratum);
1023         } catch (AbsentInformationException e) {
1024             setSuccess(false);
1025             log.complain("Unexpected exception: " + e);
1026             e.printStackTrace(log.getOutStream());
1027         }
1028 
1029     }
1030 
1031     // check that method 'Method.allLineLocations' returns only expected
1032     // locations
check_Method_allLineLocations(Method method, String stratum, List<DebugLocation> expectedLocationsOfMethod)1033     protected void check_Method_allLineLocations(Method method, String stratum,
1034             List<DebugLocation> expectedLocationsOfMethod) {
1035         try {
1036             List<Location> methodAllLineLocations = method.allLineLocations();
1037             compareLocations(methodAllLineLocations, expectedLocationsOfMethod, stratum);
1038         } catch (AbsentInformationException e) {
1039             setSuccess(false);
1040             log.complain("Unexpected exception: " + e);
1041             e.printStackTrace(log.getOutStream());
1042         }
1043     }
1044 
1045     // for each line available for method check result of
1046     // 'Method.locationsOfLine'
check_Method_locationsOfLine(Method method, String stratum, boolean allSources, List<DebugLocation> expectedLocationsOfMethod)1047     protected void check_Method_locationsOfLine(Method method, String stratum, boolean allSources,
1048             List<DebugLocation> expectedLocationsOfMethod) {
1049         try {
1050             for (DebugLocation uniqueLocation : allUniqueLocations(expectedLocationsOfMethod)) {
1051                 String sourceName = allSources ? null : uniqueLocation.sourceName;
1052 
1053                 List<DebugLocation> expectedLocationsOfLine = locationsOfLine(
1054                         expectedLocationsOfMethod,
1055                         sourceName,
1056                         uniqueLocation.inputLine);
1057 
1058                 List<Location> locationsOfLine = (stratum == null) ? method.locationsOfLine(uniqueLocation.inputLine)
1059                         : method.locationsOfLine(stratum, sourceName, uniqueLocation.inputLine);
1060 
1061                 compareLocations(locationsOfLine, expectedLocationsOfLine, stratum);
1062             }
1063         } catch (AbsentInformationException e) {
1064             setSuccess(false);
1065             log.complain("Unexpected exception: " + e);
1066             e.printStackTrace(log.getOutStream());
1067         }
1068     }
1069 
1070     // for each line available for ReferenceType check result of
1071     // 'ReferenceType.locationsOfLine'
check_ReferenceType_locationsOfLine(ReferenceType referenceType, String stratum, boolean allSources, List<DebugLocation> expectedLocations)1072     protected void check_ReferenceType_locationsOfLine(ReferenceType referenceType, String stratum, boolean allSources,
1073             List<DebugLocation> expectedLocations) {
1074         try {
1075             for (DebugLocation uniqueLocation : allUniqueLocations(expectedLocations)) {
1076                 String sourceName = allSources ? null : uniqueLocation.sourceName;
1077 
1078                 List<DebugLocation> expectedLocationsOfLine = locationsOfLine(
1079                         expectedLocations,
1080                         sourceName,
1081                         uniqueLocation.inputLine);
1082 
1083                 List<Location> locations = (stratum == null) ? referenceType.locationsOfLine(uniqueLocation.inputLine)
1084                         : referenceType.locationsOfLine(stratum, sourceName, uniqueLocation.inputLine);
1085 
1086                 compareLocations(locations, expectedLocationsOfLine, stratum);
1087             }
1088         } catch (AbsentInformationException e) {
1089             setSuccess(false);
1090             log.complain("Unexpected exception: " + e);
1091             e.printStackTrace(log.getOutStream());
1092         }
1093 
1094     }
1095 
1096     // check that method 'ReferenceType.availableStrata' returns only expected
1097     // stratums
check_ReferenceType_availableStrata(ReferenceType referenceType, List<String> expectedStrata)1098     protected void check_ReferenceType_availableStrata(ReferenceType referenceType, List<String> expectedStrata) {
1099         boolean success = true;
1100 
1101         List<String> strata = referenceType.availableStrata();
1102 
1103         if (!expectedStrata.containsAll(strata)) {
1104             success = false;
1105             log.complain("ReferenceType.availableStrata() returns unexpected values");
1106         }
1107 
1108         if (!strata.containsAll(expectedStrata)) {
1109             success = false;
1110             log.complain("Not all expected stratums was returned by ReferenceType.availableStrata()");
1111         }
1112 
1113         if (!success) {
1114             log.complain("Expected stratums:");
1115             for (String name : expectedStrata)
1116                 log.complain(name);
1117             log.complain("Actual stratums:");
1118             for (String name : strata)
1119                 log.complain(name);
1120         }
1121     }
1122 
1123 }
1124