1 /* 2 * Copyright (C) 2019 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 17 package com.android.networkstack.metrics 18 19 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR 20 import android.net.captiveportal.CaptivePortalProbeResult 21 import android.net.metrics.ValidationProbeEvent 22 import android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS 23 import android.telephony.TelephonyManager 24 import androidx.test.filters.SmallTest 25 import androidx.test.runner.AndroidJUnit4 26 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession 27 import com.android.dx.mockito.inline.extended.ExtendedMockito.verify 28 import com.android.server.connectivity.nano.CellularData 29 import com.android.server.connectivity.nano.DataStallEventProto 30 import com.android.server.connectivity.nano.DnsEvent 31 import com.google.protobuf.nano.MessageNano 32 import java.util.Arrays 33 import org.junit.Assert.assertEquals 34 import org.junit.Test 35 import org.junit.runner.RunWith 36 import org.mockito.ArgumentMatchers.eq 37 38 @RunWith(AndroidJUnit4::class) 39 @SmallTest 40 class DataStallStatsUtilsTest { 41 private val TEST_ELAPSED_TIME_MS = 123456789L 42 private val TEST_MCCMNC = "123456" 43 private val TEST_SIGNAL_STRENGTH = -100 44 private val RETURN_CODE_DNS_TIMEOUT = 255 45 46 @Test testProbeResultToEnumnull47 fun testProbeResultToEnum() { 48 assertEquals(DataStallStatsUtils.probeResultToEnum(null), DataStallEventProto.INVALID) 49 // Metrics cares only http response code. 50 assertEquals(DataStallStatsUtils.probeResultToEnum( 51 CaptivePortalProbeResult.failed(ValidationProbeEvent.PROBE_HTTP)), 52 DataStallEventProto.INVALID) 53 assertEquals(DataStallStatsUtils.probeResultToEnum( 54 CaptivePortalProbeResult.failed(ValidationProbeEvent.PROBE_HTTPS)), 55 DataStallEventProto.INVALID) 56 assertEquals(DataStallStatsUtils.probeResultToEnum( 57 CaptivePortalProbeResult.success(ValidationProbeEvent.PROBE_HTTP)), 58 DataStallEventProto.VALID) 59 assertEquals(DataStallStatsUtils.probeResultToEnum( 60 CaptivePortalProbeResult.success(ValidationProbeEvent.PROBE_HTTP)), 61 DataStallEventProto.VALID) 62 assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult.PARTIAL), 63 DataStallEventProto.PARTIAL) 64 assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult( 65 CaptivePortalProbeResult.PORTAL_CODE, ValidationProbeEvent.PROBE_HTTP)), 66 DataStallEventProto.PORTAL) 67 assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult( 68 CaptivePortalProbeResult.PORTAL_CODE, ValidationProbeEvent.PROBE_HTTPS)), 69 DataStallEventProto.PORTAL) 70 } 71 72 @Test testWritenull73 fun testWrite() { 74 val session = mockitoSession().spyStatic(NetworkStackStatsLog::class.java).startMocking() 75 val stats = DataStallDetectionStats.Builder() 76 .setEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS) 77 .setNetworkType(TRANSPORT_CELLULAR) 78 .setCellData(TelephonyManager.NETWORK_TYPE_LTE /* radioType */, 79 true /* roaming */, 80 TEST_MCCMNC /* networkMccmnc */, 81 TEST_MCCMNC /* simMccmnc */, 82 TEST_SIGNAL_STRENGTH /* signalStrength */) 83 .setTcpFailRate(90) 84 .setTcpSentSinceLastRecv(10) 85 generateTimeoutDnsEvent(stats, count = 5) 86 DataStallStatsUtils.write(stats.build(), CaptivePortalProbeResult.PARTIAL) 87 88 verify { NetworkStackStatsLog.write( 89 eq(NetworkStackStatsLog.DATA_STALL_EVENT), 90 eq(DATA_STALL_EVALUATION_TYPE_DNS), 91 eq(DataStallEventProto.PARTIAL), 92 eq(TRANSPORT_CELLULAR), 93 eq(DataStallDetectionStats.emptyWifiInfoIfNull(null)), 94 eq(makeTestCellDataNano()), 95 eq(makeTestDnsTimeoutNano(5)), 96 eq(90) /* tcpFailRate */, 97 eq(10) /* tcpSentSinceLastRecv */) } 98 99 session.finishMocking() 100 } 101 makeTestDnsTimeoutNanonull102 private fun makeTestDnsTimeoutNano(timeoutCount: Int): ByteArray? { 103 // Make an expected nano dns message. 104 val event = DnsEvent() 105 event.dnsReturnCode = IntArray(timeoutCount) 106 event.dnsTime = LongArray(timeoutCount) 107 Arrays.fill(event.dnsReturnCode, RETURN_CODE_DNS_TIMEOUT) 108 Arrays.fill(event.dnsTime, TEST_ELAPSED_TIME_MS) 109 return MessageNano.toByteArray(event) 110 } 111 makeTestCellDataNanonull112 private fun makeTestCellDataNano(): ByteArray? { 113 // Make an expected nano cell data message. 114 val data = CellularData() 115 data.ratType = DataStallEventProto.RADIO_TECHNOLOGY_LTE 116 data.networkMccmnc = TEST_MCCMNC 117 data.simMccmnc = TEST_MCCMNC 118 data.isRoaming = true 119 data.signalStrength = TEST_SIGNAL_STRENGTH 120 return MessageNano.toByteArray(data) 121 } 122 generateTimeoutDnsEventnull123 private fun generateTimeoutDnsEvent(stats: DataStallDetectionStats.Builder, count: Int) { 124 repeat(count) { 125 stats.addDnsEvent(RETURN_CODE_DNS_TIMEOUT, TEST_ELAPSED_TIME_MS) 126 } 127 } 128 } 129