forked from upstream-mirrors/OpenTracks
368 lines
11 KiB
Java
368 lines
11 KiB
Java
// Copyright 2010 Google Inc. All Rights Reserved.
|
|
|
|
package com.google.android.apps.mytracks.io;
|
|
|
|
import com.google.android.apps.mytracks.MyTracksConstants;
|
|
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.TrackBuffer;
|
|
import com.google.android.apps.mytracks.content.Waypoint;
|
|
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
|
|
|
|
import android.content.Context;
|
|
import android.database.Cursor;
|
|
import android.location.Location;
|
|
import android.test.AndroidTestCase;
|
|
|
|
import org.easymock.EasyMock;
|
|
import org.easymock.IAnswer;
|
|
|
|
import static org.easymock.EasyMock.expect;
|
|
import static org.easymock.EasyMock.isA;
|
|
import static org.easymock.EasyMock.same;
|
|
import org.easymock.IMocksControl;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.OutputStream;
|
|
|
|
/**
|
|
* Tests for the track writer.
|
|
*
|
|
* @author Rodrigo Damazio
|
|
*/
|
|
public class TrackWriterTest extends AndroidTestCase {
|
|
/**
|
|
* {@link TrackWriter} subclass which mocks out methods called from
|
|
* {@link TrackWriter#openFile}.
|
|
*/
|
|
private static final class OpenFileTrackWriter extends TrackWriter {
|
|
private final ByteArrayOutputStream stream;
|
|
private final boolean canWrite;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param stream the stream to return from
|
|
* {@link TrackWriter#newOutputStream}, or null to throw a
|
|
* {@link FileNotFoundException}
|
|
* @param canWrite the value that {@link TrackWriter#canWriteFile} will
|
|
* return
|
|
*/
|
|
private OpenFileTrackWriter(Context context,
|
|
MyTracksProviderUtils providerUtils, Track track,
|
|
TrackFormatWriter writer, ByteArrayOutputStream stream,
|
|
boolean canWrite) {
|
|
super(context, providerUtils, track, writer);
|
|
|
|
this.stream = stream;
|
|
this.canWrite = canWrite;
|
|
}
|
|
|
|
@Override
|
|
protected boolean canWriteFile() {
|
|
return canWrite;
|
|
}
|
|
|
|
@Override
|
|
protected OutputStream newOutputStream(String fileName)
|
|
throws FileNotFoundException {
|
|
assertEquals(FULL_TRACK_NAME, fileName);
|
|
|
|
if (stream == null) {
|
|
throw new FileNotFoundException();
|
|
}
|
|
|
|
return stream;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@link TrackWriter} subclass which mocks out methods called from
|
|
* {@link TrackWriter#writeTrack}.
|
|
*/
|
|
private final class WriteTracksTrackWriter extends TrackWriter {
|
|
private final boolean openResult;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param openResult the return value for {@link TrackWriter#openFile}
|
|
*/
|
|
private WriteTracksTrackWriter(Context context,
|
|
MyTracksProviderUtils providerUtils, Track track,
|
|
TrackFormatWriter writer, boolean openResult) {
|
|
super(context, providerUtils, track, writer);
|
|
this.openResult = openResult;
|
|
}
|
|
|
|
@Override
|
|
protected boolean openFile() {
|
|
openFileCalls++;
|
|
return openResult;
|
|
}
|
|
|
|
@Override
|
|
void writeDocument() {
|
|
writeDocumentCalls++;
|
|
}
|
|
|
|
@Override
|
|
protected void runOnUiThread(Runnable runnable) {
|
|
runnable.run();
|
|
}
|
|
}
|
|
|
|
private static final long TRACK_ID = 1234567L;
|
|
private static final String DEFAULT_DIR = "default/dir";
|
|
private static final String EXTENSION = "ext";
|
|
private static final String TRACK_NAME = "Swimming across the pacific";
|
|
private static final String TRACK_SANITIZED_NAME = "Swimmingacrossthepacific";
|
|
private static final String FULL_TRACK_NAME = "Swimmingacrossthepacific.ext";
|
|
|
|
private Track track;
|
|
private TrackFormatWriter formatWriter;
|
|
private TrackWriter writer;
|
|
private IMocksControl mocksControl;
|
|
private MyTracksProviderUtils providerUtils;
|
|
private Factory oldProviderUtilsFactory;
|
|
|
|
// State used in specific tests
|
|
private int writeDocumentCalls;
|
|
private int openFileCalls;
|
|
|
|
@Override
|
|
protected void setUp() throws Exception {
|
|
super.setUp();
|
|
|
|
mocksControl = EasyMock.createStrictControl();
|
|
formatWriter = mocksControl.createMock(TrackFormatWriter.class);
|
|
providerUtils = mocksControl.createMock(MyTracksProviderUtils.class);
|
|
oldProviderUtilsFactory =
|
|
TestingProviderUtilsFactory.installWithInstance(providerUtils);
|
|
|
|
expect(formatWriter.getDefaultDirectory()).andStubReturn(DEFAULT_DIR);
|
|
expect(formatWriter.getExtension()).andStubReturn(EXTENSION);
|
|
|
|
track = new Track();
|
|
track.setName(TRACK_NAME);
|
|
track.setId(TRACK_ID);
|
|
}
|
|
|
|
@Override
|
|
protected void tearDown() throws Exception {
|
|
TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory);
|
|
super.tearDown();
|
|
}
|
|
|
|
public void testWriteTrack() {
|
|
writer = new WriteTracksTrackWriter(getContext(), providerUtils, track,
|
|
formatWriter, true);
|
|
|
|
// Expect the completion callback to be run
|
|
Runnable completionCallback = mocksControl.createMock(Runnable.class);
|
|
completionCallback.run();
|
|
|
|
mocksControl.replay();
|
|
writer.setOnCompletion(completionCallback);
|
|
writer.writeTrack();
|
|
|
|
assertEquals(1, writeDocumentCalls);
|
|
assertEquals(1, openFileCalls);
|
|
mocksControl.verify();
|
|
}
|
|
|
|
public void testWriteTrack_openFails() {
|
|
writer = new WriteTracksTrackWriter(getContext(), providerUtils, track,
|
|
formatWriter, false);
|
|
|
|
// Expect the completion callback to be run
|
|
Runnable completionCallback = mocksControl.createMock(Runnable.class);
|
|
completionCallback.run();
|
|
|
|
mocksControl.replay();
|
|
writer.setOnCompletion(completionCallback);
|
|
writer.writeTrack();
|
|
|
|
assertEquals(0, writeDocumentCalls);
|
|
assertEquals(1, openFileCalls);
|
|
mocksControl.verify();
|
|
}
|
|
|
|
public void testSanitizeName() {
|
|
assertEquals(TRACK_SANITIZED_NAME, TrackWriter.sanitizeName(TRACK_NAME));
|
|
}
|
|
|
|
public void testOpenFile() {
|
|
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
writer = new OpenFileTrackWriter(
|
|
getContext(), providerUtils, track, formatWriter, stream, true);
|
|
|
|
formatWriter.prepare(track, stream);
|
|
|
|
mocksControl.replay();
|
|
assertTrue(writer.openFile());
|
|
mocksControl.verify();
|
|
}
|
|
|
|
public void testOpenFile_cantWrite() {
|
|
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
writer = new OpenFileTrackWriter(
|
|
getContext(), providerUtils, track, formatWriter, stream, false);
|
|
|
|
mocksControl.replay();
|
|
assertFalse(writer.openFile());
|
|
mocksControl.verify();
|
|
}
|
|
|
|
public void testOpenFile_streamError() {
|
|
writer = new OpenFileTrackWriter(
|
|
getContext(), providerUtils, track, formatWriter, null, true);
|
|
|
|
mocksControl.replay();
|
|
assertFalse(writer.openFile());
|
|
mocksControl.verify();
|
|
}
|
|
|
|
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);
|
|
|
|
// Set expected mock behavior
|
|
formatWriter.writeHeader();
|
|
formatWriter.writeFooter();
|
|
formatWriter.close();
|
|
|
|
mocksControl.replay();
|
|
writer.writeDocument();
|
|
|
|
assertTrue(writer.wasSuccess());
|
|
mocksControl.verify();
|
|
}
|
|
|
|
public void testWriteDocument() {
|
|
writer = new TrackWriter(getContext(), providerUtils, track, formatWriter);
|
|
|
|
Location l1 = new Location("fake1");
|
|
Location l2 = new Location("fake2");
|
|
Location l3 = new Location("fake3");
|
|
Location l4 = new Location("fake4");
|
|
Location l5 = new Location("fake5");
|
|
Location l6 = new Location("fake6");
|
|
Waypoint p1 = new Waypoint();
|
|
Waypoint p2 = new Waypoint();
|
|
|
|
addLocations(l1, l2, l3, l4, l5, l6);
|
|
stubBufferFill(
|
|
new Location[] { l1, l2, l3, l4 },
|
|
new Location[] { l5, l6 });
|
|
|
|
track.setStopId(6L);
|
|
|
|
// Make location 3 invalid
|
|
l3.setLatitude(100);
|
|
|
|
// Begin the track
|
|
formatWriter.writeHeader();
|
|
formatWriter.writeBeginTrack(l1);
|
|
|
|
// Write locations 1-2
|
|
formatWriter.writeOpenSegment();
|
|
formatWriter.writeLocation(l1);
|
|
formatWriter.writeLocation(l2);
|
|
formatWriter.writeCloseSegment();
|
|
|
|
// Location 3 is not written - it's invalid
|
|
|
|
// Write locations 4-6
|
|
formatWriter.writeOpenSegment();
|
|
formatWriter.writeLocation(l4);
|
|
formatWriter.writeLocation(l5);
|
|
formatWriter.writeLocation(l6);
|
|
formatWriter.writeCloseSegment();
|
|
|
|
// End the track
|
|
formatWriter.writeEndTrack(l6);
|
|
|
|
// Expect reading/writing of the waypoints
|
|
Cursor cursor = mocksControl.createMock(Cursor.class);
|
|
expect(providerUtils.getWaypointsCursor(
|
|
TRACK_ID, 0, MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS))
|
|
.andStubReturn(cursor);
|
|
expect(cursor.moveToFirst()).andReturn(true);
|
|
expect(cursor.moveToNext()).andReturn(true);
|
|
expect(providerUtils.createWaypoint(cursor)).andReturn(p1);
|
|
formatWriter.writeWaypoint(p1);
|
|
expect(cursor.moveToNext()).andReturn(true);
|
|
expect(providerUtils.createWaypoint(cursor)).andReturn(p2);
|
|
formatWriter.writeWaypoint(p2);
|
|
expect(cursor.moveToNext()).andReturn(false).anyTimes();
|
|
cursor.close();
|
|
|
|
formatWriter.writeFooter();
|
|
formatWriter.close();
|
|
|
|
mocksControl.replay();
|
|
writer.writeDocument();
|
|
|
|
assertTrue(writer.wasSuccess());
|
|
mocksControl.verify();
|
|
}
|
|
|
|
private void addLocations(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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Defines the behaviour of filling the track buffer when a read is
|
|
* requested.
|
|
* The IDs of the locations will be their sequential number.
|
|
*
|
|
* @param feeds is a list of location arrays, each element of which
|
|
* will be fed into the track buffer on each call
|
|
*/
|
|
private void stubBufferFill(final Location[]... feeds) {
|
|
providerUtils.getTrackPoints(same(track), isA(TrackBuffer.class));
|
|
EasyMock.expectLastCall().andStubAnswer(new IAnswer<Void>() {
|
|
private int lastId = 1;
|
|
private int reads = 0;
|
|
|
|
@Override
|
|
public Void answer() throws Throwable {
|
|
// Get the buffer from the arguments
|
|
Object[] args = EasyMock.getCurrentArguments();
|
|
assertEquals(2, args.length);
|
|
TrackBuffer buffer = (TrackBuffer) args[1];
|
|
assertNotNull(buffer);
|
|
|
|
// Check that we still have data to feed to the buffer
|
|
if (reads >= feeds.length) {
|
|
fail("More buffer reads than expected");
|
|
}
|
|
|
|
// Fill the buffer
|
|
buffer.reset();
|
|
Location[] locations = feeds[reads];
|
|
for (int i = 0; i < locations.length; i++) {
|
|
buffer.add(locations[i], lastId + i);
|
|
}
|
|
|
|
// Update internal state
|
|
lastId += locations.length;
|
|
reads++;
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
}
|