1 /* 2 * Copyright (C) 2024 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 package android.net.apf 17 18 import android.net.apf.ApfMdnsUtils.extractOffloadReplyRule 19 import android.net.nsd.OffloadEngine 20 import android.net.nsd.OffloadServiceInfo 21 import android.net.nsd.OffloadServiceInfo.Key 22 import android.os.Build 23 import androidx.test.filters.SmallTest 24 import com.android.net.module.util.NetworkStackConstants.TYPE_A 25 import com.android.net.module.util.NetworkStackConstants.TYPE_AAAA 26 import com.android.net.module.util.NetworkStackConstants.TYPE_PTR 27 import com.android.net.module.util.NetworkStackConstants.TYPE_SRV 28 import com.android.net.module.util.NetworkStackConstants.TYPE_TXT 29 import com.android.testutils.DevSdkIgnoreRule 30 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo 31 import com.android.testutils.DevSdkIgnoreRunner 32 import java.io.IOException 33 import kotlin.test.assertContentEquals 34 import kotlin.test.assertFailsWith 35 import kotlin.test.assertTrue 36 import org.junit.Rule 37 import org.junit.Test 38 import org.junit.runner.RunWith 39 40 /** 41 * Tests for Apf mDNS utility functions. 42 */ 43 @RunWith(DevSdkIgnoreRunner::class) 44 @SmallTest 45 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 46 class ApfMdnsUtilsTest { 47 @get:Rule 48 val ignoreRule = DevSdkIgnoreRule() 49 50 private val testServiceName1 = "NsdChat" 51 private val testServiceName2 = "NsdCall" 52 private val testServiceType = "_http._tcp.local" 53 private val testSubType = "tsub" 54 private val testHostName = "Android.local" 55 private val testRawPacket1 = byteArrayOf(1, 2, 3, 4, 5) 56 private val testRawPacket2 = byteArrayOf(6, 7, 8, 9) 57 private val encodedFullServiceName1 = intArrayOf( 58 7, 'N'.code, 'S'.code, 'D'.code, 'C'.code, 'H'.code, 'A'.code, 'T'.code, 59 5, '_'.code, 'H'.code, 'T'.code, 'T'.code, 'P'.code, 60 4, '_'.code, 'T'.code, 'C'.code, 'P'.code, 61 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null62 0, 0).map { it.toByte() }.toByteArray() 63 private val encodedFullServiceName2 = intArrayOf( 64 7, 'N'.code, 'S'.code, 'D'.code, 'C'.code, 'A'.code, 'L'.code, 'L'.code, 65 5, '_'.code, 'H'.code, 'T'.code, 'T'.code, 'P'.code, 66 4, '_'.code, 'T'.code, 'C'.code, 'P'.code, 67 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null68 0, 0).map { it.toByte() }.toByteArray() 69 private val encodedServiceType = intArrayOf( 70 5, '_'.code, 'H'.code, 'T'.code, 'T'.code, 'P'.code, 71 4, '_'.code, 'T'.code, 'C'.code, 'P'.code, 72 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null73 0, 0).map { it.toByte() }.toByteArray() 74 private val encodedServiceTypeWithSub1 = intArrayOf( 75 4, 'T'.code, 'S'.code, 'U'.code, 'B'.code, 76 4, '_'.code, 'S'.code, 'U'.code, 'B'.code, 77 5, '_'.code, 'H'.code, 'T'.code, 'T'.code, 'P'.code, 78 4, '_'.code, 'T'.code, 'C'.code, 'P'.code, 79 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null80 0, 0).map { it.toByte() }.toByteArray() 81 private val encodedServiceTypeWithWildCard = intArrayOf( 82 0xff, 83 4, '_'.code, 'S'.code, 'U'.code, 'B'.code, 84 5, '_'.code, 'H'.code, 'T'.code, 'T'.code, 'P'.code, 85 4, '_'.code, 'T'.code, 'C'.code, 'P'.code, 86 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null87 0, 0).map { it.toByte() }.toByteArray() 88 private val encodedTestHostName = intArrayOf( 89 7, 'A'.code, 'N'.code, 'D'.code, 'R'.code, 'O'.code, 'I'.code, 'D'.code, 90 5, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, <lambda>null91 0, 0).map { it.toByte() }.toByteArray() 92 93 @Test testExtractOffloadReplyRule_noPriorityReturnsEmptySetnull94 fun testExtractOffloadReplyRule_noPriorityReturnsEmptySet() { 95 val info = createOffloadServiceInfo(Int.MAX_VALUE) 96 val rules = extractOffloadReplyRule(listOf(info)) 97 assertTrue(rules.isEmpty()) 98 } 99 100 @Test testExtractOffloadReplyRule_extractRulesWithValidPrioritynull101 fun testExtractOffloadReplyRule_extractRulesWithValidPriority() { 102 val info1 = createOffloadServiceInfo(10) 103 val info2 = createOffloadServiceInfo( 104 11, 105 testServiceName2, 106 listOf("a", "b", "c", "d"), 107 testRawPacket2 108 ) 109 val rules = extractOffloadReplyRule(listOf(info2, info1)) 110 val expectedResult = listOf( 111 MdnsOffloadRule( 112 listOf( 113 MdnsOffloadRule.Matcher(encodedServiceType, TYPE_PTR), 114 MdnsOffloadRule.Matcher(encodedServiceTypeWithSub1, TYPE_PTR), 115 MdnsOffloadRule.Matcher(encodedFullServiceName1, TYPE_SRV), 116 MdnsOffloadRule.Matcher(encodedFullServiceName1, TYPE_TXT), 117 MdnsOffloadRule.Matcher(encodedTestHostName, TYPE_A), 118 MdnsOffloadRule.Matcher(encodedTestHostName, TYPE_AAAA), 119 120 ), 121 testRawPacket1, 122 ), 123 MdnsOffloadRule( 124 listOf( 125 MdnsOffloadRule.Matcher(encodedServiceTypeWithWildCard, TYPE_PTR), 126 MdnsOffloadRule.Matcher(encodedFullServiceName2, TYPE_SRV), 127 MdnsOffloadRule.Matcher(encodedFullServiceName2, TYPE_TXT), 128 129 ), 130 null, 131 ) 132 ) 133 assertContentEquals(expectedResult, rules) 134 } 135 136 @Test testExtractOffloadReplyRule_longLabelThrowsExceptionnull137 fun testExtractOffloadReplyRule_longLabelThrowsException() { 138 val info = createOffloadServiceInfo(10, "a".repeat(256)) 139 assertFailsWith<IOException> { extractOffloadReplyRule(listOf(info)) } 140 } 141 createOffloadServiceInfonull142 private fun createOffloadServiceInfo( 143 priority: Int, 144 serviceName: String = testServiceName1, 145 subTypes: List<String> = listOf(testSubType), 146 rawPacket1: ByteArray = testRawPacket1 147 ): OffloadServiceInfo = OffloadServiceInfo( 148 Key(serviceName, testServiceType), 149 subTypes, 150 testHostName, 151 rawPacket1, 152 priority, 153 OffloadEngine.OFFLOAD_TYPE_REPLY.toLong() 154 ) 155 } 156