1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.regression.tests; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertTrue; 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.doNothing; 23 import static org.mockito.Mockito.spy; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 27 import com.android.regression.tests.DetectRegression.TableRow; 28 import com.android.tradefed.result.TestDescription; 29 import com.android.tradefed.util.MultiMap; 30 31 import com.google.common.primitives.Doubles; 32 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.JUnit4; 36 import org.mockito.ArgumentCaptor; 37 38 import java.util.Arrays; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.stream.Collectors; 43 44 /** Unit tests for {@link DetectRegression}. */ 45 @RunWith(JUnit4.class) 46 public class DetectRegressionTest { 47 48 private static final double EPS = 0.0001; 49 50 @Test testCalcMean()51 public void testCalcMean() { 52 Map<Double, double[]> data = new HashMap<>(); 53 data.put(2.5, new double[] {1, 2, 3, 4}); 54 data.put( 55 4.5, 56 new double[] { 57 -11, 22, 5, 4, 2.5, 58 }); 59 data.forEach( 60 (k, v) -> { 61 assertTrue(equal(k, DetectRegression.calcMean(Doubles.asList(v)))); 62 }); 63 } 64 65 @Test testCalcStdDev()66 public void testCalcStdDev() { 67 Map<Double, double[]> data = new HashMap<>(); 68 data.put(36.331000536732, new double[] {12.3, 56.7, 45.6, 124, 56}); 69 data.put(119.99906922093, new double[] {123.4, 22.5, 5.67, 4.56, 2.5, 333}); 70 data.forEach( 71 (k, v) -> { 72 assertTrue(equal(k, DetectRegression.calcStdDev(Doubles.asList(v)))); 73 }); 74 } 75 76 @Test testDetectRegression()77 public void testDetectRegression() { 78 List<List<Double>> befores = 79 Arrays.stream( 80 new double[][] { 81 {3, 3, 3, 3, 3}, 82 {3, 5, 3, 5, 4}, 83 {3, 4, 3, 4, 3}, 84 {1, 2, 3, 2, 1}, 85 {-1, -2, -3, 0, 1, 2, 3}, 86 {5, 6, 5, 6, 6, 5, 7}, 87 }) 88 .map(Doubles::asList) 89 .collect(Collectors.toList()); 90 List<List<Double>> afters = 91 Arrays.stream( 92 new double[][] { 93 {3, 3, 3, 3, 3}, 94 {2, 3, 4, 5, 6}, 95 {2, 5, 2, 5, 2}, 96 {10, 11, 12, 13, 14}, 97 {-10, -20, -30, 0, 10, 20, 30}, 98 {5, 6, 5, 6, 6, 5, 700}, 99 }) 100 .map(Doubles::asList) 101 .collect(Collectors.toList()); 102 boolean[] result = {false, false, true, true, true, false}; 103 104 for (int i = 0; i < result.length; i++) { 105 assertEquals( 106 result[i], DetectRegression.computeRegression(befores.get(i), afters.get(i))); 107 } 108 } 109 110 @SuppressWarnings("unchecked") 111 @Test testRunRegressionDetection()112 public void testRunRegressionDetection() { 113 DetectRegression detector = spy(DetectRegression.class); 114 doNothing().when(detector).logResult(any(), any(), any(), any()); 115 TestDescription id1 = new TestDescription("class", "test1"); 116 TestDescription id2 = new TestDescription("class", "test2"); 117 Metrics before = new Metrics(false); 118 Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") 119 .forEach(e -> before.addRunMetric("metric-1", e)); 120 Arrays.asList("3.1", "3.3", "3.1", "3.2", "3.3") 121 .forEach(e -> before.addRunMetric("metric-2", e)); 122 Arrays.asList("5.1", "5.2", "5.1", "5.2", "5.1") 123 .forEach(e -> before.addRunMetric("metric-3", e)); 124 Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") 125 .forEach(e -> before.addTestMetric(id1, "metric-4", e)); 126 Arrays.asList("3.1", "3.3", "3.1", "3.2", "3.3") 127 .forEach(e -> before.addTestMetric(id2, "metric-5", e)); 128 Arrays.asList("5.1", "5.2", "5.1", "5.2", "5.1") 129 .forEach(e -> before.addTestMetric(id2, "metric-6", e)); 130 131 Metrics after = new Metrics(false); 132 Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") 133 .forEach(e -> after.addRunMetric("metric-1", e)); 134 Arrays.asList("3.2", "3.2", "3.2", "3.2", "3.2") 135 .forEach(e -> after.addRunMetric("metric-2", e)); 136 Arrays.asList("8.1", "8.2", "8.1", "8.2", "8.1") 137 .forEach(e -> after.addRunMetric("metric-3", e)); 138 Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") 139 .forEach(e -> after.addTestMetric(id1, "metric-4", e)); 140 Arrays.asList("3.2", "3.2", "3.2", "3.2", "3.2") 141 .forEach(e -> after.addTestMetric(id2, "metric-5", e)); 142 Arrays.asList("8.1", "8.2", "8.1", "8.2", "8.1") 143 .forEach(e -> after.addTestMetric(id2, "metric-6", e)); 144 145 ArgumentCaptor<List<TableRow>> runResultCaptor = ArgumentCaptor.forClass(List.class); 146 ArgumentCaptor<MultiMap<String, TableRow>> testResultCaptor = 147 ArgumentCaptor.forClass(MultiMap.class); 148 detector.runRegressionDetection(before, after); 149 verify(detector, times(1)) 150 .logResult( 151 eq(before), 152 eq(after), 153 runResultCaptor.capture(), 154 testResultCaptor.capture()); 155 156 List<TableRow> runResults = runResultCaptor.getValue(); 157 assertEquals(1, runResults.size()); 158 assertEquals("metric-3", runResults.get(0).name); 159 160 MultiMap<String, TableRow> testResults = testResultCaptor.getValue(); 161 assertEquals(1, testResults.size()); 162 assertEquals(1, testResults.get(id2.toString()).size()); 163 assertEquals("metric-6", testResults.get(id2.toString()).get(0).name); 164 } 165 equal(double d1, double d2)166 private boolean equal(double d1, double d2) { 167 return Math.abs(d1 - d2) < EPS; 168 } 169 } 170