1 /*
<lambda>null2 * 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
17 package com.android.server
18
19 import android.net.ConnectivityManager
20 import android.net.ConnectivityManager.CALLBACK_AVAILABLE
21 import android.net.ConnectivityManager.CALLBACK_CAP_CHANGED
22 import android.net.ConnectivityManager.CALLBACK_IP_CHANGED
23 import android.os.Build
24 import androidx.test.filters.SmallTest
25 import com.android.testutils.DevSdkIgnoreRule
26 import com.android.testutils.DevSdkIgnoreRunner
27 import java.lang.reflect.Modifier
28 import kotlin.test.assertEquals
29 import kotlin.test.assertFalse
30 import kotlin.test.assertTrue
31 import org.junit.Test
32 import org.junit.runner.RunWith
33
34 private const val TEST_NETID_1 = 123
35
36 // Maximum 16 bits unsigned value
37 private const val TEST_NETID_2 = 0xffff
38
39 @RunWith(DevSdkIgnoreRunner::class)
40 @SmallTest
41 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
42 class CallbackQueueTest {
43 @Test
44 fun testAddCallback() {
45 val cbs = listOf(
46 TEST_NETID_1 to CALLBACK_AVAILABLE,
47 TEST_NETID_2 to CALLBACK_AVAILABLE,
48 TEST_NETID_1 to CALLBACK_CAP_CHANGED,
49 TEST_NETID_1 to CALLBACK_CAP_CHANGED
50 )
51 val queue = CallbackQueue(intArrayOf()).apply {
52 cbs.forEach { addCallback(it.first, it.second) }
53 }
54
55 assertQueueEquals(cbs, queue)
56 }
57
58 @Test
59 fun testHasCallback() {
60 val queue = CallbackQueue(intArrayOf()).apply {
61 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
62 addCallback(TEST_NETID_2, CALLBACK_AVAILABLE)
63 addCallback(TEST_NETID_1, CALLBACK_CAP_CHANGED)
64 addCallback(TEST_NETID_1, CALLBACK_CAP_CHANGED)
65 }
66
67 assertTrue(queue.hasCallback(TEST_NETID_1, CALLBACK_AVAILABLE))
68 assertTrue(queue.hasCallback(TEST_NETID_2, CALLBACK_AVAILABLE))
69 assertTrue(queue.hasCallback(TEST_NETID_1, CALLBACK_CAP_CHANGED))
70
71 assertFalse(queue.hasCallback(TEST_NETID_2, CALLBACK_CAP_CHANGED))
72 assertFalse(queue.hasCallback(1234, CALLBACK_AVAILABLE))
73 assertFalse(queue.hasCallback(TEST_NETID_1, 5678))
74 assertFalse(queue.hasCallback(1234, 5678))
75 }
76
77 @Test
78 fun testRemoveCallbacks() {
79 val queue = CallbackQueue(intArrayOf()).apply {
80 assertFalse(removeCallbacks(TEST_NETID_1, CALLBACK_AVAILABLE))
81 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
82 addCallback(TEST_NETID_1, CALLBACK_CAP_CHANGED)
83 addCallback(TEST_NETID_2, CALLBACK_AVAILABLE)
84 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
85 assertTrue(removeCallbacks(TEST_NETID_1, CALLBACK_AVAILABLE))
86 }
87 assertQueueEquals(listOf(
88 TEST_NETID_1 to CALLBACK_CAP_CHANGED,
89 TEST_NETID_2 to CALLBACK_AVAILABLE
90 ), queue)
91 }
92
93 @Test
94 fun testRemoveCallbacksForNetId() {
95 val queue = CallbackQueue(intArrayOf()).apply {
96 assertFalse(removeCallbacksForNetId(TEST_NETID_2))
97 addCallback(TEST_NETID_2, CALLBACK_AVAILABLE)
98 assertFalse(removeCallbacksForNetId(TEST_NETID_1))
99 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
100 addCallback(TEST_NETID_1, CALLBACK_CAP_CHANGED)
101 addCallback(TEST_NETID_2, CALLBACK_CAP_CHANGED)
102 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
103 addCallback(TEST_NETID_2, CALLBACK_IP_CHANGED)
104 assertTrue(removeCallbacksForNetId(TEST_NETID_2))
105 }
106 assertQueueEquals(listOf(
107 TEST_NETID_1 to CALLBACK_AVAILABLE,
108 TEST_NETID_1 to CALLBACK_CAP_CHANGED,
109 TEST_NETID_1 to CALLBACK_AVAILABLE,
110 ), queue)
111 }
112
113 @Test
114 fun testConstructorFromExistingArray() {
115 val queue1 = CallbackQueue(intArrayOf()).apply {
116 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
117 addCallback(TEST_NETID_2, CALLBACK_AVAILABLE)
118 }
119 val queue2 = CallbackQueue(queue1.minimizedBackingArray)
120 assertQueueEquals(listOf(
121 TEST_NETID_1 to CALLBACK_AVAILABLE,
122 TEST_NETID_2 to CALLBACK_AVAILABLE
123 ), queue2)
124 }
125
126 @Test
127 fun testToString() {
128 assertEquals("[]", CallbackQueue(intArrayOf()).toString())
129 assertEquals(
130 "[CALLBACK_AVAILABLE($TEST_NETID_1)]",
131 CallbackQueue(intArrayOf()).apply {
132 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
133 }.toString()
134 )
135 assertEquals(
136 "[CALLBACK_AVAILABLE($TEST_NETID_1),CALLBACK_CAP_CHANGED($TEST_NETID_2)]",
137 CallbackQueue(intArrayOf()).apply {
138 addCallback(TEST_NETID_1, CALLBACK_AVAILABLE)
139 addCallback(TEST_NETID_2, CALLBACK_CAP_CHANGED)
140 }.toString()
141 )
142 }
143
144 @Test
145 fun testMaxNetId() {
146 // CallbackQueue assumes netIds are at most 16 bits
147 assertTrue(NetIdManager.MAX_NET_ID <= 0xffff)
148 }
149
150 @Test
151 fun testMaxCallbackId() {
152 // CallbackQueue assumes callback IDs are at most 16 bits.
153 val constants = ConnectivityManager::class.java.declaredFields.filter {
154 Modifier.isStatic(it.modifiers) && Modifier.isFinal(it.modifiers) &&
155 it.name.startsWith("CALLBACK_")
156 }
157 constants.forEach {
158 it.isAccessible = true
159 assertTrue(it.get(null) as Int <= 0xffff)
160 }
161 }
162 }
163
assertQueueEqualsnull164 private fun assertQueueEquals(expected: List<Pair<Int, Int>>, actual: CallbackQueue) {
165 assertEquals(
166 expected.size,
167 actual.length(),
168 "Size mismatch between expected: $expected and actual: $actual"
169 )
170
171 var nextIndex = 0
172 actual.forEach { netId, cbId ->
173 val (expNetId, expCbId) = expected[nextIndex]
174 val msg = "$actual does not match $expected at index $nextIndex"
175 assertEquals(expNetId, netId, msg)
176 assertEquals(expCbId, cbId, msg)
177 nextIndex++
178 }
179 // Ensure forEach iterations and size are consistent
180 assertEquals(expected.size, nextIndex)
181 }
182