diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk new file mode 100644 index 0000000000000..5850feee004ad --- /dev/null +++ b/wifi/tests/Android.mk @@ -0,0 +1,61 @@ +# Copyright (C) 2016 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. + +LOCAL_PATH:= $(call my-dir) + +# Make test APK +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +# This list is generated from the java source files in this module +# The list is a comma separated list of class names with * matching zero or more characters. +# Example: +# Input files: src/com/android/server/wifi/Test.java src/com/android/server/wifi/AnotherTest.java +# Generated exclude list: com.android.server.wifi.Test*,com.android.server.wifi.AnotherTest* + +# Filter all src files to just java files +local_java_files := $(filter %.java,$(LOCAL_SRC_FILES)) +# Transform java file names into full class names. +# This only works if the class name matches the file name and the directory structure +# matches the package. +local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files))) +# Utility variables to allow replacing a space with a comma +comma:= , +empty:= +space:= $(empty) $(empty) +# Convert class name list to jacoco exclude list +# This appends a * to all classes and replace the space separators with commas. +# These patterns will match all classes in this module and their inner classes. +jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes))) + +jacoco_include := android.net.wifi.* + +LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include) +LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude) + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-test \ + mockito-target-minus-junit4 \ + frameworks-base-testutils \ + +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + +LOCAL_PACKAGE_NAME := FrameworksWifiApiTests + +include $(BUILD_PACKAGE) diff --git a/wifi/tests/AndroidManifest.xml b/wifi/tests/AndroidManifest.xml new file mode 100644 index 0000000000000..4eaca2b98a1d7 --- /dev/null +++ b/wifi/tests/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/wifi/tests/README.md b/wifi/tests/README.md new file mode 100644 index 0000000000000..b418abd5e46b5 --- /dev/null +++ b/wifi/tests/README.md @@ -0,0 +1,50 @@ +# Wifi Unit Tests +This package contains unit tests for the android wifi framework APIs based on the +[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html). +The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/) +libraries. + +## Running Tests +The easiest way to run tests is simply run + +``` +frameworks/base/wifi/tests/runtests.sh +``` + +`runtests.sh` will build the test project and all of its dependencies and push the APK to the +connected device. It will then run the tests on the device. + +To pick up changes in framework/base, you will need to: +1. rebuild the framework library 'make -j32' +2. sync over the updated library to the device 'adb sync' +3. restart framework on the device 'adb shell stop' then 'adb shell start' + +To enable syncing data to the device for first time after clean reflash: +1. adb disable-verity +2. adb reboot +3. adb remount + +See below for a few example of options to limit which tests are run. +See the +[AndroidJUnitRunner Documentation](https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html) +for more details on the supported options. + +``` +runtests.sh -e package android.net.wifi +runtests.sh -e class android.net.wifi.WifiScannerTest +``` + +If you manually build and push the test APK to the device you can run tests using + +``` +adb shell am instrument -w 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner' +``` + +## Adding Tests +Tests can be added by adding classes to the src directory. JUnit4 style test cases can +be written by simply annotating test methods with `org.junit.Test`. + +## Debugging Tests +If you are trying to debug why tests are not doing what you expected, you can add android log +statements and use logcat to view them. The beginning and end of every tests is automatically logged +with the tag `TestRunner`. diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh new file mode 100755 index 0000000000000..ebcc2a2f34a2f --- /dev/null +++ b/wifi/tests/runtests.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +if [ -z $ANDROID_BUILD_TOP ]; then + echo "You need to source and lunch before you can use this script" + exit 1 +fi + +echo "Running tests" + +set -e # fail early + +echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/wifi/tests" +# NOTE Don't actually run the command above since this shell doesn't inherit functions from the +# caller. +make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-wifi-tests + +set -x # print commands + +adb root +adb wait-for-device + +adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk" + +adb shell am instrument -w "$@" 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner' diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java new file mode 100644 index 0000000000000..0c730705b0394 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/FakeKeys.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 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 android.net.wifi; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * A class containing test certificates. + */ +public class FakeKeys { + private static final String CA_CERT0_STRING = "-----BEGIN CERTIFICATE-----\n" + + "MIIDKDCCAhCgAwIBAgIJAILlFdwzLVurMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" + + "BAMTB0VBUCBDQTEwHhcNMTYwMTEyMTE1MDE1WhcNMjYwMTA5MTE1MDE1WjASMRAw\n" + + "DgYDVQQDEwdFQVAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" + + "znAPUz26Msae4ws43czR41/J2QtrSIZUKmVUsVumDbYHrPNvTXKSMXAcewORDQYX\n" + + "RqvHvpn8CscB1+oGXZvHwxj4zV0WKoK2zeXkau3vcyl3HIKupJfq2TEACefVjj0t\n" + + "JW+X35PGWp9/H5zIUNVNVjS7Ums84IvKhRB8512PB9UyHagXYVX5GWpAcVpyfrlR\n" + + "FI9Qdhh+Pbk0uyktdbf/CdfgHOoebrTtwRljM0oDtX+2Cv6j0wBK7hD8pPvf1+uy\n" + + "GzczigAU/4Kw7eZqydf9B+5RupR+IZipX41xEiIrKRwqi517WWzXcjaG2cNbf451\n" + + "xpH5PnV3i1tq04jMGQUzFwIDAQABo4GAMH4wHQYDVR0OBBYEFIwX4vs8BiBcScod\n" + + "5noZHRM8E4+iMEIGA1UdIwQ7MDmAFIwX4vs8BiBcScod5noZHRM8E4+ioRakFDAS\n" + + "MRAwDgYDVQQDEwdFQVAgQ0ExggkAguUV3DMtW6swDAYDVR0TBAUwAwEB/zALBgNV\n" + + "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFfQqOTA7Rv7K+luQ7pnas4BYwHE\n" + + "9GEP/uohv6KOy0TGQFbrRTjFoLVNB9BZ1ymMDZ0/TIwIUc7wi7a8t5mEqYH153wW\n" + + "aWooiSjyLLhuI4sNrNCOtisdBq2r2MFXt6h0mAQYOPv8R8K7/fgSxGFqzhyNmmVL\n" + + "1qBJldx34SpwsTALQVPb4hGwJzZfr1PcpEQx6xMnTl8xEWZE3Ms99uaUxbQqIwRu\n" + + "LgAOkNCmY2m89VhzaHJ1uV85AdM/tD+Ysmlnnjt9LRCejbBipjIGjOXrg1JP+lxV\n" + + "muM4vH+P/mlmxsPPz0d65b+EGmJZpoLkO/tdNNvCYzjJpTEWpEsO6NMhKYo=\n" + + "-----END CERTIFICATE-----\n"; + public static final X509Certificate CA_CERT0 = loadCertificate(CA_CERT0_STRING); + + private static final String CA_CERT1_STRING = "-----BEGIN CERTIFICATE-----\n" + + "MIIDKDCCAhCgAwIBAgIJAOM5SzKO2pzCMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" + + "BAMTB0VBUCBDQTAwHhcNMTYwMTEyMDAxMDQ3WhcNMjYwMTA5MDAxMDQ3WjASMRAw\n" + + "DgYDVQQDEwdFQVAgQ0EwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" + + "89ug+IEKVQXnJGKg5g4uVHg6J/8iRUxR5k2eH5o03hrJNMfN2D+cBe/wCiZcnWbI\n" + + "GbGZACWm2nQth2wy9Zgm2LOd3b4ocrHYls3XLq6Qb5Dd7a0JKU7pdGufiNVEkrmF\n" + + "EB+N64wgwH4COTvCiN4erp5kyJwkfqAl2xLkZo0C464c9XoyQOXbmYD9A8v10wZu\n" + + "jyNsEo7Nr2USyw+qhjWSbFbEirP77Tvx+7pJQJwdtk1V9Tn73T2dGF2WHYejei9S\n" + + "mcWpdIUqsu9etYH+zDmtu7I1xlkwiaVsNr2+D+qaCJyOYqrDTKVNK5nmbBPXDWZc\n" + + "NoDbTOoqquX7xONpq9M6jQIDAQABo4GAMH4wHQYDVR0OBBYEFAZ3A2S4qJZZwuNY\n" + + "wkJ6mAdc0gVdMEIGA1UdIwQ7MDmAFAZ3A2S4qJZZwuNYwkJ6mAdc0gVdoRakFDAS\n" + + "MRAwDgYDVQQDEwdFQVAgQ0EwggkA4zlLMo7anMIwDAYDVR0TBAUwAwEB/zALBgNV\n" + + "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHmdMwEhtys4d0E+t7owBmoVR+lU\n" + + "hMCcRtWs8YKX5WIM2kTweT0h/O1xwE1mWmRv/IbDAEb8od4BjAQLhIcolStr2JaO\n" + + "9ZzyxjOnNzqeErh/1DHDbb/moPpqfeJ8YiEz7nH/YU56Q8iCPO7TsgS0sNNE7PfN\n" + + "IUsBW0yHRgpQ4OxWmiZG2YZWiECRzAC0ecPzo59N5iH4vLQIMTMYquiDeMPQnn1e\n" + + "NDGxG8gCtDKIaS6tMg3a28MvWB094pr2ETou8O1C8Ji0Y4hE8QJmSdT7I4+GZjgW\n" + + "g94DZ5RiL7sdp3vC48CXOmeT61YBIvhGUsE1rPhXqkpqQ3Z3C4TFF0jXZZc=\n" + + "-----END CERTIFICATE-----\n"; + public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING); + + + private static X509Certificate loadCertificate(String blob) { + try { + final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + InputStream stream = new ByteArrayInputStream(blob.getBytes(StandardCharsets.UTF_8)); + + return (X509Certificate) certFactory.generateCertificate(stream); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java new file mode 100644 index 0000000000000..0d964b7c92d7f --- /dev/null +++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2016 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 android.net.wifi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNull; + +import android.net.wifi.WifiEnterpriseConfig.Eap; +import android.net.wifi.WifiEnterpriseConfig.Phase2; +import android.os.Parcel; +import android.security.Credentials; +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Before; +import org.junit.Test; + +import java.security.cert.X509Certificate; + + +/** + * Unit tests for {@link android.net.wifi.WifiEnterpriseConfig}. + */ +@SmallTest +public class WifiEnterpriseConfigTest { + // Maintain a ground truth of the keystore uri prefix which is expected by wpa_supplicant. + public static final String KEYSTORE_URI = "keystore://"; + public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE; + public static final String KEYSTORES_URI = "keystores://"; + + private WifiEnterpriseConfig mEnterpriseConfig; + + @Before + public void setUp() throws Exception { + mEnterpriseConfig = new WifiEnterpriseConfig(); + } + + @Test + public void testGetEmptyCaCertificate() { + // A newly-constructed WifiEnterpriseConfig object should have no CA certificate. + assertNull(mEnterpriseConfig.getCaCertificate()); + assertNull(mEnterpriseConfig.getCaCertificates()); + // Setting CA certificate to null explicitly. + mEnterpriseConfig.setCaCertificate(null); + assertNull(mEnterpriseConfig.getCaCertificate()); + // Setting CA certificate to null using setCaCertificates(). + mEnterpriseConfig.setCaCertificates(null); + assertNull(mEnterpriseConfig.getCaCertificates()); + // Setting CA certificate to zero-length array. + mEnterpriseConfig.setCaCertificates(new X509Certificate[0]); + assertNull(mEnterpriseConfig.getCaCertificates()); + } + + @Test + public void testSetGetSingleCaCertificate() { + X509Certificate cert0 = FakeKeys.CA_CERT0; + mEnterpriseConfig.setCaCertificate(cert0); + assertEquals(mEnterpriseConfig.getCaCertificate(), cert0); + } + + @Test + public void testSetGetMultipleCaCertificates() { + X509Certificate cert0 = FakeKeys.CA_CERT0; + X509Certificate cert1 = FakeKeys.CA_CERT1; + mEnterpriseConfig.setCaCertificates(new X509Certificate[] {cert0, cert1}); + X509Certificate[] result = mEnterpriseConfig.getCaCertificates(); + assertEquals(result.length, 2); + assertTrue(result[0] == cert0 && result[1] == cert1); + } + + @Test + public void testSaveSingleCaCertificateAlias() { + final String alias = "single_alias 0"; + mEnterpriseConfig.setCaCertificateAliases(new String[] {alias}); + assertEquals(getCaCertField(), CA_CERT_PREFIX + alias); + } + + @Test + public void testLoadSingleCaCertificateAlias() { + final String alias = "single_alias 1"; + setCaCertField(CA_CERT_PREFIX + alias); + String[] aliases = mEnterpriseConfig.getCaCertificateAliases(); + assertEquals(aliases.length, 1); + assertEquals(aliases[0], alias); + } + + @Test + public void testSaveMultipleCaCertificates() { + final String alias0 = "single_alias 0"; + final String alias1 = "single_alias 1"; + mEnterpriseConfig.setCaCertificateAliases(new String[] {alias0, alias1}); + assertEquals(getCaCertField(), String.format("%s%s %s", + KEYSTORES_URI, + WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0), + WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1))); + } + + @Test + public void testLoadMultipleCaCertificates() { + final String alias0 = "single_alias 0"; + final String alias1 = "single_alias 1"; + setCaCertField(String.format("%s%s %s", + KEYSTORES_URI, + WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0), + WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1))); + String[] aliases = mEnterpriseConfig.getCaCertificateAliases(); + assertEquals(aliases.length, 2); + assertEquals(aliases[0], alias0); + assertEquals(aliases[1], alias1); + } + + private String getCaCertField() { + return mEnterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY); + } + + private void setCaCertField(String value) { + mEnterpriseConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, value); + } + + // Retrieves the value for a specific key supplied to wpa_supplicant. + private class SupplicantConfigExtractor implements WifiEnterpriseConfig.SupplicantSaver { + private String mValue = null; + private String mKey; + + SupplicantConfigExtractor(String key) { + mKey = key; + } + + @Override + public boolean saveValue(String key, String value) { + if (key.equals(mKey)) { + mValue = value; + } + return true; + } + + public String getValue() { + return mValue; + } + } + + private String getSupplicantEapMethod() { + SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor( + WifiEnterpriseConfig.EAP_KEY); + mEnterpriseConfig.saveToSupplicant(entryExtractor); + return entryExtractor.getValue(); + } + + private String getSupplicantPhase2Method() { + SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor( + WifiEnterpriseConfig.PHASE2_KEY); + mEnterpriseConfig.saveToSupplicant(entryExtractor); + return entryExtractor.getValue(); + } + + /** Verifies the default value for EAP outer and inner methods */ + @Test + public void eapInnerDefault() { + assertEquals(null, getSupplicantEapMethod()); + assertEquals(null, getSupplicantPhase2Method()); + } + + /** Verifies that the EAP inner method is reset when we switch to TLS */ + @Test + public void eapPhase2MethodForTls() { + // Initially select an EAP method that supports an phase2. + mEnterpriseConfig.setEapMethod(Eap.PEAP); + mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); + assertEquals("PEAP", getSupplicantEapMethod()); + assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); + + // Change the EAP method to another type which supports a phase2. + mEnterpriseConfig.setEapMethod(Eap.TTLS); + assertEquals("TTLS", getSupplicantEapMethod()); + assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); + + // Change the EAP method to TLS which does not support a phase2. + mEnterpriseConfig.setEapMethod(Eap.TLS); + assertEquals(null, getSupplicantPhase2Method()); + } + + /** Verfies that the EAP inner method is reset when we switch phase2 to NONE */ + @Test + public void eapPhase2None() { + // Initially select an EAP method that supports an phase2. + mEnterpriseConfig.setEapMethod(Eap.PEAP); + mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); + assertEquals("PEAP", getSupplicantEapMethod()); + assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method()); + + // Change the phase2 method to NONE and ensure the value is cleared. + mEnterpriseConfig.setPhase2Method(Phase2.NONE); + assertEquals(null, getSupplicantPhase2Method()); + } + + /** Verfies that the correct "autheap" parameter is supplied for TTLS/GTC. */ + @Test + public void peapGtcToTtls() { + mEnterpriseConfig.setEapMethod(Eap.PEAP); + mEnterpriseConfig.setPhase2Method(Phase2.GTC); + assertEquals("PEAP", getSupplicantEapMethod()); + assertEquals("\"auth=GTC\"", getSupplicantPhase2Method()); + + mEnterpriseConfig.setEapMethod(Eap.TTLS); + assertEquals("TTLS", getSupplicantEapMethod()); + assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); + } + + /** Verfies that the correct "auth" parameter is supplied for PEAP/GTC. */ + @Test + public void ttlsGtcToPeap() { + mEnterpriseConfig.setEapMethod(Eap.TTLS); + mEnterpriseConfig.setPhase2Method(Phase2.GTC); + assertEquals("TTLS", getSupplicantEapMethod()); + assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); + + mEnterpriseConfig.setEapMethod(Eap.PEAP); + assertEquals("PEAP", getSupplicantEapMethod()); + assertEquals("\"auth=GTC\"", getSupplicantPhase2Method()); + } + + /** Verfies that the copy constructor preseves the inner method information. */ + @Test + public void copyConstructor() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(Eap.TTLS); + enterpriseConfig.setPhase2Method(Phase2.GTC); + mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig); + assertEquals("TTLS", getSupplicantEapMethod()); + assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); + } + + /** Verfies that parceling a WifiEnterpriseConfig preseves method information. */ + @Test + public void parcelConstructor() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(Eap.TTLS); + enterpriseConfig.setPhase2Method(Phase2.GTC); + Parcel parcel = Parcel.obtain(); + enterpriseConfig.writeToParcel(parcel, 0); + parcel.setDataPosition(0); // Allow parcel to be read from the beginning. + mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel); + assertEquals("TTLS", getSupplicantEapMethod()); + assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); + } + + /** Verifies proper operation of the getKeyId() method. */ + @Test + public void getKeyId() { + assertEquals("NULL", mEnterpriseConfig.getKeyId(null)); + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(Eap.TTLS); + enterpriseConfig.setPhase2Method(Phase2.GTC); + assertEquals("TTLS_GTC", mEnterpriseConfig.getKeyId(enterpriseConfig)); + mEnterpriseConfig.setEapMethod(Eap.PEAP); + mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); + assertEquals("PEAP_MSCHAPV2", mEnterpriseConfig.getKeyId(enterpriseConfig)); + } + + /** Verifies that passwords are not displayed in toString. */ + @Test + public void passwordNotInToString() { + String password = "supersecret"; + mEnterpriseConfig.setPassword(password); + assertFalse(mEnterpriseConfig.toString().contains(password)); + } +} diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java new file mode 100644 index 0000000000000..a829eb933b592 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 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 android.net.wifi; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.validateMockitoUsage; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.wifi.WifiScanner.BssidInfo; +import android.net.wifi.WifiScanner.BssidListener; +import android.os.Handler; +import android.os.Message; +import android.os.test.TestLooper; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.internal.util.test.BidirectionalAsyncChannelServer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for {@link android.net.wifi.WifiScanner}. + */ +@SmallTest +public class WifiScannerTest { + @Mock + private Context mContext; + @Mock + private IWifiScanner mService; + @Mock + private BssidListener mBssidListener; + + private WifiScanner mWifiScanner; + private TestLooper mLooper; + private Handler mHandler; + + /** + * Setup before tests. + */ + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mLooper = new TestLooper(); + mHandler = mock(Handler.class); + BidirectionalAsyncChannelServer server = new BidirectionalAsyncChannelServer( + mContext, mLooper.getLooper(), mHandler); + when(mService.getMessenger()).thenReturn(server.getMessenger()); + mWifiScanner = new WifiScanner(mContext, mService, mLooper.getLooper()); + mLooper.dispatchAll(); + } + + /** + * Clean up after tests. + */ + @After + public void cleanup() { + validateMockitoUsage(); + } + + private void verifySetHotlistMessage(Handler handler) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture()); + assertEquals("message.what is not CMD_SET_HOTLIST", + WifiScanner.CMD_SET_HOTLIST, + messageCaptor.getValue().what); + } + + /** + * Test duplicate listeners for bssid tracking. + */ + @Test + public void testStartTrackingBssidsDuplicateListeners() throws Exception { + BssidInfo[] bssids = new BssidInfo[] { + new BssidInfo() + }; + + // First start tracking succeeds. + mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener); + mLooper.dispatchAll(); + verifySetHotlistMessage(mHandler); + + // Second start tracking should fail. + mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener); + mLooper.dispatchAll(); + verify(mBssidListener).onFailure(eq(WifiScanner.REASON_DUPLICATE_REQEUST), anyString()); + } +}