diff --git a/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java b/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java index 244adcd..9f22d79 100644 --- a/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java +++ b/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java @@ -19,7 +19,7 @@ public CollaborationAliasCollector(IAliasCollector dac) { aliasList.addAll(dac.getAliasList()); - aliasList = sort(aliasList); + aliasList = sortAliasListByTimeStamp(aliasList); } /* @@ -40,7 +40,7 @@ */ public void merge(IAliasCollector other) { List otherAliasList = other.getAliasList(); - otherAliasList = sort(otherAliasList); + otherAliasList = sortAliasListByTimeStamp(otherAliasList); int otherIdx = 0; // Index of otherAliasList int thisIdx = 0; // Index of thisAliasList while(otherIdx < otherAliasList.size()) { @@ -81,7 +81,7 @@ * @param aliasList AliasList to sort. * @return Sorted AliasList. */ - private List sort(List aliasList) { + private List sortAliasListByTimeStamp(List aliasList) { List cloneAliasList = new ArrayList<>(aliasList); List sortedAliasList = cloneAliasList.stream().sorted(new Comparator() { @Override diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index 1a64cb4..ed4bc60 100644 --- a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java @@ -1,56 +1,125 @@ package org.ntlab.deltaViewer; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.ntlab.deltaExtractor.ExtractedStructure; import org.ntlab.trace.MethodExecution; import org.ntlab.trace.Reference; import org.ntlab.trace.TracePoint; +/** + * CollaborationObjectCallGraph is IObjectCallGraph implementation class to merge ExtractedStructure. + * + * @author Nitta Lab. + */ public class CollaborationObjectCallGraph implements IObjectCallGraph { - private List references = new ArrayList<>(); - private List startPoints = new ArrayList<>(); + private Set references = new HashSet<>(); + private List startPoints = new ArrayList<>(); // Common ancestor point private List relatedPoints = new ArrayList<>(); public CollaborationObjectCallGraph(ExtractedStructure e) { references.addAll(e.getDelta().getSrcSide()); references.addAll(e.getDelta().getDstSide()); startPoints.add(e.getCoordinator()); - relatedPoints.add(e.getRelatedTracePoint()); + relatedPoints.add(e.getRelatedTracePoint().duplicate()); } @Override public List getReferences() { - // TODO Auto-generated method stub - return references; + return new ArrayList(references); // Convert to List from Set. } @Override public List getStartPoints() { - // TODO Auto-generated method stub return startPoints; } @Override public List getRelatedPoints() { - // TODO Auto-generated method stub return relatedPoints; } @Override public Map> getCallTree() { - // TODO Auto-generated method stub return null; } + /** + * Merge ExtractedStructure not to overlap reference. + * @param e ExtractedStructure to be merged into the field. + */ public void merge(ExtractedStructure e) { references.addAll(e.getDelta().getSrcSide()); references.addAll(e.getDelta().getDstSide()); - // lowest common ancestor algorithm -// startPoints.add(e.getCoordinator()); - relatedPoints.add(e.getRelatedTracePoint()); // ���ԏ��ɂ���̂� + + // There may be bug. (Two object has each coordinator like JHotDraw Transform) + MethodExecution thisStartPoint = startPoints.get(0); + MethodExecution tmp = thisStartPoint; + MethodExecution thisRoot = thisStartPoint.getParent(); + MethodExecution otherStartPoint = e.getCoordinator(); + while(thisRoot != null) { // Get Root of thisStartPoint. + tmp = tmp.getParent(); + thisRoot = tmp.getParent(); + } + thisRoot = tmp; + /* lowest common ancestor algorithm */ + MethodExecution lca = lowestCommonAncestor(thisRoot, thisStartPoint, otherStartPoint); + startPoints.clear(); + startPoints.add(lca); + + // Is it in time stamp order? + TracePoint otherRelatedTp = e.getRelatedTracePoint().duplicate(); + relatedPoints.add(otherRelatedTp); + relatedPoints = sortTracePointByTimeStamp(relatedPoints); } - + + /** + * Search lowest common ancestor(lca) of p and q. + * @param root + * @param p + * @param q + * @return Lca methodExecution. + */ + public MethodExecution lowestCommonAncestor(MethodExecution root, MethodExecution p, MethodExecution q) { + if(root == null || root == p || root == q) return root; + Set pRoots = new HashSet<>(); + MethodExecution pTmp = p; + while (!root.equals(pTmp) && pTmp != null) { + pRoots.add(pTmp); + pTmp = pTmp.getParent(); + } + pRoots.add(root); + MethodExecution qTmp = q; + while (!root.equals(qTmp) && qTmp != null) { + if (pRoots.contains(qTmp)) return qTmp; + qTmp = qTmp.getParent(); + } + return root; + } + + /** + * Sort tracePoint in time stamp order. + * @param tpList TracePoint List to sort. + * @return Sorted TracePoint List. + */ + private List sortTracePointByTimeStamp(List tpList) { + List cloneTpList = new ArrayList<>(tpList); + List sortedTpList = cloneTpList.stream().sorted(new Comparator() { + @Override + public int compare(TracePoint tp1, TracePoint tp2) { + long tp1TimeStamp = tp1.getStatement().getTimeStamp(); + long tp2TimeStamp = tp2.getStatement().getTimeStamp(); + if (tp1TimeStamp > tp2TimeStamp) return 1; + else if (tp1TimeStamp < tp2TimeStamp) return -1; + return 0; + } + }).collect(Collectors.toList()); + return sortedTpList; + } } diff --git a/src/tests/CollaborationAliasCollectorTest.java b/src/tests/CollaborationAliasCollectorTest.java index 213931f..88f4307 100644 --- a/src/tests/CollaborationAliasCollectorTest.java +++ b/src/tests/CollaborationAliasCollectorTest.java @@ -3,82 +3,29 @@ import static org.junit.jupiter.api.Assertions.*; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import org.ntlab.deltaExtractor.Alias; -import org.ntlab.deltaExtractor.DeltaExtractorJSON; import org.ntlab.deltaExtractor.ExtractedStructure; import org.ntlab.deltaExtractor.IAliasCollector; -import org.ntlab.deltaExtractor.IAliasTracker; import org.ntlab.deltaViewer.CollaborationAliasCollector; -import org.ntlab.deltaViewer.DeltaAliasCollector; -import org.ntlab.trace.Reference; -import org.ntlab.trace.ThreadInstance; -import org.ntlab.trace.TraceJSON; -import org.ntlab.trace.TracePoint; class CollaborationAliasCollectorTest { - // Delta Extract Type - protected static final String CONTAINER_COMPONENT = "Container-Component"; - protected static final String CONTAINER_COMPONENT_COLLECTION = "Container-Component(Collection)"; @Test void testMerge() { - Map argsMap = new HashMap<>(); - setArgmentsForDeltaExtract(argsMap); - Map> argsKeysMap = new HashMap<>(); - setArgsKeysForPluralDeltaExtract(argsKeysMap, argsMap); // Change Here! // String key = "getterOverlap"; String key = "setterOverlap"; - List argsKeys = argsKeysMap.get(key); - List eList = new ArrayList<>(); - List dacList = new ArrayList<>(); - TraceJSON trace = new TraceJSON(argsMap.get(argsKeys.get(0))[4]); - DeltaExtractorJSON s = new DeltaExtractorJSON(trace); - - for (String argsKey: argsKeys) { - if (argsMap.get(argsKey)[5] == CONTAINER_COMPONENT || argsMap.get(argsKey)[5] == CONTAINER_COMPONENT_COLLECTION) { - HashMap threads = trace.getAllThreads(); - - if (threads.values().size() == 1) { - ThreadInstance thread = threads.values().iterator().next(); // �Ō�̃X���b�h�����Ă��邾���c - TracePoint tp = thread.getRoot().get(thread.getRoot().size() - 1).getExitPoint(); - Reference reference = new Reference(argsMap.get(argsKey)[0], argsMap.get(argsKey)[1], argsMap.get(argsKey)[2], argsMap.get(argsKey)[3]); - IAliasTracker dac = new DeltaAliasCollector(); - ExtractedStructure e = s.extract(reference, tp, dac); - eList.add(e); - dacList.add(dac); - } else { - for (ThreadInstance thread: threads.values()) { - TracePoint tp = thread.getRoot().get(thread.getRoot().size() - 1).getExitPoint(); - Reference reference = new Reference(argsMap.get(argsKey)[0], argsMap.get(argsKey)[1], argsMap.get(argsKey)[2], argsMap.get(argsKey)[3]); - if (argsMap.get(argsKey)[5] == CONTAINER_COMPONENT_COLLECTION) { - reference.setCollection(true); - } -// reference.setArray(true); -// reference.setFinalLocal(true); -// reference.setCreation(true); - IAliasTracker dac = new DeltaAliasCollector(); - ExtractedStructure e = s.extract(reference, tp, dac); - System.out.println(e); - if (e != null) { - eList.add(e); - dacList.add(dac); - System.out.println("add" + eList.size() + ", " + dacList.size()); - } - System.out.println("---------------------------"); - } - } - } - } + MagnetRONFrameTest magnetRONFrame = new MagnetRONFrameTest(); + Map extractedPluralDelta = magnetRONFrame.extractPluralDelta(key); + List eList = new ArrayList<>(extractedPluralDelta.keySet()); + List dacList = new ArrayList<>(extractedPluralDelta.values()); CollaborationAliasCollector cac = null; for (IAliasCollector dac: dacList) { - if (cac == null ) { + if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { cac.merge(dac); @@ -92,19 +39,4 @@ assertTrue(cac.getAliasList().contains(dac.getAliasList().get(0))); } } - - private void setArgmentsForDeltaExtract(Map map){ - // Samples of Plural Delta - String[] getterOverlap1 = {null, null, "getterOverlap.F","getterOverlap.D", "traces/getterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("getterOverlap1", getterOverlap1); - String[] getterOverlap2 = {null, null, "getterOverlap.G","getterOverlap.D", "traces/getterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("getterOverlap2", getterOverlap2); - String[] setterOverlap1 = {null, null, "setterOverlap.F","setterOverlap.C", "traces/setterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("setterOverlap1", setterOverlap1); - String[] setterOverlap2 = {null, null, "setterOverlap.G","setterOverlap.C", "traces/setterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("setterOverlap2", setterOverlap2); - } - - private void setArgsKeysForPluralDeltaExtract(Map> argsKeysMap, Map argsMap){ - // Samples of Plural Delta - argsKeysMap.put("getterOverlap", new ArrayList(Arrays.asList("getterOverlap1", "getterOverlap2"))); - argsKeysMap.put("setterOverlap", new ArrayList(Arrays.asList("setterOverlap1", "setterOverlap2"))); - } - } diff --git a/src/tests/CollaborationObjectCallGraphTest.java b/src/tests/CollaborationObjectCallGraphTest.java new file mode 100644 index 0000000..88e3c4b --- /dev/null +++ b/src/tests/CollaborationObjectCallGraphTest.java @@ -0,0 +1,95 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.ntlab.deltaExtractor.ExtractedStructure; +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.deltaViewer.CollaborationObjectCallGraph; +import org.ntlab.trace.FieldUpdate; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.Reference; +import org.ntlab.trace.Statement; +import org.ntlab.trace.TracePoint; + +class CollaborationObjectCallGraphTest { + + @Test + void testMerge() { + // Change Here! +// String key = "getterOverlap"; + String key = "setterOverlap"; + MagnetRONFrameTest magnetRONFrame = new MagnetRONFrameTest(); + Map extractedPluralDelta = magnetRONFrame.extractPluralDelta(key); + List eList = new ArrayList<>(extractedPluralDelta.keySet()); + List dacList = new ArrayList<>(extractedPluralDelta.values()); + + CollaborationObjectCallGraph cocg = null; + for (ExtractedStructure e: eList) { + if (cocg == null) { + cocg = new CollaborationObjectCallGraph(e); + } else { + cocg.merge(e); + } + } + System.out.println("References:"); + for (Reference ref: cocg.getReferences()) { + System.out.println("\t" + ref.getSrcClassName() + "(" + ref.getSrcObjectId() + ")" + " -> " + ref.getDstClassName() + "(" + ref.getDstObjectId() + ")"); + } + System.out.println("StartPoints:"); + for (MethodExecution methodExec: cocg.getStartPoints()) { + System.out.println("\t" + methodExec.getSignature()); + } + System.out.println("RelatedPoints:"); + for (TracePoint tp: cocg.getRelatedPoints()) { + Statement statement = tp.getStatement(); + if(statement instanceof FieldUpdate) { + FieldUpdate fieldUpdateStatement = (FieldUpdate) statement; + String fieldName = fieldUpdateStatement.getFieldName(); + String srcObjId = fieldUpdateStatement.getContainerObjId(); + String tgtObjId = fieldUpdateStatement.getValueObjId(); + System.out.println(tgtObjId + " <-- " + fieldName + " -- " + srcObjId); + } + + if(statement instanceof MethodInvocation) { + MethodInvocation methodInvStatement = (MethodInvocation) statement; + MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution(); + String methodSignature = calledMethodExec.getSignature(); + String srcClassName = null; + String srcObjId = null; + String tgtObjId = null; + + if (calledMethodExec.isCollectionType() + && (methodSignature.contains("add(") + || methodSignature.contains("set(") + || methodSignature.contains("put(") + || methodSignature.contains("push(") + || methodSignature.contains("addElement("))) { + + srcClassName = calledMethodExec.getThisClassName(); + srcObjId = calledMethodExec.getThisObjId(); + tgtObjId = calledMethodExec.getArguments().get(0).getId(); + } else { + // this to another + srcClassName = methodInvStatement.getThisClassName(); + srcObjId = methodInvStatement.getThisObjId(); + tgtObjId = calledMethodExec.getReturnValue().getId(); + } + System.out.println(tgtObjId + " <-- " + srcClassName + " -- " + srcObjId); + } + } + assertNotNull(cocg); + for (ExtractedStructure e: eList) { + // TODO Test StartPoint. + assertTrue(cocg.getReferences().containsAll(e.getDelta().getSrcSide())); + assertTrue(cocg.getReferences().containsAll(e.getDelta().getDstSide())); + assertTrue(cocg.getRelatedPoints().contains(e.getRelatedTracePoint())); + + } + } +} diff --git a/src/tests/MagnetRONFrameTest.java b/src/tests/MagnetRONFrameTest.java new file mode 100644 index 0000000..96b8ef8 --- /dev/null +++ b/src/tests/MagnetRONFrameTest.java @@ -0,0 +1,105 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.ntlab.deltaExtractor.DeltaExtractorJSON; +import org.ntlab.deltaExtractor.ExtractedStructure; +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.deltaExtractor.IAliasTracker; +import org.ntlab.deltaViewer.DeltaAliasCollector; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.ObjectReference; +import org.ntlab.trace.Reference; +import org.ntlab.trace.ThreadInstance; +import org.ntlab.trace.TraceJSON; +import org.ntlab.trace.TracePoint; + +class MagnetRONFrameTest { + // Delta Extract Type + protected static final String CONTAINER_COMPONENT = "Container-Component"; + protected static final String CONTAINER_COMPONENT_COLLECTION = "Container-Component(Collection)"; + + + public MagnetRONFrameTest() { + } + + public Map extractPluralDelta(String key) { + Map extractedPluralDelta = new HashMap<>(); + Map argsMap = new HashMap<>(); + setArgmentsForDeltaExtract(argsMap); + Map> argsKeysMap = new HashMap<>(); + setArgsKeysForPluralDeltaExtract(argsKeysMap, argsMap); + List argsKeys = argsKeysMap.get(key); + TraceJSON trace = new TraceJSON(argsMap.get(argsKeys.get(0))[4]); + DeltaExtractorJSON s = new DeltaExtractorJSON(trace); + + for (String argsKey: argsKeys) { + List eList = new ArrayList<>(); + List dacList = new ArrayList<>(); + if (argsMap.get(argsKey)[5] == CONTAINER_COMPONENT || argsMap.get(argsKey)[5] == CONTAINER_COMPONENT_COLLECTION) { + HashMap threads = trace.getAllThreads(); + + if (threads.values().size() == 1) { + ThreadInstance thread = threads.values().iterator().next(); // �Ō�̃X���b�h�����Ă��邾���c + TracePoint tp = thread.getRoot().get(thread.getRoot().size() - 1).getExitPoint(); + Reference reference = new Reference(argsMap.get(argsKey)[0], argsMap.get(argsKey)[1], argsMap.get(argsKey)[2], argsMap.get(argsKey)[3]); + IAliasTracker dac = new DeltaAliasCollector(); + ExtractedStructure e = s.extract(reference, tp, dac); + eList.add(e); + dacList.add(dac); + } else { + for (ThreadInstance thread: threads.values()) { + TracePoint tp = thread.getRoot().get(thread.getRoot().size() - 1).getExitPoint(); + Reference reference = new Reference(argsMap.get(argsKey)[0], argsMap.get(argsKey)[1], argsMap.get(argsKey)[2], argsMap.get(argsKey)[3]); + if (argsMap.get(argsKey)[5] == CONTAINER_COMPONENT_COLLECTION) { + reference.setCollection(true); + } +// reference.setArray(true); +// reference.setFinalLocal(true); +// reference.setCreation(true); + IAliasTracker dac = new DeltaAliasCollector(); + ExtractedStructure e = s.extract(reference, tp, dac); + System.out.println(e); + if (e != null) { + eList.add(e); + dacList.add(dac); + System.out.println("add" + eList.size() + ", " + dacList.size()); + } + System.out.println("---------------------------"); + } + } + } else { + IAliasTracker dac = new DeltaAliasCollector(); + MethodExecution me = trace.getLastMethodExecution(argsMap.get(argsKey)[2]); + Map refs = me.getObjectReferences(argsMap.get(argsKey)[3]); + ObjectReference ref = refs.keySet().iterator().next(); + ExtractedStructure e = s.extract(refs.get(ref), ref, dac); + eList.add(e); + dacList.add(dac); + } + extractedPluralDelta.put(eList.get(0), dacList.get(0)); + } + return extractedPluralDelta; + } + + private void setArgmentsForDeltaExtract(Map map){ + // Samples of Plural Delta + String[] getterOverlap1 = {null, null, "getterOverlap.F","getterOverlap.D", "traces/getterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("getterOverlap1", getterOverlap1); + String[] getterOverlap2 = {null, null, "getterOverlap.G","getterOverlap.D", "traces/getterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("getterOverlap2", getterOverlap2); + String[] setterOverlap1 = {null, null, "setterOverlap.F","setterOverlap.C", "traces/setterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("setterOverlap1", setterOverlap1); + String[] setterOverlap2 = {null, null, "setterOverlap.G","setterOverlap.C", "traces/setterOverlap.txt", CONTAINER_COMPONENT_COLLECTION}; map.put("setterOverlap2", setterOverlap2); + } + + private void setArgsKeysForPluralDeltaExtract(Map> argsKeysMap, Map argsMap){ + // Samples of Plural Delta + argsKeysMap.put("getterOverlap", new ArrayList(Arrays.asList("getterOverlap1", "getterOverlap2"))); + argsKeysMap.put("setterOverlap", new ArrayList(Arrays.asList("setterOverlap1", "setterOverlap2"))); + } +}