/* * Copyright 2019 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.server.wifi; import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import androidx.test.filters.SmallTest; import com.android.server.wifi.WifiCandidates.Candidate; import com.android.server.wifi.WifiCandidates.CandidateScorer; import com.android.server.wifi.WifiCandidates.ScoredCandidate; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import java.util.ArrayList; import java.util.List; /** * Unit tests for implementations of * {@link com.android.server.wifi.WifiCandidates.CandidateScorer}. * * Runs tests that any reasonable CandidateScorer should pass. * Individual scorers may have additional tests of their own. */ @SmallTest @RunWith(Parameterized.class) public class CandidateScorerTest { @Parameters(name = "{index}: {0}") public static List listOfObjectArraysBecauseJUnitMadeUs() { ScoringParams sp; ArrayList ans = new ArrayList<>(); sp = new ScoringParams(); ans.add(new Object[]{ "Compatibility Scorer", CompatibilityScorer.COMPATIBILITY_SCORER_DEFAULT_EXPID, new CompatibilityScorer(sp), sp}); sp = new ScoringParams(); ans.add(new Object[]{ "Score Card Based Scorer", ScoreCardBasedScorer.SCORE_CARD_BASED_SCORER_DEFAULT_EXPID, new ScoreCardBasedScorer(sp), sp}); sp = new ScoringParams(); ans.add(new Object[]{ "Bubble Function Scorer", BubbleFunScorer.BUBBLE_FUN_SCORER_DEFAULT_EXPID, new BubbleFunScorer(sp), sp}); return ans; } @Parameter(0) public String mTitleForUseInGeneratedParameterNames; @Parameter(1) public int mExpectedExpId; @Parameter(2) public CandidateScorer mCandidateScorer; @Parameter(3) public ScoringParams mScoringParams; private static final double TOL = 1e-6; // for assertEquals(double, double, tolerance) private ConcreteCandidate mCandidate1; private ConcreteCandidate mCandidate2; /** * Sets up for unit test */ @Before public void setUp() throws Exception { mScoringParams.update(""); mCandidate1 = new ConcreteCandidate().setEvaluatorId(0).setEvaluatorScore(66) .setScanRssi(-50).setFrequency(5180); mCandidate2 = new ConcreteCandidate().setEvaluatorId(0).setEvaluatorScore(99) .setScanRssi(-50).setFrequency(5180); } /** * Test that the expected expid is computed with the built-in defaults. */ @Test public void testExpid() throws Exception { String identifier = mCandidateScorer.getIdentifier(); assertEquals(identifier, mExpectedExpId, WifiNetworkSelector.experimentIdFromIdentifier(identifier)); } /** * Utility function to build and evaluate a candidate. */ private double evaluate(ConcreteCandidate candidate) { ArrayList candidates = new ArrayList<>(1); candidates.add(candidate); ScoredCandidate choice = mCandidateScorer.scoreCandidates(candidates); return Math.max(-999999999.0, choice.value); } /** * Evaluating equal inputs should give the same result. */ @Test public void testEqualInputsShouldGiveTheSameResult() throws Exception { assertEquals(evaluate(mCandidate1), evaluate(mCandidate2), TOL); } /** * Prefer 5 GHz over 2.4 GHz in non-fringe conditions, similar rssi. */ @Test public void testPrefer5GhzOver2GhzInNonFringeConditionsSimilarRssi() throws Exception { assertThat(evaluate(mCandidate1.setFrequency(5180).setScanRssi(-44)), greaterThan(evaluate(mCandidate2.setFrequency(2024).setScanRssi(-44)))); } /** * Prefer higher rssi. */ @Test public void testPreferHigherRssi() throws Exception { assertThat(evaluate(mCandidate1.setScanRssi(-63)), greaterThan(evaluate(mCandidate2.setScanRssi(-64)))); } /** * Prefer a secure network over an open one. */ @Test public void testPreferASecureNetworkOverAnOpenOne() throws Exception { assertThat(evaluate(mCandidate1), greaterThan(evaluate(mCandidate2.setOpenNetwork(true)))); } /** * Prefer the current network, even if rssi difference is significant. */ @Test public void testPreferTheCurrentNetworkEvenIfRssiDifferenceIsSignificant() throws Exception { assertThat(evaluate(mCandidate1.setScanRssi(-77).setCurrentNetwork(true)), greaterThan(evaluate(mCandidate2.setScanRssi(-68)))); } /** * Above saturation, don't switch from current even with a large rssi difference. */ @Test public void testAboveSaturationDoNotSwitchAwayEvenWithALargeRssiDifference() throws Exception { int goodRssi = mScoringParams.getGoodRssi(mCandidate1.getFrequency()); int unbelievablyGoodRssi = -1; assertThat(evaluate(mCandidate1.setScanRssi(goodRssi).setCurrentNetwork(true)), greaterThan(evaluate(mCandidate2.setScanRssi(unbelievablyGoodRssi)))); } }