/* * Copyright (C) 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.networkstack.metrics import android.net.NetworkCapabilities.TRANSPORT_CELLULAR import android.net.captiveportal.CaptivePortalProbeResult import android.net.metrics.ValidationProbeEvent import android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS import android.telephony.TelephonyManager import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.dx.mockito.inline.extended.ExtendedMockito.verify import com.android.server.connectivity.nano.CellularData import com.android.server.connectivity.nano.DataStallEventProto import com.android.server.connectivity.nano.DnsEvent import com.google.protobuf.nano.MessageNano import java.util.Arrays import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq @RunWith(AndroidJUnit4::class) @SmallTest class DataStallStatsUtilsTest { private val TEST_ELAPSED_TIME_MS = 123456789L private val TEST_MCCMNC = "123456" private val TEST_SIGNAL_STRENGTH = -100 private val RETURN_CODE_DNS_TIMEOUT = 255 @Test fun testProbeResultToEnum() { assertEquals(DataStallStatsUtils.probeResultToEnum(null), DataStallEventProto.INVALID) // Metrics cares only http response code. assertEquals(DataStallStatsUtils.probeResultToEnum( CaptivePortalProbeResult.failed(ValidationProbeEvent.PROBE_HTTP)), DataStallEventProto.INVALID) assertEquals(DataStallStatsUtils.probeResultToEnum( CaptivePortalProbeResult.failed(ValidationProbeEvent.PROBE_HTTPS)), DataStallEventProto.INVALID) assertEquals(DataStallStatsUtils.probeResultToEnum( CaptivePortalProbeResult.success(ValidationProbeEvent.PROBE_HTTP)), DataStallEventProto.VALID) assertEquals(DataStallStatsUtils.probeResultToEnum( CaptivePortalProbeResult.success(ValidationProbeEvent.PROBE_HTTP)), DataStallEventProto.VALID) assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult.PARTIAL), DataStallEventProto.PARTIAL) assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult( CaptivePortalProbeResult.PORTAL_CODE, ValidationProbeEvent.PROBE_HTTP)), DataStallEventProto.PORTAL) assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult( CaptivePortalProbeResult.PORTAL_CODE, ValidationProbeEvent.PROBE_HTTPS)), DataStallEventProto.PORTAL) } @Test fun testWrite() { val session = mockitoSession().spyStatic(NetworkStackStatsLog::class.java).startMocking() val stats = DataStallDetectionStats.Builder() .setEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS) .setNetworkType(TRANSPORT_CELLULAR) .setCellData(TelephonyManager.NETWORK_TYPE_LTE /* radioType */, true /* roaming */, TEST_MCCMNC /* networkMccmnc */, TEST_MCCMNC /* simMccmnc */, TEST_SIGNAL_STRENGTH /* signalStrength */) .setTcpFailRate(90) .setTcpSentSinceLastRecv(10) generateTimeoutDnsEvent(stats, count = 5) DataStallStatsUtils.write(stats.build(), CaptivePortalProbeResult.PARTIAL) verify { NetworkStackStatsLog.write( eq(NetworkStackStatsLog.DATA_STALL_EVENT), eq(DATA_STALL_EVALUATION_TYPE_DNS), eq(DataStallEventProto.PARTIAL), eq(TRANSPORT_CELLULAR), eq(DataStallDetectionStats.emptyWifiInfoIfNull(null)), eq(makeTestCellDataNano()), eq(makeTestDnsTimeoutNano(5)), eq(90) /* tcpFailRate */, eq(10) /* tcpSentSinceLastRecv */) } session.finishMocking() } private fun makeTestDnsTimeoutNano(timeoutCount: Int): ByteArray? { // Make an expected nano dns message. val event = DnsEvent() event.dnsReturnCode = IntArray(timeoutCount) event.dnsTime = LongArray(timeoutCount) Arrays.fill(event.dnsReturnCode, RETURN_CODE_DNS_TIMEOUT) Arrays.fill(event.dnsTime, TEST_ELAPSED_TIME_MS) return MessageNano.toByteArray(event) } private fun makeTestCellDataNano(): ByteArray? { // Make an expected nano cell data message. val data = CellularData() data.ratType = DataStallEventProto.RADIO_TECHNOLOGY_LTE data.networkMccmnc = TEST_MCCMNC data.simMccmnc = TEST_MCCMNC data.isRoaming = true data.signalStrength = TEST_SIGNAL_STRENGTH return MessageNano.toByteArray(data) } private fun generateTimeoutDnsEvent(stats: DataStallDetectionStats.Builder, count: Int) { repeat(count) { stats.addDnsEvent(RETURN_CODE_DNS_TIMEOUT, TEST_ELAPSED_TIME_MS) } } }