javaextensions/location/tsrc/vipertest/src/CoordinatesTest.java
branchRCL_3
changeset 18 9ac0a0a7da70
parent 17 0fd27995241b
child 19 71c436fe3ce0
equal deleted inserted replaced
17:0fd27995241b 18:9ac0a0a7da70
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 import javax.microedition.location.*;
       
    18 
       
    19 /*
       
    20  * This suite of testcases tests that:
       
    21  * - Coordinates object can be created and changed
       
    22  * - legal parameters are accepted
       
    23  * - illegal parameters are not accepted
       
    24  */
       
    25 public class CoordinatesTest extends ViperUnitTest
       
    26 {
       
    27     protected double iLat;
       
    28 
       
    29     protected double iLon;
       
    30 
       
    31     protected float iAlt;
       
    32 
       
    33     protected final static float[] LEGAL_ALT_VALUES = { Float.NaN,
       
    34             Float.MAX_VALUE, -Float.MAX_VALUE, Float.MIN_VALUE,
       
    35             Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY
       
    36                                                       };
       
    37 
       
    38     public CoordinatesTest()
       
    39     {
       
    40         super("CoordinatesTest");
       
    41     }
       
    42 
       
    43     protected CoordinatesTest(String s)
       
    44     {
       
    45         super(s);
       
    46     }
       
    47 
       
    48     protected void runTest() throws Throwable
       
    49     {
       
    50         testGoodArguments();
       
    51         testBadArguments();
       
    52         testArgumentsRange();
       
    53 
       
    54         testLocationMathNormal();
       
    55         testLocationMathReverse();
       
    56         testLocationMathShortDistance();
       
    57         testLocationMathPolar();
       
    58         testLocationMathSameCoords();
       
    59         testLocationMathNullCoord();
       
    60 
       
    61         testConvertFromStringBadArguments();
       
    62         testConvertFromString_DD_MM();
       
    63         testConvertFromString_DD_MM_SS();
       
    64 
       
    65         testConvertToStringBadArguments();
       
    66         testConvertToString_DD_MM();
       
    67         testConvertToString_DD_MM_SS();
       
    68 
       
    69         testLocationMathThreadSafe();
       
    70     }
       
    71 
       
    72     void testGoodArguments()
       
    73     {
       
    74         setCurrentTest("testGoodArguments()");
       
    75 
       
    76         // Test some values in allowed range
       
    77         double lat = 57.111111d;
       
    78         double lon = 17.111111d;
       
    79         float alt = 31.111111f;
       
    80 
       
    81         // tests -lat, -lon and -alt too
       
    82         assertReallyGood(lat, lon, alt);
       
    83 
       
    84         // Test some legal values for alt
       
    85         for (int i = 0; i < LEGAL_ALT_VALUES.length; ++i)
       
    86         {
       
    87             assertGood(lat, lon, LEGAL_ALT_VALUES[i]);
       
    88         }
       
    89     }
       
    90 
       
    91     void testBadArguments()
       
    92     {
       
    93         setCurrentTest("testBadArguments()");
       
    94 
       
    95         double lat = 57.111111d;
       
    96         double lon = 17.111111d;
       
    97         float alt = 31.111111f;
       
    98 
       
    99         // Test that NaN is illegal for lat, lon
       
   100         assertBad(Double.NaN, lon, alt);
       
   101         assertBad(lat, Double.NaN, alt);
       
   102         assertBad(Double.NaN, Double.NaN, alt);
       
   103 
       
   104         // Test some more bad values for lat
       
   105         assertBad(Double.MAX_VALUE, lon, alt);
       
   106         assertBad(Double.POSITIVE_INFINITY, lon, alt);
       
   107         assertBad(Double.NEGATIVE_INFINITY, lon, alt);
       
   108 
       
   109         // Test some more bad values for lon
       
   110         assertBad(lat, Double.MAX_VALUE, alt);
       
   111         assertBad(lat, Double.POSITIVE_INFINITY, alt);
       
   112         assertBad(lat, Double.NEGATIVE_INFINITY, alt);
       
   113     }
       
   114 
       
   115     // Tests range of allowed values.
       
   116     void testArgumentsRange()
       
   117     {
       
   118         setCurrentTest("testArgumentsRange()");
       
   119 
       
   120         // Test maximum allowed values
       
   121         double lat = 90.0d;
       
   122         double lon = 179.99999999999d;
       
   123         float alt = Float.POSITIVE_INFINITY;
       
   124         assertGood(lat, lon, alt);
       
   125 
       
   126         // Test minimum allowed values
       
   127         lat = -90.0d;
       
   128         lon = -180.0d;
       
   129         alt = Float.NEGATIVE_INFINITY;
       
   130         assertGood(lat, lon, alt);
       
   131 
       
   132         // Test out of range positive values
       
   133         lat = 0;
       
   134         lon = 0;
       
   135         double badLat = 90.0000000000001d;
       
   136         double badLon = 180.0d;
       
   137 
       
   138         assertBad(badLat, lon, alt);
       
   139         assertBad(lat, badLon, alt);
       
   140         assertBad(badLat, badLon, alt);
       
   141 
       
   142         // Test out of range negative values
       
   143         badLat = -90.000000000001d;
       
   144         badLon = -180.00000000001d;
       
   145 
       
   146         assertBad(badLat, lon, alt);
       
   147         assertBad(lat, badLon, alt);
       
   148         assertBad(badLat, badLon, alt);
       
   149     }
       
   150 
       
   151     // Tests that a 'normal' calculation computes correct results.
       
   152     void testLocationMathNormal() throws Exception
       
   153     {
       
   154         setCurrentTest("testLocationMathNormal()");
       
   155 
       
   156         // Define the expected results
       
   157         float expectedDistance = 407342.9950f; // from www.fai.org
       
   158         float expectedBearing = 33.2208175f; // from www.fai.org
       
   159 
       
   160         checkDistanceAndAzimuth(new Coordinates(57.0, 17.0, -1000.0f),
       
   161                                 new Coordinates(60.0, 21.0, 2000.0f), expectedDistance,
       
   162                                 expectedBearing);
       
   163 
       
   164         // Define the expected results
       
   165         expectedDistance = 6500256.303349322f; // from www.fai.org
       
   166         expectedBearing = 200.08970684975316f; // from www.fai.org
       
   167 
       
   168         checkDistanceAndAzimuth(new Coordinates(57.0, 17.0, -1000.0f),
       
   169                                 new Coordinates(0.0, 0.0, 2000.0f), expectedDistance,
       
   170                                 expectedBearing);
       
   171 
       
   172     }
       
   173 
       
   174     // Tests that the reverse of the 'normal' calculation computes correct
       
   175     void testLocationMathReverse() throws Exception
       
   176     {
       
   177         setCurrentTest("testLocationMathReverse()");
       
   178 
       
   179         // Create two Coordinates object with 'normal' parameters and
       
   180         // check that the computed distance and bearing are correct
       
   181         Coordinates fromCoords = new Coordinates(60.0, 21.0, 2000.0f);
       
   182         Coordinates toCoords = new Coordinates(57.0, 17.0, -1000.0f);
       
   183 
       
   184         // Define the expected results
       
   185         float expectedDistance = (float) 407342.9950; // from www.fai.org
       
   186         float expectedBearing = (float) 216.63292698852845; // from www.fai.org
       
   187 
       
   188         checkDistanceAndAzimuth(fromCoords, toCoords, expectedDistance,
       
   189                                 expectedBearing);
       
   190     }
       
   191 
       
   192     // Tests that a 'normal' calculation computes correct results.
       
   193     void testLocationMathShortDistance() throws Exception
       
   194     {
       
   195         setCurrentTest("testLocationMathNormal2()");
       
   196 
       
   197         // Define the expected results
       
   198         float expectedDistance = 789.11491522f; // from www.fai.org
       
   199         float expectedBearing = 44.96957375f; // from www.fai.org
       
   200 
       
   201         checkDistanceAndAzimuth(new Coordinates(57.0, 17.0, -1000.0f),
       
   202                                 new Coordinates(57.005013, 17.009178, 2000.0f),
       
   203                                 expectedDistance, expectedBearing);
       
   204 
       
   205         checkDistanceAndAzimuth(new Coordinates(0, 0, 0.0f), new Coordinates(0,
       
   206                                 0.00001, 0.0f), 1.11319f, 90.0f);
       
   207     }
       
   208 
       
   209     // Tests that polar values give correct results.
       
   210     void testLocationMathPolar() throws Exception
       
   211     {
       
   212         setCurrentTest("testLocationMathPolar()");
       
   213 
       
   214         Coordinates northPole = new Coordinates(90.0, 0.0, 0.0f);
       
   215         Coordinates southPole = new Coordinates(-90.0, 0.0, 0.0f);
       
   216 
       
   217         // Define the expected results
       
   218         float expectedDistance = 20003931.458622963f; // from www.fai.org
       
   219 
       
   220         checkDistanceAndAzimuth(northPole, southPole, expectedDistance, 180.0f);
       
   221         checkDistanceAndAzimuth(southPole, northPole, expectedDistance, 0.0f);
       
   222     }
       
   223 
       
   224     // Tests that same coordinates doesn't cause exception.
       
   225     void testLocationMathSameCoords() throws Exception
       
   226     {
       
   227         setCurrentTest("testLocationMathSameCoords()");
       
   228 
       
   229         // Expected results
       
   230         float expectedDistance = 0.0f;
       
   231         float expectedBearing = 0.0f;
       
   232 
       
   233         checkDistanceAndAzimuth(new Coordinates(57.0, 17.0, 0.0f),
       
   234                                 new Coordinates(57.0, 17.0, 0.0f), expectedDistance,
       
   235                                 expectedBearing);
       
   236 
       
   237         // Altitude should not be used in distance and azimuth calculation
       
   238         checkDistanceAndAzimuth(new Coordinates(57.0, 17.0, 4000.0f),
       
   239                                 new Coordinates(57.0, 17.0, -1000.0f), expectedDistance,
       
   240                                 expectedBearing);
       
   241 
       
   242         // North pole
       
   243         checkDistanceAndAzimuth(new Coordinates(90.0, 10.0, 0.0f),
       
   244                                 new Coordinates(90.0, 10.0, 0.0f), expectedDistance,
       
   245                                 expectedBearing);
       
   246 
       
   247         // South pole
       
   248         checkDistanceAndAzimuth(new Coordinates(-90.0, 10.0, 0.0f),
       
   249                                 new Coordinates(-90.0, 10.0, 0.0f), expectedDistance,
       
   250                                 expectedBearing);
       
   251     }
       
   252 
       
   253     // Tests that a null coordinate causes exception.
       
   254     void testLocationMathNullCoord()
       
   255     {
       
   256         setCurrentTest("testLocationMathNullCoord()");
       
   257 
       
   258         Coordinates fromCoords = new Coordinates(57.0, 17.0, -1000.0f);
       
   259         try
       
   260         {
       
   261             float distance = fromCoords.distance(null);
       
   262             assertTrue(false, "NullPointerException was never thrown");
       
   263         }
       
   264         catch (NullPointerException npe)
       
   265         {
       
   266             // Exception thrown correctly
       
   267             assertTrue(npe.getMessage() == null, "Message not allowed for "
       
   268                        + npe);
       
   269         }
       
   270 
       
   271         try
       
   272         {
       
   273             float azimuth = fromCoords.azimuthTo(null);
       
   274             assertTrue(false, "NullPointerException was never thrown");
       
   275         }
       
   276         catch (NullPointerException npe)
       
   277         {
       
   278             // Exception thrown correctly
       
   279             assertTrue(npe.getMessage() == null, "Message not allowed for "
       
   280                        + npe);
       
   281         }
       
   282     }
       
   283 
       
   284     // Tests that the convert() function works.
       
   285     void testConvertFromStringBadArguments()
       
   286     {
       
   287         setCurrentTest("testConvertFromStringBadArguments()");
       
   288         try
       
   289         {
       
   290             double result = Coordinates.convert(null);
       
   291             assertTrue(false, "NullPointerException was never thrown");
       
   292         }
       
   293         catch (NullPointerException npe)
       
   294         {
       
   295             // Exception thrown correctly
       
   296             assertTrue(npe.getMessage() == null, "Message not allowed for "
       
   297                        + npe);
       
   298         }
       
   299 
       
   300         // Illegal values
       
   301         assertConvertBad("");
       
   302         assertConvertBad("44.44");
       
   303         assertConvertBad("1234");
       
   304         assertConvertBad("123A");
       
   305         assertConvertBad("convertThis!");
       
   306 
       
   307         // DD:MM
       
   308         assertConvertBad(":"); // empty
       
   309         assertConvertBad("a:11"); // Degrees illegal value
       
   310         assertConvertBad("1#:11"); // Degrees illegal value
       
   311         assertConvertBad("a1:11"); // Degrees illegal value
       
   312         assertConvertBad("+90:22"); // Degrees illegal value
       
   313         assertConvertBad("90@:22"); // Degrees illegal value
       
   314         assertConvertBad("1?2:33"); // Degrees illegal value
       
   315         assertConvertBad("-x12:44"); // Degrees illegal value
       
   316         assertConvertBad("01:10"); // starts with 0
       
   317         assertConvertBad("011:11"); // starts with 0
       
   318         assertConvertBad("-09:12"); // starts with -0
       
   319         assertConvertBad("-099:19"); // starts with -0
       
   320         assertConvertBad("180:00"); // >= 180
       
   321         assertConvertBad("-181:01"); // < -180
       
   322         assertConvertBad("-180:59.99999"); // < -180
       
   323         assertConvertBad("60:0"); // Minutes < 10 does not start with 0
       
   324         assertConvertBad("-160:1"); // Minutes < 10 does not start with 0
       
   325         assertConvertBad("70:9.9"); // Minutes < 10 does not start with 0
       
   326         assertConvertBad("20:300"); // Minutes > 59
       
   327         assertConvertBad("-10:60"); // Minutes > 59
       
   328         assertConvertBad("80:-1"); // Minutes < 0
       
   329         assertConvertBad("90:+2"); // Minutes illegal value
       
   330         assertConvertBad("90:?2"); // Minutes illegal value
       
   331         assertConvertBad("80:33+1"); // Minutes illegal value
       
   332         assertConvertBad("90:44;5"); // Minutes illegal value
       
   333         assertConvertBad("-70:12.123456"); // Minutes too many decimals
       
   334 
       
   335         // DD:MM:SS
       
   336         assertConvertBad("::"); // empty
       
   337         assertConvertBad("b:11:11"); // Degrees illegal value
       
   338         assertConvertBad("1$:11:22"); // Degrees illegal value
       
   339         assertConvertBad("c1:11:33"); // Degrees illegal value
       
   340         assertConvertBad("*90:22:44"); // Degrees illegal value
       
   341         assertConvertBad("90!:22:55"); // Degrees illegal value
       
   342         assertConvertBad("1-2:33:01"); // Degrees illegal value
       
   343         assertConvertBad("-z12:44:02"); // Degrees illegal value
       
   344         assertConvertBad(":10:20"); // starts with :
       
   345         assertConvertBad("01:10:20"); // starts with 0
       
   346         assertConvertBad("010:10:21"); // starts with 0
       
   347         assertConvertBad("-09:10:22"); // starts with -0
       
   348         assertConvertBad("-090:10:29"); // starts with -0
       
   349         assertConvertBad("180:00:00"); // >= 180
       
   350         assertConvertBad("280:59:59"); // >= 180
       
   351         assertConvertBad("-181:00:00"); // < -180
       
   352         assertConvertBad("-180:01:00"); // < -180
       
   353         assertConvertBad("-180:00:00.001"); // < -180
       
   354         assertConvertBad("12:3:40"); // Minutes < 10 does not start with 0
       
   355         assertConvertBad("56:07.8:09"); // Minutes has decimals
       
   356         assertConvertBad("31:17.33:12"); // Minutes has decimals
       
   357         assertConvertBad("100:60:10"); // Minutes > 59
       
   358         assertConvertBad("20:300:21"); // Minutes > 59
       
   359         assertConvertBad("-10:60:01"); // Minutes > 59
       
   360         assertConvertBad("80:-1:11"); // Minutes illegal value
       
   361         assertConvertBad("90:?2:22"); // Minutes illegal value
       
   362         assertConvertBad("80:3+:33"); // Minutes illegal value
       
   363         assertConvertBad("90:4;:44"); // Minutes illegal value
       
   364         assertConvertBad("60:10:0"); // Seconds < 10 does not start with 0
       
   365         assertConvertBad("59:59:1"); // Seconds < 10 does not start with 0
       
   366         assertConvertBad("69:49:9.999"); // Seconds < 10 does not start with 0
       
   367         assertConvertBad("89:29:60"); // Seconds > 59.999
       
   368         assertConvertBad("-90:39:60.000"); // Seconds > 59.999
       
   369         assertConvertBad("99:19:100"); // Seconds > 59.999
       
   370         assertConvertBad("10:10:-1"); // Seconds illegal value
       
   371         assertConvertBad("20:20:?2"); // Seconds illegal value
       
   372         assertConvertBad("-123:45.x2"); // Seconds illegal value
       
   373         assertConvertBad("30:30:3+.3"); // Seconds illegal value
       
   374         assertConvertBad("40:40:4;.4"); // Seconds illegal value
       
   375         assertConvertBad("-80:01:31..97"); // Seconds illegal value
       
   376         assertConvertBad("9:09:12.1234"); // Seconds too many decimals
       
   377         assertConvertBad("-70:30:12.3456"); // Seconds too many decimals
       
   378     }
       
   379 
       
   380     // Tests that the convert() function works.
       
   381     void testConvertFromString_DD_MM() throws Exception
       
   382     {
       
   383         setCurrentTest("testConvertFromString_DD_MM()");
       
   384 
       
   385         // All legal values that should be equal to zero
       
   386         String[] zeroValues = { "0:00", "0:00.0", "0:00.00", "0:00.000",
       
   387                                 "0:00.0000", "0:00.00000", "-0:00", "-0:00.0", "-0:00.00",
       
   388                                 "-0:00.000", "-0:00.0000", "-0:00.00000"
       
   389                               };
       
   390 
       
   391         for (int i = 0; i < zeroValues.length; ++i)
       
   392         {
       
   393             double zero = Coordinates.convert(zeroValues[i]);
       
   394             assertTrue(zero == 0d, "Conversion failed for " + zeroValues[i]
       
   395                        + ": " + zero + " != 0");
       
   396         }
       
   397 
       
   398         // Define the input values
       
   399         String[] strings = { "-0:00.06", "-0:30.0", "-0:00.5", "-59:40.4",
       
   400                              "-0:06.666", "0:39.996", "179:59.9994", "61:30.6"
       
   401                            };
       
   402 
       
   403         // Define the expected results
       
   404         double[] expecteds = { -0.0010d, -0.5d, -0.00833d, -59.6733d, -0.1111d,
       
   405                                0.6666d, 179.99999d, 61.51d
       
   406                              };
       
   407 
       
   408         // Define the tolerance
       
   409         double tol = 0.001d;
       
   410 
       
   411         for (int i = 0; i < strings.length; ++i)
       
   412         {
       
   413             double result = Coordinates.convert(strings[i]);
       
   414             assertTrue(Math.abs(expecteds[i] - result) < tol,
       
   415                        "Conversion failed for " + strings[i] + ": " + result
       
   416                        + " != " + expecteds[i]);
       
   417         }
       
   418     }
       
   419 
       
   420     // Tests that the convert() function works.
       
   421     void testConvertFromString_DD_MM_SS() throws Exception
       
   422     {
       
   423         setCurrentTest("testConvertFromString_DD_MM_SS()");
       
   424 
       
   425         // All legal values that should be equal to zero
       
   426         String[] zeroValues = { "0:00:00", "0:00:00.0", "0:00:00.00",
       
   427                                 "0:00:00.000", "-0:00:00", "-0:00:00.0", "-0:00:00.00",
       
   428                                 "-0:00:00.000"
       
   429                               };
       
   430 
       
   431         for (int i = 0; i < zeroValues.length; ++i)
       
   432         {
       
   433             double zero = Coordinates.convert(zeroValues[i]);
       
   434             assertTrue(zero == 0d, "Conversion failed for " + zeroValues[i]
       
   435                        + ": " + zero + " != 0");
       
   436         }
       
   437 
       
   438         // Define the input values
       
   439         String[] strings = { "-0:30:00.0", "-59:40", "-0:06:39.96",
       
   440                              "0:39:59.76", "179:59:59.964", "61:30:36"
       
   441                            };
       
   442 
       
   443         // Define the expected results
       
   444         double[] expecteds = { -0.5d, -59.6667d, -0.1111d, 0.6666d, 179.99999d,
       
   445                                61.51d
       
   446                              };
       
   447 
       
   448         // Define the tolerance
       
   449         double tol = 0.0001d;
       
   450 
       
   451         for (int i = 0; i < strings.length; i++)
       
   452         {
       
   453             double result = Coordinates.convert(strings[i]);
       
   454             assertTrue(Math.abs(expecteds[i] - result) < tol,
       
   455                        "Conversion failed for " + strings[i] + ": " + result
       
   456                        + " != " + expecteds[i]);
       
   457         }
       
   458     }
       
   459 
       
   460     // Tests that the convert() function works.
       
   461     void testConvertToStringBadArguments()
       
   462     {
       
   463         setCurrentTest("testConvertToStringBadArguments()");
       
   464 
       
   465         double[] badCoords = { Double.NaN, Double.MAX_VALUE, -Double.MAX_VALUE,
       
   466                                Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 180.0d,
       
   467                                -180.0001d, 300.99999d
       
   468                              };
       
   469 
       
   470         for (int i = 0; i < badCoords.length; ++i)
       
   471         {
       
   472             assertConvertBad(badCoords[i], Coordinates.DD_MM);
       
   473             assertConvertBad(badCoords[i], Coordinates.DD_MM_SS);
       
   474         }
       
   475     }
       
   476 
       
   477     // Tests that the convert() function works.
       
   478     void testConvertToString_DD_MM()
       
   479     {
       
   480         setCurrentTest("testConvertToString_DD_MM()");
       
   481 
       
   482         double[] coords = { 61.51d, 57.0d, 0.6666d, -0.1111d, 179.99999d,
       
   483                             30.1234567d, 1.333333d, -5.1d, -97.99d, -180.0d, 0.01d, 0.0d,
       
   484                             1.000013d, 80.133602d, 1.666666666666666e-7d, 10.9833333d,
       
   485                             0.999999916666667d
       
   486                           };
       
   487 
       
   488         String[] expected = { "61:30.6", "57:00.0", "0:39.996", "-0:06.666",
       
   489                               "179:59.9994", "30:07.4074", "1:19.99998", "-5:06.0",
       
   490                               "-97:59.4", "-180:00.0", "0:00.6", "0:00.0", "1:00.00078",
       
   491                               "80:08.01612", "0:00.00001", "10:59.0", "1:00.0"
       
   492                             };
       
   493 
       
   494         for (int i = 0; i < coords.length; i++)
       
   495         {
       
   496             String result = Coordinates.convert(coords[i], Coordinates.DD_MM);
       
   497             assertTrue(expected[i].equals(result), "Conversion failed for "
       
   498                        + coords[i] + " (" + result + " != " + expected[i] + ")");
       
   499         }
       
   500     }
       
   501 
       
   502     // Tests that the convert() function works.
       
   503     void testConvertToString_DD_MM_SS()
       
   504     {
       
   505         setCurrentTest("testConvertToString_DD_MM_SS()");
       
   506 
       
   507         double[] coords = { 61.51d, 57.0d, 0.6666d, -0.1111d, 179.99999d,
       
   508                             30.1234567d, 1.333333d, -5.1d, -97.99d, -180.0d,
       
   509                             7.000277777777778d, 0.01d, 0.0d, -179.000002d, -16.4d,
       
   510                             2.777777777777778e-7d, 7.001111d, -8.002222d,
       
   511                             0.999999916666667d
       
   512                           };
       
   513 
       
   514         String[] expected = { "61:30:36.0", "57:00:00.0", "0:39:59.76",
       
   515                               "-0:06:39.96", "179:59:59.964", "30:07:24.444", "1:19:59.999",
       
   516                               "-5:06:00.0", "-97:59:24.0", "-180:00:00.0", "7:00:01.0",
       
   517                               "0:00:36.0", "0:00:00.0", "-179:00:00.007", "-16:24:00.0",
       
   518                               "0:00:00.001", "7:00:04.0", "-8:00:07.999", "1:00:00.0"
       
   519                             };
       
   520 
       
   521         for (int i = 0; i < coords.length; i++)
       
   522         {
       
   523             String result = Coordinates
       
   524                             .convert(coords[i], Coordinates.DD_MM_SS);
       
   525             assertTrue(expected[i].equals(result), "Conversion failed for "
       
   526                        + coords[i] + " (" + result + " != " + expected[i] + ")");
       
   527         }
       
   528     }
       
   529 
       
   530     void testLocationMathThreadSafe() throws InterruptedException
       
   531     {
       
   532         setCurrentTest("testLocationMathThreadSafe()");
       
   533         ThreadSafeTester t2 = new ThreadSafeTester();
       
   534 
       
   535         Coordinates from = new Coordinates(57.0f, 17.0f, 0f);
       
   536         Coordinates to = new Coordinates(60.0f, 21.0f, 0f);
       
   537 
       
   538         t2.start();
       
   539 
       
   540         for (int i = 0; i < 100; i++)
       
   541         {
       
   542             float d = from.distance(to);
       
   543             float a = from.azimuthTo(to);
       
   544             checkDistanceAndAzimuth(from, to, d, a);
       
   545         }
       
   546 
       
   547         t2.join();
       
   548         assertTrue(t2.iSuccess, "Thread t2 produced the wrong result");
       
   549     }
       
   550 
       
   551     private class ThreadSafeTester extends Thread
       
   552     {
       
   553         boolean iSuccess = false;
       
   554 
       
   555         public void run()
       
   556         {
       
   557             Coordinates from = new Coordinates(57.0f, 17.0f, 0f);
       
   558             Coordinates to = new Coordinates(56.0f, 17.0f, 0f);
       
   559             for (int i = 0; i < 100; i++)
       
   560             {
       
   561                 float d = from.distance(to);
       
   562                 float a = from.azimuthTo(to);
       
   563                 checkDistanceAndAzimuth(from, to, d, a);
       
   564             }
       
   565             iSuccess = true;
       
   566         }
       
   567     }
       
   568 
       
   569     // Also used in QualifiedCoordinatesTest
       
   570     protected Coordinates newCoordinates()
       
   571     {
       
   572         return new Coordinates(iLat, iLon, iAlt);
       
   573     }
       
   574 
       
   575     // Also used in QualifiedCoordinatesTest
       
   576     protected Coordinates newZeroCoordinates()
       
   577     {
       
   578         return new Coordinates(0, 0, 0);
       
   579     }
       
   580 
       
   581     //------------------------ Helper methods -----------------------
       
   582 
       
   583     private void assertReallyGood(double lat, double lon, float alt)
       
   584     {
       
   585         assertGood(lat, lon, alt);
       
   586         assertGood(-lat, lon, alt);
       
   587         assertGood(lat, -lon, alt);
       
   588         assertGood(lat, lon, -alt);
       
   589         assertGood(-lat, lon, -alt);
       
   590         assertGood(lat, -lon, -alt);
       
   591         assertGood(-lat, -lon, -alt);
       
   592     }
       
   593 
       
   594     protected void assertGood(double aLat, double aLon, float aAlt)
       
   595     {
       
   596         // Test constructor
       
   597         iLat = aLat;
       
   598         iLon = aLon;
       
   599         iAlt = aAlt;
       
   600         Coordinates coords = newCoordinates();
       
   601 
       
   602         assertTrue(coords.getLatitude() == aLat
       
   603                    && coords.getLongitude() == aLon
       
   604                    && (Float.isNaN(aAlt) ^ coords.getAltitude() == aAlt),
       
   605                    "Coordinates values not equal to constructor input (" + aLat
       
   606                    + "," + aLon + "," + aAlt + ")");
       
   607 
       
   608         // Test setters
       
   609         coords = newZeroCoordinates();
       
   610 
       
   611         try
       
   612         {
       
   613             coords.setLatitude(aLat);
       
   614         }
       
   615         catch (IllegalArgumentException iae)
       
   616         {
       
   617             assertTrue(false, "setLatitude(" + aLat + ") failed");
       
   618         }
       
   619 
       
   620         try
       
   621         {
       
   622             coords.setLongitude(aLon);
       
   623         }
       
   624         catch (IllegalArgumentException iae)
       
   625         {
       
   626             assertTrue(false, "setLongitude(" + aLon + ") failed");
       
   627         }
       
   628 
       
   629         try
       
   630         {
       
   631             coords.setAltitude(aAlt);
       
   632         }
       
   633         catch (IllegalArgumentException iae)
       
   634         {
       
   635             assertTrue(false, "setAtitude(" + aAlt + ") failed");
       
   636         }
       
   637 
       
   638         assertTrue(coords.getLatitude() == aLat
       
   639                    && coords.getLongitude() == aLon
       
   640                    && (Float.isNaN(aAlt) ^ coords.getAltitude() == aAlt),
       
   641                    "Coordinates values not equal to set values (" + aLat + ","
       
   642                    + aLon + "," + aAlt + ")");
       
   643     }
       
   644 
       
   645     protected void assertBad(double aLat, double aLon, float aAlt)
       
   646     {
       
   647         // Test constructor
       
   648         try
       
   649         {
       
   650             iLat = aLat;
       
   651             iLon = aLon;
       
   652             iAlt = aAlt;
       
   653             Coordinates coords = newCoordinates();
       
   654 
       
   655             assertTrue(false, "No exception thrown for constructor (" + aLat
       
   656                        + ", " + aLon + ", " + aAlt + ")");
       
   657         }
       
   658         catch (IllegalArgumentException iae)
       
   659         {
       
   660             // Exception was thrown correctly
       
   661             assertTrue(iae.getMessage() == null, "Message not allowed for "
       
   662                        + iae);
       
   663         }
       
   664 
       
   665         // Test setters
       
   666         Coordinates coords = newZeroCoordinates();
       
   667 
       
   668         try
       
   669         {
       
   670             coords.setLatitude(aLat);
       
   671             coords.setLongitude(aLon);
       
   672             assertTrue(false, "IllegalArgumentException not thrown for setter");
       
   673         }
       
   674         catch (IllegalArgumentException iae)
       
   675         {
       
   676             // Exception was thrown correctly
       
   677             assertTrue(iae.getMessage() == null, "Message not allowed for "
       
   678                        + iae);
       
   679         }
       
   680 
       
   681         // setAltitude should never throw exception
       
   682         coords.setAltitude(aAlt);
       
   683     }
       
   684 
       
   685     private void checkDistanceAndAzimuth(Coordinates aFrom, Coordinates aTo,
       
   686                                          float aExpectedDistance, float aExpectedAzimuth)
       
   687     {
       
   688         // Define the tolerance
       
   689         float distTol = 0.0035f; // Relative error
       
   690         float azTol = 1f; // Absolute error
       
   691 
       
   692         float distance = aFrom.distance(aTo);
       
   693         if (aExpectedDistance != 0.0f)
       
   694         {
       
   695             float distErr = Math.abs((distance - aExpectedDistance)
       
   696                                      / aExpectedDistance);
       
   697 
       
   698             assertTrue(distErr <= distTol, "Computed distance " + distance
       
   699                        + " != " + aExpectedDistance);
       
   700         }
       
   701         else
       
   702         {
       
   703             assertTrue(distance == 0.0f, "Computed distance " + distance
       
   704                        + " != 0.0");
       
   705         }
       
   706 
       
   707         float azimuth = aFrom.azimuthTo(aTo);
       
   708         if (aExpectedAzimuth != 0.0f)
       
   709         {
       
   710             assertTrue(Math.abs(azimuth - aExpectedAzimuth) <= azTol,
       
   711                        "Computed bearing " + azimuth + " != " + aExpectedAzimuth);
       
   712         }
       
   713         else
       
   714         {
       
   715             assertTrue(azimuth == 0.0f, "Computed bearing " + azimuth
       
   716                        + " != 0.0");
       
   717         }
       
   718     }
       
   719 
       
   720     private void assertConvertBad(String aString)
       
   721     {
       
   722         try
       
   723         {
       
   724             double result = Coordinates.convert(aString);
       
   725             assertTrue(false, "No exception thrown for convert(" + aString
       
   726                        + ")");
       
   727         }
       
   728         catch (IllegalArgumentException iae)
       
   729         {
       
   730             // Exception was thrown correctly
       
   731             assertTrue(iae.getMessage() == null, "Message not allowed for "
       
   732                        + iae);
       
   733         }
       
   734     }
       
   735 
       
   736     private void assertConvertBad(double aCoord, int aFormat)
       
   737     {
       
   738         try
       
   739         {
       
   740             String result = Coordinates.convert(aCoord, aFormat);
       
   741             assertTrue(false, "IllegalArgumentException was never thrown");
       
   742         }
       
   743         catch (IllegalArgumentException iae)
       
   744         {
       
   745             // Exception thrown correctly
       
   746             assertTrue(iae.getMessage() == null, "Message not allowed for "
       
   747                        + iae);
       
   748         }
       
   749     }
       
   750 }