mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 17:43:06 +02:00
TrackDetailView: show connected bluetooth device.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for the BootReceiver.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BootReceiverTest {
|
||||
private static final String SERVICE_NAME = "com.google.android.apps.mytracks.services.TrackRecordingService";
|
||||
|
||||
/**
|
||||
* Tests the behavior when receive notification which is the phone boot.
|
||||
*/
|
||||
@Test
|
||||
public void testOnReceive_startService() {
|
||||
// Make sure no TrackRecordingService
|
||||
Intent stopIntent = new Intent(InstrumentationRegistry.getInstrumentation().getContext(), TrackRecordingService.class);
|
||||
InstrumentationRegistry.getInstrumentation().getContext().stopService(stopIntent);
|
||||
Assert.assertFalse(isServiceExisted(InstrumentationRegistry.getInstrumentation().getContext(), SERVICE_NAME));
|
||||
|
||||
BootReceiver bootReceiver = new BootReceiver();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
bootReceiver.onReceive(InstrumentationRegistry.getInstrumentation().getContext(), intent);
|
||||
// Check if the service is started
|
||||
Assert.assertFalse(isServiceExisted(InstrumentationRegistry.getInstrumentation().getContext(), SERVICE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior when receive notification which is not the phone boot.
|
||||
*/
|
||||
@Test
|
||||
public void testOnReceive_noStartService() {
|
||||
// Make sure no TrackRecordingService
|
||||
Intent stopIntent = new Intent(InstrumentationRegistry.getInstrumentation().getContext(), TrackRecordingService.class);
|
||||
InstrumentationRegistry.getInstrumentation().getContext().stopService(stopIntent);
|
||||
Assert.assertFalse(isServiceExisted(InstrumentationRegistry.getInstrumentation().getContext(), SERVICE_NAME));
|
||||
|
||||
BootReceiver bootReceiver = new BootReceiver();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_BUG_REPORT);
|
||||
bootReceiver.onReceive(InstrumentationRegistry.getInstrumentation().getContext(), intent);
|
||||
|
||||
// Check if the service is not started
|
||||
Assert.assertFalse(isServiceExisted(InstrumentationRegistry.getInstrumentation().getContext(), SERVICE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a service is started in a context.
|
||||
*
|
||||
* @param context the context for checking a service
|
||||
* @param serviceName the service name to find if existed
|
||||
*/
|
||||
private boolean isServiceExisted(Context context, String serviceName) {
|
||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(Integer.MAX_VALUE);
|
||||
|
||||
for (int i = 0; i < serviceList.size(); i++) {
|
||||
RunningServiceInfo serviceInfo = serviceList.get(i);
|
||||
ComponentName componentName = serviceInfo.service;
|
||||
if (componentName.getClassName().equals(serviceName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests {@link ChartValueSeries}.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ChartValueSeriesTest {
|
||||
private ChartValueSeries series;
|
||||
|
||||
@Before
|
||||
protected void setUp() {
|
||||
series = new ChartValueSeries(
|
||||
InstrumentationRegistry.getInstrumentation().getContext(),
|
||||
Integer.MIN_VALUE,
|
||||
Integer.MAX_VALUE,
|
||||
new int[] {100, 1000 },
|
||||
R.string.description_elevation_metric,
|
||||
R.string.description_elevation_imperial,
|
||||
R.color.chart_elevation_fill,
|
||||
R.color.chart_elevation_border);
|
||||
}
|
||||
|
||||
public void testInitialConditions() {
|
||||
Assert.assertEquals(1, series.getInterval());
|
||||
Assert.assertEquals(0, series.getMinMarkerValue());
|
||||
Assert.assertEquals(5, series.getMaxMarkerValue());
|
||||
Assert.assertTrue(series.isEnabled());
|
||||
}
|
||||
|
||||
public void testEnabled() {
|
||||
series.setEnabled(false);
|
||||
Assert.assertFalse(series.isEnabled());
|
||||
}
|
||||
|
||||
public void testSmallUpdates() {
|
||||
series.update(0);
|
||||
series.update(10);
|
||||
series.updateDimension();
|
||||
Assert.assertEquals(100, series.getInterval());
|
||||
Assert.assertEquals(0, series.getMinMarkerValue());
|
||||
Assert.assertEquals(500, series.getMaxMarkerValue());
|
||||
}
|
||||
|
||||
public void testBigUpdates() {
|
||||
series.update(0);
|
||||
series.update(901);
|
||||
series.updateDimension();
|
||||
Assert.assertEquals(1000, series.getInterval());
|
||||
Assert.assertEquals(0, series.getMinMarkerValue());
|
||||
Assert.assertEquals(5000, series.getMaxMarkerValue());
|
||||
}
|
||||
|
||||
public void testNotZeroBasedUpdates() {
|
||||
series.update(220);
|
||||
series.update(250);
|
||||
series.updateDimension();
|
||||
Assert.assertEquals(100, series.getInterval());
|
||||
Assert.assertEquals(200, series.getMinMarkerValue());
|
||||
Assert.assertEquals(700, series.getMaxMarkerValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.sensor.Sensor.SensorDataSet;
|
||||
|
||||
/**
|
||||
* Commons utilities for creating stubs of track, location. The class will be
|
||||
* enriched if needs more similar stubs for test.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class TrackStubUtils {
|
||||
|
||||
static final String LOCATION_PROVIDER = "gps";
|
||||
public static final double INITIAL_LATITUDE = 22;
|
||||
public static final double INITIAL_LONGITUDE = 22;
|
||||
public static final double INITIAL_ALTITUDE = 22;
|
||||
static final float INITIAL_ACCURACY = 5;
|
||||
static final float INITIAL_SPEED = 10;
|
||||
public static final long INITIAL_TIME = 1000L;
|
||||
static final float INITIAL_BEARING = 3.0f;
|
||||
// Used to change the value of latitude, longitude, and altitude.
|
||||
static final double DIFFERENCE = 0.01;
|
||||
|
||||
/**
|
||||
* Gets a a {@link Track} stub with specified number of locations.
|
||||
*
|
||||
* @param numberOfLocations the number of locations for the track
|
||||
* @return a track stub.
|
||||
*/
|
||||
public static Track createTrack(int numberOfLocations) {
|
||||
Track track = new Track();
|
||||
for (int i = 0; i < numberOfLocations; i++) {
|
||||
track.addLocation(createMyTracksLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE
|
||||
+ i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE));
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MyTracks location with default values.
|
||||
*
|
||||
* @return a track stub.
|
||||
*/
|
||||
public static MyTracksLocation createMyTracksLocation() {
|
||||
return createMyTracksLocation(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MyTracksLocation} stub with specified values.
|
||||
*
|
||||
* @return a MyTracksLocation stub.
|
||||
*/
|
||||
public static MyTracksLocation createMyTracksLocation(double latitude, double longitude,
|
||||
double altitude) {
|
||||
// Initial Location
|
||||
Location loc = new Location(LOCATION_PROVIDER);
|
||||
loc.setLatitude(latitude);
|
||||
loc.setLongitude(longitude);
|
||||
loc.setAltitude(altitude);
|
||||
loc.setAccuracy(INITIAL_ACCURACY);
|
||||
loc.setSpeed(INITIAL_SPEED);
|
||||
loc.setTime(INITIAL_TIME);
|
||||
loc.setBearing(INITIAL_BEARING);
|
||||
SensorDataSet sd = SensorDataSet.newBuilder().build();
|
||||
|
||||
return new MyTracksLocation(loc, sd);
|
||||
}
|
||||
|
||||
}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link DescriptionGeneratorImpl}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DescriptionGeneratorImplTest {
|
||||
|
||||
private static final long START_TIME = 1288721514000L;
|
||||
private DescriptionGeneratorImpl descriptionGenerator;
|
||||
|
||||
@Before
|
||||
protected void setUp() throws Exception {
|
||||
descriptionGenerator = new DescriptionGeneratorImpl(InstrumentationRegistry.getInstrumentation().getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track,
|
||||
* java.util.Vector, java.util.Vector, boolean)}.
|
||||
*/
|
||||
public void testGenerateTrackDescription() {
|
||||
Track track = new Track();
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(550);
|
||||
stats.setMinElevation(-500);
|
||||
stats.setTotalElevationGain(6000);
|
||||
stats.setMaxGrade(0.42);
|
||||
stats.setMinGrade(0.11);
|
||||
stats.setStartTime(START_TIME);
|
||||
track.setTripStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
String expected = "Created by"
|
||||
+ " <a href='http://www.google.com/mobile/mytracks'>Google My Tracks</a> on Android<p>"
|
||||
+ "Name: -<br>"
|
||||
+ "Activity type: hiking<br>"
|
||||
+ "Description: -<br>"
|
||||
+ "Total distance: 20.00 km (12.4 mi)<br>"
|
||||
+ "Total time: 10:00<br>"
|
||||
+ "Moving time: 05:00<br>"
|
||||
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
|
||||
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
|
||||
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
|
||||
+ "Average pace: 0:30 min/km (0:48 min/mi)<br>"
|
||||
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
|
||||
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
|
||||
+ "Max elevation: 550 m (1804 ft)<br>"
|
||||
+ "Min elevation: -500 m (-1640 ft)<br>"
|
||||
+ "Elevation gain: 6000 m (19685 ft)<br>"
|
||||
+ "Max grade: 42 %<br>"
|
||||
+ "Min grade: 11 %<br>"
|
||||
+ "Recorded: " + StringUtils.formatDateTime(InstrumentationRegistry.getInstrumentation().getContext(), START_TIME) + "<br>";
|
||||
Assert.assertEquals(expected, descriptionGenerator.generateTrackDescription(track, null, null, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#generateWaypointDescription(TripStatistics)}.
|
||||
*/
|
||||
public void testGenerateWaypointDescription() {
|
||||
Waypoint waypoint = new Waypoint();
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(550);
|
||||
stats.setMinElevation(-500);
|
||||
stats.setTotalElevationGain(6000);
|
||||
stats.setMaxGrade(0.42);
|
||||
stats.setMinGrade(0.11);
|
||||
stats.setStartTime(START_TIME);
|
||||
waypoint.setTripStatistics(stats);
|
||||
String expected = "Total distance: 20.00 km (12.4 mi)\n"
|
||||
+ "Total time: 10:00\n"
|
||||
+ "Moving time: 05:00\n"
|
||||
+ "Average speed: 120.00 km/h (74.6 mi/h)\n"
|
||||
+ "Average moving speed: 240.00 km/h (149.1 mi/h)\n"
|
||||
+ "Max speed: 360.00 km/h (223.7 mi/h)\n"
|
||||
+ "Average pace: 0:30 min/km (0:48 min/mi)\n"
|
||||
+ "Average moving pace: 0:15 min/km (0:24 min/mi)\n"
|
||||
+ "Fastest pace: 0:10 min/km (0:16 min/mi)\n"
|
||||
+ "Max elevation: 550 m (1804 ft)\n"
|
||||
+ "Min elevation: -500 m (-1640 ft)\n"
|
||||
+ "Elevation gain: 6000 m (19685 ft)\n"
|
||||
+ "Max grade: 42 %\n"
|
||||
+ "Min grade: 11 %\n"
|
||||
+ "Recorded: " + StringUtils.formatDateTime(InstrumentationRegistry.getInstrumentation().getContext(), START_TIME) + "\n";
|
||||
Assert.assertEquals(
|
||||
expected, descriptionGenerator.generateWaypointDescription(waypoint.getTripStatistics()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteDistance() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeDistance(1100, builder, R.string.description_total_distance, "<br>");
|
||||
Assert.assertEquals("Total distance: 1.10 km (0.7 mi)<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int,
|
||||
* String)}.
|
||||
*/
|
||||
public void testWriteTime() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeTime(1000, builder, R.string.description_total_time, "<br>");
|
||||
Assert.assertEquals("Total time: 00:01<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteSpeed() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeSpeed(1.1, builder, R.string.description_average_speed, "\n");
|
||||
Assert.assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteElevation() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeElevation(4.2, builder, R.string.description_min_elevation, "<br>");
|
||||
Assert.assertEquals("Min elevation: 4 m (14 ft)<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writePace(double, StringBuilder, int,
|
||||
* String)}.
|
||||
*/
|
||||
public void testWritePace() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writePace(1.1, builder, R.string.description_average_pace_in_minute, "\n");
|
||||
Assert.assertEquals("Average pace: 15:09 min/km (24:23 min/mi)\n", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteGrade() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(.042, builder, R.string.description_max_grade, "<br>");
|
||||
Assert.assertEquals("Max grade: 4 %<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)} with a NaN.
|
||||
*/
|
||||
public void testWriteGrade_nan() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(Double.NaN, builder, R.string.description_max_grade, "<br>");
|
||||
Assert.assertEquals("Max grade: 0 %<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)} with an infinite number.
|
||||
*/
|
||||
public void testWriteGrade_infinite() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(
|
||||
Double.POSITIVE_INFINITY, builder, R.string.description_max_grade, "<br>");
|
||||
Assert.assertEquals("Max grade: 0 %<br>", builder.toString());
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider.DatabaseHelper;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MyTracksProviderTest {
|
||||
|
||||
private static final String DATABASE_NAME = "mytrackstest.db";
|
||||
|
||||
private SQLiteDatabase db;
|
||||
private MyTracksProvider myTracksProvider;
|
||||
|
||||
@Before
|
||||
protected void setUp() {
|
||||
InstrumentationRegistry.getInstrumentation().getContext().deleteDatabase(DATABASE_NAME);
|
||||
db = (new DatabaseHelper(InstrumentationRegistry.getInstrumentation().getContext(), DATABASE_NAME)).getWritableDatabase();
|
||||
myTracksProvider = new MyTracksProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onCreate(SQLiteDatabase)}.
|
||||
*/
|
||||
public void testDatabaseHelper_OnCreate() {
|
||||
Assert.assertTrue(hasTable(TracksColumns.TABLE_NAME));
|
||||
Assert.assertTrue(hasTable(TrackPointsColumns.TABLE_NAME));
|
||||
Assert.assertTrue(hasTable(WaypointsColumns.TABLE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider#onCreate(android.content.Context)}.
|
||||
*/
|
||||
public void testOnCreate() {
|
||||
Assert.assertTrue(myTracksProvider.onCreate(InstrumentationRegistry.getInstrumentation().getContext()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider#getType(Uri)}.
|
||||
*/
|
||||
public void testGetType() {
|
||||
Assert.assertEquals(TracksColumns.CONTENT_TYPE, myTracksProvider.getType(TracksColumns.CONTENT_URI));
|
||||
Assert.assertEquals(
|
||||
TrackPointsColumns.CONTENT_TYPE, myTracksProvider.getType(TrackPointsColumns.CONTENT_URI));
|
||||
Assert.assertEquals(
|
||||
WaypointsColumns.CONTENT_TYPE, myTracksProvider.getType(WaypointsColumns.CONTENT_URI));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table, containing one column.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private void createTable(String table) {
|
||||
db.execSQL("CREATE TABLE " + table + " (test INTEGER)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a table in database.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private void dropTable(String table) {
|
||||
db.execSQL("Drop TABLE " + table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the table exists.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private boolean hasTable(String table) {
|
||||
try {
|
||||
db.rawQuery("select count(*) from " + table, null);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the column in the table exists.
|
||||
*
|
||||
* @param table the table name
|
||||
* @param column the column name
|
||||
*/
|
||||
private boolean hasColumn(String table, String column) {
|
||||
try {
|
||||
db.execSQL("SElECT count(*) from " + table + " order by " + column);
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage().indexOf("no such column") > -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up upgrade.
|
||||
*
|
||||
* @param oldVersion thd old database version
|
||||
*/
|
||||
private void setupUpgrade(int oldVersion) {
|
||||
dropTable(TracksColumns.TABLE_NAME);
|
||||
dropTable(TrackPointsColumns.TABLE_NAME);
|
||||
dropTable(WaypointsColumns.TABLE_NAME);
|
||||
createTable(TracksColumns.TABLE_NAME);
|
||||
createTable(TrackPointsColumns.TABLE_NAME);
|
||||
createTable(WaypointsColumns.TABLE_NAME);
|
||||
|
||||
DatabaseHelper databaseHelper = new DatabaseHelper(InstrumentationRegistry.getInstrumentation().getContext());
|
||||
databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION);
|
||||
}
|
||||
}
|
||||
+912
@@ -0,0 +1,912 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A unit test for {@link MyTracksProviderUtilsImpl}.
|
||||
*
|
||||
* @author Bartlomiej Niechwiej
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MyTracksProviderUtilsImplTest {
|
||||
private Context context;
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
|
||||
private static final String NAME_PREFIX = "test name";
|
||||
private static final String MOCK_DESC = "Mock Next Waypoint Desc!";
|
||||
private static final String TEST_DESC = "Test Desc!";
|
||||
private static final String TEST_DESC_NEW = "Test Desc new!";
|
||||
private double INITIAL_LATITUDE = 37.0;
|
||||
private double INITIAL_LONGITUDE = -57.0;
|
||||
private double ALTITUDE_INTERVAL = 2.5;
|
||||
|
||||
@Before
|
||||
protected void setUp() {
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
context = new MockContext(mockContentResolver, targetContext);
|
||||
MyTracksProvider provider = new MyTracksProvider();
|
||||
provider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
providerUtils.deleteAllTracks(context);
|
||||
}
|
||||
|
||||
public void testLocationIterator_noPoints() {
|
||||
testIterator(1, 0, 1, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_customFactory() {
|
||||
final Location location = new Location("test_location");
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
testIterator(1, 15, 4, false, new LocationFactory() {
|
||||
@Override
|
||||
public Location createLocation() {
|
||||
counter.incrementAndGet();
|
||||
return location;
|
||||
}
|
||||
});
|
||||
// Make sure we were called exactly as many times as we had track points.
|
||||
Assert.assertEquals(15, counter.get());
|
||||
}
|
||||
|
||||
public void testLocationIterator_nullFactory() {
|
||||
try {
|
||||
testIterator(1, 15, 4, false, null);
|
||||
fail("Expecting IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
public void testLocationIterator_noBatchAscending() {
|
||||
testIterator(1, 50, 100, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 50, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_noBatchDescending() {
|
||||
testIterator(1, 50, 100, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 50, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_batchAscending() {
|
||||
testIterator(1, 50, 11, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 25, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_batchDescending() {
|
||||
testIterator(1, 50, 11, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 25, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_largeTrack() {
|
||||
testIterator(1, 20000, 2000, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
private List<Location> testIterator(long trackId, int numPoints, int batchSize,
|
||||
boolean descending, LocationFactory locationFactory) {
|
||||
long lastPointId = initializeTrack(trackId, numPoints);
|
||||
((MyTracksProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize);
|
||||
List<Location> locations = new ArrayList<Location>(numPoints);
|
||||
LocationIterator it = providerUtils.getTrackPointLocationIterator(
|
||||
trackId, -1L, descending, locationFactory);
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
Location loc = it.next();
|
||||
Assert.assertNotNull(loc);
|
||||
locations.add(loc);
|
||||
// Make sure the IDs are returned in the right order.
|
||||
Assert.assertEquals(descending ? lastPointId - locations.size() + 1
|
||||
: lastPointId - numPoints + locations.size(), it.getLocationId());
|
||||
}
|
||||
Assert.assertEquals(numPoints, locations.size());
|
||||
} finally {
|
||||
it.close();
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private long initializeTrack(long id, int numPoints) {
|
||||
Track track = new Track();
|
||||
track.setId(id);
|
||||
track.setName("Test: " + id);
|
||||
track.setNumberOfPoints(numPoints);
|
||||
providerUtils.insertTrack(track);
|
||||
track = providerUtils.getTrack(id);
|
||||
Assert.assertNotNull(track);
|
||||
|
||||
Location[] locations = new Location[numPoints];
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(37.0 + (double) i / 10000.0);
|
||||
loc.setLongitude(57.0 - (double) i / 10000.0);
|
||||
loc.setAccuracy((float) i / 100.0f);
|
||||
loc.setAltitude(i * 2.5);
|
||||
locations[i] = loc;
|
||||
}
|
||||
providerUtils.bulkInsertTrackPoint(locations, numPoints, id);
|
||||
|
||||
// Load all inserted locations.
|
||||
long lastPointId = -1;
|
||||
int counter = 0;
|
||||
LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false,
|
||||
MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
lastPointId = it.getLocationId();
|
||||
counter++;
|
||||
}
|
||||
} finally {
|
||||
it.close();
|
||||
}
|
||||
|
||||
Assert.assertTrue(numPoints == 0 || lastPointId > 0);
|
||||
Assert.assertEquals(numPoints, track.getNumberOfPoints());
|
||||
Assert.assertEquals(numPoints, counter);
|
||||
|
||||
return lastPointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createTrack(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateTrack() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
int startColumnIndex = 1;
|
||||
int columnIndex = startColumnIndex;
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns._ID))
|
||||
.andReturn(columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).andReturn(
|
||||
columnIndex++);
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// Name
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
long trackId = System.currentTimeMillis();
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
|
||||
// Name
|
||||
String name = NAME_PREFIX + trackId;
|
||||
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
|
||||
AndroidMock.replay(cursorMock);
|
||||
Track track = providerUtils.createTrack(cursorMock);
|
||||
Assert.assertEquals(trackId, track.getId());
|
||||
Assert.assertEquals(name, track.getName());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#deleteAllTracks(Context)}
|
||||
*/
|
||||
public void testDeleteAllTracks() {
|
||||
// Insert track, points and waypoint at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
Waypoint waypoint = new Waypoint();
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
Assert.assertEquals(1, tracksCursor.getCount());
|
||||
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
Assert.assertEquals(10, tracksPointsCursor.getCount());
|
||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
Assert.assertEquals(1, waypointCursor.getCount());
|
||||
// Delete all.
|
||||
providerUtils.deleteAllTracks(context);
|
||||
// Check whether all have been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
Assert.assertEquals(0, tracksCursor.getCount());
|
||||
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
Assert.assertEquals(0, tracksPointsCursor.getCount());
|
||||
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
Assert.assertEquals(0, waypointCursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#deleteTrack(Context, long)}.
|
||||
*/
|
||||
public void testDeleteTrack() {
|
||||
// Insert three tracks, points of two tracks and way point of one track.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
|
||||
providerUtils.insertTrack(track);
|
||||
insertTrackWithLocations(getTrack(trackId + 1, 10));
|
||||
insertTrackWithLocations(getTrack(trackId + 2, 10));
|
||||
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
Assert.assertEquals(3, tracksCursor.getCount());
|
||||
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
Assert.assertEquals(20, tracksPointsCursor.getCount());
|
||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
Assert.assertEquals(1, waypointCursor.getCount());
|
||||
// Delete one track.
|
||||
providerUtils.deleteTrack(context, trackId);
|
||||
// Check whether all data of a track has been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
Assert.assertEquals(2, tracksCursor.getCount());
|
||||
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
Assert.assertEquals(20, tracksPointsCursor.getCount());
|
||||
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
Assert.assertEquals(0, waypointCursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getAllTracks()}
|
||||
*/
|
||||
public void testGetAllTracks() {
|
||||
int initialTrackNumber = providerUtils.getAllTracks().size();
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
List<Track> allTracks = providerUtils.getAllTracks();
|
||||
Assert.assertEquals(initialTrackNumber + 1, allTracks.size());
|
||||
Assert.assertEquals(trackId, allTracks.get(allTracks.size() - 1).getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrack()}
|
||||
*/
|
||||
public void testGetLastTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
Assert.assertEquals(trackId, providerUtils.getLastTrack().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getTrack(long)}
|
||||
*/
|
||||
public void testGetTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
Assert.assertNotNull(providerUtils.getTrack(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#updateTrack(Track)}
|
||||
*/
|
||||
public void testUpdateTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 0);
|
||||
String nameOld = "name1";
|
||||
String nameNew = "name2";
|
||||
track.setName(nameOld);
|
||||
providerUtils.insertTrack(track);
|
||||
Assert.assertEquals(nameOld, providerUtils.getTrack(trackId).getName());
|
||||
track.setName(nameNew);
|
||||
providerUtils.updateTrack(track);
|
||||
Assert.assertEquals(nameNew, providerUtils.getTrack(trackId).getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createContentValues(Waypoint)}.
|
||||
*/
|
||||
public void testCreateContentValues_waypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
// Bottom
|
||||
long startTime = 1000L;
|
||||
// AverageSpeed
|
||||
double minGrade = -20.11;
|
||||
TripStatistics statistics = new TripStatistics();
|
||||
statistics.setStartTime(startTime);
|
||||
statistics.setStopTime(2500L);
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics.setMovingTime(700L);
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics.setMaxSpeed(60.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(minGrade);
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
// Insert at first.
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setType(WaypointType.STATISTICS);
|
||||
waypoint.setTripStatistics(statistics);
|
||||
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(22);
|
||||
loc.setLongitude(22);
|
||||
loc.setAccuracy((float) 1 / 100.0f);
|
||||
loc.setAltitude(2.5);
|
||||
waypoint.setLocation(loc);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
MyTracksProviderUtilsImpl myTracksProviderUtilsImpl = new MyTracksProviderUtilsImpl(
|
||||
new MockContentResolver());
|
||||
|
||||
long waypointId = System.currentTimeMillis();
|
||||
waypoint.setId(waypointId);
|
||||
ContentValues contentValues = myTracksProviderUtilsImpl.createContentValues(waypoint);
|
||||
Assert.assertEquals(waypointId, contentValues.get(WaypointsColumns._ID));
|
||||
Assert.assertEquals(22 * 1000000, contentValues.get(WaypointsColumns.LONGITUDE));
|
||||
Assert.assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
|
||||
Assert.assertEquals(startTime, contentValues.get(WaypointsColumns.STARTTIME));
|
||||
Assert.assertEquals(minGrade, contentValues.get(WaypointsColumns.MINGRADE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createWaypoint(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateWaypoint() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
int startColumnIndex = 1;
|
||||
int columnIndex = startColumnIndex;
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns._ID))
|
||||
.andReturn(columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.NAME)).andReturn(
|
||||
columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.TRACKID)).andReturn(
|
||||
columnIndex++);
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// Name
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// trackIdIndex
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
long id = System.currentTimeMillis();
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(id);
|
||||
// Name
|
||||
String name = NAME_PREFIX + id;
|
||||
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
|
||||
// trackIdIndex
|
||||
long trackId = 11L;
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
|
||||
AndroidMock.replay(cursorMock);
|
||||
Waypoint waypoint = providerUtils.createWaypoint(cursorMock);
|
||||
Assert.assertEquals(id, waypoint.getId());
|
||||
Assert.assertEquals(name, waypoint.getName());
|
||||
Assert.assertEquals(trackId, waypoint.getTrackId());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)}
|
||||
* when there is only one waypoint in the track.
|
||||
*/
|
||||
public void testDeleteWaypoint_onlyOneWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
// Insert at first.
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setDescription(TEST_DESC);
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
|
||||
// Delete
|
||||
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
|
||||
|
||||
@Override
|
||||
public String generateWaypointDescription(TripStatistics tripStatistics) {
|
||||
return MyTracksProviderUtilsImplTest.MOCK_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
|
||||
Vector<Double> elevations, boolean html) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
providerUtils.deleteWaypoint(context, 1, descriptionGenerator);
|
||||
|
||||
Assert.assertNull(providerUtils.getWaypoint(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)}
|
||||
* when there is more than one waypoint in the track.
|
||||
*/
|
||||
public void testDeleteWaypoint_hasNextWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
TripStatistics statistics = new TripStatistics();
|
||||
statistics.setStartTime(1000L);
|
||||
statistics.setStopTime(2500L);
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics.setMovingTime(700L);
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics.setMaxSpeed(60.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(-25.0);
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
// Insert at first.
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setDescription(Long.toString(trackId));
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setTripStatistics(statistics);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setDescription(Long.toString(trackId));
|
||||
waypoint2.setTrackId(trackId);
|
||||
waypoint2.setType(WaypointType.STATISTICS);
|
||||
waypoint2.setTripStatistics(statistics);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
|
||||
// Delete
|
||||
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
|
||||
@Override
|
||||
public String generateWaypointDescription(TripStatistics tripStatistics) {
|
||||
return MyTracksProviderUtilsImplTest.MOCK_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
|
||||
Vector<Double> elevations, boolean html) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
providerUtils.deleteWaypoint(context, 1, descriptionGenerator);
|
||||
|
||||
Assert.assertNull(providerUtils.getWaypoint(1));
|
||||
Assert.assertEquals(MyTracksProviderUtilsImplTest.MOCK_DESC, providerUtils.getWaypoint(2)
|
||||
.getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstWaypointId(long)}.
|
||||
*/
|
||||
public void testGetFirstWaypointId() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setTrackId(trackId);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
|
||||
Assert.assertEquals(-1L, providerUtils.getFirstWaypointId(-1));
|
||||
Assert.assertEquals(1L, providerUtils.getFirstWaypointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getNextWaypointNumber(long, WaypointType)}.
|
||||
*/
|
||||
public void testGetNextWaypointNumber() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setTrackId(trackId);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setType(WaypointType.WAYPOINT);
|
||||
waypoint2.setTrackId(trackId);
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
waypoint3.setType(WaypointType.STATISTICS);
|
||||
waypoint3.setTrackId(trackId);
|
||||
Waypoint waypoint4 = new Waypoint();
|
||||
waypoint4.setType(WaypointType.WAYPOINT);
|
||||
waypoint4.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
providerUtils.insertWaypoint(waypoint3);
|
||||
providerUtils.insertWaypoint(waypoint4);
|
||||
|
||||
Assert.assertEquals(2, providerUtils.getNextWaypointNumber(trackId, WaypointType.STATISTICS));
|
||||
Assert.assertEquals(3, providerUtils.getNextWaypointNumber(trackId, WaypointType.WAYPOINT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtils#getLastWaypoint(long, WaypointType)}.
|
||||
*/
|
||||
public void testGetLastStatisticsWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setDescription("Desc1");
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setTrackId(trackId);
|
||||
waypoint2.setType(WaypointType.STATISTICS);
|
||||
waypoint2.setDescription("Desc2");
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
waypoint3.setTrackId(trackId);
|
||||
waypoint3.setType(WaypointType.WAYPOINT);
|
||||
waypoint3.setDescription("Desc3");
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
providerUtils.insertWaypoint(waypoint3);
|
||||
|
||||
Assert.assertEquals("Desc2", providerUtils.getLastWaypoint(trackId, WaypointType.STATISTICS).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#insertWaypoint(Waypoint)} and
|
||||
* {@link MyTracksProviderUtilsImpl#getWaypoint(long)}.
|
||||
*/
|
||||
public void testInsertAndGetWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
Assert.assertEquals(TEST_DESC, providerUtils.getWaypoint(1).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#updateWaypoint(Waypoint)}.
|
||||
*/
|
||||
public void testUpdateWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
// Insert at first.
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
// Update
|
||||
waypoint = providerUtils.getWaypoint(1);
|
||||
waypoint.setDescription(TEST_DESC_NEW);
|
||||
providerUtils.updateWaypoint(waypoint);
|
||||
|
||||
Assert.assertEquals(TEST_DESC_NEW, providerUtils.getWaypoint(1).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#bulkInsertTrackPoint(Location[],
|
||||
* int, long)}.
|
||||
*/
|
||||
public void testBulkInsertTrackPoint() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), -1, trackId);
|
||||
Assert.assertEquals(20, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), 8, trackId);
|
||||
Assert.assertEquals(28, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createTrackPoint(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateTrackPoint() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
|
||||
// Set index.
|
||||
int index = 1;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getColumnIndex(TrackPointsColumns._ID)).andReturn(index++);
|
||||
// Longitude
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE)).andReturn(
|
||||
index++);
|
||||
// Latitude
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE)).andReturn(
|
||||
index++);
|
||||
// Time
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.TIME))
|
||||
.andReturn(index++);
|
||||
// Speed
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn(
|
||||
index++);
|
||||
// Sensor
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_HEARTRATE)).andReturn(
|
||||
index++);
|
||||
|
||||
// Set return value of isNull().
|
||||
index = 2;
|
||||
// Longitude
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Latitude
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Time
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Speed
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Sensor
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
|
||||
// Set return value of isNull().
|
||||
index = 2;
|
||||
// Longitude
|
||||
int longitude = 11;
|
||||
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(longitude * 1000000);
|
||||
// Latitude.
|
||||
int latitude = 22;
|
||||
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(latitude * 1000000);
|
||||
// Time
|
||||
long time = System.currentTimeMillis();
|
||||
AndroidMock.expect(cursorMock.getLong(index++)).andReturn(time);
|
||||
// Speed
|
||||
float speed = 2.2f;
|
||||
AndroidMock.expect(cursorMock.getFloat(index++)).andReturn(speed);
|
||||
// Sensor
|
||||
byte[] sensor = "Sensor state".getBytes();
|
||||
AndroidMock.expect(cursorMock.getBlob(index++)).andReturn(sensor);
|
||||
|
||||
AndroidMock.replay(cursorMock);
|
||||
Location location = providerUtils.createTrackPoint(cursorMock);
|
||||
Assert.assertEquals((double) longitude, location.getLongitude());
|
||||
Assert.assertEquals((double) latitude, location.getLatitude());
|
||||
Assert.assertEquals(time, location.getTime());
|
||||
Assert.assertEquals(speed, location.getSpeed());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#insertTrackPoint(Location, long)}.
|
||||
*/
|
||||
public void testInsertTrackPoint() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
providerUtils.insertTrackPoint(createLocation(22), trackId);
|
||||
Assert.assertEquals(11, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstTrackPointId(long)}.
|
||||
*/
|
||||
public void testGetFirstTrackPointId() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Assert.assertEquals(1, providerUtils.getFirstTrackPointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrackPointId(long)}.
|
||||
*/
|
||||
public void testGetLastTrackPointId() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Assert.assertEquals(10, providerUtils.getLastTrackPointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastValidTrackPoint(long)}.
|
||||
*/
|
||||
public void testGetLastValidTrackPoint() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Location lastLocation = providerUtils.getLastValidTrackPoint(trackId);
|
||||
checkLocation(9, lastLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
|
||||
* in descending.
|
||||
*/
|
||||
public void testGetTrackPointCursor_desc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, true);
|
||||
Assert.assertEquals(2, cursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
|
||||
* in ascending.
|
||||
*/
|
||||
public void testGetTrackPointCursor_asc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, false);
|
||||
Assert.assertEquals(5, cursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
|
||||
* in descending.
|
||||
*/
|
||||
public void testGetTrackPointLocationIterator_desc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
long startTrackPointId = 2L;
|
||||
|
||||
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
|
||||
startTrackPointId, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
for (int i = 1; i >= 0; i--) {
|
||||
Assert.assertTrue(locationIterator.hasNext());
|
||||
Location location = locationIterator.next();
|
||||
Assert.assertEquals(2 + (i - 1), locationIterator.getLocationId());
|
||||
checkLocation(i, location);
|
||||
}
|
||||
Assert.assertFalse(locationIterator.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
|
||||
* in ascending.
|
||||
*/
|
||||
public void testGetTrackPointLocationIterator_asc() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
long startTrackPointId = 2L;
|
||||
|
||||
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
|
||||
startTrackPointId, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
Assert.assertTrue(locationIterator.hasNext());
|
||||
Location location = locationIterator.next();
|
||||
Assert.assertEquals(2 + (i - 1), locationIterator.getLocationId());
|
||||
checkLocation(i, location);
|
||||
}
|
||||
Assert.assertFalse(locationIterator.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a track which is used for testing.
|
||||
*
|
||||
* @param id the id of the track
|
||||
* @param numPoints the location number in the track
|
||||
* @return the simulated track
|
||||
*/
|
||||
private Track getTrack(long id,int numPoints) {
|
||||
Track track = new Track();
|
||||
track.setId(id);
|
||||
track.setName("Test: " + id);
|
||||
track.setNumberOfPoints(numPoints);
|
||||
for(int i = 0; i < numPoints; i++) {
|
||||
track.addLocation(createLocation(i));
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a location.
|
||||
* @param i the index to set the value of location.
|
||||
* @return created location
|
||||
*/
|
||||
private Location createLocation(int i) {
|
||||
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
||||
loc.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||
loc.setAccuracy((float) i / 100.0f);
|
||||
loc.setAltitude(i * ALTITUDE_INTERVAL);
|
||||
return loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the value of a location.
|
||||
*
|
||||
* @param i the index of this location which created in the method
|
||||
* {@link MyTracksProviderUtilsImplTest#getTrack(long, int)}
|
||||
* @param location the location to be checked
|
||||
*/
|
||||
private void checkLocation(int i, Location location) {
|
||||
Assert.assertEquals(INITIAL_LATITUDE + (double) i / 10000.0, location.getLatitude());
|
||||
Assert.assertEquals(INITIAL_LONGITUDE - (double) i / 10000.0, location.getLongitude());
|
||||
Assert.assertEquals((float) i / 100.0f, location.getAccuracy());
|
||||
Assert.assertEquals(i * ALTITUDE_INTERVAL, location.getAltitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a track with locations into the database.
|
||||
*
|
||||
* @param track track to be inserted
|
||||
*/
|
||||
private void insertTrackWithLocations(Track track) {
|
||||
providerUtils.insertTrack(track);
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), track
|
||||
.getLocations().size(), track.getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.android.apps.mytracks.content.SearchEngine.ScoredResult;
|
||||
import com.google.android.apps.mytracks.content.SearchEngine.SearchQuery;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for {@link SearchEngine}.
|
||||
* These are not meant to be quality tests, but instead feature-by-feature tests
|
||||
* (in other words, they don't test the mixing of different score boostings, just
|
||||
* each boosting separately)
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SearchEngineTest {
|
||||
|
||||
private static final Location HERE = new Location("gps");
|
||||
private static final long NOW = 1234567890000L; // After OLDEST_ALLOWED_TIMESTAMP
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private SearchEngine engine;
|
||||
|
||||
@Before
|
||||
protected void setUp() {
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
MockContext context = new MockContext(mockContentResolver, targetContext);
|
||||
MyTracksProvider provider = new MyTracksProvider();
|
||||
provider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
engine = new SearchEngine(providerUtils);
|
||||
}
|
||||
|
||||
@After
|
||||
protected void tearDown() throws Exception {
|
||||
providerUtils.deleteAllTracks(getContext());
|
||||
}
|
||||
|
||||
private long insertTrack(String title, String description, String category, double distance, long hoursAgo) {
|
||||
Track track = new Track();
|
||||
track.setName(title);
|
||||
track.setDescription(description);
|
||||
track.setCategory(category);
|
||||
|
||||
TripStatistics stats = track.getTripStatistics();
|
||||
if (hoursAgo > 0) {
|
||||
// Started twice hoursAgo, so the average time is hoursAgo.
|
||||
stats.setStartTime(NOW - hoursAgo * 1000L * 60L * 60L * 2);
|
||||
stats.setStopTime(NOW);
|
||||
}
|
||||
|
||||
int latitude = (int) ((HERE.getLatitude() + distance) * 1E6);
|
||||
int longitude = (int) ((HERE.getLongitude() + distance) * 1E6);
|
||||
stats.setBounds(latitude, longitude, latitude, longitude);
|
||||
|
||||
Uri uri = providerUtils.insertTrack(track);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, String description, String category) {
|
||||
return insertTrack(title, description, category, 0, -1);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, double distance) {
|
||||
return insertTrack(title, "", "", distance, -1);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, long hoursAgo) {
|
||||
return insertTrack(title, "", "", 0.0, hoursAgo);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) {
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setName(title);
|
||||
waypoint.setDescription(description);
|
||||
waypoint.setCategory(category);
|
||||
waypoint.setTrackId(trackId);
|
||||
|
||||
Location location = new Location(HERE);
|
||||
location.setLatitude(location.getLatitude() + distance);
|
||||
location.setLongitude(location.getLongitude() + distance);
|
||||
if (hoursAgo >= 0) {
|
||||
location.setTime(NOW - hoursAgo * 1000L * 60L * 60L);
|
||||
}
|
||||
waypoint.setLocation(location);
|
||||
|
||||
Uri uri = providerUtils.insertWaypoint(waypoint);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, String description, String category) {
|
||||
return insertWaypoint(title, description, category, 0.0, -1, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, double distance) {
|
||||
return insertWaypoint(title, "", "", distance, -1, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, long hoursAgo) {
|
||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, long hoursAgo, long trackId) {
|
||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId);
|
||||
}
|
||||
|
||||
public void testSearchText() {
|
||||
// Insert 7 tracks (purposefully out of result order):
|
||||
// - one which won't match
|
||||
// - one which will match the description
|
||||
// - one which will match the category
|
||||
// - one which will match the title
|
||||
// - one which will match in title and category
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertTrack("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertTrack("bb", "aa", "cc");
|
||||
long categoryMatchId = insertTrack("bb", "cc", "aa");
|
||||
long titleMatchId = insertTrack("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
||||
long allMatchId = insertTrack("aa", "ba", "ca");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertTrackResults(results,
|
||||
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
|
||||
categoryMatchId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointText() {
|
||||
// Insert 7 waypoints (purposefully out of result order):
|
||||
// - one which won't match
|
||||
// - one which will match the description
|
||||
// - one which will match the category
|
||||
// - one which will match the title
|
||||
// - one which will match in title and category
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
||||
long categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
||||
long titleMatchId = insertWaypoint("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
||||
long allMatchId = insertWaypoint("aa", "ba", "ca");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertWaypointResults(results,
|
||||
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
|
||||
categoryMatchId);
|
||||
}
|
||||
|
||||
public void testSearchMixedText() {
|
||||
// Insert 5 entries (purposefully out of result order):
|
||||
// - one waypoint which will match by description
|
||||
// - one waypoint which won't match
|
||||
// - one waypoint which will match by title
|
||||
// - one track which won't match
|
||||
// - one track which will match by title
|
||||
long descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
||||
insertTrack("bb", "cc", "dd");
|
||||
long trackId = insertTrack("aa", "bb", "cc");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertEquals(results.toString(), 3, results.size());
|
||||
assertTrackResult(trackId, results.get(0));
|
||||
assertWaypointResult(titleWaypointId, results.get(1));
|
||||
assertWaypointResult(descriptionWaypointId, results.get(2));
|
||||
}
|
||||
|
||||
public void testSearchTrackDistance() {
|
||||
// All results match text, but they're at difference distances from the user.
|
||||
long farFarAwayId = insertTrack("aa", 0.3);
|
||||
long nearId = insertTrack("ab", 0.1);
|
||||
long farId = insertTrack("ac", 0.2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Distance order.
|
||||
assertTrackResults(results, nearId, farId, farFarAwayId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointDistance() {
|
||||
// All results match text, but they're at difference distances from the user.
|
||||
long farFarAwayId = insertWaypoint("aa", 0.3);
|
||||
long nearId = insertWaypoint("ab", 0.1);
|
||||
long farId = insertWaypoint("ac", 0.2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Distance order.
|
||||
assertWaypointResults(results, nearId, farId, farFarAwayId);
|
||||
}
|
||||
|
||||
public void testSearchTrackRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertTrack("aa", 3);
|
||||
long recentId = insertTrack("ab", 1);
|
||||
long oldId = insertTrack("ac", 2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Reverse time order.
|
||||
assertTrackResults(results, recentId, oldId, oldestId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertWaypoint("aa", 2);
|
||||
long recentId = insertWaypoint("ab", 0);
|
||||
long oldId = insertWaypoint("ac", 1);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Reverse time order.
|
||||
assertWaypointResults(results, recentId, oldId, oldestId);
|
||||
}
|
||||
|
||||
public void testSearchCurrentTrack() {
|
||||
// All results match text, but one of them is the current track.
|
||||
long currentId = insertTrack("ab", 1);
|
||||
long otherId = insertTrack("aa", 1);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Current track should be demoted.
|
||||
assertTrackResults(results, otherId, currentId);
|
||||
}
|
||||
|
||||
public void testSearchCurrentTrackWaypoint() {
|
||||
// All results match text, but one of them is in the current track.
|
||||
long otherId = insertWaypoint("aa", 1, 456);
|
||||
long currentId = insertWaypoint("ab", 1, 123);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, 123, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Waypoint in current track should be promoted.
|
||||
assertWaypointResults(results, currentId, otherId);
|
||||
}
|
||||
|
||||
private void assertTrackResult(long trackId, ScoredResult result) {
|
||||
assertNotNull("Not a track", result.track);
|
||||
assertNull("Ambiguous result", result.waypoint);
|
||||
assertEquals(trackId, result.track.getId());
|
||||
}
|
||||
|
||||
private void assertTrackResults(List<ScoredResult> results, long... trackIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results;
|
||||
assertEquals(results.size(), trackIds.length);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
ScoredResult result = results.get(i);
|
||||
assertNotNull(errMsg, result.track);
|
||||
assertNull(errMsg, result.waypoint);
|
||||
assertEquals(errMsg, trackIds[i], result.track.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertWaypointResult(long waypointId, ScoredResult result) {
|
||||
assertNotNull("Not a waypoint", result.waypoint);
|
||||
assertNull("Ambiguous result", result.track);
|
||||
assertEquals(waypointId, result.waypoint.getId());
|
||||
}
|
||||
|
||||
private void assertWaypointResults(List<ScoredResult> results, long... waypointIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results;
|
||||
assertEquals(results.size(), waypointIds.length);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
ScoredResult result = results.get(i);
|
||||
assertNotNull(errMsg, result.waypoint);
|
||||
assertNull(errMsg, result.track);
|
||||
assertEquals(errMsg, waypointIds[i], result.waypoint.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.location.Location;
|
||||
import android.provider.BaseColumns;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import org.easymock.Capture;
|
||||
import org.easymock.IAnswer;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
import static com.google.android.testing.mocking.AndroidMock.isA;
|
||||
|
||||
/**
|
||||
* Tests for {@link TrackDataHub}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackDataHubTest {
|
||||
|
||||
private static final long TRACK_ID = 42L;
|
||||
private static final int TARGET_POINTS = 50;
|
||||
|
||||
private MockContext context;
|
||||
private SharedPreferences sharedPreferences;
|
||||
private MyTracksProviderUtils myTracksProviderUtils;
|
||||
private DataSource dataSource;
|
||||
private TrackDataManager trackDataManager;
|
||||
private TrackDataHub trackDataHub;
|
||||
private TrackDataListener trackDataListener1;
|
||||
private TrackDataListener trackDataListener2;
|
||||
private Capture<OnSharedPreferenceChangeListener> preferenceChangeListenerCapture = new Capture<
|
||||
SharedPreferences.OnSharedPreferenceChangeListener>();
|
||||
|
||||
@Before
|
||||
@UsesMocks({ MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class })
|
||||
@Override
|
||||
protected void setUp() {
|
||||
context = new MockContext(new MockContentResolver(), new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test."));
|
||||
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
|
||||
dataSource = AndroidMock.createMock(DataSource.class, context);
|
||||
trackDataManager = new TrackDataManager();
|
||||
trackDataHub = new TrackDataHub(
|
||||
context, trackDataManager, myTracksProviderUtils, TARGET_POINTS) {
|
||||
@Override
|
||||
protected DataSource newDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runInHanderThread(Runnable runnable) {
|
||||
// Run everything in the same thread
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
trackDataListener1 = AndroidMock.createStrictMock(
|
||||
"trackDataListener1", TrackDataListener.class);
|
||||
trackDataListener2 = AndroidMock.createStrictMock(
|
||||
"trackDataListener2", TrackDataListener.class);
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, TRACK_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
AndroidMock.reset(dataSource);
|
||||
|
||||
// Expect everything to be unregistered.
|
||||
dataSource.unregisterContentObserver(isA(ContentObserver.class));
|
||||
AndroidMock.expectLastCall().times(3);
|
||||
dataSource.unregisterOnSharedPreferenceChangeListener(
|
||||
isA(OnSharedPreferenceChangeListener.class));
|
||||
AndroidMock.replay(dataSource);
|
||||
|
||||
trackDataHub.stop();
|
||||
trackDataHub = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests registering for tracks table update.
|
||||
*/
|
||||
public void testTracksTableUpdate() {
|
||||
|
||||
// Register two listeners
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
Track track = new Track();
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
dataSource.registerContentObserver(
|
||||
eq(TracksColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Causes tracks table update
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the second listener
|
||||
dataSource.unregisterContentObserver(contentObserver);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener2);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests registering for waypoints table update.
|
||||
*/
|
||||
public void testWaypointsTableUpdate() {
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
Waypoint waypoint4 = new Waypoint();
|
||||
Location location = new Location("gps");
|
||||
location.setLatitude(10.0);
|
||||
location.setLongitude(8.0);
|
||||
waypoint1.setLocation(location);
|
||||
waypoint2.setLocation(location);
|
||||
waypoint3.setLocation(location);
|
||||
waypoint4.setLocation(location);
|
||||
|
||||
// Register two listeners
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(2));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint1).andReturn(waypoint2);
|
||||
dataSource.registerContentObserver(
|
||||
eq(WaypointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener1.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener1.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Cause waypoints table update
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(3));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3);
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener1.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener1.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener1.onNewWaypoint(waypoint3);
|
||||
trackDataListener2.onNewWaypoint(waypoint3);
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(4));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3).andReturn(waypoint4);
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint3);
|
||||
trackDataListener2.onNewWaypoint(waypoint4);
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the second listener
|
||||
dataSource.unregisterContentObserver(contentObserver);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener2);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate() {
|
||||
// Register one listener
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Register a second listener
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Deliver more points - should go to both listeners without clearing
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
locationIterator = new FixedSizeLocationIterator(11, 10, 1);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(20L);
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener and change track
|
||||
locationIterator = new FixedSizeLocationIterator(101, 10);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
|
||||
.andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(110L);
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
trackDataHub.loadTrack(TRACK_ID + 1);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with registering the same listener.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_reRegister() {
|
||||
|
||||
// Register one listener
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the listener
|
||||
ContentObserver observer = contentObserverCapture.getValue();
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
verifyAndReset();
|
||||
|
||||
// Register again
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests tracks point able change. Register a listener after a track change.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_reRegisterAfterTrackChange() {
|
||||
|
||||
// Register one listener
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the listener
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
verifyAndReset();
|
||||
|
||||
// Register the listener after a new track
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
|
||||
.andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.loadTrack(TRACK_ID + 1);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with large track sampling.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_largeTrackSampling() {
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(200L);
|
||||
AndroidMock.expectLastCall().anyTimes();
|
||||
FixedSizeLocationIterator locationIterator1 = new FixedSizeLocationIterator(
|
||||
1, 200, 4, 25, 71, 120);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator1);
|
||||
FixedSizeLocationIterator locationIterator2 = new FixedSizeLocationIterator(
|
||||
1, 200, 4, 25, 71, 120);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator2);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator1.expectSampledLocationsDelivered(trackDataListener1, 4, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator2.expectSampledLocationsDelivered(trackDataListener2, 4, true);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(trackDataListener2, EnumSet.of(
|
||||
TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE, TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with resampling.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_resampling() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
// Deliver 30 points (no sampling happens)
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(30L);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Now deliver 30 more (incrementally sampled)
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
locationIterator = new FixedSizeLocationIterator(31, 30);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(31L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(60L);
|
||||
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
observer.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Now another 30 (triggers resampling)
|
||||
locationIterator = new FixedSizeLocationIterator(1, 90);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(90L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
observer.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests preferences change.
|
||||
*/
|
||||
public void testPreferencesChange() throws Exception {
|
||||
|
||||
// Register two listeners
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_rate_key, PreferencesUtils.STATS_RATE_DEFAULT);
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key,
|
||||
PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
||||
|
||||
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
|
||||
expect(trackDataListener1.onMetricUnitsChanged(true)).andReturn(false);
|
||||
expect(trackDataListener1.onReportSpeedChanged(true)).andReturn(false);
|
||||
expect(
|
||||
trackDataListener1.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT))
|
||||
.andReturn(false);
|
||||
expect(trackDataListener1.onRecordingDistanceIntervalChanged(
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false);
|
||||
expect(trackDataListener1.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false);
|
||||
|
||||
expect(trackDataListener2.onMetricUnitsChanged(true)).andReturn(false);
|
||||
expect(trackDataListener2.onReportSpeedChanged(true)).andReturn(false);
|
||||
expect(
|
||||
trackDataListener2.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT))
|
||||
.andReturn(false);
|
||||
expect(trackDataListener2.onRecordingDistanceIntervalChanged(
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false);
|
||||
expect(trackDataListener2.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false);
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.PREFERENCE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.PREFERENCE));
|
||||
verifyAndReset();
|
||||
|
||||
// Change report speed to false
|
||||
expect(trackDataListener1.onReportSpeedChanged(false)).andReturn(false);
|
||||
expect(trackDataListener2.onReportSpeedChanged(false)).andReturn(false);
|
||||
replay();
|
||||
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_rate_key, context.getString(R.string.stats_rate_pace));
|
||||
OnSharedPreferenceChangeListener listener = preferenceChangeListenerCapture.getValue();
|
||||
listener.onSharedPreferenceChanged(
|
||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_rate_key));
|
||||
verifyAndReset();
|
||||
|
||||
// Change metric units to false
|
||||
expect(trackDataListener1.onMetricUnitsChanged(false)).andReturn(false);
|
||||
expect(trackDataListener2.onMetricUnitsChanged(false)).andReturn(false);
|
||||
replay();
|
||||
|
||||
String imperialUnits = context.getString(R.string.stats_units_imperial);
|
||||
PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits);
|
||||
listener.onSharedPreferenceChanged(
|
||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replays mocks.
|
||||
*/
|
||||
private void replay() {
|
||||
AndroidMock.replay(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies and resets mocks.
|
||||
*/
|
||||
private void verifyAndReset() {
|
||||
AndroidMock.verify(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
AndroidMock.reset(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed size cursor answer.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private static class FixedSizeCursorAnswer implements IAnswer<Cursor> {
|
||||
private final int size;
|
||||
|
||||
public FixedSizeCursorAnswer(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor answer() throws Throwable {
|
||||
MatrixCursor cursor = new MatrixCursor(new String[] { BaseColumns._ID });
|
||||
for (long i = 0; i < size; i++) {
|
||||
cursor.addRow(new Object[] { i });
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed size location iterator.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private static class FixedSizeLocationIterator implements LocationIterator {
|
||||
private final long startId;
|
||||
private final Location[] locations;
|
||||
private final Set<Integer> splitIndexSet = new HashSet<Integer>();
|
||||
private int currentIndex = -1;
|
||||
|
||||
public FixedSizeLocationIterator(long startId, int size) {
|
||||
this(startId, size, null);
|
||||
}
|
||||
|
||||
public FixedSizeLocationIterator(long startId, int size, int... splitIndexes) {
|
||||
this.startId = startId;
|
||||
this.locations = new Location[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Location location = new Location("gps");
|
||||
location.setLatitude(-15.0 + i / 1000.0);
|
||||
location.setLongitude(37 + i / 1000.0);
|
||||
location.setAltitude(i);
|
||||
locations[i] = location;
|
||||
}
|
||||
|
||||
if (splitIndexes != null) {
|
||||
for (int splitIndex : splitIndexes) {
|
||||
splitIndexSet.add(splitIndex);
|
||||
|
||||
Location splitLocation = locations[splitIndex];
|
||||
splitLocation.setLatitude(100.0);
|
||||
splitLocation.setLongitude(200.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void expectLocationsDelivered(TrackDataListener listener) {
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
if (splitIndexSet.contains(i)) {
|
||||
listener.onSegmentSplit(locations[i]);
|
||||
} else {
|
||||
listener.onSampledInTrackPoint(locations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void expectSampledLocationsDelivered(
|
||||
TrackDataListener listener, int sampleFrequency, boolean includeSampledOut) {
|
||||
boolean includeNext = false;
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
if (splitIndexSet.contains(i)) {
|
||||
listener.onSegmentSplit(locations[i]);
|
||||
includeNext = true;
|
||||
} else if (includeNext || (i % sampleFrequency == 0)) {
|
||||
listener.onSampledInTrackPoint(locations[i]);
|
||||
includeNext = false;
|
||||
} else if (includeSampledOut) {
|
||||
listener.onSampledOutTrackPoint(locations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentIndex < locations.length - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location next() {
|
||||
currentIndex++;
|
||||
return locations[currentIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLocationId() {
|
||||
return startId + currentIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#start()}.
|
||||
*/
|
||||
public void testRegisterTracksTableListener() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture));
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
expect(myTracksProviderUtils.getTrack(capture(new Capture<Long>()))).andReturn(track);
|
||||
// Make the track id is unique.
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, System.currentTimeMillis());
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
replay();
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#start()}.
|
||||
*/
|
||||
public void testRegisterWaypointsTableListener() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
capture(new Capture<Long>()), capture(new Capture<Long>()),
|
||||
capture(new Capture<Integer>()))).andReturn(null);
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
replay();
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.min_required_accuracy_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_minRequiredAccuracy() {
|
||||
int value = 1;
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.recording_gps_accuracy_key));
|
||||
assertEquals(value, trackDataHub.getRecordingGpsAccuracy());
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value + 1);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.recording_gps_accuracy_key));
|
||||
assertEquals(value + 1, trackDataHub.getRecordingGpsAccuracy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.metric_units_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_metricUnitsNoNotify() {
|
||||
String imperialUnits = context.getString(R.string.stats_units_imperial);
|
||||
|
||||
PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits);
|
||||
trackDataHub.notifyPreferenceChanged(
|
||||
PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
assertEquals(false, trackDataHub.isMetricUnits());
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
trackDataHub.notifyPreferenceChanged(
|
||||
PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
assertEquals(true, trackDataHub.isMetricUnits());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.metric_units_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_reportSpeedNoNotify() {
|
||||
String value = context.getString(R.string.stats_rate_pace);
|
||||
PreferencesUtils.setString(context, R.string.stats_rate_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.stats_rate_key));
|
||||
assertEquals(false, trackDataHub.isReportSpeed());
|
||||
|
||||
value = context.getString(R.string.stats_rate_speed);
|
||||
PreferencesUtils.setString(context, R.string.stats_rate_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.stats_rate_key));
|
||||
assertEquals(true, trackDataHub.isReportSpeed());
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for the WaypointCreationRequest class.
|
||||
* {@link WaypointCreationRequest}
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class WaypointCreationRequestTest {
|
||||
|
||||
public void testTypeParceling() {
|
||||
WaypointCreationRequest original = WaypointCreationRequest.DEFAULT_WAYPOINT;
|
||||
Parcel p = Parcel.obtain();
|
||||
original.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
|
||||
Assert.assertEquals(original.getType(), copy.getType());
|
||||
Assert.assertFalse(copy.isTrackStatistics());
|
||||
Assert.assertNull(copy.getName());
|
||||
Assert.assertNull(copy.getDescription());
|
||||
Assert.assertNull(copy.getIconUrl());
|
||||
}
|
||||
|
||||
public void testAllAttributesParceling() {
|
||||
WaypointCreationRequest original = new WaypointCreationRequest(
|
||||
WaypointType.WAYPOINT, false, "name", "category", "description", "img.png", null);
|
||||
Parcel p = Parcel.obtain();
|
||||
original.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
|
||||
Assert.assertEquals(original.getType(), copy.getType());
|
||||
Assert.assertFalse(copy.isTrackStatistics());
|
||||
Assert.assertEquals("name", copy.getName());
|
||||
Assert.assertEquals("category", copy.getCategory());
|
||||
Assert.assertEquals("description", copy.getDescription());
|
||||
Assert.assertEquals("img.png", copy.getIconUrl());
|
||||
}
|
||||
}
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.fragments;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView;
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.sensor.Sensor;
|
||||
import com.google.android.apps.mytracks.content.sensor.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests {@link ChartFragment}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ChartFragmentTest {
|
||||
|
||||
private static final double HOURS_PER_UNIT = 60.0;
|
||||
|
||||
private ChartFragment chartFragment;
|
||||
|
||||
@Before
|
||||
protected void setUp() {
|
||||
chartFragment = new ChartFragment();
|
||||
chartFragment.setChartView(new ChartView(InstrumentationRegistry.getInstrumentation().getContext()));
|
||||
chartFragment.setTripStatisticsUpdater(TrackStubUtils.INITIAL_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}
|
||||
*/
|
||||
public void testFillDataPoint_sensorIncorrect() {
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
// No input.
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
|
||||
// Input incorrect state.
|
||||
// Creates SensorData.
|
||||
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
|
||||
.setValue(100).setState(Sensor.SensorState.NONE);
|
||||
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
|
||||
.setValue(101).setState(Sensor.SensorState.NONE);
|
||||
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
|
||||
.setValue(102).setState(Sensor.SensorState.NONE);
|
||||
|
||||
// Creates SensorDataSet.
|
||||
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
|
||||
sensorDataSet = sensorDataSet.toBuilder()
|
||||
.setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build();
|
||||
myTracksLocation.setSensorDataSet(sensorDataSet);
|
||||
// Test.
|
||||
point = fillDataPointTestHelper(myTracksLocation);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the correct values of sensor in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_sensorCorrect() {
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
// No input.
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
Assert.assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
|
||||
// Creates SensorData.
|
||||
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
|
||||
.setValue(100).setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
|
||||
.setValue(101).setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
|
||||
.setValue(102).setState(Sensor.SensorState.SENDING);
|
||||
|
||||
// Creates SensorDataSet.
|
||||
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
|
||||
sensorDataSet = sensorDataSet.toBuilder()
|
||||
.setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build();
|
||||
myTracksLocation.setSensorDataSet(sensorDataSet);
|
||||
// Test.
|
||||
point = fillDataPointTestHelper(myTracksLocation);
|
||||
Assert.assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
Assert.assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1]);
|
||||
Assert.assertEquals(102.0, point[ChartView.POWER_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of metric Distance in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_distanceMetric() {
|
||||
// By distance.
|
||||
chartFragment.setChartByDistance(true);
|
||||
// Resets last location and writes first location.
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[0]);
|
||||
|
||||
// The second is a same location, just different time.
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals(0.0, point[0]);
|
||||
|
||||
// The third location is a new location, and use metric.
|
||||
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation3.setLatitude(23);
|
||||
point = fillDataPointTestHelper(myTracksLocation3);
|
||||
|
||||
// Computes the distance between Latitude 22 and 23.
|
||||
float[] results = new float[4];
|
||||
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
|
||||
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
|
||||
double distance1 = results[0] * UnitConversions.M_TO_KM;
|
||||
Assert.assertEquals(distance1, point[0]);
|
||||
|
||||
// The fourth location is a new location, and use metric.
|
||||
MyTracksLocation myTracksLocation4 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation4.setLatitude(24);
|
||||
point = fillDataPointTestHelper(myTracksLocation4);
|
||||
|
||||
// Computes the distance between Latitude 23 and 24.
|
||||
Location.distanceBetween(myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(),
|
||||
myTracksLocation4.getLatitude(), myTracksLocation4.getLongitude(), results);
|
||||
double distance2 = results[0] * UnitConversions.M_TO_KM;
|
||||
Assert.assertEquals((distance1 + distance2), point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of imperial Distance in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_distanceImperial() {
|
||||
// By distance.
|
||||
chartFragment.setChartByDistance(true);
|
||||
// Setups to use imperial.
|
||||
chartFragment.setMetricUnits(false);
|
||||
|
||||
// The first is a same location, just different time.
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[0]);
|
||||
|
||||
// The second location is a new location, and use imperial.
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setLatitude(23);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
|
||||
/*
|
||||
* Computes the distance between Latitude 22 and 23. And for we set using
|
||||
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
|
||||
*/
|
||||
float[] results = new float[4];
|
||||
Location.distanceBetween(myTracksLocation1.getLatitude(), myTracksLocation1.getLongitude(),
|
||||
myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), results);
|
||||
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||
Assert.assertEquals(distance1, point[0]);
|
||||
|
||||
// The third location is a new location, and use imperial.
|
||||
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation3.setLatitude(24);
|
||||
point = fillDataPointTestHelper(myTracksLocation3);
|
||||
|
||||
/*
|
||||
* Computes the distance between Latitude 23 and 24. And for we set using
|
||||
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
|
||||
*/
|
||||
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
|
||||
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
|
||||
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||
Assert.assertEquals(distance1 + distance2, point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the values of time in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_time() {
|
||||
// By time
|
||||
chartFragment.setChartByDistance(false);
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[0]);
|
||||
long timeSpan = 222;
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setTime(myTracksLocation1.getTime() + timeSpan);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals((double) timeSpan, point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of elevation in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])} by one and two points.
|
||||
*/
|
||||
public void testFillDataPoint_elevation() {
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* At first, clear old points of elevation, so give true to the second
|
||||
* parameter. Then only one value INITIALLONGTITUDE in buffer.
|
||||
*/
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1]);
|
||||
|
||||
/*
|
||||
* Send another value to buffer, now there are two values, INITIALALTITUDE
|
||||
* and INITIALALTITUDE * 2.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0,
|
||||
point[ChartView.ELEVATION_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of speed in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}. In this test, firstly remove all
|
||||
* points in memory, and then fill in two points one by one. The speed values
|
||||
* of these points are 129, 130.
|
||||
*/
|
||||
public void testFillDataPoint_speed() {
|
||||
/*
|
||||
* At first, clear old points of speed, so give true to the second
|
||||
* parameter. It will not be filled in to the speed buffer.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(128.5f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
/*
|
||||
* Tests the logic when both metricUnits and reportSpeed are true.This
|
||||
* location will be filled into speed buffer.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid, the value
|
||||
* 222 here is doesn't matter.
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation1.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(130);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to compute speed when use Imperial.
|
||||
*/
|
||||
public void testFillDataPoint_speedImperial() {
|
||||
// Setups to use imperial.
|
||||
chartFragment.setMetricUnits(false);
|
||||
|
||||
// First data point is not added to the speed buffer
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(100.0f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid and the speed
|
||||
* is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION
|
||||
* * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(102);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, point[ChartView.SPEED_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get pace value when reportSpeed is false.
|
||||
*/
|
||||
public void testFillDataPoint_pace_nonZeroSpeed() {
|
||||
// Setups reportSpeed to false.
|
||||
chartFragment.setReportSpeed(false);
|
||||
|
||||
// First data point is not added to the speed buffer
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(100.0f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
Assert.assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid and the speed
|
||||
* is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION
|
||||
* * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(102);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
Assert.assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get pace value when reportSpeed is false and average
|
||||
* speed is zero.
|
||||
*/
|
||||
public void testFillDataPoint_pace_zeroSpeed() {
|
||||
// Setups reportSpeed to false.
|
||||
chartFragment.setReportSpeed(false);
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation.setSpeed(0);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
Assert.assertEquals(0.0, point[ChartView.PACE_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test fillDataPoint.
|
||||
*
|
||||
* @param location location to fill
|
||||
* @return data of this location
|
||||
*/
|
||||
private double[] fillDataPointTestHelper(Location location) {
|
||||
double[] point = new double[ChartView.NUM_SERIES + 1];
|
||||
chartFragment.fillDataPoint(location, point);
|
||||
return point;
|
||||
}
|
||||
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.SimpleTimeZone;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Abstract class for testing file track importers.
|
||||
*
|
||||
* @author Jimmy Shih.
|
||||
*/
|
||||
public class AbstractTestFileTrackImporter extends AndroidTestCase {
|
||||
|
||||
protected static final String TRACK_NAME_0 = "blablub";
|
||||
protected static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer";
|
||||
|
||||
protected static final String TRACK_NAME_1 = "another track";
|
||||
protected static final String TRACK_DESCRIPTION_1 = "another description";
|
||||
|
||||
protected static final double TRACK_LATITUDE = 48.768364;
|
||||
protected static final double TRACK_LONGITUDE = 9.177886;
|
||||
protected static final double TRACK_ELEVATION = 324.0;
|
||||
|
||||
protected static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z";
|
||||
protected static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123";
|
||||
protected static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123";
|
||||
protected static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123";
|
||||
|
||||
protected static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
||||
protected static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||
|
||||
static {
|
||||
/*
|
||||
* We can't omit the timezones in the test, otherwise it'll use the local
|
||||
* timezone and fail depending on where the test runner is.
|
||||
*/
|
||||
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
|
||||
DATE_FORMAT_0.setTimeZone(utc);
|
||||
DATE_FORMAT_1.setTimeZone(utc);
|
||||
}
|
||||
|
||||
protected static final long TRACK_ID_0 = 1;
|
||||
protected static final long TRACK_ID_1 = 2;
|
||||
protected static final long TRACK_POINT_ID_0 = 1;
|
||||
protected static final long TRACK_POINT_ID_1 = 2;
|
||||
protected static final long TRACK_POINT_ID_3 = 4;
|
||||
protected static final long WAYPOINT_ID_0 = 1;
|
||||
|
||||
protected static final Uri TRACK_ID_0_URI = ContentUris.appendId(
|
||||
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build();
|
||||
protected static final Uri TRACK_ID_1_URI = ContentUris.appendId(
|
||||
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_1).build();
|
||||
protected static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(
|
||||
WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
||||
|
||||
protected MyTracksProviderUtils myTracksProviderUtils;
|
||||
|
||||
private Factory oldMyTracksProviderUtilsFactory;
|
||||
|
||||
@UsesMocks(MyTracksProviderUtils.class)
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
|
||||
oldMyTracksProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(
|
||||
myTracksProviderUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TestingProviderUtilsFactory.restoreOldFactory(oldMyTracksProviderUtilsFactory);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected Location createLocation(int index, long time) {
|
||||
Location location = new Location(LocationManager.GPS_PROVIDER);
|
||||
location.setLatitude(TRACK_LATITUDE + index);
|
||||
location.setLongitude(TRACK_LONGITUDE + index);
|
||||
location.setAltitude(TRACK_ELEVATION + index);
|
||||
location.setTime(time);
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the first track point to be added.
|
||||
*
|
||||
* @param location the location
|
||||
* @param trackId the track id
|
||||
* @param trackPointId the track point id
|
||||
*/
|
||||
protected void expectFirstTrackPoint(Location location, long trackId, long trackPointId) {
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
location != null ? LocationsMatcher.eqLoc(location) : (Location[]) AndroidMock.anyObject(),
|
||||
eq(1), eq(trackId))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getFirstTrackPointId(trackId)).andReturn(trackPointId);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(trackId)).andReturn(trackPointId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the track to be updated.
|
||||
*
|
||||
* @param track the track
|
||||
* @param lastTrack true if it is the last track in the gpx
|
||||
* @param trackId the track id
|
||||
*/
|
||||
protected void expectUpdateTrack(Capture<Track> track, boolean lastTrack, long trackId) {
|
||||
myTracksProviderUtils.updateTrack(AndroidMock.capture(track));
|
||||
expect(myTracksProviderUtils.insertWaypoint((Waypoint) AndroidMock.anyObject()))
|
||||
.andReturn(WAYPOINT_ID_O_URI);
|
||||
if (lastTrack) {
|
||||
// Return null to not add waypoints
|
||||
expect(myTracksProviderUtils.getTrack(trackId)).andReturn(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyTrack(Track track, String name, String description, long time) {
|
||||
assertEquals(name, track.getName());
|
||||
assertEquals(description, track.getDescription());
|
||||
if (time != -1L) {
|
||||
assertEquals(time, track.getTripStatistics().getStartTime());
|
||||
}
|
||||
assertNotSame(-1, track.getStartId());
|
||||
assertNotSame(-1, track.getStopId());
|
||||
}
|
||||
}
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Tests for {@link GpxFileTrackImporter}.
|
||||
*
|
||||
* @author Steffen Horlacher
|
||||
*/
|
||||
public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
||||
|
||||
private static String getNameAndDescription(String name, String description) {
|
||||
return "<name><![CDATA[" + name + "]]></name>" + "<desc><![CDATA[" + description + "]]></desc>";
|
||||
}
|
||||
|
||||
private static String getTrackPoint(int index, String time) {
|
||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
||||
String elevation = Double.toString(TRACK_ELEVATION + index);
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(
|
||||
"<trkpt lat=\"" + latitude + "\" lon=\"" + longitude + "\"><ele>" + elevation + "</ele>");
|
||||
if (time != null) {
|
||||
buffer.append("<time>" + time + "</time>");
|
||||
}
|
||||
buffer.append("</trkpt>");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg><trkseg>"
|
||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + "</trkseg></trk></gpx>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, null) + getTrackPoint(1, null) + "</trkseg><trkseg>"
|
||||
+ getTrackPoint(2, null) + getTrackPoint(3, null) + "</trkseg></trk></gpx>";
|
||||
|
||||
private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring(
|
||||
0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50);
|
||||
private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LATITUDE), "1000.0");
|
||||
private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
TRACK_TIME_0, "invalid");
|
||||
private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_ELEVATION), "invalid");
|
||||
private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LATITUDE), "invalid");
|
||||
private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LONGITUDE), "invalid");
|
||||
|
||||
/**
|
||||
* Tests one track with one segment.
|
||||
*/
|
||||
public void testOneTrackOneSegment() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime());
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments.
|
||||
*/
|
||||
public void testOneTrackTwoSegments() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
||||
assertEquals(
|
||||
time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0,
|
||||
DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments, but no time in the track points.
|
||||
*/
|
||||
public void testOneTrackTwoSegmentsNoTime() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(
|
||||
VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
assertEquals(0, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid xml input.
|
||||
*/
|
||||
public void testInvalidXml() throws Exception {
|
||||
testInvalidGpx(INVALID_XML_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid location.
|
||||
*/
|
||||
public void testInvalidLocation() throws Exception {
|
||||
testInvalidGpx(INVALID_LOCATION_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid time.
|
||||
*/
|
||||
public void testInvalidTime() throws Exception {
|
||||
testInvalidGpx(INVALID_TIME_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid altitude.
|
||||
*/
|
||||
public void testInvalidAltitude() throws Exception {
|
||||
testInvalidGpx(INVALID_ALTITUDE_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid latitude.
|
||||
*/
|
||||
public void testInvalidLatitude() throws Exception {
|
||||
testInvalidGpx(INVALID_LATITUDE_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid longitude.
|
||||
*/
|
||||
public void testInvalidLongitude() throws Exception {
|
||||
testInvalidGpx(INVALID_LONGITUDE_GPX);
|
||||
}
|
||||
|
||||
private void testInvalidGpx(String xml) throws Exception {
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
|
||||
// For the following, use StubReturn since we don't care whether they are
|
||||
// invoked or not.
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), AndroidMock.anyInt(), AndroidMock.anyLong()))
|
||||
.andStubReturn(1);
|
||||
expect(myTracksProviderUtils.getFirstTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
myTracksProviderUtils.deleteTrack(getContext(), TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(-1L, trackId);
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Tests for {@link KmlFileTrackImporter}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
||||
|
||||
private static String getNameAndDescription(String name, String description) {
|
||||
return "<name><![CDATA[" + name + "]]></name><description><![CDATA[" + description
|
||||
+ "]]></description>";
|
||||
}
|
||||
|
||||
private static String getTrackPoint(int index, String time) {
|
||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
||||
String altitude = Double.toString(TRACK_ELEVATION + index);
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<when>" + time + "</when>" + "<gx:coord>" + longitude + " " + latitude + " "
|
||||
+ altitude + "</gx:coord>");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX =
|
||||
"<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1)
|
||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX =
|
||||
"<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</gx:Track><gx:Track>"
|
||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3)
|
||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
||||
|
||||
/**
|
||||
* Tests one track with one segment.
|
||||
*/
|
||||
public void testOneTrackOneSegment() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
||||
|
||||
myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(
|
||||
getContext(), TRACK_ID_0, myTracksProviderUtils);
|
||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime());
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments.
|
||||
*/
|
||||
public void testOneTrackTwoSegments() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
|
||||
myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(
|
||||
getContext(), TRACK_ID_0, myTracksProviderUtils);
|
||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
||||
assertEquals(
|
||||
time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0,
|
||||
DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.easymock.IArgumentMatcher;
|
||||
|
||||
/**
|
||||
* Locations matcher. Workaround because of capture bug 2617107 in easymock:
|
||||
* http://sourceforge.net/tracker/?func=detail&aid=2617107&group_id=82958&atid=567837
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class LocationsMatcher implements IArgumentMatcher {
|
||||
|
||||
public static Location[] eqLoc(Location expected) {
|
||||
return eqLoc(new Location[] { expected });
|
||||
}
|
||||
|
||||
public static Location[] eqLoc(Location[] expected) {
|
||||
IArgumentMatcher matcher = new LocationsMatcher(expected);
|
||||
AndroidMock.reportMatcher(matcher);
|
||||
return null;
|
||||
}
|
||||
|
||||
private final Location[] expectedLocations;
|
||||
|
||||
private LocationsMatcher(Location[] expected) {
|
||||
this.expectedLocations = expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buf) {
|
||||
buf.append("eqLoc(").append(Arrays.toString(expectedLocations)).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object obj) {
|
||||
if (!(obj instanceof Location[])) {
|
||||
return false;
|
||||
}
|
||||
Location[] locations = (Location[]) obj;
|
||||
if (locations.length < expectedLocations.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only check the first elements (those that will be taken into account)
|
||||
for (int i = 0; i < expectedLocations.length; i++) {
|
||||
if (!matchLocation(locations[i], expectedLocations[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchLocation(Location location1, Location location2) {
|
||||
return (location1.getTime() == location2.getTime())
|
||||
&& (location1.getLatitude() == location2.getLatitude())
|
||||
&& (location1.getLongitude() == location2.getLongitude())
|
||||
&& (location1.getAltitude() == location2.getAltitude());
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests the {@link AdaptiveLocationListenerPolicy}.
|
||||
*
|
||||
* @author youtaol
|
||||
*/
|
||||
public class AdaptiveLocationListenerPolicyTest extends TestCase {
|
||||
|
||||
private AdaptiveLocationListenerPolicy adocationListenerPolicy;
|
||||
private static final long MIN = 1000;
|
||||
private static final long MAX = 3000;
|
||||
private static final int MIN_DISTANCE = 10;
|
||||
private static final long NEW_IDLE_TIME_BIG = 10000;
|
||||
private static final long NEW_IDLE_TIME_NORMAL = 5000;
|
||||
private static final long NEW_IDLE_TIME_SMALL = 2000;
|
||||
private static final long NEW_IDLE_TIME_LESS_THAN_MIN = 500;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
adocationListenerPolicy = new AdaptiveLocationListenerPolicy(MIN, MAX, MIN_DISTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the
|
||||
* {@link AdaptiveLocationListenerPolicy#getDesiredPollingInterval()} in four
|
||||
* situations.
|
||||
* <ul>
|
||||
* <li>The newIdleTime is bigger than max interval.</li>
|
||||
* <li>The newIdleTime is between min and max interval.</li>
|
||||
* <li>The newIdleTime is smaller than max interval.</li>
|
||||
* <li>The newIdleTime is smaller than the smallest interval unit.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void testGetDesiredPollingInterval() {
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_BIG);
|
||||
assertEquals(MAX, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_NORMAL);
|
||||
// First get the half of NEW_IDLE_TIME_NORMAL, and then round it to the
|
||||
// nearest second.
|
||||
assertEquals((NEW_IDLE_TIME_NORMAL / 2 / 1000) * 1000,
|
||||
adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_SMALL);
|
||||
assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_LESS_THAN_MIN);
|
||||
assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link AdaptiveLocationListenerPolicy#getMinDistance()}.
|
||||
*/
|
||||
public void testGetMinDistance() {
|
||||
assertEquals(MIN_DISTANCE, adocationListenerPolicy.getMinDistance());
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.RemoteException;
|
||||
import android.test.ServiceTestCase;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
/**
|
||||
* Tests {@link ControlRecordingService}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class ControlRecordingServiceTest extends ServiceTestCase<ControlRecordingService> {
|
||||
|
||||
private Context context;
|
||||
private ControlRecordingService controlRecordingService;
|
||||
|
||||
public ControlRecordingServiceTest() {
|
||||
super(ControlRecordingService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the start of {@link ControlRecordingService} and tests the method
|
||||
* {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)}
|
||||
* to start a track recording.
|
||||
*/
|
||||
@UsesMocks(ITrackRecordingService.class)
|
||||
public void testStartRecording() {
|
||||
assertNull(controlRecordingService);
|
||||
Intent intent = startControlRecordingService(context.getString(R.string.track_action_start));
|
||||
assertNotNull(controlRecordingService);
|
||||
|
||||
ITrackRecordingService iTrackRecordingServiceMock = EasyMock
|
||||
.createStrictMock(ITrackRecordingService.class);
|
||||
try {
|
||||
EasyMock.expect(iTrackRecordingServiceMock.startNewTrack()).andReturn(1L);
|
||||
EasyMock.replay(iTrackRecordingServiceMock);
|
||||
controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock);
|
||||
EasyMock.verify(iTrackRecordingServiceMock);
|
||||
} catch (RemoteException e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)}
|
||||
* to stop a track recording.
|
||||
*/
|
||||
@UsesMocks(ITrackRecordingService.class)
|
||||
public void testStopRecording() {
|
||||
Intent intent = startControlRecordingService(context.getString(R.string.track_action_end));
|
||||
|
||||
ITrackRecordingService iTrackRecordingServiceMock = EasyMock
|
||||
.createStrictMock(ITrackRecordingService.class);
|
||||
try {
|
||||
iTrackRecordingServiceMock.endCurrentTrack();
|
||||
EasyMock.replay(iTrackRecordingServiceMock);
|
||||
controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock);
|
||||
EasyMock.verify(iTrackRecordingServiceMock);
|
||||
} catch (RemoteException e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a ControlRecordingService with a specified action.
|
||||
*
|
||||
* @param action the action string in the start intent
|
||||
*/
|
||||
private Intent startControlRecordingService(String action) {
|
||||
Intent intent = new Intent(context, ControlRecordingService.class);
|
||||
intent.setAction(action);
|
||||
startService(intent);
|
||||
controlRecordingService = getService();
|
||||
return intent;
|
||||
}
|
||||
|
||||
}
|
||||
+761
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.ServiceTestCase;
|
||||
import android.test.mock.MockContentProvider;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for the MyTracks track recording service.
|
||||
* <p>
|
||||
* TODO: The original class, ServiceTestCase, has a few limitations, e.g. it's
|
||||
* not possible to properly shutdown the service, unless tearDown() is called,
|
||||
* which prevents from testing multiple scenarios in a single test (see
|
||||
* runFunctionTest for more details).
|
||||
*
|
||||
* @author Bartlomiej Niechwiej
|
||||
*/
|
||||
public class TrackRecordingServiceTest extends ServiceTestCase<TestRecordingService> {
|
||||
|
||||
private Context context;
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
|
||||
/*
|
||||
* In order to support starting and binding to the service in the same unit
|
||||
* test, we provide a workaround, as the original class doesn't allow to bind
|
||||
* after the service has been previously started.
|
||||
*/
|
||||
|
||||
private boolean bound;
|
||||
private Intent serviceIntent;
|
||||
|
||||
public TrackRecordingServiceTest() {
|
||||
super(TestRecordingService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* A context wrapper with the user provided {@link ContentResolver}. TODO:
|
||||
* Move to test utils package.
|
||||
*/
|
||||
public static class MockContext extends ContextWrapper {
|
||||
private final ContentResolver contentResolver;
|
||||
|
||||
public MockContext(ContentResolver contentResolver, Context base) {
|
||||
super(base);
|
||||
this.contentResolver = contentResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return contentResolver;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBinder bindService(Intent intent) {
|
||||
if (getService() != null) {
|
||||
if (bound) {
|
||||
throw new IllegalStateException("Service: " + getService() + " is already bound");
|
||||
}
|
||||
bound = true;
|
||||
serviceIntent = intent.cloneFilter();
|
||||
return getService().onBind(intent);
|
||||
} else {
|
||||
return super.bindService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdownService() {
|
||||
if (bound) {
|
||||
assertNotNull(getService());
|
||||
getService().onUnbind(serviceIntent);
|
||||
bound = false;
|
||||
}
|
||||
super.shutdownService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
/*
|
||||
* Create a mock context that uses a mock content resolver and a renaming
|
||||
* delegating context.
|
||||
*/
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext renamingDelegatingContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
context = new MockContext(mockContentResolver, renamingDelegatingContext);
|
||||
|
||||
// Set up the mock content resolver
|
||||
MyTracksProvider myTracksProvider = new MyTracksProvider();
|
||||
myTracksProvider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider);
|
||||
|
||||
MockContentProvider settingsProvider = new MockContentProvider(context) {
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
mockContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
|
||||
|
||||
// Set the context
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
// Let's use default values.
|
||||
sharedPreferences.edit().clear().apply();
|
||||
|
||||
// Disable auto resume by default.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, 0);
|
||||
// No recording track.
|
||||
PreferencesUtils.setLong(
|
||||
context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testStartable() {
|
||||
startService(createStartIntent());
|
||||
assertNotNull(getService());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testBindable() {
|
||||
IBinder service = bindService(createStartIntent());
|
||||
assertNotNull(service);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_shouldResume() throws Exception {
|
||||
// Insert a dummy track and mark it as recording track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), true);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We expect to resume the previous track.
|
||||
assertTrue(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(123L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: shutdownService() has a bug and doesn't set mServiceCreated to false,
|
||||
* thus preventing from a second call to onCreate(). Report the bug to Android
|
||||
* team. Until then, the following tests and checks must be commented out.
|
||||
*
|
||||
* TODO: If fixed, remove "disabled" prefix from the test name.
|
||||
*/
|
||||
@MediumTest
|
||||
public void disabledTestResumeAfterReboot_simulateReboot() throws Exception {
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
// Simulate recording a track.
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(service.isRecording());
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
shutdownService();
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
assertTrue(getService().isRecording());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_noRecordingTrack() throws Exception {
|
||||
// Insert a dummy track and mark it as recording track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), false);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because it was stopped.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_expiredTrack() throws Exception {
|
||||
// Insert a dummy track last updated 20 min ago.
|
||||
createDummyTrack(123L, System.currentTimeMillis() - 20 * 60 * 1000, true);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because it has expired.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_tooManyAttempts() throws Exception {
|
||||
// Insert a dummy track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), true);
|
||||
|
||||
// Set the number of attempts to max.
|
||||
updateAutoResumePrefs(TrackRecordingService.MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because there were already
|
||||
// too many attempts.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_noTracks() throws Exception {
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
// Test if we start in no-recording mode by default.
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_oldTracks() throws Exception {
|
||||
createDummyTrack(123L, -1L, false);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_orphanedRecordingTrack() throws Exception {
|
||||
// Just set recording track to a bogus value.
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, 256L);
|
||||
|
||||
// Make sure that the service will not start recording and will clear
|
||||
// the bogus track.
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous/waitable broadcast receiver to be used in testing.
|
||||
*/
|
||||
private class BlockingBroadcastReceiver extends BroadcastReceiver {
|
||||
private static final long MAX_WAIT_TIME_MS = 10000;
|
||||
private List<Intent> receivedIntents = new ArrayList<Intent>();
|
||||
|
||||
public List<Intent> getReceivedIntents() {
|
||||
return receivedIntents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
Log.d("MyTracksTest", "Got broadcast: " + intent);
|
||||
synchronized (receivedIntents) {
|
||||
receivedIntents.add(intent);
|
||||
receivedIntents.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitUntilReceived(int receiveCount) {
|
||||
long deadline = System.currentTimeMillis() + MAX_WAIT_TIME_MS;
|
||||
synchronized (receivedIntents) {
|
||||
while (receivedIntents.size() < receiveCount) {
|
||||
try {
|
||||
// Wait releases synchronized lock until it returns
|
||||
receivedIntents.wait(500);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() > deadline) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStartNewTrack_noRecording() throws Exception {
|
||||
// NOTICE: due to the way Android permissions work, if this fails,
|
||||
// uninstall the test apk then retry - the test must be installed *after*
|
||||
// My Tracks (go figure).
|
||||
// Reference: http://code.google.com/p/android/issues/detail?id=5521
|
||||
BlockingBroadcastReceiver startReceiver = new BlockingBroadcastReceiver();
|
||||
String startAction = context.getString(R.string.track_started_broadcast_action);
|
||||
context.registerReceiver(startReceiver, new IntentFilter(startAction));
|
||||
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(id >= 0);
|
||||
assertTrue(service.isRecording());
|
||||
Track track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
assertEquals(PreferencesUtils.getString(
|
||||
context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT),
|
||||
track.getCategory());
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
|
||||
// Verify that the start broadcast was received.
|
||||
assertTrue(startReceiver.waitUntilReceived(1));
|
||||
List<Intent> receivedIntents = startReceiver.getReceivedIntents();
|
||||
assertEquals(1, receivedIntents.size());
|
||||
Intent broadcastIntent = receivedIntents.get(0);
|
||||
assertEquals(startAction, broadcastIntent.getAction());
|
||||
assertEquals(id,
|
||||
broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L));
|
||||
|
||||
context.unregisterReceiver(startReceiver);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStartNewTrack_alreadyRecording() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
|
||||
// Starting a new track when there is a recording should just return -1L.
|
||||
long newTrack = service.startNewTrack();
|
||||
assertEquals(-1L, newTrack);
|
||||
|
||||
assertEquals(123L, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(123L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testEndCurrentTrack_alreadyRecording() throws Exception {
|
||||
// See comment above if this fails randomly.
|
||||
BlockingBroadcastReceiver stopReceiver = new BlockingBroadcastReceiver();
|
||||
String stopAction = context.getString(R.string.track_stopped_broadcast_action);
|
||||
context.registerReceiver(stopReceiver, new IntentFilter(stopAction));
|
||||
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
|
||||
// End the current track.
|
||||
service.endCurrentTrack();
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
|
||||
PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
|
||||
// Verify that the stop broadcast was received.
|
||||
assertTrue(stopReceiver.waitUntilReceived(1));
|
||||
List<Intent> receivedIntents = stopReceiver.getReceivedIntents();
|
||||
assertEquals(1, receivedIntents.size());
|
||||
Intent broadcastIntent = receivedIntents.get(0);
|
||||
assertEquals(stopAction, broadcastIntent.getAction());
|
||||
assertEquals(123L,
|
||||
broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L));
|
||||
|
||||
context.unregisterReceiver(stopReceiver);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testEndCurrentTrack_noRecording() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
/*
|
||||
* Ending the current track when there is no recording should not result in
|
||||
* any error.
|
||||
*/
|
||||
service.endCurrentTrack();
|
||||
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
|
||||
PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testIntegration_completeRecordingSession() throws Exception {
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertStatisticsMarker_noRecordingTrack() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||
assertEquals(-1L, waypointId);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertStatisticsMarker_validLocation() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
assertFalse(service.isPaused());
|
||||
insertLocation(service);
|
||||
|
||||
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
|
||||
assertEquals(2, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
|
||||
|
||||
Waypoint wpt = providerUtils.getWaypoint(2);
|
||||
assertEquals(getContext().getString(R.string.marker_statistics_icon_url), wpt.getIcon());
|
||||
assertEquals(getContext().getString(R.string.marker_split_name_format, 1), wpt.getName());
|
||||
assertEquals(WaypointType.STATISTICS, wpt.getType());
|
||||
assertEquals(123L, wpt.getTrackId());
|
||||
assertEquals(0.0, wpt.getLength());
|
||||
assertNotNull(wpt.getLocation());
|
||||
assertNotNull(wpt.getTripStatistics());
|
||||
// TODO check the rest of the params.
|
||||
|
||||
// TODO: Check waypoint 2.
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertWaypointMarker_noRecordingTrack() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
|
||||
assertEquals(-1L, waypointId);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertWaypointMarker_validWaypoint() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
insertLocation(service);
|
||||
|
||||
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT));
|
||||
Waypoint wpt = providerUtils.getWaypoint(1);
|
||||
assertEquals(getContext().getString(R.string.marker_waypoint_icon_url), wpt.getIcon());
|
||||
assertEquals(getContext().getString(R.string.marker_name_format, 1), wpt.getName());
|
||||
assertEquals(WaypointType.WAYPOINT, wpt.getType());
|
||||
assertEquals(123L, wpt.getTrackId());
|
||||
assertEquals(0.0, wpt.getLength());
|
||||
assertNotNull(wpt.getLocation());
|
||||
assertNull(wpt.getTripStatistics());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(
|
||||
context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyByDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.voice_frequency_key, -1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyByTime() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.voice_frequency_key, 1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_maxRecordingDistanceDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.max_recording_distance_key,
|
||||
PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_maxRecordingDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.max_recording_distance_key, 50);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingDistanceDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, 2);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(
|
||||
context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyByDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.split_frequency_key, -1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyByTime() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.split_frequency_key, 1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_metricUnitsDefault() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_metricUnitsDisabled() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, context.getString(R.string.stats_units_imperial));
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingIntervalDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.min_recording_interval_key,
|
||||
PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingInterval() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.min_recording_interval_key, 2);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRequiredAccuracyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key,
|
||||
PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRequiredAccuracy() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, 500);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_sensorTypeDefault() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.sensor_type_key, PreferencesUtils.SENSOR_TYPE_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_sensorTypeZephyr() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.sensor_type_key, context.getString(R.string.sensor_type_value_zephyr));
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
private ITrackRecordingService bindAndGetService(Intent intent) {
|
||||
ITrackRecordingService service = ITrackRecordingService.Stub.asInterface(bindService(intent));
|
||||
assertNotNull(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
private Track createDummyTrack(long id, long stopTime, boolean isRecording) {
|
||||
Track dummyTrack = new Track();
|
||||
dummyTrack.setId(id);
|
||||
dummyTrack.setName("Dummy Track");
|
||||
TripStatistics tripStatistics = new TripStatistics();
|
||||
tripStatistics.setStopTime(stopTime);
|
||||
dummyTrack.setTripStatistics(tripStatistics);
|
||||
addTrack(dummyTrack, isRecording);
|
||||
return dummyTrack;
|
||||
}
|
||||
|
||||
private void updateAutoResumePrefs(int attempts, int timeoutMins) {
|
||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts);
|
||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_timeout_key, timeoutMins);
|
||||
}
|
||||
|
||||
private Intent createStartIntent() {
|
||||
Intent startIntent = new Intent();
|
||||
startIntent.setClass(context, TrackRecordingService.class);
|
||||
return startIntent;
|
||||
}
|
||||
|
||||
private void addTrack(Track track, boolean isRecording) {
|
||||
assertTrue(track.getId() >= 0);
|
||||
providerUtils.insertTrack(track);
|
||||
assertEquals(track.getId(), providerUtils.getTrack(track.getId()).getId());
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key,
|
||||
isRecording ? track.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording);
|
||||
}
|
||||
|
||||
private void fullRecordingSession() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
// Start a track.
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(id >= 0);
|
||||
assertTrue(service.isRecording());
|
||||
Track track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
|
||||
// Insert a few points, markers and statistics.
|
||||
long startTime = System.currentTimeMillis();
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Location loc = new Location("gps");
|
||||
loc.setLongitude(35.0f + i / 10.0f);
|
||||
loc.setLatitude(45.0f - i / 5.0f);
|
||||
loc.setAccuracy(5);
|
||||
loc.setSpeed(10);
|
||||
loc.setTime(startTime + i * 10000);
|
||||
loc.setBearing(3.0f);
|
||||
service.insertTrackPoint(loc);
|
||||
|
||||
if (i % 10 == 0) {
|
||||
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||
} else if (i % 7 == 0) {
|
||||
service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the track. Validate if it has correct data.
|
||||
service.endCurrentTrack();
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
TripStatistics tripStatistics = track.getTripStatistics();
|
||||
assertNotNull(tripStatistics);
|
||||
assertTrue(tripStatistics.getStartTime() > 0);
|
||||
assertTrue(tripStatistics.getStopTime() >= tripStatistics.getStartTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a location and waits for 100ms.
|
||||
*
|
||||
* @param trackRecordingService the track recording service
|
||||
*/
|
||||
private void insertLocation(ITrackRecordingService trackRecordingService)
|
||||
throws RemoteException, InterruptedException {
|
||||
Location location = new Location("gps");
|
||||
location.setLongitude(35.0f);
|
||||
location.setLatitude(45.0f);
|
||||
location.setAccuracy(5);
|
||||
location.setSpeed(10);
|
||||
location.setTime(System.currentTimeMillis());
|
||||
location.setBearing(3.0f);
|
||||
trackRecordingService.insertTrackPoint(location);
|
||||
Thread.sleep(200);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnouncementPeriodicTaskFactory}.
|
||||
* These tests require Donut+ to run.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class AnnouncementPeriodicTaskFactoryTest {
|
||||
public void testCreate() {
|
||||
PeriodicTaskFactory factory = new AnnouncementPeriodicTaskFactory();
|
||||
PeriodicTask task = factory.create(InstrumentationRegistry.getInstrumentation().getContext());
|
||||
Assert.assertTrue(task instanceof AnnouncementPeriodicTask);
|
||||
}
|
||||
}
|
||||
+533
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
import static com.google.android.testing.mocking.AndroidMock.same;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.easymock.Capture;
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnouncementPeriodicTask}.
|
||||
* WARNING: I'm not responsible if your eyes start bleeding while reading this
|
||||
* code. You have been warned. It's still better than no test, though.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class AnnouncementPeriodicTaskTest extends AndroidTestCase {
|
||||
|
||||
// Use something other than our hardcoded value
|
||||
private static final Locale DEFAULT_LOCALE = Locale.KOREAN;
|
||||
private static final String ANNOUNCEMENT = "I can haz cheeseburger?";
|
||||
private Locale oldDefaultLocale;
|
||||
|
||||
private AnnouncementPeriodicTask task;
|
||||
private AnnouncementPeriodicTask mockTask;
|
||||
private Capture<OnInitListener> initListenerCapture;
|
||||
private Capture<PhoneStateListener> phoneListenerCapture;
|
||||
private TextToSpeechDelegate ttsDelegate;
|
||||
private TextToSpeechInterface tts;
|
||||
|
||||
/**
|
||||
* Mockable interface that we delegate TTS calls to.
|
||||
*/
|
||||
interface TextToSpeechInterface {
|
||||
int addEarcon(String earcon, String packagename, int resourceId);
|
||||
int addEarcon(String earcon, String filename);
|
||||
int addSpeech(String text, String packagename, int resourceId);
|
||||
int addSpeech(String text, String filename);
|
||||
boolean areDefaultsEnforced();
|
||||
String getDefaultEngine();
|
||||
Locale getLanguage();
|
||||
int isLanguageAvailable(Locale loc);
|
||||
boolean isSpeaking();
|
||||
int playEarcon(String earcon, int queueMode,
|
||||
HashMap<String, String> params);
|
||||
int playSilence(long durationInMs, int queueMode,
|
||||
HashMap<String, String> params);
|
||||
int setEngineByPackageName(String enginePackageName);
|
||||
int setLanguage(Locale loc);
|
||||
int setOnUtteranceCompletedListener(OnUtteranceCompletedListener listener);
|
||||
int setPitch(float pitch);
|
||||
int setSpeechRate(float speechRate);
|
||||
void shutdown();
|
||||
int speak(String text, int queueMode, HashMap<String, String> params);
|
||||
int stop();
|
||||
int synthesizeToFile(String text, HashMap<String, String> params,
|
||||
String filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass of {@link TextToSpeech} which delegates calls to the interface
|
||||
* above.
|
||||
* The logic here is stupid and the author is ashamed of having to write it
|
||||
* like this, but basically the issue is that TextToSpeech cannot be mocked
|
||||
* without running its constructor, its constructor runs async operations
|
||||
* which call other methods (and then if the methods are part of a mock we'd
|
||||
* have to set a behavior, but we can't 'cause the object hasn't been fully
|
||||
* built yet).
|
||||
* The logic is that calls made during the constructor (when tts is not yet
|
||||
* set) will go up to the original class, but after tts is set we'll forward
|
||||
* them all to the mock.
|
||||
*/
|
||||
private class TextToSpeechDelegate
|
||||
extends TextToSpeech implements TextToSpeechInterface {
|
||||
public TextToSpeechDelegate(Context context, OnInitListener listener) {
|
||||
super(context, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addEarcon(String earcon, String packagename, int resourceId) {
|
||||
if (tts == null) {
|
||||
return super.addEarcon(earcon, packagename, resourceId);
|
||||
}
|
||||
return tts.addEarcon(earcon, packagename, resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addEarcon(String earcon, String filename) {
|
||||
if (tts == null) {
|
||||
return super.addEarcon(earcon, filename);
|
||||
}
|
||||
return tts.addEarcon(earcon, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addSpeech(String text, String packagename, int resourceId) {
|
||||
if (tts == null) {
|
||||
return super.addSpeech(text, packagename, resourceId);
|
||||
}
|
||||
return tts.addSpeech(text, packagename, resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addSpeech(String text, String filename) {
|
||||
if (tts == null) {
|
||||
return super.addSpeech(text, filename);
|
||||
}
|
||||
return tts.addSpeech(text, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLanguage() {
|
||||
if (tts == null) {
|
||||
return super.getLanguage();
|
||||
}
|
||||
return tts.getLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isLanguageAvailable(Locale loc) {
|
||||
if (tts == null) {
|
||||
return super.isLanguageAvailable(loc);
|
||||
}
|
||||
return tts.isLanguageAvailable(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpeaking() {
|
||||
if (tts == null) {
|
||||
return super.isSpeaking();
|
||||
}
|
||||
return tts.isSpeaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int playEarcon(String earcon, int queueMode,
|
||||
HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.playEarcon(earcon, queueMode, params);
|
||||
}
|
||||
return tts.playEarcon(earcon, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int playSilence(long durationInMs, int queueMode,
|
||||
HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.playSilence(durationInMs, queueMode, params);
|
||||
}
|
||||
return tts.playSilence(durationInMs, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setLanguage(Locale loc) {
|
||||
if (tts == null) {
|
||||
return super.setLanguage(loc);
|
||||
}
|
||||
return tts.setLanguage(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setOnUtteranceCompletedListener(
|
||||
OnUtteranceCompletedListener listener) {
|
||||
if (tts == null) {
|
||||
return super.setOnUtteranceCompletedListener(listener);
|
||||
}
|
||||
return tts.setOnUtteranceCompletedListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setPitch(float pitch) {
|
||||
if (tts == null) {
|
||||
return super.setPitch(pitch);
|
||||
}
|
||||
return tts.setPitch(pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setSpeechRate(float speechRate) {
|
||||
if (tts == null) {
|
||||
return super.setSpeechRate(speechRate);
|
||||
}
|
||||
return tts.setSpeechRate(speechRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (tts == null) {
|
||||
super.shutdown();
|
||||
return;
|
||||
}
|
||||
tts.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int speak(
|
||||
String text, int queueMode, HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.speak(text, queueMode, params);
|
||||
}
|
||||
return tts.speak(text, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int stop() {
|
||||
if (tts == null) {
|
||||
return super.stop();
|
||||
}
|
||||
return tts.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int synthesizeToFile(String text, HashMap<String, String> params,
|
||||
String filename) {
|
||||
if (tts == null) {
|
||||
return super.synthesizeToFile(text, params, filename);
|
||||
}
|
||||
return tts.synthesizeToFile(text, params, filename);
|
||||
}
|
||||
}
|
||||
|
||||
@UsesMocks({
|
||||
AnnouncementPeriodicTask.class,
|
||||
StringUtils.class,
|
||||
})
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
oldDefaultLocale = Locale.getDefault();
|
||||
Locale.setDefault(DEFAULT_LOCALE);
|
||||
|
||||
// Eww, the effort required just to mock TextToSpeech is insane
|
||||
final AtomicBoolean listenerCalled = new AtomicBoolean();
|
||||
OnInitListener blockingListener = new OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
synchronized (this) {
|
||||
listenerCalled.set(true);
|
||||
notify();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ttsDelegate = new TextToSpeechDelegate(getContext(), blockingListener);
|
||||
|
||||
// Wait for all async operations done in the constructor to finish.
|
||||
synchronized (blockingListener) {
|
||||
while (!listenerCalled.get()) {
|
||||
// Releases the synchronized lock until we're woken up.
|
||||
blockingListener.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Phew, done, now we can start forwarding calls
|
||||
tts = AndroidMock.createMock(TextToSpeechInterface.class);
|
||||
|
||||
initListenerCapture = new Capture<OnInitListener>();
|
||||
phoneListenerCapture = new Capture<PhoneStateListener>();
|
||||
|
||||
// Create a partial forwarding mock
|
||||
mockTask = AndroidMock.createMock(AnnouncementPeriodicTask.class, getContext());
|
||||
task = new AnnouncementPeriodicTask(getContext()) {
|
||||
@Override
|
||||
protected TextToSpeech newTextToSpeech(Context ctx,
|
||||
OnInitListener onInitListener) {
|
||||
return mockTask.newTextToSpeech(ctx, onInitListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAnnouncement(TripStatistics stats) {
|
||||
return mockTask.getAnnouncement(stats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void listenToPhoneState(
|
||||
PhoneStateListener listener, int events) {
|
||||
mockTask.listenToPhoneState(listener, events);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() {
|
||||
Locale.setDefault(oldDefaultLocale);
|
||||
}
|
||||
|
||||
public void testStart() {
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
assertNotNull(ttsInitListener);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
ttsInitListener.onInit(TextToSpeech.SUCCESS);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testStart_notReady() {
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
assertNotNull(ttsInitListener);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
ttsInitListener.onInit(TextToSpeech.ERROR);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testShutdown() {
|
||||
// First, start
|
||||
doStart();
|
||||
AndroidMock.verify(mockTask);
|
||||
AndroidMock.reset(mockTask);
|
||||
|
||||
// Then, shut down
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
mockTask.listenToPhoneState(
|
||||
same(phoneListener), eq(PhoneStateListener.LISTEN_NONE));
|
||||
tts.shutdown();
|
||||
AndroidMock.replay(mockTask, tts);
|
||||
task.shutdown();
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun() throws Exception {
|
||||
// Expect service data calls
|
||||
TripStatistics stats = new TripStatistics();
|
||||
|
||||
// Expect announcement building call
|
||||
expect(mockTask.getAnnouncement(same(stats))).andStubReturn(ANNOUNCEMENT);
|
||||
|
||||
// Put task in "ready" state
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isLanguageAvailable(DEFAULT_LOCALE)).andStubReturn(TextToSpeech.LANG_AVAILABLE);
|
||||
expect(tts.setLanguage(DEFAULT_LOCALE)).andReturn(TextToSpeech.LANG_AVAILABLE);
|
||||
expect(tts.setSpeechRate(AnnouncementPeriodicTask.TTS_SPEECH_RATE)).andReturn(
|
||||
TextToSpeech.SUCCESS);
|
||||
expect(tts.setOnUtteranceCompletedListener((OnUtteranceCompletedListener) EasyMock.anyObject()))
|
||||
.andReturn(0);
|
||||
|
||||
// Expect actual announcement call
|
||||
expect(
|
||||
tts.speak(eq(ANNOUNCEMENT), eq(TextToSpeech.QUEUE_FLUSH),
|
||||
eq(AnnouncementPeriodicTask.SPEECH_PARAMS))).andReturn(0);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.announce(stats);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_notReady() throws Exception {
|
||||
// Put task in "not ready" state
|
||||
startTask(TextToSpeech.ERROR);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_duringCall() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(false);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, null);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_ringWhileSpeaking() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(true);
|
||||
expect(tts.stop()).andReturn(TextToSpeech.SUCCESS);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
// Update the state to ringing - this should stop the current announcement.
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
|
||||
|
||||
// Run the announcement - this should do nothing.
|
||||
task.run(null);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_whileRinging() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(false);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_noService() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_noStats() throws Exception {
|
||||
// Expect service data calls
|
||||
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time zero.
|
||||
*/
|
||||
public void testGetAnnounceTime_time_zero() {
|
||||
long time = 0; // 0 seconds
|
||||
assertEquals("0 minutes 0 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time one.
|
||||
*/
|
||||
public void testGetAnnounceTime_time_one() {
|
||||
long time = 1 * 1000; // 1 second
|
||||
assertEquals("0 minutes 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
|
||||
* numbers with the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_singular_has_hour() {
|
||||
long time = (1 * 60 * 60 * 1000) + (1 * 60 * 1000) + (1 * 1000); // 1 hour 1 minute 1 second
|
||||
assertEquals("1 hour 1 minute 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
|
||||
* with the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_plural_has_hour() {
|
||||
long time = (2 * 60 * 60 * 1000) + (2 * 60 * 1000) + (2 * 1000); // 2 hours 2 minutes 2 seconds
|
||||
assertEquals("2 hours 2 minutes 2 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
|
||||
* numbers without the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_singular_no_hour() {
|
||||
long time = (1 * 60 * 1000) + (1 * 1000); // 1 minute 1 second
|
||||
assertEquals("1 minute 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
|
||||
* without the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_plural_no_hour() {
|
||||
long time = (2 * 60 * 1000) + (2 * 1000); // 2 minutes 2 seconds
|
||||
assertEquals("2 minutes 2 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
private void startTask(int state) {
|
||||
AndroidMock.resetToNice(tts);
|
||||
AndroidMock.replay(tts);
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
ttsInitListener.onInit(state);
|
||||
AndroidMock.resetToDefault(tts);
|
||||
}
|
||||
|
||||
private void doStart() {
|
||||
mockTask.listenToPhoneState(capture(phoneListenerCapture),
|
||||
eq(PhoneStateListener.LISTEN_CALL_STATE));
|
||||
expect(mockTask.newTextToSpeech(
|
||||
same(getContext()), capture(initListenerCapture)))
|
||||
.andStubReturn(ttsDelegate);
|
||||
AndroidMock.replay(mockTask);
|
||||
task.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.stats;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link TripStatistics}.
|
||||
* This only tests non-trivial pieces of that class.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TripStatisticsTest extends TestCase {
|
||||
|
||||
private TripStatistics statistics;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
statistics = new TripStatistics();
|
||||
}
|
||||
|
||||
public void testSetBounds() {
|
||||
// This is not a trivial setter, conversion happens in it
|
||||
statistics.setBounds(12345, -34567, 56789, -98765);
|
||||
assertEquals(12345, statistics.getLeft());
|
||||
assertEquals(-34567, statistics.getTop());
|
||||
assertEquals(56789, statistics.getRight());
|
||||
assertEquals(-98765, statistics.getBottom());
|
||||
}
|
||||
|
||||
public void testMerge() {
|
||||
TripStatistics statistics2 = new TripStatistics();
|
||||
statistics.setStartTime(1000L); // Resulting start time
|
||||
statistics.setStopTime(2500L);
|
||||
statistics2.setStartTime(3000L);
|
||||
statistics2.setStopTime(4000L); // Resulting stop time
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics2.setTotalTime(1000L); // Result: 1500+1000
|
||||
statistics.setMovingTime(700L);
|
||||
statistics2.setMovingTime(600L); // Result: 700+600
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics2.setTotalDistance(350.0); // Result: 750+350
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics2.setTotalElevationGain(850.0); // Result: 850+50
|
||||
statistics.setMaxSpeed(60.0); // Resulting max speed
|
||||
statistics2.setMaxSpeed(30.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0); // Resulting min elevation
|
||||
statistics2.setMaxElevation(3575.0); // Resulting max elevation
|
||||
statistics2.setMinElevation(2800.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(-25.0); // Resulting min grade
|
||||
statistics2.setMaxGrade(35.0); // Resulting max grade
|
||||
statistics2.setMinGrade(0.0);
|
||||
|
||||
// Resulting bounds: -10000, 35000, 30000, -40000
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
statistics2.setBounds(-5000, 35000, 0, 20000);
|
||||
|
||||
statistics.merge(statistics2);
|
||||
|
||||
assertEquals(1000L, statistics.getStartTime());
|
||||
assertEquals(4000L, statistics.getStopTime());
|
||||
assertEquals(2500L, statistics.getTotalTime());
|
||||
assertEquals(1300L, statistics.getMovingTime());
|
||||
assertEquals(1100.0, statistics.getTotalDistance());
|
||||
assertEquals(900.0, statistics.getTotalElevationGain());
|
||||
assertEquals(statistics.getTotalDistance()/ (statistics.getMovingTime() / 1000.0), statistics.getMaxSpeed());
|
||||
assertEquals(-10000, statistics.getLeft());
|
||||
assertEquals(30000, statistics.getRight());
|
||||
assertEquals(35000, statistics.getTop());
|
||||
assertEquals(-40000, statistics.getBottom());
|
||||
assertEquals(1200.0, statistics.getMinElevation());
|
||||
assertEquals(3575.0, statistics.getMaxElevation());
|
||||
assertEquals(-25.0, statistics.getMinGrade());
|
||||
assertEquals(35.0, statistics.getMaxGrade());
|
||||
}
|
||||
|
||||
public void testGetAverageSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setTotalTime(50000); // in milliseconds
|
||||
assertEquals(20.0, statistics.getAverageSpeed());
|
||||
}
|
||||
|
||||
public void testGetAverageMovingSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setMovingTime(20000); // in milliseconds
|
||||
assertEquals(50.0, statistics.getAverageMovingSpeed());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link FileUtils}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class FileUtilsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#getPath(String...)}.
|
||||
*/
|
||||
public void testBuildExternalDirectoryPath() {
|
||||
String expectedName = Environment.getExternalStorageDirectory() + File.separator
|
||||
+ FileUtils.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator
|
||||
+ "c";
|
||||
String dirName = FileUtils.getPath("a", "b", "c");
|
||||
assertEquals(expectedName, dirName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
|
||||
* file is new.
|
||||
*/
|
||||
public void testBuildUniqueFileName_new() {
|
||||
String filename = FileUtils.buildUniqueFileName(new File("/dir"), "Filename", "ext");
|
||||
assertEquals("Filename.ext", filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
|
||||
* file exists already.
|
||||
*/
|
||||
public void testBuildUniqueFileName_exist() {
|
||||
// Expect "/default.prop" to exist on the phone/emulator
|
||||
String filename = FileUtils.buildUniqueFileName(new File("/"), "default", "prop");
|
||||
assertEquals("default(1).prop", filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#sanitizeFileName(String)} with special characters.
|
||||
* Verifies that they are sanitized.
|
||||
*/
|
||||
public void testSanitizeFileName() {
|
||||
String name = "Swim\10ming-^across:/the/ pacific (ocean).";
|
||||
String expected = "Swim_ming-^across_the_ pacific (ocean)_";
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in
|
||||
* Chinese and Russian). Verifies that they are allowed.
|
||||
*/
|
||||
public void testSanitizeFileName_i18n() {
|
||||
String name = "您好-привет";
|
||||
String expected = "您好-привет";
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32
|
||||
* characters. Verifies that they are allowed.
|
||||
*/
|
||||
public void testSanitizeFileName_special_characters() {
|
||||
String name = "$%'-_@~`!(){}^#&+,;=[] ";
|
||||
String expected = "$%'-_@~`!(){}^#&+,;=[] ";
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped
|
||||
* characters in a row. Verifies that they are collapsed into one underscore.
|
||||
*/
|
||||
public void testSanitizeFileName_collapse() {
|
||||
String name = "hello//there";
|
||||
String expected = "hello_there";
|
||||
assertEquals(expected, FileUtils.sanitizeFileName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link FileUtils#truncateFileName(File, String, String)}. Verifies
|
||||
* the a long file name is truncated.
|
||||
*/
|
||||
public void testTruncateFileName() {
|
||||
File directory = new File("/dir1/dir2/");
|
||||
String suffix = ".gpx";
|
||||
char[] name = new char[FileUtils.MAX_FAT32_PATH_LENGTH];
|
||||
for (int i = 0; i < name.length; i++) {
|
||||
name[i] = 'a';
|
||||
}
|
||||
String nameString = new String(name);
|
||||
String truncated = FileUtils.truncateFileName(directory, nameString, suffix);
|
||||
|
||||
for (int i = 0; i < truncated.length(); i++) {
|
||||
assertEquals('a', truncated.charAt(i));
|
||||
}
|
||||
assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH,
|
||||
new File(directory, truncated + suffix).getPath().length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Tests for {@link StringUtils}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class StringUtilsTest {
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatDateTimeIso8601(long)}.
|
||||
*/
|
||||
public void testFormatDateTimeIso8601() {
|
||||
Assert.assertEquals("1970-01-01T00:00:12.345Z", StringUtils.formatDateTimeIso8601(12345));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatElapsedTime(long)}.
|
||||
*/
|
||||
public void testformatElapsedTime() {
|
||||
// 1 second
|
||||
Assert.assertEquals("00:01", StringUtils.formatElapsedTime(1000));
|
||||
// 10 seconds
|
||||
Assert.assertEquals("00:10", StringUtils.formatElapsedTime(10000));
|
||||
// 1 minute
|
||||
Assert.assertEquals("01:00", StringUtils.formatElapsedTime(60000));
|
||||
// 10 minutes
|
||||
Assert.assertEquals("10:00", StringUtils.formatElapsedTime(600000));
|
||||
// 1 hour
|
||||
Assert.assertEquals("1:00:00", StringUtils.formatElapsedTime(3600000));
|
||||
// 10 hours
|
||||
Assert.assertEquals("10:00:00", StringUtils.formatElapsedTime(36000000));
|
||||
// 100 hours
|
||||
Assert.assertEquals("100:00:00", StringUtils.formatElapsedTime(360000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatElapsedTimeWithHour(long)}.
|
||||
*/
|
||||
public void testformatElapsedTimeWithHour() {
|
||||
// 1 second
|
||||
Assert.assertEquals("0:00:01", StringUtils.formatElapsedTimeWithHour(1000));
|
||||
// 10 seconds
|
||||
Assert.assertEquals("0:00:10", StringUtils.formatElapsedTimeWithHour(10000));
|
||||
// 1 minute
|
||||
Assert.assertEquals("0:01:00", StringUtils.formatElapsedTimeWithHour(60000));
|
||||
// 10 minutes
|
||||
Assert.assertEquals("0:10:00", StringUtils.formatElapsedTimeWithHour(600000));
|
||||
// 1 hour
|
||||
Assert.assertEquals("1:00:00", StringUtils.formatElapsedTimeWithHour(3600000));
|
||||
// 10 hours
|
||||
Assert.assertEquals("10:00:00", StringUtils.formatElapsedTimeWithHour(36000000));
|
||||
// 100 hours
|
||||
Assert.assertEquals("100:00:00", StringUtils.formatElapsedTimeWithHour(360000000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatDistance(android.content.Context, double,
|
||||
* boolean)}.
|
||||
*/
|
||||
public void testFormatDistance() {
|
||||
// A large number in metric
|
||||
Assert.assertEquals("5.00 km", StringUtils.formatDistance(InstrumentationRegistry.getInstrumentation().getContext(), 5000, true));
|
||||
// A large number in imperial
|
||||
Assert.assertEquals("3.11 mi", StringUtils.formatDistance(InstrumentationRegistry.getInstrumentation().getContext(), 5000, false));
|
||||
// A small number in metric
|
||||
Assert.assertEquals("100.00 m", StringUtils.formatDistance(InstrumentationRegistry.getInstrumentation().getContext(), 100, true));
|
||||
// A small number in imperial
|
||||
Assert.assertEquals("328.08 ft", StringUtils.formatDistance(InstrumentationRegistry.getInstrumentation().getContext(), 100, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatCData(String)}.
|
||||
*/
|
||||
public void testFormatCData() {
|
||||
Assert.assertEquals("<![CDATA[hello]]>", StringUtils.formatCData("hello"));
|
||||
Assert.assertEquals("<![CDATA[hello]]]]><![CDATA[>there]]>", StringUtils.formatCData("hello]]>there"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTime(String)}.
|
||||
*/
|
||||
public void testGetTime() {
|
||||
assertGetTime("2010-05-04T03:02:01", 2010, 5, 4, 3, 2, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTime(String)} with fractional seconds.
|
||||
*/
|
||||
public void testGetTime_fractional() {
|
||||
assertGetTime("2010-05-04T03:02:01.3", 2010, 5, 4, 3, 2, 1, 300);
|
||||
assertGetTime("2010-05-04T03:02:01.35", 2010, 5, 4, 3, 2, 1, 350);
|
||||
assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352);
|
||||
assertGetTime("2010-05-04T03:02:01.3525Z", 2010, 5, 4, 3, 2, 1, 352);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTime(String)} with time zone.
|
||||
*/
|
||||
public void testGetTime_timezone() {
|
||||
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01+01:00", 2010, 5, 4, 2, 2, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01+10:30", 2010, 5, 3, 16, 32, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01-09:30", 2010, 5, 4, 12, 32, 1, 0);
|
||||
assertGetTime("2010-05-04T03:02:01-05:00", 2010, 5, 4, 8, 2, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTime(String)} with fractional seconds and time
|
||||
* zone.
|
||||
*/
|
||||
public void testGetTime_fractionalAndTimezone() {
|
||||
assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352);
|
||||
assertGetTime("2010-05-04T03:02:01.47+00:00", 2010, 5, 4, 3, 2, 1, 470);
|
||||
assertGetTime("2010-05-04T03:02:01.5791+03:00", 2010, 5, 4, 0, 2, 1, 579);
|
||||
assertGetTime("2010-05-04T03:02:01.8-05:30", 2010, 5, 4, 8, 32, 1, 800);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link StringUtils#getTime(String)} returns the expected
|
||||
* values.
|
||||
*
|
||||
* @param xmlDateTime the xml date time string
|
||||
* @param year the expected year
|
||||
* @param month the expected month
|
||||
* @param day the expected day
|
||||
* @param hour the expected hour
|
||||
* @param minute the expected minute
|
||||
* @param second the expected second
|
||||
* @param millisecond the expected milliseconds
|
||||
*/
|
||||
private void assertGetTime(String xmlDateTime, int year, int month, int day, int hour, int minute,
|
||||
int second, int millisecond) {
|
||||
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
calendar.set(year, month - 1, day, hour, minute, second);
|
||||
calendar.set(GregorianCalendar.MILLISECOND, millisecond);
|
||||
Assert.assertEquals(calendar.getTimeInMillis(), StringUtils.getTime(xmlDateTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTimeParts(long)} with a positive number.
|
||||
*/
|
||||
public void testGetTimeParts_postive() {
|
||||
int[] parts = StringUtils.getTimeParts(61000);
|
||||
Assert.assertEquals(1, parts[0]);
|
||||
Assert.assertEquals(1, parts[1]);
|
||||
Assert.assertEquals(0, parts[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTimeParts(long)} with a negative number.
|
||||
*/
|
||||
public void testGetTimeParts_negative() {
|
||||
int[] parts = StringUtils.getTimeParts(-61000);
|
||||
Assert.assertEquals(-1, parts[0]);
|
||||
Assert.assertEquals(-1, parts[1]);
|
||||
Assert.assertEquals(0, parts[2]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Tests {@link TrackNameUtils}.
|
||||
*
|
||||
* @author Matthew Simmons
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackNameUtilsTest {
|
||||
|
||||
private static final long TRACK_ID = 1L;
|
||||
private static final long START_TIME = 1288213406000L;
|
||||
|
||||
private static final Context CONTEXT = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
|
||||
/**
|
||||
* Tests when the track_name_key is
|
||||
* settings_recording_track_name_date_local_value.
|
||||
*/
|
||||
public void testTrackName_date_local() {
|
||||
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_date_local_value));
|
||||
Assert.assertEquals(StringUtils.formatDateTime(CONTEXT, START_TIME),
|
||||
TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the track_name_key is
|
||||
* settings_recording_track_name_date_iso_8601_value.
|
||||
*/
|
||||
public void testTrackName_date_iso_8601() {
|
||||
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_date_iso_8601_value));
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
TrackNameUtils.ISO_8601_FORMAT, Locale.US);
|
||||
Assert.assertEquals(simpleDateFormat.format(new Date(START_TIME)),
|
||||
TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the track_name_key is
|
||||
* settings_recording_track_name_number_value.
|
||||
*/
|
||||
public void testTrackName_number() {
|
||||
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_number_value));
|
||||
Assert.assertEquals(
|
||||
"Track " + TRACK_ID, TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME, null));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user