forked from upstream-mirrors/OpenTracks
Importing tests source
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the CSV track exporter.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class CsvTrackWriterTest extends TrackFormatWriterTest {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.Waypoint;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the GPX track exporter.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class GpxTrackWriterTest extends TrackFormatWriterTest {
|
||||||
|
|
||||||
|
public void testXmlOutput() throws Exception {
|
||||||
|
TrackFormatWriter writer = new GpxTrackWriter();
|
||||||
|
String result = writeTrack(writer);
|
||||||
|
Document doc = parseXmlDocument(result);
|
||||||
|
|
||||||
|
Element gpxTag = getChildElement(doc, "gpx");
|
||||||
|
Element trackTag = getChildElement(gpxTag, "trk");
|
||||||
|
assertEquals(TRACK_NAME, getChildTextValue(trackTag, "name"));
|
||||||
|
assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackTag, "desc"));
|
||||||
|
assertEquals(Long.toString(TRACK_ID),
|
||||||
|
getChildTextValue(trackTag, "number"));
|
||||||
|
List<Element> segmentTags = getChildElements(trackTag, "trkseg", 2);
|
||||||
|
Element segment1Tag = segmentTags.get(0);
|
||||||
|
Element segment2Tag = segmentTags.get(1);
|
||||||
|
List<Element> seg1PointTags = getChildElements(segment1Tag, "trkpt", 2);
|
||||||
|
List<Element> seg2PointTags = getChildElements(segment2Tag, "trkpt", 2);
|
||||||
|
assertTagsMatchPoints(seg1PointTags, location1, location2);
|
||||||
|
assertTagsMatchPoints(seg2PointTags, location3, location4);
|
||||||
|
List<Element> waypointTags = getChildElements(gpxTag, "wpt", 2);
|
||||||
|
assertTagsMatchWaypoints(waypointTags, wp1, wp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the given tags describe the given waypoints, in the same
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
protected void assertTagsMatchWaypoints(List<Element> tags, Waypoint... wps) {
|
||||||
|
assertEquals(wps.length, tags.size());
|
||||||
|
for (int i = 0; i < wps.length; i++) {
|
||||||
|
Element tag = tags.get(i);
|
||||||
|
Waypoint wp = wps[i];
|
||||||
|
Location loc = wp.getLocation();
|
||||||
|
|
||||||
|
assertTagMatchesLocation(tag, loc);
|
||||||
|
|
||||||
|
assertEquals(wp.getName(), getChildTextValue(tag, "name"));
|
||||||
|
assertEquals(wp.getDescription(), getChildTextValue(tag, "desc"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the given tags describe the given points, in the same order.
|
||||||
|
*/
|
||||||
|
protected void assertTagsMatchPoints(List<Element> tags, Location... locs) {
|
||||||
|
assertEquals(locs.length, tags.size());
|
||||||
|
for (int i = 0; i < locs.length; i++) {
|
||||||
|
Element tag = tags.get(i);
|
||||||
|
Location loc = locs[i];
|
||||||
|
|
||||||
|
assertTagMatchesLocation(tag, loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the given tag describes the given location.
|
||||||
|
*/
|
||||||
|
private void assertTagMatchesLocation(Element tag, Location loc) {
|
||||||
|
assertEquals(Double.toString(loc.getLatitude()), tag.getAttribute("lat"));
|
||||||
|
assertEquals(Double.toString(loc.getLongitude()), tag.getAttribute("lon"));
|
||||||
|
assertEquals(
|
||||||
|
GpxTrackWriter.TIMESTAMP_FORMAT.format(new Date(loc.getTime())),
|
||||||
|
getChildTextValue(tag, "time"));
|
||||||
|
assertEquals(Double.toString(loc.getAltitude()),
|
||||||
|
getChildTextValue(tag, "ele"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
|
import com.google.android.apps.mytracks.util.StringUtils;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the KML track exporter.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class KmlTrackWriterTest extends TrackFormatWriterTest {
|
||||||
|
private static final String FULL_TRACK_DESCRIPTION = "full track description";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fake version of {@link StringUtils} which returns a fixed track
|
||||||
|
* description, thus not depending on the context.
|
||||||
|
*/
|
||||||
|
private class FakeStringUtils extends StringUtils {
|
||||||
|
public FakeStringUtils() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateTrackDescription(Track track,
|
||||||
|
Vector<Double> distances, Vector<Double> elevations) {
|
||||||
|
assertSame(KmlTrackWriterTest.super.track, track);
|
||||||
|
assertTrue(distances.isEmpty());
|
||||||
|
assertTrue(elevations.isEmpty());
|
||||||
|
return FULL_TRACK_DESCRIPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testXmlOutput() throws Exception {
|
||||||
|
KmlTrackWriter writer = new KmlTrackWriter(new FakeStringUtils());
|
||||||
|
String result = writeTrack(writer);
|
||||||
|
Document doc = parseXmlDocument(result);
|
||||||
|
|
||||||
|
Element kmlTag = getChildElement(doc, "kml");
|
||||||
|
Element docTag = getChildElement(kmlTag, "Document");
|
||||||
|
assertEquals(TRACK_NAME, getChildTextValue(docTag, "name"));
|
||||||
|
assertEquals(TRACK_DESCRIPTION, getChildTextValue(docTag, "description"));
|
||||||
|
|
||||||
|
// There are 5 placemarks - start, segments, end, waypoint 1, waypoint 2
|
||||||
|
List<Element> placemarkTags = getChildElements(docTag, "Placemark", 5);
|
||||||
|
assertTagIsPlacemark(placemarkTags.get(0),
|
||||||
|
"(Start)", TRACK_DESCRIPTION, location1);
|
||||||
|
assertTagIsPlacemark(placemarkTags.get(2),
|
||||||
|
"(End)", FULL_TRACK_DESCRIPTION, location4);
|
||||||
|
assertTagIsPlacemark(placemarkTags.get(3),
|
||||||
|
WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2);
|
||||||
|
assertTagIsPlacemark(placemarkTags.get(4),
|
||||||
|
WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3);
|
||||||
|
|
||||||
|
Element trackPlacemarkTag = placemarkTags.get(1);
|
||||||
|
assertEquals(TRACK_NAME, getChildTextValue(trackPlacemarkTag, "name"));
|
||||||
|
assertEquals(TRACK_DESCRIPTION,
|
||||||
|
getChildTextValue(trackPlacemarkTag, "description"));
|
||||||
|
Element geometryTag = getChildElement(trackPlacemarkTag, "MultiGeometry");
|
||||||
|
List<Element> segmentTags = getChildElements(geometryTag, "LineString", 2);
|
||||||
|
assertTagHasPoints(segmentTags.get(0), location1, location2);
|
||||||
|
assertTagHasPoints(segmentTags.get(1), location3, location4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the given XML tag is a placemark with the given properties.
|
||||||
|
*
|
||||||
|
* @param tag the tag to analyze
|
||||||
|
* @param name the expected name for the placemark
|
||||||
|
* @param description the expected description for the placemark
|
||||||
|
* @param location the expected location of the placemark
|
||||||
|
*/
|
||||||
|
private void assertTagIsPlacemark(Element tag, String name,
|
||||||
|
String description, Location location) {
|
||||||
|
assertEquals(name, getChildTextValue(tag, "name"));
|
||||||
|
assertEquals(description, getChildTextValue(tag, "description"));
|
||||||
|
Element pointTag = getChildElement(tag, "Point");
|
||||||
|
String expectedCoords =
|
||||||
|
location.getLongitude() + "," + location.getLatitude();
|
||||||
|
String actualCoords = getChildTextValue(pointTag, "coordinates");
|
||||||
|
assertEquals(expectedCoords, actualCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the given tag has a "coordinates" subtag with the given
|
||||||
|
* locations.
|
||||||
|
*
|
||||||
|
* @param tag the tag to analyze
|
||||||
|
* @param locs the locations to expect in the coordinates
|
||||||
|
*/
|
||||||
|
private void assertTagHasPoints(Element tag, Location... locs) {
|
||||||
|
StringBuilder expectedBuilder = new StringBuilder();
|
||||||
|
for (Location loc : locs) {
|
||||||
|
expectedBuilder.append(loc.getLongitude());
|
||||||
|
expectedBuilder.append(',');
|
||||||
|
expectedBuilder.append(loc.getLatitude());
|
||||||
|
expectedBuilder.append(',');
|
||||||
|
expectedBuilder.append(loc.getAltitude());
|
||||||
|
expectedBuilder.append(' ');
|
||||||
|
}
|
||||||
|
String expectedCoordinates = expectedBuilder.toString().trim();
|
||||||
|
String actualCoordinates = getChildTextValue(tag, "coordinates").trim();
|
||||||
|
assertEquals(expectedCoordinates, actualCoordinates);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
package com.google.android.apps.mytracks.io;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.w3c.dom.Text;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.FactoryConfigurationError;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for track format writer tests, which sets up a fake track and
|
||||||
|
* gives auxiliary methods for verifying XML output.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public abstract class TrackFormatWriterTest extends AndroidTestCase {
|
||||||
|
|
||||||
|
// All the user-provided strings have "]]>" to ensure that proper escaping is
|
||||||
|
// being done.
|
||||||
|
protected static final String TRACK_NAME = "Home]]>";
|
||||||
|
protected static final String TRACK_DESCRIPTION = "The long ]]> journey home";
|
||||||
|
protected static final String WAYPOINT1_NAME = "point]]>1";
|
||||||
|
protected static final String WAYPOINT1_DESCRIPTION = "point 1]]>description";
|
||||||
|
protected static final String WAYPOINT2_NAME = "point]]>2";
|
||||||
|
protected static final String WAYPOINT2_DESCRIPTION = "point 2]]>description";
|
||||||
|
private static final int BUFFER_SIZE = 10240;
|
||||||
|
protected static final long TRACK_ID = 12345L;
|
||||||
|
protected Track track;
|
||||||
|
protected Location location1, location2, location3, location4;
|
||||||
|
protected Waypoint wp1, wp2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
track = new Track();
|
||||||
|
track.setId(TRACK_ID);
|
||||||
|
track.setName(TRACK_NAME);
|
||||||
|
track.setDescription(TRACK_DESCRIPTION);
|
||||||
|
|
||||||
|
location1 = new Location("mock");
|
||||||
|
location2 = new Location("mock");
|
||||||
|
location3 = new Location("mock");
|
||||||
|
location4 = new Location("mock");
|
||||||
|
populateLocations(location1, location2, location3, location4);
|
||||||
|
|
||||||
|
wp1 = new Waypoint();
|
||||||
|
wp2 = new Waypoint();
|
||||||
|
wp1.setLocation(location2);
|
||||||
|
wp1.setName(WAYPOINT1_NAME);
|
||||||
|
wp1.setDescription(WAYPOINT1_DESCRIPTION);
|
||||||
|
wp2.setLocation(location3);
|
||||||
|
wp2.setName(WAYPOINT2_NAME);
|
||||||
|
wp2.setDescription(WAYPOINT2_DESCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the given locations with coordinates and time.
|
||||||
|
*/
|
||||||
|
protected void populateLocations(Location... locs) {
|
||||||
|
for (int i = 0; i < locs.length; i++) {
|
||||||
|
Location loc = locs[i];
|
||||||
|
loc.setAltitude(i * 1000);
|
||||||
|
loc.setLatitude(i);
|
||||||
|
loc.setLongitude(-i);
|
||||||
|
loc.setTime(10000000 + i * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the right sequence of calls to the writer in order to write the fake
|
||||||
|
* track in {@link #track}.
|
||||||
|
*
|
||||||
|
* @param writer the writer to write to
|
||||||
|
* @return the written contents
|
||||||
|
*/
|
||||||
|
protected String writeTrack(TrackFormatWriter writer) {
|
||||||
|
OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE);
|
||||||
|
writer.prepare(track, output);
|
||||||
|
writer.writeHeader();
|
||||||
|
writer.writeBeginTrack(location1);
|
||||||
|
writer.writeOpenSegment();
|
||||||
|
writer.writeLocation(location1);
|
||||||
|
writer.writeLocation(location2);
|
||||||
|
writer.writeCloseSegment();
|
||||||
|
writer.writeOpenSegment();
|
||||||
|
writer.writeLocation(location3);
|
||||||
|
writer.writeLocation(location4);
|
||||||
|
writer.writeCloseSegment();
|
||||||
|
writer.writeEndTrack(location4);
|
||||||
|
writer.writeWaypoint(wp1);
|
||||||
|
writer.writeWaypoint(wp2);
|
||||||
|
writer.writeFooter();
|
||||||
|
writer.close();
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the text data contained inside a tag.
|
||||||
|
*
|
||||||
|
* @param parent the parent of the tag containing the text
|
||||||
|
* @param elementName the name of the tag containing the text
|
||||||
|
* @return the text contents
|
||||||
|
*/
|
||||||
|
protected String getChildTextValue(Element parent, String elementName) {
|
||||||
|
Element child = getChildElement(parent, elementName);
|
||||||
|
assertTrue(child.hasChildNodes());
|
||||||
|
NodeList children = child.getChildNodes();
|
||||||
|
int length = children.getLength();
|
||||||
|
assertTrue(length > 0);
|
||||||
|
|
||||||
|
// The children may be a sucession of text elements, just concatenate them
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
Text textNode = (Text) children.item(i);
|
||||||
|
result += textNode.getNodeValue();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all child elements of a given parent which gave the given name.
|
||||||
|
*
|
||||||
|
* @param parent the parent to get children from
|
||||||
|
* @param elementName the element name to look for
|
||||||
|
* @param expectedChildren the number of children we're expected to find
|
||||||
|
* @return a list of the found elements
|
||||||
|
*/
|
||||||
|
protected List<Element> getChildElements(Node parent, String elementName,
|
||||||
|
int expectedChildren) {
|
||||||
|
assertTrue(parent.hasChildNodes());
|
||||||
|
NodeList children = parent.getChildNodes();
|
||||||
|
int length = children.getLength();
|
||||||
|
List<Element> result = new ArrayList<Element>();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
Node childNode = children.item(i);
|
||||||
|
if (childNode.getNodeType() == Node.ELEMENT_NODE
|
||||||
|
&& childNode.getNodeName().equalsIgnoreCase(elementName)) {
|
||||||
|
result.add((Element) childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(children.toString(), result.size() == expectedChildren);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the single child element of the given parent with the given type.
|
||||||
|
*
|
||||||
|
* @param parent the parent to get a child from
|
||||||
|
* @param elementName the name of the child to look for
|
||||||
|
* @return the child element
|
||||||
|
*/
|
||||||
|
protected Element getChildElement(Node parent, String elementName) {
|
||||||
|
return getChildElements(parent, elementName, 1).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given XML contents and returns a DOM {@link Document} for it.
|
||||||
|
*/
|
||||||
|
protected Document parseXmlDocument(String contents)
|
||||||
|
throws FactoryConfigurationError, ParserConfigurationException,
|
||||||
|
SAXException, IOException {
|
||||||
|
DocumentBuilderFactory builderFactory =
|
||||||
|
DocumentBuilderFactory.newInstance();
|
||||||
|
builderFactory.setCoalescing(true);
|
||||||
|
// TODO: Somehow do XML validation on Android
|
||||||
|
// builderFactory.setValidating(true);
|
||||||
|
builderFactory.setNamespaceAware(true);
|
||||||
|
builderFactory.setIgnoringComments(true);
|
||||||
|
builderFactory.setIgnoringElementContentWhitespace(true);
|
||||||
|
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
|
||||||
|
Document doc = documentBuilder.parse(
|
||||||
|
new InputSource(new StringReader(contents)));
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Google Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.stats;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the DoubleBuffer class.
|
||||||
|
*
|
||||||
|
* @author Sandor Dornbush
|
||||||
|
*/
|
||||||
|
public class DoubleBufferTest extends TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the constructor leaves the buffer in a valid state.
|
||||||
|
*/
|
||||||
|
public void testConstructor() {
|
||||||
|
DoubleBuffer buffer = new DoubleBuffer(10);
|
||||||
|
assertFalse(buffer.isFull());
|
||||||
|
assertEquals(0.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(0.0, averageAndVariance[0]);
|
||||||
|
assertEquals(0.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple test with 10 of the same values.
|
||||||
|
*/
|
||||||
|
public void testBasic() {
|
||||||
|
DoubleBuffer buffer = new DoubleBuffer(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
buffer.setNext(1.0);
|
||||||
|
assertFalse(buffer.isFull());
|
||||||
|
assertEquals(1.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(1.0, averageAndVariance[0]);
|
||||||
|
assertEquals(0.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
buffer.setNext(1);
|
||||||
|
assertTrue(buffer.isFull());
|
||||||
|
assertEquals(1.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(1.0, averageAndVariance[0]);
|
||||||
|
assertEquals(0.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests with 5 entries of -10 and 5 entries of 10.
|
||||||
|
*/
|
||||||
|
public void testSplit() {
|
||||||
|
DoubleBuffer buffer = new DoubleBuffer(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
buffer.setNext(-10);
|
||||||
|
assertFalse(buffer.isFull());
|
||||||
|
assertEquals(-10.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(-10.0, averageAndVariance[0]);
|
||||||
|
assertEquals(0.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < 5; i++) {
|
||||||
|
buffer.setNext(10);
|
||||||
|
assertFalse(buffer.isFull());
|
||||||
|
double expectedAverage = ((i * 10.0) - 50.0) / (i + 5);
|
||||||
|
assertEquals(buffer.toString(),
|
||||||
|
expectedAverage, buffer.getAverage(), 0.01);
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(expectedAverage, averageAndVariance[0]);
|
||||||
|
}
|
||||||
|
buffer.setNext(10);
|
||||||
|
assertTrue(buffer.isFull());
|
||||||
|
assertEquals(0.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(0.0, averageAndVariance[0]);
|
||||||
|
assertEquals(100.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that reset leaves the buffer in a valid state.
|
||||||
|
*/
|
||||||
|
public void testReset() {
|
||||||
|
DoubleBuffer buffer = new DoubleBuffer(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
buffer.setNext(i);
|
||||||
|
}
|
||||||
|
assertTrue(buffer.isFull());
|
||||||
|
|
||||||
|
buffer.reset();
|
||||||
|
assertFalse(buffer.isFull());
|
||||||
|
assertEquals(0.0, buffer.getAverage());
|
||||||
|
double[] averageAndVariance = buffer.getAverageAndVariance();
|
||||||
|
assertEquals(0.0, averageAndVariance[0]);
|
||||||
|
assertEquals(0.0, averageAndVariance[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that if a lot of items are inserted the smoothing and looping works.
|
||||||
|
*/
|
||||||
|
public void testLoop() {
|
||||||
|
DoubleBuffer buffer = new DoubleBuffer(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
buffer.setNext(i);
|
||||||
|
assertEquals(i >= 9, buffer.isFull());
|
||||||
|
if (i > 10) {
|
||||||
|
assertEquals(i - 4.5, buffer.getAverage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2009 Google Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package com.google.android.apps.mytracks.stats;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class test the ExtremityMonitor class.
|
||||||
|
*
|
||||||
|
* @author Sandor Dornbush
|
||||||
|
*/
|
||||||
|
public class ExtremityMonitorTest extends TestCase {
|
||||||
|
|
||||||
|
public ExtremityMonitorTest(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialize() {
|
||||||
|
ExtremityMonitor monitor = new ExtremityMonitor();
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, monitor.getMin());
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimple() {
|
||||||
|
ExtremityMonitor monitor = new ExtremityMonitor();
|
||||||
|
assertTrue(monitor.update(0));
|
||||||
|
assertTrue(monitor.update(1));
|
||||||
|
assertEquals(0.0, monitor.getMin());
|
||||||
|
assertEquals(1.0, monitor.getMax());
|
||||||
|
assertFalse(monitor.update(1));
|
||||||
|
assertFalse(monitor.update(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a bunch of random numbers between [0,1] at the monitor.
|
||||||
|
*/
|
||||||
|
public void testRandom() {
|
||||||
|
ExtremityMonitor monitor = new ExtremityMonitor();
|
||||||
|
Random random = new Random(42);
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
monitor.update(random.nextDouble());
|
||||||
|
}
|
||||||
|
assertTrue(monitor.getMin() < 0.1);
|
||||||
|
assertTrue(monitor.getMax() < 1.0);
|
||||||
|
assertTrue(monitor.getMin() >= 0.0);
|
||||||
|
assertTrue(monitor.getMax() > 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReset() {
|
||||||
|
ExtremityMonitor monitor = new ExtremityMonitor();
|
||||||
|
assertTrue(monitor.update(0));
|
||||||
|
assertTrue(monitor.update(1));
|
||||||
|
monitor.reset();
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, monitor.getMin());
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax());
|
||||||
|
assertTrue(monitor.update(0));
|
||||||
|
assertTrue(monitor.update(1));
|
||||||
|
assertEquals(0.0, monitor.getMin());
|
||||||
|
assertEquals(1.0, monitor.getMax());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
// Copyright 2009 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.stats;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.MyTracksConstants;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the the function of the TripStatistics class.
|
||||||
|
*
|
||||||
|
* @author Sandor Dornbush
|
||||||
|
*/
|
||||||
|
public class TripStatisticsTest extends TestCase {
|
||||||
|
|
||||||
|
private TripStatistics stats = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
stats = new TripStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddLocationSimple() throws Exception {
|
||||||
|
stats = new TripStatistics(1000);
|
||||||
|
|
||||||
|
assertEquals(0.0, stats.getSmoothedElevation());
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, stats.getMinElevation());
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxElevation());
|
||||||
|
assertEquals(0.0, stats.getMaxSpeed());
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, stats.getMinGrade());
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxGrade());
|
||||||
|
assertEquals(0.0, stats.getTotalElevationGain());
|
||||||
|
assertEquals(0, stats.getMovingTime());
|
||||||
|
assertEquals(0.0, stats.getTotalDistance());
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
Location l = new Location("test");
|
||||||
|
l.setAccuracy(1.0f);
|
||||||
|
l.setLongitude(45.0);
|
||||||
|
|
||||||
|
// Going up by 5 meters each time.
|
||||||
|
l.setAltitude(i);
|
||||||
|
// Moving by .1% of a degree latitude.
|
||||||
|
l.setLatitude(i * .001);
|
||||||
|
l.setSpeed(11.1f);
|
||||||
|
// Each time slice is 10 seconds.
|
||||||
|
long time = 1000 + 10000 * i;
|
||||||
|
l.setTime(time);
|
||||||
|
boolean moving = stats.addLocation(l, time);
|
||||||
|
assertEquals((i != 0), moving);
|
||||||
|
|
||||||
|
assertEquals(10000 * i, stats.getTotalTime());
|
||||||
|
System.out.println("i: " + i + "\nLocation: " + l + "\nStats: " + stats);
|
||||||
|
assertEquals(10000 * i, stats.getMovingTime());
|
||||||
|
assertEquals(i, stats.getSmoothedElevation(),
|
||||||
|
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2);
|
||||||
|
assertEquals(0.0, stats.getMinElevation());
|
||||||
|
assertEquals(i , stats.getMaxElevation(),
|
||||||
|
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR / 2);
|
||||||
|
assertEquals(i, stats.getTotalElevationGain(),
|
||||||
|
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
|
if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) {
|
||||||
|
assertEquals(11.1f, stats.getMaxSpeed(), 0.1);
|
||||||
|
}
|
||||||
|
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR)
|
||||||
|
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) {
|
||||||
|
assertEquals(0.009, stats.getMinGrade(), 0.0001);
|
||||||
|
assertEquals(0.009, stats.getMaxGrade(), 0.0001);
|
||||||
|
}
|
||||||
|
// 1 degree = 111 km
|
||||||
|
// 1 timeslice = 0.001 degree = 111 m
|
||||||
|
assertEquals(111.0 * i, stats.getTotalDistance(), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that elevation works if the user is stable.
|
||||||
|
*/
|
||||||
|
public void testElevationSimple() throws Exception {
|
||||||
|
for (double elevation = 0; elevation < 1000; elevation += 10) {
|
||||||
|
stats = new TripStatistics();
|
||||||
|
for (int j = 0; j < 100; j++) {
|
||||||
|
assertEquals(0.0, stats.updateElevation(elevation));
|
||||||
|
assertEquals(elevation, stats.getSmoothedElevation());
|
||||||
|
assertEquals(elevation, stats.getMinElevation());
|
||||||
|
assertEquals(elevation, stats.getMaxElevation());
|
||||||
|
assertEquals(0.0, stats.getTotalElevationGain());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testElevationGain() throws Exception {
|
||||||
|
for (double i = 0; i < 1000; i++) {
|
||||||
|
double expectedGain;
|
||||||
|
if (i < (MyTracksConstants.ELEVATION_SMOOTHING_FACTOR - 1)) {
|
||||||
|
expectedGain = 0;
|
||||||
|
} else if (i < MyTracksConstants.ELEVATION_SMOOTHING_FACTOR) {
|
||||||
|
expectedGain = 0.5;
|
||||||
|
} else {
|
||||||
|
expectedGain = 1.0;
|
||||||
|
}
|
||||||
|
assertEquals(expectedGain,
|
||||||
|
stats.updateElevation(i));
|
||||||
|
assertEquals(i, stats.getSmoothedElevation(), 20);
|
||||||
|
assertEquals(0.0, stats.getMinElevation(), 0.0);
|
||||||
|
assertEquals(i, stats.getMaxElevation(),
|
||||||
|
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
|
assertEquals(i, stats.getTotalElevationGain(),
|
||||||
|
MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGradeSimple() throws Exception {
|
||||||
|
for (double i = 0; i < 1000; i++) {
|
||||||
|
// The value of the elevation does not matter. This is just to fill the
|
||||||
|
// buffer.
|
||||||
|
stats.updateElevation(i);
|
||||||
|
stats.updateGrade(100, 100);
|
||||||
|
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR)
|
||||||
|
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) {
|
||||||
|
assertEquals(1.0, stats.getMaxGrade());
|
||||||
|
assertEquals(1.0, stats.getMinGrade());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (double i = 0; i < 1000; i++) {
|
||||||
|
// The value of the elevation does not matter. This is just to fill the
|
||||||
|
// buffer.
|
||||||
|
stats.updateElevation(i);
|
||||||
|
stats.updateGrade(100, -100);
|
||||||
|
if ((i > MyTracksConstants.GRADE_SMOOTHING_FACTOR)
|
||||||
|
&& (i > MyTracksConstants.ELEVATION_SMOOTHING_FACTOR)) {
|
||||||
|
assertEquals(1.0, stats.getMaxGrade());
|
||||||
|
assertEquals(-1.0, stats.getMinGrade());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGradeIgnoreShort() throws Exception {
|
||||||
|
for (double i = 0; i < 100; i++) {
|
||||||
|
// The value of the elevation does not matter. This is just to fill the
|
||||||
|
// buffer.
|
||||||
|
stats.updateElevation(i);
|
||||||
|
stats.updateGrade(1, 100);
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxGrade());
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, stats.getMinGrade());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSpeedIncludeZero() {
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
stats.updateSpeed(i + 1000, 0.0, i, 4.0);
|
||||||
|
assertEquals(0.0, stats.getMaxSpeed());
|
||||||
|
assertEquals((i + 1) * 1000, stats.getMovingTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSpeedIngoreErrorCode() {
|
||||||
|
stats.updateSpeed(12345000, 128.0, 12344000, 0.0);
|
||||||
|
assertEquals(0.0, stats.getMaxSpeed());
|
||||||
|
assertEquals(1000, stats.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSpeedIngoreLargeAcceleration() {
|
||||||
|
stats.updateSpeed(12345000, 100.0, 12344000, 1.0);
|
||||||
|
assertEquals(0.0, stats.getMaxSpeed());
|
||||||
|
assertEquals(1000, stats.getMovingTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSpeed() {
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
stats.updateSpeed(i + 1000, 4.0, i, 4.0);
|
||||||
|
assertEquals((i + 1) * 1000, stats.getMovingTime());
|
||||||
|
if (i > MyTracksConstants.SPEED_SMOOTHING_FACTOR) {
|
||||||
|
assertEquals(4.0, stats.getMaxSpeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.testing;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||||
|
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fake factory for {@link MyTracksProviderUtils} which always returns a
|
||||||
|
* predefined instance.
|
||||||
|
*
|
||||||
|
* @author Rodrigo Damazio
|
||||||
|
*/
|
||||||
|
public class TestingProviderUtilsFactory extends Factory {
|
||||||
|
private MyTracksProviderUtils instance;
|
||||||
|
|
||||||
|
public TestingProviderUtilsFactory(MyTracksProviderUtils instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MyTracksProviderUtils newForContext(Context context) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Factory installWithInstance(MyTracksProviderUtils instance) {
|
||||||
|
Factory oldFactory = Factory.getInstance();
|
||||||
|
Factory factory = new TestingProviderUtilsFactory(instance);
|
||||||
|
MyTracksProviderUtils.Factory.overrideInstance(factory);
|
||||||
|
return oldFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void restoreOldFactory(Factory factory) {
|
||||||
|
MyTracksProviderUtils.Factory.overrideInstance(factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2009 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.util;
|
||||||
|
|
||||||
|
import com.google.android.apps.mytracks.content.Track;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the Chart URL generator.
|
||||||
|
*
|
||||||
|
* @author Sandor Dornbush
|
||||||
|
*/
|
||||||
|
public class ChartURLGeneratorTest extends TestCase {
|
||||||
|
|
||||||
|
public void testgetChartUrl() {
|
||||||
|
Vector<Double> distances = new Vector<Double>();
|
||||||
|
Vector<Double> elevations = new Vector<Double>();
|
||||||
|
Track t = new Track();
|
||||||
|
t.setMinElevation(0);
|
||||||
|
t.setMaxElevation(2000);
|
||||||
|
t.setTotalDistance(100);
|
||||||
|
|
||||||
|
distances.add(0.0);
|
||||||
|
elevations.add(10.0);
|
||||||
|
|
||||||
|
distances.add(10.0);
|
||||||
|
elevations.add(300.0);
|
||||||
|
|
||||||
|
distances.add(20.0);
|
||||||
|
elevations.add(800.0);
|
||||||
|
|
||||||
|
distances.add(50.0);
|
||||||
|
elevations.add(1900.0);
|
||||||
|
|
||||||
|
distances.add(75.0);
|
||||||
|
elevations.add(1200.0);
|
||||||
|
|
||||||
|
distances.add(90.0);
|
||||||
|
elevations.add(700.0);
|
||||||
|
|
||||||
|
distances.add(100.0);
|
||||||
|
elevations.add(70.0);
|
||||||
|
|
||||||
|
String chart = ChartURLGenerator.getChartUrl(distances,
|
||||||
|
elevations,
|
||||||
|
t,
|
||||||
|
"Title",
|
||||||
|
true,
|
||||||
|
false);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"http://chart.apis.google.com/chart?&chs=600x350&cht=lxy&"
|
||||||
|
+ "chtt=Title&chxt=x,y&chxr=0,0,0,0|1,0.0,2100.0,300&chco=009A00&"
|
||||||
|
+ "chm=B,00AA00,0,0,0&chg=100000,14.285714285714286,1,0&"
|
||||||
|
+ "chd=e:AAGZMzf.v.5l..,ATJJYY55kkVVCI",
|
||||||
|
chart);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user