1 /* 2 * Copyright (C) 2015 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.location; 18 19 import junit.framework.TestCase; 20 21 import android.test.suitebuilder.annotation.SmallTest; 22 23 import java.lang.reflect.Constructor; 24 import java.lang.reflect.Method; 25 import java.util.HashSet; 26 import java.util.Iterator; 27 import java.util.Random; 28 import java.util.Set; 29 30 /** 31 * Unit tests for {@link GpsStatus}. 32 */ 33 @SmallTest 34 public class GpsStatusTest extends TestCase { 35 36 private static final int MAX_VALUE = 250; 37 38 private final Random mRandom = new Random(); 39 40 private GpsStatus mStatus; 41 private int mCount; 42 private int[] mPrns; 43 private float[] mCn0s; 44 private float[] mElevations; 45 private float[] mAzimuth; 46 private int mEphemerisMask; 47 private int mAlmanacMask; 48 private int mUsedInFixMask; 49 50 public void setUp() throws Exception { 51 super.setUp(); 52 mStatus = createGpsStatus(); 53 generateSatellitesData(generateInt()); 54 } 55 56 public void testEmptyGpsStatus() throws Exception { 57 verifyIsEmpty(mStatus); 58 } 59 60 public void testGpsStatusIterator() throws Exception { 61 generateSatellitesData(2); 62 setSatellites(mStatus); 63 Iterator<GpsSatellite> iterator = mStatus.getSatellites().iterator(); 64 assertTrue("hasNext(1)", iterator.hasNext()); 65 assertTrue("hasNext(1) does not overflow", iterator.hasNext()); 66 GpsSatellite satellite1 = iterator.next(); 67 assertNotNull("satellite", satellite1); 68 assertTrue("hasNext(2)", iterator.hasNext()); 69 assertTrue("hasNext(2) does not overflow", iterator.hasNext()); 70 GpsSatellite satellite2 = iterator.next(); 71 assertNotNull("satellite", satellite2); 72 assertFalse("hasNext() no elements", iterator.hasNext()); 73 } 74 75 public void testTtff() throws Exception { 76 int testTtff = generateInt(); 77 set(mStatus, testTtff); 78 verifyTtff(mStatus, testTtff); 79 } 80 81 public void testCopyTtff() throws Exception { 82 int testTtff = generateInt(); 83 verifyTtff(mStatus, 0); 84 85 GpsStatus otherStatus = createGpsStatus(); 86 set(otherStatus, testTtff); 87 verifyTtff(otherStatus, testTtff); 88 89 set(mStatus, otherStatus); 90 verifyTtff(mStatus, testTtff); 91 } 92 93 public void testSetSatellites() throws Exception { 94 setSatellites(mStatus); 95 verifySatellites(mStatus); 96 } 97 98 public void testCopySatellites() throws Exception { 99 verifyIsEmpty(mStatus); 100 101 GpsStatus otherStatus = createGpsStatus(); 102 setSatellites(otherStatus); 103 verifySatellites(otherStatus); 104 105 set(mStatus, otherStatus); 106 verifySatellites(mStatus); 107 } 108 109 public void testOverrideSatellites() throws Exception { 110 setSatellites(mStatus); 111 verifySatellites(mStatus); 112 113 GpsStatus otherStatus = createGpsStatus(); 114 generateSatellitesData(mCount, true /* reusePrns */); 115 setSatellites(otherStatus); 116 verifySatellites(otherStatus); 117 118 set(mStatus, otherStatus); 119 verifySatellites(mStatus); 120 } 121 122 public void testAddSatellites() throws Exception { 123 int count = 10; 124 generateSatellitesData(count); 125 setSatellites(mStatus); 126 verifySatellites(mStatus); 127 128 GpsStatus otherStatus = createGpsStatus(); 129 generateSatellitesData(count); 130 setSatellites(otherStatus); 131 verifySatellites(otherStatus); 132 133 set(mStatus, otherStatus); 134 verifySatellites(mStatus); 135 } 136 137 public void testAddMoreSatellites() throws Exception { 138 int count = 25; 139 generateSatellitesData(count); 140 setSatellites(mStatus); 141 verifySatellites(mStatus); 142 143 GpsStatus otherStatus = createGpsStatus(); 144 generateSatellitesData(count * 2); 145 setSatellites(otherStatus); 146 verifySatellites(otherStatus); 147 148 set(mStatus, otherStatus); 149 verifySatellites(mStatus); 150 } 151 152 public void testAddLessSatellites() throws Exception { 153 int count = 25; 154 generateSatellitesData(count * 2); 155 setSatellites(mStatus); 156 verifySatellites(mStatus); 157 158 GpsStatus otherStatus = createGpsStatus(); 159 generateSatellitesData(count); 160 setSatellites(otherStatus); 161 verifySatellites(otherStatus); 162 163 set(mStatus, otherStatus); 164 verifySatellites(mStatus); 165 } 166 167 private static void verifyIsEmpty(GpsStatus status) { 168 verifySatelliteCount(status, 0); 169 verifyTtff(status, 0); 170 } 171 172 private static void verifySatelliteCount(GpsStatus status, int expectedCount) { 173 int satellites = 0; 174 for (GpsSatellite s : status.getSatellites()) { 175 ++satellites; 176 } 177 assertEquals("GpsStatus::SatelliteCount", expectedCount, satellites); 178 } 179 180 private void verifySatellites(GpsStatus status) { 181 verifySatelliteCount(status, mCount); 182 verifySatellites(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, 183 mAlmanacMask, mUsedInFixMask); 184 } 185 186 private static void verifySatellites( 187 GpsStatus status, 188 int count, 189 int[] prns, 190 float[] cn0s, 191 float[] elevations, 192 float[] azimuth, 193 int ephemerisMask, 194 int almanacMask, 195 int usedInFixMask) { 196 for (int i = 0; i < count; ++i) { 197 int prn = prns[i]; 198 GpsSatellite satellite = getSatellite(status, prn); 199 assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite); 200 assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), cn0s[i], satellite.getSnr()); 201 assertEquals( 202 getSatelliteAssertInfo(i, prn, "Elevation"), 203 elevations[i], 204 satellite.getElevation()); 205 assertEquals( 206 getSatelliteAssertInfo(i, prn, "Azimuth"), 207 azimuth[i], 208 satellite.getAzimuth()); 209 int prnShift = 1 << (prn - 1); 210 assertEquals( 211 getSatelliteAssertInfo(i, prn, "ephemeris"), 212 (ephemerisMask & prnShift) != 0, 213 satellite.hasEphemeris()); 214 assertEquals( 215 getSatelliteAssertInfo(i, prn, "almanac"), 216 (almanacMask & prnShift) != 0, 217 satellite.hasAlmanac()); 218 assertEquals( 219 getSatelliteAssertInfo(i, prn, "usedInFix"), 220 (usedInFixMask & prnShift) != 0, 221 satellite.usedInFix()); 222 } 223 } 224 225 private static void verifyTtff(GpsStatus status, int expectedTtff) { 226 assertEquals("GpsStatus::TTFF", expectedTtff, status.getTimeToFirstFix()); 227 } 228 229 private static GpsStatus createGpsStatus() throws Exception { 230 Constructor<GpsStatus> ctor = GpsStatus.class.getDeclaredConstructor(); 231 ctor.setAccessible(true); 232 return ctor.newInstance(); 233 } 234 235 private static void set(GpsStatus status, int ttff) throws Exception { 236 Class<?> statusClass = status.getClass(); 237 Method setTtff = statusClass.getDeclaredMethod("setTimeToFirstFix", Integer.TYPE); 238 setTtff.setAccessible(true); 239 setTtff.invoke(status, ttff); 240 } 241 242 private static void set(GpsStatus status, GpsStatus statusToSet) throws Exception { 243 Class<?> statusClass = status.getClass(); 244 Method setStatus = statusClass.getDeclaredMethod("setStatus", statusClass); 245 setStatus.setAccessible(true); 246 setStatus.invoke(status, statusToSet); 247 } 248 249 private void setSatellites(GpsStatus status) throws Exception { 250 set(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask, 251 mUsedInFixMask); 252 } 253 254 private static void set( 255 GpsStatus status, 256 int count, 257 int[] prns, 258 float[] cn0s, 259 float[] elevations, 260 float[] azimuth, 261 int ephemerisMask, 262 int almanacMask, 263 int usedInFixMask) throws Exception { 264 Class<?> statusClass = status.getClass(); 265 Class<?> intClass = Integer.TYPE; 266 Class<?> floatArrayClass = Class.forName("[F"); 267 Method setStatus = statusClass.getDeclaredMethod( 268 "setStatus", 269 intClass, 270 Class.forName("[I"), 271 floatArrayClass, 272 floatArrayClass, 273 floatArrayClass, 274 intClass, 275 intClass, 276 intClass); 277 setStatus.setAccessible(true); 278 setStatus.invoke( 279 status, 280 count, 281 prns, 282 cn0s, 283 elevations, 284 azimuth, 285 ephemerisMask, 286 almanacMask, 287 usedInFixMask); 288 } 289 290 private int generateInt() { 291 return mRandom.nextInt(MAX_VALUE) + 1; 292 } 293 294 private int[] generateIntArray(int count) { 295 Set<Integer> generatedPrns = new HashSet<>(); 296 int[] array = new int[count]; 297 for(int i = 0; i < count; ++i) { 298 int generated; 299 do { 300 generated = generateInt(); 301 } while (generatedPrns.contains(generated)); 302 array[i] = generated; 303 generatedPrns.add(generated); 304 } 305 return array; 306 } 307 308 private float[] generateFloatArray(int count) { 309 float[] array = new float[count]; 310 for(int i = 0; i < count; ++i) { 311 array[i] = generateInt(); 312 } 313 return array; 314 } 315 316 private int generateMask(int[] prns) { 317 int mask = 0; 318 int prnsLength = prns.length; 319 for (int i = 0; i < prnsLength; ++i) { 320 if (mRandom.nextBoolean()) { 321 mask |= 1 << (prns[i] - 1); 322 } 323 } 324 return mask; 325 } 326 327 private void generateSatellitesData(int count) { 328 generateSatellitesData(count, false /* reusePrns */); 329 } 330 331 private void generateSatellitesData(int count, boolean reusePrns) { 332 mCount = count; 333 if (!reusePrns) { 334 mPrns = generateIntArray(count); 335 } 336 mCn0s = generateFloatArray(count); 337 mElevations = generateFloatArray(count); 338 mAzimuth = generateFloatArray(count); 339 mEphemerisMask = generateMask(mPrns); 340 mAlmanacMask = generateMask(mPrns); 341 mUsedInFixMask = generateMask(mPrns); 342 } 343 344 private static GpsSatellite getSatellite(GpsStatus status, int prn) { 345 for (GpsSatellite satellite : status.getSatellites()) { 346 if (satellite.getPrn() == prn) { 347 return satellite; 348 } 349 } 350 return null; 351 } 352 353 private static String getSatelliteAssertInfo(int index, int prn, String param) { 354 return String.format("Satellite::%s [i=%d, prn=%d]", param, index, prn); 355 } 356 } 357