Merging gingerbread changes to head.

This commit is contained in:
Rodrigo Damazio
2010-12-10 14:30:29 -02:00
parent 93b95954c4
commit 19d5fe1ba6
111 changed files with 5041 additions and 837 deletions
@@ -19,9 +19,9 @@ 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.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
@@ -77,7 +77,7 @@ public class GpxImporterTest extends AndroidTestCase {
DATE_FORMAT2.setTimeZone(utc);
}
// TODO use real files from different sources with more track points
// TODO: use real files from different sources with more track points.
private static final String VALID_TEST_GPX = "<gpx><trk><name><![CDATA["
+ TRACK_NAME + "]]></name><desc><![CDATA[" + TRACK_DESC
+ "]]></desc><trkseg>" + "<trkpt lat=\"" + TRACK_LAT_1 + "\" lon=\""
@@ -93,6 +93,12 @@ public class GpxImporterTest extends AndroidTestCase {
.replaceAll(TRACK_LAT_1, "1000.0");
private static final String INVALID_TIME_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_TIME_1, "invalid");
private static final String INVALID_ALTITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_ELE_1, "invalid");
private static final String INVALID_LATITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LAT_1, "invalid");
private static final String INVALID_LONGITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LON_1, "invalid");
private static final long TRACK_ID = 1;
private static final long TRACK_POINT_ID_1 = 1;
@@ -122,7 +128,7 @@ public class GpxImporterTest extends AndroidTestCase {
}
/**
* Test import success
* Test import success.
*/
public void testImportSuccess() throws Exception {
Capture<Track> trackParam = new Capture<Track>();
@@ -171,7 +177,7 @@ public class GpxImporterTest extends AndroidTestCase {
}
/**
* Test with invalid location - track should be deleted
* Test with invalid location - track should be deleted.
*/
public void testImportLocationFailure() throws ParserConfigurationException,
SAXException, IOException {
@@ -179,7 +185,7 @@ public class GpxImporterTest extends AndroidTestCase {
}
/**
* Test with invalid time - track should be deleted
* Test with invalid time - track should be deleted.
*/
public void testImportTimeFailure() throws ParserConfigurationException,
SAXException, IOException {
@@ -187,13 +193,37 @@ public class GpxImporterTest extends AndroidTestCase {
}
/**
* Test with invalid xml - track should be deleted
* Test with invalid xml - track should be deleted.
*/
public void testImportXMLFailure() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_XML_TEST_GPX);
}
/**
* Test with invalid altitude - track should be deleted.
*/
public void testImportInvalidAltitude() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_ALTITUDE_TEST_GPX);
}
/**
* Test with invalid latitude - track should be deleted.
*/
public void testImportInvalidLatitude() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_LATITUDE_TEST_GPX);
}
/**
* Test with invalid longitude - track should be deleted.
*/
public void testImportInvalidLongitude() throws ParserConfigurationException,
SAXException, IOException {
testInvalidXML(INVALID_LONGITUDE_TEST_GPX);
}
private void testInvalidXML(String xml) throws ParserConfigurationException,
IOException {
expect(providerUtils.insertTrack((Track) AndroidMock.anyObject()))
@@ -1,7 +1,8 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io;
import android.location.Location;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -38,11 +39,11 @@ public class TcxTrackWriterTest extends TrackFormatWriterTest {
/**
* Asserts that the given tags describe the given points, in the same order.
*/
private void assertTagsMatchPoints(List<Element> tags, Location... locs) {
private void assertTagsMatchPoints(List<Element> tags, MyTracksLocation... locs) {
assertEquals(locs.length, tags.size());
for (int i = 0; i < locs.length; i++) {
Element tag = tags.get(i);
Location loc = locs[i];
MyTracksLocation loc = locs[i];
assertTagMatchesLocation(tag, loc);
}
@@ -51,7 +52,7 @@ public class TcxTrackWriterTest extends TrackFormatWriterTest {
/**
* Asserts that the given tag describes the given location.
*/
private void assertTagMatchesLocation(Element tag, Location loc) {
private void assertTagMatchesLocation(Element tag, MyTracksLocation loc) {
Element posTag = getChildElement(tag, "Position");
assertEquals(Double.toString(loc.getLatitude()),
getChildTextValue(posTag, "LatitudeDegrees"));
@@ -62,5 +63,16 @@ public class TcxTrackWriterTest extends TrackFormatWriterTest {
getChildTextValue(tag, "Time"));
assertEquals(Double.toString(loc.getAltitude()),
getChildTextValue(tag, "AltitudeMeters"));
assertTrue(loc.getSensorDataSet() != null);
Sensor.SensorDataSet sds = loc.getSensorDataSet();
List<Element> bpm = getChildElements(tag, "HeartRateBpm", 1);
assertEquals(Integer.toString(sds.getHeartRate().getValue()),
getChildTextValue(bpm.get(0), "Value"));
List<Element> ext = getChildElements(tag, "Extensions", 1);
List<Element> tpx = getChildElements(ext.get(0), "TPX", 1);
assertEquals(Integer.toString(sds.getPower().getValue()),
getChildTextValue(tpx.get(0), "Watts"));
}
}
@@ -1,10 +1,11 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import android.location.Location;
import android.test.AndroidTestCase;
import org.w3c.dom.Document;
@@ -46,7 +47,7 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase {
private static final int BUFFER_SIZE = 10240;
protected static final long TRACK_ID = 12345L;
protected Track track;
protected Location location1, location2, location3, location4;
protected MyTracksLocation location1, location2, location3, location4;
protected Waypoint wp1, wp2;
@Override
@@ -58,10 +59,10 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase {
track.setName(TRACK_NAME);
track.setDescription(TRACK_DESCRIPTION);
location1 = new Location("mock");
location2 = new Location("mock");
location3 = new Location("mock");
location4 = new Location("mock");
location1 = new MyTracksLocation("mock");
location2 = new MyTracksLocation("mock");
location3 = new MyTracksLocation("mock");
location4 = new MyTracksLocation("mock");
populateLocations(location1, location2, location3, location4);
wp1 = new Waypoint();
@@ -77,13 +78,24 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase {
/**
* Populates the given locations with coordinates and time.
*/
protected void populateLocations(Location... locs) {
protected void populateLocations(MyTracksLocation... locs) {
for (int i = 0; i < locs.length; i++) {
Location loc = locs[i];
MyTracksLocation loc = locs[i];
loc.setAltitude(i * 1000);
loc.setLatitude(i);
loc.setLongitude(-i);
loc.setTime(10000000 + i * 1000);
Sensor.SensorData.Builder hr = Sensor.SensorData.newBuilder()
.setValue(100 + i)
.setState(Sensor.SensorState.SENDING);
Sensor.SensorData.Builder power = Sensor.SensorData.newBuilder()
.setValue(400 + i)
.setState(Sensor.SensorState.SENDING);
Sensor.SensorDataSet sds =
Sensor.SensorDataSet.newBuilder().setHeartRate(hr.build())
.setPower(power)
.build();
loc.setSensorData(sds);
}
}
@@ -139,7 +151,7 @@ public abstract class TrackFormatWriterTest extends AndroidTestCase {
}
/**
* Returns all child elements of a given parent which gave the given name.
* Returns all child elements of a given parent which have the given name.
*
* @param parent the parent to get children from
* @param elementName the element name to look for
@@ -1,72 +0,0 @@
/*
* 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 com.google.android.apps.mytracks.util.ApiFeatures;
import android.test.AndroidTestCase;
/**
* Tests for {@link SignalStrengthTaskFactoryTest}.
* These tests require Eclair+ (API level 7) to run.
*
* @author Rodrigo Damazio
*/
public class SignalStrengthTaskFactoryTest extends AndroidTestCase {
/**
* Mock version of the {@link ApiFeatures} class.
*/
private static class MockApiFeatures extends ApiFeatures {
private boolean hasModernStrength;
public void setHasModernSignalStrength(boolean hasModernStrength) {
this.hasModernStrength = hasModernStrength;
}
@Override
public boolean hasModernSignalStrength() {
return hasModernStrength;
}
}
private MockApiFeatures apiFeatures;
@Override
protected void setUp() throws Exception {
super.setUp();
apiFeatures = new MockApiFeatures();
}
public void testCreate() {
apiFeatures.setHasModernSignalStrength(true);
SignalStrengthTaskFactory factory =
new SignalStrengthTaskFactory(apiFeatures);
PeriodicTask task = factory.create(getContext());
assertTrue(task.getClass().getName(),
task instanceof SignalStrengthTaskModern);
}
public void testCreate_legacy() {
apiFeatures.setHasModernSignalStrength(false);
SignalStrengthTaskFactory factory =
new SignalStrengthTaskFactory(apiFeatures);
PeriodicTask task = factory.create(getContext());
assertTrue(task.getClass().getName(), task instanceof SignalStrengthTask);
}
}
@@ -26,10 +26,12 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
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.content.SharedPreferences.Editor;
import android.location.Location;
@@ -39,7 +41,9 @@ import android.test.ServiceTestCase;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
@@ -130,9 +134,9 @@ public class TrackRecordingServiceTest
@Override
protected void setUp() throws Exception {
super.setUp();
ApiFeatures.injectInstance(new MockApiFeatures());
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
@@ -141,14 +145,14 @@ public class TrackRecordingServiceTest
provider.attachInfo(context, null);
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
setContext(context);
providerUtils = MyTracksProviderUtils.Factory.get(context);
sharedPreferences = context.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0);
// Let's use default values.
sharedPreferences.edit().clear().commit();
// Disable auto resume by default.
updateAutoResumePrefs(0, -1);
// No recording track.
@@ -168,7 +172,7 @@ public class TrackRecordingServiceTest
IBinder service = bindService(createStartIntent());
assertNotNull(service);
}
@MediumTest
public void testResumeAfterReboot_shouldResume() throws Exception {
// Insert a dummy track and mark it as recording track.
@@ -214,7 +218,7 @@ public class TrackRecordingServiceTest
startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true);
startService(startIntent);
assertNotNull(getService());
assertTrue(getService().isRecording());
}
@@ -237,7 +241,7 @@ public class TrackRecordingServiceTest
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertEquals(-1, service.getRecordingTrackId());
}
@MediumTest
public void testResumeAfterReboot_expiredTrack() throws Exception {
// Insert a dummy track last updated 20 min ago.
@@ -251,7 +255,7 @@ public class TrackRecordingServiceTest
startIntent.putExtra(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());
@@ -284,17 +288,17 @@ public class TrackRecordingServiceTest
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(-1, service.getRecordingTrackId());
}
@MediumTest
public void testRecording_oldTracks() throws Exception {
createDummyTrack(123, -1, false);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
assertEquals(-1, service.getRecordingTrackId());
@@ -304,22 +308,71 @@ public class TrackRecordingServiceTest
public void testRecording_orphanedRecordingTrack() throws Exception {
// Just set recording track to a bogus value.
setRecordingTrack(256);
// Make sure that the service will not start recording and will clear
// the bogus track.
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
assertEquals(-1, 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 context, 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());
@@ -329,15 +382,26 @@ public class TrackRecordingServiceTest
assertEquals(id, sharedPreferences.getLong(
context.getString(R.string.recording_track_key), -1));
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), -1));
context.unregisterReceiver(startReceiver);
}
@MediumTest
public void testStartNewTrack_alreadyRecording() throws Exception {
createDummyTrack(123, -1, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
try {
service.startNewTrack();
fail("Expecting IllegalStateException");
@@ -347,12 +411,17 @@ public class TrackRecordingServiceTest
assertEquals(123, sharedPreferences.getLong(
context.getString(R.string.recording_track_key), 0));
assertEquals(123, 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(123, -1, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
@@ -362,8 +431,19 @@ public class TrackRecordingServiceTest
assertEquals(-1, sharedPreferences.getLong(
context.getString(R.string.recording_track_key), 0));
assertEquals(-1, 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(123, broadcastIntent.getLongExtra(
context.getString(R.string.track_id_broadcast_extra), -1));
context.unregisterReceiver(stopReceiver);
}
@MediumTest
public void testEndCurrentTrack_noRecording() throws Exception {
ITrackRecordingService service = bindAndGetService(createStartIntent());
@@ -561,16 +641,6 @@ public class TrackRecordingServiceTest
functionalTest(R.string.min_recording_distance_key, 2);
}
@MediumTest
public void testWithProperties_noSignalSamplingFreq() throws Exception {
functionalTest(R.string.signal_sampling_frequency_key, (Object) null);
}
@MediumTest
public void testWithProperties_defaultSignalSamplingFreq() throws Exception {
functionalTest(R.string.signal_sampling_frequency_key, 1);
}
@MediumTest
public void testWithProperties_noSplitFreq() throws Exception {
functionalTest(R.string.split_frequency_key, (Object) null);
@@ -622,6 +692,17 @@ public class TrackRecordingServiceTest
functionalTest(R.string.min_required_accuracy_key, 500);
}
@MediumTest
public void testWithProperties_noSensorType() throws Exception {
functionalTest(R.string.sensor_type_key, (Object) null);
}
@MediumTest
public void testWithProperties_zephyrSensorType() throws Exception {
functionalTest(R.string.sensor_type_key,
context.getString(R.string.zephyr_sensor_type));
}
private ITrackRecordingService bindAndGetService(Intent intent) {
ITrackRecordingService service = ITrackRecordingService.Stub.asInterface(
bindService(intent));
@@ -0,0 +1,39 @@
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.maps.mytracks.R;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
public class SensorManagerFactoryTest extends AndroidTestCase {
private SharedPreferences sharedPreferences;
@Override
protected void setUp() throws Exception {
super.setUp();
sharedPreferences = getContext().getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0);
// Let's use default values.
sharedPreferences.edit().clear().commit();
}
@SmallTest
public void testDefaultSettings() throws Exception {
assertNull(SensorManagerFactory.getSensorManager(getContext()));
}
@SmallTest
public void testCreateZephyr() throws Exception {
sharedPreferences.edit()
.putString(getContext().getString(R.string.sensor_type_key),
getContext().getString(R.string.zephyr_sensor_type))
.commit();
SensorManager sm = SensorManagerFactory.getSensorManager(getContext());
assertNotNull(sm);
assertTrue(sm instanceof ZephyrSensorManager);
}
}
@@ -0,0 +1,36 @@
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.content.Sensor;
import junit.framework.TestCase;
public class ZephyrMessageParserTest extends TestCase {
ZephyrMessageParser parser = new ZephyrMessageParser();
public void testIsValid() {
byte[] buf = new byte[60];
assertFalse(parser.isValid(buf));
buf[0] = 0x02;
assertFalse(parser.isValid(buf));
buf[59] = 0x03;
assertTrue(parser.isValid(buf));
}
public void testParseBuffer() {
byte[] buf = new byte[60];
buf[12] = 50;
Sensor.SensorDataSet sds = parser.parseBuffer(buf);
assertTrue(sds.hasHeartRate());
assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING);
assertEquals(50, sds.getHeartRate().getValue());
}
public void testFindNextAlignment() {
byte[] buf = new byte[60];
assertEquals(-1, parser.findNextAlignment(buf));
buf[10] = 0x03;
buf[11] = 0x02;
assertEquals(10, parser.findNextAlignment(buf));
}
}
@@ -65,17 +65,6 @@ public class ApiFeaturesTest extends TestCase {
}
}
public void testHasModernSignalStrength() {
for (int i = 3; i <= 6; i++) {
features.setApiLevel(i);
assertFalse(features.hasModernSignalStrength());
}
features.setApiLevel(7);
assertTrue(features.hasModernSignalStrength());
features.setApiLevel(8);
assertTrue(features.hasModernSignalStrength());
}
public void testGetApiPlatformAdapter() {
assertNotNull(features.getApiPlatformAdapter());
}