/
Mutation Testing Meets Approximate Computing Mutation Testing Meets Approximate Computing

Mutation Testing Meets Approximate Computing - PowerPoint Presentation

olivia-moreira
olivia-moreira . @olivia-moreira
Follow
375 views
Uploaded On 2018-03-06

Mutation Testing Meets Approximate Computing - PPT Presentation

Milos Gligoric 1 Sarfraz Khurshid 1 Sasa Misailovic 2 August Shi 2 ICSE NIER 2017 Buenos Aires Argentina May 24 2017 1 CCF1409423 CCF1421503 CCF1566363 CCF1629431 CCF1319688 CNS1239498 ID: 641153

values double int data double values data int iterator treeset count unique matharrays approximate length return add mutation size

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Mutation Testing Meets Approximate Compu..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Mutation Testing Meets Approximate Computing

Milos Gligoric1, Sarfraz Khurshid1, Sasa Misailovic2, August Shi2ICSE NIER 2017Buenos Aires, ArgentinaMay 24, 2017

1

CCF-1409423, CCF-1421503,

CCF-1566363, CCF-1629431,

CCF-1319688, CNS-1239498

1

2Slide2

Mutation Testing

Goal: Evaluate quality of test suitesHow: Apply transformations (mutation operators) on the code and run tests to see if they can detect the changesExample:

x = x + 12Slide3

Mutation Testing

Goal: Evaluate quality of test suitesHow: Apply transformations (mutation operators) on the code and run tests to see if they can detect the changesExample:

x = x + 2

Problems:Evaluation of quality limited by mutation operatorsToo slow3Slide4

Approximate Computing

Goal: Improve performance of codeHow: Apply transformations that may lead to (slightly) inaccurate resultsExample:for (

i

= 0; i < n; i

= i + 1)

4Slide5

Approximate Computing

Goal: Improve performance of codeHow: Apply transformations that may lead to (slightly) inaccurate resultsExample:for (

i

= 0; i < n; i

= i +

2)Problems:

Not sure where in exact code to apply approximationsUnclear how to check quality of tests on already approximate code5Slide6

How can

Mutation Testing and Approximate Computingimprove one another?6Slide7

Improving One Another

Approximate computing to provide new mutation operators for evaluating quality of testsApproximate computing to improve speed of mutation testingMutation testing to point out opportunities for applying approximations on exact codeMutation testing to evaluate quality of tests on (already) approximate code

7Slide8

Example Code: Commons-Math

8// MathArrays.javastatic

double

[] unique(double[] data) {

TreeSet<Double> values =

new

TreeSet<>(); for (int i = 0; i

< data.length

;

i

++) {

0

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new

double[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;}

// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique(x), 0);}

Test PassesSlide9

// MathArrays.java

static double[] unique(

double

[] data) { TreeSet<Double> values =

new

TreeSet

<>(); for (int i = 0; i < data.length;

i++) {

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new

double

[count];

Iterator<Double>

iterator = values.descendingIterator(); int i = 1; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;}

Mutant: Constant Replacement9Mutant KilledReplace 0 with 1Test Fails// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2

};

double[] values = {11, 9, 7,

5, 3, 0, -1, -2};

assertArrayEquals

(values

,

MathArrays.unique

(x

), 0);

}Slide10

// MathArrays.java

static double[] unique(

double

[] data) { TreeSet<Double> values =

new

TreeSet

<>(); for (int i = 1; i <

data.length;

i

++) {

0

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new

double

[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;}

Mutant: Constant Replacement10Mutant SurvivedReplace 0 with 1// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7,

5, 3, 0, -1, -2};

assertArrayEquals

(values,

MathArrays.unique

(x

), 0);

}

Test PassesSlide11

// MathArrays.java

static double[] unique(

double

[] data) { TreeSet<Double> values =

new

TreeSet

<>(); for (int i = 0; i <

data.length;

i

+=2

)

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new

double[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;

} Approximate: Loop Perforation11Skip every other iteration68% of runtime is in this loop// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2};

double[] values = {11, 9, 7,

5, 3, 0, -1, -2};

assertArrayEquals(values

,

MathArrays.unique

(x

), 0);

}

Test FailsSlide12

Approximate: Loop Perforation

12

Test Passes

// MathArraysTest.javavoid

testUnique()

{

double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2};

assertArraySubset

(values

,

MathArrays.unique

(x

), 0);

}

Modify assertion

Approximation is Acceptable

// MathArrays.java

static

double

[] unique(

double

[] data) {

TreeSet

<Double> values =

new TreeSet<>(); for (int i = 0; i < data.length; i+=2)

values.add(data[i]); } int count = values.size(); double[] out = new double[count]; Iterator<Double> iterator = values.descendingIterator(); int i

= 0; while

(iterator.hasNext

()) { out[i

++] =

iterator.next

();

}

return

out;

}

Skip every other iteration

68% of runtime is in this loopSlide13

Comparison of Transformation Results

13Failing TestPassing Test

Mutation

Testing

Approximate

ComputingSlide14

Comparison of Transformation Results

14Failing TestPassing Test

Mutation

Testing

Approximate

ComputingSlide15

Approx. Transformation as Operator

15// MathArrays.javastatic

double

[] unique(double[] data) {

TreeSet<Double> values =

new

TreeSet<>(); for (int i = 0;

i

<

data.length

;

i

++)

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new double[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return

out;} // MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique

(x), 0);}Slide16

Approx. Transformation as Operator

16// MathArrays.javastatic

double

[] unique(double[] data) {

TreeSet<Double> values =

new

TreeSet<>(); for (int i = 0;

i

<

data.length

;

i

+=2

)

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out = new double[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return

out;} // MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique

(x), 0);}

Replace

i

++

with

i

+=2

Perforates loop

Mutant Killed

Test FailsSlide17

Questions for Approx. Operators

Do killed approximate mutants indicate different strengths? Do surviving approximate mutants indicate new weaknesses in the test suite?How do mutants generated by approximate computing differ from traditional mutants?Are approximate mutants faster than traditional mutants?17Slide18

Mutants Find Approx. Opportunities

18// MathArrays.javastatic

double

[] unique(double[] data) {

TreeSet<Double> values =

new

TreeSet<>(); for (int i = 0;

i

<

data.length

;

i

++)

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new double[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;

} // MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique(x

), 0);}Slide19

// MathArrays.java

static double[] unique(

double

[] data) { TreeSet<Double> values =

new

TreeSet

<>(); for (int i = 1; i <

data.length;

i

++)

values.add

(data[

i

]);

}

int

count =

values.size

();

double

[] out =

new

double

[count]; Iterator<Double> iterator = values.descendingIterator(); int i = 0; while (iterator.hasNext()) { out[i++] = iterator.next(); } return out;}

// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11, 7, 3, 5, −1, −2}; double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique(x), 0);}

Mutants Find Approx. Opportunities19

Replace 0 with

1

Approximable

?

Test PassesSlide20

Questions for Approx. Opportunities

How can we classify surviving mutants? Are they good for approximate computing?What approximations are applicable for which surviving mutants?How can we tailor mutants for the purpose of finding approximate computing opportunities?20Slide21

Improving One Another

Approximate computing to provide new mutation operators for evaluating quality of testsApproximate computing to improve speed of mutation testingMutation testing to point out opportunities for applying approximations on exact codeMutation testing to evaluate quality of tests on (already) approximate code21

More in paper!Slide22

Conclusions

Approximate computing can provide newmutation operatorsMutation testing can show opportunities for approximate computing on exact codeThere is so much more we can do(More directions in the paper)22

August Shi: awshi2@illinois.eduSlide23

BACKUP

23Slide24

Mutating Approximate Code?

24 // MathArrays.javastatic

double

[] unique(double[] data) {

TreeSet<Double> values =

new

TreeSet<>(); for (int i = 1

; i

<

data.length

;

i

++) {

if

(i%2 != 0)

continue

;

values.add

(data[

i

]);

}

return

values.toArray();} Test PassesReplace 0 with 1// MathArraysTest.javavoid testUnique() { double[] x = {0, 9, 3, 0, 11,

7, 3, 5, −1, −2} double[] values = {11, 9, 7, 5, 3, 0, -1, -2}; assertArrayEquals(values, MathArrays.unique(x), 0);}Slide25

Loop Perforation (Line 04)

Skip every 2

nd iteration100

Skip every 4th iteration95

Only execute every 4th iteration100

Mutation testing approximate code?

Approximate TransformationInstance% Mutants KilledExact VersionN/A9525

What precisely do these changes in percentages mean?Slide26

Directions for Research

If approximate version is proxy of exact version, is mutation score of approximate version also proxy of mutation score of exact version?Do I get same confidence in quality of tests at cheaper cost?If so, what are the exact conditions where they are good proxies?26Slide27

Approximate Code to Speed up Testing?

27 // MathArrays.java01.

static

double[] unique(double

[] data) {02.

TreeSet values =

03. new TreeSet<>();04. for (int

i

= 0;

05.

i

<

data.length

;

i

++) {

06.

if

(i%2 != 0)

continue

;

07.

values.add

(data[

i

]);

08. }09. int count = values.size()10. double[] out = new double[count];11. Iterator iterator =12. values.descendingIterator();13. int

i = 0;14. while (iterator.hasNext()) {15. if (i == data.length / 2 + 1) break;16. out[i++] = iterator.next();17. }19. return out;20.

}

// MathArraysTest.java

void

testUnique

()

{

double

[] x = {0, 9, 3, 0,

11,

7

, 3, 5, −1, −

2}

double

[] values = {

11, 3,

0

, -

1};

assertArrayEquals

(values,

MathArrays.unique

(x), 0);

}

Loop (line 04) takes

68% of runtime

Perforation can cut

time in halfSlide28

// MathArraysTest.java

void testUnique()

{

double[] x = {0, 9, 3, 0,

11, 7, 3, 5, −1, −

2}

double[] values = {11, 9, 7, 5, 3, 0, -1, -2};

assertApproxEquals

(values,

MathArrays.unique

(x), 0

0.8

);

}

Approximate Code to Speed up Testing?

28

// MathArrays.java

01.

static

double

[] unique(

double

[] data) {

02.

TreeSet values =03. new TreeSet<>();04. for (int i = 0;05. i < data.length; i++) {06.

if (i%2 != 0) continue;07. values.add(data[i]);08. }09. int count = values.size()10. double[] out = new double[count];11. Iterator iterator =

12. values.descendingIterator

();13.

int

i

= 0;

14.

while

(

iterator.hasNext

()) {

15.

if

(

i

==

data.length

/ 2 + 1)

break

;

16.

out[

i

++] =

iterator.next

();

17.

}

19.

return

out;

20.

}

Introduce new assertions?Slide29

Example: Mutation Testing (SURVIVED)

29// MathArrays.java

static

double[] unique(double

[] data) {

TreeSet

values = new TreeSet<>(); for

(int

i

=

0;

i

<

data.length

;

i

++)

{

if (i%2

!= 0)

continue

;

values.add(data[i]); } int count = values.size() double[] out = new double[count]; … return out;}

ConstantReplacementOriginalMutantTest passes on originalTest passes on mutant => Mutant SURVIVED// MathArrays.javastatic double[] unique(double[] data) { TreeSet values = new TreeSet

<>();

for

(int

i

= 1

;

i

<

data.length

;

i

++)

{

if (i%2

!= 0)

continue

;

values.add

(data[

i

]);

}

int

count =

values.size

()

double

[] out =

new

double

[count

];

return

out

;

}

// MathArraysTest.java

void

testUnique

()

{

double

[] x = {0, 9, 3, 0,

11,

7

, 3, 5, −1, −

2}

double

[] values = {11, 9, 7, 5,

3,

0

, -1, -2

};

assertArrayEquals

(values,

MathArrays.unique

(x

), 0

);

}Slide30

Example: Mutation Testing (KILLED)

30// MathArrays.java

static

double[] unique(double

[] data) {

TreeSet

values = new TreeSet<>(); for

(int

i

=

0;

i

<

data.length

;

i

++)

{

if (i%2

!= 0)

continue

;

values.add(data[i]); } int count = values.size() double[] out = new double[count]; … return out;}

BoundaryMutatorOriginalMutantTest passes on originalTest passes on mutant => Mutant KILLED// MathArrays.javastatic double[] unique(double[] data) { TreeSet values = new TreeSet

<>();

for

(int

i

=

0;

i

<=

data.length

;

i

++)

{

if (i%2

!= 0)

continue

;

values.add

(data[

i

]);

}

int

count =

values.size

()

double

[] out =

new

double

[count

];

return

out

;

}

// MathArraysTest.java

void

testUnique

()

{

double

[] x = {0, 9, 3, 0,

11,

7

, 3, 5, −1, −

2}

double

[] values = {11, 9, 7, 5,

3,

0

, -1, -2

};

assertArrayEquals

(values,

MathArrays.unique

(x

), 0

);

}Slide31

Example: Loop Perforation

31// MathArrays.java

static

double[] unique(double

[] data) {

TreeSet

values = new TreeSet<>(); for

(int

i

=

0;

i

<

data.length

;

i

++)

{

if (i%2

!= 0)

continue

;

values.add(data[i]); } int count = values.size() double[] out = new double[count]; … return out;}

Skip EveryOther IterationOriginalMutant// MathArrays.javastatic double[] unique(double[] data) { TreeSet values = new TreeSet<>();

for (

int

i =

0;

i

<

data.length

;

i

+=2) {

if (i%2

!= 0)

continue

;

values.add

(data[

i

]);

}

int

count =

values.size

()

double

[] out =

new

double

[count

];

return

out

;

}