Automated Transplantation and Differential Testing for Clones Tianyi Zhang, Miryung Kim University of California, Los Angeles 1
Problem Statement • Code clones are common in modern software systems. • Developers often find it difficult to examine the runtime behavior of clones. • This problem is exacerbated by a lack of tests. 46% of clone pairs are only partially covered by existing test suites. • We present Grafter to reuse tests between clones and examine behavior differences. 2
A pair of similar but not identical clones that are detected by an existing clone detection tool, Deckard [ICSE 2007]. public class Copy extends Task{ public class Delete extends Task{ private IncludePatternSet includes ; private ExcludePatternSet excludes ; public void setIncludes (String patterns){ public void setExcludes (String patterns){ … … StringTokenizer tok = new StringTokenizer(patterns, “,”); StringTokenizer tok = new StringTokenizer(patterns, “,”); while(tok.hasMoreTokens()){ while(tok.hasMoreTokens()){ includes .addPattern(tok.next); excludes .addPattern(tok.next); } } … … } } } } class IncludePatternSet { class ExcludePatternSet { public Set<String> set; public Set<String> set; public void addPattern(String s) { set.add(s); }; public void addPattern(String s) { set.add(s); }; } } Copy.java Delete.java * The example is adapted from Apache Ant 1.9.6 for presentation purposes . 3
A programmer updates the use of StringTokenizer to StringUtils.split in the Copy and Delete classes. ? test public class Delete extends Task{ public class Copy extends Task{ private ExcludePatternSet excludes; private IncludePatternSet includes; public void setExcludes(String patterns){ public void setIncludes(String patterns){ … … + String[] tokens = StringUtils.split(patterns, “.”); + String[] tokens = StringUtils.split(patterns, “,”); + for(String tok : tokens){ + for(String tok : tokens){ + excludes.addPattern(tok); + includes.addPattern(tok); + } + } … … } } } } Copy.java Delete.java * The example is adapted from Apache Ant 1.9.6 for presentation purposes . 4
Limitation of Existing Techniques • Existing test reuse technique for clones works only at a method or class level and requires a reuse plan. [Makady & Walker] • Existing differential testing or random testing techniques are not geared towards intra method clones [Geno, Diffut, Randoop] • Existing clone inconsistency detection techniques do not detect behavioral differences between clones [Jiang et al., CBCD, SPA] 5
Grafter: Automated Test Reuse and Differential Testing public class Copy extends Task{ private IncludePatternSet includes; … String[] tokens = StringUtils.split(patterns, “,”); Success Failure Copy.java for(String tok : tokens){ includes.addPattern(tok); (recipient) } … testCopy public class Delete extends Task{ private ExcludePatternSet excludes; … ? String[] tokens = StringUtils.split(patterns, “.”); String[] tokens = StringUtils.split(patterns, “.”); Delete.java for(String tok : tokens){ for(String tok : tokens){ (donor) excludes.addPattern(tok); excludes.addPattern(tok); } } 6 …
Grafter: Automated Test Reuse and Differential Testing public class Copy extends Task{ private IncludePatternSet includes; … String[] tokens = StringUtils.split(patterns, “,”); Success Copy.java for(String tok : tokens){ includes.addPattern(tok); } … testCopy public class Delete extends Task{ private ExcludePatternSet excludes; … Failure String[] tokens = StringUtils.split(patterns, “.”); String[] tokens = StringUtils.split(patterns, “.”); Delete.java for(String tok : tokens){ for(String tok : tokens){ excludes.addPattern(tok); excludes.addPattern(tok); } } 7 …
Grafter Approach Overview Clone Pair Test Suite A B Variation Code Data Differential Identification Transplantation Propagation Testing State Clone A Clone B Test Clone A Clone B S1 “string” “string” T1 pass fail S2 true false T2 pass pass 8
Grafter Approach Overview Variation Code Data Differential Identification Transplantation Propagation Testing • Name Variation • Declare Variables • Populate intermediate • Type Variation • Transform Types input data to clone • Test Comparison • Method Call • Declare Methods • Transfer intermediate • State Comparison • Recursive Calls Variation output back to test 9
Grafter Approach Overview Variation Variation Code Code Data Data Differential Differential Identification Identification Transplantation Transplantation Propagation Propagation Testing Testing • Name Variation • Name Variation • Declare Variables • Declare Variables • Populate intermediate • Populate intermediate • Type Variation • Type Variation • Transform Types • Transform Types input data to clone input data to clone • Test Comparison • Test Comparison • Method Call • Method Call • Declare Methods • Declare Methods • Transfer intermediate • Transfer intermediate • State Comparison • State Comparison • Recursive Calls • Recursive Calls Variation Variation output back to test output back to test 10
Grafter Approach Overview Variation Code Data Differential Identification Transplantation Propagation Testing • Name Variation • Declare Variables • Populate intermediate • Type Variation • Transform Types input data to clone • Test Comparison • Method Call • Declare Methods • Transfer intermediate • State Comparison • Recursive Calls Variation output back to test 11
Grafter Approach Overview Variation Code Data Differential Identification Transplantation Propagation Testing • Name Variation • Declare Variables • Populate intermediate • Type Variation • Transform Types input data to clone • Test Comparison • Method Call • Declare Methods • Transfer intermediate • State Comparison • Recursive Calls Variation output back to test 12
Step 1: Variation Identification Variation Code Data Differential Identification Transplantation Propagation Testing public class Copy extends Task{ public class Delete extends Task{ private IncludePatternSet includes; private ExcludePatternSet excludes; public void setIncludes(String patterns){ public void setExcludes(String patterns){ … … String[] tokens = StringUtils.split(patterns, “ , ”); String[] tokens = StringUtils.split(patterns, “ . ”); for(String tok : tokens){ for(String tok : tokens){ includes.addPattern(tok); excludes.addPattern(tok); } } } } … … 13
Step 1: Variation Identification Variation Code Data Differential Identification Transplantation Propagation Testing public class Copy extends Task{ public class Delete extends Task{ private IncludePatternSet includes; private ExcludePatternSet excludes; public void setIncludes(String patterns){ public void setExcludes(String patterns){ … … String[] tokens = StringUtils.split(patterns, “ , ”); String[] tokens = StringUtils.split(patterns, “ . ”); for(String tok : tokens){ for(String tok : tokens){ includes .addPattern(tok); excludes .addPattern(tok); } } } } … … 14
Step 2: Code Transplantation Code Variation Data Differential Identification Transplantation Propagation Testing public class Copy extends Task{ public class Delete extends Task{ private IncludePatternSet includes; private ExcludePatternSet excludes; public void setIncludes(String patterns){ public void setExcludes(String patterns){ … … String[] tokens = StringUtils.split(patterns, “ , ”); String[] tokens = StringUtils.split(patterns, “ . ”); String[] tokens = StringUtils.split(patterns, “ . ”); for(String tok : tokens){ for(String tok : tokens){ for(String tok : tokens){ includes .addPattern(tok); excludes .addPattern(tok); excludes .addPattern(tok); } } } } } … … 15
Step 2: Code Transplantation Code Variation Data Differential Identification Transplantation Propagation Testing public class Copy extends Task{ public class Delete extends Task{ private IncludePatternSet includes; private ExcludePatternSet excludes; + private ExcludePatternSet excludes; public void setExcludes(String patterns){ public void setIncludes(String patterns){ … … String[] tokens = StringUtils.split(patterns, “ . ”); + excludes = new ExcludePatternSet(); for(String tok : tokens){ String[] tokens = StringUtils.split(patterns, “ . ”); excludes .addPattern(tok); for(String tok : tokens){ } excludes .addPattern(tok); } } … } … 16
Step 3: Data Propagation Data Variation Code Differential Identification Transplantation Propagation Testing public class Copy extends Task{ private IncludePatternSet includes; + private ExcludePatternSet excludes; public class Delete extends Task{ public void setIncludes(String patterns){ private ExcludePatternSet excludes; … public void setExcludes(String patterns){ + excludes = new ExcludePatternSet(); … + excludes.set = includes.set; String[] tokens = StringUtils.split(patterns, “ . ”); String[] tokens = StringUtils.split(patterns, “ . ”); for(String tok : tokens){ for(String tok : tokens){ excludes .addPattern(tok); excludes .addPattern(tok); } } } + includes.set = excludes.set; … } … 17
Recommend
More recommend