Merging changes from main repository

This commit is contained in:
marian.steinbach
2011-01-12 19:17:47 +01:00
parent 9184827195
commit 6221ccb53b
19 changed files with 1005 additions and 400 deletions
@@ -2,31 +2,27 @@
package com.google.android.apps.mytracks.io;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.leq;
import static org.easymock.EasyMock.same;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.content.MyTracksProvider;
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.Waypoint;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
import android.content.Context;
import android.database.MatrixCursor;
import android.location.Location;
import android.provider.BaseColumns;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IArgumentMatcher;
import org.easymock.IMocksControl;
@@ -138,12 +134,19 @@ public class TrackWriterTest extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
Context 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);
oldProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(providerUtils);
mocksControl = EasyMock.createStrictControl();
formatWriter = mocksControl.createMock(TrackFormatWriter.class);
providerUtils = mocksControl.createMock(MyTracksProviderUtils.class);
oldProviderUtilsFactory =
TestingProviderUtilsFactory.installWithInstance(providerUtils);
expect(formatWriter.getExtension()).andStubReturn(EXTENSION);
track = new Track();
@@ -225,13 +228,6 @@ public class TrackWriterTest extends AndroidTestCase {
public void testWriteDocument_emptyTrack() {
writer = new TrackWriter(getContext(), providerUtils, track, formatWriter);
// Don't let it write any waypoints
expect(providerUtils.getWaypointsCursor(
TRACK_ID, 0, MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS))
.andStubReturn(null);
expect(providerUtils.getLocationsCursor(
eq(TRACK_ID), leq(0L), leq(0), eq(false))).andStubReturn(null);
// Set expected mock behavior
formatWriter.writeHeader();
formatWriter.writeFooter();
@@ -253,7 +249,7 @@ public class TrackWriterTest extends AndroidTestCase {
new Location("fake2"),
new Location("fake3"),
new Location("fake4"),
new Location("fake5"),
new Location("fake5")
};
Waypoint[] wps = { new Waypoint(), new Waypoint(), new Waypoint() };
@@ -262,37 +258,14 @@ public class TrackWriterTest extends AndroidTestCase {
// Make location 3 invalid
locs[2].setLatitude(100);
// Set up cursors
// We use fake columns since the cursor is only read by the provider utils
final MatrixCursor locCursor =
new MatrixCursor(new String[] { BaseColumns._ID }, 6);
for (int i = 1; i <= 6; i++) {
locCursor.newRow().add(i);
assertEquals(locs.length, providerUtils.bulkInsertTrackPoints(locs, locs.length, TRACK_ID));
for (int i = 0; i < wps.length; ++i) {
Waypoint wpt = wps[i];
wpt.setTrackId(TRACK_ID);
assertNotNull(providerUtils.insertWaypoint(wpt));
wpt.setId(i + 1);
}
expect(providerUtils.getLocationsCursor(
eq(TRACK_ID), leq(0L), leq(0), eq(false))).andStubReturn(locCursor);
providerUtils.fillLocation(same(locCursor), isA(Location.class));
EasyMock.expectLastCall().andStubAnswer(new IAnswer<Void>() {
@Override
public Void answer() throws Throwable {
Location loc = (Location) EasyMock.getCurrentArguments()[1];
loc.set(locs[locCursor.getPosition()]);
return null;
}
});
MatrixCursor wpCursor =
new MatrixCursor(new String[] { BaseColumns._ID }, 3);
wpCursor.newRow().add(1);
wpCursor.newRow().add(2);
wpCursor.newRow().add(3);
expect(providerUtils.getWaypointsCursor(
eq(TRACK_ID), leq(0L),
eq(MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS)))
.andStubReturn(wpCursor);
expect(providerUtils.createWaypoint(wpCursor))
.andStubAnswer(stubCursorToArray(wpCursor, wps));
// Begin the track
formatWriter.writeHeader();
@@ -317,8 +290,8 @@ public class TrackWriterTest extends AndroidTestCase {
formatWriter.writeEndTrack(locEq(locs[5]));
// Expect reading/writing of the waypoints (except the first)
formatWriter.writeWaypoint(wps[1]);
formatWriter.writeWaypoint(wps[2]);
formatWriter.writeWaypoint(wptEq(wps[1]));
formatWriter.writeWaypoint(wptEq(wps[2]));
formatWriter.writeFooter();
formatWriter.close();
@@ -330,6 +303,26 @@ public class TrackWriterTest extends AndroidTestCase {
mocksControl.verify();
}
private static Waypoint wptEq(final Waypoint wpt) {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object wptObj2) {
if (wptObj2 == null || wpt == null) return wpt == wptObj2;
Waypoint wpt2 = (Waypoint) wptObj2;
return wpt.getId() == wpt2.getId();
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("wptEq(");
buffer.append(wpt);
buffer.append(")");
}
});
return null;
}
private static Location locEq(final Location loc) {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
@@ -359,23 +352,14 @@ public class TrackWriterTest extends AndroidTestCase {
});
return null;
}
private <T> IAnswer<T> stubCursorToArray(
final MatrixCursor cursor, final T[] values) {
return new IAnswer<T>() {
@Override
public T answer() throws Throwable {
return values[cursor.getPosition()];
}
};
}
private void fillLocations(Location... locs) {
assertTrue(locs.length < 90);
for (int i = 0; i < locs.length; i++) {
Location location = locs[i];
location.setLatitude(i + 1);
location.setLongitude(i + 1);
location.setTime(i + 1000);
}
}
}
@@ -0,0 +1,101 @@
/*
* 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.docs;
import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
import android.content.Context;
import android.test.mock.MockContext;
import junit.framework.TestCase;
import java.io.IOException;
/**
* Tests for {@link DocsHelper}, with the exception of
* {@link DocsHelper#addTrackRow}, which is in
* {@link DocsHelper_AddTrackRowTest}.
*
* @author Matthew Simmons
*/
public class DocsHelperTest extends TestCase {
private Context mockContext = new MockContext();
// TODO(simmonmt): Use AndroidMock to mock this class. We do it the hard
// way because use of AndroidMock to mock GDataWrapper triggers a compile
// error in an unrelated file. Specifically, it causes a NoClassDefFound
// exception for com.google.wireless.gdata2.client.AuthenticationException,
// (wrongly) attributed to the first source file in the project. Using the
// @UsesMocks(GDataWrapper.class) annotation is enough -- you don't have to
// touch AndroidMock at all to get this failure.
// The bug is filed with Android Mock as
// http://code.google.com/p/android-mock/issues/detail?id=3
private class MockGDataWrapper extends GDataWrapper {
private final boolean returnValue;
MockGDataWrapper(boolean returnValue) {
this.returnValue = returnValue;
}
@Override
public boolean runQuery(QueryFunction queryFunction) {
return returnValue;
}
}
public void testCreateSpreadsheet_noException() throws Exception {
// Our mock GDataWrapper isn't able to affect the return value from
// DocsHelper#createSpreadsheet. As such, we're only able to simulate the
// case where there weren't any GData errors, but not spreadsheet ID was
// actually returned. createSpreadsheet is defined to return null in that
// situation.
assertNull(new DocsHelper().createSpreadsheet(
mockContext, new MockGDataWrapper(true), "sheetName"));
}
public void testCreateSpreadsheet_exception() throws Exception {
try {
new DocsHelper().createSpreadsheet(
mockContext, new MockGDataWrapper(false), "sheetName");
fail();
} catch (IOException expected) {}
}
public void testRequestSpreadsheetId_noException() throws Exception {
assertNull(new DocsHelper().requestSpreadsheetId(
new MockGDataWrapper(true), "sheetName"));
}
public void testRequestSpreadsheetId_exception() throws Exception {
try {
new DocsHelper().requestSpreadsheetId(new MockGDataWrapper(false),
"sheetName");
fail();
} catch (IOException expected) {}
}
public void testGetWorksheetId_noException() throws Exception {
assertNull(new DocsHelper().getWorksheetId(new MockGDataWrapper(true),
"sheetId"));
}
public void testGetWorksheetId_exception() throws Exception {
try {
new DocsHelper().getWorksheetId(new MockGDataWrapper(false), "sheetId");
fail();
} catch (IOException expected) {}
}
}
@@ -0,0 +1,159 @@
/*
* 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.docs;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.res.Resources;
import android.test.mock.MockContext;
import android.test.mock.MockResources;
import junit.framework.TestCase;
import java.io.IOException;
/**
* Tests for {@link DocsHelper#addTrackRow}
*
* @author Matthew Simmons
*/
public class DocsHelper_AddTrackRowTest extends TestCase {
private static final long TIME = 1288721514000L;
private static class StringWritingDocsHelper extends DocsHelper {
String writtenSheetUri = null;
String writtenData = null;
@Override
protected void writeRowData(AuthManager trixAuth, String worksheetUri,
String postText) {
writtenSheetUri = worksheetUri;
writtenData = postText;
}
}
public void testAddTrackRow_imperial() throws Exception {
StringWritingDocsHelper docsHelper = new StringWritingDocsHelper();
addTrackRow(docsHelper, false);
String expectedData =
"<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gsx='http://schemas.google.com/spreadsheets/2006/extended'>"
+ "<gsx:name><![CDATA[trackName]]></gsx:name>"
+ "<gsx:description><![CDATA[trackDescription]]></gsx:description>"
// We format the date here because we can't guarantee/force the timezone
+ "<gsx:date><![CDATA[" + String.format("%tc", TIME) + "]]></gsx:date>"
+ "<gsx:totaltime><![CDATA[0:00:05]]></gsx:totaltime>"
+ "<gsx:movingtime><![CDATA[0:00:04]]></gsx:movingtime>"
+ "<gsx:distance><![CDATA[12.43]]></gsx:distance>"
+ "<gsx:distanceunit><![CDATA[mile]]></gsx:distanceunit>"
+ "<gsx:averagespeed><![CDATA[8,947.75]]></gsx:averagespeed>"
+ "<gsx:averagemovingspeed><![CDATA[11,184.68]]>"
+ "</gsx:averagemovingspeed>"
+ "<gsx:maxspeed><![CDATA[3,355.40]]></gsx:maxspeed>"
+ "<gsx:speedunit><![CDATA[mph]]></gsx:speedunit>"
+ "<gsx:elevationgain><![CDATA[19,685]]></gsx:elevationgain>"
+ "<gsx:minelevation><![CDATA[-1,640]]></gsx:minelevation>"
+ "<gsx:maxelevation><![CDATA[1,804]]></gsx:maxelevation>"
+ "<gsx:elevationunit><![CDATA[feet]]></gsx:elevationunit>"
+ "<gsx:map>"
+ "<![CDATA[http://maps.google.com/maps/ms?msa=0&msid=trackMapId]]>"
+ "</gsx:map>"
+ "</entry>";
assertEquals(
"http://spreadsheets.google.com/feeds/list/ssid/wsid/private/full",
docsHelper.writtenSheetUri);
assertEquals(expectedData, docsHelper.writtenData);
}
public void testAddTrackRow_metric() throws Exception {
StringWritingDocsHelper docsHelper = new StringWritingDocsHelper();
addTrackRow(docsHelper, true);
// The imperial test verifies that the tags come out in the proper order,
// and with the proper names. We need only verify that the labels are
// correct, and that at least one of the unit-dependent value tags is
// correct.
assertTrue(docsHelper.writtenData.contains(
"<gsx:distanceunit><![CDATA[km]]></gsx:distanceunit>"));
assertTrue(docsHelper.writtenData.contains(
"<gsx:speedunit><![CDATA[kph]]></gsx:speedunit>"));
assertTrue(docsHelper.writtenData.contains(
"<gsx:elevationunit><![CDATA[meter]]></gsx:elevationunit>"));
assertTrue(docsHelper.writtenData.contains(
"<gsx:distance><![CDATA[20.00]]></gsx:distance>"));
}
@UsesMocks({AuthManager.class, MockContext.class, MockResources.class,
Track.class})
/** Adds a row to the spreadsheet, using the provided helper. */
private void addTrackRow(DocsHelper docsHelper, boolean useMetric)
throws IOException {
Resources mockResources = AndroidMock.createMock(MockResources.class);
if (useMetric) {
AndroidMock.expect(mockResources.getString(R.string.kilometer))
.andReturn("km");
AndroidMock.expect(mockResources.getString(R.string.kilometer_per_hour))
.andReturn("kph");
AndroidMock.expect(mockResources.getString(R.string.meter))
.andReturn("meter");
} else {
AndroidMock.expect(mockResources.getString(R.string.mile))
.andReturn("mile");
AndroidMock.expect(mockResources.getString(R.string.mile_per_hour))
.andReturn("mph");
AndroidMock.expect(mockResources.getString(R.string.feet))
.andReturn("feet");
}
AndroidMock.replay(mockResources);
Context mockContext = AndroidMock.createMock(MockContext.class);
AndroidMock.expect(mockContext.getResources())
.andReturn(mockResources).anyTimes();
AndroidMock.replay(mockContext);
AuthManager mockAuthManager = AndroidMock.createMock(AuthManager.class);
AndroidMock.replay(mockAuthManager);
TripStatistics stats = new TripStatistics();
stats.setStartTime(TIME);
stats.setTotalTime(5000);
stats.setMovingTime(4000);
stats.setTotalDistance(20000);
stats.setMaxSpeed(1500);
stats.setTotalElevationGain(6000);
stats.setMinElevation(-500);
stats.setMaxElevation(550);
Track track = new Track();
track.setName("trackName");
track.setDescription("trackDescription");
track.setMapId("trackMapId");
track.setStatistics(stats);
docsHelper.addTrackRow(mockContext, mockAuthManager, "ssid", "wsid",
track, useMetric);
}
}
@@ -0,0 +1,60 @@
/*
* 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.docs;
import junit.framework.TestCase;
/**
* This class tests {@link DocsTagBuilder}
*
* @author Matthew Simmons
*/
public class DocsTagBuilderTest extends TestCase {
public void testAppend() {
assertEquals("<gsx:tag><![CDATA[value]]></gsx:tag>",
new DocsTagBuilder(false).append("tag", "value").build());
}
public void testMultiAppend() {
String actual = new DocsTagBuilder(false)
.append("tag1", "value1")
.append("tag2", "value2")
.build();
assertEquals("<gsx:tag1><![CDATA[value1]]></gsx:tag1>"
+ "<gsx:tag2><![CDATA[value2]]></gsx:tag2>", actual);
}
public void testAppendLargeUnits_imperial() {
assertEquals("<gsx:tag><![CDATA[62.14]]></gsx:tag>",
new DocsTagBuilder(false).appendLargeUnits("tag", 100.0).build());
}
public void testAppendLargeUnits_metric() {
assertEquals("<gsx:tag><![CDATA[100.00]]></gsx:tag>",
new DocsTagBuilder(true).appendLargeUnits("tag", 100.0).build());
}
public void testAppendSmallUnits_imperial() {
assertEquals("<gsx:tag><![CDATA[328]]></gsx:tag>",
new DocsTagBuilder(false).appendSmallUnits("tag", 100.0).build());
}
public void testAppendSmallUnits_metric() {
assertEquals("<gsx:tag><![CDATA[100]]></gsx:tag>",
new DocsTagBuilder(true).appendSmallUnits("tag", 100.0).build());
}
}