blob: b2341f8c14210b0a9b88724e99f68d1f25b2504e [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2010 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.tests.compiler.smap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeMap;
import junit.framework.TestCase;
/** Tests the Method which generates the Smap for Baseclasse.
* @author ike
*/
public class BaseClassSmapGenerationMethodTest extends TestCase
{
public void testMethod001()
{
String baseClassFileName = "SimpleClass$1" ;
String baseClassSourceUnit = "path/to/SimpleClass";
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("path/to/TeamA.java", lineMappings);
int baseMapping [][] = null;
String expectedString =
"SMAP" + "\n" +
"SimpleClass$1.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"+ 1 TeamA.java" + "\n" +
"path/to/TeamA.java" + "\n" +
"+ 2 SimpleClass.java" + "\n" +
"path/to/SimpleClass.java" + "\n" +
"*L" + "\n" +
"1#2:1" + "\n" +
"2#1,2:7" + "\n" +
"3#1:8" + "\n" +
"*E"
;
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testMethod002()
{
String baseClassFileName = "SimpleClass$1" ;
String baseClassSourceUnit = "SimpleClass";
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("TeamA.java", lineMappings);
int baseMapping [][] = null;
String expectedString =
"SMAP" + "\n" +
"SimpleClass$1.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"1 TeamA.java" + "\n" +
"2 SimpleClass.java" + "\n" +
"*L" + "\n" +
"1#2:1" + "\n" +
"2#1,2:7" + "\n" +
"3#1:8" + "\n" +
"*E";
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testMethod003()
{
String baseClassFileName = "SimpleClass$1" ;
String baseClassSourceUnit = "SimpleClass";
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();
int baseMapping [][] = null;
String expectedString =
"SMAP" + "\n" +
"SimpleClass$1.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"1 SimpleClass.java" + "\n" +
"*L" + "\n" +
"1#1,3:1" + "\n" +
"*E";
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testMethod004()
{
String baseClassFileName = "BaseClass" ;
String baseClassSourceUnit = "very/very/long/path/to/BaseClass";
int endlineNumber = 50;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();
int lineMappings1[][] = new int[7][3];
lineMappings1[0] = new int[]{7,0,10};
lineMappings1[1] = new int[]{14,1,25};
lineMappings1[2] = new int[]{21,0,30};
lineMappings1[3] = new int[]{28,2,35};
lineMappings1[4] = new int[]{35,0,40};
lineMappings1[5] = new int[]{42,3,45};
lineMappings1[6] = new int[]{125,0,250};
mappings.put("path/to/TeamB.java", lineMappings1);
int lineMappings2[][] = new int[4][3];
lineMappings2[0] = new int[]{8,0,3};
lineMappings2[1] = new int[]{16,1,9};
lineMappings2[2] = new int[]{24,0,12};
lineMappings2[3] = new int[]{32,5,15};
mappings.put("very/long/path/to/TeamA.java", lineMappings1);
int baseMapping [][] = null;
String expectedString =
"SMAP" + "\n" +
"BaseClass.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"+ 1 TeamA.java" + "\n" +
"very/long/path/to/TeamA.java" + "\n" +
"+ 2 TeamB.java" + "\n" +
"path/to/TeamB.java" + "\n" +
"+ 3 BaseClass.java" + "\n" +
"very/very/long/path/to/BaseClass.java" + "\n" +
"*L" + "\n" +
"1#3,6:1" + "\n" +
"7#2:10" + "\n" +
"8#3,6:8" + "\n" +
"14#2,1:25" + "\n" +
"15#3,6:15" + "\n" +
"21#2:30" + "\n" +
"22#3,6:22" + "\n" +
"28#2,2:35" + "\n" +
"29#3,6:29" + "\n" +
"35#2:40" + "\n" +
"36#3,6:36" + "\n" +
"42#2,3:45" + "\n" +
"43#3,8:43" + "\n" +
"125#2:250" + "\n" +
"*E";
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testSMAPIsNull001()
{
String baseClassFileName = "SimpleClass$1" ;
String baseClassSourceUnit = "path/to/SimpleClass";
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = null;
int baseMapping [][] = null;
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
assertNull("No SMAP should be generated.", actual);
}
public void testSMAPIsNull002()
{
String baseClassFileName = null;
String baseClassSourceUnit = "path/to/SimpleClass";
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();;
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("path/to/TeamA.java", lineMappings);
int baseMapping[][] = null;
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
assertNull("No SMAP should be generated.", actual);
}
public void testSMAPIsNotNull001()
{
String baseClassFileName = "SimpleClass$1";
String baseClassSourceUnit = null;
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();;
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("path/to/TeamA.java", lineMappings);
int baseMapping[][] = null;
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String expectedString =
"SMAP" + "\n" +
"SimpleClass$1.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"+ 1 TeamA.java" + "\n" +
"path/to/TeamA.java" + "\n" +
"2 SimpleClass$1.java" + "\n" +
"*L" + "\n" +
"1#2:1" + "\n" +
"2#1,2:7" + "\n" +
"3#1:8" + "\n" +
"*E";
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testSMAPIsNotNull002()
{
String baseClassFileName = "pkg.subpkg.SimpleClass$1";
String baseClassSourceUnit = null;
int endlineNumber = 3;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();;
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("path/to/TeamA.java", lineMappings);
int baseMapping [][] = null;
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String expectedString =
"SMAP" + "\n" +
"SimpleClass$1.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"+ 1 TeamA.java" + "\n" +
"path/to/TeamA.java" + "\n" +
"+ 2 SimpleClass$1.java" + "\n" +
"pkg/subpkg/SimpleClass$1.java" + "\n" +
"*L" + "\n" +
"1#2:1" + "\n" +
"2#1,2:7" + "\n" +
"3#1:8" + "\n" +
"*E";
String actualString = new String(actual);
assertEquals("SMAP should be equal.", expectedString, actualString);
}
public void testSMAPBaseMappings()
{
String baseClassFileName = "path.to.SimpleClass";
String baseClassSourceUnit = "path/to/SimpleClass";
int endlineNumber = 15;
Hashtable<String, int[][]> mappings = new Hashtable<String, int[][]>();;
int lineMappings[][] = new int[2][3];
lineMappings[0] = new int[]{2,2,7};
lineMappings[1] = new int[]{3,0,8};
mappings.put("path/to/TeamA.java", lineMappings);
int baseMapping[][] = new int[2][2];
baseMapping[0] = new int[]{10,1};
baseMapping[1] = new int[]{12,6};
byte actual[] = generateSMAP(baseClassFileName, baseClassSourceUnit, endlineNumber, mappings, baseMapping);
String actualString = new String(actual);
String expectedString =
"SMAP" + "\n" +
"SimpleClass.class" + "\n" +
"OTJ" + "\n" +
"*S OTJ" + "\n" +
"*F" + "\n" +
"+ 1 TeamA.java" + "\n" +
"path/to/TeamA.java" + "\n" +
"+ 2 SimpleClass.java" + "\n" +
"path/to/SimpleClass.java" + "\n" +
"*L" + "\n" +
"1#2:1" + "\n" +
"2#1,2:7" + "\n" +
"3#1:8" + "\n" +
"4#2,6:4" + "\n" +
"10#2:1" + "\n" +
"11#2:11" + "\n" +
"12#2:6" + "\n" +
"13#2,3:13" + "\n" +
"*E";
assertEquals("SMAP should be equal.", expectedString, actualString);
}
///////////////////////////////////////////////////////////////////////////////////////
//// THIS METHOD IS TESTED ////
///////////////////////////////////////////////////////////////////////////////////////
/** This method generates a SMAP for Baseclasses. This SMAP maps generated code for
* callin bindings to theirs corresponding sourcecodepresentation.
*
* @param baseClassfileName - name of classfile this smap is generated for (e.g. pkg.subpkg.SimpleClass)
* @param baseSourceunitName - path of sourceunit of corresponding baseclasstype,
* (e.g path/to/SimpleClass);
* if baseSourceunitName is not available name and path are generated from
* baseClassfileName
*
* @param endlineNumber - this linenumber is the maximum linenumber of all entries in linenumbertables of all methods;
* it is not the endlinenumber of sourcefile.
* @param mappings -
* String -> int[][]<br>
* key: path of Team or RoleFile sourceunit which has callins"<br>
* value: int-array with:<br> int[0][0] - inputstartline of callin<br>
* int[0][1] - offset, if callin has more as one line(0 means one line, 1 means 2 lines, ...)<br>
* int[0][2] - written linenumber in baseclasscode (linenumber of _OT$MyRole$roleMethod$baseMethod() call in chainMethod)<br>
* e.g.<br>
* path/to/Teamname.java -> <br>[9][0][16]<br> [20][2][18]
*
* @param baseMappings - contains mappings to itself (int[][]):<br>
* int[0][0] - generated linenumber<br>
* int[0][1] - fixed linenumber (linenumber of e.g. signature of "_OT$xyz$orig(..)")
*
* @return smap - the string which should be stored in Classfileattribute SourceDebugExtension
*
* @author ike
*/
public byte[] generateSMAP(String baseClassfileName, String baseSourceunitName, int endlineNumber, Hashtable<String, int[][]> mappings, int baseMappings [][])
{
if (baseClassfileName==null || mappings==null)
{
return null;
}
String OTJ_STRATUM_NAME = "OTJ";
String CLASS_ENDING = ".class";
String JAVA_ENDING = ".java";
String generatedFileName = new String();
String components[] = baseClassfileName.split("\\.");
String newBaseSourceunitName = null;
String absoluteBaseSourceunitName = null;
boolean baseSourceunitNameAvailable = (baseSourceunitName != null);
if (components.length > 1)
{
generatedFileName = components[components.length -1] + CLASS_ENDING;
newBaseSourceunitName = components[components.length -1] + JAVA_ENDING;
absoluteBaseSourceunitName = (baseClassfileName.replaceAll("\\.", "/") + JAVA_ENDING);
}
else
{
generatedFileName = baseClassfileName + CLASS_ENDING;
newBaseSourceunitName = baseClassfileName + JAVA_ENDING;
absoluteBaseSourceunitName = null;
}
if (baseSourceunitNameAvailable)
{
String tmp[] = baseSourceunitName.split("/");
int index = tmp.length;
newBaseSourceunitName = tmp[index-1] + JAVA_ENDING;
if (tmp.length > 1)
{
absoluteBaseSourceunitName = baseSourceunitName + JAVA_ENDING;
}
}
Hashtable<String, Integer> typeNameToFileId = new Hashtable<String, Integer>();
int fileSectionIdCounter = 1;
StringBuffer out = new StringBuffer();
// print Header
out.append("SMAP\n");
out.append(generatedFileName + "\n");
// print strata
out.append(OTJ_STRATUM_NAME+ "\n");
// begin StratumSection
out.append("*S " + OTJ_STRATUM_NAME + "\n");
// print FileSection
out.append("*F" + "\n");
for (Iterator<String> iter = mappings.keySet().iterator(); iter.hasNext();)
{
String fullqualifiedName = iter.next();
typeNameToFileId.put(fullqualifiedName, new Integer(fileSectionIdCounter));
// extract filename and absoluteFileName from typename
String tmp[] = fullqualifiedName.split("/");
int index = tmp.length;
String fileName = tmp[index-1];
String absoluteFileName = null;
typeNameToFileId.put(fileName, new Integer(fileSectionIdCounter));
if (tmp.length >= 2)
{
absoluteFileName = fullqualifiedName;
}
if (absoluteFileName != null)
{
out.append("+ " );
}
out.append(fileSectionIdCounter + " " + fileName + "\n");
if (absoluteFileName != null)
{
out.append(absoluteFileName + "\n");
}
fileSectionIdCounter++;
}
// add basename to smap
int baseClassFileId = -1;
typeNameToFileId.put(newBaseSourceunitName, new Integer(fileSectionIdCounter));
baseClassFileId = typeNameToFileId.get(newBaseSourceunitName).intValue();
if (absoluteBaseSourceunitName != null)
{
out.append("+ " );
}
out.append(baseClassFileId + " " + newBaseSourceunitName + "\n");
if (absoluteBaseSourceunitName != null)
{
out.append(absoluteBaseSourceunitName + "\n");
}
// print LineSection
out.append("*L" + "\n");
TreeMap<Integer, String> lineInfos = new TreeMap<Integer, String>();
StringBuffer lineBuffer = new StringBuffer();
for (Iterator<String> iter = mappings.keySet().iterator(); iter.hasNext();)
{
String typeName = iter.next();
int[][] linemappings = mappings.get(typeName);
int fileId = typeNameToFileId.get(typeName).intValue();
for (int idx = 0; idx < linemappings.length; idx++)
{
int[] singleLineMapping = linemappings[idx];
Integer inputStartLine = new Integer( singleLineMapping[0]);
int inputOffset = singleLineMapping[1];
int outputLine = singleLineMapping[2];
if (inputOffset == 0)
{
lineBuffer.append(inputStartLine.intValue());
lineBuffer.append("#" + fileId);
lineBuffer.append(":" + outputLine + "\n");
}
else
{
lineBuffer.append(inputStartLine.intValue());
lineBuffer.append("#" + fileId);
lineBuffer.append("," + inputOffset);
lineBuffer.append(":" + outputLine + "\n");
}
lineInfos.put(inputStartLine, lineBuffer.toString());
lineBuffer.delete(0, lineBuffer.length());
}
}
//add given mappings to itself (basemappings)
if (baseMappings != null && baseMappings.length > 0)
{
for (int idx = 0; idx < baseMappings.length; idx++)
{
int key = baseMappings[idx][0];
int value = baseMappings[idx][1];
lineBuffer.append(key);
lineBuffer.append("#" + baseClassFileId);
lineBuffer.append(":" + value + "\n");
lineInfos.put(new Integer(key), lineBuffer.toString());
lineBuffer.delete(0, lineBuffer.length());
}
}
//add mappings to itself,
//endlinenumber is the maximum linenumber of all entries in linenumbertables of all methods;
//endlinenumber is not the endlinenumber of sourcefile, cause it is available at this time
TreeMap<Integer, int[]> baseToBaselineInfos = new TreeMap<Integer, int[]>();
for (int idx = 1; idx <= endlineNumber; idx++)
{
Integer currentLineNumber = new Integer(idx);
if (!lineInfos.containsKey(currentLineNumber))
{
Integer previousLineNumber = currentLineNumber-1;
if (baseToBaselineInfos.containsKey(previousLineNumber))
{
int[] oldValues = baseToBaselineInfos.get(previousLineNumber);
int intputStartline = oldValues[0];
int repeatCount= oldValues[1]+1;
int newValues[] = {intputStartline, repeatCount};
baseToBaselineInfos.put(currentLineNumber, newValues);
}
else
{
baseToBaselineInfos.put(currentLineNumber, new int[]{currentLineNumber.intValue(), 1});
}
}
}
lineBuffer = new StringBuffer();
for (Iterator<Integer> iter = baseToBaselineInfos.keySet().iterator(); iter.hasNext();)
{
Integer key= iter.next();
int[] endValues = baseToBaselineInfos.get(key);
int inputStartLine = endValues[0];
int repeatCount = endValues[1];
lineBuffer.append(inputStartLine);
lineBuffer.append("#" + baseClassFileId);
if (repeatCount > 1)
lineBuffer.append("," + repeatCount);
lineBuffer.append(":" + inputStartLine + "\n");
lineInfos.put(new Integer(inputStartLine), lineBuffer.toString());
lineBuffer.delete(0, lineBuffer.length());
}
for (Iterator<Integer> iter = lineInfos.keySet().iterator(); iter.hasNext();)
{
Integer inputStartline= iter.next();
String lineInfo = lineInfos.get(inputStartline);
out.append(lineInfo);
}
// print EndStratumSection
out.append("*E");
return out.toString().getBytes();
}
}