Semantic Slicing of Software Version Histories Yi Li / U Toronto Julia Rubin / MIT Marsha Chechik / U Toronto ASE 2015 / Lincoln, NE
Motivation Feb, 2015 release [1.3.8] v1.3.8 … make ’groovy.sandbox.blacklist’ append-only avoid NullPointerException if optional Groovy jar is removed 30 authors 67 commits make groovy sandbox method blacklist dynamically additive 87 files changed … prepare for next development iteration (1.3.7-SNAPSHOT) updated docs to use v1.3.6 as current Nov, 2014 release [1.3.6] v1.3.6 2
Motivation Feb, 2015 release [1.3.8] v1.3.8 … make ’groovy.sandbox.blacklist’ append-only avoid NullPointerException if optional Groovy jar is removed 30 authors 67 commits make groovy sandbox method blacklist dynamically additive 87 files changed … prepare for next development iteration (1.3.7-SNAPSHOT) updated docs to use v1.3.6 as current Nov, 2014 release [1.3.6] v1.3.6 2
Motivation Feb, 2015 release [1.3.8] v1.3.8 … make ’groovy.sandbox.blacklist’ append-only avoid NullPointerException if optional Groovy jar is removed 30 authors 67 commits make groovy sandbox method blacklist dynamically additive 87 files changed … prepare for next development iteration (1.3.7-SNAPSHOT) updated docs to use v1.3.6 as current Nov, 2014 release [1.3.6] v1.3.6 2
Motivation Feb, 2015 release [1.3.8] v1.3.8 … make ’groovy.sandbox.blacklist’ append-only avoid NullPointerException if optional Groovy jar is removed 30 authors 67 commits make groovy sandbox method blacklist dynamically additive 87 files changed … prepare for next development iteration (1.3.7-SNAPSHOT) updated docs to use v1.3.6 as current Nov, 2014 release [1.3.6] v1.3.6 2
Why is it so hard? target base 3
Why is it so hard? Options? target 1. Pick target commits 2. Pick the whole history 3. Manually identify necessary commits base 3
Why is it so hard? Options? target 1. Pick target commits 2. Pick the whole history 3. Manually identify necessary commits base 3
Why is it so hard? Options? target 1. Pick target commits 2. Pick the whole history 3. Manually identify necessary commits base 3
Why is it so hard? Options? target 1. Pick target commits // comment int boo1() { 2. Pick the whole history - {return 0;} + {return (new Bar()).y;} } 3. Manually identify necessary commits class Bar { + int y = 0; static int bar1(int x) {return x - 1;} Existing version control tools: • Code treated as plain texts • Do not understand the semantics • User provided semantic/logical grouping is inaccurate! base 3
What can we do? Exploit existing artifacts: target • Strictly structured data • Well-defined language syntax and semantics • Carefully designed test suites base 4
What can we do? Exploit existing artifacts: target • Strictly structured data • Well-defined language syntax and semantics • Carefully designed test suites base 4
Solution: Semantic Slicing Exploit existing artifacts: target target • Strictly structured data • Well-defined language syntax and semantics • Carefully designed test suites base History: Sub-history: sequence of commits well-formed: compiles + & Criterion: semantic preserving: set of tests passing tests base 4
Outline 1. Introduction 2. Dependency Hierarchy 3. CSlicer Algorithm 4. Evaluation 5. Related Work & Conclusion 5
Running Example class A { int g() {return 0;} } class B { static int f(int x) v1.0 {return x + 1;} } 6
Running Example class A { // comment int g() {return 0;} class A { } + // comment C 1 int g() class B { {return 0;} static int f(int x) v1.0 {return x + 1;} } 6
Running Example class A { class A { static int f(int x) { // comment - {return x + 1;} C 2 + {return x - 1;} int g() } {return 0;} class A { } + // comment C 1 int g() class B { {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example // comment int g() { - {return 0;} + {return (new B()).y;} class A { C 3 } class A { // comment class B { static int f(int x) { + int y = 0; int g() - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} {return (new B()).y;} } } class A { class B { + // comment C 1 int g() int y = 0; {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example class A { C 4 + int x; // comment // comment int g() { int g() class A { - {return 0;} + {return (new B()).y;} int x; C 3 } class A { // comment class B { static int f(int x) { + int y = 0; int g() - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} {return (new B()).y;} } } class A { class B { + // comment C 1 int g() int y = 0; {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example Test case: class TestA { a.g()==-1 public void t1() class A { A a = new A(); int x; v1.1 {assertEquals(-1, a.g();} + int g() C 5 + {return B.f(x);} } // comment int h() class A { class A { C 4 + int x; // comment int x; // comment int g() { int g() int g() - {return 0;} + {return (new B()).y;} {return B.f(x);} C 3 } class A { // comment class B { static int f(int x) { + int y = 0; int h() - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} {return (new B()).y;} } } class A { class B { + // comment C 1 int g() int y = 0; {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example Test case: class TestA { a.g()==-1 public void t1() class A { A a = new A(); int x; v1.1 {assertEquals(-1, a.g();} + int g() C 5 + {return B.f(x);} } // comment int h() class A { C 4 + int x; // comment class A { // comment int g() { int g() int x; - {return 0;} + {return (new B()).y;} int g() C 3 } class A { {return B.f(x);} class B { static int f(int x) { + int y = 0; // comment - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} int h() } {return 0;} class A { } + // comment C 1 int g() class B{ {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example Test case: class TestA { a.g()==-1 public void t1() class A { A a = new A(); int x; v1.1 {assertEquals(-1, a.g();} + int g() C 5 + {return B.f(x);} } // comment int h() class A { C 4 + int x; // comment class A { // comment int g() { int g() int x; - {return 0;} + {return (new B()).y;} int g() C 3 } class A { {return B.f(x);} class B { static int f(int x) { + int y = 0; // comment - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} int h() } {return 0;} class A { } + // comment C 1 int g() class B{ {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example Test case: class TestA { a.g()==-1 public void t1() class A { A a = new A(); int x; v1.1 {assertEquals(-1, a.g();} + int g() C 5 + {return B.f(x);} } // comment int h() class A { C 4 + int x; // comment class A { // comment int g() { int g() int x; - {return 0;} + {return (new B()).y;} int g() C 3 } class A { {return B.f(x);} class B { static int f(int x) { + int y = 0; // comment - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} int h() } {return 0;} class A { } + // comment C 1 int g() class B{ {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Running Example Test case: class TestA { a.g()==-1 public void t1() class A { A a = new A(); int x; v1.1 {assertEquals(-1, a.g();} + int g() C 5 + {return B.f(x);} } // comment int h() class A { C 4 + int x; // comment class A { // comment int g() { int g() int x; - {return 0;} + {return (new B()).y;} int g() C 3 } class A { {return B.f(x);} class B { static int f(int x) { + int y = 0; // comment - {return x + 1;} static int f(int x) C 2 + {return x - 1;} {return x - 1;} int h() } {return 0;} class A { } + // comment C 1 int g() class B{ {return 0;} static int f(int x) v1.0 {return x - 1;} } 6
Dependency Hierarchy Dependency Examples Definitions Types class A { required for maintaining the static int f(int x) { - {return x + 1;} Functional semantic behaviours (e.g., pass C 2 + {return x - 1;} } the same tests) required for maintaining the class A { C 4 wellformedness of the program + int x; Compilation // comment (e.g., free from compilation int g() errors) class A { specific to text-based version + // comment Hunk C 1 int g() control systems (e.g., Git) {return 0;} 7
Dependency Hierarchy Dependency Examples Definitions Dependency Hierarchy Types class A { Correctness required for maintaining the static int f(int x) { - {return x + 1;} Functional Functional semantic behaviours (e.g., pass C 2 + {return x - 1;} } Core the same tests) required for maintaining the Well-formedness class A { Structural C 4 wellformedness of the program + int x; Compilation // comment Glue Code (e.g., free from compilation int g() errors) class A { specific to text-based version Applicability + // comment Hunk Textual Contexts C 1 int g() control systems (e.g., Git) {return 0;} 7
Outline 1. Introduction 2. Dependency Hierarchy 3. CSlicer Algorithm 4. Evaluation 5. Related Work & Conclusion 8
Recommend
More recommend