Skip to content

Commit

Permalink
Fix for issue #790 + Add test
Browse files Browse the repository at this point in the history
  • Loading branch information
tsantalis committed Oct 19, 2024
1 parent 99ee636 commit f150318
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import static gr.uom.java.xmi.decomposition.ReplacementAlgorithm.streamAPIName;
import static gr.uom.java.xmi.decomposition.StringBasedHeuristics.*;
import static gr.uom.java.xmi.decomposition.Visitor.stringify;
import static gr.uom.java.xmi.diff.UMLClassBaseDiff.getParameterValues;
import static gr.uom.java.xmi.diff.UMLClassBaseDiff.matchParamsWithReplacements;

import gr.uom.java.xmi.decomposition.replacement.CompositeReplacement;
import gr.uom.java.xmi.decomposition.replacement.IntersectionReplacement;
Expand Down Expand Up @@ -113,6 +115,7 @@ public class UMLOperationBodyMapper implements Comparable<UMLOperationBodyMapper
private Set<VariableDeclaration> addedVariables;
private Set<Pair<VariableDeclaration, VariableDeclaration>> movedVariables;
private int callsToExtractedMethod = 0;
private List<Set<AbstractCodeMapping>> internalParameterizeTestMultiMappings = new ArrayList<Set<AbstractCodeMapping>>();
private boolean nested;
private boolean lambdaBodyMapper;
private AbstractCall operationInvocation;
Expand Down Expand Up @@ -3726,6 +3729,50 @@ public Set<Replacement> getReplacements() {
return replacements;
}

public List<Set<AbstractCodeMapping>> getInternalParameterizeTestMultiMappings() {
return internalParameterizeTestMultiMappings;
}

public int countMappingsForInternalParameterizedTest() {
if(this.internalParameterizeTestMultiMappings.size() > 0) {
int count = 0;
Set<AbstractCodeMapping> processedMappings = new LinkedHashSet<AbstractCodeMapping>();
for(Set<AbstractCodeMapping> set : internalParameterizeTestMultiMappings) {
count++;
processedMappings.addAll(set);
}
for(AbstractCodeMapping mapping : getMappings()) {
if(!processedMappings.contains(mapping)) {
count++;
}
}
return count;
}
return getMappings().size();
}

public int countReplacementsForInternalParameterizedTest() {
if(this.internalParameterizeTestMultiMappings.size() > 0) {
int count = 0;
Set<AbstractCodeMapping> processedMappings = new LinkedHashSet<AbstractCodeMapping>();
for(Set<AbstractCodeMapping> set : internalParameterizeTestMultiMappings) {
int localCount = 0;
for(AbstractCodeMapping mapping : set) {
localCount += mapping.getReplacements().size();
}
count += localCount/set.size();
processedMappings.addAll(set);
}
for(AbstractCodeMapping mapping : getMappings()) {
if(!processedMappings.contains(mapping)) {
count += mapping.getReplacements().size();
}
}
return count;
}
return getReplacements().size();
}

public Set<Replacement> getReplacementsOfType(ReplacementType type) {
Set<Replacement> replacements = new LinkedHashSet<Replacement>();
for(AbstractCodeMapping mapping : getMappings()) {
Expand Down Expand Up @@ -6247,6 +6294,16 @@ else if((catchBlockMap = allMappingsNestedUnderCatchBlocks(mappingSet)) != null)
leafIterator2.remove();
checkForMatchingMergedVariableDeclaration(leaf2, leaves1, parameterToArgumentMap, equalNumberOfAssertions);
}
else if(internalParameterizeTest(mappingSet) && mappingSet.size() > 1) {
Set<AbstractCodeMapping> multiMappings = new LinkedHashSet<AbstractCodeMapping>();
for(AbstractCodeMapping mapping : mappingSet) {
multiMappings.add(mapping);
addToMappings((LeafMapping) mapping, mappingSet);
leaves1.remove(mapping.getFragment1());
}
this.internalParameterizeTestMultiMappings.add(multiMappings);
leafIterator2.remove();
}
else {
if(!duplicateMappingInParentMapper(mappingSet)) {
AbstractCodeMapping alreadyMatched = null;
Expand Down Expand Up @@ -6331,6 +6388,23 @@ else if(existingMappingWithCommonParents(variableDeclarationMapping)) {
}
}

private boolean internalParameterizeTest(Set<LeafMapping> mappingSet) {
if(container2.hasParameterizedTestAnnotation() && !container1.hasParameterizedTestAnnotation()) {
List<String> parameterNames = container2.getParameterNameList();
List<List<String>> parameterValues = getParameterValues((UMLOperation)container2, modelDiff);
Set<Replacement> replacements = new LinkedHashSet<Replacement>();
for(AbstractCodeMapping mapping : mappingSet) {
replacements.addAll(mapping.getReplacements());
}
Map<Integer, Integer> matchingTestParameters = matchParamsWithReplacements(parameterValues, parameterNames, replacements);
int max = matchingTestParameters.isEmpty() ? 0 : Collections.max(matchingTestParameters.values());
if(max >= 1) {
return true;
}
}
return false;
}

private boolean nestedDirectlyUnderMethodBody(AbstractCodeMapping mapping) {
AbstractCodeFragment f1 = mapping.getFragment1();
AbstractCodeFragment f2 = mapping.getFragment2();
Expand Down
26 changes: 20 additions & 6 deletions src/main/java/gr/uom/java/xmi/diff/UMLClassBaseDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -1310,10 +1310,15 @@ else if(removedOperation.hasTestAnnotation() && addedOperation.hasParameterizedT
if(!matchingMergeCandidateFound && !matchingSplitCandidateFound) {
if(addedOperation.hasParameterizedTestAnnotation() && !firstMapper.getContainer1().hasParameterizedTestAnnotation()) {
Set<UMLOperationBodyMapper> filteredMapperSet = new LinkedHashSet<UMLOperationBodyMapper>();
List<List<String>> parameterValues = getParameterValues(addedOperation);
List<List<String>> parameterValues = getParameterValues(addedOperation, modelDiff);
List<String> parameterNames = addedOperation.getParameterNameList();
int overallMaxMatchingTestParameters = -1;
Map<Integer, Integer> overallMatchingTestParameters = new LinkedHashMap<Integer, Integer>();
boolean internalParameterizeTest = false;
for(UMLOperationBodyMapper mapper : mapperSet) {
if(mapper.getInternalParameterizeTestMultiMappings().size() > 0) {
internalParameterizeTest = true;
}
Map<Integer, Integer> matchingTestParameters = matchParamsWithReplacements(parameterValues, parameterNames, mapper.getReplacements());
if (matchingTestParameters.isEmpty()) {
matchingTestParameters = matchParamsWithRemovedStatements(parameterValues, parameterNames, mapper.getNonMappedLeavesT1());
Expand All @@ -1323,19 +1328,28 @@ else if(removedOperation.hasTestAnnotation() && addedOperation.hasParameterizedT
if(max > overallMaxMatchingTestParameters) {
overallMaxMatchingTestParameters = max;
}
filteredMapperSet.add(mapper);
int sizeBefore = overallMatchingTestParameters.size();
overallMatchingTestParameters.putAll(matchingTestParameters);
if(internalParameterizeTest) {
if(overallMatchingTestParameters.size() > sizeBefore) {
filteredMapperSet.add(mapper);
}
}
else {
filteredMapperSet.add(mapper);
}
}
}
//cluster mappers based on number of mappings and number of total replacements
Set<UMLOperationBodyMapper> filteredMapperSet2 = new LinkedHashSet<UMLOperationBodyMapper>();
int maxMappings = -1;
int minReplacements = Integer.MAX_VALUE;
for(UMLOperationBodyMapper mapper : filteredMapperSet) {
int mappings = mapper.getMappings().size();
int mappings = mapper.countMappingsForInternalParameterizedTest();
if(mappings > maxMappings) {
maxMappings = mappings;
}
int replacements = mapper.getReplacements().size();
int replacements = mapper.countReplacementsForInternalParameterizedTest();
if(replacements < minReplacements) {
minReplacements = replacements;
}
Expand Down Expand Up @@ -1512,7 +1526,7 @@ private boolean isPerfectMapper(UMLOperationBodyMapper mapper) {
return mapper.getMappings().size() > 0 && nonMappedLeavesT1 <= 0 && nonMappedLeavesT2 <= 0 && nonMappedInnerNodesT1 == 0 && nonMappedInnerNodesT2 == 0;
}

private List<List<String>> getParameterValues(UMLOperation addedOperation) {
public static List<List<String>> getParameterValues(UMLOperation addedOperation, UMLModelDiff modelDiff) {
List<List<String>> parameterValues = new ArrayList<>();
for(UMLAnnotation annotation : addedOperation.getAnnotations()) {
try {
Expand Down Expand Up @@ -1545,7 +1559,7 @@ private Map<Integer, Integer> matchParamsWithRemovedStatements(List<List<String>
return matchingTestParameters;
}

private static Map<Integer, Integer> matchParamsWithReplacements(List<List<String>> testParameters, List<String> parameterNames, Set<Replacement> replacements) {
public static Map<Integer, Integer> matchParamsWithReplacements(List<List<String>> testParameters, List<String> parameterNames, Set<Replacement> replacements) {
Map<Integer, Integer> matchingTestParameters = new LinkedHashMap<>();
for(Replacement r : replacements) {
if(parameterNames.contains(r.getAfter())) {
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/org/refactoringminer/test/TestStatementMappings.java
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,31 @@ public void testParameterizedTestMappings() throws Exception {
Assertions.assertTrue(expected.size() == actual.size() && expected.containsAll(actual) && actual.containsAll(expected));
}

@Test
public void testParameterizedTestMappings4() throws Exception {
final List<String> actual = new ArrayList<>();
Map<String, String> fileContentsBefore = new LinkedHashMap<String, String>();
Map<String, String> fileContentsCurrent = new LinkedHashMap<String, String>();
String contentsV1 = FileUtils.readFileToString(new File(EXPECTED_PATH + "FileNameCleanerTest-v1.txt"));
String contentsV2 = FileUtils.readFileToString(new File(EXPECTED_PATH + "FileNameCleanerTest-v2.txt"));
fileContentsBefore.put("src/test/java/org/jabref/logic/util/FileNameCleanerTest.java", contentsV1);
fileContentsCurrent.put("src/test/java/org/jabref/logic/util/FileNameCleanerTest.java", contentsV2);
UMLModel parentUMLModel = GitHistoryRefactoringMinerImpl.createModel(fileContentsBefore, new LinkedHashSet<String>());
UMLModel currentUMLModel = GitHistoryRefactoringMinerImpl.createModel(fileContentsCurrent, new LinkedHashSet<String>());

UMLModelDiff modelDiff = parentUMLModel.diff(currentUMLModel);
List<Refactoring> refactorings = modelDiff.getRefactorings();
for(Refactoring r : refactorings) {
if(r instanceof ParameterizeTestRefactoring) {
ParameterizeTestRefactoring parameterizeTest = (ParameterizeTestRefactoring)r;
UMLOperationBodyMapper mapper = parameterizeTest.getBodyMapper();
mapperInfo(mapper, actual);
}
}
List<String> expected = IOUtils.readLines(new FileReader(EXPECTED_PATH + "jabRef-FileNameCleanerTest.txt"));
Assertions.assertTrue(expected.size() == actual.size() && expected.containsAll(actual) && actual.containsAll(expected));
}

@ParameterizedTest
@CsvSource({
"https://github.com/apache/camel.git, b57b72d0e85f2340cb2d55be44d2175c0caa7cc1, camel-b57b72d0e85f2340cb2d55be44d2175c0caa7cc1.txt",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1874,6 +1874,31 @@ public void testParameterizedTestMappings() throws Exception {
Assert.assertTrue(expected.size() == actual.size() && expected.containsAll(actual) && actual.containsAll(expected));
}

@Test
public void testParameterizedTestMappings4() throws Exception {
final List<String> actual = new ArrayList<>();
Map<String, String> fileContentsBefore = new LinkedHashMap<String, String>();
Map<String, String> fileContentsCurrent = new LinkedHashMap<String, String>();
String contentsV1 = FileUtils.readFileToString(new File(EXPECTED_PATH + "FileNameCleanerTest-v1.txt"));
String contentsV2 = FileUtils.readFileToString(new File(EXPECTED_PATH + "FileNameCleanerTest-v2.txt"));
fileContentsBefore.put("src/test/java/org/jabref/logic/util/FileNameCleanerTest.java", contentsV1);
fileContentsCurrent.put("src/test/java/org/jabref/logic/util/FileNameCleanerTest.java", contentsV2);
UMLModel parentUMLModel = GitHistoryRefactoringMinerImpl.createModel(fileContentsBefore, new LinkedHashSet<String>());
UMLModel currentUMLModel = GitHistoryRefactoringMinerImpl.createModel(fileContentsCurrent, new LinkedHashSet<String>());

UMLModelDiff modelDiff = parentUMLModel.diff(currentUMLModel);
List<Refactoring> refactorings = modelDiff.getRefactorings();
for(Refactoring r : refactorings) {
if(r instanceof ParameterizeTestRefactoring) {
ParameterizeTestRefactoring parameterizeTest = (ParameterizeTestRefactoring)r;
UMLOperationBodyMapper mapper = parameterizeTest.getBodyMapper();
mapperInfo(mapper, actual);
}
}
List<String> expected = IOUtils.readLines(new FileReader(EXPECTED_PATH + "jabRef-FileNameCleanerTest.txt"));
Assert.assertTrue(expected.size() == actual.size() && expected.containsAll(actual) && actual.containsAll(expected));
}

@Test
public void testParameterizedTestMappings2() throws Exception {
GitHistoryRefactoringMinerImpl miner = new GitHistoryRefactoringMinerImpl();
Expand Down
36 changes: 36 additions & 0 deletions src/test/resources/mappings/FileNameCleanerTest-v1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.jabref.logic.util;

import org.jabref.logic.util.io.FileNameCleaner;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class FileNameCleanerTest {

@Test
void cleanFileName() {
assertEquals("legalFilename.txt", FileNameCleaner.cleanFileName("legalFilename.txt"));
assertEquals("illegalFilename______.txt", FileNameCleaner.cleanFileName("illegalFilename/?*<>|.txt"));
assertEquals("illegalFileName_.txt", FileNameCleaner.cleanFileName("illegalFileName{.txt"));
}

@Test
void cleanDirectoryName() {
assertEquals("legalFilename.txt", FileNameCleaner.cleanDirectoryName("legalFilename.txt"));
assertEquals("subdir/legalFilename.txt", FileNameCleaner.cleanDirectoryName("subdir/legalFilename.txt"));
assertEquals("illegalFilename/_____.txt", FileNameCleaner.cleanDirectoryName("illegalFilename/?*<>|.txt"));
}

@Test
void cleanDirectoryNameForWindows() {
assertEquals("legalFilename.txt", FileNameCleaner.cleanDirectoryName("legalFilename.txt"));
assertEquals("subdir\\legalFilename.txt", FileNameCleaner.cleanDirectoryName("subdir\\legalFilename.txt"));
assertEquals("illegalFilename\\_____.txt", FileNameCleaner.cleanDirectoryName("illegalFilename\\?*<>|.txt"));
}

@Test
void cleanCurlyBracesAsWell() {
assertEquals("The Evolution of Sentiment_ Analysis_A Review of Research Topics, Venues, and Top Cited Papers.PDF", FileNameCleaner.cleanFileName("The Evolution of Sentiment} Analysis}A Review of Research Topics, Venues, and Top Cited Papers.PDF"));
}
}
43 changes: 43 additions & 0 deletions src/test/resources/mappings/FileNameCleanerTest-v2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.jabref.logic.util;

import org.jabref.logic.util.io.FileNameCleaner;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

class FileNameCleanerTest {

@ParameterizedTest
@CsvSource({
"legalFilename.txt, legalFilename.txt",
"illegalFilename______.txt, illegalFilename/?*<>|.txt",
"illegalFileName_.txt, illegalFileName{.txt",
"_The Evolution of Sentiment_ Analysis_.PDF, ?The Evolution of Sentiment} Analysis}.PDF",
"'The Evolution of Sentiment_ Analysis_A Review of Research Topics, Venues, and Top Cited Papers.PDF', 'The Evolution of Sentiment} Analysis}A Review of Research Topics, Venues, and Top Cited Papers.PDF'"
})
void cleanFileName(String expected, String input) {
assertEquals(expected, FileNameCleaner.cleanFileName(input));
}

@ParameterizedTest
@CsvSource({
"legalFilename.txt, legalFilename.txt",
"subdir/legalFilename.txt, subdir/legalFilename.txt",
"illegalFilename/_____.txt, illegalFilename/?*<>|.txt"
})
void cleanDirectoryName(String expected, String input) {
assertEquals(expected, FileNameCleaner.cleanDirectoryName(input));
}

@ParameterizedTest
@CsvSource({
"legalFilename.txt, legalFilename.txt",
"subdir\\legalFilename.txt, subdir\\legalFilename.txt",
"illegalFilename\\_____.txt, illegalFilename\\?*<>|.txt"
})
void cleanDirectoryNameForWindows(String expected, String input) {
assertEquals(expected, FileNameCleaner.cleanDirectoryName(input));
}
}
14 changes: 14 additions & 0 deletions src/test/resources/mappings/jabRef-FileNameCleanerTest.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cleanFileName() : void -> package cleanFileName(expected String, input String) : void
line range:13-13==line range:21-21
line range:15-15==line range:21-21
line range:14-14==line range:21-21
package cleanCurlyBracesAsWell() : void -> package cleanFileName(expected String, input String) : void
line range:34-34==line range:21-21
package cleanDirectoryName() : void -> package cleanDirectoryName(expected String, input String) : void
line range:20-20==line range:31-31
line range:21-21==line range:31-31
line range:22-22==line range:31-31
package cleanDirectoryNameForWindows() : void -> package cleanDirectoryNameForWindows(expected String, input String) : void
line range:27-27==line range:41-41
line range:28-28==line range:41-41
line range:29-29==line range:41-41

0 comments on commit f150318

Please sign in to comment.