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