Home | History | Annotate | Download | only in location
      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