Importing tests source

This commit is contained in:
Rodrigo Damazio
2010-05-19 17:35:08 -07:00
parent 27dd5298f7
commit 870dda9b8b
10 changed files with 1233 additions and 0 deletions
@@ -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());
}
}
}
}
@@ -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);
}
}