mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-17 00:03:07 +02:00
Move everything one directory upper
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 17
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.maps.mytracks"
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 19
|
||||
|
||||
testApplicationId "com.google.android.maps.mytracks.test"
|
||||
testInstrumentationRunner "android.test.InstrumentationTestRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles 'proguard.cfg', 'proguard-google-api-client.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':myTracksLib')
|
||||
compile files('libs/android-support-v4.jar')
|
||||
compile files('libs/antlib.jar')
|
||||
compile files('libs/gdata-client-1.0.jar')
|
||||
compile files('libs/gdata-client-meta-1.0.jar')
|
||||
compile files('libs/gdata-core-1.0.jar')
|
||||
compile files('libs/gdata-spreadsheet-3.0.jar')
|
||||
compile files('libs/gdata-spreadsheet-meta-3.0.jar')
|
||||
compile files('libs/google-api-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar')
|
||||
compile files('libs/google-common.jar')
|
||||
compile files('libs/google-http-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-gson-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-jackson-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-jackson2-1.12.0-beta.jar')
|
||||
compile files('libs/google-oauth-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-play-services.jar')
|
||||
compile files('libs/gson-2.1.jar')
|
||||
compile files('libs/guava-jdk5-13.0.jar')
|
||||
compile files('libs/jackson-core-2.0.5.jar')
|
||||
compile files('libs/jackson-core-asl-1.9.9.jar')
|
||||
compile files('libs/jsr305.jar')
|
||||
compile files('libs/libGoogleAnalytics.jar')
|
||||
androidTestCompile files('libs/AndroidMockGenerator.jar')
|
||||
androidTestCompile files('libs/robotium-solo-3.3.jar')
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
<issue id="AdapterViewChildren" severity="error" />
|
||||
<issue id="DuplicateIds" severity="error" />
|
||||
<issue id="DuplicateIncludedIds" severity="error" />
|
||||
<issue id="ExtraTranslation" severity="error" />
|
||||
<issue id="GifUsage" severity="error" />
|
||||
<issue id="InconsistentArrays" severity="error" />
|
||||
<issue id="MissingTranslation" severity="warning" />
|
||||
<issue id="Proguard" severity="warning" />
|
||||
<issue id="ScrollViewCount" severity="error" />
|
||||
<issue id="ScrollViewSize" severity="error" />
|
||||
<issue id="StateListReachable" severity="error" />
|
||||
<issue id="TypographyDashes" severity="informational" />
|
||||
<issue id="TypographyEllipsis" severity="informational" />
|
||||
<issue id="TypographyFractions" severity="informational" />
|
||||
<issue id="TypographyOther" severity="informational" />
|
||||
<issue id="TypographyQuotes" severity="informational" />
|
||||
</lint>
|
||||
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":myTracks" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="mytracks" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":myTracks" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 17 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="google-oauth-client-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-api-services-fusiontables-v1-rev16-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-support-v4" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-api-client-android-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="gdata-core-1.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-http-client-gson-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-play-services" level="project" />
|
||||
<orderEntry type="library" exported="" scope="TEST" name="robotium-solo-3.3" level="project" />
|
||||
<orderEntry type="library" exported="" name="libGoogleAnalytics" level="project" />
|
||||
<orderEntry type="library" exported="" name="gdata-spreadsheet-3.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-http-client-jackson-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-api-services-drive-v2-rev30-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="gdata-client-1.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-api-client-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-common" level="project" />
|
||||
<orderEntry type="library" exported="" name="gson-2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="gdata-client-meta-1.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="jsr305" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-http-client-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="jackson-core-asl-1.9.9" level="project" />
|
||||
<orderEntry type="library" exported="" name="jackson-core-2.0.5" level="project" />
|
||||
<orderEntry type="library" exported="" scope="TEST" name="AndroidMockGenerator" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-http-client-jackson2-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="antlib" level="project" />
|
||||
<orderEntry type="library" exported="" name="google-http-client-android-1.12.0-beta" level="project" />
|
||||
<orderEntry type="library" exported="" name="guava-jdk5-13.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="gdata-spreadsheet-meta-3.0" level="project" />
|
||||
<orderEntry type="module" module-name="myTracksLib" exported="" />
|
||||
<orderEntry type="library" exported="" name="android-android-17" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,38 @@
|
||||
# ProGuard Configuration file
|
||||
#
|
||||
# See http://proguard.sourceforge.net/index.html#manual/usage.html
|
||||
|
||||
# Needed to keep generic types and @Key annotations accessed via reflection
|
||||
|
||||
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
|
||||
|
||||
-keepclassmembers class * {
|
||||
@com.google.api.client.util.Key <fields>;
|
||||
}
|
||||
|
||||
# Needed by Guava
|
||||
# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI
|
||||
|
||||
-dontwarn sun.misc.Unsafe
|
||||
-dontwarn com.google.common.collect.MinMaxPriorityQueue
|
||||
|
||||
# Needed by google-http-client-android when linking against an older platform version
|
||||
|
||||
-dontwarn com.google.api.client.extensions.android.**
|
||||
|
||||
# Needed by google-api-client-android when linking against an older platform version
|
||||
|
||||
-dontwarn com.google.api.client.googleapis.extensions.android.**
|
||||
|
||||
# Additional flags from
|
||||
# http://stackoverflow.com/questions/14410520/google-drive-api-doesnt-play-well-with-proguard-npe
|
||||
-keep class com.google.** { *;}
|
||||
-keep interface com.google.** { *;}
|
||||
-dontwarn com.google.**
|
||||
-keepattributes *Annotation*,Signature
|
||||
-keep class * extends com.google.api.client.json.GenericJson {
|
||||
*;
|
||||
}
|
||||
-keep class com.google.api.services.drive.** {
|
||||
*;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
#
|
||||
# Section 1
|
||||
# Default eclipse project proguard settings.
|
||||
#
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-verbose
|
||||
|
||||
-dontpreverify
|
||||
|
||||
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
|
||||
# change from 5 to 2. With 5 passes, the CursorLoader in the android.support.v4 will not compile.
|
||||
# See http://stackoverflow.com/questions/6605971/android-sdk-tools-revision-12-has-problem-with-proguard-error-conversion-to
|
||||
-optimizationpasses 2
|
||||
-allowaccessmodification
|
||||
|
||||
-keepattributes *Annotation*
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgent
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class * extends android.support.v4.app.Fragment
|
||||
-keep public class * extends android.app.Fragment
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keep public class * extends android.view.View {
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
public void set*(...);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
# The support library contains references to newer platform versions.
|
||||
# Don't warn about those in case this app is linking against an older
|
||||
# platform version. We know about them, and they are safe.
|
||||
-dontwarn android.support.**
|
||||
|
||||
#
|
||||
# Section 2
|
||||
# Google Play Services and Google Maps API Library
|
||||
#
|
||||
|
||||
# For Google Play Services
|
||||
-keep class * extends java.util.ListResourceBundle {
|
||||
protected Object[][] getContents();
|
||||
}
|
||||
|
||||
# For Google Maps API library
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
private static final long serialVersionUID;
|
||||
}
|
||||
-keep public class com.google.googlenav.capabilities.CapabilitiesController*
|
||||
|
||||
#
|
||||
# Section 3
|
||||
# My Tracks specific proguard settings.
|
||||
#
|
||||
|
||||
# Add the libraries, but ignore warnings about them
|
||||
-libraryjars libs
|
||||
-libraryjars ../MyTracksLib/libs
|
||||
-dontwarn com.android.common.**
|
||||
-dontwarn com.google.android.googleapps.**
|
||||
-dontwarn com.google.android.gsf.**
|
||||
-dontwarn javax.servlet.**
|
||||
-dontwarn org.apache.avalon.framework.logger.**
|
||||
-dontwarn org.apache.log.**
|
||||
-dontwarn org.apache.log4j.**
|
||||
|
||||
# Make our stack traces useful
|
||||
# Line numbers will be correct, file names will be replaced by "MT" since the
|
||||
# class name is enough to get the file name.
|
||||
-renamesourcefileattribute MT
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# Keep services needed by ANT+ protocol
|
||||
-keep public class com.dsi.ant.IAnt_6
|
||||
-keep public class com.dsi.ant.IAnt
|
||||
-keep public class com.dsi.ant.IServiceSettings
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for the BootReceiver.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class BootReceiverTest extends AndroidTestCase {
|
||||
private static final String SERVICE_NAME = "com.google.android.apps.mytracks.services.TrackRecordingService";
|
||||
|
||||
/**
|
||||
* Tests the behavior when receive notification which is the phone boot.
|
||||
*/
|
||||
public void testOnReceive_startService() {
|
||||
// Make sure no TrackRecordingService
|
||||
Intent stopIntent = new Intent(getContext(), TrackRecordingService.class);
|
||||
getContext().stopService(stopIntent);
|
||||
assertFalse(isServiceExisted(getContext(), SERVICE_NAME));
|
||||
|
||||
BootReceiver bootReceiver = new BootReceiver();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
bootReceiver.onReceive(getContext(), intent);
|
||||
// Check if the service is started
|
||||
assertTrue(isServiceExisted(getContext(), SERVICE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior when receive notification which is not the phone boot.
|
||||
*/
|
||||
public void testOnReceive_noStartService() {
|
||||
// Make sure no TrackRecordingService
|
||||
Intent stopIntent = new Intent(getContext(), TrackRecordingService.class);
|
||||
getContext().stopService(stopIntent);
|
||||
assertFalse(isServiceExisted(getContext(), SERVICE_NAME));
|
||||
|
||||
BootReceiver bootReceiver = new BootReceiver();
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_BUG_REPORT);
|
||||
bootReceiver.onReceive(getContext(), intent);
|
||||
// Check if the service is not started
|
||||
assertFalse(isServiceExisted(getContext(), SERVICE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a service is started in a context.
|
||||
*
|
||||
* @param context the context for checking a service
|
||||
* @param serviceName the service name to find if existed
|
||||
*/
|
||||
private boolean isServiceExisted(Context context, String serviceName) {
|
||||
ActivityManager activityManager = (ActivityManager) context
|
||||
.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
|
||||
.getRunningServices(Integer.MAX_VALUE);
|
||||
for (int i = 0; i < serviceList.size(); i++) {
|
||||
RunningServiceInfo serviceInfo = serviceList.get(i);
|
||||
ComponentName componentName = serviceInfo.service;
|
||||
if (componentName.getClassName().equals(serviceName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link ChartValueSeries}.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class ChartValueSeriesTest extends AndroidTestCase {
|
||||
private ChartValueSeries series;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
series = new ChartValueSeries(getContext(),
|
||||
Integer.MIN_VALUE,
|
||||
Integer.MAX_VALUE,
|
||||
new int[] {100, 1000 },
|
||||
R.string.description_elevation_metric,
|
||||
R.string.description_elevation_imperial,
|
||||
R.color.chart_elevation_fill,
|
||||
R.color.chart_elevation_border);
|
||||
}
|
||||
|
||||
public void testInitialConditions() {
|
||||
assertEquals(1, series.getInterval());
|
||||
assertEquals(0, series.getMinMarkerValue());
|
||||
assertEquals(5, series.getMaxMarkerValue());
|
||||
assertTrue(series.isEnabled());
|
||||
}
|
||||
|
||||
public void testEnabled() {
|
||||
series.setEnabled(false);
|
||||
assertFalse(series.isEnabled());
|
||||
}
|
||||
|
||||
public void testSmallUpdates() {
|
||||
series.update(0);
|
||||
series.update(10);
|
||||
series.updateDimension();
|
||||
assertEquals(100, series.getInterval());
|
||||
assertEquals(0, series.getMinMarkerValue());
|
||||
assertEquals(500, series.getMaxMarkerValue());
|
||||
}
|
||||
|
||||
public void testBigUpdates() {
|
||||
series.update(0);
|
||||
series.update(901);
|
||||
series.updateDimension();
|
||||
assertEquals(1000, series.getInterval());
|
||||
assertEquals(0, series.getMinMarkerValue());
|
||||
assertEquals(5000, series.getMaxMarkerValue());
|
||||
}
|
||||
|
||||
public void testNotZeroBasedUpdates() {
|
||||
series.update(220);
|
||||
series.update(250);
|
||||
series.updateDimension();
|
||||
assertEquals(100, series.getInterval());
|
||||
assertEquals(200, series.getMinMarkerValue());
|
||||
assertEquals(700, series.getMaxMarkerValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
* Commons utilities for creating stubs of track, location. The class will be
|
||||
* enriched if needs more similar stubs for test.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class TrackStubUtils {
|
||||
|
||||
static final String LOCATION_PROVIDER = "gps";
|
||||
public static final double INITIAL_LATITUDE = 22;
|
||||
public static final double INITIAL_LONGITUDE = 22;
|
||||
public static final double INITIAL_ALTITUDE = 22;
|
||||
static final float INITIAL_ACCURACY = 5;
|
||||
static final float INITIAL_SPEED = 10;
|
||||
public static final long INITIAL_TIME = 1000L;
|
||||
static final float INITIAL_BEARING = 3.0f;
|
||||
// Used to change the value of latitude, longitude, and altitude.
|
||||
static final double DIFFERENCE = 0.01;
|
||||
|
||||
/**
|
||||
* Gets a a {@link Track} stub with specified number of locations.
|
||||
*
|
||||
* @param numberOfLocations the number of locations for the track
|
||||
* @return a track stub.
|
||||
*/
|
||||
public static Track createTrack(int numberOfLocations) {
|
||||
Track track = new Track();
|
||||
for (int i = 0; i < numberOfLocations; i++) {
|
||||
track.addLocation(createMyTracksLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE
|
||||
+ i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE));
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MyTracks location with default values.
|
||||
*
|
||||
* @return a track stub.
|
||||
*/
|
||||
public static MyTracksLocation createMyTracksLocation() {
|
||||
return createMyTracksLocation(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MyTracksLocation} stub with specified values.
|
||||
*
|
||||
* @return a MyTracksLocation stub.
|
||||
*/
|
||||
public static MyTracksLocation createMyTracksLocation(double latitude, double longitude,
|
||||
double altitude) {
|
||||
// Initial Location
|
||||
Location loc = new Location(LOCATION_PROVIDER);
|
||||
loc.setLatitude(latitude);
|
||||
loc.setLongitude(longitude);
|
||||
loc.setAltitude(altitude);
|
||||
loc.setAccuracy(INITIAL_ACCURACY);
|
||||
loc.setSpeed(INITIAL_SPEED);
|
||||
loc.setTime(INITIAL_TIME);
|
||||
loc.setBearing(INITIAL_BEARING);
|
||||
SensorDataSet sd = SensorDataSet.newBuilder().build();
|
||||
MyTracksLocation myTracksLocation = new MyTracksLocation(loc, sd);
|
||||
|
||||
return myTracksLocation;
|
||||
}
|
||||
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.content;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link DescriptionGeneratorImpl}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class DescriptionGeneratorImplTest extends AndroidTestCase {
|
||||
|
||||
private static final long START_TIME = 1288721514000L;
|
||||
private DescriptionGeneratorImpl descriptionGenerator;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
descriptionGenerator = new DescriptionGeneratorImpl(getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track,
|
||||
* java.util.Vector, java.util.Vector, boolean)}.
|
||||
*/
|
||||
public void testGenerateTrackDescription() {
|
||||
Track track = new Track();
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(550);
|
||||
stats.setMinElevation(-500);
|
||||
stats.setTotalElevationGain(6000);
|
||||
stats.setMaxGrade(0.42);
|
||||
stats.setMinGrade(0.11);
|
||||
stats.setStartTime(START_TIME);
|
||||
track.setTripStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
String expected = "Created by"
|
||||
+ " <a href='http://www.google.com/mobile/mytracks'>Google My Tracks</a> on Android<p>"
|
||||
+ "Name: -<br>"
|
||||
+ "Activity type: hiking<br>"
|
||||
+ "Description: -<br>"
|
||||
+ "Total distance: 20.00 km (12.4 mi)<br>"
|
||||
+ "Total time: 10:00<br>"
|
||||
+ "Moving time: 05:00<br>"
|
||||
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
|
||||
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
|
||||
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
|
||||
+ "Average pace: 0:30 min/km (0:48 min/mi)<br>"
|
||||
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
|
||||
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
|
||||
+ "Max elevation: 550 m (1804 ft)<br>"
|
||||
+ "Min elevation: -500 m (-1640 ft)<br>"
|
||||
+ "Elevation gain: 6000 m (19685 ft)<br>"
|
||||
+ "Max grade: 42 %<br>"
|
||||
+ "Min grade: 11 %<br>"
|
||||
+ "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "<br>";
|
||||
assertEquals(expected, descriptionGenerator.generateTrackDescription(track, null, null, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#generateWaypointDescription(TripStatistics)}.
|
||||
*/
|
||||
public void testGenerateWaypointDescription() {
|
||||
Waypoint waypoint = new Waypoint();
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(550);
|
||||
stats.setMinElevation(-500);
|
||||
stats.setTotalElevationGain(6000);
|
||||
stats.setMaxGrade(0.42);
|
||||
stats.setMinGrade(0.11);
|
||||
stats.setStartTime(START_TIME);
|
||||
waypoint.setTripStatistics(stats);
|
||||
String expected = "Total distance: 20.00 km (12.4 mi)\n"
|
||||
+ "Total time: 10:00\n"
|
||||
+ "Moving time: 05:00\n"
|
||||
+ "Average speed: 120.00 km/h (74.6 mi/h)\n"
|
||||
+ "Average moving speed: 240.00 km/h (149.1 mi/h)\n"
|
||||
+ "Max speed: 360.00 km/h (223.7 mi/h)\n"
|
||||
+ "Average pace: 0:30 min/km (0:48 min/mi)\n"
|
||||
+ "Average moving pace: 0:15 min/km (0:24 min/mi)\n"
|
||||
+ "Fastest pace: 0:10 min/km (0:16 min/mi)\n"
|
||||
+ "Max elevation: 550 m (1804 ft)\n"
|
||||
+ "Min elevation: -500 m (-1640 ft)\n"
|
||||
+ "Elevation gain: 6000 m (19685 ft)\n"
|
||||
+ "Max grade: 42 %\n"
|
||||
+ "Min grade: 11 %\n"
|
||||
+ "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "\n";
|
||||
assertEquals(
|
||||
expected, descriptionGenerator.generateWaypointDescription(waypoint.getTripStatistics()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteDistance() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeDistance(1100, builder, R.string.description_total_distance, "<br>");
|
||||
assertEquals("Total distance: 1.10 km (0.7 mi)<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int,
|
||||
* String)}.
|
||||
*/
|
||||
public void testWriteTime() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeTime(1000, builder, R.string.description_total_time, "<br>");
|
||||
assertEquals("Total time: 00:01<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteSpeed() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeSpeed(1.1, builder, R.string.description_average_speed, "\n");
|
||||
assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteElevation() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeElevation(4.2, builder, R.string.description_min_elevation, "<br>");
|
||||
assertEquals("Min elevation: 4 m (14 ft)<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writePace(double, StringBuilder, int,
|
||||
* String)}.
|
||||
*/
|
||||
public void testWritePace() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writePace(1.1, builder, R.string.description_average_pace_in_minute, "\n");
|
||||
assertEquals("Average pace: 15:09 min/km (24:23 min/mi)\n", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)}.
|
||||
*/
|
||||
public void testWriteGrade() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(.042, builder, R.string.description_max_grade, "<br>");
|
||||
assertEquals("Max grade: 4 %<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)} with a NaN.
|
||||
*/
|
||||
public void testWriteGrade_nan() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(Double.NaN, builder, R.string.description_max_grade, "<br>");
|
||||
assertEquals("Max grade: 0 %<br>", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder,
|
||||
* int, String)} with an infinite number.
|
||||
*/
|
||||
public void testWriteGrade_infinite() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeGrade(
|
||||
Double.POSITIVE_INFINITY, builder, R.string.description_max_grade, "<br>");
|
||||
assertEquals("Max grade: 0 %<br>", builder.toString());
|
||||
}
|
||||
}
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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.content;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider.DatabaseHelper;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MyTracksProviderTest extends AndroidTestCase {
|
||||
|
||||
private static final String DATABASE_NAME = "mytrackstest.db";
|
||||
|
||||
private SQLiteDatabase db;
|
||||
private MyTracksProvider myTracksProvider;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
getContext().deleteDatabase(DATABASE_NAME);
|
||||
db = (new DatabaseHelper(getContext(), DATABASE_NAME)).getWritableDatabase();
|
||||
myTracksProvider = new MyTracksProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onCreate(SQLiteDatabase)}.
|
||||
*/
|
||||
public void testDatabaseHelper_OnCreate() {
|
||||
assertTrue(hasTable(TracksColumns.TABLE_NAME));
|
||||
assertTrue(hasTable(TrackPointsColumns.TABLE_NAME));
|
||||
assertTrue(hasTable(WaypointsColumns.TABLE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is less than 17.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version16() {
|
||||
dropTable(TracksColumns.TABLE_NAME);
|
||||
dropTable(TrackPointsColumns.TABLE_NAME);
|
||||
dropTable(WaypointsColumns.TABLE_NAME);
|
||||
|
||||
int oldVersion = 16;
|
||||
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
|
||||
databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION);
|
||||
|
||||
assertTrue(hasTable(TracksColumns.TABLE_NAME));
|
||||
assertTrue(hasTable(TrackPointsColumns.TABLE_NAME));
|
||||
assertTrue(hasTable(WaypointsColumns.TABLE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 17.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version17() {
|
||||
setupUpgrade(17);
|
||||
|
||||
assertTrue(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 18.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version18() {
|
||||
setupUpgrade(18);
|
||||
|
||||
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 19.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version19() {
|
||||
setupUpgrade(19);
|
||||
|
||||
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 20.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version20() {
|
||||
setupUpgrade(20);
|
||||
|
||||
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 21.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version21() {
|
||||
setupUpgrade(21);
|
||||
|
||||
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int,
|
||||
* int)} when version is 22.
|
||||
*/
|
||||
public void testDatabaseHelper_onUpgrade_Version22() {
|
||||
setupUpgrade(22);
|
||||
|
||||
assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER));
|
||||
assertFalse(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL));
|
||||
assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider#onCreate(android.content.Context)}.
|
||||
*/
|
||||
public void testOnCreate() {
|
||||
assertTrue(myTracksProvider.onCreate(getContext()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MyTracksProvider#getType(Uri)}.
|
||||
*/
|
||||
public void testGetType() {
|
||||
assertEquals(TracksColumns.CONTENT_TYPE, myTracksProvider.getType(TracksColumns.CONTENT_URI));
|
||||
assertEquals(
|
||||
TrackPointsColumns.CONTENT_TYPE, myTracksProvider.getType(TrackPointsColumns.CONTENT_URI));
|
||||
assertEquals(
|
||||
WaypointsColumns.CONTENT_TYPE, myTracksProvider.getType(WaypointsColumns.CONTENT_URI));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table, containing one column.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private void createTable(String table) {
|
||||
db.execSQL("CREATE TABLE " + table + " (test INTEGER)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a table in database.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private void dropTable(String table) {
|
||||
db.execSQL("Drop TABLE " + table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the table exists.
|
||||
*
|
||||
* @param table the table name
|
||||
*/
|
||||
private boolean hasTable(String table) {
|
||||
try {
|
||||
db.rawQuery("select count(*) from " + table, null);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the column in the table exists.
|
||||
*
|
||||
* @param table the table name
|
||||
* @param column the column name
|
||||
*/
|
||||
private boolean hasColumn(String table, String column) {
|
||||
try {
|
||||
db.execSQL("SElECT count(*) from " + table + " order by " + column);
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage().indexOf("no such column") > -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up upgrade.
|
||||
*
|
||||
* @param oldVersion thd old database version
|
||||
*/
|
||||
private void setupUpgrade(int oldVersion) {
|
||||
dropTable(TracksColumns.TABLE_NAME);
|
||||
dropTable(TrackPointsColumns.TABLE_NAME);
|
||||
dropTable(WaypointsColumns.TABLE_NAME);
|
||||
createTable(TracksColumns.TABLE_NAME);
|
||||
createTable(TrackPointsColumns.TABLE_NAME);
|
||||
createTable(WaypointsColumns.TABLE_NAME);
|
||||
|
||||
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
|
||||
databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION);
|
||||
}
|
||||
}
|
||||
+908
@@ -0,0 +1,908 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A unit test for {@link MyTracksProviderUtilsImpl}.
|
||||
*
|
||||
* @author Bartlomiej Niechwiej
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MyTracksProviderUtilsImplTest extends AndroidTestCase {
|
||||
private Context context;
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
|
||||
private static final String NAME_PREFIX = "test name";
|
||||
private static final String MOCK_DESC = "Mock Next Waypoint Desc!";
|
||||
private static final String TEST_DESC = "Test Desc!";
|
||||
private static final String TEST_DESC_NEW = "Test Desc new!";
|
||||
private double INITIAL_LATITUDE = 37.0;
|
||||
private double INITIAL_LONGITUDE = -57.0;
|
||||
private double ALTITUDE_INTERVAL = 2.5;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
context = new MockContext(mockContentResolver, targetContext);
|
||||
MyTracksProvider provider = new MyTracksProvider();
|
||||
provider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
providerUtils.deleteAllTracks(context);
|
||||
}
|
||||
|
||||
public void testLocationIterator_noPoints() {
|
||||
testIterator(1, 0, 1, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_customFactory() {
|
||||
final Location location = new Location("test_location");
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
testIterator(1, 15, 4, false, new LocationFactory() {
|
||||
@Override
|
||||
public Location createLocation() {
|
||||
counter.incrementAndGet();
|
||||
return location;
|
||||
}
|
||||
});
|
||||
// Make sure we were called exactly as many times as we had track points.
|
||||
assertEquals(15, counter.get());
|
||||
}
|
||||
|
||||
public void testLocationIterator_nullFactory() {
|
||||
try {
|
||||
testIterator(1, 15, 4, false, null);
|
||||
fail("Expecting IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
public void testLocationIterator_noBatchAscending() {
|
||||
testIterator(1, 50, 100, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 50, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_noBatchDescending() {
|
||||
testIterator(1, 50, 100, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 50, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_batchAscending() {
|
||||
testIterator(1, 50, 11, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 25, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_batchDescending() {
|
||||
testIterator(1, 50, 11, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
testIterator(2, 50, 25, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
public void testLocationIterator_largeTrack() {
|
||||
testIterator(1, 20000, 2000, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
}
|
||||
|
||||
private List<Location> testIterator(long trackId, int numPoints, int batchSize,
|
||||
boolean descending, LocationFactory locationFactory) {
|
||||
long lastPointId = initializeTrack(trackId, numPoints);
|
||||
((MyTracksProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize);
|
||||
List<Location> locations = new ArrayList<Location>(numPoints);
|
||||
LocationIterator it = providerUtils.getTrackPointLocationIterator(
|
||||
trackId, -1L, descending, locationFactory);
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
Location loc = it.next();
|
||||
assertNotNull(loc);
|
||||
locations.add(loc);
|
||||
// Make sure the IDs are returned in the right order.
|
||||
assertEquals(descending ? lastPointId - locations.size() + 1
|
||||
: lastPointId - numPoints + locations.size(), it.getLocationId());
|
||||
}
|
||||
assertEquals(numPoints, locations.size());
|
||||
} finally {
|
||||
it.close();
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private long initializeTrack(long id, int numPoints) {
|
||||
Track track = new Track();
|
||||
track.setId(id);
|
||||
track.setName("Test: " + id);
|
||||
track.setNumberOfPoints(numPoints);
|
||||
providerUtils.insertTrack(track);
|
||||
track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
|
||||
Location[] locations = new Location[numPoints];
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(37.0 + (double) i / 10000.0);
|
||||
loc.setLongitude(57.0 - (double) i / 10000.0);
|
||||
loc.setAccuracy((float) i / 100.0f);
|
||||
loc.setAltitude(i * 2.5);
|
||||
locations[i] = loc;
|
||||
}
|
||||
providerUtils.bulkInsertTrackPoint(locations, numPoints, id);
|
||||
|
||||
// Load all inserted locations.
|
||||
long lastPointId = -1;
|
||||
int counter = 0;
|
||||
LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false,
|
||||
MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
lastPointId = it.getLocationId();
|
||||
counter++;
|
||||
}
|
||||
} finally {
|
||||
it.close();
|
||||
}
|
||||
|
||||
assertTrue(numPoints == 0 || lastPointId > 0);
|
||||
assertEquals(numPoints, track.getNumberOfPoints());
|
||||
assertEquals(numPoints, counter);
|
||||
|
||||
return lastPointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createTrack(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateTrack() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
int startColumnIndex = 1;
|
||||
int columnIndex = startColumnIndex;
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns._ID))
|
||||
.andReturn(columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).andReturn(
|
||||
columnIndex++);
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// Name
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
long trackId = System.currentTimeMillis();
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
|
||||
// Name
|
||||
String name = NAME_PREFIX + Long.toString(trackId);
|
||||
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
|
||||
AndroidMock.replay(cursorMock);
|
||||
Track track = providerUtils.createTrack(cursorMock);
|
||||
assertEquals(trackId, track.getId());
|
||||
assertEquals(name, track.getName());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#deleteAllTracks(Context)}
|
||||
*/
|
||||
public void testDeleteAllTracks() {
|
||||
// Insert track, points and waypoint at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
Waypoint waypoint = new Waypoint();
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
assertEquals(1, tracksCursor.getCount());
|
||||
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
assertEquals(10, tracksPointsCursor.getCount());
|
||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
assertEquals(1, waypointCursor.getCount());
|
||||
// Delete all.
|
||||
providerUtils.deleteAllTracks(context);
|
||||
// Check whether all have been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
assertEquals(0, tracksCursor.getCount());
|
||||
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
assertEquals(0, tracksPointsCursor.getCount());
|
||||
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
assertEquals(0, waypointCursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#deleteTrack(Context, long)}.
|
||||
*/
|
||||
public void testDeleteTrack() {
|
||||
// Insert three tracks, points of two tracks and way point of one track.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
|
||||
providerUtils.insertTrack(track);
|
||||
insertTrackWithLocations(getTrack(trackId + 1, 10));
|
||||
insertTrackWithLocations(getTrack(trackId + 2, 10));
|
||||
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
assertEquals(3, tracksCursor.getCount());
|
||||
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
assertEquals(20, tracksPointsCursor.getCount());
|
||||
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
assertEquals(1, waypointCursor.getCount());
|
||||
// Delete one track.
|
||||
providerUtils.deleteTrack(context, trackId);
|
||||
// Check whether all data of a track has been deleted.
|
||||
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
|
||||
TracksColumns._ID);
|
||||
assertEquals(2, tracksCursor.getCount());
|
||||
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
|
||||
null, TrackPointsColumns._ID);
|
||||
assertEquals(20, tracksPointsCursor.getCount());
|
||||
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
|
||||
null, WaypointsColumns._ID);
|
||||
assertEquals(0, waypointCursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getAllTracks()}
|
||||
*/
|
||||
public void testGetAllTracks() {
|
||||
int initialTrackNumber = providerUtils.getAllTracks().size();
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
List<Track> allTracks = providerUtils.getAllTracks();
|
||||
assertEquals(initialTrackNumber + 1, allTracks.size());
|
||||
assertEquals(trackId, allTracks.get(allTracks.size() - 1).getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrack()}
|
||||
*/
|
||||
public void testGetLastTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
assertEquals(trackId, providerUtils.getLastTrack().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getTrack(long)}
|
||||
*/
|
||||
public void testGetTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
providerUtils.insertTrack(getTrack(trackId, 0));
|
||||
assertNotNull(providerUtils.getTrack(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#updateTrack(Track)}
|
||||
*/
|
||||
public void testUpdateTrack() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 0);
|
||||
String nameOld = "name1";
|
||||
String nameNew = "name2";
|
||||
track.setName(nameOld);
|
||||
providerUtils.insertTrack(track);
|
||||
assertEquals(nameOld, providerUtils.getTrack(trackId).getName());
|
||||
track.setName(nameNew);
|
||||
providerUtils.updateTrack(track);
|
||||
assertEquals(nameNew, providerUtils.getTrack(trackId).getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createContentValues(Waypoint)}.
|
||||
*/
|
||||
public void testCreateContentValues_waypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
// Bottom
|
||||
long startTime = 1000L;
|
||||
// AverageSpeed
|
||||
double minGrade = -20.11;
|
||||
TripStatistics statistics = new TripStatistics();
|
||||
statistics.setStartTime(startTime);
|
||||
statistics.setStopTime(2500L);
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics.setMovingTime(700L);
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics.setMaxSpeed(60.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(minGrade);
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
// Insert at first.
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setType(WaypointType.STATISTICS);
|
||||
waypoint.setTripStatistics(statistics);
|
||||
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(22);
|
||||
loc.setLongitude(22);
|
||||
loc.setAccuracy((float) 1 / 100.0f);
|
||||
loc.setAltitude(2.5);
|
||||
waypoint.setLocation(loc);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
MyTracksProviderUtilsImpl myTracksProviderUtilsImpl = new MyTracksProviderUtilsImpl(
|
||||
new MockContentResolver());
|
||||
|
||||
long waypointId = System.currentTimeMillis();
|
||||
waypoint.setId(waypointId);
|
||||
ContentValues contentValues = myTracksProviderUtilsImpl.createContentValues(waypoint);
|
||||
assertEquals(waypointId, contentValues.get(WaypointsColumns._ID));
|
||||
assertEquals(22 * 1000000, contentValues.get(WaypointsColumns.LONGITUDE));
|
||||
assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
|
||||
assertEquals(startTime, contentValues.get(WaypointsColumns.STARTTIME));
|
||||
assertEquals(minGrade, contentValues.get(WaypointsColumns.MINGRADE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createWaypoint(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateWaypoint() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
int startColumnIndex = 1;
|
||||
int columnIndex = startColumnIndex;
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns._ID))
|
||||
.andReturn(columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.NAME)).andReturn(
|
||||
columnIndex++);
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.TRACKID)).andReturn(
|
||||
columnIndex++);
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// Name
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
// trackIdIndex
|
||||
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
|
||||
long id = System.currentTimeMillis();
|
||||
columnIndex = startColumnIndex;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(id);
|
||||
// Name
|
||||
String name = NAME_PREFIX + Long.toString(id);
|
||||
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
|
||||
// trackIdIndex
|
||||
long trackId = 11L;
|
||||
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
|
||||
AndroidMock.replay(cursorMock);
|
||||
Waypoint waypoint = providerUtils.createWaypoint(cursorMock);
|
||||
assertEquals(id, waypoint.getId());
|
||||
assertEquals(name, waypoint.getName());
|
||||
assertEquals(trackId, waypoint.getTrackId());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)}
|
||||
* when there is only one waypoint in the track.
|
||||
*/
|
||||
public void testDeleteWaypoint_onlyOneWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
// Insert at first.
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setDescription(TEST_DESC);
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
|
||||
// Delete
|
||||
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
|
||||
|
||||
@Override
|
||||
public String generateWaypointDescription(TripStatistics tripStatistics) {
|
||||
return MyTracksProviderUtilsImplTest.MOCK_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
|
||||
Vector<Double> elevations, boolean html) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
providerUtils.deleteWaypoint(context, 1, descriptionGenerator);
|
||||
|
||||
assertNull(providerUtils.getWaypoint(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)}
|
||||
* when there is more than one waypoint in the track.
|
||||
*/
|
||||
public void testDeleteWaypoint_hasNextWayPoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
TripStatistics statistics = new TripStatistics();
|
||||
statistics.setStartTime(1000L);
|
||||
statistics.setStopTime(2500L);
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics.setMovingTime(700L);
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics.setMaxSpeed(60.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(-25.0);
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
// Insert at first.
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setDescription(Long.toString(trackId));
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setTripStatistics(statistics);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setDescription(Long.toString(trackId));
|
||||
waypoint2.setTrackId(trackId);
|
||||
waypoint2.setType(WaypointType.STATISTICS);
|
||||
waypoint2.setTripStatistics(statistics);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
|
||||
// Delete
|
||||
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
|
||||
@Override
|
||||
public String generateWaypointDescription(TripStatistics tripStatistics) {
|
||||
return MyTracksProviderUtilsImplTest.MOCK_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
|
||||
Vector<Double> elevations, boolean html) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
providerUtils.deleteWaypoint(context, 1, descriptionGenerator);
|
||||
|
||||
assertNull(providerUtils.getWaypoint(1));
|
||||
assertEquals(MyTracksProviderUtilsImplTest.MOCK_DESC, providerUtils.getWaypoint(2)
|
||||
.getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstWaypointId(long)}.
|
||||
*/
|
||||
public void testGetFirstWaypointId() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setTrackId(trackId);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
|
||||
assertEquals(-1L, providerUtils.getFirstWaypointId(-1));
|
||||
assertEquals(1L, providerUtils.getFirstWaypointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getNextWaypointNumber(long, WaypointType)}.
|
||||
*/
|
||||
public void testGetNextWaypointNumber() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setTrackId(trackId);
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setType(WaypointType.WAYPOINT);
|
||||
waypoint2.setTrackId(trackId);
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
waypoint3.setType(WaypointType.STATISTICS);
|
||||
waypoint3.setTrackId(trackId);
|
||||
Waypoint waypoint4 = new Waypoint();
|
||||
waypoint4.setType(WaypointType.WAYPOINT);
|
||||
waypoint4.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
providerUtils.insertWaypoint(waypoint3);
|
||||
providerUtils.insertWaypoint(waypoint4);
|
||||
|
||||
assertEquals(2, providerUtils.getNextWaypointNumber(trackId, WaypointType.STATISTICS));
|
||||
assertEquals(3, providerUtils.getNextWaypointNumber(trackId, WaypointType.WAYPOINT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtils#getLastWaypoint(long, WaypointType)}.
|
||||
*/
|
||||
public void testGetLastStatisticsWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
waypoint1.setTrackId(trackId);
|
||||
waypoint1.setType(WaypointType.STATISTICS);
|
||||
waypoint1.setDescription("Desc1");
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
waypoint2.setTrackId(trackId);
|
||||
waypoint2.setType(WaypointType.STATISTICS);
|
||||
waypoint2.setDescription("Desc2");
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
waypoint3.setTrackId(trackId);
|
||||
waypoint3.setType(WaypointType.WAYPOINT);
|
||||
waypoint3.setDescription("Desc3");
|
||||
providerUtils.insertWaypoint(waypoint1);
|
||||
providerUtils.insertWaypoint(waypoint2);
|
||||
providerUtils.insertWaypoint(waypoint3);
|
||||
|
||||
assertEquals("Desc2", providerUtils.getLastWaypoint(trackId, WaypointType.STATISTICS).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#insertWaypoint(Waypoint)} and
|
||||
* {@link MyTracksProviderUtilsImpl#getWaypoint(long)}.
|
||||
*/
|
||||
public void testInsertAndGetWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
|
||||
assertEquals(TEST_DESC, providerUtils.getWaypoint(1).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#updateWaypoint(Waypoint)}.
|
||||
*/
|
||||
public void testUpdateWaypoint() {
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
providerUtils.insertTrack(track);
|
||||
// Insert at first.
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setDescription(TEST_DESC);
|
||||
waypoint.setTrackId(trackId);
|
||||
providerUtils.insertWaypoint(waypoint);
|
||||
// Update
|
||||
waypoint = providerUtils.getWaypoint(1);
|
||||
waypoint.setDescription(TEST_DESC_NEW);
|
||||
providerUtils.updateWaypoint(waypoint);
|
||||
|
||||
assertEquals(TEST_DESC_NEW, providerUtils.getWaypoint(1).getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#bulkInsertTrackPoint(Location[],
|
||||
* int, long)}.
|
||||
*/
|
||||
public void testBulkInsertTrackPoint() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), -1, trackId);
|
||||
assertEquals(20, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), 8, trackId);
|
||||
assertEquals(28, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#createTrackPoint(Cursor)}.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testCreateTrackPoint() {
|
||||
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
|
||||
|
||||
// Set index.
|
||||
int index = 1;
|
||||
// Id
|
||||
AndroidMock.expect(cursorMock.getColumnIndex(TrackPointsColumns._ID)).andReturn(index++);
|
||||
// Longitude
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE)).andReturn(
|
||||
index++);
|
||||
// Latitude
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE)).andReturn(
|
||||
index++);
|
||||
// Time
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.TIME))
|
||||
.andReturn(index++);
|
||||
// Speed
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn(
|
||||
index++);
|
||||
// Sensor
|
||||
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR)).andReturn(
|
||||
index++);
|
||||
|
||||
// Set return value of isNull().
|
||||
index = 2;
|
||||
// Longitude
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Latitude
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Time
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Speed
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
// Sensor
|
||||
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
|
||||
|
||||
// Set return value of isNull().
|
||||
index = 2;
|
||||
// Longitude
|
||||
int longitude = 11;
|
||||
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(longitude * 1000000);
|
||||
// Latitude.
|
||||
int latitude = 22;
|
||||
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(latitude * 1000000);
|
||||
// Time
|
||||
long time = System.currentTimeMillis();
|
||||
AndroidMock.expect(cursorMock.getLong(index++)).andReturn(time);
|
||||
// Speed
|
||||
float speed = 2.2f;
|
||||
AndroidMock.expect(cursorMock.getFloat(index++)).andReturn(speed);
|
||||
// Sensor
|
||||
byte[] sensor = "Sensor state".getBytes();
|
||||
AndroidMock.expect(cursorMock.getBlob(index++)).andReturn(sensor);
|
||||
|
||||
AndroidMock.replay(cursorMock);
|
||||
Location location = providerUtils.createTrackPoint(cursorMock);
|
||||
assertEquals((double) longitude, location.getLongitude());
|
||||
assertEquals((double) latitude, location.getLatitude());
|
||||
assertEquals(time, location.getTime());
|
||||
assertEquals(speed, location.getSpeed());
|
||||
AndroidMock.verify(cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#insertTrackPoint(Location, long)}.
|
||||
*/
|
||||
public void testInsertTrackPoint() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
providerUtils.insertTrackPoint(createLocation(22), trackId);
|
||||
assertEquals(11, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstTrackPointId(long)}.
|
||||
*/
|
||||
public void testGetFirstTrackPointId() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
assertEquals(1, providerUtils.getFirstTrackPointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrackPointId(long)}.
|
||||
*/
|
||||
public void testGetLastTrackPointId() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
assertEquals(10, providerUtils.getLastTrackPointId(trackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link MyTracksProviderUtilsImpl#getLastValidTrackPoint(long)}.
|
||||
*/
|
||||
public void testGetLastValidTrackPoint() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Location lastLocation = providerUtils.getLastValidTrackPoint(trackId);
|
||||
checkLocation(9, lastLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
|
||||
* in descending.
|
||||
*/
|
||||
public void testGetTrackPointCursor_desc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, true);
|
||||
assertEquals(2, cursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
|
||||
* in ascending.
|
||||
*/
|
||||
public void testGetTrackPointCursor_asc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, false);
|
||||
assertEquals(5, cursor.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
|
||||
* in descending.
|
||||
*/
|
||||
public void testGetTrackPointLocationIterator_desc() {
|
||||
// Insert track, points at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
long startTrackPointId = 2L;
|
||||
|
||||
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
|
||||
startTrackPointId, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
for (int i = 1; i >= 0; i--) {
|
||||
assertTrue(locationIterator.hasNext());
|
||||
Location location = locationIterator.next();
|
||||
assertEquals(2 + (i - 1), locationIterator.getLocationId());
|
||||
checkLocation(i, location);
|
||||
}
|
||||
assertFalse(locationIterator.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
|
||||
* in ascending.
|
||||
*/
|
||||
public void testGetTrackPointLocationIterator_asc() {
|
||||
// Insert track, point at first.
|
||||
long trackId = System.currentTimeMillis();
|
||||
Track track = getTrack(trackId, 10);
|
||||
insertTrackWithLocations(track);
|
||||
|
||||
long startTrackPointId = 2L;
|
||||
|
||||
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
|
||||
startTrackPointId, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
assertTrue(locationIterator.hasNext());
|
||||
Location location = locationIterator.next();
|
||||
assertEquals(2 + (i - 1), locationIterator.getLocationId());
|
||||
checkLocation(i, location);
|
||||
}
|
||||
assertFalse(locationIterator.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a track which is used for testing.
|
||||
*
|
||||
* @param id the id of the track
|
||||
* @param numPoints the location number in the track
|
||||
* @return the simulated track
|
||||
*/
|
||||
private Track getTrack(long id,int numPoints) {
|
||||
Track track = new Track();
|
||||
track.setId(id);
|
||||
track.setName("Test: " + id);
|
||||
track.setNumberOfPoints(numPoints);
|
||||
for(int i = 0; i < numPoints; i++) {
|
||||
track.addLocation(createLocation(i));
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a location.
|
||||
* @param i the index to set the value of location.
|
||||
* @return created location
|
||||
*/
|
||||
private Location createLocation(int i) {
|
||||
|
||||
Location loc = new Location("test");
|
||||
loc.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
|
||||
loc.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||
loc.setAccuracy((float) i / 100.0f);
|
||||
loc.setAltitude(i * ALTITUDE_INTERVAL);
|
||||
return loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the value of a location.
|
||||
*
|
||||
* @param i the index of this location which created in the method
|
||||
* {@link MyTracksProviderUtilsImplTest#getTrack(long, int)}
|
||||
* @param location the location to be checked
|
||||
*/
|
||||
private void checkLocation(int i, Location location) {
|
||||
assertEquals(INITIAL_LATITUDE + (double) i / 10000.0, location.getLatitude());
|
||||
assertEquals(INITIAL_LONGITUDE - (double) i / 10000.0, location.getLongitude());
|
||||
assertEquals((float) i / 100.0f, location.getAccuracy());
|
||||
assertEquals(i * ALTITUDE_INTERVAL, location.getAltitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a track with locations into the database.
|
||||
*
|
||||
* @param track track to be inserted
|
||||
*/
|
||||
private void insertTrackWithLocations(Track track) {
|
||||
providerUtils.insertTrack(track);
|
||||
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), track
|
||||
.getLocations().size(), track.getId());
|
||||
}
|
||||
}
|
||||
+326
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* 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.content;
|
||||
|
||||
import com.google.android.apps.mytracks.content.SearchEngine.ScoredResult;
|
||||
import com.google.android.apps.mytracks.content.SearchEngine.SearchQuery;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for {@link SearchEngine}.
|
||||
* These are not meant to be quality tests, but instead feature-by-feature tests
|
||||
* (in other words, they don't test the mixing of different score boostings, just
|
||||
* each boosting separately)
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class SearchEngineTest extends AndroidTestCase {
|
||||
|
||||
private static final Location HERE = new Location("gps");
|
||||
private static final long NOW = 1234567890000L; // After OLDEST_ALLOWED_TIMESTAMP
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private SearchEngine engine;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
MockContext context = new MockContext(mockContentResolver, targetContext);
|
||||
MyTracksProvider provider = new MyTracksProvider();
|
||||
provider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
engine = new SearchEngine(providerUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
providerUtils.deleteAllTracks(getContext());
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private long insertTrack(String title, String description, String category, double distance, long hoursAgo) {
|
||||
Track track = new Track();
|
||||
track.setName(title);
|
||||
track.setDescription(description);
|
||||
track.setCategory(category);
|
||||
|
||||
TripStatistics stats = track.getTripStatistics();
|
||||
if (hoursAgo > 0) {
|
||||
// Started twice hoursAgo, so the average time is hoursAgo.
|
||||
stats.setStartTime(NOW - hoursAgo * 1000L * 60L * 60L * 2);
|
||||
stats.setStopTime(NOW);
|
||||
}
|
||||
|
||||
int latitude = (int) ((HERE.getLatitude() + distance) * 1E6);
|
||||
int longitude = (int) ((HERE.getLongitude() + distance) * 1E6);
|
||||
stats.setBounds(latitude, longitude, latitude, longitude);
|
||||
|
||||
Uri uri = providerUtils.insertTrack(track);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, String description, String category) {
|
||||
return insertTrack(title, description, category, 0, -1);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, double distance) {
|
||||
return insertTrack(title, "", "", distance, -1);
|
||||
}
|
||||
|
||||
private long insertTrack(String title, long hoursAgo) {
|
||||
return insertTrack(title, "", "", 0.0, hoursAgo);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) {
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setName(title);
|
||||
waypoint.setDescription(description);
|
||||
waypoint.setCategory(category);
|
||||
waypoint.setTrackId(trackId);
|
||||
|
||||
Location location = new Location(HERE);
|
||||
location.setLatitude(location.getLatitude() + distance);
|
||||
location.setLongitude(location.getLongitude() + distance);
|
||||
if (hoursAgo >= 0) {
|
||||
location.setTime(NOW - hoursAgo * 1000L * 60L * 60L);
|
||||
}
|
||||
waypoint.setLocation(location);
|
||||
|
||||
Uri uri = providerUtils.insertWaypoint(waypoint);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, String description, String category) {
|
||||
return insertWaypoint(title, description, category, 0.0, -1, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, double distance) {
|
||||
return insertWaypoint(title, "", "", distance, -1, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, long hoursAgo) {
|
||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, -1);
|
||||
}
|
||||
|
||||
private long insertWaypoint(String title, long hoursAgo, long trackId) {
|
||||
return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId);
|
||||
}
|
||||
|
||||
public void testSearchText() {
|
||||
// Insert 7 tracks (purposefully out of result order):
|
||||
// - one which won't match
|
||||
// - one which will match the description
|
||||
// - one which will match the category
|
||||
// - one which will match the title
|
||||
// - one which will match in title and category
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertTrack("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertTrack("bb", "aa", "cc");
|
||||
long categoryMatchId = insertTrack("bb", "cc", "aa");
|
||||
long titleMatchId = insertTrack("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertTrack("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
|
||||
long allMatchId = insertTrack("aa", "ba", "ca");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertTrackResults(results,
|
||||
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
|
||||
categoryMatchId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointText() {
|
||||
// Insert 7 waypoints (purposefully out of result order):
|
||||
// - one which won't match
|
||||
// - one which will match the description
|
||||
// - one which will match the category
|
||||
// - one which will match the title
|
||||
// - one which will match in title and category
|
||||
// - one which will match in title and description
|
||||
// - one which will match in all fields
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long descriptionMatchId = insertWaypoint("bb", "aa", "cc");
|
||||
long categoryMatchId = insertWaypoint("bb", "cc", "aa");
|
||||
long titleMatchId = insertWaypoint("aa", "bb", "cc");
|
||||
long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
|
||||
long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
|
||||
long allMatchId = insertWaypoint("aa", "ba", "ca");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertWaypointResults(results,
|
||||
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
|
||||
categoryMatchId);
|
||||
}
|
||||
|
||||
public void testSearchMixedText() {
|
||||
// Insert 5 entries (purposefully out of result order):
|
||||
// - one waypoint which will match by description
|
||||
// - one waypoint which won't match
|
||||
// - one waypoint which will match by title
|
||||
// - one track which won't match
|
||||
// - one track which will match by title
|
||||
long descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
|
||||
insertWaypoint("bb", "cc", "dd");
|
||||
long titleWaypointId = insertWaypoint("aa", "bb", "cc");
|
||||
insertTrack("bb", "cc", "dd");
|
||||
long trackId = insertTrack("aa", "bb", "cc");
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Title > Description > Category.
|
||||
assertEquals(results.toString(), 3, results.size());
|
||||
assertTrackResult(trackId, results.get(0));
|
||||
assertWaypointResult(titleWaypointId, results.get(1));
|
||||
assertWaypointResult(descriptionWaypointId, results.get(2));
|
||||
}
|
||||
|
||||
public void testSearchTrackDistance() {
|
||||
// All results match text, but they're at difference distances from the user.
|
||||
long farFarAwayId = insertTrack("aa", 0.3);
|
||||
long nearId = insertTrack("ab", 0.1);
|
||||
long farId = insertTrack("ac", 0.2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Distance order.
|
||||
assertTrackResults(results, nearId, farId, farFarAwayId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointDistance() {
|
||||
// All results match text, but they're at difference distances from the user.
|
||||
long farFarAwayId = insertWaypoint("aa", 0.3);
|
||||
long nearId = insertWaypoint("ab", 0.1);
|
||||
long farId = insertWaypoint("ac", 0.2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Distance order.
|
||||
assertWaypointResults(results, nearId, farId, farFarAwayId);
|
||||
}
|
||||
|
||||
public void testSearchTrackRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertTrack("aa", 3);
|
||||
long recentId = insertTrack("ab", 1);
|
||||
long oldId = insertTrack("ac", 2);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Reverse time order.
|
||||
assertTrackResults(results, recentId, oldId, oldestId);
|
||||
}
|
||||
|
||||
public void testSearchWaypointRecent() {
|
||||
// All results match text, but they're were recorded at different times.
|
||||
long oldestId = insertWaypoint("aa", 2);
|
||||
long recentId = insertWaypoint("ab", 0);
|
||||
long oldId = insertWaypoint("ac", 1);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, -1, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Reverse time order.
|
||||
assertWaypointResults(results, recentId, oldId, oldestId);
|
||||
}
|
||||
|
||||
public void testSearchCurrentTrack() {
|
||||
// All results match text, but one of them is the current track.
|
||||
long currentId = insertTrack("ab", 1);
|
||||
long otherId = insertTrack("aa", 1);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Current track should be demoted.
|
||||
assertTrackResults(results, otherId, currentId);
|
||||
}
|
||||
|
||||
public void testSearchCurrentTrackWaypoint() {
|
||||
// All results match text, but one of them is in the current track.
|
||||
long otherId = insertWaypoint("aa", 1, 456);
|
||||
long currentId = insertWaypoint("ab", 1, 123);
|
||||
|
||||
SearchQuery query = new SearchQuery("a", null, 123, NOW);
|
||||
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
|
||||
|
||||
// Waypoint in current track should be promoted.
|
||||
assertWaypointResults(results, currentId, otherId);
|
||||
}
|
||||
|
||||
private void assertTrackResult(long trackId, ScoredResult result) {
|
||||
assertNotNull("Not a track", result.track);
|
||||
assertNull("Ambiguous result", result.waypoint);
|
||||
assertEquals(trackId, result.track.getId());
|
||||
}
|
||||
|
||||
private void assertTrackResults(List<ScoredResult> results, long... trackIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results;
|
||||
assertEquals(results.size(), trackIds.length);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
ScoredResult result = results.get(i);
|
||||
assertNotNull(errMsg, result.track);
|
||||
assertNull(errMsg, result.waypoint);
|
||||
assertEquals(errMsg, trackIds[i], result.track.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertWaypointResult(long waypointId, ScoredResult result) {
|
||||
assertNotNull("Not a waypoint", result.waypoint);
|
||||
assertNull("Ambiguous result", result.track);
|
||||
assertEquals(waypointId, result.waypoint.getId());
|
||||
}
|
||||
|
||||
private void assertWaypointResults(List<ScoredResult> results, long... waypointIds) {
|
||||
String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results;
|
||||
assertEquals(results.size(), waypointIds.length);
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
ScoredResult result = results.get(i);
|
||||
assertNotNull(errMsg, result.waypoint);
|
||||
assertNull(errMsg, result.track);
|
||||
assertEquals(errMsg, waypointIds[i], result.waypoint.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
+805
@@ -0,0 +1,805 @@
|
||||
/*
|
||||
* Copyright 2011 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.content;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
import static com.google.android.testing.mocking.AndroidMock.isA;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.location.Location;
|
||||
import android.provider.BaseColumns;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.easymock.Capture;
|
||||
import org.easymock.IAnswer;
|
||||
|
||||
/**
|
||||
* Tests for {@link TrackDataHub}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TrackDataHubTest extends AndroidTestCase {
|
||||
|
||||
private static final long TRACK_ID = 42L;
|
||||
private static final int TARGET_POINTS = 50;
|
||||
|
||||
private MockContext context;
|
||||
private SharedPreferences sharedPreferences;
|
||||
private MyTracksProviderUtils myTracksProviderUtils;
|
||||
private DataSource dataSource;
|
||||
private TrackDataManager trackDataManager;
|
||||
private TrackDataHub trackDataHub;
|
||||
private TrackDataListener trackDataListener1;
|
||||
private TrackDataListener trackDataListener2;
|
||||
private Capture<OnSharedPreferenceChangeListener> preferenceChangeListenerCapture = new Capture<
|
||||
SharedPreferences.OnSharedPreferenceChangeListener>();
|
||||
|
||||
@UsesMocks({ MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class })
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = new MockContext(new MockContentResolver(), new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test."));
|
||||
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
|
||||
dataSource = AndroidMock.createMock(DataSource.class, context);
|
||||
trackDataManager = new TrackDataManager();
|
||||
trackDataHub = new TrackDataHub(
|
||||
context, trackDataManager, myTracksProviderUtils, TARGET_POINTS) {
|
||||
@Override
|
||||
protected DataSource newDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runInHanderThread(Runnable runnable) {
|
||||
// Run everything in the same thread
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
trackDataListener1 = AndroidMock.createStrictMock(
|
||||
"trackDataListener1", TrackDataListener.class);
|
||||
trackDataListener2 = AndroidMock.createStrictMock(
|
||||
"trackDataListener2", TrackDataListener.class);
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, TRACK_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
AndroidMock.reset(dataSource);
|
||||
|
||||
// Expect everything to be unregistered.
|
||||
dataSource.unregisterContentObserver(isA(ContentObserver.class));
|
||||
AndroidMock.expectLastCall().times(3);
|
||||
dataSource.unregisterOnSharedPreferenceChangeListener(
|
||||
isA(OnSharedPreferenceChangeListener.class));
|
||||
AndroidMock.replay(dataSource);
|
||||
|
||||
trackDataHub.stop();
|
||||
trackDataHub = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests registering for tracks table update.
|
||||
*/
|
||||
public void testTracksTableUpdate() {
|
||||
|
||||
// Register two listeners
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
Track track = new Track();
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
dataSource.registerContentObserver(
|
||||
eq(TracksColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Causes tracks table update
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener
|
||||
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
|
||||
trackDataListener2.onTrackUpdated(track);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the second listener
|
||||
dataSource.unregisterContentObserver(contentObserver);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener2);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests registering for waypoints table update.
|
||||
*/
|
||||
public void testWaypointsTableUpdate() {
|
||||
Waypoint waypoint1 = new Waypoint();
|
||||
Waypoint waypoint2 = new Waypoint();
|
||||
Waypoint waypoint3 = new Waypoint();
|
||||
Waypoint waypoint4 = new Waypoint();
|
||||
Location location = new Location("gps");
|
||||
location.setLatitude(10.0);
|
||||
location.setLongitude(8.0);
|
||||
waypoint1.setLocation(location);
|
||||
waypoint2.setLocation(location);
|
||||
waypoint3.setLocation(location);
|
||||
waypoint4.setLocation(location);
|
||||
|
||||
// Register two listeners
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(2));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint1).andReturn(waypoint2);
|
||||
dataSource.registerContentObserver(
|
||||
eq(WaypointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener1.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener1.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Cause waypoints table update
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(3));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3);
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener1.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener1.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener1.onNewWaypoint(waypoint3);
|
||||
trackDataListener2.onNewWaypoint(waypoint3);
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS)))
|
||||
.andStubAnswer(new FixedSizeCursorAnswer(4));
|
||||
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
|
||||
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3).andReturn(waypoint4);
|
||||
trackDataListener2.clearWaypoints();
|
||||
trackDataListener2.onNewWaypoint(waypoint1);
|
||||
trackDataListener2.onNewWaypoint(waypoint2);
|
||||
trackDataListener2.onNewWaypoint(waypoint3);
|
||||
trackDataListener2.onNewWaypoint(waypoint4);
|
||||
trackDataListener2.onNewWaypointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the second listener
|
||||
dataSource.unregisterContentObserver(contentObserver);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener2);
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate() {
|
||||
// Register one listener
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Register a second listener
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Deliver more points - should go to both listeners without clearing
|
||||
ContentObserver contentObserver = contentObserverCapture.getValue();
|
||||
locationIterator = new FixedSizeLocationIterator(11, 10, 1);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(20L);
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
contentObserver.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister one listener and change track
|
||||
locationIterator = new FixedSizeLocationIterator(101, 10);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
|
||||
.andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(110L);
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener2);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
trackDataHub.loadTrack(TRACK_ID + 1);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with registering the same listener.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_reRegister() {
|
||||
|
||||
// Register one listener
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the listener
|
||||
ContentObserver observer = contentObserverCapture.getValue();
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
verifyAndReset();
|
||||
|
||||
// Register again
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests tracks point able change. Register a listener after a track change.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_reRegisterAfterTrackChange() {
|
||||
|
||||
// Register one listener
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Unregister the listener
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
dataSource.unregisterContentObserver(observer);
|
||||
replay();
|
||||
|
||||
trackDataHub.unregisterTrackDataListener(trackDataListener1);
|
||||
verifyAndReset();
|
||||
|
||||
// Register the listener after a new track
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
locationIterator = new FixedSizeLocationIterator(1, 10);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
|
||||
.andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(10L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.loadTrack(TRACK_ID + 1);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with large track sampling.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_largeTrackSampling() {
|
||||
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
|
||||
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(200L);
|
||||
AndroidMock.expectLastCall().anyTimes();
|
||||
FixedSizeLocationIterator locationIterator1 = new FixedSizeLocationIterator(
|
||||
1, 200, 4, 25, 71, 120);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator1);
|
||||
FixedSizeLocationIterator locationIterator2 = new FixedSizeLocationIterator(
|
||||
1, 200, 4, 25, 71, 120);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator2);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator1.expectSampledLocationsDelivered(trackDataListener1, 4, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
trackDataListener2.clearTrackPoints();
|
||||
locationIterator2.expectSampledLocationsDelivered(trackDataListener2, 4, true);
|
||||
trackDataListener2.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
trackDataHub.registerTrackDataListener(trackDataListener2, EnumSet.of(
|
||||
TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE, TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track points table update with resampling.
|
||||
*/
|
||||
public void testTrackPointsTableUpdate_resampling() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(
|
||||
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
|
||||
// Deliver 30 points (no sampling happens)
|
||||
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(30L);
|
||||
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectLocationsDelivered(trackDataListener1);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.loadTrack(TRACK_ID);
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
|
||||
verifyAndReset();
|
||||
|
||||
// Now deliver 30 more (incrementally sampled)
|
||||
ContentObserver observer = observerCapture.getValue();
|
||||
locationIterator = new FixedSizeLocationIterator(31, 30);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(31L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(60L);
|
||||
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
observer.onChange(false);
|
||||
verifyAndReset();
|
||||
|
||||
// Now another 30 (triggers resampling)
|
||||
locationIterator = new FixedSizeLocationIterator(1, 90);
|
||||
expect(myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(90L);
|
||||
trackDataListener1.clearTrackPoints();
|
||||
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
|
||||
trackDataListener1.onNewTrackPointsDone();
|
||||
replay();
|
||||
|
||||
observer.onChange(false);
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests preferences change.
|
||||
*/
|
||||
public void testPreferencesChange() throws Exception {
|
||||
|
||||
// Register two listeners
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_rate_key, PreferencesUtils.STATS_RATE_DEFAULT);
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key,
|
||||
PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
||||
|
||||
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
|
||||
expect(trackDataListener1.onMetricUnitsChanged(true)).andReturn(false);
|
||||
expect(trackDataListener1.onReportSpeedChanged(true)).andReturn(false);
|
||||
expect(
|
||||
trackDataListener1.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT))
|
||||
.andReturn(false);
|
||||
expect(trackDataListener1.onRecordingDistanceIntervalChanged(
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false);
|
||||
expect(trackDataListener1.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false);
|
||||
|
||||
expect(trackDataListener2.onMetricUnitsChanged(true)).andReturn(false);
|
||||
expect(trackDataListener2.onReportSpeedChanged(true)).andReturn(false);
|
||||
expect(
|
||||
trackDataListener2.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT))
|
||||
.andReturn(false);
|
||||
expect(trackDataListener2.onRecordingDistanceIntervalChanged(
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false);
|
||||
expect(trackDataListener2.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false);
|
||||
replay();
|
||||
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.PREFERENCE));
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener2, EnumSet.of(TrackDataType.PREFERENCE));
|
||||
verifyAndReset();
|
||||
|
||||
// Change report speed to false
|
||||
expect(trackDataListener1.onReportSpeedChanged(false)).andReturn(false);
|
||||
expect(trackDataListener2.onReportSpeedChanged(false)).andReturn(false);
|
||||
replay();
|
||||
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_rate_key, context.getString(R.string.stats_rate_pace));
|
||||
OnSharedPreferenceChangeListener listener = preferenceChangeListenerCapture.getValue();
|
||||
listener.onSharedPreferenceChanged(
|
||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_rate_key));
|
||||
verifyAndReset();
|
||||
|
||||
// Change metric units to false
|
||||
expect(trackDataListener1.onMetricUnitsChanged(false)).andReturn(false);
|
||||
expect(trackDataListener2.onMetricUnitsChanged(false)).andReturn(false);
|
||||
replay();
|
||||
|
||||
String imperialUnits = context.getString(R.string.stats_units_imperial);
|
||||
PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits);
|
||||
listener.onSharedPreferenceChanged(
|
||||
sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replays mocks.
|
||||
*/
|
||||
private void replay() {
|
||||
AndroidMock.replay(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies and resets mocks.
|
||||
*/
|
||||
private void verifyAndReset() {
|
||||
AndroidMock.verify(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
AndroidMock.reset(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed size cursor answer.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private static class FixedSizeCursorAnswer implements IAnswer<Cursor> {
|
||||
private final int size;
|
||||
|
||||
public FixedSizeCursorAnswer(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor answer() throws Throwable {
|
||||
MatrixCursor cursor = new MatrixCursor(new String[] { BaseColumns._ID });
|
||||
for (long i = 0; i < size; i++) {
|
||||
cursor.addRow(new Object[] { i });
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed size location iterator.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private static class FixedSizeLocationIterator implements LocationIterator {
|
||||
private final long startId;
|
||||
private final Location[] locations;
|
||||
private final Set<Integer> splitIndexSet = new HashSet<Integer>();
|
||||
private int currentIndex = -1;
|
||||
|
||||
public FixedSizeLocationIterator(long startId, int size) {
|
||||
this(startId, size, null);
|
||||
}
|
||||
|
||||
public FixedSizeLocationIterator(long startId, int size, int... splitIndexes) {
|
||||
this.startId = startId;
|
||||
this.locations = new Location[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Location location = new Location("gps");
|
||||
location.setLatitude(-15.0 + i / 1000.0);
|
||||
location.setLongitude(37 + i / 1000.0);
|
||||
location.setAltitude(i);
|
||||
locations[i] = location;
|
||||
}
|
||||
|
||||
if (splitIndexes != null) {
|
||||
for (int splitIndex : splitIndexes) {
|
||||
splitIndexSet.add(splitIndex);
|
||||
|
||||
Location splitLocation = locations[splitIndex];
|
||||
splitLocation.setLatitude(100.0);
|
||||
splitLocation.setLongitude(200.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void expectLocationsDelivered(TrackDataListener listener) {
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
if (splitIndexSet.contains(i)) {
|
||||
listener.onSegmentSplit(locations[i]);
|
||||
} else {
|
||||
listener.onSampledInTrackPoint(locations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void expectSampledLocationsDelivered(
|
||||
TrackDataListener listener, int sampleFrequency, boolean includeSampledOut) {
|
||||
boolean includeNext = false;
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
if (splitIndexSet.contains(i)) {
|
||||
listener.onSegmentSplit(locations[i]);
|
||||
includeNext = true;
|
||||
} else if (includeNext || (i % sampleFrequency == 0)) {
|
||||
listener.onSampledInTrackPoint(locations[i]);
|
||||
includeNext = false;
|
||||
} else if (includeSampledOut) {
|
||||
listener.onSampledOutTrackPoint(locations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentIndex < locations.length - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location next() {
|
||||
currentIndex++;
|
||||
return locations[currentIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLocationId() {
|
||||
return startId + currentIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#start()}.
|
||||
*/
|
||||
public void testRegisterTracksTableListener() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture));
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
expect(myTracksProviderUtils.getTrack(capture(new Capture<Long>()))).andReturn(track);
|
||||
// Make the track id is unique.
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, System.currentTimeMillis());
|
||||
trackDataListener1.onTrackUpdated(track);
|
||||
replay();
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#start()}.
|
||||
*/
|
||||
public void testRegisterWaypointsTableListener() {
|
||||
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
|
||||
dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture));
|
||||
expect(myTracksProviderUtils.getWaypointCursor(
|
||||
capture(new Capture<Long>()), capture(new Capture<Long>()),
|
||||
capture(new Capture<Integer>()))).andReturn(null);
|
||||
trackDataListener1.clearWaypoints();
|
||||
trackDataListener1.onNewWaypointsDone();
|
||||
replay();
|
||||
trackDataHub.start();
|
||||
trackDataHub.registerTrackDataListener(
|
||||
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
|
||||
verifyAndReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.min_required_accuracy_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_minRequiredAccuracy() {
|
||||
int value = 1;
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.recording_gps_accuracy_key));
|
||||
assertEquals(value, trackDataHub.getRecordingGpsAccuracy());
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value + 1);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.recording_gps_accuracy_key));
|
||||
assertEquals(value + 1, trackDataHub.getRecordingGpsAccuracy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.metric_units_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_metricUnitsNoNotify() {
|
||||
String imperialUnits = context.getString(R.string.stats_units_imperial);
|
||||
|
||||
PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits);
|
||||
trackDataHub.notifyPreferenceChanged(
|
||||
PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
assertEquals(false, trackDataHub.isMetricUnits());
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
trackDataHub.notifyPreferenceChanged(
|
||||
PreferencesUtils.getKey(context, R.string.stats_units_key));
|
||||
assertEquals(true, trackDataHub.isMetricUnits());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
|
||||
* the key is R.string.metric_units_key.
|
||||
*/
|
||||
public void testNotifyPreferenceChanged_reportSpeedNoNotify() {
|
||||
String value = context.getString(R.string.stats_rate_pace);
|
||||
PreferencesUtils.setString(context, R.string.stats_rate_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.stats_rate_key));
|
||||
assertEquals(false, trackDataHub.isReportSpeed());
|
||||
|
||||
value = context.getString(R.string.stats_rate_speed);
|
||||
PreferencesUtils.setString(context, R.string.stats_rate_key, value);
|
||||
trackDataHub.notifyPreferenceChanged(PreferencesUtils
|
||||
.getKey(context, R.string.stats_rate_key));
|
||||
assertEquals(true, trackDataHub.isReportSpeed());
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.content;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for the WaypointCreationRequest class.
|
||||
* {@link WaypointCreationRequest}
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class WaypointCreationRequestTest extends AndroidTestCase {
|
||||
|
||||
public void testTypeParceling() {
|
||||
WaypointCreationRequest original = WaypointCreationRequest.DEFAULT_WAYPOINT;
|
||||
Parcel p = Parcel.obtain();
|
||||
original.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
|
||||
assertEquals(original.getType(), copy.getType());
|
||||
assertFalse(copy.isTrackStatistics());
|
||||
assertNull(copy.getName());
|
||||
assertNull(copy.getDescription());
|
||||
assertNull(copy.getIconUrl());
|
||||
}
|
||||
|
||||
public void testAllAttributesParceling() {
|
||||
WaypointCreationRequest original = new WaypointCreationRequest(
|
||||
WaypointType.WAYPOINT, false, "name", "category", "description", "img.png", null);
|
||||
Parcel p = Parcel.obtain();
|
||||
original.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
|
||||
assertEquals(original.getType(), copy.getType());
|
||||
assertFalse(copy.isTrackStatistics());
|
||||
assertEquals("name", copy.getName());
|
||||
assertEquals("category", copy.getCategory());
|
||||
assertEquals("description", copy.getDescription());
|
||||
assertEquals("img.png", copy.getIconUrl());
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.test.InstrumentationTestRunner;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* End-to-end test test runner.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class EndToEndTestRunner extends InstrumentationTestRunner {
|
||||
|
||||
private static final String TAG = EndToEndTestRunner.class.getSimpleName();
|
||||
private static final String PORT_KEY = "port";
|
||||
private static final String RESOURCE_KEY = "resource";
|
||||
private static final String SENSOR_KEY = "sensor";
|
||||
private static final String STRESS_KEY = "stress";
|
||||
private static final String TRUE_VALUE = "true";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
|
||||
// Get the emulator port parameter for GPS signals
|
||||
String port = bundle.getString(PORT_KEY);
|
||||
if (port != null) {
|
||||
try {
|
||||
EndToEndTestUtils.emulatorPort = Integer.parseInt(port);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to get emulator port parameter, use the default value.", e);
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Emulator port: " + EndToEndTestUtils.emulatorPort);
|
||||
|
||||
RunConfiguration runConfiguration = RunConfiguration.getInstance();
|
||||
|
||||
runConfiguration.setRunResourceTest(
|
||||
TRUE_VALUE.equalsIgnoreCase(bundle.getString(RESOURCE_KEY)));
|
||||
Log.d(TAG, "Run resource test: " + runConfiguration.getRunResourceTest());
|
||||
|
||||
runConfiguration.setRunSensorTest(TRUE_VALUE.equalsIgnoreCase(bundle.getString(SENSOR_KEY)));
|
||||
Log.d(TAG, "Run sensor test: " + runConfiguration.getRunSensorTest());
|
||||
|
||||
runConfiguration.setRunStressTest(TRUE_VALUE.equalsIgnoreCase(bundle.getString(STRESS_KEY)));
|
||||
Log.d(TAG, "Run stress test: " + runConfiguration.getRunStressTest());
|
||||
|
||||
super.onCreate(bundle);
|
||||
}
|
||||
}
|
||||
+936
@@ -0,0 +1,936 @@
|
||||
package com.google.android.apps.mytracks.endtoendtest;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.robotium.solo.Solo;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Provides utilities to smoke test.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class EndToEndTestUtils {
|
||||
|
||||
public static final int TINY_WAIT_TIME = 200;
|
||||
public static final int VERY_SHORT_WAIT_TIME = 500;
|
||||
public static final int SHORT_WAIT_TIME = 2000;
|
||||
public static final int NORMAL_WAIT_TIME = 8000;
|
||||
public static final int LONG_WAIT_TIME = 15000;
|
||||
public static final int SUPER_LONG_WAIT_TIME = 100000;
|
||||
|
||||
// Pause 200ms between each send.
|
||||
public static final double START_LONGITUDE = 51;
|
||||
public static final double START_LATITUDE = -1.3f;
|
||||
public static final double DELTA_LONGITUDE = 0.0005f;
|
||||
public static final double DELTA_LADITUDE = 0.0005f;
|
||||
public static final String WAYPOINT_NAME = "testWaypoint";
|
||||
public static final String WAYPOINT_TYPE = "testWaypoinType";
|
||||
public static final String WAYPOINT_DESCRIPTION = "testWaypointDesc";
|
||||
public static final String DEFAULT_ACTIVITY_TYPE = "TestActivity";
|
||||
public static final String TRACK_NAME_PREFIX = "testTrackName";
|
||||
|
||||
private static final String TAG = EndToEndTestUtils.class.getSimpleName();
|
||||
private static final String TRACK_DESCRIPTION_PREFIX = "testTrackDesc";
|
||||
|
||||
private static final int ORIENTATION_PORTRAIT = 1;
|
||||
private static final int ORIENTATION_LANDSCAPE = 0;
|
||||
|
||||
private static final String ANDROID_LOCAL_IP = "10.0.2.2";
|
||||
private static final String NO_GPS_MESSAGE_PREFIX = "GPS is not available";
|
||||
private static final String MORE_OPTION_CLASSNAME = "com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton";
|
||||
private static final String MENUITEM_CLASSNAME = "com.android.internal.view.menu.IconMenuItemView";
|
||||
|
||||
// Following is some check strings in English and Chinese
|
||||
private static final HashMap<String, String>
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("en", "mins ago");
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("de", "Minuten");
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("fr", "minute");
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("ar", "دقيقة");
|
||||
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("zh", "分钟前");
|
||||
}
|
||||
|
||||
public static int emulatorPort = 5554; // usually 5554.
|
||||
public static String activityType = DEFAULT_ACTIVITY_TYPE;
|
||||
public static String trackName;
|
||||
public static String trackDescription;
|
||||
public static com.robotium.solo.Solo SOLO;
|
||||
public static Instrumentation instrumentation;
|
||||
public static TrackListActivity trackListActivity;
|
||||
|
||||
/*
|
||||
* Check whether the UI has an action bar which is related with the version of
|
||||
* Android OS.
|
||||
*/
|
||||
public static boolean hasActionBar = false;
|
||||
public static boolean isEmulator = true;
|
||||
public static boolean hasGpsSignal = true;
|
||||
|
||||
private static boolean isCheckedFirstLaunch = false;
|
||||
private static boolean isGooglePlayServicesLatest = true;
|
||||
private static String language;
|
||||
|
||||
private EndToEndTestUtils() {};
|
||||
|
||||
/**
|
||||
* Checks the language, then sets the fields with right string.
|
||||
*/
|
||||
private static void checkLanguage() {
|
||||
Locale locale = new Locale("en");
|
||||
Locale.setDefault(locale);
|
||||
|
||||
Configuration configuration = trackListActivity.getBaseContext()
|
||||
.getResources().getConfiguration();
|
||||
configuration.locale = locale;
|
||||
|
||||
language = instrumentation.getContext().getResources().getConfiguration().locale.getLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Gps data to emulator, and the start value has an offset.
|
||||
*
|
||||
* @param number send times
|
||||
* @param offset is used to compute the start latitude and longitude
|
||||
* @param pause pause interval between each sending
|
||||
*/
|
||||
public static void sendGps(int number, int offset, int pause) {
|
||||
if (number < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pauseInterval = TINY_WAIT_TIME;
|
||||
if (pause != -1) {
|
||||
pauseInterval = pause;
|
||||
}
|
||||
|
||||
// If it's a real device, does not send simulated GPS signal.
|
||||
if (!isEmulator) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrintStream out = null;
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket(ANDROID_LOCAL_IP, emulatorPort);
|
||||
out = new PrintStream(socket.getOutputStream());
|
||||
double longitude = START_LONGITUDE + offset * DELTA_LONGITUDE;
|
||||
double latitude = START_LATITUDE + offset * DELTA_LADITUDE;
|
||||
for (int i = 0; i < number; i++) {
|
||||
out.println("geo fix " + longitude + " " + latitude);
|
||||
longitude += DELTA_LONGITUDE;
|
||||
latitude += DELTA_LADITUDE;
|
||||
Thread.sleep(pauseInterval);
|
||||
}
|
||||
// Wait the GPS signal can be obtained by MyTracks.
|
||||
Thread.sleep(SHORT_WAIT_TIME);
|
||||
} catch (UnknownHostException e) {
|
||||
System.exit(-1);
|
||||
} catch (IOException e) {
|
||||
System.exit(-1);
|
||||
} catch (InterruptedException e) {
|
||||
System.exit(-1);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Gps data to emulator.
|
||||
*
|
||||
* @param number number of signals
|
||||
* @param offset is used to compute the start latitude and longitude
|
||||
*/
|
||||
public static void sendGps(int number, int offset) {
|
||||
sendGps(number, offset, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Gps data to emulator.
|
||||
*
|
||||
* @param number number of signals
|
||||
*/
|
||||
public static void sendGps(int number) {
|
||||
sendGps(number, 0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status whether the test is run on an emulator or not.
|
||||
*/
|
||||
private static void setIsEmulator() {
|
||||
isEmulator = android.os.Build.MODEL.equals("google_sdk");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the Google Play Services need update.
|
||||
*/
|
||||
private static boolean isGooglePlayServicesLatest() {
|
||||
return findTextView("Google Play services") == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A setup for debugging end-to-end tests.
|
||||
*
|
||||
* @param inst the instrumentation
|
||||
* @param activity the track list activity
|
||||
*/
|
||||
public static void setupForDebug(Instrumentation inst, TrackListActivity activity) {
|
||||
instrumentation = inst;
|
||||
trackListActivity = activity;
|
||||
SOLO = new Solo(instrumentation, trackListActivity);
|
||||
setIsEmulator();
|
||||
hasActionBar = setHasActionBar();
|
||||
checkLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* A setup for all end-to-end tests.
|
||||
*
|
||||
* @param inst the instrumentation
|
||||
* @param activity the track list activity
|
||||
*/
|
||||
public static void setupForAllTest(Instrumentation inst, TrackListActivity activity) {
|
||||
instrumentation = inst;
|
||||
trackListActivity = activity;
|
||||
SOLO = new Solo(instrumentation, trackListActivity);
|
||||
|
||||
if (!isGooglePlayServicesLatest) {
|
||||
SOLO.finishOpenedActivities();
|
||||
Assert.fail();
|
||||
Log.e(TAG, "Need update Google Play Services");
|
||||
}
|
||||
|
||||
// Check if open MyTracks first time after install. If so, there would be a
|
||||
// welcome view with accept buttons. And makes sure only check once.
|
||||
if (!isCheckedFirstLaunch) {
|
||||
isGooglePlayServicesLatest = isGooglePlayServicesLatest();
|
||||
if (!isGooglePlayServicesLatest) {
|
||||
SOLO.finishOpenedActivities();
|
||||
Assert.fail();
|
||||
Log.e(TAG, "Need update Google Play Services");
|
||||
}
|
||||
setIsEmulator();
|
||||
|
||||
verifyFirstLaunch();
|
||||
hasActionBar = setHasActionBar();
|
||||
checkLanguage();
|
||||
isCheckedFirstLaunch = true;
|
||||
|
||||
inst.waitForIdleSync();
|
||||
// Check the status of real phone. For emulator, we would fix GPS signal.
|
||||
if (!isEmulator) {
|
||||
findAndClickMyLocation(activity);
|
||||
hasGpsSignal = !SOLO.waitForText(NO_GPS_MESSAGE_PREFIX, 1, SHORT_WAIT_TIME);
|
||||
SOLO.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
// Delete all tracks when there are two many tracks which may make some test
|
||||
// run slowly, such as sync test cases.
|
||||
if (trackNumber > 3) {
|
||||
deleteAllTracks();
|
||||
}
|
||||
|
||||
// Check whether is under recording. If previous test failed, the recording
|
||||
// may not be recording.
|
||||
if (isUnderRecording()) {
|
||||
stopRecording(true);
|
||||
}
|
||||
|
||||
resetAllSettings(activity, false);
|
||||
inst.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the given activity.
|
||||
*
|
||||
* @param activity a given activity
|
||||
*/
|
||||
private static void rotateActivity(Activity activity) {
|
||||
activity
|
||||
.setRequestedOrientation(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
|
||||
: ORIENTATION_PORTRAIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts terms and configures units.
|
||||
*/
|
||||
private static void verifyFirstLaunch() {
|
||||
if ((getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), false, false) != null)) {
|
||||
getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simple track which can be used by subsequent test. This method
|
||||
* will save a customized track name.
|
||||
*
|
||||
* @param numberOfGpsData number of simulated Gps data
|
||||
* @param showTrackList whether stay on track list activity or track detail
|
||||
* activity
|
||||
*/
|
||||
public static void createSimpleTrack(int numberOfGpsData, boolean showTrackList) {
|
||||
startRecording();
|
||||
sendGps(numberOfGpsData);
|
||||
instrumentation.waitForIdleSync();
|
||||
stopRecording(true);
|
||||
|
||||
if (showTrackList) {
|
||||
SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a track which contains pause during recording.
|
||||
*
|
||||
* @param numberOfGpsData number of simulated Gps data before pause and after
|
||||
* resume
|
||||
*/
|
||||
public static void createTrackWithPause(int numberOfGpsData) {
|
||||
startRecording();
|
||||
sendGps(numberOfGpsData);
|
||||
pauseRecording();
|
||||
resumeRecording();
|
||||
sendGps(numberOfGpsData, numberOfGpsData);
|
||||
stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is no track in track list. For some tests need at least one
|
||||
* track, the method can save time to create a new track.
|
||||
*
|
||||
* @param isClick if not empty, true means click any track
|
||||
* @return return true if the track list is empty
|
||||
*/
|
||||
private static boolean isTrackListEmpty(boolean isClick) {
|
||||
instrumentation.waitForIdleSync();
|
||||
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
if (trackNumber <= 0) {
|
||||
return true;
|
||||
}
|
||||
View oneTrack = SOLO.getCurrentViews(ListView.class).get(0).getChildAt(0);
|
||||
View aa = oneTrack.findViewById(R.id.list_item_name);
|
||||
if (aa != null) {
|
||||
trackName = (String) ((TextView) oneTrack.findViewById(R.id.list_item_name)).getText();
|
||||
}
|
||||
|
||||
if (isClick) {
|
||||
SOLO.scrollUp();
|
||||
SOLO.clickOnView(oneTrack);
|
||||
SOLO.waitForText(trackListActivity.getString(R.string.track_detail_chart_tab));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new track if the track is empty.
|
||||
*
|
||||
* @param gpsNumber the number of gps signals
|
||||
* @param showTrackList whether stay on track list activity or track detail
|
||||
* activity
|
||||
*/
|
||||
public static void createTrackIfEmpty(int gpsNumber, boolean showTrackList) {
|
||||
if (isTrackListEmpty(!showTrackList)) {
|
||||
// Create a simple track.
|
||||
createSimpleTrack(gpsNumber, showTrackList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts recoding track.
|
||||
*/
|
||||
public static void startRecording() {
|
||||
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
|
||||
if (startButton != null && startButton.isShown()) {
|
||||
SOLO.clickOnView(startButton);
|
||||
}
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses recoding track.
|
||||
*/
|
||||
public static void pauseRecording() {
|
||||
View pauseButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
|
||||
if (pauseButton != null && pauseButton.isShown()) {
|
||||
SOLO.clickOnView(pauseButton);
|
||||
}
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume recoding track.
|
||||
*/
|
||||
public static void resumeRecording() {
|
||||
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
|
||||
if (startButton != null && startButton.isShown()) {
|
||||
SOLO.clickOnView(startButton);
|
||||
}
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the MyTracks is under recording.
|
||||
*
|
||||
* @return true if it is under recording.
|
||||
*/
|
||||
private static boolean isUnderRecording() {
|
||||
instrumentation.waitForIdleSync();
|
||||
View view = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
|
||||
// TODO: understand why view can be null here
|
||||
return view != null ? view.isEnabled() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops recoding track.
|
||||
*
|
||||
* @param isSave true means should save this track
|
||||
*/
|
||||
public static void stopRecording(boolean isSave) {
|
||||
View stopButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
|
||||
if (stopButton != null && stopButton.isShown()) {
|
||||
SOLO.clickOnView(stopButton);
|
||||
if (isSave) {
|
||||
SOLO.waitForText(trackListActivity.getString(R.string.generic_save), 1, 5000);
|
||||
// Make every track name is unique to make sure every check can be
|
||||
// trusted.
|
||||
long currentMillis = System.currentTimeMillis();
|
||||
trackName = TRACK_NAME_PREFIX + currentMillis;
|
||||
trackDescription = TRACK_DESCRIPTION_PREFIX + currentMillis;
|
||||
SOLO.sendKey(KeyEvent.KEYCODE_DEL);
|
||||
enterTextAvoidSoftKeyBoard(0, trackName);
|
||||
enterTextAvoidSoftKeyBoard(1, activityType);
|
||||
enterTextAvoidSoftKeyBoard(2, trackDescription);
|
||||
SOLO.clickOnText(trackListActivity.getString(R.string.generic_save));
|
||||
instrumentation.waitForIdleSync();
|
||||
} else {
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all tracks. This method should be call when the TracksListActivity
|
||||
* is shown.
|
||||
*/
|
||||
public static void deleteAllTracks() {
|
||||
if (!isTrackListEmpty(false)) {
|
||||
findMenuItem(trackListActivity.getString(R.string.menu_delete_all), true);
|
||||
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
waitTextToDisappear(trackListActivity.getString(R.string.generic_progress_title));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a button is existed in the screen.
|
||||
*
|
||||
* @param buttonName the name string of the button
|
||||
* @param isWait whether wait the text
|
||||
* @param isClick whether click the button if find it
|
||||
* @return the button to search, and null means can not find the button
|
||||
*/
|
||||
public static View getButtonOnScreen(String buttonName, boolean isWait, boolean isClick) {
|
||||
View button = null;
|
||||
|
||||
instrumentation.waitForIdleSync();
|
||||
if (isWait) {
|
||||
SOLO.waitForText(buttonName);
|
||||
}
|
||||
|
||||
// Find on action bar.
|
||||
if (hasActionBar) {
|
||||
ArrayList<View> allViews = SOLO.getViews();
|
||||
for (View view : allViews) {
|
||||
String className = view.getClass().getName();
|
||||
if (className.indexOf("ActionMenuItemView") > 0) {
|
||||
String menuItemNameString = view.getContentDescription().toString();
|
||||
if (menuItemNameString.equalsIgnoreCase(buttonName)) {
|
||||
button = view;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get all buttons and find.
|
||||
if (button == null) {
|
||||
ArrayList<Button> currentButtons = SOLO.getCurrentViews(Button.class);
|
||||
for (Button oneButton : currentButtons) {
|
||||
String title = (String) oneButton.getText();
|
||||
if (title.equalsIgnoreCase(buttonName)) {
|
||||
button = oneButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (button != null && isClick) {
|
||||
SOLO.clickOnView(button);
|
||||
}
|
||||
|
||||
if (button == null && isClick) {
|
||||
Log.d(TAG, "Don't find the button " + buttonName);
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an action bar is shown.
|
||||
*
|
||||
* @return false means can not check failed.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
private static boolean setHasActionBar() {
|
||||
try {
|
||||
return trackListActivity.getActionBar() == null ? false : true;
|
||||
} catch (Throwable e) {
|
||||
// For in Android which does not has action bar, here will meet a error.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates all activities.
|
||||
*/
|
||||
public static void rotateCurrentActivity() {
|
||||
rotateActivity(SOLO.getCurrentActivity());
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an item in the menu with the option to click the item.
|
||||
*
|
||||
* @param menuName the name of item
|
||||
* @param click true means need click this menu
|
||||
* @return true if find this menu
|
||||
*/
|
||||
public static boolean findMenuItem(String menuName, boolean click) {
|
||||
instrumentation.waitForIdleSync();
|
||||
boolean findResult = false;
|
||||
boolean isMoreMenuOpened = false;
|
||||
|
||||
// ICS phone.
|
||||
if (hasActionBar) {
|
||||
// Firstly find in action bar.
|
||||
View button = getButtonOnScreen(menuName, false, false);
|
||||
if (button != null) {
|
||||
findResult = true;
|
||||
if (click) {
|
||||
SOLO.clickOnView(button);
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
return findResult;
|
||||
}
|
||||
showMenuItem();
|
||||
findResult = SOLO.waitForText(menuName, 1, LONG_WAIT_TIME, true);
|
||||
} else {
|
||||
// Non-ICS phone.
|
||||
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
|
||||
if (SOLO.searchText(menuName, 1, true)) {
|
||||
findResult = true;
|
||||
} else if (getMoreOptionView() != null) {
|
||||
SOLO.clickOnView(getMoreOptionView());
|
||||
findResult = SOLO.searchText(menuName, 1, true);
|
||||
isMoreMenuOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (findResult && click) {
|
||||
SOLO.clickOnView(SOLO.getText(menuName));
|
||||
instrumentation.waitForIdleSync();
|
||||
} else {
|
||||
// Quit more menu list if opened.
|
||||
if (isMoreMenuOpened) {
|
||||
SOLO.goBack();
|
||||
}
|
||||
// Quit menu list.
|
||||
SOLO.goBack();
|
||||
}
|
||||
return findResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show menu item list.
|
||||
*/
|
||||
private static void showMenuItem() {
|
||||
showMenuItem(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets more menu items operation is different for different Android OS. When
|
||||
* get overflow button view on action, it usually be able to click. But in
|
||||
* some situation, will meet an error when click it. So catch it and try
|
||||
* again. In most situation, the second click will be pass.
|
||||
*
|
||||
* @param depth control the depth of recursion to prevent dead circulation
|
||||
*/
|
||||
private static void showMenuItem(int depth) {
|
||||
// ICS phone.
|
||||
if (hasActionBar) {
|
||||
instrumentation.waitForIdleSync();
|
||||
View moreButton = getMoreOptionView();
|
||||
// ICS phone without menu key.
|
||||
if (moreButton != null) {
|
||||
try {
|
||||
SOLO.clickOnView(moreButton);
|
||||
} catch (Throwable e) {
|
||||
if (depth < 5 && e.getMessage().indexOf("Click can not be completed") > -1) {
|
||||
showMenuItem(depth++);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// ICS phone with menu key.
|
||||
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
|
||||
}
|
||||
} else {
|
||||
// Non-ICS phone with menu key.
|
||||
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the more option menu. It should match following conditions:
|
||||
* <ul>
|
||||
* <li>The view extends ImageButton.</li>
|
||||
* <li>The view name equals {@link #MORE_OPTION_CLASSNAME}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return the more option view. Null means can not find it.
|
||||
*/
|
||||
private static View getMoreOptionView() {
|
||||
View viewResult = null;
|
||||
if (hasActionBar) {
|
||||
ArrayList<View> allViews = SOLO.getViews();
|
||||
for (View view : allViews) {
|
||||
if (view instanceof ImageButton && view.getClass().getName().equals(MORE_OPTION_CLASSNAME)) {
|
||||
viewResult = view;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ArrayList<View> allViews = SOLO.getViews();
|
||||
for (View view : allViews) {
|
||||
if (view.getClass().getName().equals(MENUITEM_CLASSNAME)) {
|
||||
viewResult = view;
|
||||
// No break here to get the last menu item.
|
||||
}
|
||||
}
|
||||
}
|
||||
return viewResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a displayed text view with specified text in a view.
|
||||
*
|
||||
* @param text text to find
|
||||
* @param parent which text view in in
|
||||
* @return the text view, null means can not find it
|
||||
*/
|
||||
public static TextView findTextViewInView(String text, View parent) {
|
||||
ArrayList<TextView> textViews = SOLO.getCurrentViews(TextView.class, parent);
|
||||
for (TextView textView : textViews) {
|
||||
String textString = (String) textView.getText();
|
||||
if (textView.isShown() && textString.endsWith(text)) {
|
||||
return textView;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a displayed text view with specified text.
|
||||
*
|
||||
* @param text text to find
|
||||
* @return the text view, null means can not find it
|
||||
*/
|
||||
public static TextView findTextView(String text) {
|
||||
ArrayList<View> allViews = SOLO.getViews();
|
||||
if (allViews != null) {
|
||||
for (View view : allViews) {
|
||||
if (view instanceof TextView) {
|
||||
TextView textView = (TextView) view;
|
||||
String textString = (String) textView.getText();
|
||||
if (textView.isShown() && textString.endsWith(text)) {
|
||||
return textView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a displayed text view with specified text and index number.
|
||||
*
|
||||
* @param text text to find
|
||||
* @param index the index to search
|
||||
* @return the text view, null means can not find it
|
||||
*/
|
||||
public static TextView findTextViewByIndex(String text, int index) {
|
||||
int number = 1;
|
||||
ArrayList<View> allViews = SOLO.getViews();
|
||||
for (View view : allViews) {
|
||||
if (view instanceof TextView) {
|
||||
TextView textView = (TextView) view;
|
||||
String textString = (String) textView.getText();
|
||||
if (textView.isShown() && textString.endsWith(text)) {
|
||||
if (number == index) {
|
||||
return textView;
|
||||
} else {
|
||||
number++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all settings of MyTracks.
|
||||
*
|
||||
* @param activityMyTracks current activity
|
||||
* @param keepInSettingList whether keep in setting list or not
|
||||
*/
|
||||
public static void resetAllSettings(Activity activityMyTracks, boolean keepInSettingList) {
|
||||
findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
|
||||
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_advanced));
|
||||
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset)));
|
||||
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_reset));
|
||||
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset_done)));
|
||||
instrumentation.waitForIdleSync();
|
||||
SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
if (!keepInSettingList) {
|
||||
SOLO.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a edit text and enter text in it. This method can hides soft key
|
||||
* board when input text.
|
||||
*
|
||||
* @param editTextIndex the index of edit text
|
||||
* @param text to enter
|
||||
*/
|
||||
public static void enterTextAvoidSoftKeyBoard(int editTextIndex, String text) {
|
||||
EditText editText = SOLO.getEditText(editTextIndex);
|
||||
SOLO.enterText(editText, text);
|
||||
SOLO.hideSoftKeyboard();
|
||||
|
||||
// Above line does not work every time. And it is should be a Robotium
|
||||
// issue.
|
||||
InputMethodManager imm = (InputMethodManager) trackListActivity.getApplicationContext()
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(editText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits n milliseconds.
|
||||
*
|
||||
* @param milliseconds time to sleep
|
||||
*/
|
||||
public static void sleep(long milliseconds) {
|
||||
try {
|
||||
Thread.sleep(milliseconds);
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Unable to sleep " + milliseconds, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the recording is not started.
|
||||
*/
|
||||
public static void checkNotRecording() {
|
||||
instrumentation.waitForIdleSync();
|
||||
Assert.assertEquals(trackListActivity.getString(R.string.image_record),
|
||||
(String) SOLO.getCurrentActivity()
|
||||
.findViewById(R.id.track_controller_record).getContentDescription());
|
||||
Assert.assertFalse(
|
||||
SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop).isEnabled());
|
||||
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
|
||||
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
|
||||
Assert.assertFalse(
|
||||
SOLO.getCurrentActivity().findViewById(R.id.track_controller_total_time).isShown());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the MyTracks is under recording.
|
||||
*/
|
||||
public static void checkUnderRecording() {
|
||||
instrumentation.waitForIdleSync();
|
||||
Assert.assertEquals(trackListActivity.getString(R.string.image_pause), (String) SOLO
|
||||
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
|
||||
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
|
||||
.isEnabled());
|
||||
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
|
||||
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
|
||||
|
||||
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
|
||||
R.id.track_controller_total_time)).getText().toString();
|
||||
sleep(2000);
|
||||
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
|
||||
R.id.track_controller_total_time)).getText().toString();
|
||||
Assert.assertFalse(totalTimeOld.equalsIgnoreCase(totalTimeNew));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the recording is paused.
|
||||
*/
|
||||
public static void checkUnderPaused() {
|
||||
instrumentation.waitForIdleSync();
|
||||
Assert.assertEquals(trackListActivity.getString(R.string.image_record), (String) SOLO
|
||||
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
|
||||
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
|
||||
.isEnabled());
|
||||
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
|
||||
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
|
||||
|
||||
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
|
||||
R.id.track_controller_total_time)).getText().toString();
|
||||
sleep(2000);
|
||||
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
|
||||
R.id.track_controller_total_time)).getText().toString();
|
||||
Assert.assertTrue(totalTimeOld.equalsIgnoreCase(totalTimeNew));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a way point during track recording.
|
||||
*
|
||||
* @param markerNumber of number of previous markers
|
||||
*/
|
||||
public static void createWaypoint(int markerNumber) {
|
||||
findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
|
||||
instrumentation.waitForIdleSync();
|
||||
if (markerNumber > 0 && hasGpsSignal) {
|
||||
SOLO.waitForText(WAYPOINT_NAME);
|
||||
int actualMarkerNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
Assert.assertEquals(markerNumber, actualMarkerNumber);
|
||||
} else {
|
||||
Log.d(TAG, "marker number, hasGpsSignal: " + markerNumber + ", " + hasGpsSignal);
|
||||
Assert.assertTrue(SOLO.waitForText(trackListActivity
|
||||
.getString(R.string.marker_list_empty_message)));
|
||||
}
|
||||
findMenuItem(trackListActivity.getString(R.string.menu_insert_marker), true);
|
||||
enterTextAvoidSoftKeyBoard(0, WAYPOINT_NAME + (markerNumber + 1));
|
||||
enterTextAvoidSoftKeyBoard(1, WAYPOINT_TYPE + (markerNumber + 1));
|
||||
enterTextAvoidSoftKeyBoard(2, WAYPOINT_DESCRIPTION + (markerNumber + 1));
|
||||
SOLO.clickOnButton(trackListActivity.getString(R.string.generic_add));
|
||||
instrumentation.waitForIdleSync();
|
||||
if (hasGpsSignal) {
|
||||
Assert.assertTrue(SOLO.waitForText(WAYPOINT_NAME, 1, LONG_WAIT_TIME, true));
|
||||
} else {
|
||||
Assert.assertFalse(SOLO.searchText(WAYPOINT_NAME));
|
||||
}
|
||||
SOLO.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits a text to disappear.
|
||||
*/
|
||||
public static void waitTextToDisappear(String text) {
|
||||
instrumentation.waitForIdleSync();
|
||||
SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME);
|
||||
while (SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME)) {}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the My Location view and click it.
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private static void findAndClickMyLocation(Activity activity) {
|
||||
createTrackIfEmpty(1, false);
|
||||
sendGps(30);
|
||||
|
||||
View myLocation = SOLO.getCurrentActivity().findViewById(R.id.map_my_location);
|
||||
instrumentation.waitForIdleSync();
|
||||
// Find the My Location button in another if null.
|
||||
if (myLocation == null) {
|
||||
ArrayList<ImageButton> aa = SOLO.getCurrentViews(ImageButton.class);
|
||||
for (ImageButton imageButton : aa) {
|
||||
if (imageButton.getContentDescription() != null
|
||||
&& imageButton.getContentDescription().equals(
|
||||
activity.getString(R.string.image_my_location))) {
|
||||
myLocation = imageButton;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SOLO.clickOnView(myLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative start time suffix.
|
||||
*/
|
||||
public static String getRelativeStartTimeSuffix() {
|
||||
String value = RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get(language);
|
||||
return value != null ? value : RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get("en");
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes to metric units.
|
||||
*/
|
||||
public static void changeToMetricUnits() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_stats_tab));
|
||||
Assert.assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.settings_stats_units_title)));
|
||||
|
||||
// Change the preferred units
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_stats_units_title));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.unit_kilometer));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
}
|
||||
}
|
||||
+398
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapFeatureEntry;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsClient;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsMapMetadata;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.XmlMapsGDataParserFactory;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsAsyncTask;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
import com.google.android.common.gdata.AndroidXmlParserFactory;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.client.auth.oauth2.BearerToken;
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.extensions.android.http.AndroidHttp;
|
||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import com.google.api.services.drive.model.File;
|
||||
import com.google.api.services.fusiontables.Fusiontables;
|
||||
import com.google.api.services.fusiontables.model.Table;
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.data.spreadsheet.ListEntry;
|
||||
import com.google.gdata.data.spreadsheet.ListFeed;
|
||||
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
||||
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
||||
import com.google.wireless.gdata.parser.GDataParser;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Utilities for accessing Google Drive, Google Maps, Google Fusion Tables, and
|
||||
* Google Spreadsheets.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class GoogleUtils {
|
||||
|
||||
public static final String ACCOUNT_1 = "mytrackstest@gmail.com";
|
||||
public static final String ACCOUNT_2 = "mytrackstest2@gmail.com";
|
||||
|
||||
private static final String TAG = GoogleUtils.class.getSimpleName();
|
||||
private static final String MY_TRACKS_PREFIX = "My Tracks";
|
||||
private static final String SPREADSHEETS_NAME = MY_TRACKS_PREFIX + "-"
|
||||
+ EndToEndTestUtils.activityType;
|
||||
private static final String SPREADSHEETS_WORKSHEET_NAME = "Log";
|
||||
private static final String SPREADSHEETS_TRANCK_NAME_COLUMN = "Name";
|
||||
private static final String DRIVE_TEST_FILES_QUERY = "'root' in parents and title contains '"
|
||||
+ EndToEndTestUtils.TRACK_NAME_PREFIX + "' and trashed = false";
|
||||
|
||||
/**
|
||||
* Deletes Google Drive test files.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
*/
|
||||
public static void deleteDriveTestFiles(Context context, String accountName) {
|
||||
try {
|
||||
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
|
||||
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
|
||||
if (googleAccountCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
|
||||
com.google.api.services.drive.Drive.Files.List list = drive.files()
|
||||
.list().setQ(DRIVE_TEST_FILES_QUERY);
|
||||
List<File> files = list.execute().getItems();
|
||||
Iterator<File> iterator = files.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
File file = (File) iterator.next();
|
||||
drive.files().delete(file.getId()).execute();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to delete Google Drive test files.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Google Maps of the first Google account.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
* @param mapTitle the map title
|
||||
* @return true if deletion is success.
|
||||
*/
|
||||
public static boolean deleteMaps(Context context, String accountName, String mapTitle) {
|
||||
Account account = getGoogleAccount(context, accountName);
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
MapsClient mapsClient = new MapsClient(GDataClientFactory.getGDataClient(context),
|
||||
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
|
||||
ArrayList<MapsMapMetadata> mapMetadata = getMaps(context, account, mapsClient);
|
||||
for (MapsMapMetadata data : mapMetadata) {
|
||||
if (data.getDescription().indexOf(MY_TRACKS_PREFIX) > -1
|
||||
&& data.getTitle().equals(mapTitle)) {
|
||||
try {
|
||||
mapsClient.deleteEntry(data.getGDataEditUri(), AccountManager.get(context)
|
||||
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to delete maps.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all Google Maps of the first Google account
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
*/
|
||||
public static void deleteAllMaps(Context context, String accountName) {
|
||||
Account account = getGoogleAccount(context, accountName);
|
||||
if (account == null) {
|
||||
Log.e(TAG, "Unable to get account.");
|
||||
return;
|
||||
}
|
||||
MapsClient mapsClient = new MapsClient(GDataClientFactory.getGDataClient(context),
|
||||
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
|
||||
ArrayList<MapsMapMetadata> mapMetadata = getMaps(context, account, mapsClient);
|
||||
for (MapsMapMetadata oneData : mapMetadata) {
|
||||
try {
|
||||
mapsClient.deleteEntry(oneData.getGDataEditUri(), AccountManager.get(context)
|
||||
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false));
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to delete maps.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Google Fusion Tables.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
* @param tableName the table name
|
||||
* @return true if deletion is success.
|
||||
*/
|
||||
public static boolean deleteFusionTables(Context context, String accountName, String tableName) {
|
||||
try {
|
||||
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
|
||||
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.FUSION_TABLES_SCOPE);
|
||||
if (googleAccountCredential == null) {
|
||||
return false;
|
||||
}
|
||||
Fusiontables fusiontables = new Fusiontables.Builder(
|
||||
AndroidHttp.newCompatibleTransport(), new GsonFactory(), googleAccountCredential).build();
|
||||
List<Table> tables = fusiontables.table().list().execute().getItems();
|
||||
Iterator<Table> iterator = tables.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Table table = (Table) iterator.next();
|
||||
String name = table.getName();
|
||||
if (name != null && name.equals(tableName)) {
|
||||
fusiontables.table().delete(table.getTableId()).execute();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to search fusion tables.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches Google Spreadsheets.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
* @return the list of spreadsheets matching the title. Null if unable to
|
||||
* search.
|
||||
*/
|
||||
public static List<File> searchSpreadsheets(Context context, String accountName) {
|
||||
try {
|
||||
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
|
||||
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
|
||||
if (googleAccountCredential == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
|
||||
com.google.api.services.drive.Drive.Files.List list = drive.files().list().setQ(String.format(
|
||||
Locale.US, SendSpreadsheetsAsyncTask.GET_SPREADSHEET_QUERY, SPREADSHEETS_NAME));
|
||||
return list.execute().getItems();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to search spreadsheets.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Google Spreadsheets.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
* @return true if deletion is success.
|
||||
*/
|
||||
public static boolean deleteSpreadsheets(Context context, String accountName) {
|
||||
try {
|
||||
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
|
||||
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
|
||||
if (googleAccountCredential == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
|
||||
com.google.api.services.drive.Drive.Files.List list = drive.files().list().setQ(String.format(
|
||||
Locale.US, SendSpreadsheetsAsyncTask.GET_SPREADSHEET_QUERY, SPREADSHEETS_NAME));
|
||||
List<File> files = list.execute().getItems();
|
||||
Iterator<File> iterator = files.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
File file = (File) iterator.next();
|
||||
drive.files().delete(file.getId()).execute();
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to delete spreadsheets.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Google Spreadsheets row.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
* @param trackName the track name
|
||||
* @return true if deletion is success.
|
||||
*/
|
||||
public static boolean deleteSpreadsheetsRow(
|
||||
Context context, String accountName, String trackName) {
|
||||
try {
|
||||
// Get spreadsheet Id
|
||||
List<File> files = searchSpreadsheets(context, accountName);
|
||||
if (files == null || files.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
String spreadsheetId = files.get(0).getId();
|
||||
|
||||
// Get spreadsheet service
|
||||
SpreadsheetService spreadsheetService = new SpreadsheetService(
|
||||
"MyTracks-" + SystemUtils.getMyTracksVersion(context));
|
||||
Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod());
|
||||
credential.setAccessToken(
|
||||
SendToGoogleUtils.getToken(context, accountName, SendToGoogleUtils.SPREADSHEETS_SCOPE));
|
||||
spreadsheetService.setOAuth2Credentials(credential);
|
||||
|
||||
// Get work sheet
|
||||
WorksheetFeed worksheetFeed = spreadsheetService.getFeed(new URL(
|
||||
String.format(Locale.US, SendSpreadsheetsAsyncTask.GET_WORKSHEETS_URI, spreadsheetId)),
|
||||
WorksheetFeed.class);
|
||||
Iterator<WorksheetEntry> worksheetEntryIterator = worksheetFeed.getEntries().iterator();
|
||||
while (worksheetEntryIterator.hasNext()) {
|
||||
WorksheetEntry worksheetEntry = (WorksheetEntry) worksheetEntryIterator.next();
|
||||
String worksheetTitle = worksheetEntry.getTitle().getPlainText();
|
||||
if (worksheetTitle.equals(SPREADSHEETS_WORKSHEET_NAME)) {
|
||||
URL url = worksheetEntry.getListFeedUrl();
|
||||
Iterator<ListEntry> listEntryIterator = spreadsheetService.getFeed(url, ListFeed.class)
|
||||
.getEntries().iterator();
|
||||
while (listEntryIterator.hasNext()) {
|
||||
ListEntry listEntry = (ListEntry) listEntryIterator.next();
|
||||
String name = listEntry.getCustomElements().getValue(SPREADSHEETS_TRANCK_NAME_COLUMN);
|
||||
if (name.equals(trackName)) {
|
||||
listEntry.delete();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to delete spreadsheets row.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an account is available.
|
||||
*/
|
||||
public static boolean isAccountAvailable() {
|
||||
// Check the no account dialog
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_no_account_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), false, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the choose account dialog
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_choose_account_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
EndToEndTestUtils.SOLO.clickOnText(ACCOUNT_1);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), false, true);
|
||||
}
|
||||
|
||||
// Check the no account permission dialog
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_no_account_permission), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the google account.
|
||||
*
|
||||
* @param context the context
|
||||
* @param accountName the account name
|
||||
*/
|
||||
private static Account getGoogleAccount(Context context, String accountName) {
|
||||
Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
for (Account account : accounts) {
|
||||
if (account.name.equals(accountName)) {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Google Maps.
|
||||
*
|
||||
* @param context the context
|
||||
* @param account the account
|
||||
* @param mapsClient the map client
|
||||
* @return a list of maps.
|
||||
*/
|
||||
private static ArrayList<MapsMapMetadata> getMaps(
|
||||
Context context, Account account, MapsClient mapsClient) {
|
||||
String authToken = null;
|
||||
ArrayList<String> mapIds = new ArrayList<String>();
|
||||
ArrayList<MapsMapMetadata> mapMetadata = new ArrayList<MapsMapMetadata>();
|
||||
|
||||
try {
|
||||
authToken = AccountManager.get(context)
|
||||
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to get auth token.", e);
|
||||
return mapMetadata;
|
||||
}
|
||||
|
||||
GDataParser gDataParser = null;
|
||||
try {
|
||||
gDataParser = mapsClient.getParserForFeed(
|
||||
MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken);
|
||||
gDataParser.init();
|
||||
while (gDataParser.hasMoreData()) {
|
||||
MapFeatureEntry entry = (MapFeatureEntry) gDataParser.readNextEntry(null);
|
||||
mapIds.add(MapsGDataConverter.getMapidForEntry(entry));
|
||||
mapMetadata.add(MapsGDataConverter.getMapMetadataForEntry(entry));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to get maps.", e);
|
||||
} finally {
|
||||
if (gDataParser != null) {
|
||||
gDataParser.close();
|
||||
}
|
||||
}
|
||||
return mapMetadata;
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2013 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;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
/**
|
||||
* Run configuration for various tests.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class RunConfiguration {
|
||||
|
||||
private static RunConfiguration instance;
|
||||
|
||||
/**
|
||||
* Gets an instance of {@link RunConfiguration}.
|
||||
*/
|
||||
public static RunConfiguration getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new RunConfiguration();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set to false as default. True to run the test. Default to false since these
|
||||
* tests can take a long time.
|
||||
*/
|
||||
private boolean runResourceTest = false;
|
||||
private boolean runSensorTest = false;
|
||||
private boolean runStressTest = false;
|
||||
private boolean runSyncTest = false;
|
||||
|
||||
private RunConfiguration() {
|
||||
// Sets run sync test in run-time
|
||||
setRunSyncTest(canRunSyncTest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to run the resource test.
|
||||
*/
|
||||
public boolean getRunResourceTest() {
|
||||
return runResourceTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets run resource test.
|
||||
*
|
||||
* @param run true to run
|
||||
*/
|
||||
public void setRunResourceTest(boolean run) {
|
||||
runResourceTest = run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to run the sensor test.
|
||||
*/
|
||||
public boolean getRunSensorTest() {
|
||||
return runSensorTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets run sensor test.
|
||||
*
|
||||
* @param run true to run
|
||||
*/
|
||||
public void setRunSensorTest(boolean run) {
|
||||
runSensorTest = run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to run the stress test.
|
||||
*/
|
||||
public boolean getRunStressTest() {
|
||||
return runStressTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets run stress test.
|
||||
*
|
||||
* @param run true to run
|
||||
*/
|
||||
public void setRunStressTest(boolean run) {
|
||||
runStressTest = run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to run the sync test.
|
||||
*/
|
||||
public boolean getRunSyncTest() {
|
||||
return runSyncTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets run sync test.
|
||||
*
|
||||
* @param run true to run
|
||||
*/
|
||||
public void setRunSyncTest(boolean run) {
|
||||
runSyncTest = run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if can run the sync test. Needs two specific test accounts on
|
||||
* the device.
|
||||
*/
|
||||
private boolean canRunSyncTest() {
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_drive), true);
|
||||
boolean canRun = EndToEndTestUtils.SOLO.waitForText(
|
||||
GoogleUtils.ACCOUNT_1, 1, EndToEndTestUtils.SHORT_WAIT_TIME)
|
||||
&& EndToEndTestUtils.SOLO.waitForText(
|
||||
GoogleUtils.ACCOUNT_2, 1, EndToEndTestUtils.TINY_WAIT_TIME);
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.generic_cancel));
|
||||
return canRun;
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* Tests creating new tracks.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class CreateTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public CreateTrackTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
|
||||
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a new track and checks the relative time in
|
||||
* {@link TrackListActivity}.
|
||||
*/
|
||||
public void testNewTrack() {
|
||||
// Start a recording
|
||||
EndToEndTestUtils.startRecording();
|
||||
checkRecording();
|
||||
|
||||
// Stop the recording
|
||||
EndToEndTestUtils.stopRecording(false);
|
||||
|
||||
// Save the track
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_save), true, true);
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Go back to the TrackListActivity
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Make sure "mins ago" is displayed
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
EndToEndTestUtils.getRelativeStartTimeSuffix(), 1, false, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a new track with two markers.
|
||||
*/
|
||||
public void testNewTrackWithMarker() {
|
||||
// Start a recording
|
||||
EndToEndTestUtils.startRecording();
|
||||
checkRecording();
|
||||
|
||||
// Create a marker
|
||||
EndToEndTestUtils.sendGps(2);
|
||||
EndToEndTestUtils.createWaypoint(0);
|
||||
|
||||
// Send more gps points
|
||||
EndToEndTestUtils.sendGps(2, 2);
|
||||
EndToEndTestUtils.createWaypoint(1);
|
||||
|
||||
// Go back to the TrackListActivity
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Rotate the phone
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
|
||||
// Stop the recording
|
||||
EndToEndTestUtils.stopRecording(false);
|
||||
|
||||
// Update edit page and save
|
||||
String trackName = EndToEndTestUtils.TRACK_NAME_PREFIX + System.currentTimeMillis();
|
||||
EndToEndTestUtils.SOLO.enterText(0, trackName);
|
||||
EndToEndTestUtils.SOLO.enterText(1, EndToEndTestUtils.activityType);
|
||||
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Check the track name in the TrackListActivity
|
||||
EndToEndTestUtils.SOLO.scrollUp();
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackName, 1, EndToEndTestUtils.NORMAL_WAIT_TIME, true, false));
|
||||
|
||||
// Go to the TrackDetailActivity
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackName);
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Go to Markers
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Make sure there are two markers
|
||||
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() == 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests creating a new track with split markers.
|
||||
*/
|
||||
public void testNewTrackWithSplit() {
|
||||
EndToEndTestUtils.changeToMetricUnits();
|
||||
|
||||
EndToEndTestUtils.startRecording();
|
||||
checkRecording();
|
||||
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_split_frequency), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.unit_kilometer), 0);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_ok), true, true);
|
||||
|
||||
// Send gps to give a distance more than one kilometer
|
||||
EndToEndTestUtils.sendGps(50);
|
||||
assertTrue(
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true));
|
||||
instrumentation.waitForIdleSync();
|
||||
if (EndToEndTestUtils.isEmulator) {
|
||||
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() > 0);
|
||||
}
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks recording.
|
||||
*/
|
||||
private void checkRecording() {
|
||||
if (EndToEndTestUtils.hasActionBar) {
|
||||
// Check the title is Recording...
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
trackListActivity.getString(R.string.generic_recording)));
|
||||
}
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* Tests delete tracks.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class DeleteTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public DeleteTest() {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all tracks.
|
||||
*/
|
||||
public void testDeleteAllTracks() {
|
||||
EndToEndTestUtils.createSimpleTrack(1, true);
|
||||
|
||||
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() > 0);
|
||||
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete_all), true);
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
EndToEndTestUtils.waitTextToDisappear(
|
||||
trackListActivity.getString(R.string.generic_progress_title));
|
||||
instrumentation.waitForIdleSync();
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.track_list_empty_message)));
|
||||
assertEquals(0, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes one track.
|
||||
*/
|
||||
public void testDeleteOneTrack() {
|
||||
EndToEndTestUtils.createSimpleTrack(1, true);
|
||||
|
||||
ListView listView = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0);
|
||||
int trackCount = listView.getCount();
|
||||
assertTrue(trackCount > 0);
|
||||
|
||||
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(0));
|
||||
EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.track_detail_chart_tab));
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
EndToEndTestUtils.waitTextToDisappear(
|
||||
trackListActivity.getString(R.string.generic_progress_title));
|
||||
assertEquals(
|
||||
trackCount - 1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes multiple tracks in {@link TrackListActivity}.
|
||||
*/
|
||||
public void testDeleteMultiple() {
|
||||
if (!EndToEndTestUtils.hasActionBar) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create 3 tracks
|
||||
for (int i = 0; i < 3; i++) {
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
}
|
||||
|
||||
ListView listView = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0);
|
||||
int trackCount = listView.getCount();
|
||||
assertTrue(trackCount > 2);
|
||||
|
||||
// Select 3 tracks
|
||||
EndToEndTestUtils.SOLO.clickLongOnView(listView.getChildAt(0));
|
||||
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(1));
|
||||
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(2));
|
||||
|
||||
// Deselect the first one
|
||||
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(0));
|
||||
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
EndToEndTestUtils.waitTextToDisappear(
|
||||
trackListActivity.getString(R.string.generic_progress_title));
|
||||
assertEquals(
|
||||
trackCount - 2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a recording track.
|
||||
*/
|
||||
public void testDeleteRecordingTrack() {
|
||||
EndToEndTestUtils.startRecording();
|
||||
EndToEndTestUtils.checkUnderRecording();
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_yes), true, true);
|
||||
EndToEndTestUtils.waitTextToDisappear(
|
||||
trackListActivity.getString(R.string.generic_progress_title));
|
||||
EndToEndTestUtils.checkNotRecording();
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
* Tests editing a track.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class EditTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public EditTrackTest() {
|
||||
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 editing a track.
|
||||
*/
|
||||
public void testEditTrack() {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
|
||||
EndToEndTestUtils.createSimpleTrack(1, false);
|
||||
|
||||
// Click on the Edit menu item
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
|
||||
|
||||
// Rotate phone
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_save));
|
||||
|
||||
String newName = EndToEndTestUtils.TRACK_NAME_PREFIX + "_new" + System.currentTimeMillis();
|
||||
String newActivityType = EndToEndTestUtils.activityType;
|
||||
String newDescription = "new_description_" + newName;
|
||||
|
||||
// Clear name field
|
||||
sendKeys(KeyEvent.KEYCODE_DEL);
|
||||
// Enter new name
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, newName);
|
||||
|
||||
// Enter new activity type
|
||||
EndToEndTestUtils.SOLO.clearEditText(1);
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(1, newActivityType);
|
||||
|
||||
// Enter new description
|
||||
EndToEndTestUtils.SOLO.clearEditText(2);
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(2, newDescription);
|
||||
|
||||
// Change activity type using the activity picker
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(newActivityType));
|
||||
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentActivity()
|
||||
.findViewById(R.id.track_edit_activity_type_icon));
|
||||
EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.track_edit_activity_type_hint));
|
||||
int walkingActivityTypeIndex = 1;
|
||||
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getImage(walkingActivityTypeIndex));
|
||||
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_ok));
|
||||
|
||||
// The activity type should be replaced by the walking activity type
|
||||
assertFalse(EndToEndTestUtils.SOLO.searchText(newActivityType));
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
trackListActivity.getString(R.string.activity_type_walking)));
|
||||
|
||||
// Save
|
||||
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Go back to the TrackListActivity
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(newName));
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(newDescription));
|
||||
}
|
||||
}
|
||||
+637
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.services.drive.model.File;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests export single track to Google. Each test would export one track to
|
||||
* Google Maps, Google Fusion Tables and Google Spreadsheets.
|
||||
*
|
||||
* @author youtaol
|
||||
*/
|
||||
public class ExportSingleTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity activityMyTracks;
|
||||
|
||||
public ExportSingleTrackTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
activityMyTracks = getActivity();
|
||||
|
||||
GoogleUtils.deleteAllMaps(activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
|
||||
GoogleUtils.deleteDriveTestFiles(
|
||||
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all services and send to google.
|
||||
*/
|
||||
public void testCreateAndSendTrack_send() {
|
||||
// Create a new track.
|
||||
EndToEndTestUtils.createSimpleTrack(1, false);
|
||||
instrumentation.waitForIdleSync();
|
||||
checkSendTrackToGoogle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all services and send to google.
|
||||
*/
|
||||
public void testCreateAndSendTrack_sendPausedTrack() {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
EndToEndTestUtils.createTrackWithPause(3);
|
||||
instrumentation.waitForIdleSync();
|
||||
checkSendTrackToGoogle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends two tracks with same activity. Two tracks should be in the same
|
||||
* spreadsheet.
|
||||
*/
|
||||
public void testSendTwoTracksWithSameActivity() {
|
||||
String testActivity = "(TestActivity)";
|
||||
EndToEndTestUtils.activityType = testActivity;
|
||||
GoogleUtils.deleteSpreadsheets(
|
||||
EndToEndTestUtils.trackListActivity.getApplicationContext(), GoogleUtils.ACCOUNT_1);
|
||||
EndToEndTestUtils.createSimpleTrack(1, false);
|
||||
boolean result = sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
|
||||
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
|
||||
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets));
|
||||
result = result && sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
|
||||
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
|
||||
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets));
|
||||
|
||||
// Result is true mean has account bound with this device and send
|
||||
// successful.
|
||||
if (result) {
|
||||
List<File> fileList = GoogleUtils.searchSpreadsheets(
|
||||
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
|
||||
assertEquals(1, fileList.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the process of sending track to google.
|
||||
*/
|
||||
private void checkSendTrackToGoogle() {
|
||||
if (!sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
|
||||
|| !sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
|
||||
|| !sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets))) {
|
||||
return;
|
||||
}
|
||||
// Check whether all data is correct on Google Drive, Maps, Documents, and
|
||||
// Spreadsheet.
|
||||
// assertTrue(SyncTestUtils.checkFile(EndToEndTestUtils.trackName, true,
|
||||
// SyncTestUtils.getGoogleDrive(activityMyTracks.getApplicationContext())));
|
||||
assertTrue(GoogleUtils.deleteMaps(
|
||||
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
|
||||
EndToEndTestUtils.trackName));
|
||||
assertTrue(GoogleUtils.deleteFusionTables(
|
||||
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
|
||||
EndToEndTestUtils.trackName));
|
||||
assertTrue(GoogleUtils.deleteSpreadsheetsRow(
|
||||
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
|
||||
EndToEndTestUtils.trackName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a track to Google.
|
||||
*
|
||||
* @param exportDestination destination to export
|
||||
* @return true means send successfully
|
||||
*/
|
||||
private boolean sendToGoogle(String exportDestination) {
|
||||
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_export), true);
|
||||
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.export_title));
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
EndToEndTestUtils.SOLO.clickOnText(exportDestination);
|
||||
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.getButtonOnScreen(activityMyTracks.getString(R.string.menu_export), true,
|
||||
true);
|
||||
|
||||
instrumentation.waitForIdleSync();
|
||||
if (!GoogleUtils.isAccountAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Following check the process of "Send to Google", the second condition is
|
||||
// in case the export has done.
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.generic_progress_title))
|
||||
|| EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.generic_success_title)));
|
||||
|
||||
// Waiting the send is finish. Should double check it for the progress
|
||||
// dialog may disappear and display again while switch to next send(There
|
||||
// are four sends currently, there are send to drive, maps, fusion table and
|
||||
// spreadsheet).
|
||||
while (EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.generic_progress_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)
|
||||
|| EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.generic_progress_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {}
|
||||
|
||||
if (exportDestination.endsWith(activityMyTracks.getString(R.string.export_google_maps))) {
|
||||
// Check whether the result dialog is display.
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.share_track_share_url)));
|
||||
} else {
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.generic_success_title)));
|
||||
}
|
||||
EndToEndTestUtils
|
||||
.getButtonOnScreen(activityMyTracks.getString(R.string.generic_ok), true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a large track to Google.
|
||||
*/
|
||||
public void testSendLargeTrackToGoogle() {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
EndToEndTestUtils.createSimpleTrack(200, false);
|
||||
instrumentation.waitForIdleSync();
|
||||
checkSendTrackToGoogle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
EndToEndTestUtils.activityType = EndToEndTestUtils.DEFAULT_ACTIVITY_TYPE;
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Tests menu items.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public MenuItemsTest() {
|
||||
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 following More menu items.
|
||||
* <ul>
|
||||
* <li>Aggregated statistics in {@link TrackListActivity}</li>
|
||||
* <li>Help & feedback in {@link TrackListActivity}</li>
|
||||
* <li>Help & feedback in {@link TrackDetailActivity}</li>
|
||||
* <li>Export in {@link TrackDetailActivity}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void testMoreMenuItems() {
|
||||
// Aggregated statistics in TrackListActivity
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_aggregated_statistics), true);
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_distance));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Help & feedback in TrackListActivity
|
||||
checkHelpFeedbackPage();
|
||||
|
||||
EndToEndTestUtils.createSimpleTrack(1, false);
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Help & feedback in TrackDetailActivity
|
||||
checkHelpFeedbackPage();
|
||||
|
||||
// Export in TrackDetailActivity
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_export), true);
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.export_title));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the search menu. When search is displayed, the track controller
|
||||
* should be hidden.
|
||||
*/
|
||||
public void testSearchMenu() {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
assertTrue(isTrackControllerShown());
|
||||
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_search), true);
|
||||
assertFalse(isTrackControllerShown());
|
||||
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, EndToEndTestUtils.trackName);
|
||||
sendKeys(KeyEvent.KEYCODE_ENTER);
|
||||
instrumentation.waitForIdleSync();
|
||||
assertEquals(1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
|
||||
// TODO: not sure why the following fails. It passes in debug mode.
|
||||
// assertFalse(isTrackControllerShown());
|
||||
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
assertTrue(isTrackControllerShown());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the voice frequency and the split frequency menu. When recording,
|
||||
* they should be in both the {@link TrackDetailActivity} menu and the
|
||||
* recording settings. When not recording, they should only be in the
|
||||
* recording settings.
|
||||
*/
|
||||
public void testFrequencyMenu() {
|
||||
EndToEndTestUtils.startRecording();
|
||||
|
||||
assertTrue(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_voice_frequency), false));
|
||||
assertTrue(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_split_frequency), false));
|
||||
|
||||
checkFrequencyInSettings();
|
||||
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
|
||||
assertFalse(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_voice_frequency), false));
|
||||
assertFalse(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_split_frequency), false));
|
||||
|
||||
checkFrequencyInSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests start and stop gps.
|
||||
*/
|
||||
public void testGpsMenu() {
|
||||
// Start gps
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_start_gps), true);
|
||||
EndToEndTestUtils.waitTextToDisappear(trackListActivity.getString(R.string.menu_start_gps));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_stop_gps), false));
|
||||
|
||||
// Stop gps
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_stop_gps), true);
|
||||
EndToEndTestUtils.waitTextToDisappear(trackListActivity.getString(R.string.menu_stop_gps));
|
||||
assertTrue(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_start_gps), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the help & feedback page.
|
||||
*/
|
||||
private void checkHelpFeedbackPage() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_help_feedback), true);
|
||||
assertNotNull(EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.menu_feedback).toUpperCase(Locale.getDefault()), true,
|
||||
false));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the track controller is shown.
|
||||
*/
|
||||
private boolean isTrackControllerShown() {
|
||||
return trackListActivity.findViewById(R.id.track_controler_container).isShown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the frequency options exists in settings.
|
||||
*/
|
||||
private void checkFrequencyInSettings() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_recording));
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
trackListActivity.getString(R.string.menu_voice_frequency), 1, true, true));
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
trackListActivity.getString(R.string.menu_split_frequency), 1, true, true));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Tests the my location button.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MyLocationTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public MyLocationTest() {
|
||||
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 the my location button.
|
||||
*/
|
||||
public void testMyLocation() {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
EndToEndTestUtils.createSimpleTrack(1, false);
|
||||
View myLocation = EndToEndTestUtils.SOLO.getCurrentActivity()
|
||||
.findViewById(R.id.map_my_location);
|
||||
EndToEndTestUtils.SOLO.clickOnView(myLocation);
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
if (EndToEndTestUtils.isEmulator) {
|
||||
EndToEndTestUtils.SOLO.waitForText(
|
||||
GoogleLocationUtils.getGpsDisabledMyLocationMessage(trackListActivity), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME);
|
||||
} else {
|
||||
// TODO How to verify my location is shown on the map?
|
||||
}
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingService;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.location.Location;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
|
||||
/**
|
||||
* Tests pause and resume during a recording.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class PauseResumeTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private static final int SEND_INTERVAL = 100; // ms
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public PauseResumeTest() {
|
||||
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 stop after a pause.
|
||||
*/
|
||||
public void testStopAfterPause() {
|
||||
int firstBatch = 3;
|
||||
int secondBatch = 10;
|
||||
|
||||
EndToEndTestUtils.checkNotRecording();
|
||||
|
||||
// Start a recording
|
||||
EndToEndTestUtils.startRecording();
|
||||
EndToEndTestUtils.checkUnderRecording();
|
||||
EndToEndTestUtils.sendGps(firstBatch);
|
||||
|
||||
// Pause the recording
|
||||
EndToEndTestUtils.pauseRecording();
|
||||
EndToEndTestUtils.checkUnderPaused();
|
||||
EndToEndTestUtils.sendGps(secondBatch, firstBatch);
|
||||
|
||||
// Stop the recording
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
checkTrackLocation(firstBatch, 1, 0);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.checkNotRecording();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests stop after a resume.
|
||||
*/
|
||||
public void testStopAfterResume() {
|
||||
int firstBatch = 3;
|
||||
int secondBatch = 5;
|
||||
int thirdBatch = 7;
|
||||
|
||||
EndToEndTestUtils.checkNotRecording();
|
||||
|
||||
// Start a recording
|
||||
EndToEndTestUtils.startRecording();
|
||||
EndToEndTestUtils.checkUnderRecording();
|
||||
EndToEndTestUtils.sendGps(firstBatch);
|
||||
|
||||
// Pause the recording
|
||||
EndToEndTestUtils.pauseRecording();
|
||||
EndToEndTestUtils.checkUnderPaused();
|
||||
|
||||
// Send gps signal after pause
|
||||
EndToEndTestUtils.sendGps(secondBatch, firstBatch, SEND_INTERVAL);
|
||||
|
||||
// Resume the recording
|
||||
EndToEndTestUtils.resumeRecording();
|
||||
EndToEndTestUtils.checkUnderRecording();
|
||||
EndToEndTestUtils.sendGps(thirdBatch, firstBatch + secondBatch);
|
||||
|
||||
// Stop the recordinga
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
checkTrackLocation(firstBatch + secondBatch, 1, 1);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.checkNotRecording();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the last track's location.
|
||||
*
|
||||
* @param expectedPoint the number of expected points
|
||||
* @param expectedPause the number of expected pauses
|
||||
* @param expectedResume the number of expected resumes
|
||||
*/
|
||||
private void checkTrackLocation(int expectedPoint, int expectedPause, int expectedResume) {
|
||||
if (EndToEndTestUtils.isEmulator) {
|
||||
int point = 0;
|
||||
int pause = 0;
|
||||
int resume = 0;
|
||||
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(
|
||||
trackListActivity.getApplicationContext());
|
||||
long trackId = myTracksProviderUtils.getLastTrack().getId();
|
||||
LocationIterator locationIterator = myTracksProviderUtils.getTrackPointLocationIterator(
|
||||
trackId, 0, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
|
||||
while (locationIterator.hasNext()) {
|
||||
Location location = locationIterator.next();
|
||||
double latitude = location.getLatitude();
|
||||
if (latitude == TrackRecordingService.PAUSE_LATITUDE) {
|
||||
pause++;
|
||||
} else if (latitude == TrackRecordingService.RESUME_LATITUDE) {
|
||||
resume++;
|
||||
} else {
|
||||
point++;
|
||||
}
|
||||
}
|
||||
assertEquals(expectedPoint, point);
|
||||
assertEquals(expectedPause, pause);
|
||||
assertEquals(expectedResume, resume);
|
||||
}
|
||||
}
|
||||
}
|
||||
+296
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Tests the settings.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SettingsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private static final String GMAIL_COM = "gmail.com";
|
||||
private static final String NEW_ACTIVITY_TYPE = "NewActivityType";
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public SettingsTest() {
|
||||
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 changing preferred units to imperial.
|
||||
*/
|
||||
public void testPreferredUnits_imperial() {
|
||||
testPreferredUnits(R.string.unit_mile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing preferred units to metric.
|
||||
*/
|
||||
public void testPreferredUnits_metric() {
|
||||
testPreferredUnits(R.string.unit_kilometer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing preferred units while recording and viewing the chart tab.
|
||||
*/
|
||||
public void testPreferredUnitsRecording_chart() {
|
||||
testPreferredUnitsRecording(R.string.track_detail_chart_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing preferred units while recording and viewing the stats tab.
|
||||
*/
|
||||
public void testPreferredUnitsRecording_stats() {
|
||||
testPreferredUnitsRecording(R.string.track_detail_stats_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests changing preferred units while recording and viewing the map tab.
|
||||
*/
|
||||
public void testPreferredUnitsRecording_map() {
|
||||
testPreferredUnitsRecording(R.string.track_detail_map_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests grade/elevation and latitude/longitude..
|
||||
*/
|
||||
public void testGradeElevationAndLatitudeLongitude() {
|
||||
// Ennable grade/elevation and latitude/longitude
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_stats_tab));
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.settings_stats_units_title)));
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_stats_grade_elevation));
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_stats_coordinate));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
|
||||
// Start recording and check stats tab
|
||||
EndToEndTestUtils.startRecording();
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_stats_tab));
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.stats_elevation), 1,
|
||||
EndToEndTestUtils.NORMAL_WAIT_TIME, true));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_grade)));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_latitude)));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_longitude)));
|
||||
|
||||
// Stop recording and check stats tab
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.stats_elevation), 1,
|
||||
EndToEndTestUtils.NORMAL_WAIT_TIME, true));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_grade)));
|
||||
assertNull(
|
||||
EndToEndTestUtils.findTextView(trackListActivity.getString(R.string.stats_latitude)));
|
||||
assertNull(
|
||||
EndToEndTestUtils.findTextView(trackListActivity.getString(R.string.stats_longitude)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests default track name and default activity type.
|
||||
*/
|
||||
public void testDefaultTrackNameAndDefaultActivityType() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_recording));
|
||||
|
||||
// Change the default track name to number
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_recording_track_name_title));
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_recording_track_name_number_option));
|
||||
|
||||
// Change the default activity type to NEW_ACTIVITY_TYPE
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_recording_default_activity_title));
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, NEW_ACTIVITY_TYPE);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_ok), true, true);
|
||||
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
|
||||
EndToEndTestUtils.startRecording();
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.stopRecording(false);
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(
|
||||
trackListActivity.getString(R.string.track_name_format).split(" ")[0]));
|
||||
assertTrue(EndToEndTestUtils.SOLO.searchText(NEW_ACTIVITY_TYPE));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_save));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track color setting for fixed thresholds.
|
||||
*/
|
||||
public void testTrackColor_fixed() {
|
||||
testTrackColor(R.string.settings_map_track_color_mode_fixed,
|
||||
R.string.settings_map_track_color_mode_fixed_summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track color setting for dynamic thresholds.
|
||||
*/
|
||||
public void testTrackColorSettings_dynamic() {
|
||||
testTrackColor(R.string.settings_map_track_color_mode_dynamic,
|
||||
R.string.settings_map_track_color_mode_dynamic_summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track color setting for single color.
|
||||
*/
|
||||
public void testTrackColorSettings_single() {
|
||||
testTrackColor(R.string.settings_map_track_color_mode_single,
|
||||
R.string.settings_map_track_color_mode_single);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests allow access.
|
||||
*/
|
||||
public void testAllowAccess() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_advanced));
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.settings_sharing_allow_access), 1,
|
||||
EndToEndTestUtils.NORMAL_WAIT_TIME));
|
||||
EndToEndTestUtils.SOLO.clickOnCheckBox(0);
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.settings_sharing_allow_access_confirm_message), 1,
|
||||
EndToEndTestUtils.NORMAL_WAIT_TIME));
|
||||
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_yes));
|
||||
instrumentation.waitForIdleSync();
|
||||
assertEquals(true, EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class).get(0).isChecked());
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sync.
|
||||
*/
|
||||
public void testSync() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.menu_sync_drive));
|
||||
|
||||
// Whether there is a gmail.com account
|
||||
if (!EndToEndTestUtils.SOLO.waitForText(GMAIL_COM, 1, EndToEndTestUtils.TINY_WAIT_TIME)) {
|
||||
return;
|
||||
}
|
||||
// Click the first gmail.com account
|
||||
EndToEndTestUtils.SOLO.clickOnText(GMAIL_COM, 0);
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_ok), true, true);
|
||||
|
||||
EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.sync_drive_confirm_message).split("%")[0], 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_no));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
assertEquals(false,
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sync_now), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests preferred units.
|
||||
*
|
||||
* @param unitId the unit id
|
||||
*/
|
||||
private void testPreferredUnits(int unitId) {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_stats_tab));
|
||||
Assert.assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.settings_stats_units_title)));
|
||||
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_stats_units_title));
|
||||
instrumentation.waitForIdleSync();
|
||||
String unit = trackListActivity.getString(unitId);
|
||||
EndToEndTestUtils.SOLO.clickOnText(unit);
|
||||
EndToEndTestUtils.SOLO.searchText(unit);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests preferred units while recording.
|
||||
*
|
||||
* @param tabId the tab id
|
||||
*/
|
||||
private void testPreferredUnitsRecording(int tabId) {
|
||||
testPreferredUnits(R.string.unit_kilometer);
|
||||
|
||||
EndToEndTestUtils.startRecording();
|
||||
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(tabId));
|
||||
EndToEndTestUtils.sendGps(3);
|
||||
testPreferredUnits(R.string.unit_mile);
|
||||
EndToEndTestUtils.sendGps(3, 3);
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests track color setting.
|
||||
*
|
||||
* @param modeId the mode id
|
||||
* @param summaryId the summary id
|
||||
*/
|
||||
private void testTrackColor(int modeId, int summaryId) {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.menu_map));
|
||||
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.settings_map_track_color_mode));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(modeId));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(summaryId));
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2013 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.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.sync.SyncTestUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Tests the share feature.
|
||||
*
|
||||
* @author youtaol
|
||||
*/
|
||||
public class ShareTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity activityMyTracks;
|
||||
|
||||
public ShareTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
activityMyTracks = getActivity();
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the share one track.
|
||||
*/
|
||||
public void testShare() {
|
||||
EndToEndTestUtils.resetAllSettings(activityMyTracks, false);
|
||||
EndToEndTestUtils.createTrackIfEmpty(0, false);
|
||||
|
||||
// Click share again and confirm the share.
|
||||
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_share), true);
|
||||
// Whether can found any account.
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.send_google_no_account_title), 1,
|
||||
EndToEndTestUtils.VERY_SHORT_WAIT_TIME)) {
|
||||
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isAccount2Bound = false;
|
||||
// If Choose account dialog prompt, choose the first account.
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.send_google_choose_account_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
// Whether can found account2.
|
||||
if (EndToEndTestUtils.SOLO.waitForText(
|
||||
GoogleUtils.ACCOUNT_2, 1, EndToEndTestUtils.VERY_SHORT_WAIT_TIME)) {
|
||||
isAccount2Bound = true;
|
||||
}
|
||||
EndToEndTestUtils.SOLO.clickOnText(GoogleUtils.ACCOUNT_1);
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
activityMyTracks.getString(R.string.generic_ok), true, true);
|
||||
}
|
||||
|
||||
// Check all check boxes.
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.share_track_title)));
|
||||
ArrayList<CheckBox> checkBoxs = EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class);
|
||||
for (int i = 0; i < checkBoxs.size(); i++) {
|
||||
if (!checkBoxs.get(i).isChecked()) {
|
||||
EndToEndTestUtils.SOLO.clickOnView(checkBoxs.get(i));
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
}
|
||||
|
||||
// Input account to share and click OK button.
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
|
||||
.getString(R.string.share_track_emails_hint)));
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, GoogleUtils.ACCOUNT_2);
|
||||
EndToEndTestUtils
|
||||
.getButtonOnScreen(activityMyTracks.getString(R.string.generic_ok), true, true);
|
||||
|
||||
// Waiting the send is finish.
|
||||
while (EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.generic_progress_title), 1,
|
||||
EndToEndTestUtils.SHORT_WAIT_TIME)) {}
|
||||
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.SOLO
|
||||
.getString(R.string.share_track_share_url_title)));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
|
||||
// Make more checks if the second account is also bound with this device.
|
||||
if (isAccount2Bound) {
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(
|
||||
activityMyTracks.getString(R.string.track_list_shared_with_me), 1,
|
||||
EndToEndTestUtils.SUPER_LONG_WAIT_TIME));
|
||||
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.trackName, 1,
|
||||
EndToEndTestUtils.SUPER_LONG_WAIT_TIME));
|
||||
}
|
||||
}
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.fragments.ChartFragment;
|
||||
import com.google.android.apps.mytracks.fragments.MyTracksMapFragment;
|
||||
import com.google.android.apps.mytracks.fragments.StatsFragment;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Tests switching views and the menu list of each view.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class ViewsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public ViewsTest() {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches tab from {@link MyTracksMapFragment} to {@link ChartFragment},
|
||||
* then to {@link StatsFragment}, and then to {@link MyTracksMapFragment}. In
|
||||
* each tab, checks menu items like settings and map layer.
|
||||
*/
|
||||
public void testSwitchTabAndViewMenu() {
|
||||
EndToEndTestUtils.createTrackIfEmpty(3, true);
|
||||
|
||||
EndToEndTestUtils.SOLO.scrollUp();
|
||||
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName, 1, true);
|
||||
|
||||
// Switch to chart view
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_chart_tab));
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
assertTrue(
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
|
||||
assertFalse(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_map_layer), false));
|
||||
|
||||
// Switch to stats view
|
||||
EndToEndTestUtils.SOLO.clickOnText(
|
||||
trackListActivity.getString(R.string.track_detail_stats_tab));
|
||||
assertTrue(
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
|
||||
assertFalse(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_map_layer), false));
|
||||
|
||||
// Switch to map view
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
assertTrue(
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
|
||||
assertTrue(EndToEndTestUtils.findMenuItem(
|
||||
trackListActivity.getString(R.string.menu_map_layer), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test selecting map layer.
|
||||
*/
|
||||
public void testMapLayer() {
|
||||
EndToEndTestUtils.createTrackIfEmpty(1, false);
|
||||
|
||||
selectMapLayer(R.string.menu_terrain);
|
||||
selectMapLayer(R.string.menu_satellite_with_streets);
|
||||
selectMapLayer(R.string.menu_satellite);
|
||||
selectMapLayer(R.string.menu_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the track controller position in landscape view and portrait view on
|
||||
* {@link TrackListActivity} and {@link TrackDetailActivity}.
|
||||
*/
|
||||
public void testTrackControllerPostion() {
|
||||
checkTrackControllerPosition();
|
||||
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
instrumentation.waitForIdleSync();
|
||||
checkTrackControllerPosition();
|
||||
|
||||
EndToEndTestUtils.startRecording();
|
||||
instrumentation.waitForIdleSync();
|
||||
checkTrackControllerPosition();
|
||||
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
instrumentation.waitForIdleSync();
|
||||
checkTrackControllerPosition();
|
||||
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
checkTrackControllerPosition();
|
||||
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
instrumentation.waitForIdleSync();
|
||||
checkTrackControllerPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a map layer
|
||||
*
|
||||
* @param id the map layer id
|
||||
*/
|
||||
private void selectMapLayer(int id) {
|
||||
|
||||
// Make sure can see the map tab
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.track_detail_map_tab));
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_map_layer), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(id));
|
||||
EndToEndTestUtils.getButtonOnScreen(
|
||||
trackListActivity.getString(R.string.generic_ok), true, true);
|
||||
instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the position of track controller in landscape view and portrait
|
||||
* view.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void checkTrackControllerPosition() {
|
||||
View controller = EndToEndTestUtils.SOLO.getCurrentActivity()
|
||||
.findViewById(R.id.track_controler_container);
|
||||
Display display = EndToEndTestUtils.SOLO.getCurrentActivity()
|
||||
.getWindowManager().getDefaultDisplay();
|
||||
int width = display.getWidth();
|
||||
int height = display.getHeight();
|
||||
|
||||
if (width > height) {
|
||||
// In landscape view
|
||||
Assert.assertTrue(controller.getWidth() < controller.getHeight());
|
||||
Assert.assertTrue(controller.getTop() < height / 2);
|
||||
Assert.assertTrue(controller.getRight() < width / 2);
|
||||
} else {
|
||||
// In portrait view
|
||||
Assert.assertTrue(controller.getWidth() > controller.getHeight());
|
||||
Assert.assertTrue(controller.getTop() > height / 2);
|
||||
Assert.assertTrue(controller.getRight() > width / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
package com.google.android.apps.mytracks.endtoendtest.others;
|
||||
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningAppProcessInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* A utility to support the big test cases, such as sensor test, stress test and
|
||||
* so forth which under the package
|
||||
* {@link com.google.android.apps.mytracks.endtoendtest.others}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class BigTestUtils {
|
||||
|
||||
public static final String DISABLE_MESSAGE = "This test is disabled";
|
||||
public static final String MYTRACKS_PROCESS_NAME = "com.google.android.maps.mytracks";
|
||||
public static final String MYTRACKS_TEST_INFO_FILE = "MyTracksTestInfo.txt";
|
||||
|
||||
private static final String TAG = BigTestUtils.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Gets the memory usage of MyTracks process. This method would get the Pss
|
||||
* memory. Pss is the amount of memory shared with other processes, accounted
|
||||
* in a way that the amount is divided evenly between the processes that share
|
||||
* it. This is memory that would not be released if the process was
|
||||
* terminated, but is indicative of the amount that this process is
|
||||
* "contributing" to the overall memory load.
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static String getMyTracksPssMemoryInfo(Context context) {
|
||||
int MyTracksProcessId = -1;
|
||||
ActivityManager activityManager = (ActivityManager) context
|
||||
.getSystemService(Activity.ACTIVITY_SERVICE);
|
||||
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
|
||||
|
||||
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) {
|
||||
if (runningAppProcessInfo.processName.equalsIgnoreCase(MYTRACKS_PROCESS_NAME)) {
|
||||
MyTracksProcessId = runningAppProcessInfo.pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (MyTracksProcessId == -1) {
|
||||
Assert.fail();
|
||||
}
|
||||
int pids[] = { MyTracksProcessId };
|
||||
android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
|
||||
int memoryUsage = memoryInfoArray[0].getTotalPss();
|
||||
return String.format(Locale.US, " MyTracks TotalPss Memory: %d (kB) ", memoryUsage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the battery info of device, and then writes it to a file.
|
||||
*
|
||||
* @param context the context of application
|
||||
*/
|
||||
public static String getBatteryUsageInfo(Context context) {
|
||||
Intent batteryIntent = context.getApplicationContext().registerReceiver(null,
|
||||
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
int rawlevel = batteryIntent.getIntExtra("level", -1);
|
||||
double scale = batteryIntent.getIntExtra("scale", -1);
|
||||
return String.format("Device has %s of %s battery left", rawlevel, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a string to battery info file. This method would add a time string
|
||||
* before the given value.
|
||||
*
|
||||
* @param string string to write
|
||||
* @param isAppend true means append to file
|
||||
*/
|
||||
public static void writeToFile(String string, boolean isAppend) {
|
||||
String path = Environment.getExternalStorageDirectory() + File.separator
|
||||
+ MYTRACKS_TEST_INFO_FILE;
|
||||
try {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(new File(path), isAppend);
|
||||
OutputStreamWriter osw = new OutputStreamWriter(fileOutputStream);
|
||||
|
||||
try {
|
||||
// Write the string to the file
|
||||
osw.write(string);
|
||||
} finally {
|
||||
osw.flush();
|
||||
osw.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Meet error when write test info to file.", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors the battery and memory usage during test, and writes the usage
|
||||
* info to a local file.
|
||||
*
|
||||
* @param context application context
|
||||
* @param interval the milliseconds to get usage info
|
||||
* @param testTime the total test milliseconds
|
||||
*/
|
||||
public static void moniterTest(Context context, int interval, int testTime) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
while ((System.currentTimeMillis() - startTime) < testTime) {
|
||||
String memoryUsageString = getMyTracksPssMemoryInfo(context);
|
||||
String batteryUsageString = getBatteryUsageInfo(context);
|
||||
String oneInfo = String.format("{%s: memory use %s, battery left %s. \r\n",
|
||||
String.format("{%1$tm/%1$td/%1$tY %1$tH:%1$tM:%1$tS", new Date()), memoryUsageString,
|
||||
batteryUsageString);
|
||||
writeToFile(oneInfo, true);
|
||||
Log.d(TAG, oneInfo);
|
||||
EndToEndTestUtils.sleep(interval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks and wakes up the device.
|
||||
*/
|
||||
public static void unlockAndWakeupDevice() {
|
||||
// The menu item of setting should be found if the screen is not locked.
|
||||
try {
|
||||
EndToEndTestUtils.SOLO.getCurrentActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Window wind = EndToEndTestUtils.SOLO.getCurrentActivity().getWindow();
|
||||
wind.addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
|
||||
wind.addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||
wind.addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Meet error when unlock device screen, may the device is not locked.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.others;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Tests the battery and memory usage of long tracks. As this test may be run a
|
||||
* long time test and without connect to desktop computer during test. The test
|
||||
* result will be recorded to a file. And at the beginning of test, it need
|
||||
* user's confirm by click a button.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class ResourceUsageTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private static final String TAG = ResourceUsageTest.class.getSimpleName();
|
||||
|
||||
public ResourceUsageTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
private boolean runTest = false;
|
||||
private static boolean isUserConfirmed = false;
|
||||
private Context context;
|
||||
/**
|
||||
* Default duration for each test is half one hour.
|
||||
*/
|
||||
private int TEST_DURATION_IN_MILLISECONDS = 30 * 60 * 1000;
|
||||
private int INTERVALE_TO_CHECK = 5 * 60 * 1000;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
runTest = RunConfiguration.getInstance().getRunResourceTest();
|
||||
if (!runTest) {
|
||||
return;
|
||||
}
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
context = trackListActivity.getApplicationContext();
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.setupForDebug(instrumentation, trackListActivity);
|
||||
BigTestUtils.unlockAndWakeupDevice();
|
||||
if (!isUserConfirmed) {
|
||||
confirmTest();
|
||||
}
|
||||
BigTestUtils.writeToFile("Test case start:" + getName() + "\r\n", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts a dialog to make user confirm whether start the test.
|
||||
*/
|
||||
private void confirmTest() {
|
||||
try {
|
||||
trackListActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new AlertDialog.Builder(EndToEndTestUtils.SOLO.getCurrentActivity())
|
||||
.setTitle("Confirm long time test.")
|
||||
.setMessage(
|
||||
String
|
||||
.format(
|
||||
"Please disconnect the power cord of your device and click 'Start' button. Each case need run %d minutes, and the battery/memory usage will be recorded in every %d minutes.",
|
||||
TEST_DURATION_IN_MILLISECONDS / 1000 / 60, INTERVALE_TO_CHECK / 60 / 1000))
|
||||
.setPositiveButton("Start Test", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
isUserConfirmed = true;
|
||||
runTest = true;
|
||||
BigTestUtils.writeToFile("Test start:\r\n", false);
|
||||
}
|
||||
}).setNegativeButton("Cancel Test", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
isUserConfirmed = true;
|
||||
runTest = false;
|
||||
fail();
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, "Meet error when create confirm dialog.", e);
|
||||
}
|
||||
// Waiting user confirm the testing
|
||||
while (!isUserConfirmed) {
|
||||
EndToEndTestUtils.sleep(EndToEndTestUtils.TINY_WAIT_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resource usage when display track list activity during recording.
|
||||
*/
|
||||
public void testBatteryUsage_showTrackList() {
|
||||
recordingLongTrack(true, R.string.track_detail_map_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resource usage when display map view during recording.
|
||||
*/
|
||||
public void testBatteryUsage_showMapView() {
|
||||
recordingLongTrack(false, R.string.track_detail_map_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resource usage when display chart view during recording.
|
||||
*/
|
||||
public void testBatteryUsage_showChartView() {
|
||||
recordingLongTrack(false, R.string.track_detail_chart_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the resource usage when display stats view during recording.
|
||||
*/
|
||||
public void testBatteryUsage_showStatsView() {
|
||||
recordingLongTrack(false, R.string.track_detail_stats_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a long time track and keeps in the specified tab or in tracks list
|
||||
* during recording.
|
||||
*
|
||||
* @param isShowTracksList true means show tracks list
|
||||
* @param tabNameId the name string id of tab, it's useless when the first
|
||||
* parameter is true.
|
||||
*/
|
||||
public void recordingLongTrack(boolean isShowTracksList, int tabNameId) {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
EndToEndTestUtils.startRecording();
|
||||
if (isShowTracksList) {
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
} else {
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(tabNameId));
|
||||
}
|
||||
BigTestUtils.moniterTest(context, INTERVALE_TO_CHECK, TEST_DURATION_IN_MILLISECONDS);
|
||||
BigTestUtils.unlockAndWakeupDevice();
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (!runTest) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
BigTestUtils.writeToFile("Test case done:" + getName() + "\r\n\r\n", true);
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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.others;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.util.Log;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Tests connecting to sensors.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SensorTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private static final String TAG = SensorTest.class.getSimpleName();
|
||||
private static final String ZEPHYR_NAME = "HXM";
|
||||
private static final String POLAR_NAME = "Polar";
|
||||
|
||||
public SensorTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
private boolean runTest = false;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
runTest = RunConfiguration.getInstance().getRunSensorTest();
|
||||
super.setUp();
|
||||
if (!runTest) {
|
||||
return;
|
||||
}
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to a Zephyr Bluetooth sensor while not recording. Before this test, a Zephyr
|
||||
* sensor must be paired with the device.
|
||||
*/
|
||||
public void testConnectZephyrBluetoothSensor_notRecording() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
bluetoothSensorTest(R.string.settings_sensor_type_zephyr, ZEPHYR_NAME, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to a Zephyr Bluetooth sensor while under recording. Before this test, a Zephyr
|
||||
* sensor must be paired with the device.
|
||||
*/
|
||||
public void testConnectZephyrBluetoothSensor_underRecording() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
bluetoothSensorTest(R.string.settings_sensor_type_zephyr, ZEPHYR_NAME, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to a Polar Bluetooth sensor while not recording. Before this test, a Polar
|
||||
* sensor must be paired with the device.
|
||||
*/
|
||||
public void testConnectPolarBluetoothSensor_notRecording() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
bluetoothSensorTest(R.string.settings_sensor_type_polar, POLAR_NAME, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to a Polar Bluetooth sensor while under recording. Before this test, a Polar
|
||||
* sensor must be paired with the device.
|
||||
*/
|
||||
public void testConnectPolarBluetoothSensor_underRecording() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
bluetoothSensorTest(R.string.settings_sensor_type_polar, POLAR_NAME, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the paired sensor.
|
||||
*
|
||||
* @param sensorTypeStringId the string id of paired sensors type
|
||||
* @param nameString part of the sensor name string which can distinguish
|
||||
* different Bluetooth sensors
|
||||
* @param isUnderRecording true means test under recording
|
||||
*/
|
||||
private void bluetoothSensorTest(int sensorTypeStringId, String nameString,
|
||||
boolean isUnderRecording) {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor_type));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(sensorTypeStringId));
|
||||
checkPairedSensorsNumber(nameString);
|
||||
// Set the paired sensor.
|
||||
EndToEndTestUtils.SOLO.clickOnText(nameString);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
if (isUnderRecording) {
|
||||
assertTrue(checkSensorsStatus_underRecording());
|
||||
} else {
|
||||
assertTrue(checkSensorsStatus_notRecording());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the number of paired sensors.
|
||||
*/
|
||||
private void checkPairedSensorsNumber(String nameString) {
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.settings_sensor_bluetooth_sensor));
|
||||
instrumentation.waitForIdleSync();
|
||||
ArrayList<ListView> allListViews = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class);
|
||||
int number = allListViews.get(0).getCount();
|
||||
if (number > 0
|
||||
&& EndToEndTestUtils.SOLO.waitForText(nameString, 1, EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "No sensor is paried");
|
||||
fail("No bluetooth sensor is paired. Please pair at Settings->Bluetooth before running the test.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to a cadence ANT+ sensor.
|
||||
*/
|
||||
public void testConnectANTSensor_Cadence() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
useANTSeonsor();
|
||||
assertTrue(checkSensorsStatus_notRecording());
|
||||
checkANTSensorsStatus(R.id.sensor_state_cadence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connecting to cadence and heart rate ANT+ sensors at the same time.
|
||||
*/
|
||||
public void testConnectTwoANTSensors() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
useANTSeonsor();
|
||||
assertTrue(checkSensorsStatus_notRecording());
|
||||
checkANTSensorsStatus(R.id.sensor_state_cadence);
|
||||
checkANTSensorsStatus(R.id.sensor_state_heart_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setting to use ANT+ sensor
|
||||
*/
|
||||
private void useANTSeonsor() {
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor_type));
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.settings_sensor_type_ant));
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the ANT+ sensor is connected with MyTracks.
|
||||
*
|
||||
* @param viewID the id to check which is not equal with None
|
||||
*/
|
||||
private void checkANTSensorsStatus(int viewID) {
|
||||
TextView sensorValueText = ((TextView) EndToEndTestUtils.SOLO.getCurrentActivity()
|
||||
.findViewById(viewID));
|
||||
assertNotNull(sensorValueText);
|
||||
String realValue = sensorValueText.getText().toString();
|
||||
String noneValue = trackListActivity.getString(R.string.value_none);
|
||||
assertNotSame(realValue, noneValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the sensor is connected with MyTracks during recording.
|
||||
*
|
||||
* @return true means the sensor is connected with MyTracks
|
||||
*/
|
||||
private boolean checkSensorsStatus_underRecording() {
|
||||
EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.startRecording();
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sensor_state), true);
|
||||
boolean result = EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.sensor_state_connected), 1,
|
||||
EndToEndTestUtils.LONG_WAIT_TIME);
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the sensor is connected with MyTracks while not under recording.
|
||||
*
|
||||
* @return true means the sensor is connected with MyTracks
|
||||
*/
|
||||
private boolean checkSensorsStatus_notRecording() {
|
||||
EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.createTrackIfEmpty(0, false);
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sensor_state), true);
|
||||
return EndToEndTestUtils.SOLO.waitForText(
|
||||
trackListActivity.getString(R.string.sensor_state_connected), 1,
|
||||
EndToEndTestUtils.LONG_WAIT_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (!runTest) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.others;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.util.Log;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* Stress test of MyTracks.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class StressTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private static final String TAG = StressTest.class.getSimpleName();
|
||||
private static final int TEST_DURATION_IN_MILLISECONDS = 30 * 60 * 1000;
|
||||
private static final int MAX_TRACK_NUMBER = 30;
|
||||
private boolean runTest = false;
|
||||
|
||||
private long startTime = 0;
|
||||
private int numberOfTracks;
|
||||
|
||||
public StressTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
runTest = RunConfiguration.getInstance().getRunStressTest();
|
||||
super.setUp();
|
||||
if (!runTest) {
|
||||
return;
|
||||
}
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
|
||||
BigTestUtils.unlockAndWakeupDevice();
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Records tracks and deletes them when there are more than
|
||||
* {@link #MAX_TRACK_NUMBER} tracks. Keeps sending different GPS locations in
|
||||
* each track, making it closer to the real stress.
|
||||
*/
|
||||
public void testRecordAndDeleteTracks() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; (System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS; i++) {
|
||||
EndToEndTestUtils.startRecording();
|
||||
// Points in a tracks keep increasing.
|
||||
EndToEndTestUtils.sendGps(i * 10, 0, 10);
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
numberOfTracks = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
if (numberOfTracks > MAX_TRACK_NUMBER) {
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
}
|
||||
logStatus(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates screen when display map view. Keeps sending different GPS locations
|
||||
* in each track, making it closer to the real stress.
|
||||
*/
|
||||
public void testRotateMapViewInTrackDetailActivity() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.startRecording();
|
||||
for (int i = 0; (System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS; i++) {
|
||||
EndToEndTestUtils.sendGps(10, i * 10);
|
||||
EndToEndTestUtils.rotateCurrentActivity();
|
||||
Log.d(TAG, String.format("Totate %d times in %d minutes!", i,
|
||||
(System.currentTimeMillis() - startTime) / 1000 / 60));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches view between MAP, CHART and STAT.
|
||||
*/
|
||||
public void testSwitchTabs() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.startRecording();
|
||||
int i = 0;
|
||||
while ((System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS) {
|
||||
EndToEndTestUtils.SOLO
|
||||
.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.track_detail_chart_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.track_detail_stats_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
logStatus(++i);
|
||||
}
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a long track.
|
||||
*/
|
||||
public void testRecordLongTrack() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.startRecording();
|
||||
int gpsNumber = 5000;
|
||||
for (int i = 0; i < gpsNumber / 10; i++) {
|
||||
EndToEndTestUtils.sendGps(10, i * 10);
|
||||
}
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches view between MAP, CHART and STAT. And create way points, pause and
|
||||
* resume the track during recording.
|
||||
*/
|
||||
public void testSwitchTabs_wayPoints() {
|
||||
if (!runTest) {
|
||||
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.startRecording();
|
||||
|
||||
int i = 0;
|
||||
while ((System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS) {
|
||||
// Create one way points.
|
||||
EndToEndTestUtils.sendGps(10, 10 * i);
|
||||
EndToEndTestUtils.createWaypoint(i);
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_recording));
|
||||
EndToEndTestUtils.pauseRecording();
|
||||
|
||||
EndToEndTestUtils.SOLO
|
||||
.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.track_detail_chart_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
|
||||
.getString(R.string.track_detail_stats_tab));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_paused));
|
||||
EndToEndTestUtils.resumeRecording();
|
||||
logStatus(++i);
|
||||
}
|
||||
EndToEndTestUtils.stopRecording(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs status.
|
||||
*
|
||||
* @param times the number of times this test has been run
|
||||
*/
|
||||
private void logStatus(int times) {
|
||||
int minutes =
|
||||
(int) (TEST_DURATION_IN_MILLISECONDS - (System.currentTimeMillis() - startTime)) / 60
|
||||
/ 1000;
|
||||
Log.d(TAG, String.format(
|
||||
"This test has run %d times and will be finished in %d minutes!", times, minutes));
|
||||
Log.d(TAG, String.format("There are %d tracks!", numberOfTracks));
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2013 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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.services.drive.Drive;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* Tests the situation when user use multiple account in MyTracks.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MultiAccountsSyncTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Drive drive;
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public MultiAccountsSyncTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
drive = SyncTestUtils
|
||||
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sync tracks with Google Drive of two accounts with following
|
||||
* sequence:
|
||||
* <ul>
|
||||
* <li>1. Enable sync with account1.</li>
|
||||
* <li>2. Create a track.</li>
|
||||
* <li>3. Enable sync with account2.</li>
|
||||
* <li>4. Create a track.</li>
|
||||
* <li>5. Sync and check</li>
|
||||
* <li>6. Enable sync with account1.</li>
|
||||
* <li>7. Sync and check</li>
|
||||
* <li>8. Enable sync with account2.</li>
|
||||
* <li>9. Check</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void testSyncTracksWithMultiAccounts() throws Exception {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
// Create tracks with first track.
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
|
||||
// Create tracks with second track.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
|
||||
// Sync with Google Drive and then check it of the second account.
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
|
||||
// Check Google Drive of the first account.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
|
||||
// Back to account1 change check that files are still existed.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
|
||||
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of MyTracks about delete operation and switch accounts
|
||||
* with following sequence.:
|
||||
* <ul>
|
||||
* <li>1. Create 3 tracks.</li>
|
||||
* <li>2. Delete 1 track.</li>
|
||||
* <li>3. Sync with account2(account2 should have 2 files).</li>
|
||||
* <li>4. Delete 1 track (account2 should have 1 file).</li>
|
||||
* <li>5. Sync with account 1 (account 1 should have 1 file, account2 should
|
||||
* also have 1 file).</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void testDeleteTracksWithMultiAccounts() throws Exception {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
|
||||
// Delete one track.
|
||||
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class)
|
||||
.get(0).getChildAt(0));
|
||||
EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.menu_delete));
|
||||
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.generic_yes));
|
||||
|
||||
// Switch account and delete another track.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
|
||||
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class)
|
||||
.get(0).getChildAt(0));
|
||||
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.menu_delete));
|
||||
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.generic_yes));
|
||||
|
||||
// Check Google Drive of the first account.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
|
||||
// Check Google Drive of the second account.
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
}
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2013 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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.services.drive.Drive;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tests making changes on Google Drive when syncing My Tracks with Google
|
||||
* Drive.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SyncDriveWithMyTracksTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Drive drive;
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public SyncDriveWithMyTracksTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
drive = SyncTestUtils
|
||||
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all tracks in MyTracks and checks in Google Drive.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testDeleteAllTracksInMyTracks() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes one track in MyTracks and checks it in Google Drive.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testDeleteOneTracksInMyTracks() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.createTrackIfEmpty(2, false);
|
||||
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.menu_delete));
|
||||
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
|
||||
.getString(R.string.generic_yes));
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFile(EndToEndTestUtils.trackName, false, drive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates one empty track and one non-empty track in MyTracks and then check
|
||||
* them in Google Drive.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testCreateTracksInMyTracks() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.createSimpleTrack(3, true);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits a tracks in MyTracks and checks it on Google Drive after sync.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testEditTrackInMyTracks() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.createTrackIfEmpty(3, true);
|
||||
|
||||
// Sync this track.
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFile(EndToEndTestUtils.trackName, true, drive);
|
||||
String oldTrack = SyncTestUtils.getContentOfFile(
|
||||
SyncTestUtils.getFile(EndToEndTestUtils.trackName, drive), drive);
|
||||
|
||||
String oldTrackName = EndToEndTestUtils.trackName;
|
||||
|
||||
// Edit this track.
|
||||
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName);
|
||||
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
|
||||
String newTrackName = EndToEndTestUtils.TRACK_NAME_PREFIX + "_new" + System.currentTimeMillis();
|
||||
String newType = EndToEndTestUtils.activityType + newTrackName;
|
||||
String newDesc = "desc" + newTrackName;
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_save));
|
||||
sendKeys(KeyEvent.KEYCODE_DEL);
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, newTrackName);
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(1, newType);
|
||||
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(2, newDesc);
|
||||
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.SOLO.goBack();
|
||||
instrumentation.waitForIdleSync();
|
||||
|
||||
// Sync again.
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
|
||||
// Check.
|
||||
SyncTestUtils.checkFile(oldTrackName, false, drive);
|
||||
SyncTestUtils.checkFile(newTrackName, true, drive);
|
||||
String newTrack = SyncTestUtils.getContentOfFile(SyncTestUtils.getFile(newTrackName, drive),
|
||||
drive);
|
||||
assertNotSame(oldTrack, newTrack);
|
||||
assertTrue(newTrack.indexOf(newTrackName) > 0);
|
||||
assertTrue(newTrack.indexOf(newType) > 0);
|
||||
assertTrue(newTrack.indexOf(newDesc) > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
EndToEndTestUtils.SOLO.finishOpenedActivities();
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2013 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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import com.google.api.services.drive.model.File;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tests making changes on My Tracks when syncing My Tracks with Google Drive.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SyncMyTracksWithDriveTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
|
||||
|
||||
private Drive drive;
|
||||
private Instrumentation instrumentation;
|
||||
private TrackListActivity trackListActivity;
|
||||
|
||||
public SyncMyTracksWithDriveTest() {
|
||||
super(TrackListActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
instrumentation = getInstrumentation();
|
||||
trackListActivity = getActivity();
|
||||
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
|
||||
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
|
||||
drive = SyncTestUtils
|
||||
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all tracks on Google Drive and checks in MyTracks.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testDeleteAllTracksOnDrive() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
EndToEndTestUtils.createTrackIfEmpty(0, true);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
|
||||
SyncTestUtils.removeKMLFiles(drive);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkTracksNumber(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes one file on Google Drive and checks it in MyTracks.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testDeleteOneFileOnDrive() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
|
||||
// Remove one track from Google Drive
|
||||
File file = SyncTestUtils.getFile(EndToEndTestUtils.trackName, drive);
|
||||
SyncTestUtils.removeFile(file, drive);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
SyncTestUtils.checkTracksNumber(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting and creating MyTracks folder on Google Dive by MyTracks.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void testCreateMyTracksOnDrive() throws IOException {
|
||||
if (!RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
return;
|
||||
}
|
||||
instrumentation.waitForIdleSync();
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.createSimpleTrack(0, true);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
instrumentation.waitForIdleSync();
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
File folder = SyncUtils.getMyTracksFolder(trackListActivity.getApplicationContext(), drive);
|
||||
assertNotNull(folder);
|
||||
|
||||
SyncTestUtils.removeFile(folder, drive);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
SyncTestUtils.checkFilesNumber(drive);
|
||||
}
|
||||
}
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright 2013 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.sync;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
|
||||
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
|
||||
import com.google.android.apps.mytracks.io.sync.SyncUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.gms.auth.GoogleAuthException;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.services.drive.Drive;
|
||||
import com.google.api.services.drive.model.File;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
* Utilites for Google Drive sync endtoend test.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SyncTestUtils {
|
||||
|
||||
private static final String TAG = SyncTestUtils.class.getSimpleName();
|
||||
public static boolean isCheckedRunSyncTest = false;
|
||||
public static final String KML_FILE_POSTFIX = ".kml";
|
||||
public static final long MAX_TIME_TO_WAIT_SYNC = 100000;
|
||||
|
||||
/**
|
||||
* Sets up sync tests.
|
||||
*
|
||||
* @param instrumentation the instrumentation is used for test
|
||||
* @param trackListActivity the startup activity
|
||||
* @return a Google Drive object
|
||||
*/
|
||||
public static Drive setUpForSyncTest(Instrumentation instrumentation,
|
||||
TrackListActivity trackListActivity) throws IOException, GoogleAuthException {
|
||||
if (!isCheckedRunSyncTest || RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
|
||||
}
|
||||
if (!isCheckedRunSyncTest) {
|
||||
isCheckedRunSyncTest = true;
|
||||
}
|
||||
if (RunConfiguration.getInstance().getRunSyncTest()) {
|
||||
enableSync(GoogleUtils.ACCOUNT_1);
|
||||
Drive drive1 = getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
|
||||
removeKMLFiles(drive1);
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
enableSync(GoogleUtils.ACCOUNT_2);
|
||||
Drive drive2 = getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
|
||||
removeKMLFiles(drive2);
|
||||
EndToEndTestUtils.deleteAllTracks();
|
||||
return drive2;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets drive object of Google Drive.
|
||||
*
|
||||
* @param context the context of application
|
||||
* @return a Google Drive object
|
||||
*/
|
||||
public static Drive getGoogleDrive(Context context) throws IOException, GoogleAuthException {
|
||||
String googleAccount = PreferencesUtils.getString(context, R.string.google_account_key,
|
||||
PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
|
||||
GoogleAccountCredential credential = SendToGoogleUtils.getGoogleAccountCredential(context,
|
||||
googleAccount, SendToGoogleUtils.DRIVE_SCOPE);
|
||||
return SyncUtils.getDriveService(credential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets KML files from Google Drive of current account.
|
||||
*
|
||||
* @param context the context of application
|
||||
* @param drive a Google Drive object
|
||||
* @return KML file on Google drive
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<File> getDriveFiles(Context context, Drive drive) throws IOException {
|
||||
File folder = SyncUtils.getMyTracksFolder(context, drive);
|
||||
if (folder == null) {
|
||||
return new ArrayList<File>();
|
||||
}
|
||||
String folderId = folder.getId();
|
||||
return drive.files().list()
|
||||
.setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId)).execute()
|
||||
.getItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds whether a file is existed by the name of track.
|
||||
*
|
||||
* @param trackName name of track
|
||||
* @param drive a Google Drive object
|
||||
* @return the file be found
|
||||
* @throws IOException
|
||||
*/
|
||||
public static File getFile(String trackName, Drive drive) throws IOException {
|
||||
List<File> files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(),
|
||||
drive);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
File file = files.get(i);
|
||||
String title = file.getTitle();
|
||||
if (title.equals(trackName + KML_FILE_POSTFIX)) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all KML files on Google Drive.
|
||||
*
|
||||
* @param drive a Google Drive object
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void removeKMLFiles(Drive drive) throws IOException {
|
||||
List<File> files = getDriveFiles(
|
||||
EndToEndTestUtils.trackListActivity.getApplicationContext(), drive);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
File file = files.get(i);
|
||||
removeFile(file, drive);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes one file on Google Drive.
|
||||
*
|
||||
* @param file the file to remove
|
||||
* @param drive a Google Drive object
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void removeFile(File file, Drive drive) throws IOException {
|
||||
drive.files().trash(file.getId()).execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables sync feature in MyTracks settings.
|
||||
*
|
||||
* @param accountName the account which is used to sync with
|
||||
*/
|
||||
public static void enableSync(String accountName) {
|
||||
// EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
// EndToEndTestUtils.findMenuItem(
|
||||
// EndToEndTestUtils.activityMytracks.getString(R.string.menu_settings), true);
|
||||
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.settings_google));
|
||||
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.settings_google_account_title));
|
||||
// EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
//
|
||||
// // Whether test account is bound.
|
||||
// if (EndToEndTestUtils.SOLO.waitForText(accountName, 1, EndToEndTestUtils.SHORT_WAIT_TIME)) {
|
||||
// EndToEndTestUtils.SOLO.clickOnText(accountName);
|
||||
// EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
//
|
||||
// if (EndToEndTestUtils.findTextView(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.settings_google_account_confirm_title)) != null) {
|
||||
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.generic_yes));
|
||||
// }
|
||||
// } else {
|
||||
// Assert.fail();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// EndToEndTestUtils.SOLO.waitForDialogToClose(EndToEndTestUtils.SHORT_WAIT_TIME);
|
||||
// EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
// CheckBox syncCheckBox = EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class).get(0);
|
||||
// if (!syncCheckBox.isChecked()) {
|
||||
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.menu_sync_drive));
|
||||
//
|
||||
// EndToEndTestUtils.SOLO.waitForText(
|
||||
// EndToEndTestUtils.activityMytracks.getString(R.string.sync_drive_confirm_message).split(
|
||||
// "%")[0], 1, EndToEndTestUtils.SHORT_WAIT_TIME);
|
||||
// Assert.assertTrue(EndToEndTestUtils.SOLO.searchText(accountName, true));
|
||||
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
|
||||
// .getString(R.string.generic_yes));
|
||||
// }
|
||||
//
|
||||
// // Add this sleep to work around a exception after switch account.
|
||||
// EndToEndTestUtils.sleep(15000);
|
||||
// EndToEndTestUtils.SOLO.goBack();
|
||||
// EndToEndTestUtils.SOLO.goBack();
|
||||
// EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the files number on Google Drive
|
||||
*
|
||||
* @param drive a Google Drive object
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void checkFilesNumber(Drive drive) throws IOException {
|
||||
EndToEndTestUtils.instrumentation.waitForIdleSync();
|
||||
long startTime = System.currentTimeMillis();
|
||||
int trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
List<File> files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(),
|
||||
drive);
|
||||
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
|
||||
try {
|
||||
if (files.size() == trackNumber) {
|
||||
return;
|
||||
}
|
||||
trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(), drive);
|
||||
EndToEndTestUtils.sleep(EndToEndTestUtils.SHORT_WAIT_TIME);
|
||||
EndToEndTestUtils.findMenuItem(
|
||||
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
|
||||
} catch (GoogleJsonResponseException e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(files.size(), trackNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the files number on Google Drive
|
||||
*
|
||||
* @param number number of files on Google Drive
|
||||
*/
|
||||
public static void checkTracksNumber(int number) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
|
||||
if (trackNumber == number) {
|
||||
return;
|
||||
}
|
||||
trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
|
||||
Log.d(TAG, trackNumber + ":" + number);
|
||||
}
|
||||
Assert.assertEquals(trackNumber, number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks one file on Google Drive
|
||||
*
|
||||
* @param trackName the name of track
|
||||
* @param shouldExist true means this track should be existed
|
||||
* @param drive a Google Drive object
|
||||
* @return true means the actual result is same as expectation
|
||||
* @throws IOException
|
||||
*/
|
||||
public static boolean checkFile(String trackName, boolean shouldExist, Drive drive)
|
||||
throws IOException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
|
||||
boolean exist = getFile(trackName, drive) != null;
|
||||
if (exist == shouldExist) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Assert.fail();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content of a file on Google Drive.
|
||||
*
|
||||
* @param file file to read
|
||||
* @param drive a Google Drive object
|
||||
* @return the string content of the file
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String getContentOfFile(File file, Drive drive) throws IOException {
|
||||
HttpResponse resp = drive.getRequestFactory()
|
||||
.buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(resp.getContent()));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
String fileContent = sb.toString();
|
||||
br.close();
|
||||
return fileContent;
|
||||
}
|
||||
}
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView;
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
|
||||
import android.location.Location;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link ChartFragment}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class ChartFragmentTest extends AndroidTestCase {
|
||||
|
||||
private static final double HOURS_PER_UNIT = 60.0;
|
||||
|
||||
private ChartFragment chartFragment;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
chartFragment = new ChartFragment();
|
||||
chartFragment.setChartView(new ChartView(getContext()));
|
||||
chartFragment.setTripStatisticsUpdater(TrackStubUtils.INITIAL_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}
|
||||
*/
|
||||
public void testFillDataPoint_sensorIncorrect() {
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
// No input.
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
|
||||
// Input incorrect state.
|
||||
// Creates SensorData.
|
||||
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
|
||||
.setValue(100).setState(Sensor.SensorState.NONE);
|
||||
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
|
||||
.setValue(101).setState(Sensor.SensorState.NONE);
|
||||
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
|
||||
.setValue(102).setState(Sensor.SensorState.NONE);
|
||||
|
||||
// Creates SensorDataSet.
|
||||
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
|
||||
sensorDataSet = sensorDataSet.toBuilder()
|
||||
.setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build();
|
||||
myTracksLocation.setSensorDataSet(sensorDataSet);
|
||||
// Test.
|
||||
point = fillDataPointTestHelper(myTracksLocation);
|
||||
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the correct values of sensor in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_sensorCorrect() {
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
// No input.
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
|
||||
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
|
||||
|
||||
// Creates SensorData.
|
||||
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
|
||||
.setValue(100).setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
|
||||
.setValue(101).setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
|
||||
.setValue(102).setState(Sensor.SensorState.SENDING);
|
||||
|
||||
// Creates SensorDataSet.
|
||||
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
|
||||
sensorDataSet = sensorDataSet.toBuilder()
|
||||
.setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build();
|
||||
myTracksLocation.setSensorDataSet(sensorDataSet);
|
||||
// Test.
|
||||
point = fillDataPointTestHelper(myTracksLocation);
|
||||
assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1]);
|
||||
assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1]);
|
||||
assertEquals(102.0, point[ChartView.POWER_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of metric Distance in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_distanceMetric() {
|
||||
// By distance.
|
||||
chartFragment.setChartByDistance(true);
|
||||
// Resets last location and writes first location.
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[0]);
|
||||
|
||||
// The second is a same location, just different time.
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals(0.0, point[0]);
|
||||
|
||||
// The third location is a new location, and use metric.
|
||||
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation3.setLatitude(23);
|
||||
point = fillDataPointTestHelper(myTracksLocation3);
|
||||
|
||||
// Computes the distance between Latitude 22 and 23.
|
||||
float[] results = new float[4];
|
||||
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
|
||||
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
|
||||
double distance1 = results[0] * UnitConversions.M_TO_KM;
|
||||
assertEquals(distance1, point[0]);
|
||||
|
||||
// The fourth location is a new location, and use metric.
|
||||
MyTracksLocation myTracksLocation4 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation4.setLatitude(24);
|
||||
point = fillDataPointTestHelper(myTracksLocation4);
|
||||
|
||||
// Computes the distance between Latitude 23 and 24.
|
||||
Location.distanceBetween(myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(),
|
||||
myTracksLocation4.getLatitude(), myTracksLocation4.getLongitude(), results);
|
||||
double distance2 = results[0] * UnitConversions.M_TO_KM;
|
||||
assertEquals((distance1 + distance2), point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of imperial Distance in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_distanceImperial() {
|
||||
// By distance.
|
||||
chartFragment.setChartByDistance(true);
|
||||
// Setups to use imperial.
|
||||
chartFragment.setMetricUnits(false);
|
||||
|
||||
// The first is a same location, just different time.
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[0]);
|
||||
|
||||
// The second location is a new location, and use imperial.
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setLatitude(23);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
|
||||
/*
|
||||
* Computes the distance between Latitude 22 and 23. And for we set using
|
||||
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
|
||||
*/
|
||||
float[] results = new float[4];
|
||||
Location.distanceBetween(myTracksLocation1.getLatitude(), myTracksLocation1.getLongitude(),
|
||||
myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), results);
|
||||
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||
assertEquals(distance1, point[0]);
|
||||
|
||||
// The third location is a new location, and use imperial.
|
||||
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation3.setLatitude(24);
|
||||
point = fillDataPointTestHelper(myTracksLocation3);
|
||||
|
||||
/*
|
||||
* Computes the distance between Latitude 23 and 24. And for we set using
|
||||
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
|
||||
*/
|
||||
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
|
||||
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
|
||||
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
|
||||
assertEquals(distance1 + distance2, point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the values of time in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}.
|
||||
*/
|
||||
public void testFillDataPoint_time() {
|
||||
// By time
|
||||
chartFragment.setChartByDistance(false);
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[0]);
|
||||
long timeSpan = 222;
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setTime(myTracksLocation1.getTime() + timeSpan);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals((double) timeSpan, point[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of elevation in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])} by one and two points.
|
||||
*/
|
||||
public void testFillDataPoint_elevation() {
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* At first, clear old points of elevation, so give true to the second
|
||||
* parameter. Then only one value INITIALLONGTITUDE in buffer.
|
||||
*/
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1]);
|
||||
|
||||
/*
|
||||
* Send another value to buffer, now there are two values, INITIALALTITUDE
|
||||
* and INITIALALTITUDE * 2.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0,
|
||||
point[ChartView.ELEVATION_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get the value of speed in {@link ChartFragment#fillDataPoint(Location,
|
||||
* double[])}. In this test, firstly remove all
|
||||
* points in memory, and then fill in two points one by one. The speed values
|
||||
* of these points are 129, 130.
|
||||
*/
|
||||
public void testFillDataPoint_speed() {
|
||||
/*
|
||||
* At first, clear old points of speed, so give true to the second
|
||||
* parameter. It will not be filled in to the speed buffer.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(128.5f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
/*
|
||||
* Tests the logic when both metricUnits and reportSpeed are true.This
|
||||
* location will be filled into speed buffer.
|
||||
*/
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid, the value
|
||||
* 222 here is doesn't matter.
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation1.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(130);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to compute speed when use Imperial.
|
||||
*/
|
||||
public void testFillDataPoint_speedImperial() {
|
||||
// Setups to use imperial.
|
||||
chartFragment.setMetricUnits(false);
|
||||
|
||||
// First data point is not added to the speed buffer
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(100.0f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid and the speed
|
||||
* is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION
|
||||
* * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(102);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI,
|
||||
point[ChartView.SPEED_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get pace value when reportSpeed is false.
|
||||
*/
|
||||
public void testFillDataPoint_pace_nonZeroSpeed() {
|
||||
// Setups reportSpeed to false.
|
||||
chartFragment.setReportSpeed(false);
|
||||
|
||||
// First data point is not added to the speed buffer
|
||||
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation1.setSpeed(100.0f);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation1);
|
||||
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
|
||||
|
||||
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
|
||||
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid and the speed
|
||||
* is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION
|
||||
* * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
|
||||
myTracksLocation2.setSpeed(102);
|
||||
point = fillDataPointTestHelper(myTracksLocation2);
|
||||
assertEquals(
|
||||
HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the logic to get pace value when reportSpeed is false and average
|
||||
* speed is zero.
|
||||
*/
|
||||
public void testFillDataPoint_pace_zeroSpeed() {
|
||||
// Setups reportSpeed to false.
|
||||
chartFragment.setReportSpeed(false);
|
||||
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
|
||||
myTracksLocation.setSpeed(0);
|
||||
double[] point = fillDataPointTestHelper(myTracksLocation);
|
||||
assertEquals(0.0, point[ChartView.PACE_SERIES + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to test fillDataPoint.
|
||||
*
|
||||
* @param location location to fill
|
||||
* @return data of this location
|
||||
*/
|
||||
private double[] fillDataPointTestHelper(Location location) {
|
||||
double[] point = new double[ChartView.NUM_SERIES + 1];
|
||||
chartFragment.fillDataPoint(location, point);
|
||||
return point;
|
||||
}
|
||||
|
||||
}
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link PreferenceBackupHelper}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class PreferenceBackupHelperTest extends AndroidTestCase {
|
||||
private Map<String, ?> preferenceValues;
|
||||
private SharedPreferences preferences;
|
||||
private PreferenceBackupHelper preferenceBackupHelper;
|
||||
|
||||
/**
|
||||
* Mock shared preferences editor which does not persist state.
|
||||
*/
|
||||
private class MockPreferenceEditor implements SharedPreferences.Editor {
|
||||
private Map<String, Object> newPreferences = new HashMap<String, Object>(preferenceValues);
|
||||
|
||||
@Override
|
||||
public Editor clear() {
|
||||
newPreferences.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commit() {
|
||||
apply();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
preferenceValues = newPreferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putBoolean(String key, boolean value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putFloat(String key, float value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putInt(String key, int value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putLong(String key, long value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putString(String key, String value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
public Editor putStringSet(String key, Set<String> value) {
|
||||
return put(key, value);
|
||||
}
|
||||
|
||||
private <T> Editor put(String key, T value) {
|
||||
newPreferences.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor remove(String key) {
|
||||
newPreferences.remove(key);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock shared preferences which does not persist state.
|
||||
*/
|
||||
private class MockPreferences implements SharedPreferences {
|
||||
@Override
|
||||
public boolean contains(String key) {
|
||||
return preferenceValues.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor edit() {
|
||||
return new MockPreferenceEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ?> getAll() {
|
||||
return preferenceValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String key, float defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key, String defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
public Set<String> getStringSet(String key, Set<String> defValue) {
|
||||
return get(key, defValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T get(String key, T defValue) {
|
||||
Object value = preferenceValues.get(key);
|
||||
if (value == null) return defValue;
|
||||
return (T) value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
preferenceValues = new HashMap<String, Object>();
|
||||
preferences = new MockPreferences();
|
||||
preferenceBackupHelper = new PreferenceBackupHelper(getContext());
|
||||
}
|
||||
|
||||
public void testExportImportPreferences() throws Exception {
|
||||
// Populate with some initial values
|
||||
Editor editor = preferences.edit();
|
||||
editor.clear();
|
||||
editor.putBoolean("bool1", true);
|
||||
editor.putBoolean("bool2", false);
|
||||
editor.putFloat("flt1", 3.14f);
|
||||
editor.putInt("int1", 42);
|
||||
editor.putLong("long1", 123456789L);
|
||||
editor.putString("str1", "lolcat");
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
|
||||
|
||||
// Export it
|
||||
byte[] exported = preferenceBackupHelper.exportPreferences(preferences);
|
||||
|
||||
// Mess with the previous values
|
||||
editor = preferences.edit();
|
||||
editor.clear();
|
||||
editor.putString("str2", "Shouldn't be there after restore");
|
||||
editor.putBoolean("bool2", true);
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
|
||||
|
||||
// Import it back
|
||||
preferenceBackupHelper.importPreferences(exported, preferences);
|
||||
|
||||
assertFalse(preferences.contains("str2"));
|
||||
assertTrue(preferences.getBoolean("bool1", false));
|
||||
assertFalse(preferences.getBoolean("bool2", true));
|
||||
assertEquals(3.14f, preferences.getFloat("flt1", 0.0f));
|
||||
assertEquals(42, preferences.getInt("int1", 0));
|
||||
assertEquals(123456789L, preferences.getLong("long1", 0));
|
||||
assertEquals("lolcat", preferences.getString("str1", ""));
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.io.file.exporter.CsvTrackWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link CsvTrackWriter}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class CsvTrackWriterTest extends TrackWriterTest {
|
||||
|
||||
private static final String BEGIN_TAG = "\"";
|
||||
private static final String END_TAG = "\"\n";
|
||||
private static final String SEPARATOR = "\",\"";
|
||||
|
||||
public void testCsvOutput() throws Exception {
|
||||
String expectedTrackHeader = getExpectedLine(
|
||||
"Name", "Activity type", "Description");
|
||||
String expectedTrack = getExpectedLine(TRACK_NAME, TRACK_CATEGORY, TRACK_DESCRIPTION);
|
||||
String expectedMarkerHeader = getExpectedLine("Name",
|
||||
"Marker type",
|
||||
"Description",
|
||||
"Latitude (deg)",
|
||||
"Longitude (deg)",
|
||||
"Altitude (m)",
|
||||
"Bearing (deg)",
|
||||
"Accuracy (m)",
|
||||
"Speed (m/s)",
|
||||
"Time");
|
||||
String expectedMarker1 = getExpectedLine(WAYPOINT1_NAME, WAYPOINT1_CATEGORY,
|
||||
WAYPOINT1_DESCRIPTION, "1.0", "-1.0", "10.0", "100.0", "1,000", "10,000",
|
||||
"1970-01-01T00:01:40.000Z");
|
||||
String expectedMarker2 = getExpectedLine(WAYPOINT2_NAME, WAYPOINT2_CATEGORY,
|
||||
WAYPOINT2_DESCRIPTION, "2.0", "-2.0", "20.0", "200.0", "2,000", "20,000",
|
||||
"1970-01-01T00:03:20.000Z");
|
||||
String expectedPointHeader = getExpectedLine("Segment", "Point", "Latitude (deg)",
|
||||
"Longitude (deg)", "Altitude (m)", "Bearing (deg)", "Accuracy (m)", "Speed (m/s)", "Time",
|
||||
"Power (W)", "Cadence (rpm)", "Heart rate (bpm)");
|
||||
String expectedPoint1 = getExpectedLine("1", "1", "0.0", "0.0", "0.0", "0.0", "0", "0",
|
||||
"1970-01-01T00:00:00.000Z", "100.0", "200.0", "300.0");
|
||||
String expectedPoint2 = getExpectedLine("1", "2", "1.0", "-1.0", "10.0", "100.0", "1,000",
|
||||
"10,000", "1970-01-01T00:01:40.000Z", "101.0", "201.0", "301.0");
|
||||
String expectedPoint3 = getExpectedLine("2", "1", "2.0", "-2.0", "20.0", "200.0", "2,000",
|
||||
"20,000", "1970-01-01T00:03:20.000Z", "102.0", "202.0", "302.0");
|
||||
String expectedPoint4 = getExpectedLine("2", "2", "3.0", "-3.0", "30.0", "300.0", "3,000",
|
||||
"30,000", "1970-01-01T00:05:00.000Z", "103.0", "203.0", "303.0");
|
||||
String expected = expectedTrackHeader + expectedTrack + "\n"
|
||||
+ expectedMarkerHeader + expectedMarker1 + expectedMarker2 + "\n"
|
||||
+ expectedPointHeader + expectedPoint1 + expectedPoint2 + expectedPoint3 + expectedPoint4;
|
||||
|
||||
CsvTrackWriter csvTrackWriter = new CsvTrackWriter(getContext());
|
||||
assertEquals(expected, writeTrack(csvTrackWriter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expected CSV line from a list of expected values.
|
||||
*
|
||||
* @param values expected values
|
||||
*/
|
||||
private String getExpectedLine(String... values) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(BEGIN_TAG);
|
||||
boolean first = true;
|
||||
for (String value : values) {
|
||||
if (!first) {
|
||||
builder.append(SEPARATOR);
|
||||
}
|
||||
first = false;
|
||||
builder.append(value);
|
||||
}
|
||||
builder.append(END_TAG);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
|
||||
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.mock.MockContentResolver;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.easymock.IArgumentMatcher;
|
||||
import org.easymock.IMocksControl;
|
||||
|
||||
/**
|
||||
* Tests for {@link FileTrackExporter}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class FileTrackExporterTest extends AndroidTestCase {
|
||||
|
||||
private static final long TRACK_ID = 1234567L;
|
||||
private static final String TRACK_NAME = "Swimming across the pacific";
|
||||
|
||||
private MyTracksProviderUtils myTracksProviderUtils;
|
||||
private Factory oldProviderUtilsFactory;
|
||||
|
||||
private IMocksControl mocksControl;
|
||||
|
||||
private TrackWriter trackWriter;
|
||||
private Track[] tracks;
|
||||
private OutputStream outputStream;
|
||||
private FileTrackExporter fileTrackExporter;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
Context context = new MockContext(mockContentResolver, targetContext);
|
||||
MyTracksProvider myTracksProvider = new MyTracksProvider();
|
||||
myTracksProvider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider);
|
||||
setContext(context);
|
||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
oldProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(
|
||||
myTracksProviderUtils);
|
||||
|
||||
mocksControl = EasyMock.createStrictControl();
|
||||
trackWriter = mocksControl.createMock(TrackWriter.class);
|
||||
|
||||
Track track = new Track();
|
||||
track.setName(TRACK_NAME);
|
||||
track.setId(TRACK_ID);
|
||||
|
||||
tracks = new Track[] {track};
|
||||
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
TrackExporterListener trackExporterListener = new TrackExporterListener() {
|
||||
|
||||
@Override
|
||||
public void onProgressUpdate(int number, int max) {
|
||||
// Safe to ignore
|
||||
|
||||
}
|
||||
};
|
||||
fileTrackExporter = new FileTrackExporter(
|
||||
myTracksProviderUtils, tracks, trackWriter, trackExporterListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests write track with an empty track.
|
||||
*/
|
||||
public void testWriteTrack_emptyTrack() throws Exception {
|
||||
|
||||
// Set expected mock behavior
|
||||
trackWriter.prepare(outputStream);
|
||||
trackWriter.writeHeader(tracks);
|
||||
trackWriter.writeBeginTracks();
|
||||
trackWriter.writeBeginTrack(tracks[0], null);
|
||||
trackWriter.writeEndTrack(tracks[0], null);
|
||||
trackWriter.writeEndTracks();
|
||||
trackWriter.writeFooter();
|
||||
trackWriter.close();
|
||||
|
||||
mocksControl.replay();
|
||||
assertTrue(fileTrackExporter.writeTrack(outputStream));
|
||||
mocksControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests write track with invalid locations. Make sure an empty track is
|
||||
* written.
|
||||
*/
|
||||
public void testWriteTrack_oneInvalidLocation() throws Exception {
|
||||
|
||||
// Add two locations
|
||||
Location[] locations = { new Location("fake0"), new Location("fake1") };
|
||||
fillLocations(locations);
|
||||
|
||||
// Make locations invalid
|
||||
locations[0].setLatitude(100.0);
|
||||
locations[1].setLatitude(100.0);
|
||||
|
||||
assertEquals(locations.length,
|
||||
myTracksProviderUtils.bulkInsertTrackPoint(locations, locations.length, TRACK_ID));
|
||||
|
||||
// Set expected mock behavior
|
||||
trackWriter.prepare(outputStream);
|
||||
trackWriter.writeHeader(tracks);
|
||||
trackWriter.writeBeginTracks();
|
||||
trackWriter.writeBeginTrack(tracks[0], null);
|
||||
trackWriter.writeEndTrack(tracks[0], null);
|
||||
trackWriter.writeEndTracks();
|
||||
trackWriter.writeFooter();
|
||||
trackWriter.close();
|
||||
|
||||
mocksControl.replay();
|
||||
|
||||
assertTrue(fileTrackExporter.writeTrack(outputStream));
|
||||
mocksControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests write track.
|
||||
*/
|
||||
public void testWriteTrack() throws Exception {
|
||||
|
||||
// Add six locations
|
||||
Location[] locations = { new Location("fake0"), new Location("fake1"), new Location("fake2"),
|
||||
new Location("fake3"), new Location("fake4"), new Location("fake5") };
|
||||
fillLocations(locations);
|
||||
|
||||
// Make location 3 invalid
|
||||
locations[2].setLatitude(100.0);
|
||||
|
||||
assertEquals(locations.length,
|
||||
myTracksProviderUtils.bulkInsertTrackPoint(locations, locations.length, TRACK_ID));
|
||||
|
||||
Waypoint[] waypoints = { new Waypoint(), new Waypoint(), new Waypoint() };
|
||||
|
||||
for (int i = 0; i < waypoints.length; i++) {
|
||||
Waypoint waypoint = waypoints[i];
|
||||
waypoint.setTrackId(TRACK_ID);
|
||||
assertNotNull(myTracksProviderUtils.insertWaypoint(waypoint));
|
||||
waypoint.setId(i + 1);
|
||||
}
|
||||
|
||||
trackWriter.prepare(outputStream);
|
||||
trackWriter.writeHeader(tracks);
|
||||
|
||||
// Expect reading/writing of the waypoints (except the first)
|
||||
trackWriter.writeBeginWaypoints(tracks[0]);
|
||||
trackWriter.writeWaypoint(waypointEq(waypoints[1]));
|
||||
trackWriter.writeWaypoint(waypointEq(waypoints[2]));
|
||||
trackWriter.writeEndWaypoints();
|
||||
|
||||
// Begin the track
|
||||
trackWriter.writeBeginTracks();
|
||||
trackWriter.writeBeginTrack(trackEq(tracks[0]), locationEq(locations[0]));
|
||||
|
||||
// Write locations 1-2
|
||||
trackWriter.writeOpenSegment();
|
||||
trackWriter.writeLocation(locationEq(locations[0]));
|
||||
trackWriter.writeLocation(locationEq(locations[1]));
|
||||
trackWriter.writeCloseSegment();
|
||||
|
||||
// Location 3 is not written - it's invalid
|
||||
|
||||
// Write locations 4-6
|
||||
trackWriter.writeOpenSegment();
|
||||
trackWriter.writeLocation(locationEq(locations[3]));
|
||||
trackWriter.writeLocation(locationEq(locations[4]));
|
||||
trackWriter.writeLocation(locationEq(locations[5]));
|
||||
trackWriter.writeCloseSegment();
|
||||
|
||||
// End the track
|
||||
trackWriter.writeEndTrack(trackEq(tracks[0]), locationEq(locations[5]));
|
||||
trackWriter.writeEndTracks();
|
||||
|
||||
trackWriter.writeFooter();
|
||||
trackWriter.close();
|
||||
|
||||
mocksControl.replay();
|
||||
|
||||
assertTrue(fileTrackExporter.writeTrack(outputStream));
|
||||
mocksControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waypoint equals.
|
||||
*
|
||||
* @param waypoint the waypoint
|
||||
*/
|
||||
private Waypoint waypointEq(final Waypoint waypoint) {
|
||||
EasyMock.reportMatcher(new IArgumentMatcher() {
|
||||
@Override
|
||||
public boolean matches(Object object) {
|
||||
if (object == null || waypoint == null) {
|
||||
return waypoint == object;
|
||||
}
|
||||
Waypoint waypoint2 = (Waypoint) object;
|
||||
|
||||
return waypoint.getId() == waypoint2.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buffer) {
|
||||
buffer.append("waypointEq(");
|
||||
buffer.append(waypoint);
|
||||
buffer.append(")");
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location equals.
|
||||
*
|
||||
* @param location the location
|
||||
*/
|
||||
private Location locationEq(final Location location) {
|
||||
EasyMock.reportMatcher(new IArgumentMatcher() {
|
||||
@Override
|
||||
public boolean matches(Object object) {
|
||||
if (object == null || location == null) {
|
||||
return location == object;
|
||||
}
|
||||
Location location2 = (Location) object;
|
||||
|
||||
return location.hasAccuracy() == location2.hasAccuracy()
|
||||
&& (!location.hasAccuracy() || location.getAccuracy() == location2.getAccuracy())
|
||||
&& location.hasAltitude() == location2.hasAltitude()
|
||||
&& (!location.hasAltitude() || location.getAltitude() == location2.getAltitude())
|
||||
&& location.hasBearing() == location2.hasBearing()
|
||||
&& (!location.hasBearing() || location.getBearing() == location2.getBearing())
|
||||
&& location.hasSpeed() == location2.hasSpeed()
|
||||
&& (!location.hasSpeed() || location.getSpeed() == location2.getSpeed())
|
||||
&& location.getLatitude() == location2.getLatitude()
|
||||
&& location.getLongitude() == location2.getLongitude()
|
||||
&& location.getTime() == location2.getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buffer) {
|
||||
buffer.append("locationEq(");
|
||||
buffer.append(location);
|
||||
buffer.append(")");
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track equals.
|
||||
*
|
||||
* @param track1 the track
|
||||
*/
|
||||
private Track trackEq(final Track track1) {
|
||||
EasyMock.reportMatcher(new IArgumentMatcher() {
|
||||
@Override
|
||||
public boolean matches(Object object) {
|
||||
if (object == null || track1 == null) {
|
||||
return track1 == object;
|
||||
}
|
||||
Track track2 = (Track) object;
|
||||
|
||||
return track1.getName().equals(track2.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buffer) {
|
||||
buffer.append("trackEq(");
|
||||
buffer.append(track1);
|
||||
buffer.append(")");
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the locations.
|
||||
*
|
||||
* @param locations the locations
|
||||
*/
|
||||
private void fillLocations(Location... locations) {
|
||||
assertTrue(locations.length < 90);
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
Location location = locations[i];
|
||||
location.setLatitude(i + 1);
|
||||
location.setLongitude(i + 1);
|
||||
location.setTime(i + 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.io.file.exporter.GpxTrackWriter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Tests for {@link GpxTrackWriter}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class GpxTrackWriterTest extends TrackWriterTest {
|
||||
|
||||
public void testXmlOutput() throws Exception {
|
||||
GpxTrackWriter gpxTrackWriter = new GpxTrackWriter(getContext());
|
||||
String result = writeTrack(gpxTrackWriter);
|
||||
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"));
|
||||
List<Element> segmentTags = getChildElements(trackTag, "trkseg", 2);
|
||||
List<Element> segPointTags = getChildElements(segmentTags.get(0), "trkpt", 2);
|
||||
assertTagMatchesLocation(segPointTags.get(0), "0", "0", "1970-01-01T00:00:00.000Z", "0");
|
||||
assertTagMatchesLocation(segPointTags.get(1), "1", "-1", "1970-01-01T00:01:40.000Z", "10");
|
||||
|
||||
segPointTags = getChildElements(segmentTags.get(1), "trkpt", 2);
|
||||
assertTagMatchesLocation(segPointTags.get(0), "2", "-2", "1970-01-01T00:03:20.000Z", "20");
|
||||
assertTagMatchesLocation(segPointTags.get(1), "3", "-3", "1970-01-01T00:05:00.000Z", "30");
|
||||
|
||||
List<Element> waypointTags = getChildElements(gpxTag, "wpt", 2);
|
||||
Element wptTag = waypointTags.get(0);
|
||||
assertEquals(WAYPOINT1_NAME, getChildTextValue(wptTag, "name"));
|
||||
assertEquals(WAYPOINT1_DESCRIPTION, getChildTextValue(wptTag, "desc"));
|
||||
assertTagMatchesLocation(wptTag, "1", "-1", "1970-01-01T00:01:40.000Z", "10");
|
||||
|
||||
wptTag = waypointTags.get(1);
|
||||
assertEquals(WAYPOINT2_NAME, getChildTextValue(wptTag, "name"));
|
||||
assertEquals(WAYPOINT2_DESCRIPTION, getChildTextValue(wptTag, "desc"));
|
||||
assertTagMatchesLocation(wptTag, "2", "-2", "1970-01-01T00:03:20.000Z", "20");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given tag describes a location.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param latitude the location's latitude
|
||||
* @param longitude the location's longitude
|
||||
* @param time the location's time
|
||||
* @param elevation the location's elevation
|
||||
*/
|
||||
private void assertTagMatchesLocation(
|
||||
Element tag, String latitude, String longitude, String time, String elevation) {
|
||||
assertEquals(latitude, tag.getAttribute("lat"));
|
||||
assertEquals(longitude, tag.getAttribute("lon"));
|
||||
assertEquals(time, getChildTextValue(tag, "time"));
|
||||
assertEquals(elevation, getChildTextValue(tag, "ele"));
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.content.DescriptionGenerator;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Tests for {@link KmlTrackWriter}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class KmlTrackWriterTest extends TrackWriterTest {
|
||||
|
||||
private static final String FULL_TRACK_DESCRIPTION = "full track description";
|
||||
|
||||
/**
|
||||
* A fake version of {@link DescriptionGenerator} which returns a fixed track
|
||||
* description, thus not depending on the context.
|
||||
*/
|
||||
private class FakeDescriptionGenerator implements DescriptionGenerator {
|
||||
@Override
|
||||
public String generateTrackDescription(
|
||||
Track aTrack, Vector<Double> distances, Vector<Double> elevations, boolean html) {
|
||||
return FULL_TRACK_DESCRIPTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateWaypointDescription(TripStatistics tripStatistics) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testXmlOutput() throws Exception {
|
||||
KmlTrackWriter kmlTrackWriter = new KmlTrackWriter(
|
||||
getContext(), false, false, new FakeDescriptionGenerator());
|
||||
String result = writeTrack(kmlTrackWriter);
|
||||
Document doc = parseXmlDocument(result);
|
||||
|
||||
Element kmlTag = getChildElement(doc, "kml");
|
||||
Element docTag = getChildElement(kmlTag, "Document");
|
||||
assertEquals(TRACK_NAME, getChildTextValue(docTag, "name"));
|
||||
|
||||
// There are 3 placemarks - start, track, and end
|
||||
List<Element> placemarkTags = getChildElements(docTag, "Placemark", 3);
|
||||
assertTagIsPlacemark(
|
||||
placemarkTags.get(0), TRACK_NAME + " (Start)", "", location1);
|
||||
assertTagIsPlacemark(
|
||||
placemarkTags.get(2), TRACK_NAME + " (End)", FULL_TRACK_DESCRIPTION, location4);
|
||||
|
||||
List<Element> folderTag = getChildElements(docTag, "Folder", 1);
|
||||
List<Element> folderPlacemarkTags = getChildElements(folderTag.get(0), "Placemark", 2);
|
||||
assertTagIsPlacemark(
|
||||
folderPlacemarkTags.get(0), WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2);
|
||||
assertTagIsPlacemark(
|
||||
folderPlacemarkTags.get(1), WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3);
|
||||
|
||||
Element trackPlacemarkTag = placemarkTags.get(1);
|
||||
assertEquals(TRACK_NAME, getChildTextValue(trackPlacemarkTag, "name"));
|
||||
assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackPlacemarkTag, "description"));
|
||||
Element multiTrackTag = getChildElement(trackPlacemarkTag, "gx:MultiTrack");
|
||||
List<Element> trackTags = getChildElements(multiTrackTag, "gx:Track", 2);
|
||||
assertTagHasPoints(trackTags.get(0), location1, location2);
|
||||
assertTagHasPoints(trackTags.get(1), location3, location4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given tag is a placemark with the given properties.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param name the expected placemark name
|
||||
* @param description the expected placemark description
|
||||
* @param location the expected placemark location
|
||||
*/
|
||||
private void assertTagIsPlacemark(
|
||||
Element tag, String name, String description, Location location) {
|
||||
assertEquals(name, getChildTextValue(tag, "name"));
|
||||
if (description != null && !description.equals("")) {
|
||||
assertEquals(description, getChildTextValue(tag, "description"));
|
||||
}
|
||||
Element pointTag = getChildElement(tag, "Point");
|
||||
String expected = location.getLongitude() + "," + location.getLatitude() + ","
|
||||
+ location.getAltitude();
|
||||
String actual = getChildTextValue(pointTag, "coordinates");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given tag has a list of "gx:coord" subtags matching the
|
||||
* expected locations.
|
||||
*
|
||||
* @param tag the parent tag
|
||||
* @param locations list of expected locations
|
||||
*/
|
||||
private void assertTagHasPoints(Element tag, Location... locations) {
|
||||
List<Element> coordTags = getChildElements(tag, "gx:coord", locations.length);
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
Location location = locations[i];
|
||||
String expected = location.getLongitude() + " " + location.getLatitude() + " "
|
||||
+ location.getAltitude();
|
||||
String actual = coordTags.get(i).getFirstChild().getTextContent();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.io.file.exporter.TcxTrackWriter;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Tests for {@link TcxTrackWriter}.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class TcxTrackWriterTest extends TrackWriterTest {
|
||||
|
||||
public void testXmlOutput() throws Exception {
|
||||
TcxTrackWriter tcxTrackWriter = new TcxTrackWriter(getContext());
|
||||
String result = writeTrack(tcxTrackWriter);
|
||||
Document doc = parseXmlDocument(result);
|
||||
|
||||
Element root = getChildElement(doc, "TrainingCenterDatabase");
|
||||
Element activitiesTag = getChildElement(root, "Activities");
|
||||
Element activityTag = getChildElement(activitiesTag, "Activity");
|
||||
Element lapTag = getChildElement(activityTag, "Lap");
|
||||
|
||||
List<Element> segmentTags = getChildElements(lapTag, "Track", 2);
|
||||
Element segment1Tag = segmentTags.get(0);
|
||||
Element segment2Tag = segmentTags.get(1);
|
||||
List<Element> seg1PointTags = getChildElements(segment1Tag, "Trackpoint", 2);
|
||||
List<Element> seg2PointTags = getChildElements(segment2Tag, "Trackpoint", 2);
|
||||
assertTagsMatchPoints(seg1PointTags, location1, location2);
|
||||
assertTagsMatchPoints(seg2PointTags, location3, location4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given tags describe the given locations in the same order.
|
||||
*
|
||||
* @param tags list of tags
|
||||
* @param locations list of locations
|
||||
*/
|
||||
private void assertTagsMatchPoints(List<Element> tags, MyTracksLocation... locations) {
|
||||
assertEquals(locations.length, tags.size());
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
assertTagMatchesLocation(tags.get(i), locations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given tag describes the given location.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param location the location
|
||||
*/
|
||||
private void assertTagMatchesLocation(Element tag, MyTracksLocation location) {
|
||||
assertEquals(StringUtils.formatDateTimeIso8601(location.getTime()), getChildTextValue(tag, "Time"));
|
||||
|
||||
Element positionTag = getChildElement(tag, "Position");
|
||||
assertEquals(
|
||||
Double.toString(location.getLatitude()), getChildTextValue(positionTag, "LatitudeDegrees"));
|
||||
assertEquals(Double.toString(location.getLongitude()),
|
||||
getChildTextValue(positionTag, "LongitudeDegrees"));
|
||||
|
||||
assertEquals(Double.toString(location.getAltitude()), getChildTextValue(tag, "AltitudeMeters"));
|
||||
assertTrue(location.getSensorDataSet() != null);
|
||||
Sensor.SensorDataSet sds = location.getSensorDataSet();
|
||||
|
||||
List<Element> heartRate = getChildElements(tag, "HeartRateBpm", 1);
|
||||
assertEquals(Integer.toString(sds.getHeartRate().getValue()),
|
||||
getChildTextValue(heartRate.get(0), "Value"));
|
||||
|
||||
List<Element> extensions = getChildElements(tag, "Extensions", 1);
|
||||
List<Element> tpx = getChildElements(extensions.get(0), "TPX", 1);
|
||||
assertEquals(
|
||||
Integer.toString(sds.getCadence().getValue()), getChildTextValue(tpx.get(0), "RunCadence"));
|
||||
assertEquals(
|
||||
Integer.toString(sds.getPower().getValue()), getChildTextValue(tpx.get(0), "Watts"));
|
||||
}
|
||||
}
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
// Copyright 2010 Google Inc. All Rights Reserved.
|
||||
package com.google.android.apps.mytracks.io.file.exporter;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 TrackWriterTest 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_CATEGORY = "Hiking";
|
||||
protected static final String TRACK_DESCRIPTION = "The long ]]> journey home";
|
||||
protected static final String WAYPOINT1_NAME = "point]]>1";
|
||||
protected static final String WAYPOINT1_CATEGORY = "Statistics";
|
||||
protected static final String WAYPOINT1_DESCRIPTION = "point 1]]>description";
|
||||
protected static final String WAYPOINT2_NAME = "point]]>2";
|
||||
protected static final String WAYPOINT2_CATEGORY = "Waypoint";
|
||||
protected static final String WAYPOINT2_DESCRIPTION = "point 2]]>description";
|
||||
private static final int BUFFER_SIZE = 10240;
|
||||
protected Track track;
|
||||
protected MyTracksLocation location1, location2, location3, location4;
|
||||
protected Waypoint wp1, wp2;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
track = new Track();
|
||||
track.setName(TRACK_NAME);
|
||||
track.setCategory(TRACK_CATEGORY);
|
||||
track.setDescription(TRACK_DESCRIPTION);
|
||||
|
||||
location1 = new MyTracksLocation("mock");
|
||||
location2 = new MyTracksLocation("mock");
|
||||
location3 = new MyTracksLocation("mock");
|
||||
location4 = new MyTracksLocation("mock");
|
||||
populateLocations(location1, location2, location3, location4);
|
||||
|
||||
wp1 = new Waypoint();
|
||||
wp2 = new Waypoint();
|
||||
wp1.setLocation(location2);
|
||||
wp1.setName(WAYPOINT1_NAME);
|
||||
wp1.setCategory(WAYPOINT1_CATEGORY);
|
||||
wp1.setDescription(WAYPOINT1_DESCRIPTION);
|
||||
wp2.setLocation(location3);
|
||||
wp2.setName(WAYPOINT2_NAME);
|
||||
wp2.setCategory(WAYPOINT2_CATEGORY);
|
||||
wp2.setDescription(WAYPOINT2_DESCRIPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a list of locations with values.
|
||||
*
|
||||
* @param locations a list of locations
|
||||
*/
|
||||
private void populateLocations(MyTracksLocation... locations) {
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
MyTracksLocation location = locations[i];
|
||||
location.setLatitude(i);
|
||||
location.setLongitude(-i);
|
||||
location.setAltitude(i * 10);
|
||||
location.setBearing(i * 100);
|
||||
location.setAccuracy(i * 1000);
|
||||
location.setSpeed(i * 10000);
|
||||
location.setTime(i * 100000);
|
||||
Sensor.SensorData.Builder power = Sensor.SensorData.newBuilder().setValue(100 + i)
|
||||
.setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder cadence = Sensor.SensorData.newBuilder().setValue(200 + i)
|
||||
.setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorData.Builder heartRate = Sensor.SensorData.newBuilder().setValue(300 + i)
|
||||
.setState(Sensor.SensorState.SENDING);
|
||||
Sensor.SensorDataSet sensorDataSet = Sensor.SensorDataSet.newBuilder().setPower(power)
|
||||
.setCadence(cadence).setHeartRate(heartRate).build();
|
||||
location.setSensorDataSet(sensorDataSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the right sequence of calls to the writer in order to write the fake
|
||||
* track in {@link #track}.
|
||||
*
|
||||
* @param trackWriter the track writer
|
||||
* @return the written contents
|
||||
*/
|
||||
protected String writeTrack(TrackWriter trackWriter) throws Exception {
|
||||
OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE);
|
||||
trackWriter.prepare(output);
|
||||
trackWriter.writeHeader(new Track[] {track});
|
||||
trackWriter.writeBeginWaypoints(track);
|
||||
trackWriter.writeWaypoint(wp1);
|
||||
trackWriter.writeWaypoint(wp2);
|
||||
trackWriter.writeEndWaypoints();
|
||||
trackWriter.writeBeginTracks();
|
||||
trackWriter.writeBeginTrack(track, location1);
|
||||
trackWriter.writeOpenSegment();
|
||||
trackWriter.writeLocation(location1);
|
||||
trackWriter.writeLocation(location2);
|
||||
trackWriter.writeCloseSegment();
|
||||
trackWriter.writeOpenSegment();
|
||||
trackWriter.writeLocation(location3);
|
||||
trackWriter.writeLocation(location4);
|
||||
trackWriter.writeCloseSegment();
|
||||
trackWriter.writeEndTrack(track, location4);
|
||||
trackWriter.writeEndTracks();
|
||||
trackWriter.writeFooter();
|
||||
trackWriter.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 have 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;
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
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.TracksColumns;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.WaypointsColumns;
|
||||
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.SimpleTimeZone;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Abstract class for testing file track importers.
|
||||
*
|
||||
* @author Jimmy Shih.
|
||||
*/
|
||||
public class AbstractTestFileTrackImporter extends AndroidTestCase {
|
||||
|
||||
protected static final String TRACK_NAME_0 = "blablub";
|
||||
protected static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer";
|
||||
|
||||
protected static final String TRACK_NAME_1 = "another track";
|
||||
protected static final String TRACK_DESCRIPTION_1 = "another description";
|
||||
|
||||
protected static final double TRACK_LATITUDE = 48.768364;
|
||||
protected static final double TRACK_LONGITUDE = 9.177886;
|
||||
protected static final double TRACK_ELEVATION = 324.0;
|
||||
|
||||
protected static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z";
|
||||
protected static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123";
|
||||
protected static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123";
|
||||
protected static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123";
|
||||
|
||||
protected static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
|
||||
protected static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||
|
||||
static {
|
||||
/*
|
||||
* We can't omit the timezones in the test, otherwise it'll use the local
|
||||
* timezone and fail depending on where the test runner is.
|
||||
*/
|
||||
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
|
||||
DATE_FORMAT_0.setTimeZone(utc);
|
||||
DATE_FORMAT_1.setTimeZone(utc);
|
||||
}
|
||||
|
||||
protected static final long TRACK_ID_0 = 1;
|
||||
protected static final long TRACK_ID_1 = 2;
|
||||
protected static final long TRACK_POINT_ID_0 = 1;
|
||||
protected static final long TRACK_POINT_ID_1 = 2;
|
||||
protected static final long TRACK_POINT_ID_3 = 4;
|
||||
protected static final long WAYPOINT_ID_0 = 1;
|
||||
|
||||
protected static final Uri TRACK_ID_0_URI = ContentUris.appendId(
|
||||
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build();
|
||||
protected static final Uri TRACK_ID_1_URI = ContentUris.appendId(
|
||||
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_1).build();
|
||||
protected static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(
|
||||
WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
|
||||
|
||||
protected MyTracksProviderUtils myTracksProviderUtils;
|
||||
|
||||
private Factory oldMyTracksProviderUtilsFactory;
|
||||
|
||||
@UsesMocks(MyTracksProviderUtils.class)
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
|
||||
oldMyTracksProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(
|
||||
myTracksProviderUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TestingProviderUtilsFactory.restoreOldFactory(oldMyTracksProviderUtilsFactory);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected Location createLocation(int index, long time) {
|
||||
Location location = new Location(LocationManager.GPS_PROVIDER);
|
||||
location.setLatitude(TRACK_LATITUDE + index);
|
||||
location.setLongitude(TRACK_LONGITUDE + index);
|
||||
location.setAltitude(TRACK_ELEVATION + index);
|
||||
location.setTime(time);
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the first track point to be added.
|
||||
*
|
||||
* @param location the location
|
||||
* @param trackId the track id
|
||||
* @param trackPointId the track point id
|
||||
*/
|
||||
protected void expectFirstTrackPoint(Location location, long trackId, long trackPointId) {
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
location != null ? LocationsMatcher.eqLoc(location) : (Location[]) AndroidMock.anyObject(),
|
||||
eq(1), eq(trackId))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getFirstTrackPointId(trackId)).andReturn(trackPointId);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(trackId)).andReturn(trackPointId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the track to be updated.
|
||||
*
|
||||
* @param track the track
|
||||
* @param lastTrack true if it is the last track in the gpx
|
||||
* @param trackId the track id
|
||||
*/
|
||||
protected void expectUpdateTrack(Capture<Track> track, boolean lastTrack, long trackId) {
|
||||
myTracksProviderUtils.updateTrack(AndroidMock.capture(track));
|
||||
expect(myTracksProviderUtils.insertWaypoint((Waypoint) AndroidMock.anyObject()))
|
||||
.andReturn(WAYPOINT_ID_O_URI);
|
||||
if (lastTrack) {
|
||||
// Return null to not add waypoints
|
||||
expect(myTracksProviderUtils.getTrack(trackId)).andReturn(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyTrack(Track track, String name, String description, long time) {
|
||||
assertEquals(name, track.getName());
|
||||
assertEquals(description, track.getDescription());
|
||||
if (time != -1L) {
|
||||
assertEquals(time, track.getTripStatistics().getStartTime());
|
||||
}
|
||||
assertNotSame(-1, track.getStartId());
|
||||
assertNotSame(-1, track.getStopId());
|
||||
}
|
||||
}
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Tests for {@link GpxFileTrackImporter}.
|
||||
*
|
||||
* @author Steffen Horlacher
|
||||
*/
|
||||
public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
||||
|
||||
private static String getNameAndDescription(String name, String description) {
|
||||
return "<name><![CDATA[" + name + "]]></name>" + "<desc><![CDATA[" + description + "]]></desc>";
|
||||
}
|
||||
|
||||
private static String getTrackPoint(int index, String time) {
|
||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
||||
String elevation = Double.toString(TRACK_ELEVATION + index);
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(
|
||||
"<trkpt lat=\"" + latitude + "\" lon=\"" + longitude + "\"><ele>" + elevation + "</ele>");
|
||||
if (time != null) {
|
||||
buffer.append("<time>" + time + "</time>");
|
||||
}
|
||||
buffer.append("</trkpt>");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg><trkseg>"
|
||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + "</trkseg></trk></gpx>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "<gpx><trk>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
|
||||
+ getTrackPoint(0, null) + getTrackPoint(1, null) + "</trkseg><trkseg>"
|
||||
+ getTrackPoint(2, null) + getTrackPoint(3, null) + "</trkseg></trk></gpx>";
|
||||
|
||||
private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring(
|
||||
0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50);
|
||||
private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LATITUDE), "1000.0");
|
||||
private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
TRACK_TIME_0, "invalid");
|
||||
private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_ELEVATION), "invalid");
|
||||
private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LATITUDE), "invalid");
|
||||
private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
|
||||
Double.toString(TRACK_LONGITUDE), "invalid");
|
||||
|
||||
/**
|
||||
* Tests one track with one segment.
|
||||
*/
|
||||
public void testOneTrackOneSegment() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime());
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments.
|
||||
*/
|
||||
public void testOneTrackTwoSegments() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
||||
assertEquals(
|
||||
time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0,
|
||||
DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments, but no time in the track points.
|
||||
*/
|
||||
public void testOneTrackTwoSegmentsNoTime() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(
|
||||
VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
assertEquals(0, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid xml input.
|
||||
*/
|
||||
public void testInvalidXml() throws Exception {
|
||||
testInvalidGpx(INVALID_XML_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid location.
|
||||
*/
|
||||
public void testInvalidLocation() throws Exception {
|
||||
testInvalidGpx(INVALID_LOCATION_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid time.
|
||||
*/
|
||||
public void testInvalidTime() throws Exception {
|
||||
testInvalidGpx(INVALID_TIME_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid altitude.
|
||||
*/
|
||||
public void testInvalidAltitude() throws Exception {
|
||||
testInvalidGpx(INVALID_ALTITUDE_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid latitude.
|
||||
*/
|
||||
public void testInvalidLatitude() throws Exception {
|
||||
testInvalidGpx(INVALID_LATITUDE_GPX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test an invalid longitude.
|
||||
*/
|
||||
public void testInvalidLongitude() throws Exception {
|
||||
testInvalidGpx(INVALID_LONGITUDE_GPX);
|
||||
}
|
||||
|
||||
private void testInvalidGpx(String xml) throws Exception {
|
||||
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
|
||||
.andReturn(TRACK_ID_0_URI);
|
||||
|
||||
// For the following, use StubReturn since we don't care whether they are
|
||||
// invoked or not.
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), AndroidMock.anyInt(), AndroidMock.anyLong()))
|
||||
.andStubReturn(1);
|
||||
expect(myTracksProviderUtils.getFirstTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
myTracksProviderUtils.deleteTrack(getContext(), TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
|
||||
GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter(
|
||||
getContext(), myTracksProviderUtils);
|
||||
long trackId = gpxFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(-1L, trackId);
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.io.file.importer;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.easymock.Capture;
|
||||
|
||||
/**
|
||||
* Tests for {@link KmlFileTrackImporter}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter {
|
||||
|
||||
private static String getNameAndDescription(String name, String description) {
|
||||
return "<name><![CDATA[" + name + "]]></name><description><![CDATA[" + description
|
||||
+ "]]></description>";
|
||||
}
|
||||
|
||||
private static String getTrackPoint(int index, String time) {
|
||||
String latitude = Double.toString(TRACK_LATITUDE + index);
|
||||
String longitude = Double.toString(TRACK_LONGITUDE + index);
|
||||
String altitude = Double.toString(TRACK_ELEVATION + index);
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<when>" + time + "</when>" + "<gx:coord>" + longitude + " " + latitude + " "
|
||||
+ altitude + "</gx:coord>");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX =
|
||||
"<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1)
|
||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
||||
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX =
|
||||
"<kml xmlns:gx=\"http://www.google.com/kml/ext/2.2\"><Placemark>"
|
||||
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<gx:MultiTrack><gx:Track>"
|
||||
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</gx:Track><gx:Track>"
|
||||
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3)
|
||||
+ "</gx:Track></gx:MultiTrack></Placemark></kml>";
|
||||
|
||||
/**
|
||||
* Tests one track with one segment.
|
||||
*/
|
||||
public void testOneTrackOneSegment() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
|
||||
|
||||
myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(
|
||||
getContext(), TRACK_ID_0, myTracksProviderUtils);
|
||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime());
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests one track with two segments.
|
||||
*/
|
||||
public void testOneTrackTwoSegments() throws Exception {
|
||||
Capture<Track> track = new Capture<Track>();
|
||||
|
||||
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
|
||||
myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0);
|
||||
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
|
||||
|
||||
// A flush happens at the end
|
||||
expect(myTracksProviderUtils.bulkInsertTrackPoint(
|
||||
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
|
||||
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
|
||||
expect(
|
||||
myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(),
|
||||
R.string.recording_track_id_key))).andStubReturn(null);
|
||||
expectUpdateTrack(track, true, TRACK_ID_0);
|
||||
AndroidMock.replay(myTracksProviderUtils);
|
||||
|
||||
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
|
||||
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(
|
||||
getContext(), TRACK_ID_0, myTracksProviderUtils);
|
||||
long trackId = kmlFileTrackImporter.importFile(inputStream);
|
||||
assertEquals(TRACK_ID_0, trackId);
|
||||
|
||||
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
|
||||
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
|
||||
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
|
||||
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
|
||||
assertEquals(
|
||||
time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime());
|
||||
|
||||
AndroidMock.verify(myTracksProviderUtils);
|
||||
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0,
|
||||
DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.io.file.importer;
|
||||
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.easymock.IArgumentMatcher;
|
||||
|
||||
/**
|
||||
* Locations matcher. Workaround because of capture bug 2617107 in easymock:
|
||||
* http://sourceforge.net/tracker/?func=detail&aid=2617107&group_id=82958&atid=567837
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class LocationsMatcher implements IArgumentMatcher {
|
||||
|
||||
public static Location[] eqLoc(Location expected) {
|
||||
return eqLoc(new Location[] { expected });
|
||||
}
|
||||
|
||||
public static Location[] eqLoc(Location[] expected) {
|
||||
IArgumentMatcher matcher = new LocationsMatcher(expected);
|
||||
AndroidMock.reportMatcher(matcher);
|
||||
return null;
|
||||
}
|
||||
|
||||
private final Location[] expectedLocations;
|
||||
|
||||
private LocationsMatcher(Location[] expected) {
|
||||
this.expectedLocations = expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buf) {
|
||||
buf.append("eqLoc(").append(Arrays.toString(expectedLocations)).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object obj) {
|
||||
if (!(obj instanceof Location[])) {
|
||||
return false;
|
||||
}
|
||||
Location[] locations = (Location[]) obj;
|
||||
if (locations.length < expectedLocations.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only check the first elements (those that will be taken into account)
|
||||
for (int i = 0; i < expectedLocations.length; i++) {
|
||||
if (!matchLocation(locations[i], expectedLocations[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchLocation(Location location1, Location location2) {
|
||||
return (location1.getTime() == location2.getTime())
|
||||
&& (location1.getLatitude() == location2.getLatitude())
|
||||
&& (location1.getLongitude() == location2.getLongitude())
|
||||
&& (location1.getAltitude() == location2.getAltitude());
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.io.fusiontables;
|
||||
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests the {@link SendFusionTablesActivity}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SendFusionTablesActivityTest extends AndroidTestCase {
|
||||
|
||||
private SendFusionTablesActivity sendFusionTablesActivity;
|
||||
private SendRequest sendRequest;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
sendRequest = new SendRequest(1L);
|
||||
sendFusionTablesActivity = new SendFusionTablesActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to false and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelNotSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(false);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to true and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(SendSpreadsheetsActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to true and true.
|
||||
*/
|
||||
public void testGetNextClass_cancelSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
|
||||
* the flags of "sendSpreadsheets" and "cancel" to false and true.
|
||||
*/
|
||||
public void testGetNextClass_cancelNotSendSpreadsheets() {
|
||||
sendRequest.setSendSpreadsheets(false);
|
||||
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
}
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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.io.fusiontables;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SendFusionTablesUtilsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null track.
|
||||
*/
|
||||
public void testGetMapUrl_null_track() {
|
||||
assertEquals(null, SendFusionTablesUtils.getMapUrl(null, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null stats.
|
||||
*/
|
||||
public void testGetMapUrl_null_stats() {
|
||||
Track track = new Track();
|
||||
track.setTripStatistics(null);
|
||||
assertEquals(null, SendFusionTablesUtils.getMapUrl(track, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with a valid track.
|
||||
*/
|
||||
public void testGetMapUrl_valid_track() {
|
||||
Track track = new Track();
|
||||
track.setNumberOfPoints(2);
|
||||
TripStatistics stats = new TripStatistics();
|
||||
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
|
||||
track.setTripStatistics(stats);
|
||||
assertEquals(
|
||||
"https://www.google.com/fusiontables/embedviz?"
|
||||
+ "viz=MAP&q=select+col0,+col1,+col2,+col3+from+123+&h=false&lat=7.500000&lng=75.000000"
|
||||
+ "&z=15&t=1&l=col2", SendFusionTablesUtils.getMapUrl(track, "123"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* no value.
|
||||
*/
|
||||
public void testFormatSqlValues_no_value() {
|
||||
assertEquals("()", SendFusionTablesUtils.formatSqlValues());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* an empty string.
|
||||
*/
|
||||
public void testFormatSqlValues_empty_string() {
|
||||
assertEquals("(\'\')", SendFusionTablesUtils.formatSqlValues(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* one value.
|
||||
*/
|
||||
public void testFormatSqlValues_one_value() {
|
||||
assertEquals("(\'first\')", SendFusionTablesUtils.formatSqlValues("first"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with
|
||||
* two values.
|
||||
*/
|
||||
public void testFormatSqlValues_two_values() {
|
||||
assertEquals(
|
||||
"(\'first\',\'second\')", SendFusionTablesUtils.formatSqlValues("first", "second"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#escapeSqlString(String)} with a value
|
||||
* containing several single quotes.
|
||||
*/
|
||||
public void testEscapeSqValuel() {
|
||||
String value = "let's'";
|
||||
assertEquals("let''s''", SendFusionTablesUtils.escapeSqlString(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a null
|
||||
* point.
|
||||
*/
|
||||
public void testGetKmlPoint_null_point() {
|
||||
assertEquals(
|
||||
"<Point><coordinates></coordinates></Point>", SendFusionTablesUtils.getKmlPoint(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a valid
|
||||
* point.
|
||||
*/
|
||||
public void testGetKmlPoint_valid_point() {
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
assertEquals("<Point><coordinates>10.1,20.2,30.3</coordinates></Point>",
|
||||
SendFusionTablesUtils.getKmlPoint(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with a null
|
||||
* locations.
|
||||
*/
|
||||
public void testKmlLineString_null_locations() {
|
||||
assertEquals("<LineString><coordinates></coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with no
|
||||
* location.
|
||||
*/
|
||||
public void testKmlLineString_no_location() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
assertEquals("<LineString><coordinates></coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with one
|
||||
* location.
|
||||
*/
|
||||
public void testKmlLineString_one_location() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
locations.add(location);
|
||||
assertEquals("<LineString><coordinates>10.1,20.2,30.3</coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with two
|
||||
* locations.
|
||||
*/
|
||||
public void testKmlLineString_two_locations() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location1 = new Location("test");
|
||||
location1.setLongitude(10.1);
|
||||
location1.setLatitude(20.2);
|
||||
location1.setAltitude(30.3);
|
||||
locations.add(location1);
|
||||
|
||||
Location location2 = new Location("test");
|
||||
location2.setLongitude(1.1);
|
||||
location2.setLatitude(2.2);
|
||||
location2.removeAltitude();
|
||||
locations.add(location2);
|
||||
|
||||
assertEquals("<LineString><coordinates>10.1,20.2,30.3 1.1,2.2</coordinates></LineString>",
|
||||
SendFusionTablesUtils.getKmlLineString(locations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)}
|
||||
* with no altitude.
|
||||
*/
|
||||
public void testAppendLocation_no_altitude() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.removeAltitude();
|
||||
SendFusionTablesUtils.appendLocation(location, builder);
|
||||
assertEquals("10.1,20.2", builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)}
|
||||
* with altitude.
|
||||
*/
|
||||
public void testAppendLocation_has_altitude() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Location location = new Location("test");
|
||||
location.setLongitude(10.1);
|
||||
location.setLatitude(20.2);
|
||||
location.setAltitude(30.3);
|
||||
SendFusionTablesUtils.appendLocation(location, builder);
|
||||
assertEquals("10.1,20.2,30.3", builder.toString());
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.io.maps;
|
||||
|
||||
import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
|
||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests the {@link SendMapsActivity}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SendMapsActivityTest extends AndroidTestCase {
|
||||
|
||||
private SendMapsActivity sendMapsActivity;
|
||||
private SendRequest sendRequest;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
sendRequest = new SendRequest(1L);
|
||||
sendMapsActivity = new SendMapsActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelSendFusionTables() {
|
||||
sendRequest.setSendFusionTables(true);
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(SendFusionTablesActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to false, true and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelSendSpreadsheets() {
|
||||
sendRequest.setSendFusionTables(false);
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(SendSpreadsheetsActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to false, false and false.
|
||||
*/
|
||||
public void testGetNextClass_notCancelNotSend() {
|
||||
sendRequest.setSendFusionTables(false);
|
||||
sendRequest.setSendSpreadsheets(false);
|
||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
|
||||
* of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and true.
|
||||
*/
|
||||
public void testGetNextClass_cancelSendSpreadsheets() {
|
||||
sendRequest.setSendFusionTables(true);
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
Class<?> next = sendMapsActivity.getNextClass(sendRequest, true);
|
||||
assertEquals(UploadResultActivity.class, next);
|
||||
}
|
||||
|
||||
}
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* 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.io.maps;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* Tests {@link SendMapsAsyncTask}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SendMapsAsyncTaskTest extends AndroidTestCase {
|
||||
|
||||
private static final long TRACK_ID = 1;
|
||||
// Records the run times of {@link SendMapsAsyncTaskMock#uploadMarker(String,
|
||||
// String, String, Location)}
|
||||
private int uploadMarkerCounter = 0;
|
||||
// Records the run times of {@link
|
||||
// SendMapsAsyncTaskMock#prepareAndUploadPoints(Track, List<Location>,
|
||||
// boolean)}
|
||||
private int prepareAndUploadPointsCounter = 0;
|
||||
|
||||
private SendMapsActivity sendMapsActivityMock;
|
||||
private MyTracksProviderUtils myTracksProviderUtilsMock;
|
||||
private SendRequest sendRequest;
|
||||
|
||||
private class SendMapsAsyncTaskMock extends SendMapsAsyncTask {
|
||||
|
||||
private boolean[] uploadMarkerResult = { false, false };
|
||||
private boolean prepareAndUploadPointsResult = false;
|
||||
|
||||
private SendMapsAsyncTaskMock(SendMapsActivity activity, long trackId, Account account,
|
||||
MyTracksProviderUtils myTracksProviderUtils) {
|
||||
super(activity, trackId, account, myTracksProviderUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean uploadMarker(String title, String description, String iconUrl, Location location) {
|
||||
int runTimes = uploadMarkerCounter++;
|
||||
return uploadMarkerResult[runTimes];
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean prepareAndUploadPoints(Track track, List<Location> locations, boolean lastBatch) {
|
||||
prepareAndUploadPointsCounter++;
|
||||
return prepareAndUploadPointsResult;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@UsesMocks({ SendMapsActivity.class, MyTracksProviderUtils.class })
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
uploadMarkerCounter = 0;
|
||||
prepareAndUploadPointsCounter = 0;
|
||||
sendMapsActivityMock = AndroidMock.createMock(SendMapsActivity.class);
|
||||
myTracksProviderUtilsMock = AndroidMock.createMock(MyTracksProviderUtils.class);
|
||||
sendRequest = new SendRequest(TRACK_ID);
|
||||
AndroidMock.expect(sendMapsActivityMock.getApplicationContext()).andReturn(getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendMapsAsyncTask#fetchSendMapId(Track)} when chooseMapId is
|
||||
* null and makes sure it returns false.
|
||||
*/
|
||||
public void testFetchSendMapId_nullMapID() {
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
|
||||
// Makes chooseMapId to null.
|
||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
// Returns false for an exception would be thrown.
|
||||
assertFalse(sendMapsAsyncTask.fetchSendMapId(track));
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
||||
* the location iterator has no item. And makes sure it returns true.
|
||||
*/
|
||||
public void testUploadAllTrackPoints_empptyLocationIterator() {
|
||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
||||
locationIterator.close();
|
||||
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
||||
.andReturn(locationIterator);
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
||||
* uploads the first marker is failed.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadAllTrackPoints_uploadFirstMarkerFailed() {
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
|
||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true);
|
||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1"));
|
||||
locationIterator.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
||||
.andReturn(locationIterator);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
sendMapsAsyncTask.uploadMarkerResult[0] = false;
|
||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
||||
assertEquals(1, uploadMarkerCounter);
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
||||
* uploads the two markers is successful but failed when
|
||||
* prepareAndUploadPoints.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadAllTrackPoints_prepareAndUploadPointsFailed() {
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
|
||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
||||
locationIterator.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
||||
.andReturn(locationIterator);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
// For will be failed when run prepareAndUploadPoints, it no require to
|
||||
// set uploadMarkerResult[1].
|
||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
||||
sendMapsAsyncTask.prepareAndUploadPointsResult = false;
|
||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
||||
assertEquals(1, uploadMarkerCounter);
|
||||
assertEquals(1, prepareAndUploadPointsCounter);
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
||||
* uploads the last marker is failed.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadAllTrackPoints_uploadLastMarkerFailed() {
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
|
||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
||||
locationIterator.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
||||
.andReturn(locationIterator);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
||||
sendMapsAsyncTask.uploadMarkerResult[1] = false;
|
||||
sendMapsAsyncTask.prepareAndUploadPointsResult = true;
|
||||
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
||||
assertEquals(2, uploadMarkerCounter);
|
||||
assertEquals(1, prepareAndUploadPointsCounter);
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
|
||||
* return true.a
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadAllTrackPoints_success() {
|
||||
Track track = TrackStubUtils.createTrack(1);
|
||||
|
||||
LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2);
|
||||
AndroidMock.expect(locationIterator.hasNext()).andReturn(false);
|
||||
AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2);
|
||||
locationIterator.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator(
|
||||
TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY))
|
||||
.andReturn(locationIterator);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
sendMapsAsyncTask.uploadMarkerResult[0] = true;
|
||||
sendMapsAsyncTask.uploadMarkerResult[1] = true;
|
||||
sendMapsAsyncTask.prepareAndUploadPointsResult = true;
|
||||
assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track));
|
||||
assertEquals(2, uploadMarkerCounter);
|
||||
assertEquals(1, prepareAndUploadPointsCounter);
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when cursor is
|
||||
* null.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadWaypoints_nullCursor() {
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(null);
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
|
||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
assertTrue(sendMapsAsyncTask.uploadWaypoints());
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when there is
|
||||
* only one point.
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadWaypoints_onePoint() {
|
||||
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
|
||||
AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true);
|
||||
// Only one point, so next is null.
|
||||
AndroidMock.expect(cursorMock.moveToNext()).andReturn(false);
|
||||
cursorMock.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
|
||||
assertTrue(sendMapsAsyncTask.uploadWaypoints());
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()}. Makes sure a
|
||||
* cursor is created and a way point is created with such cursor.
|
||||
*
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
@UsesMocks(Cursor.class)
|
||||
public void testUploadWaypoints() throws XmlPullParserException {
|
||||
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
|
||||
MapsGDataConverter mapsGDataConverterMock = new MapsGDataConverter();
|
||||
|
||||
AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true);
|
||||
AndroidMock.expect(cursorMock.moveToNext()).andReturn(true);
|
||||
cursorMock.close();
|
||||
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor(
|
||||
TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
|
||||
Waypoint waypoint = new Waypoint();
|
||||
waypoint.setLocation(TrackStubUtils.createMyTracksLocation());
|
||||
AndroidMock.expect(myTracksProviderUtilsMock.createWaypoint(cursorMock))
|
||||
.andReturn(waypoint).times(1);
|
||||
|
||||
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
||||
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
|
||||
sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock);
|
||||
sendMapsAsyncTask.setMapsGDataConverter(mapsGDataConverterMock);
|
||||
// Would be failed for there is no source for uploading.
|
||||
assertFalse(sendMapsAsyncTask.uploadWaypoints());
|
||||
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendMapsAsyncTask#getPercentage(int, int)}.
|
||||
*/
|
||||
public void testCountPercentage() {
|
||||
assertEquals(SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN, SendMapsAsyncTask.getPercentage(0, 5));
|
||||
assertEquals(
|
||||
SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX, SendMapsAsyncTask.getPercentage(50, 50));
|
||||
assertEquals((int) ((double) 5 / 11
|
||||
* (SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX - SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN)
|
||||
+ SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN), SendMapsAsyncTask.getPercentage(5, 11));
|
||||
}
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.io.maps;
|
||||
|
||||
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SendMapsUtils}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SendMapsUtilsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
||||
* Location)} with a title.
|
||||
*/
|
||||
public void testBuildMapsMarkerFeature_with_title() {
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(123.0);
|
||||
location.setLongitude(456.0);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
||||
"name", "this\nmap\ndescription", "url", location);
|
||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("name", mapFeature.getTitle());
|
||||
assertEquals("this<br>map<br>description", mapFeature.getDescription());
|
||||
assertEquals("url", mapFeature.getIconUrl());
|
||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
||||
* Location)} with an empty title.
|
||||
*/
|
||||
public void testBuildMapsMarkerFeature_empty_title() {
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(123.0);
|
||||
location.setLongitude(456.0);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
||||
"", "description", "url", location);
|
||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("-", mapFeature.getTitle());
|
||||
assertEquals("description", mapFeature.getDescription());
|
||||
assertEquals("url", mapFeature.getIconUrl());
|
||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
|
||||
* Location)} with a null title.
|
||||
*/
|
||||
public void testBuildMapsMarkerFeature_null_title() {
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(123.0);
|
||||
location.setLongitude(456.0);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
|
||||
null, "description", "url", location);
|
||||
assertEquals(MapsFeature.MARKER, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("-", mapFeature.getTitle());
|
||||
assertEquals("description", mapFeature.getDescription());
|
||||
assertEquals("url", mapFeature.getIconUrl());
|
||||
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
|
||||
* title.
|
||||
*/
|
||||
public void testBuildMapsLineFeature_with_title() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(50.0);
|
||||
location.setLongitude(100.0);
|
||||
locations.add(location);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("name", locations);
|
||||
|
||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("name", mapFeature.getTitle());
|
||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with an
|
||||
* empty title.
|
||||
*/
|
||||
public void testBuildMapsLineFeature_empty_title() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(50.0);
|
||||
location.setLongitude(100.0);
|
||||
locations.add(location);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("", locations);
|
||||
|
||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("-", mapFeature.getTitle());
|
||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
|
||||
* null title.
|
||||
*/
|
||||
public void testBuildMapsLineFeature_null_title() {
|
||||
ArrayList<Location> locations = new ArrayList<Location>();
|
||||
Location location = new Location("test");
|
||||
location.setLatitude(50.0);
|
||||
location.setLongitude(100.0);
|
||||
locations.add(location);
|
||||
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature(null, locations);
|
||||
|
||||
assertEquals(MapsFeature.LINE, mapFeature.getType());
|
||||
assertNotNull(mapFeature.getAndroidId());
|
||||
assertEquals("-", mapFeature.getTitle());
|
||||
assertEquals(0x80FF0000, mapFeature.getColor());
|
||||
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
|
||||
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
|
||||
}
|
||||
}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* 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.io.sendtogoogle;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests the {@link SendRequest}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class SendRequestTest extends AndroidTestCase {
|
||||
|
||||
private SendRequest sendRequest;
|
||||
|
||||
private final static String ACCOUNTNAME = "testAccount1";
|
||||
private final static String ACCOUNTYPE = "testType1";
|
||||
private final static String DRIVE_SHARE_EMAILS = "foo@foo.com";
|
||||
private final static String SHARE_URL = "url@url.com";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
sendRequest = new SendRequest(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#getTrackId()}. The value should be set
|
||||
* to 1 when it is initialed in setup method.
|
||||
*/
|
||||
public void testGetTrackId() {
|
||||
assertEquals(1, sendRequest.getTrackId());
|
||||
}
|
||||
|
||||
public void testIsSendMaps() {
|
||||
assertEquals(false, sendRequest.isSendMaps());
|
||||
sendRequest.setSendMaps(true);
|
||||
assertEquals(true, sendRequest.isSendMaps());
|
||||
}
|
||||
|
||||
public void testIsSendFusionTables() {
|
||||
assertEquals(false, sendRequest.isSendFusionTables());
|
||||
sendRequest.setSendFusionTables(true);
|
||||
assertEquals(true, sendRequest.isSendFusionTables());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#isSendSpreadsheets()}. The value should
|
||||
* be set to false which is its default value when it is initialed in setup
|
||||
* method.
|
||||
*/
|
||||
public void testIsSendSpreadsheets() {
|
||||
assertEquals(false, sendRequest.isSendSpreadsheets());
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
assertEquals(true, sendRequest.isSendSpreadsheets());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#getAccount()}. The value should be set
|
||||
* to null which is its default value when it is initialed in setup method.
|
||||
*/
|
||||
public void testGetAccount() {
|
||||
assertEquals(null, sendRequest.getAccount());
|
||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
||||
sendRequest.setAccount(account);
|
||||
assertEquals(account, sendRequest.getAccount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#isMapsSuccess()}. The value should be
|
||||
* set to false which is its default value when it is initialed in setup
|
||||
* method.
|
||||
*/
|
||||
public void testIsMapsSuccess() {
|
||||
assertEquals(false, sendRequest.isMapsSuccess());
|
||||
sendRequest.setMapsSuccess(true);
|
||||
assertEquals(true, sendRequest.isMapsSuccess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#isFusionTablesSuccess()}. The value
|
||||
* should be set to false which is its default value when it is initialed in
|
||||
* setup method.
|
||||
*/
|
||||
public void testIsFusionTablesSuccess() {
|
||||
assertEquals(false, sendRequest.isFusionTablesSuccess());
|
||||
sendRequest.setFusionTablesSuccess(true);
|
||||
assertEquals(true, sendRequest.isFusionTablesSuccess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link SendRequest#isSpreadsheetsSuccess()}. The value
|
||||
* should be set to false which is its default value when it is initialed in
|
||||
* setup method.
|
||||
*/
|
||||
public void testIsSpreadsheetsSuccess() {
|
||||
assertEquals(false, sendRequest.isSpreadsheetsSuccess());
|
||||
sendRequest.setSpreadsheetsSuccess(true);
|
||||
assertEquals(true, sendRequest.isSpreadsheetsSuccess());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SendRequest.CREATOR.createFromParcel when all values are true.
|
||||
*/
|
||||
public void testCreateFromParcel_true() {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.setDataPosition(0);
|
||||
parcel.writeLong(2);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeString(DRIVE_SHARE_EMAILS);
|
||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
||||
parcel.writeParcelable(account, 0);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeByte((byte) 1);
|
||||
parcel.writeString(SHARE_URL);
|
||||
parcel.setDataPosition(0);
|
||||
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
|
||||
assertEquals(2, sendRequest.getTrackId());
|
||||
assertTrue(sendRequest.isSendDrive());
|
||||
assertTrue(sendRequest.isSendMaps());
|
||||
assertTrue(sendRequest.isSendFusionTables());
|
||||
assertTrue(sendRequest.isSendSpreadsheets());
|
||||
assertTrue(sendRequest.isDriveSync());
|
||||
assertTrue(sendRequest.isDriveSharePublic());
|
||||
assertEquals(DRIVE_SHARE_EMAILS, sendRequest.getDriveShareEmails());
|
||||
assertEquals(account, sendRequest.getAccount());
|
||||
assertTrue(sendRequest.isDriveSuccess());
|
||||
assertTrue(sendRequest.isMapsSuccess());
|
||||
assertTrue(sendRequest.isFusionTablesSuccess());
|
||||
assertTrue(sendRequest.isSpreadsheetsSuccess());
|
||||
assertEquals(SHARE_URL, sendRequest.getShareUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SendRequest.CREATOR.createFromParcel when all values are false.
|
||||
*/
|
||||
public void testCreateFromParcel_false() {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.setDataPosition(0);
|
||||
parcel.writeLong(4);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeString(null);
|
||||
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
|
||||
parcel.writeParcelable(account, 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeByte((byte) 0);
|
||||
parcel.writeString(null);
|
||||
parcel.setDataPosition(0);
|
||||
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
|
||||
assertEquals(4, sendRequest.getTrackId());
|
||||
assertFalse(sendRequest.isSendDrive());
|
||||
assertFalse(sendRequest.isSendMaps());
|
||||
assertFalse(sendRequest.isSendFusionTables());
|
||||
assertFalse(sendRequest.isSendSpreadsheets());
|
||||
assertFalse(sendRequest.isDriveSync());
|
||||
assertFalse(sendRequest.isDriveSharePublic());
|
||||
assertNull(sendRequest.getDriveShareEmails());
|
||||
assertEquals(account, sendRequest.getAccount());
|
||||
assertFalse(sendRequest.isDriveSuccess());
|
||||
assertFalse(sendRequest.isMapsSuccess());
|
||||
assertFalse(sendRequest.isFusionTablesSuccess());
|
||||
assertFalse(sendRequest.isSpreadsheetsSuccess());
|
||||
assertNull(sendRequest.getShareUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendRequest#writeToParcel(Parcel, int)} with default values.
|
||||
*/
|
||||
public void testWriteToParcel_default() {
|
||||
sendRequest = new SendRequest(1);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.setDataPosition(0);
|
||||
sendRequest.writeToParcel(parcel, 1);
|
||||
parcel.setDataPosition(0);
|
||||
long trackId = parcel.readLong();
|
||||
boolean sendDrive = parcel.readByte() == 1;
|
||||
boolean sendMaps = parcel.readByte() == 1;
|
||||
boolean sendFusionTables = parcel.readByte() == 1;
|
||||
boolean sendSpreadsheets = parcel.readByte() == 1;
|
||||
boolean driveSync = parcel.readByte() == 1;
|
||||
boolean driveSharePublic = parcel.readByte() == 1;
|
||||
String dirveShareEmails = parcel.readString();
|
||||
Parcelable account = parcel.readParcelable(null);
|
||||
boolean driveSuccess = parcel.readByte() == 1;
|
||||
boolean mapsSuccess = parcel.readByte() == 1;
|
||||
boolean fusionTablesSuccess = parcel.readByte() == 1;
|
||||
boolean spreadsheetsSuccess = parcel.readByte() == 1;
|
||||
String shareUrl = parcel.readString();
|
||||
assertEquals(1, trackId);
|
||||
assertFalse(sendDrive);
|
||||
assertFalse(sendMaps);
|
||||
assertFalse(sendFusionTables);
|
||||
assertFalse(sendSpreadsheets);
|
||||
assertFalse(driveSync);
|
||||
assertFalse(driveSharePublic);
|
||||
assertNull(dirveShareEmails);
|
||||
assertNull(account);
|
||||
assertFalse(driveSuccess);
|
||||
assertFalse(mapsSuccess);
|
||||
assertFalse(fusionTablesSuccess);
|
||||
assertFalse(spreadsheetsSuccess);
|
||||
assertNull(shareUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendRequest#writeToParcel(Parcel, int)}.
|
||||
*/
|
||||
public void testWriteToParcel() {
|
||||
sendRequest = new SendRequest(4);
|
||||
sendRequest.setSendDrive(true);
|
||||
sendRequest.setSendMaps(true);
|
||||
sendRequest.setSendFusionTables(true);
|
||||
sendRequest.setSendSpreadsheets(true);
|
||||
sendRequest.setDriveSync(true);
|
||||
sendRequest.setDriveSharePublic(true);
|
||||
sendRequest.setDriveShareEmails(DRIVE_SHARE_EMAILS);
|
||||
Account accountNew = new Account(ACCOUNTNAME + "2", ACCOUNTYPE + "2");
|
||||
sendRequest.setAccount(accountNew);
|
||||
sendRequest.setMapsSuccess(true);
|
||||
sendRequest.setDriveSuccess(true);
|
||||
sendRequest.setFusionTablesSuccess(true);
|
||||
sendRequest.setSpreadsheetsSuccess(true);
|
||||
sendRequest.setShareUrl(SHARE_URL);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.setDataPosition(0);
|
||||
sendRequest.writeToParcel(parcel, 1);
|
||||
parcel.setDataPosition(0);
|
||||
long trackId = parcel.readLong();
|
||||
boolean sendDrive = parcel.readByte() == 1;
|
||||
boolean sendMaps = parcel.readByte() == 1;
|
||||
boolean sendFusionTables = parcel.readByte() == 1;
|
||||
boolean sendSpreadsheets = parcel.readByte() == 1;
|
||||
boolean driveSync = parcel.readByte() == 1;
|
||||
boolean driveSharePublic = parcel.readByte() == 1;
|
||||
String driveShareEmails = parcel.readString();
|
||||
Parcelable account = parcel.readParcelable(null);
|
||||
boolean driveSuccess = parcel.readByte() == 1;
|
||||
boolean mapsSuccess = parcel.readByte() == 1;
|
||||
boolean fusionTablesSuccess = parcel.readByte() == 1;
|
||||
boolean spreadsheetsSuccess = parcel.readByte() == 1;
|
||||
String shareUrl = parcel.readString();
|
||||
assertEquals(4, trackId);
|
||||
assertTrue(sendDrive);
|
||||
assertTrue(sendMaps);
|
||||
assertTrue(sendFusionTables);
|
||||
assertTrue(sendSpreadsheets);
|
||||
assertTrue(driveSync);
|
||||
assertTrue(driveSharePublic);
|
||||
assertEquals(DRIVE_SHARE_EMAILS, driveShareEmails);
|
||||
assertEquals(accountNew, account);
|
||||
assertTrue(driveSuccess);
|
||||
assertTrue(mapsSuccess);
|
||||
assertTrue(fusionTablesSuccess);
|
||||
assertTrue(spreadsheetsSuccess);
|
||||
assertEquals(SHARE_URL, shareUrl);
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.io.sendtogoogle;
|
||||
|
||||
/**
|
||||
* Tests the {@link SendToGoogleUtils}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
import com.google.android.apps.mytracks.TrackStubUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SendToGoogleUtilsTest extends TestCase {
|
||||
|
||||
private final static long TRACK_ID = 1L;
|
||||
private final static String TRACK_CATEGORY = "trackCategory";
|
||||
private final static String TRACK_NAME = "trackName";
|
||||
private final static double DIFFERENCE = 0.02;
|
||||
private final static double INVALID_LATITUDE = 91;
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)}
|
||||
* when there is only one location in a segment.
|
||||
*/
|
||||
public void testPrepareTrackSegment_onlyOneLocation() {
|
||||
Track segment = TrackStubUtils.createTrack(1);
|
||||
assertFalse(SendToGoogleUtils.endSegment(segment, -1L, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)} when there
|
||||
* is no stop time.
|
||||
*/
|
||||
public void testPrepareTrackSegment_noStopTime() {
|
||||
Track segment = TrackStubUtils.createTrack(2);
|
||||
assertEquals(-1L, segment.getTripStatistics().getStopTime());
|
||||
|
||||
ArrayList<Track> tracksArray = new ArrayList<Track>();
|
||||
assertTrue(SendToGoogleUtils.endSegment(
|
||||
segment, segment.getLocations().get(1).getTime(), tracksArray));
|
||||
assertEquals(segment, tracksArray.get(0));
|
||||
// The stop time should be the time of last location
|
||||
assertEquals(
|
||||
segment.getLocations().get(1).getTime(), segment.getTripStatistics().getStopTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link SendToGoogleUtils#prepareLocations(Track, java.util.List)} .
|
||||
*/
|
||||
public void testPrepareLocations() {
|
||||
Track trackStub = TrackStubUtils.createTrack(2);
|
||||
trackStub.setId(TRACK_ID);
|
||||
trackStub.setName(TRACK_NAME);
|
||||
trackStub.setCategory(TRACK_CATEGORY);
|
||||
|
||||
List<Location> locationsArray = new ArrayList<Location>();
|
||||
// Adds 100 location to List.
|
||||
for (int i = 0; i < 100; i++) {
|
||||
// Use this variable as a flag to make all points in the track can be kept
|
||||
// after run the LocationUtils#decimate(Track, double) with
|
||||
// Ramer–Douglas–Peucker algorithm.
|
||||
double latitude = TrackStubUtils.INITIAL_LATITUDE;
|
||||
if (i % 2 == 0) {
|
||||
latitude -= DIFFERENCE * (i % 10);
|
||||
}
|
||||
// Inserts 9 points which have wrong latitude, so would have 10 segments.
|
||||
if (i % 10 == 0 && i > 0) {
|
||||
MyTracksLocation location = TrackStubUtils.createMyTracksLocation();
|
||||
location.setLatitude(INVALID_LATITUDE);
|
||||
locationsArray.add(location);
|
||||
} else {
|
||||
locationsArray.add(TrackStubUtils.createMyTracksLocation(latitude,
|
||||
TrackStubUtils.INITIAL_LONGITUDE + DIFFERENCE * (i % 10),
|
||||
TrackStubUtils.INITIAL_ALTITUDE + DIFFERENCE * (i % 10)));
|
||||
}
|
||||
}
|
||||
ArrayList<Track> result = SendToGoogleUtils.prepareLocations(trackStub, locationsArray);
|
||||
assertEquals(10, result.size());
|
||||
// Checks all segments.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Track segmentOne = result.get(i);
|
||||
assertEquals(TRACK_ID, segmentOne.getId());
|
||||
assertEquals(TRACK_NAME, segmentOne.getName());
|
||||
assertEquals(TRACK_CATEGORY, segmentOne.getCategory());
|
||||
}
|
||||
// Checks all locations in the first segment.
|
||||
for (int j = 0; j < 9; j++) {
|
||||
double latitude = TrackStubUtils.INITIAL_LATITUDE;
|
||||
if (j % 2 == 0) {
|
||||
latitude -= DIFFERENCE * (j % 10);
|
||||
}
|
||||
Location oneLocation = result.get(0).getLocations().get(j);
|
||||
assertEquals(TrackStubUtils.createMyTracksLocation().getAltitude() + DIFFERENCE * (j % 10),
|
||||
oneLocation.getAltitude());
|
||||
assertEquals(latitude, oneLocation.getLatitude());
|
||||
assertEquals(TrackStubUtils.createMyTracksLocation().getLongitude() + DIFFERENCE * (j % 10),
|
||||
oneLocation.getLongitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.io.spreadsheets;
|
||||
|
||||
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsUtils;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils}.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SendSpreadsheetsUtilsTest extends AndroidTestCase {
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with metric units.
|
||||
*/
|
||||
public void testGetDistance_metric() {
|
||||
assertEquals("1.22", SendSpreadsheetsUtils.getDistance(1222.3, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with imperial
|
||||
* units.
|
||||
*/
|
||||
public void testGetDistance_imperial() {
|
||||
assertEquals("0.76", SendSpreadsheetsUtils.getDistance(1222.3, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with metric units.
|
||||
*/
|
||||
public void testGetSpeed_metric() {
|
||||
assertEquals("15.55", SendSpreadsheetsUtils.getSpeed(4.32, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with imperial units.
|
||||
*/
|
||||
public void testGetSpeed_imperial() {
|
||||
assertEquals("9.66", SendSpreadsheetsUtils.getSpeed(4.32, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with metric
|
||||
* units.
|
||||
*/
|
||||
public void testGetElevation_metric() {
|
||||
assertEquals("3", SendSpreadsheetsUtils.getElevation(3.456, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with imperial
|
||||
* units.
|
||||
*/
|
||||
public void testGetElevation_imperial() {
|
||||
assertEquals("11", SendSpreadsheetsUtils.getElevation(3.456, false));
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.maps;
|
||||
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for the {@link DynamicSpeedTrackPathDescriptor}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class DynamicSpeedTrackPathDescriptorTest extends AndroidTestCase {
|
||||
|
||||
private Context context;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link DynamicSpeedTrackPathDescriptor#getSpeedMargin()}
|
||||
* with zero, normal and illegal value.
|
||||
*/
|
||||
public void testGetSpeedMargin() {
|
||||
// The default value of speedMargin is 25.
|
||||
int[] expectations = { 0, 50, 99, 25 };
|
||||
// Test
|
||||
for (int i = 0; i < expectations.length; i++) {
|
||||
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, expectations[i]);
|
||||
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
|
||||
context);
|
||||
assertEquals(expectations[i], dynamicSpeedTrackPathDescriptor.getSpeedMargin());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DynamicSpeedTrackPathDescriptor#getSlowSpeed()}.
|
||||
*/
|
||||
public void testGetSlowSpeed() {
|
||||
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
|
||||
context);
|
||||
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
|
||||
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
|
||||
assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
|
||||
assertEquals(45.0, dynamicSpeedTrackPathDescriptor.getSlowSpeed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DynamicSpeedTrackPathDescriptor#getNormalSpeed()}.
|
||||
*/
|
||||
public void testGetNormalSpeed() {
|
||||
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
|
||||
context);
|
||||
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
|
||||
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
|
||||
assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
|
||||
assertEquals(55.0, dynamicSpeedTrackPathDescriptor.getNormalSpeed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DynamicSpeedTrackPathDescriptor#updateState(com.google.android.apps.mytracks.stats.TripStatistics)}
|
||||
* by different averageMovingSpeed.
|
||||
*/
|
||||
public void testIsDiffereceSignificant() {
|
||||
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
|
||||
context);
|
||||
double[] averageMovingSpeeds = { 0, 30, 30, 30 };
|
||||
double[] newAverageMovingSpeed = { 20, 30,
|
||||
// Difference is less than CRITICAL_DIFFERENCE_PERCENTAGE
|
||||
30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100) / 2),
|
||||
// Difference is more than CRITICAL_DIFFERENCE_PERCENTAGE
|
||||
30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100.00) * 2) };
|
||||
boolean[] expectedValues = { true, false, false, true };
|
||||
double[] expectedAverageMovingSpeed = { 0, 30, 30, 30 };
|
||||
// Test
|
||||
for (int i = 0; i < newAverageMovingSpeed.length; i++) {
|
||||
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(averageMovingSpeeds[i]);
|
||||
assertEquals(expectedValues[i], dynamicSpeedTrackPathDescriptor.isDifferenceSignificant(
|
||||
averageMovingSpeeds[i], newAverageMovingSpeed[i]));
|
||||
assertEquals(expectedAverageMovingSpeed[i],
|
||||
dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
|
||||
}
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.maps;
|
||||
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for the {@link FixedSpeedTrackPathDescriptor}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class FixedSpeedTrackPathDescriptorTest extends AndroidTestCase {
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
Context context = getContext();
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key,
|
||||
PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT);
|
||||
PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key,
|
||||
PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the slow speed and the normal speed are both zero.
|
||||
*/
|
||||
public void testGetSpeed_zero() {
|
||||
testSpeed(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the slow speed and the normal speed are both one.
|
||||
*/
|
||||
public void testGetSpeed_one() {
|
||||
testSpeed(1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the slow speed and the normal speed are both large number. E.g.,
|
||||
* 99 and 100.
|
||||
*/
|
||||
public void testGetSpeed_large() {
|
||||
testSpeed(99, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when the slow speed and the normal speed are both the default value.
|
||||
*/
|
||||
public void testGetSpeed_default() {
|
||||
testSpeed(PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT,
|
||||
PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT);
|
||||
}
|
||||
|
||||
private void testSpeed(int slowSpeed, int normalSpeed) {
|
||||
testSpeed(slowSpeed, normalSpeed, true);
|
||||
testSpeed(slowSpeed, normalSpeed, false);
|
||||
}
|
||||
|
||||
private void testSpeed(int slowSpeed, int normalSpeed, boolean metric) {
|
||||
Context context = getContext();
|
||||
PreferencesUtils.setString(context, R.string.stats_units_key,
|
||||
context.getString(metric ? R.string.stats_units_metric : R.string.stats_units_imperial));
|
||||
PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, slowSpeed);
|
||||
PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, normalSpeed);
|
||||
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
|
||||
context);
|
||||
double expectedSlowSpeed = metric ? slowSpeed : slowSpeed * UnitConversions.MI_TO_KM;
|
||||
double expectedNormalSpeed = metric ? normalSpeed : normalSpeed * UnitConversions.MI_TO_KM;
|
||||
assertEquals(expectedSlowSpeed, fixedSpeedTrackPathDescriptor.getSlowSpeed());
|
||||
assertEquals(expectedNormalSpeed, fixedSpeedTrackPathDescriptor.getNormalSpeed());
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.maps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for the {@link MultiColorTrackPath}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class MultiColorTrackPathTest extends AndroidTestCase {
|
||||
|
||||
private MultiColorTrackPath multiColorTrackPath;
|
||||
private Context context;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the {@link MultiColorTrackPath#getColor(double)} when use dynamic speed
|
||||
* track path descriptor.
|
||||
*/
|
||||
public void testGetColor_DynamicSpeedTrackPathDescriptor() {
|
||||
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
|
||||
context);
|
||||
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
|
||||
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
|
||||
multiColorTrackPath = new MultiColorTrackPath(context, dynamicSpeedTrackPathDescriptor);
|
||||
|
||||
// Slow speed should be below 45 (10% of 50), and fast speed should be above
|
||||
// 55 (10% of 50).
|
||||
assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(5));
|
||||
assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(44));
|
||||
assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(50));
|
||||
assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(54));
|
||||
assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(56));
|
||||
assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(100));
|
||||
|
||||
assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getNormalColor());
|
||||
assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getFastColor());
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.services;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests the {@link AdaptiveLocationListenerPolicy}.
|
||||
*
|
||||
* @author youtaol
|
||||
*/
|
||||
public class AdaptiveLocationListenerPolicyTest extends TestCase {
|
||||
|
||||
private AdaptiveLocationListenerPolicy adocationListenerPolicy;
|
||||
private static final long MIN = 1000;
|
||||
private static final long MAX = 3000;
|
||||
private static final int MIN_DISTANCE = 10;
|
||||
private static final long NEW_IDLE_TIME_BIG = 10000;
|
||||
private static final long NEW_IDLE_TIME_NORMAL = 5000;
|
||||
private static final long NEW_IDLE_TIME_SMALL = 2000;
|
||||
private static final long NEW_IDLE_TIME_LESS_THAN_MIN = 500;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
adocationListenerPolicy = new AdaptiveLocationListenerPolicy(MIN, MAX, MIN_DISTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the
|
||||
* {@link AdaptiveLocationListenerPolicy#getDesiredPollingInterval()} in four
|
||||
* situations.
|
||||
* <ul>
|
||||
* <li>The newIdleTime is bigger than max interval.</li>
|
||||
* <li>The newIdleTime is between min and max interval.</li>
|
||||
* <li>The newIdleTime is smaller than max interval.</li>
|
||||
* <li>The newIdleTime is smaller than the smallest interval unit.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void testGetDesiredPollingInterval() {
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_BIG);
|
||||
assertEquals(MAX, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_NORMAL);
|
||||
// First get the half of NEW_IDLE_TIME_NORMAL, and then round it to the
|
||||
// nearest second.
|
||||
assertEquals((NEW_IDLE_TIME_NORMAL / 2 / 1000) * 1000,
|
||||
adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_SMALL);
|
||||
assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_LESS_THAN_MIN);
|
||||
assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method {@link AdaptiveLocationListenerPolicy#getMinDistance()}.
|
||||
*/
|
||||
public void testGetMinDistance() {
|
||||
assertEquals(MIN_DISTANCE, adocationListenerPolicy.getMinDistance());
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.services;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.RemoteException;
|
||||
import android.test.ServiceTestCase;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
/**
|
||||
* Tests {@link ControlRecordingService}.
|
||||
*
|
||||
* @author Youtao Liu
|
||||
*/
|
||||
public class ControlRecordingServiceTest extends ServiceTestCase<ControlRecordingService> {
|
||||
|
||||
private Context context;
|
||||
private ControlRecordingService controlRecordingService;
|
||||
|
||||
public ControlRecordingServiceTest() {
|
||||
super(ControlRecordingService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the start of {@link ControlRecordingService} and tests the method
|
||||
* {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)}
|
||||
* to start a track recording.
|
||||
*/
|
||||
@UsesMocks(ITrackRecordingService.class)
|
||||
public void testStartRecording() {
|
||||
assertNull(controlRecordingService);
|
||||
Intent intent = startControlRecordingService(context.getString(R.string.track_action_start));
|
||||
assertNotNull(controlRecordingService);
|
||||
|
||||
ITrackRecordingService iTrackRecordingServiceMock = EasyMock
|
||||
.createStrictMock(ITrackRecordingService.class);
|
||||
try {
|
||||
EasyMock.expect(iTrackRecordingServiceMock.startNewTrack()).andReturn(1L);
|
||||
EasyMock.replay(iTrackRecordingServiceMock);
|
||||
controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock);
|
||||
EasyMock.verify(iTrackRecordingServiceMock);
|
||||
} catch (RemoteException e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method
|
||||
* {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)}
|
||||
* to stop a track recording.
|
||||
*/
|
||||
@UsesMocks(ITrackRecordingService.class)
|
||||
public void testStopRecording() {
|
||||
Intent intent = startControlRecordingService(context.getString(R.string.track_action_end));
|
||||
|
||||
ITrackRecordingService iTrackRecordingServiceMock = EasyMock
|
||||
.createStrictMock(ITrackRecordingService.class);
|
||||
try {
|
||||
iTrackRecordingServiceMock.endCurrentTrack();
|
||||
EasyMock.replay(iTrackRecordingServiceMock);
|
||||
controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock);
|
||||
EasyMock.verify(iTrackRecordingServiceMock);
|
||||
} catch (RemoteException e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a ControlRecordingService with a specified action.
|
||||
*
|
||||
* @param action the action string in the start intent
|
||||
*/
|
||||
private Intent startControlRecordingService(String action) {
|
||||
Intent intent = new Intent(context, ControlRecordingService.class);
|
||||
intent.setAction(action);
|
||||
startService(intent);
|
||||
controlRecordingService = getService();
|
||||
return intent;
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.test.ServiceTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A {@link TrackRecordingService} that can be used with
|
||||
* {@link ServiceTestCase}. {@link ServiceTestCase} throws a null pointer
|
||||
* exception when the service calls
|
||||
* {@link Service#startForeground(int, android.app.Notification)} and
|
||||
* {@link Service#stopForeground(boolean)}.
|
||||
* <p>
|
||||
* See http://code.google.com/p/android/issues/detail?id=12122
|
||||
* <p>
|
||||
* Wrap these two methods in wrappers and override them.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class TestRecordingService extends TrackRecordingService {
|
||||
|
||||
private static final String TAG = TestRecordingService.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
protected void startForegroundService(PendingIntent pendingIntent, int messageId) {
|
||||
try {
|
||||
Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class);
|
||||
setForegroundMethod.invoke(this, true);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopForegroundService() {
|
||||
try {
|
||||
Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class);
|
||||
setForegroundMethod.invoke(this, false);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(TAG, "Unable to start a service in foreground", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+798
@@ -0,0 +1,798 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProvider;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
||||
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.test.RenamingDelegatingContext;
|
||||
import android.test.ServiceTestCase;
|
||||
import android.test.mock.MockContentProvider;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.test.mock.MockCursor;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for the MyTracks track recording service.
|
||||
* <p>
|
||||
* TODO: The original class, ServiceTestCase, has a few limitations, e.g. it's
|
||||
* not possible to properly shutdown the service, unless tearDown() is called,
|
||||
* which prevents from testing multiple scenarios in a single test (see
|
||||
* runFunctionTest for more details).
|
||||
*
|
||||
* @author Bartlomiej Niechwiej
|
||||
*/
|
||||
public class TrackRecordingServiceTest extends ServiceTestCase<TestRecordingService> {
|
||||
|
||||
private Context context;
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
|
||||
/*
|
||||
* In order to support starting and binding to the service in the same unit
|
||||
* test, we provide a workaround, as the original class doesn't allow to bind
|
||||
* after the service has been previously started.
|
||||
*/
|
||||
|
||||
private boolean bound;
|
||||
private Intent serviceIntent;
|
||||
|
||||
public TrackRecordingServiceTest() {
|
||||
super(TestRecordingService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* A context wrapper with the user provided {@link ContentResolver}. TODO:
|
||||
* Move to test utils package.
|
||||
*/
|
||||
public static class MockContext extends ContextWrapper {
|
||||
private final ContentResolver contentResolver;
|
||||
|
||||
public MockContext(ContentResolver contentResolver, Context base) {
|
||||
super(base);
|
||||
this.contentResolver = contentResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return contentResolver;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBinder bindService(Intent intent) {
|
||||
if (getService() != null) {
|
||||
if (bound) {
|
||||
throw new IllegalStateException("Service: " + getService() + " is already bound");
|
||||
}
|
||||
bound = true;
|
||||
serviceIntent = intent.cloneFilter();
|
||||
return getService().onBind(intent);
|
||||
} else {
|
||||
return super.bindService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdownService() {
|
||||
if (bound) {
|
||||
assertNotNull(getService());
|
||||
getService().onUnbind(serviceIntent);
|
||||
bound = false;
|
||||
}
|
||||
super.shutdownService();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
/*
|
||||
* Create a mock context that uses a mock content resolver and a renaming
|
||||
* delegating context.
|
||||
*/
|
||||
MockContentResolver mockContentResolver = new MockContentResolver();
|
||||
RenamingDelegatingContext renamingDelegatingContext = new RenamingDelegatingContext(
|
||||
getContext(), getContext(), "test.");
|
||||
context = new MockContext(mockContentResolver, renamingDelegatingContext);
|
||||
|
||||
// Set up the mock content resolver
|
||||
MyTracksProvider myTracksProvider = new MyTracksProvider();
|
||||
myTracksProvider.attachInfo(context, null);
|
||||
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider);
|
||||
|
||||
MockContentProvider settingsProvider = new MockContentProvider(context) {
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
mockContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
|
||||
|
||||
MockContentProvider googleSettingsProvider = new MockContentProvider(context) {
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
MockCursor mockCursor = new MockCursor() {
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToNext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(int columnIndex) {
|
||||
return String.valueOf(GoogleLocationUtils.USE_LOCATION_FOR_SERVICES_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
};
|
||||
return mockCursor;
|
||||
}
|
||||
};
|
||||
mockContentResolver.addProvider("com.google.settings", googleSettingsProvider);
|
||||
|
||||
// Set the context
|
||||
setContext(context);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
// Let's use default values.
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear());
|
||||
|
||||
// Disable auto resume by default.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, 0);
|
||||
// No recording track.
|
||||
PreferencesUtils.setLong(
|
||||
context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testStartable() {
|
||||
startService(createStartIntent());
|
||||
assertNotNull(getService());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testBindable() {
|
||||
IBinder service = bindService(createStartIntent());
|
||||
assertNotNull(service);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_shouldResume() throws Exception {
|
||||
// Insert a dummy track and mark it as recording track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), true);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We expect to resume the previous track.
|
||||
assertTrue(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(123L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: shutdownService() has a bug and doesn't set mServiceCreated to false,
|
||||
* thus preventing from a second call to onCreate(). Report the bug to Android
|
||||
* team. Until then, the following tests and checks must be commented out.
|
||||
*
|
||||
* TODO: If fixed, remove "disabled" prefix from the test name.
|
||||
*/
|
||||
@MediumTest
|
||||
public void disabledTestResumeAfterReboot_simulateReboot() throws Exception {
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
// Simulate recording a track.
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(service.isRecording());
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
shutdownService();
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
assertTrue(getService().isRecording());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_noRecordingTrack() throws Exception {
|
||||
// Insert a dummy track and mark it as recording track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), false);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because it was stopped.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_expiredTrack() throws Exception {
|
||||
// Insert a dummy track last updated 20 min ago.
|
||||
createDummyTrack(123L, System.currentTimeMillis() - 20 * 60 * 1000, true);
|
||||
|
||||
// Clear the number of attempts and set the timeout to 10 min.
|
||||
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because it has expired.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testResumeAfterReboot_tooManyAttempts() throws Exception {
|
||||
// Insert a dummy track.
|
||||
createDummyTrack(123L, System.currentTimeMillis(), true);
|
||||
|
||||
// Set the number of attempts to max.
|
||||
updateAutoResumePrefs(TrackRecordingService.MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS,
|
||||
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
|
||||
|
||||
// Start the service in "resume" mode (simulates the on-reboot action).
|
||||
Intent startIntent = createStartIntent();
|
||||
startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true);
|
||||
startService(startIntent);
|
||||
assertNotNull(getService());
|
||||
|
||||
// We don't expect to resume the previous track, because there were already
|
||||
// too many attempts.
|
||||
assertFalse(getService().isRecording());
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_noTracks() throws Exception {
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
// Test if we start in no-recording mode by default.
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_oldTracks() throws Exception {
|
||||
createDummyTrack(123L, -1L, false);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testRecording_orphanedRecordingTrack() throws Exception {
|
||||
// Just set recording track to a bogus value.
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key, 256L);
|
||||
|
||||
// Make sure that the service will not start recording and will clear
|
||||
// the bogus track.
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous/waitable broadcast receiver to be used in testing.
|
||||
*/
|
||||
private class BlockingBroadcastReceiver extends BroadcastReceiver {
|
||||
private static final long MAX_WAIT_TIME_MS = 10000;
|
||||
private List<Intent> receivedIntents = new ArrayList<Intent>();
|
||||
|
||||
public List<Intent> getReceivedIntents() {
|
||||
return receivedIntents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
Log.d("MyTracksTest", "Got broadcast: " + intent);
|
||||
synchronized (receivedIntents) {
|
||||
receivedIntents.add(intent);
|
||||
receivedIntents.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitUntilReceived(int receiveCount) {
|
||||
long deadline = System.currentTimeMillis() + MAX_WAIT_TIME_MS;
|
||||
synchronized (receivedIntents) {
|
||||
while (receivedIntents.size() < receiveCount) {
|
||||
try {
|
||||
// Wait releases synchronized lock until it returns
|
||||
receivedIntents.wait(500);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() > deadline) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStartNewTrack_noRecording() throws Exception {
|
||||
// NOTICE: due to the way Android permissions work, if this fails,
|
||||
// uninstall the test apk then retry - the test must be installed *after*
|
||||
// My Tracks (go figure).
|
||||
// Reference: http://code.google.com/p/android/issues/detail?id=5521
|
||||
BlockingBroadcastReceiver startReceiver = new BlockingBroadcastReceiver();
|
||||
String startAction = context.getString(R.string.track_started_broadcast_action);
|
||||
context.registerReceiver(startReceiver, new IntentFilter(startAction));
|
||||
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(id >= 0);
|
||||
assertTrue(service.isRecording());
|
||||
Track track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
assertEquals(PreferencesUtils.getString(
|
||||
context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT),
|
||||
track.getCategory());
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
|
||||
// Verify that the start broadcast was received.
|
||||
assertTrue(startReceiver.waitUntilReceived(1));
|
||||
List<Intent> receivedIntents = startReceiver.getReceivedIntents();
|
||||
assertEquals(1, receivedIntents.size());
|
||||
Intent broadcastIntent = receivedIntents.get(0);
|
||||
assertEquals(startAction, broadcastIntent.getAction());
|
||||
assertEquals(id,
|
||||
broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L));
|
||||
|
||||
context.unregisterReceiver(startReceiver);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testStartNewTrack_alreadyRecording() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
|
||||
// Starting a new track when there is a recording should just return -1L.
|
||||
long newTrack = service.startNewTrack();
|
||||
assertEquals(-1L, newTrack);
|
||||
|
||||
assertEquals(123L, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(123L, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testEndCurrentTrack_alreadyRecording() throws Exception {
|
||||
// See comment above if this fails randomly.
|
||||
BlockingBroadcastReceiver stopReceiver = new BlockingBroadcastReceiver();
|
||||
String stopAction = context.getString(R.string.track_stopped_broadcast_action);
|
||||
context.registerReceiver(stopReceiver, new IntentFilter(stopAction));
|
||||
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
|
||||
// End the current track.
|
||||
service.endCurrentTrack();
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
|
||||
PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
|
||||
// Verify that the stop broadcast was received.
|
||||
assertTrue(stopReceiver.waitUntilReceived(1));
|
||||
List<Intent> receivedIntents = stopReceiver.getReceivedIntents();
|
||||
assertEquals(1, receivedIntents.size());
|
||||
Intent broadcastIntent = receivedIntents.get(0);
|
||||
assertEquals(stopAction, broadcastIntent.getAction());
|
||||
assertEquals(123L,
|
||||
broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L));
|
||||
|
||||
context.unregisterReceiver(stopReceiver);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testEndCurrentTrack_noRecording() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
/*
|
||||
* Ending the current track when there is no recording should not result in
|
||||
* any error.
|
||||
*/
|
||||
service.endCurrentTrack();
|
||||
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
|
||||
PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testIntegration_completeRecordingSession() throws Exception {
|
||||
List<Track> tracks = providerUtils.getAllTracks();
|
||||
assertTrue(tracks.isEmpty());
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertStatisticsMarker_noRecordingTrack() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||
assertEquals(-1L, waypointId);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertStatisticsMarker_validLocation() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
assertFalse(service.isPaused());
|
||||
insertLocation(service);
|
||||
|
||||
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
|
||||
assertEquals(2, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
|
||||
|
||||
Waypoint wpt = providerUtils.getWaypoint(2);
|
||||
assertEquals(getContext().getString(R.string.marker_statistics_icon_url), wpt.getIcon());
|
||||
assertEquals(getContext().getString(R.string.marker_split_name_format, 1), wpt.getName());
|
||||
assertEquals(WaypointType.STATISTICS, wpt.getType());
|
||||
assertEquals(123L, wpt.getTrackId());
|
||||
assertEquals(0.0, wpt.getLength());
|
||||
assertNotNull(wpt.getLocation());
|
||||
assertNotNull(wpt.getTripStatistics());
|
||||
// TODO check the rest of the params.
|
||||
|
||||
// TODO: Check waypoint 2.
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertWaypointMarker_noRecordingTrack() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
|
||||
assertEquals(-1L, waypointId);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testInsertWaypointMarker_validWaypoint() throws Exception {
|
||||
createDummyTrack(123L, -1L, true);
|
||||
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertTrue(service.isRecording());
|
||||
insertLocation(service);
|
||||
|
||||
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT));
|
||||
Waypoint wpt = providerUtils.getWaypoint(1);
|
||||
assertEquals(getContext().getString(R.string.marker_waypoint_icon_url), wpt.getIcon());
|
||||
assertEquals(getContext().getString(R.string.marker_name_format, 1), wpt.getName());
|
||||
assertEquals(WaypointType.WAYPOINT, wpt.getType());
|
||||
assertEquals(123L, wpt.getTrackId());
|
||||
assertEquals(0.0, wpt.getLength());
|
||||
assertNotNull(wpt.getLocation());
|
||||
assertNull(wpt.getTripStatistics());
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(
|
||||
context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyByDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.voice_frequency_key, -1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_voiceFrequencyByTime() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.voice_frequency_key, 1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_maxRecordingDistanceDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.max_recording_distance_key,
|
||||
PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_maxRecordingDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.max_recording_distance_key, 50);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingDistanceDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key,
|
||||
PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, 2);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(
|
||||
context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyByDistance() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.split_frequency_key, -1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_splitFrequencyByTime() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.split_frequency_key, 1);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_metricUnitsDefault() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_metricUnitsDisabled() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.stats_units_key, context.getString(R.string.stats_units_imperial));
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingIntervalDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.min_recording_interval_key,
|
||||
PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRecordingInterval() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.min_recording_interval_key, 2);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRequiredAccuracyDefault() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key,
|
||||
PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_minRequiredAccuracy() throws Exception {
|
||||
PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, 500);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_sensorTypeDefault() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.sensor_type_key, PreferencesUtils.SENSOR_TYPE_DEFAULT);
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWithProperties_sensorTypeZephyr() throws Exception {
|
||||
PreferencesUtils.setString(
|
||||
context, R.string.sensor_type_key, context.getString(R.string.sensor_type_value_zephyr));
|
||||
fullRecordingSession();
|
||||
}
|
||||
|
||||
private ITrackRecordingService bindAndGetService(Intent intent) {
|
||||
ITrackRecordingService service = ITrackRecordingService.Stub.asInterface(bindService(intent));
|
||||
assertNotNull(service);
|
||||
return service;
|
||||
}
|
||||
|
||||
private Track createDummyTrack(long id, long stopTime, boolean isRecording) {
|
||||
Track dummyTrack = new Track();
|
||||
dummyTrack.setId(id);
|
||||
dummyTrack.setName("Dummy Track");
|
||||
TripStatistics tripStatistics = new TripStatistics();
|
||||
tripStatistics.setStopTime(stopTime);
|
||||
dummyTrack.setTripStatistics(tripStatistics);
|
||||
addTrack(dummyTrack, isRecording);
|
||||
return dummyTrack;
|
||||
}
|
||||
|
||||
private void updateAutoResumePrefs(int attempts, int timeoutMins) {
|
||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts);
|
||||
PreferencesUtils.setInt(context, R.string.auto_resume_track_timeout_key, timeoutMins);
|
||||
}
|
||||
|
||||
private Intent createStartIntent() {
|
||||
Intent startIntent = new Intent();
|
||||
startIntent.setClass(context, TrackRecordingService.class);
|
||||
return startIntent;
|
||||
}
|
||||
|
||||
private void addTrack(Track track, boolean isRecording) {
|
||||
assertTrue(track.getId() >= 0);
|
||||
providerUtils.insertTrack(track);
|
||||
assertEquals(track.getId(), providerUtils.getTrack(track.getId()).getId());
|
||||
PreferencesUtils.setLong(context, R.string.recording_track_id_key,
|
||||
isRecording ? track.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
|
||||
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording);
|
||||
}
|
||||
|
||||
private void fullRecordingSession() throws Exception {
|
||||
ITrackRecordingService service = bindAndGetService(createStartIntent());
|
||||
assertFalse(service.isRecording());
|
||||
|
||||
// Start a track.
|
||||
long id = service.startNewTrack();
|
||||
assertTrue(id >= 0);
|
||||
assertTrue(service.isRecording());
|
||||
Track track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
|
||||
assertEquals(id, service.getRecordingTrackId());
|
||||
|
||||
// Insert a few points, markers and statistics.
|
||||
long startTime = System.currentTimeMillis();
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Location loc = new Location("gps");
|
||||
loc.setLongitude(35.0f + i / 10.0f);
|
||||
loc.setLatitude(45.0f - i / 5.0f);
|
||||
loc.setAccuracy(5);
|
||||
loc.setSpeed(10);
|
||||
loc.setTime(startTime + i * 10000);
|
||||
loc.setBearing(3.0f);
|
||||
service.insertTrackPoint(loc);
|
||||
|
||||
if (i % 10 == 0) {
|
||||
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
|
||||
} else if (i % 7 == 0) {
|
||||
service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the track. Validate if it has correct data.
|
||||
service.endCurrentTrack();
|
||||
assertFalse(service.isRecording());
|
||||
assertEquals(-1L, service.getRecordingTrackId());
|
||||
track = providerUtils.getTrack(id);
|
||||
assertNotNull(track);
|
||||
assertEquals(id, track.getId());
|
||||
TripStatistics tripStatistics = track.getTripStatistics();
|
||||
assertNotNull(tripStatistics);
|
||||
assertTrue(tripStatistics.getStartTime() > 0);
|
||||
assertTrue(tripStatistics.getStopTime() >= tripStatistics.getStartTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a location and waits for 100ms.
|
||||
*
|
||||
* @param trackRecordingService the track recording service
|
||||
*/
|
||||
private void insertLocation(ITrackRecordingService trackRecordingService)
|
||||
throws RemoteException, InterruptedException {
|
||||
Location location = new Location("gps");
|
||||
location.setLongitude(35.0f);
|
||||
location.setLatitude(45.0f);
|
||||
location.setAccuracy(5);
|
||||
location.setSpeed(10);
|
||||
location.setTime(System.currentTimeMillis());
|
||||
location.setBearing(3.0f);
|
||||
trackRecordingService.insertTrackPoint(location);
|
||||
Thread.sleep(200);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.google.android.apps.mytracks.services.sensors;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class PolarMessageParserTest extends TestCase {
|
||||
|
||||
PolarMessageParser parser = new PolarMessageParser();
|
||||
// A complete and valid Polar HxM packet
|
||||
// FE08F701D1001104FE08F702D1001104
|
||||
private final byte[] originalBuf =
|
||||
{(byte) 0xFE, 0x08, (byte) 0xF7, 0x01, (byte) 0xD1, 0x00, 0x11, 0x04, (byte) 0xFE, 0x08,
|
||||
(byte) 0xF7, 0x02, (byte) 0xD1, 0x00, 0x11, 0x04};
|
||||
private byte[] buf;
|
||||
|
||||
public void setUp() {
|
||||
buf = ApiAdapterFactory.getApiAdapter().copyByteArray(originalBuf, 0, originalBuf.length);
|
||||
}
|
||||
|
||||
public void testIsValid() {
|
||||
assertTrue(parser.isValid(buf));
|
||||
}
|
||||
|
||||
public void testIsValid_invalidHeader() {
|
||||
// Invalidate header.
|
||||
buf[0] = 0x03;
|
||||
assertFalse(parser.isValid(buf));
|
||||
}
|
||||
|
||||
public void testIsValid_invalidCheckbyte() {
|
||||
// Invalidate checkbyte.
|
||||
buf[2] = 0x03;
|
||||
assertFalse(parser.isValid(buf));
|
||||
}
|
||||
|
||||
public void testIsValid_invalidSequence() {
|
||||
// Invalidate sequence.
|
||||
buf[3] = 0x11;
|
||||
assertFalse(parser.isValid(buf));
|
||||
}
|
||||
|
||||
public void testParseBuffer() {
|
||||
buf[5] = 70;
|
||||
Sensor.SensorDataSet sds = parser.parseBuffer(buf);
|
||||
assertTrue(sds.hasHeartRate());
|
||||
assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING);
|
||||
assertEquals(70, sds.getHeartRate().getValue());
|
||||
}
|
||||
|
||||
public void testFindNextAlignment_offset() {
|
||||
// The first 4 bytes are garbage
|
||||
buf = new byte[originalBuf.length + 4];
|
||||
buf[0] = 4;
|
||||
buf[1] = 2;
|
||||
buf[2] = 4;
|
||||
buf[3] = 2;
|
||||
|
||||
// Then the valid message.
|
||||
System.arraycopy(originalBuf, 0, buf, 4, originalBuf.length);
|
||||
assertEquals(4, parser.findNextAlignment(buf));
|
||||
}
|
||||
|
||||
public void testFindNextAlignment_invalid() {
|
||||
buf[0] = 0;
|
||||
assertEquals(-1, parser.findNextAlignment(buf));
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.google.android.apps.mytracks.services.sensors;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
public class SensorManagerFactoryTest extends AndroidTestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
SharedPreferences sharedPreferences = getContext().getSharedPreferences(
|
||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
// Let's use default values.
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testDefaultSettings() throws Exception {
|
||||
assertNull(SensorManagerFactory.getSystemSensorManager(getContext()));
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testCreateZephyr() throws Exception {
|
||||
assertClassForName(ZephyrSensorManager.class, R.string.sensor_type_value_zephyr);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testCreatePolar() throws Exception {
|
||||
assertClassForName(PolarSensorManager.class, R.string.sensor_type_value_polar);
|
||||
}
|
||||
|
||||
private void assertClassForName(Class<?> c, int i) {
|
||||
PreferencesUtils.setString(getContext(), R.string.sensor_type_key, getContext().getString(i));
|
||||
SensorManager sm = SensorManagerFactory.getSystemSensorManager(getContext());
|
||||
assertNotNull(sm);
|
||||
assertTrue(c.isInstance(sm));
|
||||
SensorManagerFactory.releaseSystemSensorManager();
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011 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.services.sensors;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dominik Rottsches
|
||||
*/
|
||||
public class StrideReadingsTest extends TestCase {
|
||||
|
||||
public void testNoReadingOnStartup() {
|
||||
StrideReadings strideReadings = new StrideReadings();
|
||||
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
|
||||
}
|
||||
|
||||
public void testAverageCadenceAvailable() {
|
||||
StrideReadings strideReadings = new StrideReadings();
|
||||
// 2 steps / second => Cadence is 120 / minute
|
||||
for (int i = 1; i <= 30; i++) {
|
||||
strideReadings.updateStrideReading(i*2);
|
||||
if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) {
|
||||
assertEquals(120, strideReadings.getCadence());
|
||||
} else {
|
||||
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for correct calculation after rolling over at 128 strides,
|
||||
* just like the HxM seems to do it.
|
||||
*/
|
||||
public void testRollover() {
|
||||
StrideReadings strideReadings = new StrideReadings();
|
||||
// 1 step per second => Cadence is 60 / minute
|
||||
// Updating readings counting upwards from initialStrides -
|
||||
// initialStrides set to a value below 128 to ensure rollover.
|
||||
int initialStrides = 128 - StrideReadings.NUM_READINGS_FOR_AVERAGE - 5;
|
||||
|
||||
for (int i = 1; i <= StrideReadings.NUM_READINGS_FOR_AVERAGE + 10; i++) {
|
||||
strideReadings.updateStrideReading((initialStrides + i) % 128);
|
||||
if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) {
|
||||
assertEquals(60, strideReadings.getCadence());
|
||||
} else {
|
||||
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.google.android.apps.mytracks.services.sensors;
|
||||
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ZephyrMessageParserTest extends TestCase {
|
||||
|
||||
ZephyrMessageParser parser = new ZephyrMessageParser();
|
||||
|
||||
public void testIsValid() {
|
||||
byte[] smallBuf = new byte[59];
|
||||
assertFalse(parser.isValid(smallBuf));
|
||||
// A complete and valid Zephyr HxM packet
|
||||
byte[] buf = { 2,38,55,26,0,49,101,80,0,49,98,100,42,113,120,-53,-24,-60,-123,-61,117,-69,42,-75,74,-78,51,-79,27,-83,28,-88,28,-93,29,-98,25,-103,26,-108,26,-113,59,-118,0,0,0,0,0,0,-22,3,125,1,48,0,96,4,30,0 };
|
||||
// Make buffer invalid
|
||||
buf[0] = buf[58] = buf[59] = 0;
|
||||
assertFalse(parser.isValid(buf));
|
||||
buf[0] = 0x02;
|
||||
assertFalse(parser.isValid(buf));
|
||||
buf[58] = 0x1E;
|
||||
assertFalse(parser.isValid(buf));
|
||||
buf[59] = 0x03;
|
||||
assertTrue(parser.isValid(buf));
|
||||
}
|
||||
|
||||
public void testParseBuffer() {
|
||||
byte[] buf = new byte[60];
|
||||
// Heart Rate (-1 =^ 255 unsigned byte)
|
||||
buf[12] = -1;
|
||||
// Battery Level
|
||||
buf[11] = 51;
|
||||
// Cadence (=^ 255*16 strides/min)
|
||||
buf[56] = -1;
|
||||
buf[57] = 15;
|
||||
Sensor.SensorDataSet sds = parser.parseBuffer(buf);
|
||||
assertTrue(sds.hasHeartRate());
|
||||
assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING);
|
||||
assertEquals(255, sds.getHeartRate().getValue());
|
||||
assertTrue(sds.hasBatteryLevel());
|
||||
assertTrue(sds.getBatteryLevel().getState() == Sensor.SensorState.SENDING);
|
||||
assertEquals(51, sds.getBatteryLevel().getValue());
|
||||
assertTrue(sds.hasCadence());
|
||||
assertTrue(sds.getCadence().getState() == Sensor.SensorState.SENDING);
|
||||
assertEquals(255, sds.getCadence().getValue());
|
||||
}
|
||||
|
||||
public void testFindNextAlignment() {
|
||||
byte[] buf = new byte[60];
|
||||
assertEquals(-1, parser.findNextAlignment(buf));
|
||||
buf[10] = 0x03;
|
||||
buf[11] = 0x02;
|
||||
assertEquals(10, parser.findNextAlignment(buf));
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnouncementPeriodicTaskFactory}.
|
||||
* These tests require Donut+ to run.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class AnnouncementPeriodicTaskFactoryTest extends AndroidTestCase {
|
||||
public void testCreate() {
|
||||
PeriodicTaskFactory factory = new AnnouncementPeriodicTaskFactory();
|
||||
PeriodicTask task = factory.create(getContext());
|
||||
assertTrue(task instanceof AnnouncementPeriodicTask);
|
||||
}
|
||||
}
|
||||
+533
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.services.tasks;
|
||||
|
||||
import static com.google.android.testing.mocking.AndroidMock.capture;
|
||||
import static com.google.android.testing.mocking.AndroidMock.eq;
|
||||
import static com.google.android.testing.mocking.AndroidMock.expect;
|
||||
import static com.google.android.testing.mocking.AndroidMock.same;
|
||||
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.testing.mocking.AndroidMock;
|
||||
import com.google.android.testing.mocking.UsesMocks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.easymock.Capture;
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnouncementPeriodicTask}.
|
||||
* WARNING: I'm not responsible if your eyes start bleeding while reading this
|
||||
* code. You have been warned. It's still better than no test, though.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class AnnouncementPeriodicTaskTest extends AndroidTestCase {
|
||||
|
||||
// Use something other than our hardcoded value
|
||||
private static final Locale DEFAULT_LOCALE = Locale.KOREAN;
|
||||
private static final String ANNOUNCEMENT = "I can haz cheeseburger?";
|
||||
private Locale oldDefaultLocale;
|
||||
|
||||
private AnnouncementPeriodicTask task;
|
||||
private AnnouncementPeriodicTask mockTask;
|
||||
private Capture<OnInitListener> initListenerCapture;
|
||||
private Capture<PhoneStateListener> phoneListenerCapture;
|
||||
private TextToSpeechDelegate ttsDelegate;
|
||||
private TextToSpeechInterface tts;
|
||||
|
||||
/**
|
||||
* Mockable interface that we delegate TTS calls to.
|
||||
*/
|
||||
interface TextToSpeechInterface {
|
||||
int addEarcon(String earcon, String packagename, int resourceId);
|
||||
int addEarcon(String earcon, String filename);
|
||||
int addSpeech(String text, String packagename, int resourceId);
|
||||
int addSpeech(String text, String filename);
|
||||
boolean areDefaultsEnforced();
|
||||
String getDefaultEngine();
|
||||
Locale getLanguage();
|
||||
int isLanguageAvailable(Locale loc);
|
||||
boolean isSpeaking();
|
||||
int playEarcon(String earcon, int queueMode,
|
||||
HashMap<String, String> params);
|
||||
int playSilence(long durationInMs, int queueMode,
|
||||
HashMap<String, String> params);
|
||||
int setEngineByPackageName(String enginePackageName);
|
||||
int setLanguage(Locale loc);
|
||||
int setOnUtteranceCompletedListener(OnUtteranceCompletedListener listener);
|
||||
int setPitch(float pitch);
|
||||
int setSpeechRate(float speechRate);
|
||||
void shutdown();
|
||||
int speak(String text, int queueMode, HashMap<String, String> params);
|
||||
int stop();
|
||||
int synthesizeToFile(String text, HashMap<String, String> params,
|
||||
String filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass of {@link TextToSpeech} which delegates calls to the interface
|
||||
* above.
|
||||
* The logic here is stupid and the author is ashamed of having to write it
|
||||
* like this, but basically the issue is that TextToSpeech cannot be mocked
|
||||
* without running its constructor, its constructor runs async operations
|
||||
* which call other methods (and then if the methods are part of a mock we'd
|
||||
* have to set a behavior, but we can't 'cause the object hasn't been fully
|
||||
* built yet).
|
||||
* The logic is that calls made during the constructor (when tts is not yet
|
||||
* set) will go up to the original class, but after tts is set we'll forward
|
||||
* them all to the mock.
|
||||
*/
|
||||
private class TextToSpeechDelegate
|
||||
extends TextToSpeech implements TextToSpeechInterface {
|
||||
public TextToSpeechDelegate(Context context, OnInitListener listener) {
|
||||
super(context, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addEarcon(String earcon, String packagename, int resourceId) {
|
||||
if (tts == null) {
|
||||
return super.addEarcon(earcon, packagename, resourceId);
|
||||
}
|
||||
return tts.addEarcon(earcon, packagename, resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addEarcon(String earcon, String filename) {
|
||||
if (tts == null) {
|
||||
return super.addEarcon(earcon, filename);
|
||||
}
|
||||
return tts.addEarcon(earcon, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addSpeech(String text, String packagename, int resourceId) {
|
||||
if (tts == null) {
|
||||
return super.addSpeech(text, packagename, resourceId);
|
||||
}
|
||||
return tts.addSpeech(text, packagename, resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addSpeech(String text, String filename) {
|
||||
if (tts == null) {
|
||||
return super.addSpeech(text, filename);
|
||||
}
|
||||
return tts.addSpeech(text, filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLanguage() {
|
||||
if (tts == null) {
|
||||
return super.getLanguage();
|
||||
}
|
||||
return tts.getLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isLanguageAvailable(Locale loc) {
|
||||
if (tts == null) {
|
||||
return super.isLanguageAvailable(loc);
|
||||
}
|
||||
return tts.isLanguageAvailable(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpeaking() {
|
||||
if (tts == null) {
|
||||
return super.isSpeaking();
|
||||
}
|
||||
return tts.isSpeaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int playEarcon(String earcon, int queueMode,
|
||||
HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.playEarcon(earcon, queueMode, params);
|
||||
}
|
||||
return tts.playEarcon(earcon, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int playSilence(long durationInMs, int queueMode,
|
||||
HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.playSilence(durationInMs, queueMode, params);
|
||||
}
|
||||
return tts.playSilence(durationInMs, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setLanguage(Locale loc) {
|
||||
if (tts == null) {
|
||||
return super.setLanguage(loc);
|
||||
}
|
||||
return tts.setLanguage(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setOnUtteranceCompletedListener(
|
||||
OnUtteranceCompletedListener listener) {
|
||||
if (tts == null) {
|
||||
return super.setOnUtteranceCompletedListener(listener);
|
||||
}
|
||||
return tts.setOnUtteranceCompletedListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setPitch(float pitch) {
|
||||
if (tts == null) {
|
||||
return super.setPitch(pitch);
|
||||
}
|
||||
return tts.setPitch(pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setSpeechRate(float speechRate) {
|
||||
if (tts == null) {
|
||||
return super.setSpeechRate(speechRate);
|
||||
}
|
||||
return tts.setSpeechRate(speechRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (tts == null) {
|
||||
super.shutdown();
|
||||
return;
|
||||
}
|
||||
tts.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int speak(
|
||||
String text, int queueMode, HashMap<String, String> params) {
|
||||
if (tts == null) {
|
||||
return super.speak(text, queueMode, params);
|
||||
}
|
||||
return tts.speak(text, queueMode, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int stop() {
|
||||
if (tts == null) {
|
||||
return super.stop();
|
||||
}
|
||||
return tts.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int synthesizeToFile(String text, HashMap<String, String> params,
|
||||
String filename) {
|
||||
if (tts == null) {
|
||||
return super.synthesizeToFile(text, params, filename);
|
||||
}
|
||||
return tts.synthesizeToFile(text, params, filename);
|
||||
}
|
||||
}
|
||||
|
||||
@UsesMocks({
|
||||
AnnouncementPeriodicTask.class,
|
||||
StringUtils.class,
|
||||
})
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
oldDefaultLocale = Locale.getDefault();
|
||||
Locale.setDefault(DEFAULT_LOCALE);
|
||||
|
||||
// Eww, the effort required just to mock TextToSpeech is insane
|
||||
final AtomicBoolean listenerCalled = new AtomicBoolean();
|
||||
OnInitListener blockingListener = new OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
synchronized (this) {
|
||||
listenerCalled.set(true);
|
||||
notify();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ttsDelegate = new TextToSpeechDelegate(getContext(), blockingListener);
|
||||
|
||||
// Wait for all async operations done in the constructor to finish.
|
||||
synchronized (blockingListener) {
|
||||
while (!listenerCalled.get()) {
|
||||
// Releases the synchronized lock until we're woken up.
|
||||
blockingListener.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Phew, done, now we can start forwarding calls
|
||||
tts = AndroidMock.createMock(TextToSpeechInterface.class);
|
||||
|
||||
initListenerCapture = new Capture<OnInitListener>();
|
||||
phoneListenerCapture = new Capture<PhoneStateListener>();
|
||||
|
||||
// Create a partial forwarding mock
|
||||
mockTask = AndroidMock.createMock(AnnouncementPeriodicTask.class, getContext());
|
||||
task = new AnnouncementPeriodicTask(getContext()) {
|
||||
@Override
|
||||
protected TextToSpeech newTextToSpeech(Context ctx,
|
||||
OnInitListener onInitListener) {
|
||||
return mockTask.newTextToSpeech(ctx, onInitListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAnnouncement(TripStatistics stats) {
|
||||
return mockTask.getAnnouncement(stats);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void listenToPhoneState(
|
||||
PhoneStateListener listener, int events) {
|
||||
mockTask.listenToPhoneState(listener, events);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() {
|
||||
Locale.setDefault(oldDefaultLocale);
|
||||
}
|
||||
|
||||
public void testStart() {
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
assertNotNull(ttsInitListener);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
ttsInitListener.onInit(TextToSpeech.SUCCESS);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testStart_notReady() {
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
assertNotNull(ttsInitListener);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
ttsInitListener.onInit(TextToSpeech.ERROR);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testShutdown() {
|
||||
// First, start
|
||||
doStart();
|
||||
AndroidMock.verify(mockTask);
|
||||
AndroidMock.reset(mockTask);
|
||||
|
||||
// Then, shut down
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
mockTask.listenToPhoneState(
|
||||
same(phoneListener), eq(PhoneStateListener.LISTEN_NONE));
|
||||
tts.shutdown();
|
||||
AndroidMock.replay(mockTask, tts);
|
||||
task.shutdown();
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun() throws Exception {
|
||||
// Expect service data calls
|
||||
TripStatistics stats = new TripStatistics();
|
||||
|
||||
// Expect announcement building call
|
||||
expect(mockTask.getAnnouncement(same(stats))).andStubReturn(ANNOUNCEMENT);
|
||||
|
||||
// Put task in "ready" state
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isLanguageAvailable(DEFAULT_LOCALE)).andStubReturn(TextToSpeech.LANG_AVAILABLE);
|
||||
expect(tts.setLanguage(DEFAULT_LOCALE)).andReturn(TextToSpeech.LANG_AVAILABLE);
|
||||
expect(tts.setSpeechRate(AnnouncementPeriodicTask.TTS_SPEECH_RATE)).andReturn(
|
||||
TextToSpeech.SUCCESS);
|
||||
expect(tts.setOnUtteranceCompletedListener((OnUtteranceCompletedListener) EasyMock.anyObject()))
|
||||
.andReturn(0);
|
||||
|
||||
// Expect actual announcement call
|
||||
expect(
|
||||
tts.speak(eq(ANNOUNCEMENT), eq(TextToSpeech.QUEUE_FLUSH),
|
||||
eq(AnnouncementPeriodicTask.SPEECH_PARAMS))).andReturn(0);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.announce(stats);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_notReady() throws Exception {
|
||||
// Put task in "not ready" state
|
||||
startTask(TextToSpeech.ERROR);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_duringCall() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(false);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, null);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_ringWhileSpeaking() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(true);
|
||||
expect(tts.stop()).andReturn(TextToSpeech.SUCCESS);
|
||||
|
||||
AndroidMock.replay(tts);
|
||||
|
||||
// Update the state to ringing - this should stop the current announcement.
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
|
||||
|
||||
// Run the announcement - this should do nothing.
|
||||
task.run(null);
|
||||
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_whileRinging() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
expect(tts.isSpeaking()).andStubReturn(false);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
|
||||
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_noService() throws Exception {
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
public void testRun_noStats() throws Exception {
|
||||
// Expect service data calls
|
||||
|
||||
startTask(TextToSpeech.SUCCESS);
|
||||
|
||||
// Run the announcement
|
||||
AndroidMock.replay(tts);
|
||||
task.run(null);
|
||||
AndroidMock.verify(mockTask, tts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time zero.
|
||||
*/
|
||||
public void testGetAnnounceTime_time_zero() {
|
||||
long time = 0; // 0 seconds
|
||||
assertEquals("0 minutes 0 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time one.
|
||||
*/
|
||||
public void testGetAnnounceTime_time_one() {
|
||||
long time = 1 * 1000; // 1 second
|
||||
assertEquals("0 minutes 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
|
||||
* numbers with the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_singular_has_hour() {
|
||||
long time = (1 * 60 * 60 * 1000) + (1 * 60 * 1000) + (1 * 1000); // 1 hour 1 minute 1 second
|
||||
assertEquals("1 hour 1 minute 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
|
||||
* with the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_plural_has_hour() {
|
||||
long time = (2 * 60 * 60 * 1000) + (2 * 60 * 1000) + (2 * 1000); // 2 hours 2 minutes 2 seconds
|
||||
assertEquals("2 hours 2 minutes 2 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
|
||||
* numbers without the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_singular_no_hour() {
|
||||
long time = (1 * 60 * 1000) + (1 * 1000); // 1 minute 1 second
|
||||
assertEquals("1 minute 1 second", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
|
||||
* without the hour unit.
|
||||
*/
|
||||
public void testGetAnnounceTime_plural_no_hour() {
|
||||
long time = (2 * 60 * 1000) + (2 * 1000); // 2 minutes 2 seconds
|
||||
assertEquals("2 minutes 2 seconds", task.getAnnounceTime(time));
|
||||
}
|
||||
|
||||
private void startTask(int state) {
|
||||
AndroidMock.resetToNice(tts);
|
||||
AndroidMock.replay(tts);
|
||||
doStart();
|
||||
OnInitListener ttsInitListener = initListenerCapture.getValue();
|
||||
ttsInitListener.onInit(state);
|
||||
AndroidMock.resetToDefault(tts);
|
||||
}
|
||||
|
||||
private void doStart() {
|
||||
mockTask.listenToPhoneState(capture(phoneListenerCapture),
|
||||
eq(PhoneStateListener.LISTEN_CALL_STATE));
|
||||
expect(mockTask.newTextToSpeech(
|
||||
same(getContext()), capture(initListenerCapture)))
|
||||
.andStubReturn(ttsDelegate);
|
||||
AndroidMock.replay(mockTask);
|
||||
task.start();
|
||||
}
|
||||
}
|
||||
+117
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -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());
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.google.android.apps.mytracks.stats;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Tests for {@link TripStatistics}.
|
||||
* This only tests non-trivial pieces of that class.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TripStatisticsTest extends TestCase {
|
||||
|
||||
private TripStatistics statistics;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
statistics = new TripStatistics();
|
||||
}
|
||||
|
||||
public void testSetBounds() {
|
||||
// This is not a trivial setter, conversion happens in it
|
||||
statistics.setBounds(12345, -34567, 56789, -98765);
|
||||
assertEquals(12345, statistics.getLeft());
|
||||
assertEquals(-34567, statistics.getTop());
|
||||
assertEquals(56789, statistics.getRight());
|
||||
assertEquals(-98765, statistics.getBottom());
|
||||
}
|
||||
|
||||
public void testMerge() {
|
||||
TripStatistics statistics2 = new TripStatistics();
|
||||
statistics.setStartTime(1000L); // Resulting start time
|
||||
statistics.setStopTime(2500L);
|
||||
statistics2.setStartTime(3000L);
|
||||
statistics2.setStopTime(4000L); // Resulting stop time
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics2.setTotalTime(1000L); // Result: 1500+1000
|
||||
statistics.setMovingTime(700L);
|
||||
statistics2.setMovingTime(600L); // Result: 700+600
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics2.setTotalDistance(350.0); // Result: 750+350
|
||||
statistics.setTotalElevationGain(50.0);
|
||||
statistics2.setTotalElevationGain(850.0); // Result: 850+50
|
||||
statistics.setMaxSpeed(60.0); // Resulting max speed
|
||||
statistics2.setMaxSpeed(30.0);
|
||||
statistics.setMaxElevation(1250.0);
|
||||
statistics.setMinElevation(1200.0); // Resulting min elevation
|
||||
statistics2.setMaxElevation(3575.0); // Resulting max elevation
|
||||
statistics2.setMinElevation(2800.0);
|
||||
statistics.setMaxGrade(15.0);
|
||||
statistics.setMinGrade(-25.0); // Resulting min grade
|
||||
statistics2.setMaxGrade(35.0); // Resulting max grade
|
||||
statistics2.setMinGrade(0.0);
|
||||
statistics2.setCalorie(50.0);
|
||||
|
||||
// Resulting bounds: -10000, 35000, 30000, -40000
|
||||
statistics.setBounds(-10000, 20000, 30000, -40000);
|
||||
statistics2.setBounds(-5000, 35000, 0, 20000);
|
||||
|
||||
statistics.merge(statistics2);
|
||||
|
||||
assertEquals(1000L, statistics.getStartTime());
|
||||
assertEquals(4000L, statistics.getStopTime());
|
||||
assertEquals(2500L, statistics.getTotalTime());
|
||||
assertEquals(1300L, statistics.getMovingTime());
|
||||
assertEquals(1100.0, statistics.getTotalDistance());
|
||||
assertEquals(900.0, statistics.getTotalElevationGain());
|
||||
assertEquals(statistics.getTotalDistance()/ (statistics.getMovingTime() / 1000.0), statistics.getMaxSpeed());
|
||||
assertEquals(-10000, statistics.getLeft());
|
||||
assertEquals(30000, statistics.getRight());
|
||||
assertEquals(35000, statistics.getTop());
|
||||
assertEquals(-40000, statistics.getBottom());
|
||||
assertEquals(1200.0, statistics.getMinElevation());
|
||||
assertEquals(3575.0, statistics.getMaxElevation());
|
||||
assertEquals(-25.0, statistics.getMinGrade());
|
||||
assertEquals(35.0, statistics.getMaxGrade());
|
||||
assertEquals(50.0, statistics.getCalorie());
|
||||
}
|
||||
|
||||
public void testGetAverageSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setTotalTime(50000); // in milliseconds
|
||||
assertEquals(20.0, statistics.getAverageSpeed());
|
||||
}
|
||||
|
||||
public void testGetAverageMovingSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setMovingTime(20000); // in milliseconds
|
||||
assertEquals(50.0, statistics.getAverageMovingSpeed());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user