/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.Instrumentation;
import android.location.Location;
import android.location.LocationManager;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.widget.ListView;
import android.widget.TextView;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Tests export all and import all.
*
* @author Youtao Liu
*/
public class ExportAllAndImportAllTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String TAG = ExportAllAndImportAllTest.class.getSimpleName();
private static final String GPX_FILE_TRACK_NAME = "TestTrackName1373523959524";
private static final int GPX_FILE_TIME_INTERVAL = 9; // seconds
private static final double GPX_FILE_INIT_LATITUDE = 39.30;
private static final double GPX_FILE_INIT_LONGITUDE = 116.0;
private static final String GPX_FILE_ELEVATION_MAX = "33.3";
private static final String GPX_FILE_ELEVATION_MIN = "22.2";
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public ExportAllAndImportAllTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests export all as KML.
*/
public void testExport_kml() {
testExport(TrackFileFormat.KML);
}
/**
* Tests export all as GPX.
*/
public void testExport_gpx() {
testExport(TrackFileFormat.GPX);
}
/**
* Tests export all as CSV.
*/
public void testExport_csv() {
testExport(TrackFileFormat.CSV);
}
/**
* Tests export all as TCX.
*/
public void testExport_tcx() {
testExport(TrackFileFormat.TCX);
}
/**
* Test import all KML when there is no file.
*/
public void testImportNoFile_kml() {
testImportNoFile(TrackFileFormat.KML);
}
/**
* Test import all GPX when there is no file.
*/
public void testImportNoFile_gpx() {
testImportNoFile(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there is only one track.
*/
public void testExportImportOne_kml() {
testExportImportOne(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there is only one track.
*/
public void testExportImportOne_gpx() {
testExportImportOne(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there is only one track and
* the track contains markers.
*/
public void testExportImportOneWithMarker_kml() {
testExportImportOneWithMarker(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there is only one track and
* the track contains markers.
*/
public void testExportImportOneWithMarker_gpx() {
testExportImportOneWithMarker(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there are multiple tracks.
*/
public void testExportImportMultiple_kml() {
testExportImportMultiple(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there are multiple tracks.
*/
public void testExportImportMultiple_gpx() {
testExportImportMultiple(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there are multiple tracks
* and the tracks contain pauses.
*/
public void testExportImportMultipleWithPause_kml() {
testExportImportMultipleWithPause(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there are multiple tracks
* and the tracks contain pauses.
*/
public void testExportImportMultipleWithPause_gpx() {
testExportImportMultipleWithPause(TrackFileFormat.GPX);
}
/**
* Tests export all.
*
* @param trackFileFormat the track file format
*/
private void testExport(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 1 gps point
EndToEndTestUtils.createTrackIfEmpty(1, true);
assertEquals(1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
exportTracks(trackFileFormat, 1);
assertEquals(1, getExternalStorageFiles(trackFileFormat).length);
}
/**
* Tests import all when there is no file.
*
* @param trackFileFormat the track file format
*/
private void testImportNoFile(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
importTracks(trackFileFormat);
EndToEndTestUtils.SOLO.waitForText(getImportErrorMessage(trackFileFormat));
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
}
/**
* Tests export all and import all with one track.
*
* @param trackFileFormat the track file format
*/
private void testExportImportOne(TrackFileFormat trackFileFormat) {
EndToEndTestUtils.changeToMetricUnits();
showGradeElevation();
addTrackFromGpxFile();
exportImport(trackFileFormat);
checkTrackFromGpxFile();
}
/**
* Tests export all and import all with one track containing markers.
*
* @param trackFileFormat the track file format
*/
private void testExportImportOneWithMarker(TrackFileFormat trackFileFormat) {
addTrackWithMarker();
exportImport(trackFileFormat);
// Check name, activity type, and description
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.trackName));
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName);
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.track_detail_chart_tab));
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackName));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.activityType));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackDescription));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_cancel));
// Check markers
if (EndToEndTestUtils.hasGpsSignal) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
// The first marker
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_NAME + 1));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_TYPE + 1));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_DESCRIPTION + 1));
// The second marker
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_NAME + 2));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_TYPE + 2));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_DESCRIPTION + 2));
}
}
/**
* Tests export all and import all with multiple tracks.
*
* @param trackFileFormat the track file format
*/
private void testExportImportMultiple(TrackFileFormat trackFileFormat) {
addTracks();
exportImport(trackFileFormat);
}
/**
* Tests export all and import all with multiple tracks containing pauses.
*
* @param trackFileFormat the track file format
*/
private void testExportImportMultipleWithPause(TrackFileFormat trackFileFormat) {
addTracksWithPause();
exportImport(trackFileFormat);
}
/**
* Adds one track by importing it from a GPX file.
*/
private void addTrackFromGpxFile() {
EndToEndTestUtils.deleteAllTracks();
deleteExternalStorageFiles(TrackFileFormat.GPX);
createOneGpxFile();
importTracks(TrackFileFormat.GPX);
checkImportSuccess();
checkTrackFromGpxFile();
}
/**
* Adds one track with markers.
*/
private void addTrackWithMarker() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with two markers
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
// Send gps before creating the first marker
EndToEndTestUtils.sendGps(2);
EndToEndTestUtils.createWaypoint(0);
EndToEndTestUtils.sendGps(2, 2);
EndToEndTestUtils.createWaypoint(1);
EndToEndTestUtils.sendGps(2, 4);
// Back to the tracks list
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(true);
}
/**
* Adds multiple tracks.
*/
private void addTracks() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 3 gps points
EndToEndTestUtils.createTrackIfEmpty(3, true);
instrumentation.waitForIdleSync();
// Create an empty track
EndToEndTestUtils.createSimpleTrack(0, true);
instrumentation.waitForIdleSync();
assertEquals(2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Adds multiple tracks with pauses.
*/
private void addTracksWithPause() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 3 gps points
EndToEndTestUtils.createTrackWithPause(3);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Create an empty track
EndToEndTestUtils.createTrackWithPause(0);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertEquals(2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Export all and import all.
*
* @param trackFileFormat the track file format
*/
private void exportImport(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
assertEquals(0, getExternalStorageFiles(trackFileFormat).length);
int trackCount = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
// Export all
exportTracks(trackFileFormat, trackCount);
assertEquals(trackCount, getExternalStorageFiles(trackFileFormat).length);
if (trackCount == 1) {
EndToEndTestUtils.deleteAllTracks();
}
// Import all
importTracks(trackFileFormat);
EndToEndTestUtils.rotateCurrentActivity();
checkImportSuccess();
EndToEndTestUtils.SOLO.waitForActivity(TrackListActivity.class);
assertEquals(trackCount == 1 ? 1 : trackCount * 2,
EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Exports all tracks.
*
* @param trackFileFormat the track file format
* @param trackCount the track count
*/
private void exportTracks(TrackFileFormat trackFileFormat, int trackCount) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_export_all), true);
EndToEndTestUtils.instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackFileFormat.name());
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), true, true);
EndToEndTestUtils.SOLO.waitForText(getExportSuccessMessage(trackCount, trackFileFormat));
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
instrumentation.waitForIdleSync();
}
/**
* Imports all tracks.
*
* @param trackFileFormat the track file format
*/
private void importTracks(TrackFileFormat trackFileFormat) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_import_all), true);
EndToEndTestUtils.SOLO.clickOnText(trackFileFormat.name());
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), true, true);
}
/**
* Gets the export all success message.
*
* @param count the count of successfully exported tracks
* @param trackFileFormat the track file format
*/
private String getExportSuccessMessage(int count, TrackFileFormat trackFileFormat) {
String trackCount = trackListActivity.getResources()
.getQuantityString(R.plurals.tracks, count, count);
String path = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
return trackListActivity.getString(R.string.export_external_storage_success, trackCount, path);
}
/**
* Gets the import all error message.
*
* @param trackFileFormat the track file format
*/
private String getImportErrorMessage(TrackFileFormat trackFileFormat) {
String fileCount = trackListActivity.getResources().getQuantityString(R.plurals.files, 0, 0);
String path = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
return trackListActivity.getString(R.string.import_error, 0, fileCount, path);
}
/**
* Checks that import all is success.
*/
private void checkImportSuccess() {
// Waiting for the prefix is much faster than waiting for the whole string
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.import_success).split("%")[0]);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
instrumentation.waitForIdleSync();
}
/**
* Creates one GPX file in the MyTracks folder.
*/
private void createOneGpxFile() {
String fileName = GPX_FILE_TRACK_NAME + "." + TrackFileFormat.GPX.getExtension();
String fileContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " + "<gpx "
+ "version=\"1.1\" " + "creator=\"Created by Google My Tracks on Android.\" "
+ "xmlns=\"http://www.topografix.com/GPX/1/1\" "
+ "xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1"
+ " http://www.topografix.com/GPX/1/1/gpx.xsd"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd\"> " + "<metadata> "
+ "<name><![CDATA[" + GPX_FILE_TRACK_NAME + "]]></name> "
+ "<desc><![CDATA[testTrackDescription1373523959524]]></desc> " + "</metadata> " + "<trk> "
+ "<name><![CDATA[" + GPX_FILE_TRACK_NAME + "]]></name> "
+ "<desc><![CDATA[testTrackDescription1373523959524]]></desc> "
+ "<type><![CDATA[TestActivityType]]></type> "
+ "<extensions><topografix:color>c0c0c0</topografix:color></extensions> " + "<trkseg> "
+ "<trkpt lat=\"" + GPX_FILE_INIT_LATITUDE + "\" lon=\"" + GPX_FILE_INIT_LONGITUDE + "\"> "
+ "<time>2013-07-10T08:00:00.000Z</time> <ele>" + GPX_FILE_ELEVATION_MIN + "</ele>"
+ "</trkpt> " + "<trkpt lat=\"39.2995\" lon=\"116.0005\"> "
+ "<time>2013-07-10T08:00:01.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.299\" lon=\"116.001\"> " + "<time>2013-07-10T08:00:02.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2985\" lon=\"116.0015\"> "
+ "<time>2013-07-10T08:00:03.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.298\" lon=\"116.002\"> " + "<time>2013-07-10T08:00:04.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2975\" lon=\"116.0025\"> "
+ "<time>2013-07-10T08:00:05.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.297\" lon=\"116.003\"> " + "<time>2013-07-10T08:00:06.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2965\" lon=\"116.0035\"> "
+ "<time>2013-07-10T08:00:07.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.296\" lon=\"116.004\"> " + "<time>2013-07-10T08:00:08.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2955\" lon=\"116.0045\"> "
+ "<time>2013-07-10T08:00:09.000Z</time> <ele>" + GPX_FILE_ELEVATION_MAX + "</ele>"
+ "</trkpt> " + "</trkseg> " + "</trk> " + "</gpx>";
FileOutputStream fileOutputStream = null;
try {
File file = new File(
FileUtils.getPath(TrackFileFormat.GPX.getExtension()) + File.separator + fileName);
if (!file.exists()) {
file.createNewFile();
}
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(fileContent.getBytes());
fileOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Unable to write GPX file", e);
fail();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
Log.e(TAG, "Unable to close GPX file", e);
fail();
}
}
}
}
/**
* Checks track imported from a GPX file.
*/
private void checkTrackFromGpxFile() {
EndToEndTestUtils.SOLO.clickOnText(GPX_FILE_TRACK_NAME);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForActivity(
TrackDetailActivity.class, EndToEndTestUtils.LONG_WAIT_TIME);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
instrumentation.waitForIdleSync();
double acceptDeviation = 0.1f;
Activity activity = EndToEndTestUtils.SOLO.getCurrentActivity();
double elevationMin = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_elevation_min).findViewById(R.id.stats_value)).getText().toString());
double elevationMax = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_elevation_max).findViewById(R.id.stats_value)).getText().toString());
double distance = Double.parseDouble(((TextView) activity.findViewById(R.id.stats_distance)
.findViewById(R.id.stats_value)).getText().toString());
double averageSpeed = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_average_speed).findViewById(R.id.stats_value)).getText().toString());
assertEquals(Double.parseDouble(GPX_FILE_ELEVATION_MIN), elevationMin);
assertEquals(getGpxFileElevationMax(), elevationMax);
// in km
double calculateDistance = getGpxFileDistance();
// in km/h
double calculateAverageSpeed = calculateDistance
/ (GPX_FILE_TIME_INTERVAL + UnitConversions.S_TO_MIN * UnitConversions.MIN_TO_HR);
assertTrue((calculateDistance - distance) / calculateDistance < acceptDeviation);
assertTrue((calculateAverageSpeed - averageSpeed) / calculateAverageSpeed < acceptDeviation);
EndToEndTestUtils.SOLO.goBack();
}
/**
* Gets the GPX file distance in km.
*/
private double getGpxFileDistance() {
double distance = 0.0;
double latitude = GPX_FILE_INIT_LATITUDE;
double longitude = GPX_FILE_INIT_LONGITUDE;
Location current = new Location(LocationManager.GPS_PROVIDER);
current.setLatitude(latitude);
current.setLongitude(longitude);
for (int i = 1; i < 10; i++) {
Location next = new Location(LocationManager.GPS_PROVIDER);
next.setLatitude(latitude - 0.0005 * i);
next.setLongitude(longitude + 0.0005 * i);
distance = distance + next.distanceTo(current) * UnitConversions.M_TO_KM;
current = next;
}
return distance;
}
/**
* Gets the GPX file elevation max.
*/
private double getGpxFileElevationMax() {
/*
* Returns the highest value of all the weighted averages. Since there are
* only two elevation data points, the highest value is the weighted average
* of both points.
*/
return (Double.parseDouble(GPX_FILE_ELEVATION_MIN) + Double.parseDouble(GPX_FILE_ELEVATION_MAX))
/ 2.0;
}
/**
* Gets the external storage files.
*
* @param trackFileFormat the track file format
*/
private File[] getExternalStorageFiles(final TrackFileFormat trackFileFormat) {
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
String suffix = trackFileFormat == TrackFileFormat.KML ? ".kmz"
: "." + trackFileFormat.getExtension();
return file.getName().endsWith(suffix);
}
};
File dir = new File(FileUtils.getPath(trackFileFormat.getExtension()));
File[] files = dir.listFiles(filter);
return files == null ? new File[0] : files;
}
/**
* Deletes the external storage files.
*
* @param trackFileFormat the track file format
*/
private void deleteExternalStorageFiles(TrackFileFormat trackFileFormat) {
File dir = new File(FileUtils.getPath(trackFileFormat.getExtension()));
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (File file : files) {
file.delete();
}
}
/**
* Shows grade elevation.
*/
private void showGradeElevation() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
String gradeElevation = trackListActivity.getString(R.string.settings_stats_grade_elevation);
if (!EndToEndTestUtils.SOLO.isCheckBoxChecked(gradeElevation)) {
EndToEndTestUtils.SOLO.clickOnText(gradeElevation);
}
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
}