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 17 package android.net.wifi; 18 19 import static android.net.wifi.QosCharacteristics.DELIVERY_RATIO_95; 20 import static android.net.wifi.QosCharacteristics.DELIVERY_RATIO_99_9999; 21 22 import static junit.framework.Assert.assertFalse; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertNotEquals; 26 import static org.junit.Assert.assertThrows; 27 import static org.junit.Assert.assertTrue; 28 import static org.junit.Assume.assumeTrue; 29 30 import android.os.Parcel; 31 32 import com.android.modules.utils.build.SdkLevel; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 37 public class QosCharacteristicsTest { 38 private static final int TEST_MIN_SERVICE_INTERVAL_MICROS = 2000; 39 private static final int TEST_MAX_SERVICE_INTERVAL_MICROS = 5000; 40 private static final int TEST_MIN_DATA_RATE_KBPS = 500; 41 private static final int TEST_BURST_SIZE_OCTETS = 2; 42 private static final int TEST_DELAY_BOUND_MICROS = 200; 43 private static final int TEST_MAX_MSDU_SIZE_OCTETS = 4; 44 private static final int TEST_SERVICE_START_TIME_MICROS = 250; 45 private static final int TEST_SERVICE_START_TIME_LINK_ID = 0x5; 46 private static final int TEST_MEAN_DATA_RATE_KBPS = 1500; 47 private static final int TEST_MSDU_LIFETIME_MILLIS = 400; 48 private static final int TEST_DELIVERY_RATIO = QosCharacteristics.DELIVERY_RATIO_99; 49 private static final int TEST_COUNT_EXPONENT = 5; 50 51 @Before setUp()52 public void setUp() { 53 assumeTrue(SdkLevel.isAtLeastV()); 54 } 55 56 /** 57 * Get a Builder with the mandatory fields set to the default test values. 58 */ getDefaultBuilder()59 private static QosCharacteristics.Builder getDefaultBuilder() { 60 return new QosCharacteristics.Builder( 61 TEST_MIN_SERVICE_INTERVAL_MICROS, TEST_MAX_SERVICE_INTERVAL_MICROS, 62 TEST_MIN_DATA_RATE_KBPS, TEST_DELAY_BOUND_MICROS); 63 } 64 65 /** 66 * Get a QosCharacteristics with all fields set to the default test values. 67 */ getDefaultQosCharacteristics()68 private static QosCharacteristics getDefaultQosCharacteristics() { 69 return getDefaultBuilder() 70 .setMaxMsduSizeOctets(TEST_MAX_MSDU_SIZE_OCTETS) 71 .setServiceStartTimeInfo( 72 TEST_SERVICE_START_TIME_MICROS, TEST_SERVICE_START_TIME_LINK_ID) 73 .setMeanDataRateKbps(TEST_MEAN_DATA_RATE_KBPS) 74 .setBurstSizeOctets(TEST_BURST_SIZE_OCTETS) 75 .setMsduLifetimeMillis(TEST_MSDU_LIFETIME_MILLIS) 76 .setMsduDeliveryInfo(TEST_DELIVERY_RATIO, TEST_COUNT_EXPONENT) 77 .build(); 78 } 79 80 /** 81 * Verify that all fields in the QosCharacteristics object contain the default test values. 82 */ validateDefaultFields(QosCharacteristics qosCharacteristics)83 private static void validateDefaultFields(QosCharacteristics qosCharacteristics) { 84 assertEquals(TEST_MIN_SERVICE_INTERVAL_MICROS, 85 qosCharacteristics.getMinServiceIntervalMicros()); 86 assertEquals(TEST_MAX_SERVICE_INTERVAL_MICROS, 87 qosCharacteristics.getMaxServiceIntervalMicros()); 88 assertEquals(TEST_MIN_DATA_RATE_KBPS, qosCharacteristics.getMinDataRateKbps()); 89 assertEquals(TEST_DELAY_BOUND_MICROS, qosCharacteristics.getDelayBoundMicros()); 90 91 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.MAX_MSDU_SIZE)); 92 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.SERVICE_START_TIME)); 93 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.MEAN_DATA_RATE)); 94 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.BURST_SIZE)); 95 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.MSDU_LIFETIME)); 96 assertTrue(qosCharacteristics.containsOptionalField(QosCharacteristics.MSDU_DELIVERY_INFO)); 97 98 assertEquals(TEST_MAX_MSDU_SIZE_OCTETS, qosCharacteristics.getMaxMsduSizeOctets()); 99 assertEquals(TEST_SERVICE_START_TIME_MICROS, 100 qosCharacteristics.getServiceStartTimeMicros()); 101 assertEquals(TEST_SERVICE_START_TIME_LINK_ID, 102 qosCharacteristics.getServiceStartTimeLinkId()); 103 assertEquals(TEST_MEAN_DATA_RATE_KBPS, qosCharacteristics.getMeanDataRateKbps()); 104 assertEquals(TEST_BURST_SIZE_OCTETS, qosCharacteristics.getBurstSizeOctets()); 105 assertEquals(TEST_MSDU_LIFETIME_MILLIS, qosCharacteristics.getMsduLifetimeMillis()); 106 assertEquals(TEST_DELIVERY_RATIO, qosCharacteristics.getDeliveryRatio()); 107 assertEquals(TEST_COUNT_EXPONENT, qosCharacteristics.getCountExponent()); 108 } 109 110 /** 111 * Test that the builder works correctly when provided valid values. 112 */ 113 @Test testBuilderValid()114 public void testBuilderValid() { 115 QosCharacteristics qosCharacteristics = getDefaultQosCharacteristics(); 116 validateDefaultFields(qosCharacteristics); 117 } 118 119 /** 120 * Test that an exception is thrown if any of the mandatory fields are assigned an 121 * invalid value. 122 */ 123 @Test testMandatoryFieldsInvalid()124 public void testMandatoryFieldsInvalid() { 125 // All mandatory fields must be positive. 126 assertThrows(IllegalArgumentException.class, () -> 127 new QosCharacteristics.Builder( 128 0, TEST_MAX_SERVICE_INTERVAL_MICROS, 129 TEST_MIN_DATA_RATE_KBPS, TEST_DELAY_BOUND_MICROS).build()); 130 assertThrows(IllegalArgumentException.class, () -> 131 new QosCharacteristics.Builder( 132 TEST_MIN_SERVICE_INTERVAL_MICROS, 0, 133 TEST_MIN_DATA_RATE_KBPS, TEST_DELAY_BOUND_MICROS).build()); 134 assertThrows(IllegalArgumentException.class, () -> 135 new QosCharacteristics.Builder( 136 TEST_MIN_SERVICE_INTERVAL_MICROS, TEST_MAX_SERVICE_INTERVAL_MICROS, 137 0, TEST_DELAY_BOUND_MICROS).build()); 138 assertThrows(IllegalArgumentException.class, () -> 139 new QosCharacteristics.Builder( 140 TEST_MIN_SERVICE_INTERVAL_MICROS, TEST_MAX_SERVICE_INTERVAL_MICROS, 141 TEST_MIN_DATA_RATE_KBPS, 0).build()); 142 143 // Min service interval must be less than or equal to the max service interval. 144 assertThrows(IllegalArgumentException.class, () -> 145 new QosCharacteristics.Builder( 146 5000 /* minServiceInterval */, 3000 /* maxServiceInterval */, 147 TEST_MIN_DATA_RATE_KBPS, 0).build()); 148 } 149 150 /** 151 * Test that an exception is thrown if any optional values that expect a positive value 152 * are assigned a zero value. 153 */ 154 @Test testOptionalFieldsInvalid_zeroValue()155 public void testOptionalFieldsInvalid_zeroValue() { 156 assertThrows(IllegalArgumentException.class, () -> 157 getDefaultBuilder().setMaxMsduSizeOctets(0).build()); 158 assertThrows(IllegalArgumentException.class, () -> 159 getDefaultBuilder().setMeanDataRateKbps(0).build()); 160 assertThrows(IllegalArgumentException.class, () -> 161 getDefaultBuilder().setBurstSizeOctets(0).build()); 162 assertThrows(IllegalArgumentException.class, () -> 163 getDefaultBuilder().setMsduLifetimeMillis(0).build()); 164 } 165 166 /** 167 * Test that an exception is thrown if any optional values that expect a <32-bit value are 168 * assigned a value that exceeds the expected bit size. 169 */ 170 @Test testOptionalFieldsInvalid_exceedUpperBound()171 public void testOptionalFieldsInvalid_exceedUpperBound() { 172 // Expects 16-bit value 173 assertThrows(IllegalArgumentException.class, () -> 174 getDefaultBuilder().setMaxMsduSizeOctets(0x1FFFF).build()); 175 176 // Expects 16-bit value 177 assertThrows(IllegalArgumentException.class, () -> 178 getDefaultBuilder().setMsduLifetimeMillis(0x1FFFF).build()); 179 180 // Expects 4-bit link ID 181 assertThrows(IllegalArgumentException.class, () -> 182 getDefaultBuilder() 183 .setServiceStartTimeInfo(TEST_SERVICE_START_TIME_MICROS, 0x1F).build()); 184 } 185 186 /** 187 * Test that an exception is thrown if any additional constraints on the optional fields 188 * are broken. 189 */ 190 @Test testOptionalFieldsInvalid_additionalConstraints()191 public void testOptionalFieldsInvalid_additionalConstraints() { 192 // MSDU lifetime should be >= the delay bound 193 int delayBoundUs = 30_000; // 30 ms 194 int msduLifetimeMs = 20; 195 assertThrows(IllegalArgumentException.class, () -> 196 new QosCharacteristics.Builder( 197 TEST_MIN_SERVICE_INTERVAL_MICROS, TEST_MAX_SERVICE_INTERVAL_MICROS, 198 TEST_MIN_DATA_RATE_KBPS, delayBoundUs) 199 .setMsduLifetimeMillis(msduLifetimeMs) 200 .build()); 201 202 // MSDU delivery ratio should be a valid enum 203 assertThrows(IllegalArgumentException.class, () -> 204 getDefaultBuilder() 205 .setMsduDeliveryInfo(DELIVERY_RATIO_95 - 1, TEST_COUNT_EXPONENT) 206 .build()); 207 assertThrows(IllegalArgumentException.class, () -> 208 getDefaultBuilder() 209 .setMsduDeliveryInfo(DELIVERY_RATIO_99_9999 + 1, TEST_COUNT_EXPONENT) 210 .build()); 211 212 // MSDU count exponent should be between 0 and 15 (inclusive) 213 assertThrows(IllegalArgumentException.class, () -> 214 getDefaultBuilder() 215 .setMsduDeliveryInfo(TEST_DELIVERY_RATIO, -1) 216 .build()); 217 assertThrows(IllegalArgumentException.class, () -> 218 getDefaultBuilder() 219 .setMsduDeliveryInfo(TEST_DELIVERY_RATIO, 16) 220 .build()); 221 } 222 223 /** 224 * Test that an exception is thrown if the caller attempts to get an optional field 225 * that was not assigned a value. 226 */ 227 @Test testOptionalFields_unsetException()228 public void testOptionalFields_unsetException() { 229 assertThrows(IllegalStateException.class, () -> 230 getDefaultBuilder().build().getMaxMsduSizeOctets()); 231 assertThrows(IllegalStateException.class, () -> 232 getDefaultBuilder().build().getServiceStartTimeMicros()); 233 assertThrows(IllegalStateException.class, () -> 234 getDefaultBuilder().build().getServiceStartTimeLinkId()); 235 assertThrows(IllegalStateException.class, () -> 236 getDefaultBuilder().build().getMeanDataRateKbps()); 237 assertThrows(IllegalStateException.class, () -> 238 getDefaultBuilder().build().getBurstSizeOctets()); 239 assertThrows(IllegalStateException.class, () -> 240 getDefaultBuilder().build().getMsduLifetimeMillis()); 241 assertThrows(IllegalStateException.class, () -> 242 getDefaultBuilder().build().getDeliveryRatio()); 243 assertThrows(IllegalStateException.class, () -> 244 getDefaultBuilder().build().getCountExponent()); 245 } 246 247 /** 248 * Tests that the parceling logic can properly read and write from a Parcel. 249 */ 250 @Test testParcelReadWrite()251 public void testParcelReadWrite() { 252 QosCharacteristics qosCharacteristics = getDefaultQosCharacteristics(); 253 Parcel parcel = Parcel.obtain(); 254 qosCharacteristics.writeToParcel(parcel, 0); 255 parcel.setDataPosition(0); // Rewind data position back to the beginning for read. 256 QosCharacteristics unparceledQosCharacteristics = 257 QosCharacteristics.CREATOR.createFromParcel(parcel); 258 validateDefaultFields(unparceledQosCharacteristics); 259 } 260 261 /** 262 * Tests that the overridden equality and hashCode operators properly compare the same object. 263 */ 264 @Test testSameObjectComparison()265 public void testSameObjectComparison() { 266 QosCharacteristics qosCharacteristics1 = getDefaultQosCharacteristics(); 267 QosCharacteristics qosCharacteristics2 = getDefaultQosCharacteristics(); 268 assertTrue(qosCharacteristics1.equals(qosCharacteristics2)); 269 assertEquals(qosCharacteristics1.hashCode(), qosCharacteristics2.hashCode()); 270 } 271 272 /** 273 * Tests that the overridden equality and hashCode operators properly compare different objects. 274 */ 275 @Test testDifferentObjectComparison()276 public void testDifferentObjectComparison() { 277 QosCharacteristics qosCharacteristics1 = getDefaultQosCharacteristics(); 278 QosCharacteristics qosCharacteristics2 = getDefaultBuilder().build(); 279 assertFalse(qosCharacteristics1.equals(qosCharacteristics2)); 280 assertNotEquals(qosCharacteristics1.hashCode(), qosCharacteristics2.hashCode()); 281 } 282 } 283