| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.regression.tests; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.doNothing; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| |
| import com.android.regression.tests.DetectRegression.TableRow; |
| import com.android.tradefed.result.TestDescription; |
| import com.android.tradefed.util.MultiMap; |
| |
| import com.google.common.primitives.Doubles; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.ArgumentCaptor; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| |
| /** Unit tests for {@link DetectRegression}. */ |
| @RunWith(JUnit4.class) |
| public class DetectRegressionTest { |
| |
| private static final double EPS = 0.0001; |
| |
| @Test |
| public void testCalcMean() { |
| Map<Double, double[]> data = new HashMap<>(); |
| data.put(2.5, new double[] {1, 2, 3, 4}); |
| data.put( |
| 4.5, |
| new double[] { |
| -11, 22, 5, 4, 2.5, |
| }); |
| data.forEach( |
| (k, v) -> { |
| assertTrue(equal(k, DetectRegression.calcMean(Doubles.asList(v)))); |
| }); |
| } |
| |
| @Test |
| public void testCalcStdDev() { |
| Map<Double, double[]> data = new HashMap<>(); |
| data.put(36.331000536732, new double[] {12.3, 56.7, 45.6, 124, 56}); |
| data.put(119.99906922093, new double[] {123.4, 22.5, 5.67, 4.56, 2.5, 333}); |
| data.forEach( |
| (k, v) -> { |
| assertTrue(equal(k, DetectRegression.calcStdDev(Doubles.asList(v)))); |
| }); |
| } |
| |
| @Test |
| public void testDetectRegression() { |
| List<List<Double>> befores = |
| Arrays.stream( |
| new double[][] { |
| {3, 3, 3, 3, 3}, |
| {3, 5, 3, 5, 4}, |
| {3, 4, 3, 4, 3}, |
| {1, 2, 3, 2, 1}, |
| {-1, -2, -3, 0, 1, 2, 3}, |
| {5, 6, 5, 6, 6, 5, 7}, |
| }) |
| .map(Doubles::asList) |
| .collect(Collectors.toList()); |
| List<List<Double>> afters = |
| Arrays.stream( |
| new double[][] { |
| {3, 3, 3, 3, 3}, |
| {2, 3, 4, 5, 6}, |
| {2, 5, 2, 5, 2}, |
| {10, 11, 12, 13, 14}, |
| {-10, -20, -30, 0, 10, 20, 30}, |
| {5, 6, 5, 6, 6, 5, 700}, |
| }) |
| .map(Doubles::asList) |
| .collect(Collectors.toList()); |
| boolean[] result = {false, false, true, true, true, false}; |
| |
| for (int i = 0; i < result.length; i++) { |
| assertEquals( |
| result[i], DetectRegression.computeRegression(befores.get(i), afters.get(i))); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void testRunRegressionDetection() { |
| DetectRegression detector = spy(DetectRegression.class); |
| doNothing().when(detector).logResult(any(), any(), any(), any()); |
| TestDescription id1 = new TestDescription("class", "test1"); |
| TestDescription id2 = new TestDescription("class", "test2"); |
| Metrics before = new Metrics(false); |
| Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") |
| .forEach(e -> before.addRunMetric("metric-1", e)); |
| Arrays.asList("3.1", "3.3", "3.1", "3.2", "3.3") |
| .forEach(e -> before.addRunMetric("metric-2", e)); |
| Arrays.asList("5.1", "5.2", "5.1", "5.2", "5.1") |
| .forEach(e -> before.addRunMetric("metric-3", e)); |
| Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") |
| .forEach(e -> before.addTestMetric(id1, "metric-4", e)); |
| Arrays.asList("3.1", "3.3", "3.1", "3.2", "3.3") |
| .forEach(e -> before.addTestMetric(id2, "metric-5", e)); |
| Arrays.asList("5.1", "5.2", "5.1", "5.2", "5.1") |
| .forEach(e -> before.addTestMetric(id2, "metric-6", e)); |
| |
| Metrics after = new Metrics(false); |
| Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") |
| .forEach(e -> after.addRunMetric("metric-1", e)); |
| Arrays.asList("3.2", "3.2", "3.2", "3.2", "3.2") |
| .forEach(e -> after.addRunMetric("metric-2", e)); |
| Arrays.asList("8.1", "8.2", "8.1", "8.2", "8.1") |
| .forEach(e -> after.addRunMetric("metric-3", e)); |
| Arrays.asList("3.0", "3.0", "3.0", "3.0", "3.0") |
| .forEach(e -> after.addTestMetric(id1, "metric-4", e)); |
| Arrays.asList("3.2", "3.2", "3.2", "3.2", "3.2") |
| .forEach(e -> after.addTestMetric(id2, "metric-5", e)); |
| Arrays.asList("8.1", "8.2", "8.1", "8.2", "8.1") |
| .forEach(e -> after.addTestMetric(id2, "metric-6", e)); |
| |
| ArgumentCaptor<List<TableRow>> runResultCaptor = ArgumentCaptor.forClass(List.class); |
| ArgumentCaptor<MultiMap<String, TableRow>> testResultCaptor = |
| ArgumentCaptor.forClass(MultiMap.class); |
| detector.runRegressionDetection(before, after); |
| verify(detector, times(1)) |
| .logResult( |
| eq(before), |
| eq(after), |
| runResultCaptor.capture(), |
| testResultCaptor.capture()); |
| |
| List<TableRow> runResults = runResultCaptor.getValue(); |
| assertEquals(1, runResults.size()); |
| assertEquals("metric-3", runResults.get(0).name); |
| |
| MultiMap<String, TableRow> testResults = testResultCaptor.getValue(); |
| assertEquals(1, testResults.size()); |
| assertEquals(1, testResults.get(id2.toString()).size()); |
| assertEquals("metric-6", testResults.get(id2.toString()).get(0).name); |
| } |
| |
| private boolean equal(double d1, double d2) { |
| return Math.abs(d1 - d2) < EPS; |
| } |
| } |