Add track location as an option for the default track name

This commit is contained in:
Jimmy Shih
2012-06-07 15:42:23 -07:00
commit 2ef56797a5
639 changed files with 65346 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="src" path=".apt_generated">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/MyTracks"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
+7
View File
@@ -0,0 +1,7 @@
<factorypath>
<factorypathentry kind="WKSPJAR" id="/MyTracksTest/libs/AndroidMockGenerator.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="ANDROID_SDK/platforms/android-15/android.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="ANDROID_SDK/add-ons/addon-google_apis-google_inc_-15/libs/maps.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="WKSPJAR" id="/MyTracksLib/bin/mytrackslib.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="MYTRACKS_BIN/classes" enabled="true" runInBatchMode="false"/>
</factorypath>
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyTracksTest</name>
<comment></comment>
<projects>
<project>MyTracks</project>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,7 @@
#Tue Oct 25 14:08:44 PDT 2011
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=.apt_generated
org.eclipse.jdt.apt.processorOptions/bin_dir=%PROJECT.DIR%/bin/classes
org.eclipse.jdt.apt.processorOptions/logfile=%PROJECT.DIR%/AnnotationProcessor.log
org.eclipse.jdt.apt.reconcileEnabled=false
@@ -0,0 +1,358 @@
#Fri Oct 21 20:06:28 BRST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=48
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=true
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=100
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=2
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
@@ -0,0 +1,61 @@
#Thu Jul 21 03:06:24 BRT 2011
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_MyTracks
formatter_settings_version=12
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=com;android;java;javax;org;
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.staticondemandthreshold=99
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=true
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=false
sp_cleanup.organize_imports=true
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=false
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+36
View File
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks.test"
android:versionCode="1"
android:versionName="1.0" >
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.google.android.maps.mytracks" />
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
<application
android:icon="@android:drawable/sym_def_app_icon"
android:label="My Tracks Tests" >
<uses-library android:name="android.test.runner" />
</application>
</manifest>
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.android.ide.eclipse.adt.junit.launchConfigurationType">
<stringAttribute key="com.android.ide.eclipse.adt.commandline" value=""/>
<intAttribute key="com.android.ide.eclipse.adt.delay" value="0"/>
<stringAttribute key="com.android.ide.eclipse.adt.instrumentation" value="android.test.InstrumentationTestRunner"/>
<booleanAttribute key="com.android.ide.eclipse.adt.nobootanim" value="true"/>
<intAttribute key="com.android.ide.eclipse.adt.speed" value="0"/>
<booleanAttribute key="com.android.ide.eclipse.adt.target" value="true"/>
<booleanAttribute key="com.android.ide.eclipse.adt.wipedata" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/MyTracksTests"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=MyTracksTests"/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="MyTracksTests"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value=""/>
</launchConfiguration>
Binary file not shown.
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>
+13
View File
@@ -0,0 +1,13 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=Google Inc.:Google APIs:15
@@ -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;
}
}
@@ -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.elevation_fill,
R.color.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,176 @@
/*
* 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.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.maps.SingleColorTrackPathPainter;
import com.google.android.maps.MapView;
import android.graphics.Canvas;
import android.graphics.Path;
import android.location.Location;
import android.test.AndroidTestCase;
/**
* Tests for the MyTracks map overlay.
*
* @author Bartlomiej Niechwiej
* @author Vangelis S.
*/
public class MapOverlayTest extends AndroidTestCase {
private Canvas canvas;
private MockMyTracksOverlay myTracksOverlay;
private MapView mockView;
@Override
protected void setUp() throws Exception {
super.setUp();
canvas = new Canvas();
myTracksOverlay = new MockMyTracksOverlay(getContext());
// Enable drawing.
myTracksOverlay.setTrackDrawingEnabled(true);
// Set a TrackPathPainter with a MockPath.
myTracksOverlay.setTrackPathPainter(new SingleColorTrackPathPainter(getContext()) {
@Override
public Path newPath() {
return new MockPath();
}
});
mockView = null;
}
public void testAddLocation() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
location.setLongitude(20);
myTracksOverlay.addLocation(location);
assertEquals(1, myTracksOverlay.getNumLocations());
assertEquals(0, myTracksOverlay.getNumWaypoints());
location.setLatitude(20);
location.setLongitude(30);
myTracksOverlay.addLocation(location);
assertEquals(2, myTracksOverlay.getNumLocations());
assertEquals(0, myTracksOverlay.getNumWaypoints());
assertNull(myTracksOverlay.getTrackPathPainter().getLastPath());
// Draw and make sure that we don't lose any point.
myTracksOverlay.draw(canvas, mockView, false);
assertEquals(2, myTracksOverlay.getNumLocations());
assertEquals(0, myTracksOverlay.getNumWaypoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
assertTrue(myTracksOverlay.getTrackPathPainter().getLastPath() instanceof MockPath);
MockPath path = (MockPath) myTracksOverlay.getTrackPathPainter().getLastPath();
assertEquals(2, path.totalPoints);
myTracksOverlay.draw(canvas, mockView, true);
assertEquals(2, myTracksOverlay.getNumLocations());
assertEquals(0, myTracksOverlay.getNumWaypoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
}
public void testClearPoints() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
location.setLongitude(20);
myTracksOverlay.addLocation(location);
assertEquals(1, myTracksOverlay.getNumLocations());
myTracksOverlay.clearPoints();
assertEquals(0, myTracksOverlay.getNumLocations());
// Same after drawing on canvas.
final int locations = 100;
for (int i = 0; i < locations; ++i) {
myTracksOverlay.addLocation(location);
}
assertEquals(locations, myTracksOverlay.getNumLocations());
myTracksOverlay.draw(canvas, mockView, false);
myTracksOverlay.draw(canvas, mockView, true);
myTracksOverlay.clearPoints();
assertEquals(0, myTracksOverlay.getNumLocations());
}
public void testAddWaypoint() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
location.setLongitude(20);
Waypoint waypoint = new Waypoint();
waypoint.setLocation(location);
myTracksOverlay.addWaypoint(waypoint);
assertEquals(1, myTracksOverlay.getNumWaypoints());
assertEquals(0, myTracksOverlay.getNumLocations());
assertNull(myTracksOverlay.getTrackPathPainter().getLastPath());
final int waypoints = 10;
for (int i = 0; i < waypoints; ++i) {
waypoint = new Waypoint();
waypoint.setLocation(location);
myTracksOverlay.addWaypoint(waypoint);
}
assertEquals(1 + waypoints, myTracksOverlay.getNumWaypoints());
assertEquals(0, myTracksOverlay.getNumLocations());
assertNull(myTracksOverlay.getTrackPathPainter().getLastPath());
}
public void testClearWaypoints() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
location.setLongitude(20);
Waypoint waypoint = new Waypoint();
waypoint.setLocation(location);
myTracksOverlay.addWaypoint(waypoint);
assertEquals(1, myTracksOverlay.getNumWaypoints());
myTracksOverlay.clearWaypoints();
assertEquals(0, myTracksOverlay.getNumWaypoints());
}
public void testDrawing() {
Location location = new Location("gps");
location.setLatitude(10);
for (int i = 0; i < 40; ++i) {
location.setLongitude(20 + i);
Waypoint waypoint = new Waypoint();
waypoint.setLocation(location);
myTracksOverlay.addWaypoint(waypoint);
}
for (int i = 0; i < 100; ++i) {
location = new Location("gps");
location.setLatitude(20 + i / 2);
location.setLongitude(150 - i);
myTracksOverlay.addLocation(location);
}
// Shadow.
myTracksOverlay.draw(canvas, mockView, true);
// We don't expect to do anything if
assertNull(myTracksOverlay.getTrackPathPainter().getLastPath());
assertEquals(40, myTracksOverlay.getNumWaypoints());
assertEquals(100, myTracksOverlay.getNumLocations());
// No shadow.
myTracksOverlay.draw(canvas, mockView, false);
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
assertTrue(myTracksOverlay.getTrackPathPainter().getLastPath() instanceof MockPath);
MockPath path = (MockPath) myTracksOverlay.getTrackPathPainter().getLastPath();
assertEquals(40, myTracksOverlay.getNumWaypoints());
assertEquals(100, myTracksOverlay.getNumLocations());
assertEquals(100, path.totalPoints);
// TODO: Check the points from the path (and the segments).
}
}
@@ -0,0 +1,51 @@
/*
* 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;
import com.google.android.maps.MapView;
import com.google.android.maps.Projection;
import android.content.Context;
import android.graphics.Rect;
/**
* Elements for Tests for the MyTracks map overlay.
*
* @author Bartlomiej Niechwiej
* @author Vangelis S.
*
* A mock version of {@code MapOverlay} that does not use
* {@class MapView}.
*/
public class MockMyTracksOverlay extends MapOverlay {
private Projection mockProjection;
public MockMyTracksOverlay(Context context) {
super(context);
mockProjection = new MockProjection();
}
@Override
public Projection getMapProjection(MapView mapView) {
return mockProjection;
}
@Override
public Rect getMapViewRect(MapView mapView) {
return new Rect(0, 0, 100, 100);
}
}
@@ -0,0 +1,60 @@
/*
* 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;
import android.graphics.Path;
import android.graphics.PointF;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import junit.framework.Assert;
/**
* Elements for Tests for the MyTracks map overlay.
*
* @author Bartlomiej Niechwiej
* @author Vangelis S.
*
* A mock class that intercepts {@code Path}'s and records calls to
* {@code #moveTo()} and {@code #lineTo()}.
*/
public class MockPath extends Path {
/** A list of disjoined path segments. */
public final List<List<PointF>> segments = new LinkedList<List<PointF>>();
/** The total number of points in this path. */
public int totalPoints;
private List<PointF> currentSegment;
@Override
public void lineTo(float x, float y) {
super.lineTo(x, y);
Assert.assertNotNull(currentSegment);
currentSegment.add(new PointF(x, y));
totalPoints++;
}
@Override
public void moveTo(float x, float y) {
super.moveTo(x, y);
segments.add(currentSegment =
new ArrayList<PointF>(Arrays.asList(new PointF(x, y))));
totalPoints++;
}
}
@@ -0,0 +1,47 @@
/*
* 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;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.Projection;
import android.graphics.Point;
/**
* Elements for Tests for the MyTracks map overlay.
*
* @author Bartlomiej Niechwiej
* @author Vangelis S.
*
* A mock {@code Projection} that acts as the identity matrix.
*/
public class MockProjection implements Projection {
@Override
public Point toPixels(GeoPoint in, Point out) {
return out;
}
@Override
public float metersToEquatorPixels(float meters) {
return meters;
}
@Override
public GeoPoint fromPixels(int x, int y) {
return new GeoPoint(y, x);
}
}
@@ -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;
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;
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(System.currentTimeMillis());
loc.setBearing(INITIAL_BEARING);
SensorDataSet sd = SensorDataSet.newBuilder().build();
MyTracksLocation myTracksLocation = new MyTracksLocation(loc, sd);
return myTracksLocation;
}
}
@@ -0,0 +1,213 @@
/*
* 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;
import android.util.Pair;
/**
* 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.setStatistics(stats);
track.setCategory("hiking");
String expected = "Created by"
+ " <a href='http://www.google.com/mobile/mytracks'>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.50 min/km (0.8 min/mi)<br>"
+ "Average moving pace: 0.25 min/km (0.4 min/mi)<br>"
+ "Fastest pace: 0.17 min/km (0.3 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(Waypoint)}.
*/
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.setStatistics(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.50 min/km (0.8 min/mi)\n"
+ "Average moving pace: 0.25 min/km (0.4 min/mi)\n"
+ "Fastest pace: 0.17 min/km (0.3 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));
}
/**
* 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(Pair, StringBuilder, int,
* String)}.
*/
public void testWritePace() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writePace(
new Pair<Double, Double>(1.1, 2.2), builder, R.string.description_average_pace, "\n");
assertEquals("Average pace: 54.55 min/km (27.3 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());
}
/**
* Tests {@link DescriptionGeneratorImpl#getPace(double)}.
*/
public void testGetPace() {
assertEquals(12.0, descriptionGenerator.getPace(5));
}
/**
* Tests {@link DescriptionGeneratorImpl#getPace(double)} with zero speed.
*/
public void testGetPace_zero() {
assertEquals(0.0, descriptionGenerator.getPace(0));
}
}
@@ -0,0 +1,171 @@
/*
* 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.services.TrackRecordingServiceTest.MockContext;
import android.content.Context;
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.concurrent.atomic.AtomicInteger;
/**
* A unit test for {@link MyTracksProviderUtilsImpl}.
*
* @author Bartlomiej Niechwiej
*/
public class MyTracksProviderUtilsImplTest extends AndroidTestCase {
private Context context;
private MyTracksProviderUtils providerUtils;
@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);
}
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.getLocationIterator(trackId, -1, 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.bulkInsertTrackPoints(locations, numPoints, id);
// Load all inserted locations.
long lastPointId = -1;
int counter = 0;
LocationIterator it = providerUtils.getLocationIterator(id, -1, 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;
}
}
@@ -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();
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.getStatistics();
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());
}
}
}
@@ -0,0 +1,858 @@
/*
* 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.anyInt;
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 static com.google.android.testing.mocking.AndroidMock.leq;
import static com.google.android.testing.mocking.AndroidMock.same;
import com.google.android.apps.mytracks.Constants;
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.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.TrackDataListener.ProviderState;
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 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.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.location.Location;
import android.location.LocationListener;
import android.provider.BaseColumns;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import java.lang.reflect.Constructor;
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 MyTracksProviderUtils providerUtils;
private TrackDataHub hub;
private TrackDataListeners listeners;
private DataSourcesWrapper dataSources;
private SharedPreferences sharedPreferences;
private TrackDataListener listener1;
private TrackDataListener listener2;
private Capture<OnSharedPreferenceChangeListener> preferenceListenerCapture =
new Capture<SharedPreferences.OnSharedPreferenceChangeListener>();
private MockContext context;
private float declination;
@Override
protected void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
context = new MockContext(mockContentResolver, targetContext);
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
providerUtils = AndroidMock.createMock("providerUtils", MyTracksProviderUtils.class);
dataSources = AndroidMock.createNiceMock("dataSources", DataSourcesWrapper.class);
listeners = new TrackDataListeners();
hub = new TrackDataHub(context, listeners, sharedPreferences, providerUtils, TARGET_POINTS) {
@Override
protected DataSourcesWrapper newDataSources() {
return dataSources;
}
@Override
protected void runInListenerThread(Runnable runnable) {
// Run everything in the same thread.
runnable.run();
}
@Override
protected float getDeclinationFor(Location location, long timestamp) {
return declination;
}
};
listener1 = AndroidMock.createStrictMock("listener1", TrackDataListener.class);
listener2 = AndroidMock.createStrictMock("listener2", TrackDataListener.class);
PreferencesUtils.setLong(context, R.string.recording_track_id_key, TRACK_ID);
PreferencesUtils.setLong(context, R.string.selected_track_id_key, TRACK_ID);
}
@Override
protected void tearDown() throws Exception {
AndroidMock.reset(dataSources);
// Expect everything to be unregistered.
if (preferenceListenerCapture.hasCaptured()) {
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListenerCapture.getValue());
}
dataSources.removeLocationUpdates(isA(LocationListener.class));
dataSources.unregisterSensorListener(isA(SensorEventListener.class));
dataSources.unregisterContentObserver(isA(ContentObserver.class));
AndroidMock.expectLastCall().times(3);
AndroidMock.replay(dataSources);
hub.stop();
hub = null;
super.tearDown();
}
public void testTrackListen() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
Track track = new Track();
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
expectStart();
dataSources.registerContentObserver(
eq(TracksColumns.CONTENT_URI), eq(false), capture(observerCapture));
// Expect the initial loading.
// Both listeners (registered before and after start) should get the same data.
listener1.onTrackUpdated(track);
listener2.onTrackUpdated(track);
replay();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.TRACK_UPDATES));
hub.start();
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.TRACK_UPDATES));
verifyAndReset();
ContentObserver observer = observerCapture.getValue();
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
// Now expect an update.
listener1.onTrackUpdated(track);
listener2.onTrackUpdated(track);
replay();
observer.onChange(false);
verifyAndReset();
// Unregister one, get another update.
expect(providerUtils.getTrack(TRACK_ID)).andStubReturn(track);
listener2.onTrackUpdated(track);
replay();
hub.unregisterTrackDataListener(listener1);
observer.onChange(false);
verifyAndReset();
// Unregister the other, expect internal unregistration
dataSources.unregisterContentObserver(observer);
replay();
hub.unregisterTrackDataListener(listener2);
observer.onChange(false);
verifyAndReset();
}
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 = 1; i <= size; i++) {
cursor.addRow(new Object[] { i });
}
return cursor;
}
}
private static class FixedSizeLocationIterator implements LocationIterator {
private final long startId;
private final Location[] locs;
private final Set<Integer> splitIndexSet = new HashSet<Integer>();
private int currentIdx = -1;
public FixedSizeLocationIterator(long startId, int size) {
this(startId, size, null);
}
public FixedSizeLocationIterator(long startId, int size, int... splitIndices) {
this.startId = startId;
this.locs = new Location[size];
for (int i = 0; i < size; i++) {
Location loc = new Location("gps");
loc.setLatitude(-15.0 + i / 1000.0);
loc.setLongitude(37 + i / 1000.0);
loc.setAltitude(i);
locs[i] = loc;
}
if (splitIndices != null) {
for (int splitIdx : splitIndices) {
splitIndexSet.add(splitIdx);
Location splitLoc = locs[splitIdx];
splitLoc.setLatitude(100.0);
splitLoc.setLongitude(200.0);
}
}
}
public void expectLocationsDelivered(TrackDataListener listener) {
for (int i = 0; i < locs.length; i++) {
if (splitIndexSet.contains(i)) {
listener.onSegmentSplit();
} else {
listener.onNewTrackPoint(locs[i]);
}
}
}
public void expectSampledLocationsDelivered(
TrackDataListener listener, int sampleFrequency, boolean includeSampledOut) {
for (int i = 0; i < locs.length; i++) {
if (splitIndexSet.contains(i)) {
listener.onSegmentSplit();
} else if (i % sampleFrequency == 0) {
listener.onNewTrackPoint(locs[i]);
} else if (includeSampledOut) {
listener.onSampledOutTrackPoint(locs[i]);
}
}
}
@Override
public boolean hasNext() {
return currentIdx < (locs.length - 1);
}
@Override
public Location next() {
currentIdx++;
return locs[currentIdx];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public long getLocationId() {
return startId + currentIdx;
}
@Override
public void close() {
// Do nothing
}
}
public void testWaypointListen() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
Waypoint wpt1 = new Waypoint(),
wpt2 = new Waypoint(),
wpt3 = new Waypoint(),
wpt4 = new Waypoint();
Location loc = new Location("gps");
loc.setLatitude(10.0);
loc.setLongitude(8.0);
wpt1.setLocation(loc);
wpt2.setLocation(loc);
wpt3.setLocation(loc);
wpt4.setLocation(loc);
expect(providerUtils.getWaypointsCursor(
eq(TRACK_ID), leq(0L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(2));
expect(providerUtils.createWaypoint(isA(Cursor.class)))
.andReturn(wpt1)
.andReturn(wpt2)
.andReturn(wpt1)
.andReturn(wpt2);
expectStart();
dataSources.registerContentObserver(
eq(WaypointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
// Expect the initial loading.
// Both listeners (registered before and after start) should get the same data.
listener1.clearWaypoints();
listener1.onNewWaypoint(wpt1);
listener1.onNewWaypoint(wpt2);
listener1.onNewWaypointsDone();
listener2.clearWaypoints();
listener2.onNewWaypoint(wpt1);
listener2.onNewWaypoint(wpt2);
listener2.onNewWaypointsDone();
replay();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.WAYPOINT_UPDATES));
hub.start();
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.WAYPOINT_UPDATES));
verifyAndReset();
ContentObserver observer = observerCapture.getValue();
expect(providerUtils.getWaypointsCursor(
eq(TRACK_ID), leq(0L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(3));
expect(providerUtils.createWaypoint(isA(Cursor.class)))
.andReturn(wpt1)
.andReturn(wpt2)
.andReturn(wpt3);
// Now expect an update.
listener1.clearWaypoints();
listener2.clearWaypoints();
listener1.onNewWaypoint(wpt1);
listener2.onNewWaypoint(wpt1);
listener1.onNewWaypoint(wpt2);
listener2.onNewWaypoint(wpt2);
listener1.onNewWaypoint(wpt3);
listener2.onNewWaypoint(wpt3);
listener1.onNewWaypointsDone();
listener2.onNewWaypointsDone();
replay();
observer.onChange(false);
verifyAndReset();
// Unregister one, get another update.
expect(providerUtils.getWaypointsCursor(
eq(TRACK_ID), leq(0L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(4));
expect(providerUtils.createWaypoint(isA(Cursor.class)))
.andReturn(wpt1)
.andReturn(wpt2)
.andReturn(wpt3)
.andReturn(wpt4);
// Now expect an update.
listener2.clearWaypoints();
listener2.onNewWaypoint(wpt1);
listener2.onNewWaypoint(wpt2);
listener2.onNewWaypoint(wpt3);
listener2.onNewWaypoint(wpt4);
listener2.onNewWaypointsDone();
replay();
hub.unregisterTrackDataListener(listener1);
observer.onChange(false);
verifyAndReset();
// Unregister the other, expect internal unregistration
dataSources.unregisterContentObserver(observer);
replay();
hub.unregisterTrackDataListener(listener2);
observer.onChange(false);
verifyAndReset();
}
public void testPointsListen() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
expectStart();
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(10L);
listener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.start();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Register a second listener - it will get the same points as the previous one
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(10L);
listener2.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener2);
listener2.onNewTrackPointsDone();
replay();
hub.start();
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Deliver more points - should go to both listeners, without clearing.
ContentObserver observer = observerCapture.getValue();
locationIterator = new FixedSizeLocationIterator(11, 10, 1);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(20L);
locationIterator.expectLocationsDelivered(listener1);
locationIterator.expectLocationsDelivered(listener2);
listener1.onNewTrackPointsDone();
listener2.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
// Unregister listener1, switch tracks to ensure data is cleared/reloaded.
locationIterator = new FixedSizeLocationIterator(101, 10);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID + 1)).andReturn(110L);
listener2.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener2);
listener2.onNewTrackPointsDone();
replay();
hub.unregisterTrackDataListener(listener1);
hub.loadTrack(TRACK_ID + 1);
verifyAndReset();
}
public void testPointsListen_beforeStart() {
}
public void testPointsListen_reRegister() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
expectStart();
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(10L);
listener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.start();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Unregister
ContentObserver observer = observerCapture.getValue();
dataSources.unregisterContentObserver(observer);
replay();
hub.unregisterTrackDataListener(listener1);
verifyAndReset();
// Register again, except only points since unregistered.
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
locationIterator = new FixedSizeLocationIterator(11, 10);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(20L);
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Deliver more points - should still be incremental.
locationIterator = new FixedSizeLocationIterator(21, 10, 1);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(21L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(30L);
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
}
public void testPointsListen_reRegisterTrackChanged() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
expectStart();
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(10L);
listener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.start();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Unregister
ContentObserver observer = observerCapture.getValue();
dataSources.unregisterContentObserver(observer);
replay();
hub.unregisterTrackDataListener(listener1);
verifyAndReset();
// Register again after track changed, expect all points.
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
locationIterator = new FixedSizeLocationIterator(1, 10);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID + 1)).andReturn(10L);
listener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.loadTrack(TRACK_ID + 1);
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
}
public void testPointsListen_largeTrackSampling() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
expectStart();
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 200, 4, 25, 71, 120);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(200L);
listener1.clearTrackPoints();
listener2.clearTrackPoints();
locationIterator.expectSampledLocationsDelivered(listener1, 4, false);
locationIterator.expectSampledLocationsDelivered(listener2, 4, true);
listener1.onNewTrackPointsDone();
listener2.onNewTrackPointsDone();
replay();
hub.registerTrackDataListener(listener1,
EnumSet.of(ListenerDataType.POINT_UPDATES));
hub.registerTrackDataListener(listener2,
EnumSet.of(ListenerDataType.POINT_UPDATES, ListenerDataType.SAMPLED_OUT_POINT_UPDATES));
hub.start();
verifyAndReset();
}
public void testPointsListen_resampling() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
expectStart();
dataSources.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), eq(false), capture(observerCapture));
// Deliver 30 points (no sampling happens)
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(30L);
listener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(listener1);
listener1.onNewTrackPointsDone();
replay();
hub.start();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.POINT_UPDATES));
verifyAndReset();
// Now deliver 30 more (incrementally sampled)
ContentObserver observer = observerCapture.getValue();
locationIterator = new FixedSizeLocationIterator(31, 30);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(31L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(60L);
locationIterator.expectSampledLocationsDelivered(listener1, 2, false);
listener1.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
// Now another 30 (triggers resampling)
locationIterator = new FixedSizeLocationIterator(1, 90);
expect(providerUtils.getLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(90L);
listener1.clearTrackPoints();
locationIterator.expectSampledLocationsDelivered(listener1, 2, false);
listener1.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
}
public void testLocationListen() {
// TODO
}
public void testCompassListen() throws Exception {
AndroidMock.resetToDefault(listener1);
Sensor compass = newSensor();
expect(dataSources.getSensor(Sensor.TYPE_ORIENTATION)).andReturn(compass);
Capture<SensorEventListener> listenerCapture = new Capture<SensorEventListener>();
dataSources.registerSensorListener(capture(listenerCapture), same(compass), anyInt());
Capture<LocationListener> locationListenerCapture = new Capture<LocationListener>();
dataSources.requestLocationUpdates(capture(locationListenerCapture));
SensorEvent event = newSensorEvent();
event.sensor = compass;
// First, get a dummy heading update.
listener1.onCurrentHeadingChanged(0.0);
// Then, get a heading update without a known location (thus can't calculate declination).
listener1.onCurrentHeadingChanged(42.0f);
// Also expect location updates which are not relevant to us.
listener1.onProviderStateChange(isA(ProviderState.class));
AndroidMock.expectLastCall().anyTimes();
replay();
hub.registerTrackDataListener(listener1,
EnumSet.of(ListenerDataType.COMPASS_UPDATES, ListenerDataType.LOCATION_UPDATES));
hub.start();
SensorEventListener sensorListener = listenerCapture.getValue();
LocationListener locationListener = locationListenerCapture.getValue();
event.values[0] = 42.0f;
sensorListener.onSensorChanged(event);
verifyAndReset();
// Expect the heading update to include declination.
listener1.onCurrentHeadingChanged(52.0);
// Also expect location updates which are not relevant to us.
listener1.onProviderStateChange(isA(ProviderState.class));
AndroidMock.expectLastCall().anyTimes();
listener1.onCurrentLocationChanged(isA(Location.class));
AndroidMock.expectLastCall().anyTimes();
replay();
// Now try injecting a location update, triggering a declination update.
Location location = new Location("gps");
location.setLatitude(10.0);
location.setLongitude(20.0);
location.setAltitude(30.0);
declination = 10.0f;
locationListener.onLocationChanged(location);
sensorListener.onSensorChanged(event);
verifyAndReset();
listener1.onCurrentHeadingChanged(52.0);
replay();
// Now try changing the known declination - it should still return the old declination, since
// updates only happen sparsely.
declination = 20.0f;
sensorListener.onSensorChanged(event);
verifyAndReset();
}
private Sensor newSensor() throws Exception {
Constructor<Sensor> constructor = Sensor.class.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
}
private SensorEvent newSensorEvent() throws Exception {
Constructor<SensorEvent> constructor = SensorEvent.class.getDeclaredConstructor(int.class);
constructor.setAccessible(true);
return constructor.newInstance(3);
}
public void testDisplayPreferencesListen() throws Exception {
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
Capture<OnSharedPreferenceChangeListener> listenerCapture =
new Capture<OnSharedPreferenceChangeListener>();
dataSources.registerOnSharedPreferenceChangeListener(capture(listenerCapture));
expect(listener1.onUnitsChanged(true)).andReturn(false);
expect(listener2.onUnitsChanged(true)).andReturn(false);
expect(listener1.onReportSpeedChanged(true)).andReturn(false);
expect(listener2.onReportSpeedChanged(true)).andReturn(false);
replay();
hub.registerTrackDataListener(listener1, EnumSet.of(ListenerDataType.DISPLAY_PREFERENCES));
hub.start();
hub.registerTrackDataListener(listener2, EnumSet.of(ListenerDataType.DISPLAY_PREFERENCES));
verifyAndReset();
expect(listener1.onReportSpeedChanged(false)).andReturn(false);
expect(listener2.onReportSpeedChanged(false)).andReturn(false);
replay();
PreferencesUtils.setBoolean(context, R.string.report_speed_key, false);
OnSharedPreferenceChangeListener listener = listenerCapture.getValue();
listener.onSharedPreferenceChanged(
sharedPreferences, PreferencesUtils.getKey(context, R.string.report_speed_key));
AndroidMock.verify(dataSources, providerUtils, listener1, listener2);
AndroidMock.reset(dataSources, providerUtils, listener1, listener2);
expect(listener1.onUnitsChanged(false)).andReturn(false);
expect(listener2.onUnitsChanged(false)).andReturn(false);
replay();
PreferencesUtils.setBoolean(context, R.string.metric_units_key, false);
listener.onSharedPreferenceChanged(
sharedPreferences, PreferencesUtils.getKey(context, R.string.metric_units_key));
verifyAndReset();
}
private void expectStart() {
dataSources.registerOnSharedPreferenceChangeListener(capture(preferenceListenerCapture));
}
private void replay() {
AndroidMock.replay(dataSources, providerUtils, listener1, listener2);
}
private void verifyAndReset() {
AndroidMock.verify(listener1, listener2, dataSources, providerUtils);
AndroidMock.reset(listener1, listener2, dataSources, providerUtils);
}
}
@@ -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.WaypointCreationRequest.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");
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());
}
}
@@ -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.endtoendtest;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.widget.CheckBox;
import java.util.ArrayList;
/**
* Tests creating a track with markers, and editing and sending send a track.
*
* @author Youtao Liu
*/
public class CreateAndSendTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String WAYPOINT_NAME = "testWaypoint";
private static final String RELATIVE_STARTTIME_POSTFIX = "mins ago";
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public CreateAndSendTrackTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
System.out.println(activityMyTracks.getString(R.string.value_unknown));
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Creates a track with markers and the setting to send to google.
*/
public void testCreateAndSendTrack() {
EndToEndTestUtils.createTrackIfEmpty(1, false);
instrumentation.waitForIdleSync();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_send_google), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.send_google_title));
EndToEndTestUtils.rotateCurrentActivity();
instrumentation.waitForIdleSync();
ArrayList<CheckBox> checkBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
for (int i = 0; i < checkBoxs.size(); i++) {
if (checkBoxs.get(i).isChecked()) {
EndToEndTestUtils.SOLO.clickOnCheckBox(i);
}
}
if (checkBoxs.size() < 3) {
EndToEndTestUtils.SOLO.scrollDown();
checkBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
for (int i = 0; i < checkBoxs.size(); i++) {
if (checkBoxs.get(i).isChecked()) {
EndToEndTestUtils.SOLO.clickOnCheckBox(i);
}
}
}
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.send_google_send_now));
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.send_google_no_service_selected)));
// Stop here for do not really send.
}
/**
* Tests editing a track.
*/
public void testEditTrack() {
EndToEndTestUtils.createTrackIfEmpty(1, false);
instrumentation.waitForIdleSync();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_edit), true);
String newTrackName = EndToEndTestUtils.TRACK_NAME_PREFIX + "_new" + System.currentTimeMillis();
String newType = "type" + newTrackName;
String newDesc = "desc" + newTrackName;
instrumentation.waitForIdleSync();
EndToEndTestUtils.rotateAllActivities();
sendKeys(KeyEvent.KEYCODE_DEL);
EndToEndTestUtils.SOLO.enterText(0, newTrackName);
sendKeys(KeyEvent.KEYCODE_TAB);
EndToEndTestUtils.SOLO.enterText(1, newType);
sendKeys(KeyEvent.KEYCODE_TAB);
EndToEndTestUtils.SOLO.enterText(2, newDesc);
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
// Go back to track list.
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.searchText(newTrackName));
assertTrue(EndToEndTestUtils.SOLO.searchText(newDesc));
}
/**
* Creates one track with a two locations, a way point and a statistics point.
*/
public void testCreateTrackWithMarkers() {
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
// Send Gps before send marker.
EndToEndTestUtils.sendGps(2);
if (EndToEndTestUtils.hasActionBar) {
// Check the title is Recording.
assertTrue(EndToEndTestUtils.SOLO.searchText(activityMyTracks
.getString(R.string.icon_recording)));
}
createWaypoint();
EndToEndTestUtils.sendGps(2);
// Back to tracks list.
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.stopRecording(false);
EndToEndTestUtils.trackName = EndToEndTestUtils.TRACK_NAME_PREFIX + System.currentTimeMillis();
EndToEndTestUtils.SOLO.enterText(0, EndToEndTestUtils.trackName);
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
// Check the new track
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.trackName, 1, 5000, true,
false));
}
/**
* Tests the display of track start time. Use relative time (x mins ago) for
* the start time if it is within the past week. But only show the start time
* if it is different from the track name.
*/
public void testTrackStartTime() {
// Delete all track first.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_delete_all), true);
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
// Test should not show relative time.
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(false);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertFalse(EndToEndTestUtils.SOLO.waitForText(RELATIVE_STARTTIME_POSTFIX, 1, 500));
// Test should show relative time for createSimpleTrack would save a track
// name that is different with the start time.
EndToEndTestUtils.createSimpleTrack(2);
EndToEndTestUtils.SOLO.goBack();
assertTrue(EndToEndTestUtils.SOLO.waitForText(RELATIVE_STARTTIME_POSTFIX, 1, 5000));
}
/**
* Creates a way point and a split maker during track recording.
*/
private void createWaypoint() {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_markers), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.marker_list_empty_message));
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_insert_marker), true);
// Rotate when show insert page.
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.SOLO.enterText(0, WAYPOINT_NAME);
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_add));
assertTrue(EndToEndTestUtils.SOLO.searchText(WAYPOINT_NAME));
EndToEndTestUtils.SOLO.goBack();
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,123 @@
/*
* 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.TrackListActivity;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.ListView;
import java.util.ArrayList;
/**
* Tests the delete of MyTracks.
*
* @author Youtao Liu
*/
public class DeleteTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public DeleteTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Deletes all tracks.
*/
public void testDeleteAllTracks() {
EndToEndTestUtils.createTrackIfEmpty(1, true);
instrumentation.waitForIdleSync();
// There is at least one track.
ArrayList<ListView> trackListView = EndToEndTestUtils.SOLO.getCurrentListViews();
assertTrue(trackListView.size() > 0);
assertTrue(trackListView.get(0).getCount() > 0);
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_delete_all), true);
instrumentation.waitForIdleSync();
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
// There is no track now.
trackListView = EndToEndTestUtils.SOLO.getCurrentListViews();
assertEquals(0, trackListView.get(0).getCount());
// Export when there is no track.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_save_all), true);
EndToEndTestUtils.SOLO
.clickOnText(String.format(activityMyTracks.getString(R.string.menu_save_format),
EndToEndTestUtils.GPX.toUpperCase()));
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.sd_card_save_error_no_track)));
EndToEndTestUtils.SOLO.clickLongOnText(activityMyTracks.getString(R.string.generic_ok));
}
/**
* Deletes only one track.
*/
public void testDeleteSingleTrack() {
EndToEndTestUtils.createTrackIfEmpty(1, true);
instrumentation.waitForIdleSync();
// Get the number of track( or tracks)
ArrayList<ListView> trackListView = EndToEndTestUtils.SOLO.getCurrentListViews();
int trackNumberOld = trackListView.get(0).getCount();
EndToEndTestUtils.SOLO.clickOnView(trackListView.get(0).getChildAt(0));
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_delete), true);
EndToEndTestUtils.SOLO.clickLongOnText(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
trackListView = EndToEndTestUtils.SOLO.getCurrentListViews();
int trackNumberNew = trackListView.get(0).getCount();
assertEquals(trackNumberOld - 1, trackNumberNew);
}
/**
* Deletes a track which is under recording.
*/
public void testDeleteOneTrackUnderRecording() {
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_stop_recording),
false));
instrumentation.waitForIdleSync();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_delete),
true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_record_track),
false));
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.findMenuItem(
activityMyTracks.getString(R.string.menu_record_track), false));
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,488 @@
/*
* 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.TrackListActivity;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R;
import com.jayway.android.robotium.solo.Solo;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.res.Configuration;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
* Provides utilities to smoke test.
*
* @author Youtao Liu
*/
public class EndToEndTestUtils {
private static final String ANDROID_LOCAL_IP = "10.0.2.2";
// usually 5554.
private static final int ANDROID_LOCAL_PORT = 5554;
private static final int ORIENTATION_PORTRAIT = 1;
private static final int ORIENTATION_LANDSCAPE = 0;
// Pause 200ms between each send.
static int PAUSE = 200;
private static final float START_LONGITUDE = 51;
private static final float START_LATITUDE = -1.3f;
private static final float DELTA_LONGITUDE = 0.0005f;
private static final float DELTA_LADITUDE = 0.0005f;
private static final String MOREOPTION_CLASSNAME = "com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton";
static final String TRACK_NAME_PREFIX = "testTrackName";
static final String GPX = "gpx";
static final String KML = "kml";
static final String CSV = "csv";
static final String TCX = "tcx";
static final String BACKUPS = "backups";
static final String MENU_MORE = "More";
static String trackName;
static Solo SOLO;
static Instrumentation INSTRUMENTATION;
static TrackListActivity ACTIVITYMYTRACKS;
// Check whether the UI has an action bar which is related with the version of
// Android OS.
static boolean hasActionBar = false;
static boolean isCheckedFirstLaunch = false;
private EndToEndTestUtils() {}
/**
* Sends Gps data to emulator.
*
* @param number send times
*/
public static void sendGps(int number) {
if (number < 1) {
return;
}
PrintStream out = null;
Socket socket = null;
try {
socket = new Socket(ANDROID_LOCAL_IP, ANDROID_LOCAL_PORT);
out = new PrintStream(socket.getOutputStream());
float longitude = START_LONGITUDE;
float latitude = START_LATITUDE;
for (int i = 0; i < number; i++) {
Thread.sleep(PAUSE);
out.println("geo fix " + latitude + " " + longitude);
longitude += DELTA_LONGITUDE;
latitude += DELTA_LADITUDE;
}
} catch (UnknownHostException e) {
System.exit(-1);
} catch (IOException e) {
System.exit(-1);
} catch (InterruptedException e) {
System.exit(-1);
} finally {
if (out != null) {
out.close();
}
}
}
/**
* A setup for all end-to-end tests.
*
* @param instrumentation the instrumentation is used for test
* @param activityMyTracks the startup activity
*/
static void setupForAllTest(Instrumentation instrumentation, TrackListActivity activityMyTracks) {
EndToEndTestUtils.INSTRUMENTATION = instrumentation;
EndToEndTestUtils.ACTIVITYMYTRACKS = activityMyTracks;
EndToEndTestUtils.SOLO = new Solo(EndToEndTestUtils.INSTRUMENTATION,
EndToEndTestUtils.ACTIVITYMYTRACKS);
// 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 (!EndToEndTestUtils.isCheckedFirstLaunch) {
if ((EndToEndTestUtils.getButtonOnScreen(EndToEndTestUtils.ACTIVITYMYTRACKS
.getString(R.string.eula_accept)) != null)) {
EndToEndTestUtils.verifyFirstLaunch();
} else if (EndToEndTestUtils.SOLO.waitForText(
// After reset setting, welcome page will show again.
ACTIVITYMYTRACKS.getString(R.string.welcome_title), 0, 500)) {
resetPreferredUnits();
}
EndToEndTestUtils.isCheckedFirstLaunch = true;
EndToEndTestUtils.setHasActionBar();
} else if (EndToEndTestUtils.SOLO.waitForText(
// After reset setting, welcome page will show again.
ACTIVITYMYTRACKS.getString(R.string.welcome_title), 0, 500)) {
resetPreferredUnits();
}
// Check whether is under recording. If previous test failed, the recording
// may not be recording.
if (isUnderRecording()) {
stopRecording(true);
}
}
/**
* Checks if need reset preferred units.
*/
private static void resetPreferredUnits() {
EndToEndTestUtils.SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.generic_ok));
SOLO.waitForText(ACTIVITYMYTRACKS.getString(R.string.settings_stats_units_title));
EndToEndTestUtils.SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.generic_ok));
INSTRUMENTATION.waitForIdleSync();
}
/**
* Rotates the given activity.
*
* @param activity a given activity
*/
static void rotateActivity(Activity activity) {
activity
.setRequestedOrientation(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT);
}
/**
* Accepts terms and configures units.
*/
static void verifyFirstLaunch() {
SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.eula_accept));
// Click for welcome.
SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.generic_ok));
// Click for choose units.
SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.generic_ok));
INSTRUMENTATION.waitForIdleSync();
}
/**
* 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
*/
static void createSimpleTrack(int numberOfGpsData) {
startRecording();
EndToEndTestUtils.sendGps(numberOfGpsData);
INSTRUMENTATION.waitForIdleSync();
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
*/
static boolean isTrackListEmpty(boolean isClick) {
int trackNumber = SOLO.getCurrentListViews().get(0).getCount();
if(trackNumber <= 0) {
return true;
}
View oneTrack = SOLO.getCurrentListViews().get(0).getChildAt(0);
trackName = (String) ((TextView) oneTrack.findViewById(R.id.list_item_name)).getText();
if (isClick) {
SOLO.clickOnView(oneTrack);
}
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
*/
static void createTrackIfEmpty(int gpsNumber, boolean showTrackList) {
if (EndToEndTestUtils.isTrackListEmpty(!showTrackList)) {
// Create a simple track.
EndToEndTestUtils.createSimpleTrack(gpsNumber);
if (showTrackList) {
EndToEndTestUtils.SOLO.goBack();
}
}
}
/**
* Starts recoding track.
*/
static void startRecording() {
if (hasActionBar) {
Button startButton = getButtonOnScreen(ACTIVITYMYTRACKS.getString(R.string.menu_record_track));
// In case a track is recording.
if (startButton == null) {
stopRecording(true);
startButton = getButtonOnScreen(ACTIVITYMYTRACKS.getString(R.string.menu_record_track));
}
SOLO.clickOnView(startButton);
} else {
showMoreMenuItem();
if (!SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_record_track))) {
// Check if in TrackDetailActivity.
if (SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_play))) {
SOLO.goBack();
} else {
// In case a track is recording.
stopRecording(true);
showMoreMenuItem();
}
}
INSTRUMENTATION.waitForIdleSync();
SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.menu_record_track));
}
}
/**
* Checks if the MyTracks is under recording.
*
* @return true if it is under recording.
*/
static boolean isUnderRecording() {
if (hasActionBar) {
return getButtonOnScreen(ACTIVITYMYTRACKS
.getString(R.string.menu_record_track)) == null;
}
showMoreMenuItem();
if (SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_record_track))
|| SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_play))) {
SOLO.goBack();
return false;
}
SOLO.goBack();
return true;
}
/**
* Stops recoding track.
*
* @param isSave ture means should save this track
*/
static void stopRecording(boolean isSave) {
if (hasActionBar) {
SOLO.clickOnView(getButtonOnScreen(ACTIVITYMYTRACKS.getString(R.string.menu_stop_recording)));
} else {
showMoreMenuItem();
INSTRUMENTATION.waitForIdleSync();
SOLO.clickOnText(ACTIVITYMYTRACKS.getString(R.string.menu_stop_recording));
}
if (isSave) {
INSTRUMENTATION.waitForIdleSync();
// Make every track name is unique to make sure every check can be
// trusted.
EndToEndTestUtils.trackName = EndToEndTestUtils.TRACK_NAME_PREFIX
+ System.currentTimeMillis();
SOLO.enterText(0, trackName);
SOLO.clickLongOnText(ACTIVITYMYTRACKS.getString(R.string.generic_save));
}
}
/**
* Deletes a kind of track in MyTracks folder.
*
* @param trackKind the kind of track
*/
static void deleteExportedFiles(String trackKind) {
File[] allFiles = (new File(FileUtils.buildExternalDirectoryPath(trackKind.toLowerCase())))
.listFiles();
if (allFiles != null) {
for (File oneFile : allFiles) {
oneFile.delete();
}
}
}
/**
* Gets a kind of exported files.
*
* @param trackKind the kind of track
* @return files array of such kind of exported tracks
*/
static File[] getExportedFiles(final String trackKind) {
String filePath = FileUtils.buildExternalDirectoryPath(trackKind);
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().indexOf("." + trackKind) > 0;
}
};
return (new File(filePath)).listFiles(filter);
}
/**
* Saves a track to a kind of file in SD card.
*
* @param trackKind the kind of track
*/
static void saveTrackToSdCard(String trackKind) {
deleteExportedFiles(trackKind);
INSTRUMENTATION.waitForIdleSync();
findMenuItem(ACTIVITYMYTRACKS.getString(R.string.menu_save), true);
INSTRUMENTATION.waitForIdleSync();
SOLO.clickOnText(trackKind.toUpperCase());
rotateAllActivities();
SOLO.waitForText(ACTIVITYMYTRACKS.getString(R.string.generic_success_title));
}
/**
* Checks if a button is existed in the screen.
*
* @param buttonName the name string of the button
* @return the button to search, and null means can not find the button
*/
static Button getButtonOnScreen(String buttonName) {
ArrayList<Button> currentButtons = SOLO.getCurrentButtons();
for (Button button : currentButtons) {
String title = (String) button.getText();
if (title.equalsIgnoreCase(buttonName)) {
return button;
}
}
return null;
}
/**
* Checks whether an action bar is shown.
*
* @return false means can not check failed.
*/
static boolean setHasActionBar() {
INSTRUMENTATION.waitForIdleSync();
// If can find record button without pressing Menu, it should be an action
// bar.
Button startButton = getButtonOnScreen(ACTIVITYMYTRACKS.getString(R.string.menu_record_track));
Button stopButton = getButtonOnScreen(ACTIVITYMYTRACKS.getString(R.string.menu_stop_recording));
if (startButton != null || stopButton != null) {
hasActionBar = true;
} else {
showMoreMenuItem();
if (SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_record_track))
|| SOLO.searchText(ACTIVITYMYTRACKS.getString(R.string.menu_stop_recording))) {
hasActionBar = false;
} else {
return false;
}
SOLO.goBack();
}
return true;
}
/**
* Rotates the current activity.
*/
static void rotateCurrentActivity() {
EndToEndTestUtils.rotateActivity(SOLO.getCurrentActivity());
INSTRUMENTATION.waitForIdleSync();
}
/**
* Rotates all activities.
*/
static void rotateAllActivities() {
ArrayList<Activity> allActivities = SOLO.getAllOpenedActivities();
for (Activity activity : allActivities) {
EndToEndTestUtils.rotateActivity(activity);
}
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
*/
static boolean findMenuItem(String menuName, boolean click) {
boolean findResult = false;
// Firstly find in action bar.
Button button = getButtonOnScreen(menuName);
if (button != null) {
findResult = true;
if (click) {
SOLO.clickOnView(button);
}
return findResult;
}
showMoreMenuItem();
if (SOLO.searchText(menuName)) {
findResult = true;
} else if (SOLO.searchText(MENU_MORE)) {
SOLO.clickOnText(MENU_MORE);
findResult = SOLO.searchText(menuName);
}
if (findResult && click) {
SOLO.clickOnText(menuName);
} else {
SOLO.goBack();
}
return findResult;
}
/**
* Get more menu items operation is different for different Android OS.
*/
public static void showMoreMenuItem() {
if (hasActionBar) {
View moreButton = getMoreOptionView();
if (moreButton != null) {
SOLO.clickOnView(moreButton);
return;
}
}
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 EndToEndTestUtils#MOREOPTION_CLASSNAME}.</li>
* </ul>
* @return the more option view. Null means can not find it.
*/
private static View getMoreOptionView() {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view instanceof ImageButton && view.getClass().getName().equals(MOREOPTION_CLASSNAME)) {
return view;
}
}
return null;
}
}
@@ -0,0 +1,137 @@
/*
* 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.TrackListActivity;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import java.io.File;
/**
* Tests the import and export of MyTracks.
*
* @author Youtao Liu
*/
public class ExportAndImportTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public ExportAndImportTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Tests export and import tracks.
* <ul>
* <li>Create two tracks, one of them is empty(Have no Gps data).</li>
* <li>Tests import when there is no track file.</li>
* <li>Tests export tracks to Gpx files.</li>
* <li>Tests import files to tracks.</li>
* <li>Tests export tracks to Kml files.</li>
* </ul>
*/
public void testExportAndImportTracks() {
// Create a new track with 3 gps data.
EndToEndTestUtils.createTrackIfEmpty(3, true);
instrumentation.waitForIdleSync();
// Create a empty track.
EndToEndTestUtils.createSimpleTrack(0);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Delete all exported gpx and kml tracks.
EndToEndTestUtils.deleteExportedFiles(EndToEndTestUtils.GPX);
EndToEndTestUtils.deleteExportedFiles(EndToEndTestUtils.KML);
int gpxFilesNumber = 0;
File[] allGpxFiles = EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX);
// For the first export, there is no MyTracks folder.
if (allGpxFiles != null) {
gpxFilesNumber = EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length;
}
// Get track number in current track list of MyTracks.
int trackNumber = EndToEndTestUtils.SOLO.getCurrentListViews().get(0).getCount();
// No file to imported.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_import), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.sd_card_import_error_no_file,
FileUtils.buildExternalDirectoryPath(EndToEndTestUtils.GPX)));
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_ok));
// Click to export tracks(At least one track) to Gpx files.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_save_all), true);
EndToEndTestUtils.SOLO
.clickOnText(String.format(activityMyTracks.getString(R.string.menu_save_format),
EndToEndTestUtils.GPX.toUpperCase()));
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.sd_card_save_success));
EndToEndTestUtils.SOLO.clickLongOnText(activityMyTracks.getString(R.string.generic_ok));
// Check export file.
assertEquals(gpxFilesNumber + trackNumber,
EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length);
instrumentation.waitForIdleSync();
// Click to import track.
gpxFilesNumber = EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length;
trackNumber = EndToEndTestUtils.SOLO.getCurrentListViews().get(0).getCount();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_import), true);
EndToEndTestUtils.rotateAllActivities();
// Wait for the prefix of import success string is much faster than wait
// the whole string.
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.sd_card_import_success_count).split(
"%")[0]);
// Check import tracks should be equal with the sum of trackNumber and
// gpxFilesNumber;
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
assertEquals(trackNumber + gpxFilesNumber, EndToEndTestUtils.SOLO.getCurrentListViews().get(0)
.getCount());
// Click to export tracks(At least two tracks) to KML files.
gpxFilesNumber = EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length;
trackNumber = EndToEndTestUtils.SOLO.getCurrentListViews().get(0).getCount();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_save_all), true);
EndToEndTestUtils.SOLO
.clickOnText(String.format(activityMyTracks.getString(R.string.menu_save_format),
EndToEndTestUtils.KML.toUpperCase()));
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.sd_card_save_success));
EndToEndTestUtils.SOLO.clickLongOnText(activityMyTracks.getString(R.string.generic_ok));
// Check export files.
assertEquals(gpxFilesNumber, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length);
assertEquals(trackNumber, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.KML).length);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,69 @@
/*
* 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.TrackListActivity;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
/**
* Tests the function of go to my location.
*
* @author Youtao Liu
*/
public class GoToMyLocationTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public GoToMyLocationTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Tests the menu My Location.
*/
public void testGotoMyLocation() {
EndToEndTestUtils.createTrackIfEmpty(1, false);
EndToEndTestUtils.sendGps(30);
View myLocation = EndToEndTestUtils.SOLO.getCurrentActivity()
.findViewById(R.id.map_my_location);
EndToEndTestUtils.SOLO.clickOnView(myLocation);
if (!EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.my_location_no_location), 1, 1000)) {
// TODO How to verify the location is shown on the map.
}
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -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.endtoendtest;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
/**
* Tests some menu items of MyTracks.
*
* @author Youtao Liu
*/
public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public MenuItemsTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Tests following items in More menu.
* <ul>
* <li>Tests the aggregated statistics activity.</li>
* <li>Tests the Sensor state activity.</li>
* <li>Tests the help menu.</li>
* </ul>
*/
public void testSomeMenuItems() {
// Menu in TrackListActivity.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_aggregated_statistics),
true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.stats_total_distance));
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
EndToEndTestUtils.createTrackIfEmpty(1, false);
instrumentation.waitForIdleSync();
// Menu in TrackDetailActivity.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_sensor_state), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.sensor_state_last_sensor_time));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_help), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.help_about));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,84 @@
/*
* 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.TrackListActivity;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
/**
* Tests sending a track to SD card.
*
* @author Youtao Liu
*/
public class SaveToSdCardTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public SaveToSdCardTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
EndToEndTestUtils.createTrackIfEmpty(1, false);
}
/**
* Tests saving a track to SD card as a GPX file.
*/
public void testSaveToSdCard_GPX() {
EndToEndTestUtils.saveTrackToSdCard(EndToEndTestUtils.GPX);
assertEquals(1, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.GPX).length);
}
/**
* Tests saving a track to SD card as a KML file.
*/
public void testSaveToSdCard_KML() {
EndToEndTestUtils.saveTrackToSdCard(EndToEndTestUtils.KML);
assertEquals(1, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.KML).length);
}
/**
* Tests saving a track to SD card as a CSV file.
*/
public void testSaveToSdCard_CSV() {
EndToEndTestUtils.saveTrackToSdCard(EndToEndTestUtils.CSV);
assertEquals(1, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.CSV).length);
}
/**
* Tests saving a track to SD card as a TCX file.
*/
public void testSaveToSdCard_TCX() {
EndToEndTestUtils.saveTrackToSdCard(EndToEndTestUtils.TCX);
assertEquals(1, EndToEndTestUtils.getExportedFiles(EndToEndTestUtils.TCX).length);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -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;
import com.google.android.apps.mytracks.TrackListActivity;
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 setting of MyTracks.
*
* @author Youtao Liu
*/
public class SettingTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private final String DEFAULTACTIVITY = "TestActivity";
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public SettingTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Changes some settings and then reset them. This test case tests three
* points:
* <ul>
* <li>Resets all settings.</li>
* <li>Changes the setting of Display.</li>
* <li>Changes the setting of Sharing.</li>
* </ul>
*/
public void testSetting() {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
instrumentation.waitForIdleSync();
// Rotate on the settings page.
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset));
// Reset all settings at first.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_reset));
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_ok));
// Change a setting of Map.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.track_detail_stats_tab));
instrumentation.waitForIdleSync();
// Rotate on a sub setting page.
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.settings_stats_units_title));
ArrayList<CheckBox> displayCheckBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
boolean useMetric = displayCheckBoxs.get(0).isChecked();
EndToEndTestUtils.SOLO.clickOnCheckBox(0);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
// Change a setting of sharing.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_sharing));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.settings_sharing_map_public), 1, 5000));
ArrayList<CheckBox> sharingCheckBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
boolean newMapsPublic = sharingCheckBoxs.get(0).isChecked();
EndToEndTestUtils.SOLO.clickOnCheckBox(0);
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.settings_sharing_map_public), 1, 5000));
assertEquals(!newMapsPublic, sharingCheckBoxs.get(0).isChecked());
EndToEndTestUtils.SOLO.goBack();
// Reset all settings.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_reset));
EndToEndTestUtils.SOLO.clickOnButton(activityMyTracks.getString(R.string.generic_ok));
// Check settings.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.track_detail_stats_tab));
EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.settings_stats_units_title));
displayCheckBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
assertEquals(useMetric, displayCheckBoxs.get(0).isChecked());
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_sharing));
EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.settings_sharing_allow_access));
sharingCheckBoxs = EndToEndTestUtils.SOLO.getCurrentCheckBoxes();
assertEquals(newMapsPublic, sharingCheckBoxs.get(0).isChecked());
}
/**
* Tests the backup.
*/
public void testBackup() {
// Delete all backup at first.
EndToEndTestUtils.deleteExportedFiles(EndToEndTestUtils.BACKUPS);
EndToEndTestUtils.createTrackIfEmpty(3, true);
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackName));
// Write to SD card.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_backup));
EndToEndTestUtils.SOLO
.clickOnText(activityMyTracks.getString(R.string.settings_backup_now));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.sd_card_save_success), 0, 100000));
instrumentation.waitForIdleSync();
// Delete all tracks.
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_delete_all), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
instrumentation.waitForIdleSync();
// Read from SD card.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_backup));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(R.string.settings_backup_restore));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.sd_card_import_success), 0, 10000));
// Check restore track.
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackName));
}
/**
* Tests the setting of recording. This test changes the default name and
* activity of tracks, and the creates a new track to check it.
*/
public void testRecording() {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.settings_recording));
// Changes the setting of recording name.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(R.string.settings_recording_track_name));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(R.string.settings_recording_track_name_number_option));
// Changes the setting of default activity.
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(R.string.settings_recording_default_activity));
EndToEndTestUtils.SOLO.enterText(0, DEFAULTACTIVITY);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(false);
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.searchText(activityMyTracks.getString(
R.string.track_name_format).split(" ")[0]));
assertTrue(EndToEndTestUtils.SOLO.searchText(DEFAULTACTIVITY));
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_save));
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -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;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.fragments.MapFragment;
import com.google.android.maps.MapView;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.view.View;
import java.util.ArrayList;
/**
* Tests switching views and the menu list of each view.
*
* @author Youtao Liu
*/
public class ViewsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public ViewsTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Switches view from {@link MapFragment} to @ ChartFragment} , then changes
* to @ StatsFragment} . Finally back to {@link MapFragment}. And check some
* menus in these views.
*/
public void testSwitchViewsAndMenusOfView() {
EndToEndTestUtils.createTrackIfEmpty(3, false);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName);
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.track_detail_chart_tab));
EndToEndTestUtils.rotateAllActivities();
EndToEndTestUtils.showMoreMenuItem();
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_settings), 1, 3000));
assertFalse(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_satellite_mode), 1, 0));
assertFalse(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_map_mode), 1, 0));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.track_detail_stats_tab));
EndToEndTestUtils.SOLO.sendKey(KeyEvent.KEYCODE_MENU);
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_settings), 1, 3000));
assertFalse(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_satellite_mode), 1, 0));
assertFalse(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_map_mode), 1, 0));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.track_detail_map_tab));
EndToEndTestUtils.showMoreMenuItem();
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_settings), 1, 3000));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.menu_satellite_mode), 1, 0)
|| EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.menu_map_mode),
1, 0));
}
/**
* Tests the switch between satellite mode and map mode.
*/
public void testSatelliteAndMapView() {
instrumentation.waitForIdleSync();
EndToEndTestUtils.createTrackIfEmpty(1, false);
instrumentation.waitForIdleSync();
// Check current mode.
boolean isMapMode = true;
// If can not find switch menu in top menu, click More menu.
if (!EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_satellite_mode),
false)) {
isMapMode = false;
}
EndToEndTestUtils.showMoreMenuItem();
// Switch to satellite mode if it's map mode now..
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(isMapMode ? R.string.menu_satellite_mode : R.string.menu_map_mode));
isMapMode = !isMapMode;
ArrayList<View> allViews = EndToEndTestUtils.SOLO.getViews();
for (View view : allViews) {
if (view instanceof MapView) {
assertEquals(isMapMode, !((MapView) view).isSatellite());
}
}
instrumentation.waitForIdleSync();
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_help), false);
instrumentation.waitForIdleSync();
EndToEndTestUtils.rotateAllActivities();
// Switch back.
EndToEndTestUtils.showMoreMenuItem();
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks
.getString(isMapMode ? R.string.menu_satellite_mode : R.string.menu_map_mode));
isMapMode = !isMapMode;
allViews = EndToEndTestUtils.SOLO.getViews();
for (View view : allViews) {
if (view instanceof MapView) {
assertEquals(isMapMode, !((MapView) view).isSatellite());
}
}
// Wait for the TrackDetailActivity, or the stop button will can not be
// found in next step.
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.track_detail_chart_tab),
0, 1000);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,333 @@
/*
* 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 ChartFragment chartFragment;
private final double HOURS_PER_UNIT = 60.0;
@Override
protected void setUp() throws Exception {
chartFragment = new ChartFragment();
chartFragment.setChartView(new ChartView(getContext()));
}
/**
* 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.setSensorData(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.setSensorData(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() {
// Set max speed to make the speed of points are valid.
chartFragment.setTrackMaxSpeed(200.0);
/*
* 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(129);
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);
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(132);
double[] point = fillDataPointTestHelper(myTracksLocation);
assertEquals(132.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);
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(134);
double[] point = fillDataPointTestHelper(myTracksLocation);
assertEquals(
HOURS_PER_UNIT / (134.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;
}
}
@@ -0,0 +1,267 @@
/*
* 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.content.ContentTypeIds;
import android.database.MatrixCursor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase;
/**
* Tests for {@link DatabaseDumper}.
*
* @author Rodrigo Damazio
*/
public class DatabaseDumperTest extends TestCase {
/**
* This class is the same as {@link MatrixCursor}, except this class
* implements {@link #getBlob} ({@link MatrixCursor} leaves it
* unimplemented).
*/
private class BlobAwareMatrixCursor extends MatrixCursor {
public BlobAwareMatrixCursor(String[] columnNames) {
super(columnNames);
}
@Override public byte[] getBlob(int columnIndex) {
return getString(columnIndex).getBytes();
}
}
private static final String[] COLUMN_NAMES = {
"intCol", "longCol", "floatCol", "doubleCol", "stringCol", "boolCol", "blobCol"
};
private static final byte[] COLUMN_TYPES = {
ContentTypeIds.INT_TYPE_ID, ContentTypeIds.LONG_TYPE_ID,
ContentTypeIds.FLOAT_TYPE_ID, ContentTypeIds.DOUBLE_TYPE_ID,
ContentTypeIds.STRING_TYPE_ID, ContentTypeIds.BOOLEAN_TYPE_ID,
ContentTypeIds.BLOB_TYPE_ID
};
private static final String[][] FAKE_DATA = {
{ "42", "123456789", "3.1415", "2.72", "lolcat", "1", "blob" },
{ null, "123456789", "3.1415", "2.72", "lolcat", "1", "blob" },
{ "42", null, "3.1415", "2.72", "lolcat", "1", "blob" },
{ "42", "123456789", null, "2.72", "lolcat", "1", "blob" },
{ "42", "123456789", "3.1415", null, "lolcat", "1", "blob" },
{ "42", "123456789", "3.1415", "2.72", null, "1", "blob" },
{ "42", "123456789", "3.1415", "2.72", "lolcat", null, "blob" },
{ "42", "123456789", "3.1415", "2.72", "lolcat", "1", null },
};
private static final long[] EXPECTED_FIELD_SETS = {
0x7F, 0x7E, 0x7D, 0x7B, 0x77, 0x6F, 0x5F, 0x3F
};
private BlobAwareMatrixCursor cursor;
@Override
protected void setUp() throws Exception {
super.setUp();
// Add fake data to the cursor
cursor = new BlobAwareMatrixCursor(COLUMN_NAMES);
for (String[] row : FAKE_DATA) {
cursor.addRow(row);
}
}
public void testWriteAllRows_noNulls() throws Exception {
testWriteAllRows(false);
}
public void testWriteAllRows_withNulls() throws Exception {
testWriteAllRows(true);
}
private void testWriteAllRows(boolean hasNullFields) throws Exception {
// Dump it
DatabaseDumper dumper = new DatabaseDumper(COLUMN_NAMES, COLUMN_TYPES, hasNullFields);
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outStream );
dumper.writeAllRows(cursor, writer);
// Read the results
byte[] result = outStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(result);
DataInputStream reader = new DataInputStream(inputStream);
// Verify the header
assertHeader(reader);
// Verify the number of rows
assertEquals(FAKE_DATA.length, reader.readInt());
// Row 0 -- everything populated
assertEquals(EXPECTED_FIELD_SETS[0], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 1 -- no int
assertEquals(EXPECTED_FIELD_SETS[1], reader.readLong());
if (hasNullFields) reader.readInt();
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 2 -- no long
assertEquals(EXPECTED_FIELD_SETS[2], reader.readLong());
assertEquals(42, reader.readInt());
if (hasNullFields) reader.readLong();
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 3 -- no float
assertEquals(EXPECTED_FIELD_SETS[3], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
if (hasNullFields) reader.readFloat();
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 4 -- no double
assertEquals(EXPECTED_FIELD_SETS[4], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
if (hasNullFields) reader.readDouble();
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 5 -- no string
assertEquals(EXPECTED_FIELD_SETS[5], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
if (hasNullFields) reader.readUTF();
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 6 -- no boolean
assertEquals(EXPECTED_FIELD_SETS[6], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
if (hasNullFields) reader.readBoolean();
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 7 -- no blob
assertEquals(EXPECTED_FIELD_SETS[7], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
if (hasNullFields) {
int length = reader.readInt();
readBlob(reader, length);
}
}
public void testFewerRows() throws Exception {
// Dump only the first two rows
DatabaseDumper dumper = new DatabaseDumper(COLUMN_NAMES, COLUMN_TYPES, false);
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outStream);
dumper.writeHeaders(cursor, 2, writer);
cursor.moveToFirst();
dumper.writeOneRow(cursor, writer);
cursor.moveToNext();
dumper.writeOneRow(cursor, writer);
// Read the results
byte[] result = outStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(result);
DataInputStream reader = new DataInputStream(inputStream);
// Verify the header
assertHeader(reader);
// Verify the number of rows
assertEquals(2, reader.readInt());
// Row 0
assertEquals(EXPECTED_FIELD_SETS[0], reader.readLong());
assertEquals(42, reader.readInt());
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
// Row 1
assertEquals(EXPECTED_FIELD_SETS[1], reader.readLong());
// Null field not read
assertEquals(123456789L, reader.readLong());
assertEquals(3.1415f, reader.readFloat());
assertEquals(2.72, reader.readDouble());
assertEquals("lolcat", reader.readUTF());
assertTrue(reader.readBoolean());
assertEquals(4, reader.readInt());
assertEquals("blob", readBlob(reader, 4));
}
private void assertHeader(DataInputStream reader) throws IOException {
assertEquals(COLUMN_NAMES.length, reader.readInt());
for (int i = 0; i < COLUMN_NAMES.length; i++) {
assertEquals(COLUMN_NAMES[i], reader.readUTF());
assertEquals(COLUMN_TYPES[i], reader.readByte());
}
}
private String readBlob(InputStream reader, int length) throws Exception {
if (length == 0) {
return "";
}
byte[] blob = new byte[length];
assertEquals(length, reader.read(blob));
return new String(blob);
}
}
@@ -0,0 +1,293 @@
/*
* 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.content.ContentTypeIds;
import android.content.ContentValues;
import android.net.Uri;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import junit.framework.TestCase;
/**
* Tests for {@link DatabaseImporter}.
*
* @author Rodrigo Damazio
*/
public class DatabaseImporterTest extends TestCase {
private static final Uri DESTINATION_URI = Uri.parse("http://www.google.com/");
private static final int TEST_BULK_SIZE = 10;
private ArrayList<ContentValues> insertedValues;
private class TestableDatabaseImporter extends DatabaseImporter {
public TestableDatabaseImporter(boolean readNullFields) {
super(DESTINATION_URI, null, readNullFields, TEST_BULK_SIZE);
}
@Override
protected void doBulkInsert(ContentValues[] values) {
insertedValues.ensureCapacity(insertedValues.size() + values.length);
// We need to make a copy of the values since the objects are re-used
for (ContentValues contentValues : values) {
insertedValues.add(new ContentValues(contentValues));
}
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
insertedValues = new ArrayList<ContentValues>();
}
public void testImportAllRows() throws Exception {
testImportAllRows(false);
}
public void testImportAllRows_readNullFields() throws Exception {
testImportAllRows(true);
}
private void testImportAllRows(boolean readNullFields) throws Exception {
// Create a fake data stream to be read
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outputStream);
writeFullHeader(writer);
// Add the number of rows
writer.writeInt(2);
// Add a row with all fields present
writer.writeLong(0x7F);
writer.writeInt(42);
writer.writeBoolean(true);
writer.writeUTF("lolcat");
writer.writeFloat(3.1415f);
writer.writeDouble(2.72);
writer.writeLong(123456789L);
writer.writeInt(4);
writer.writeBytes("blob");
// Add a row with some missing fields
writer.writeLong(0x15);
writer.writeInt(42);
if (readNullFields) writer.writeBoolean(false);
writer.writeUTF("lolcat");
if (readNullFields) writer.writeFloat(0.0f);
writer.writeDouble(2.72);
if (readNullFields) writer.writeLong(0L);
if (readNullFields) writer.writeInt(0); // empty blob
writer.flush();
// Do the importing
DatabaseImporter importer = new TestableDatabaseImporter(readNullFields);
byte[] dataBytes = outputStream.toByteArray();
importer.importAllRows(new DataInputStream(new ByteArrayInputStream(dataBytes)));
assertEquals(2, insertedValues.size());
// Verify the first row
ContentValues value = insertedValues.get(0);
assertEquals(value.toString(), 7, value.size());
assertValue(42, "col1", value);
assertValue(true, "col2", value);
assertValue("lolcat", "col3", value);
assertValue(3.1415f, "col4", value);
assertValue(2.72, "col5", value);
assertValue(123456789L, "col6", value);
assertBlobValue("blob", "col7", value);
// Verify the second row
value = insertedValues.get(1);
assertEquals(value.toString(), 3, value.size());
assertValue(42, "col1", value);
assertValue("lolcat", "col3", value);
assertValue(2.72, "col5", value);
}
public void testImportAllRows_noRows() throws Exception {
// Create a fake data stream to be read
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outputStream);
writeFullHeader(writer);
// Add the number of rows
writer.writeInt(0);
writer.flush();
// Do the importing
DatabaseImporter importer = new TestableDatabaseImporter(false);
byte[] dataBytes = outputStream.toByteArray();
importer.importAllRows(new DataInputStream(new ByteArrayInputStream(dataBytes)));
assertTrue(insertedValues.isEmpty());
}
public void testImportAllRows_emptyRows() throws Exception {
testImportAllRowsWithEmptyRows(false);
}
public void testImportAllRows_emptyRowsWithNulls() throws Exception {
testImportAllRowsWithEmptyRows(true);
}
private void testImportAllRowsWithEmptyRows(boolean readNullFields) throws Exception {
// Create a fake data stream to be read
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outputStream);
writeFullHeader(writer);
// Add the number of rows
writer.writeInt(3);
// Add 2 rows with no fields
for (int i = 0; i < 2; i++) {
writer.writeLong(0);
if (readNullFields) {
writer.writeInt(0);
writer.writeBoolean(false);
writer.writeUTF("");
writer.writeFloat(0.0f);
writer.writeDouble(0.0);
writer.writeLong(0L);
writer.writeInt(0); // empty blob
}
}
// Add a row with some missing fields
writer.writeLong(0x15);
writer.writeInt(42);
if (readNullFields) writer.writeBoolean(false);
writer.writeUTF("lolcat");
if (readNullFields) writer.writeFloat(0.0f);
writer.writeDouble(2.72);
if (readNullFields) writer.writeLong(0L);
if (readNullFields) writer.writeInt(0); // empty blob
writer.flush();
// Do the importing
DatabaseImporter importer = new TestableDatabaseImporter(readNullFields);
byte[] dataBytes = outputStream.toByteArray();
importer.importAllRows(new DataInputStream(new ByteArrayInputStream(dataBytes)));
assertEquals(insertedValues.toString(), 3, insertedValues.size());
ContentValues value = insertedValues.get(0);
assertEquals(value.toString(), 0, value.size());
value = insertedValues.get(1);
assertEquals(value.toString(), 0, value.size());
// Verify the third row (only one with values)
value = insertedValues.get(2);
assertEquals(value.toString(), 3, value.size());
assertFalse(value.containsKey("col2"));
assertFalse(value.containsKey("col4"));
assertFalse(value.containsKey("col6"));
assertValue(42, "col1", value);
assertValue("lolcat", "col3", value);
assertValue(2.72, "col5", value);
}
public void testImportAllRows_bulks() throws Exception {
// Create a fake data stream to be read
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
DataOutputStream writer = new DataOutputStream(outputStream);
// Add the header
writer.writeInt(2);
writer.writeUTF("col1");
writer.writeByte(ContentTypeIds.INT_TYPE_ID);
writer.writeUTF("col2");
writer.writeByte(ContentTypeIds.STRING_TYPE_ID);
// Add lots of rows (so the insertions are split in multiple bulks)
int numRows = TEST_BULK_SIZE * 5 / 2;
writer.writeInt(numRows);
for (int i = 0; i < numRows; i++) {
writer.writeLong(3);
writer.writeInt(i);
writer.writeUTF(Integer.toString(i * 2));
}
writer.flush();
// Do the importing
DatabaseImporter importer = new TestableDatabaseImporter(false);
byte[] dataBytes = outputStream.toByteArray();
importer.importAllRows(new DataInputStream(new ByteArrayInputStream(dataBytes)));
// Verify the rows
assertEquals(numRows, insertedValues.size());
for (int i = 0; i < numRows; i++) {
ContentValues value = insertedValues.get(i);
assertEquals(value.toString(), 2, value.size());
assertValue(i, "col1", value);
assertValue(Integer.toString(i * 2), "col2", value);
}
}
private void writeFullHeader(DataOutputStream writer) throws IOException {
// Add the header
writer.writeInt(7);
writer.writeUTF("col1");
writer.writeByte(ContentTypeIds.INT_TYPE_ID);
writer.writeUTF("col2");
writer.writeByte(ContentTypeIds.BOOLEAN_TYPE_ID);
writer.writeUTF("col3");
writer.writeByte(ContentTypeIds.STRING_TYPE_ID);
writer.writeUTF("col4");
writer.writeByte(ContentTypeIds.FLOAT_TYPE_ID);
writer.writeUTF("col5");
writer.writeByte(ContentTypeIds.DOUBLE_TYPE_ID);
writer.writeUTF("col6");
writer.writeByte(ContentTypeIds.LONG_TYPE_ID);
writer.writeUTF("col7");
writer.writeByte(ContentTypeIds.BLOB_TYPE_ID);
}
private <T> void assertValue(T expectedValue, String name, ContentValues values) {
@SuppressWarnings("unchecked")
T value = (T) values.get(name);
assertNotNull(value);
assertEquals(expectedValue, value);
}
private void assertBlobValue(String expectedValue, String name, ContentValues values ){
byte[] blob = values.getAsByteArray(name);
assertEquals(expectedValue, new String(blob));
}
}
@@ -0,0 +1,211 @@
/*
* 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 android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import junit.framework.TestCase;
/**
* Tests for {@link PreferenceBackupHelper}.
*
* @author Rodrigo Damazio
*/
public class PreferenceBackupHelperTest extends TestCase {
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();
}
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");
editor.apply();
// 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);
editor.apply();
// 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", ""));
}
}
@@ -0,0 +1,246 @@
/*
* 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.docs;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.gdata.docs.SpreadsheetsClient.WorksheetEntry;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.wireless.gdata.data.Entry;
import android.test.AndroidTestCase;
/**
* Tests {@link SendDocsUtils}.
*
* @author Jimmy Shih
*/
public class SendDocsUtilsTest extends AndroidTestCase {
private static final long TIME = 1288721514000L;
/**
* Tests {@link SendDocsUtils#getEntryId(Entry)} with a valid id.
*/
public void testGetEntryId_valid() {
Entry entry = new Entry();
entry.setId("https://docs.google.com/feeds/documents/private/full/spreadsheet%3A123");
assertEquals("123", SendDocsUtils.getEntryId(entry));
}
/**
* Tests {@link SendDocsUtils#getEntryId(Entry)} with an invalid id.
*/
public void testGetEntryId_invalid() {
Entry entry = new Entry();
entry.setId("123");
assertEquals(null, SendDocsUtils.getEntryId(entry));
}
/**
* Tests {@link SendDocsUtils#getNewSpreadsheetId(String)} with a valid id.
*/
public void testGetNewSpreadsheetId_valid_id() {
assertEquals("123", SendDocsUtils.getNewSpreadsheetId(
"<id>https://docs.google.com/feeds/documents/private/full/spreadsheet%3A123</id>"));
}
/**
* Tests {@link SendDocsUtils#getNewSpreadsheetId(String)} without an open
* tag, <id>.
*/
public void testGetNewSpreadsheetId_no_open_tag() {
assertEquals(null, SendDocsUtils.getNewSpreadsheetId(
"https://docs.google.com/feeds/documents/private/full/spreadsheet%3A123</id>"));
}
/**
* Tests {@link SendDocsUtils#getNewSpreadsheetId(String)} without an end tag,
* </id>.
*/
public void testGetNewSpreadsheetId_no_end_tag() {
assertEquals(null, SendDocsUtils.getNewSpreadsheetId(
"<id>https://docs.google.com/feeds/documents/private/full/spreadsheet%3A123"));
}
/**
* Tests {@link SendDocsUtils#getNewSpreadsheetId(String)} without the url
* prefix,
* https://docs.google.com/feeds/documents/private/full/spreadsheet%3A.
*/
public void testGetNewSpreadsheetId_no_prefix() {
assertEquals(null, SendDocsUtils.getNewSpreadsheetId("<id>123</id>"));
}
/**
* Tests {@link SendDocsUtils#getWorksheetEntryId(WorksheetEntry)} with a
* valid entry.
*/
public void testGetWorksheetEntryId_valid() {
WorksheetEntry entry = new WorksheetEntry();
entry.setId("/123");
assertEquals("123", SendDocsUtils.getWorksheetEntryId(entry));
}
/**
* Tests {@link SendDocsUtils#getWorksheetEntryId(WorksheetEntry)} with a
* invalid entry.
*/
public void testGetWorksheetEntryId_invalid() {
WorksheetEntry entry = new WorksheetEntry();
entry.setId("123");
assertEquals(null, SendDocsUtils.getWorksheetEntryId(entry));
}
/**
* Tests {@link SendDocsUtils#getRowContent(Track, boolean,
* android.content.Context)} with metric units.
*/
public void testGetRowContent_metric() throws Exception {
Track track = getTrack();
String expectedData = "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gsx='http://schemas.google.com/spreadsheets/2006/extended'>"
+ "<gsx:name><![CDATA[trackName]]></gsx:name>"
+ "<gsx:description><![CDATA[trackDescription]]></gsx:description>" + "<gsx:date><![CDATA["
+ StringUtils.formatDateTime(getContext(), TIME) + "]]></gsx:date>"
+ "<gsx:totaltime><![CDATA[0:00:05]]></gsx:totaltime>"
+ "<gsx:movingtime><![CDATA[0:00:04]]></gsx:movingtime>"
+ "<gsx:distance><![CDATA[20.00]]></gsx:distance>"
+ "<gsx:distanceunit><![CDATA[km]]></gsx:distanceunit>"
+ "<gsx:averagespeed><![CDATA[14,400.00]]></gsx:averagespeed>"
+ "<gsx:averagemovingspeed><![CDATA[18,000.00]]>" + "</gsx:averagemovingspeed>"
+ "<gsx:maxspeed><![CDATA[5,400.00]]></gsx:maxspeed>"
+ "<gsx:speedunit><![CDATA[km/h]]></gsx:speedunit>"
+ "<gsx:elevationgain><![CDATA[6,000]]></gsx:elevationgain>"
+ "<gsx:minelevation><![CDATA[-500]]></gsx:minelevation>"
+ "<gsx:maxelevation><![CDATA[550]]></gsx:maxelevation>"
+ "<gsx:elevationunit><![CDATA[m]]></gsx:elevationunit>" + "<gsx:map>"
+ "<![CDATA[https://maps.google.com/maps/ms?msa=0&msid=trackMapId]]>" + "</gsx:map>"
+ "</entry>";
assertEquals(expectedData, SendDocsUtils.getRowContent(track, true, getContext()));
}
/**
* Tests {@link SendDocsUtils#getRowContent(Track, boolean,
* android.content.Context)} with imperial units.
*/
public void testGetRowContent_imperial() throws Exception {
Track track = getTrack();
String expectedData = "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gsx='http://schemas.google.com/spreadsheets/2006/extended'>"
+ "<gsx:name><![CDATA[trackName]]></gsx:name>"
+ "<gsx:description><![CDATA[trackDescription]]></gsx:description>" + "<gsx:date><![CDATA["
+ StringUtils.formatDateTime(getContext(), TIME) + "]]></gsx:date>"
+ "<gsx:totaltime><![CDATA[0:00:05]]></gsx:totaltime>"
+ "<gsx:movingtime><![CDATA[0:00:04]]></gsx:movingtime>"
+ "<gsx:distance><![CDATA[12.43]]></gsx:distance>"
+ "<gsx:distanceunit><![CDATA[mi]]></gsx:distanceunit>"
+ "<gsx:averagespeed><![CDATA[8,947.75]]></gsx:averagespeed>"
+ "<gsx:averagemovingspeed><![CDATA[11,184.68]]>" + "</gsx:averagemovingspeed>"
+ "<gsx:maxspeed><![CDATA[3,355.40]]></gsx:maxspeed>"
+ "<gsx:speedunit><![CDATA[mi/h]]></gsx:speedunit>"
+ "<gsx:elevationgain><![CDATA[19,685]]></gsx:elevationgain>"
+ "<gsx:minelevation><![CDATA[-1,640]]></gsx:minelevation>"
+ "<gsx:maxelevation><![CDATA[1,804]]></gsx:maxelevation>"
+ "<gsx:elevationunit><![CDATA[ft]]></gsx:elevationunit>" + "<gsx:map>"
+ "<![CDATA[https://maps.google.com/maps/ms?msa=0&msid=trackMapId]]>" + "</gsx:map>"
+ "</entry>";
assertEquals(expectedData, SendDocsUtils.getRowContent(track, false, getContext()));
}
/**
* Gets a track for testing {@link SendDocsUtils#getRowContent(Track, boolean,
* android.content.Context)}.
*/
private Track getTrack() {
TripStatistics stats = new TripStatistics();
stats.setStartTime(TIME);
stats.setTotalTime(5000);
stats.setMovingTime(4000);
stats.setTotalDistance(20000);
stats.setMaxSpeed(1500);
stats.setTotalElevationGain(6000);
stats.setMinElevation(-500);
stats.setMaxElevation(550);
Track track = new Track();
track.setName("trackName");
track.setDescription("trackDescription");
track.setMapId("trackMapId");
track.setStatistics(stats);
return track;
}
/**
* Tests {@link SendDocsUtils#appendTag(StringBuilder, String, String)} with
* repeated calls.
*/
public void testAppendTag() {
StringBuilder stringBuilder = new StringBuilder();
SendDocsUtils.appendTag(stringBuilder, "name1", "value1");
assertEquals("<gsx:name1><![CDATA[value1]]></gsx:name1>", stringBuilder.toString());
SendDocsUtils.appendTag(stringBuilder, "name2", "value2");
assertEquals(
"<gsx:name1><![CDATA[value1]]></gsx:name1><gsx:name2><![CDATA[value2]]></gsx:name2>",
stringBuilder.toString());
}
/**
* Tests {@link SendDocsUtils#getDistance(double, boolean)} with metric units.
*/
public void testGetDistance_metric() {
assertEquals("1.22", SendDocsUtils.getDistance(1222.3, true));
}
/**
* Tests {@link SendDocsUtils#getDistance(double, boolean)} with imperial
* units.
*/
public void testGetDistance_imperial() {
assertEquals("0.76", SendDocsUtils.getDistance(1222.3, false));
}
/**
* Tests {@link SendDocsUtils#getSpeed(double, boolean)} with metric units.
*/
public void testGetSpeed_metric() {
assertEquals("15.55", SendDocsUtils.getSpeed(4.32, true));
}
/**
* Tests {@link SendDocsUtils#getSpeed(double, boolean)} with imperial units.
*/
public void testGetSpeed_imperial() {
assertEquals("9.66", SendDocsUtils.getSpeed(4.32, false));
}
/**
* Tests {@link SendDocsUtils#getElevation(double, boolean)} with metric
* units.
*/
public void testGetElevation_metric() {
assertEquals("3", SendDocsUtils.getElevation(3.456, true));
}
/**
* Tests {@link SendDocsUtils#getElevation(double, boolean)} with imperial
* units.
*/
public void testGetElevation_imperial() {
assertEquals("11", SendDocsUtils.getElevation(3.456, false));
}
}
@@ -0,0 +1,88 @@
/*
* 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;
/**
* Tests for {@link CsvTrackWriter}.
*
* @author Rodrigo Damazio
*/
public class CsvTrackWriterTest extends TrackFormatWriterTest {
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)", "Battery level (%)");
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", "400.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", "401.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", "402.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", "403.0");
String expected = expectedTrackHeader + expectedTrack + "\n"
+ expectedMarkerHeader + expectedMarker1 + expectedMarker2 + "\n"
+ expectedPointHeader + expectedPoint1 + expectedPoint2 + expectedPoint3 + expectedPoint4;
CsvTrackWriter writer = new CsvTrackWriter(getContext());
assertEquals(expected, writeTrack(writer));
}
/**
* 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();
}
}
@@ -0,0 +1,295 @@
/*
* 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;
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.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.io.file.GpxImporter;
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.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.SimpleTimeZone;
import javax.xml.parsers.ParserConfigurationException;
import org.easymock.Capture;
import org.easymock.IArgumentMatcher;
import org.xml.sax.SAXException;
/**
* Tests for the GPX importer.
*
* @author Steffen Horlacher
*/
public class GpxImporterTest extends AndroidTestCase {
private static final String TRACK_NAME = "blablub";
private static final String TRACK_DESC = "s'Laebe isch koi Schlotzer";
private static final String TRACK_LAT_1 = "48.768364";
private static final String TRACK_LON_1 = "9.177886";
private static final String TRACK_ELE_1 = "324.0";
private static final String TRACK_TIME_1 = "2010-04-22T18:21:00Z";
private static final String TRACK_LAT_2 = "48.768374";
private static final String TRACK_LON_2 = "9.177816";
private static final String TRACK_ELE_2 = "333.0";
private static final String TRACK_TIME_2 = "2010-04-22T18:21:50.123";
private static final SimpleDateFormat DATE_FORMAT1 =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
private static final SimpleDateFormat DATE_FORMAT2 =
new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
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_FORMAT1.setTimeZone(utc);
DATE_FORMAT2.setTimeZone(utc);
}
// TODO: use real files from different sources with more track points.
private static final String VALID_TEST_GPX = "<gpx><trk><name><![CDATA["
+ TRACK_NAME + "]]></name><desc><![CDATA[" + TRACK_DESC
+ "]]></desc><trkseg>" + "<trkpt lat=\"" + TRACK_LAT_1 + "\" lon=\""
+ TRACK_LON_1 + "\"><ele>" + TRACK_ELE_1 + "</ele><time>" + TRACK_TIME_1
+ "</time></trkpt> +" + "<trkpt lat=\"" + TRACK_LAT_2 + "\" lon=\""
+ TRACK_LON_2 + "\"><ele>" + TRACK_ELE_2 + "</ele><time>" + TRACK_TIME_2
+ "</time></trkpt>" + "</trkseg></trk></gpx>";
// invalid xml
private static final String INVALID_XML_TEST_GPX = VALID_TEST_GPX.substring(
0, VALID_TEST_GPX.length() - 50);
private static final String INVALID_LOCATION_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LAT_1, "1000.0");
private static final String INVALID_TIME_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_TIME_1, "invalid");
private static final String INVALID_ALTITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_ELE_1, "invalid");
private static final String INVALID_LATITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LAT_1, "invalid");
private static final String INVALID_LONGITUDE_TEST_GPX = VALID_TEST_GPX
.replaceAll(TRACK_LON_1, "invalid");
private static final long TRACK_ID = 1;
private static final long TRACK_POINT_ID_1 = 1;
private static final long TRACK_POINT_ID_2 = 2;
private static final Uri TRACK_ID_URI = ContentUris.appendId(
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID).build();
private MyTracksProviderUtils providerUtils;
private Factory oldProviderUtilsFactory;
@UsesMocks(MyTracksProviderUtils.class)
@Override
protected void setUp() throws Exception {
super.setUp();
providerUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
oldProviderUtilsFactory =
TestingProviderUtilsFactory.installWithInstance(providerUtils);
}
@Override
protected void tearDown() throws Exception {
TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory);
super.tearDown();
}
/**
* Test import success.
*/
public void testImportSuccess() throws Exception {
Capture<Track> trackParam = new Capture<Track>();
Location loc1 = new Location(LocationManager.GPS_PROVIDER);
loc1.setTime(DATE_FORMAT2.parse(TRACK_TIME_1).getTime());
loc1.setLatitude(Double.parseDouble(TRACK_LAT_1));
loc1.setLongitude(Double.parseDouble(TRACK_LON_1));
loc1.setAltitude(Double.parseDouble(TRACK_ELE_1));
Location loc2 = new Location(LocationManager.GPS_PROVIDER);
loc2.setTime(DATE_FORMAT1.parse(TRACK_TIME_2).getTime());
loc2.setLatitude(Double.parseDouble(TRACK_LAT_2));
loc2.setLongitude(Double.parseDouble(TRACK_LON_2));
loc2.setAltitude(Double.parseDouble(TRACK_ELE_2));
expect(providerUtils.insertTrack(AndroidMock.capture(trackParam)))
.andReturn(TRACK_ID_URI);
expect(providerUtils.getLastLocationId(TRACK_ID)).andReturn(TRACK_POINT_ID_1).andReturn(TRACK_POINT_ID_2);
// A flush happens after the first insertion to get the starting point ID,
// which is why we get two calls
expect(providerUtils.bulkInsertTrackPoints(LocationsMatcher.eqLoc(loc1),
eq(1), eq(TRACK_ID))).andReturn(1);
expect(providerUtils.bulkInsertTrackPoints(LocationsMatcher.eqLoc(loc2),
eq(1), eq(TRACK_ID))).andReturn(1);
providerUtils.updateTrack(AndroidMock.capture(trackParam));
AndroidMock.replay(providerUtils);
InputStream is = new ByteArrayInputStream(VALID_TEST_GPX.getBytes());
GpxImporter.importGPXFile(is, providerUtils);
AndroidMock.verify(providerUtils);
// verify track parameter
Track track = trackParam.getValue();
assertEquals(TRACK_NAME, track.getName());
assertEquals(TRACK_DESC, track.getDescription());
assertEquals(DATE_FORMAT2.parse(TRACK_TIME_1).getTime(), track.getStatistics()
.getStartTime());
assertNotSame(-1, track.getStartId());
assertNotSame(-1, track.getStopId());
}
/**
* Test with invalid location - track should be deleted.
*/
public void testImportLocationFailure() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_LOCATION_TEST_GPX);
}
/**
* Test with invalid time - track should be deleted.
*/
public void testImportTimeFailure() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_TIME_TEST_GPX);
}
/**
* Test with invalid xml - track should be deleted.
*/
public void testImportXMLFailure() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_XML_TEST_GPX);
}
/**
* Test with invalid altitude - track should be deleted.
*/
public void testImportInvalidAltitude() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_ALTITUDE_TEST_GPX);
}
/**
* Test with invalid latitude - track should be deleted.
*/
public void testImportInvalidLatitude() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_LATITUDE_TEST_GPX);
}
/**
* Test with invalid longitude - track should be deleted.
*/
public void testImportInvalidLongitude() throws ParserConfigurationException, IOException {
testInvalidXML(INVALID_LONGITUDE_TEST_GPX);
}
private void testInvalidXML(String xml) throws ParserConfigurationException,
IOException {
expect(providerUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_URI);
expect(providerUtils.bulkInsertTrackPoints((Location[]) AndroidMock.anyObject(),
AndroidMock.anyInt(), AndroidMock.anyLong())).andStubReturn(1);
expect(providerUtils.getLastLocationId(TRACK_ID)).andStubReturn(TRACK_POINT_ID_1);
providerUtils.deleteTrack(TRACK_ID);
AndroidMock.replay(providerUtils);
InputStream is = new ByteArrayInputStream(xml.getBytes());
try {
GpxImporter.importGPXFile(is, providerUtils);
} catch (SAXException e) {
// expected exception
}
AndroidMock.verify(providerUtils);
}
/**
* Workaround because of capture bug 2617107 in easymock:
* http://sourceforge.net
* /tracker/?func=detail&aid=2617107&group_id=82958&atid=567837
*/
private static class LocationsMatcher implements IArgumentMatcher {
private final Location[] matchLocs;
private LocationsMatcher(Location[] expected) {
this.matchLocs = expected;
}
public static Location[] eqLoc(Location[] expected) {
IArgumentMatcher matcher = new LocationsMatcher(expected);
AndroidMock.reportMatcher(matcher);
return null;
}
public static Location[] eqLoc(Location expected) {
return eqLoc(new Location[] { expected});
}
@Override
public void appendTo(StringBuffer buf) {
buf.append("eqLoc(").append(Arrays.toString(matchLocs)).append(")");
}
@Override
public boolean matches(Object obj) {
if (! (obj instanceof Location[])) { return false; }
Location[] locs = (Location[]) obj;
if (locs.length < matchLocs.length) { return false; }
// Only check the first elements (those that will be taken into account)
for (int i = 0; i < matchLocs.length; i++) {
if (!locationsMatch(locs[i], matchLocs[i])) {
return false;
}
}
return true;
}
private boolean locationsMatch(Location loc1, Location loc2) {
return (loc1.getTime() == loc2.getTime()) &&
(loc1.getLatitude() == loc2.getLatitude()) &&
(loc1.getLongitude() == loc2.getLongitude()) &&
(loc1.getAltitude() == loc2.getAltitude());
}
}
}
@@ -0,0 +1,76 @@
/*
* 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;
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 TrackFormatWriterTest {
public void testXmlOutput() throws Exception {
TrackFormatWriter writer = new GpxTrackWriter(getContext());
String result = writeTrack(writer);
Document doc = parseXmlDocument(result);
Element gpxTag = getChildElement(doc, "gpx");
Element trackTag = getChildElement(gpxTag, "trk");
assertEquals(TRACK_NAME, getChildTextValue(trackTag, "name"));
assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackTag, "desc"));
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"));
}
}
@@ -0,0 +1,125 @@
/*
* 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;
import com.google.android.apps.mytracks.content.DescriptionGenerator;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
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 TrackFormatWriterTest {
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(Waypoint waypoint) {
return null;
}
}
public void testXmlOutput() throws Exception {
KmlTrackWriter writer = new KmlTrackWriter(getContext(), new FakeDescriptionGenerator());
String result = writeTrack(writer);
Document doc = parseXmlDocument(result);
Element kmlTag = getChildElement(doc, "kml");
Element docTag = getChildElement(kmlTag, "Document");
assertEquals(TRACK_NAME, getChildTextValue(docTag, "name"));
assertEquals(TRACK_DESCRIPTION, getChildTextValue(docTag, "description"));
// There are 3 placemarks - start, track, and end
List<Element> placemarkTags = getChildElements(docTag, "Placemark", 3);
assertTagIsPlacemark(
placemarkTags.get(0), TRACK_NAME + " (Start)", TRACK_DESCRIPTION, 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"));
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);
}
}
}
@@ -0,0 +1,64 @@
/*
* 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.io.file;
import java.io.File;
/**
* A simple, fake {@link TrackWriter} subclass with all methods mocked out.
* Tests are expected to override {@link #writeTrack}.
*
* @author Matthew Simmons
*
*/
public class MockTrackWriter implements TrackWriter {
public OnWriteListener onWriteListener;
@Override
public void setOnWriteListener(OnWriteListener onWriteListener) {
this.onWriteListener = onWriteListener;
}
@Override
public void setDirectory(File directory) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public String getAbsolutePath() {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void writeTrack() {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void stopWriteTrack() {
throw new UnsupportedOperationException("not implemented");
}
@Override
public boolean wasSuccess() {
return false;
}
@Override
public int getErrorMessage() {
return 0;
}
}
@@ -0,0 +1,96 @@
/*
* 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;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor;
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 TrackFormatWriterTest {
public void testXmlOutput() throws Exception {
TrackFormatWriter writer = new TcxTrackWriter(getContext());
String result = writeTrack(writer);
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"));
}
}
@@ -0,0 +1,219 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io.file;
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 TrackFormatWriterTest extends AndroidTestCase {
// All the user-provided strings have "]]>" to ensure that proper escaping is
// being done.
protected static final String TRACK_NAME = "Home]]>";
protected static final String TRACK_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.SensorData.Builder batteryLevel = Sensor.SensorData.newBuilder().setValue(400 + i)
.setState(Sensor.SensorState.SENDING);
Sensor.SensorDataSet sensorDataSet = Sensor.SensorDataSet.newBuilder().setPower(power)
.setCadence(cadence).setHeartRate(heartRate).setBatteryLevel(batteryLevel).build();
location.setSensorData(sensorDataSet);
}
}
/**
* Makes the right sequence of calls to the writer in order to write the fake
* track in {@link #track}.
*
* @param writer the writer to write to
* @return the written contents
*/
protected String writeTrack(TrackFormatWriter writer) throws Exception {
OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE);
writer.prepare(track, output);
writer.writeHeader();
writer.writeBeginWaypoints();
writer.writeWaypoint(wp1);
writer.writeWaypoint(wp2);
writer.writeEndWaypoints();
writer.writeBeginTrack(location1);
writer.writeOpenSegment();
writer.writeLocation(location1);
writer.writeLocation(location2);
writer.writeCloseSegment();
writer.writeOpenSegment();
writer.writeLocation(location3);
writer.writeLocation(location4);
writer.writeCloseSegment();
writer.writeEndTrack(location4);
writer.writeFooter();
writer.close();
return output.toString();
}
/**
* Gets the text data contained inside a tag.
*
* @param parent the parent of the tag containing the text
* @param elementName the name of the tag containing the text
* @return the text contents
*/
protected String getChildTextValue(Element parent, String elementName) {
Element child = getChildElement(parent, elementName);
assertTrue(child.hasChildNodes());
NodeList children = child.getChildNodes();
int length = children.getLength();
assertTrue(length > 0);
// The children may be a sucession of text elements, just concatenate them
String result = "";
for (int i = 0; i < length; i++) {
Text textNode = (Text) children.item(i);
result += textNode.getNodeValue();
}
return result;
}
/**
* Returns all child elements of a given parent which 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;
}
}
@@ -0,0 +1,363 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.io.file;
import static org.easymock.EasyMock.expect;
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.File;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;
import org.easymock.IMocksControl;
/**
* Tests for the track writer.
*
* @author Rodrigo Damazio
*/
public class TrackWriterTest extends AndroidTestCase {
/**
* {@link TrackWriterImpl} subclass which mocks out methods called from
* {@link TrackWriterImpl#openFile}.
*/
private static final class OpenFileTrackWriter extends TrackWriterImpl {
private final ByteArrayOutputStream stream;
private final boolean canWrite;
/**
* Constructor.
*
* @param stream the stream to return from
* {@link TrackWriterImpl#newOutputStream}, or null to throw a
* {@link FileNotFoundException}
* @param canWrite the value that {@link TrackWriterImpl#canWriteFile} will
* return
*/
private OpenFileTrackWriter(Context context,
MyTracksProviderUtils providerUtils, Track track,
TrackFormatWriter writer, ByteArrayOutputStream stream,
boolean canWrite) {
super(context, providerUtils, track, writer);
this.stream = stream;
this.canWrite = canWrite;
// The directory is set in the canWriteFile. However, this class
// overwrites canWriteFile, thus needs to set it.
setDirectory(new File("/"));
}
@Override
protected boolean canWriteFile() {
return canWrite;
}
@Override
protected OutputStream newOutputStream(String fileName)
throws FileNotFoundException {
assertEquals(FULL_TRACK_NAME, fileName);
if (stream == null) {
throw new FileNotFoundException();
}
return stream;
}
}
/**
* {@link TrackWriterImpl} subclass which mocks out methods called from
* {@link TrackWriterImpl#writeTrack}.
*/
private final class WriteTracksTrackWriter extends TrackWriterImpl {
private final boolean openResult;
/**
* Constructor.
*
* @param openResult the return value for {@link TrackWriterImpl#openFile}
*/
private WriteTracksTrackWriter(Context context,
MyTracksProviderUtils providerUtils, Track track,
TrackFormatWriter writer, boolean openResult) {
super(context, providerUtils, track, writer);
this.openResult = openResult;
}
@Override
protected boolean openFile() {
openFileCalls++;
return openResult;
}
@Override
void writeDocument() {
writeDocumentCalls++;
}
@Override
protected void runOnUiThread(Runnable runnable) {
runnable.run();
}
}
private static final long TRACK_ID = 1234567L;
private static final String EXTENSION = "ext";
private static final String TRACK_NAME = "Swimming across the pacific";
private static final String FULL_TRACK_NAME =
"Swimming across the pacific.ext";
private Track track;
private TrackFormatWriter formatWriter;
private TrackWriterImpl writer;
private IMocksControl mocksControl;
private MyTracksProviderUtils providerUtils;
private Factory oldProviderUtilsFactory;
// State used in specific tests
private int writeDocumentCalls;
private int openFileCalls;
@Override
protected void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
Context 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);
oldProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(providerUtils);
mocksControl = EasyMock.createStrictControl();
formatWriter = mocksControl.createMock(TrackFormatWriter.class);
expect(formatWriter.getExtension()).andStubReturn(EXTENSION);
track = new Track();
track.setName(TRACK_NAME);
track.setId(TRACK_ID);
}
@Override
protected void tearDown() throws Exception {
TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory);
super.tearDown();
}
public void testWriteTrack() {
writer = new WriteTracksTrackWriter(getContext(), providerUtils, track,
formatWriter, true);
mocksControl.replay();
writer.writeTrack();
assertEquals(1, writeDocumentCalls);
assertEquals(1, openFileCalls);
mocksControl.verify();
}
public void testWriteTrack_openFails() {
writer = new WriteTracksTrackWriter(getContext(), providerUtils, track,
formatWriter, false);
mocksControl.replay();
writer.writeTrack();
assertEquals(0, writeDocumentCalls);
assertEquals(1, openFileCalls);
mocksControl.verify();
}
public void testOpenFile() {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
writer = new OpenFileTrackWriter(
getContext(), providerUtils, track, formatWriter, stream, true);
formatWriter.prepare(track, stream);
mocksControl.replay();
assertTrue(writer.openFile());
mocksControl.verify();
}
public void testOpenFile_cantWrite() {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
writer = new OpenFileTrackWriter(
getContext(), providerUtils, track, formatWriter, stream, false);
mocksControl.replay();
assertFalse(writer.openFile());
mocksControl.verify();
}
public void testOpenFile_streamError() {
writer = new OpenFileTrackWriter(
getContext(), providerUtils, track, formatWriter, null, true);
mocksControl.replay();
assertFalse(writer.openFile());
mocksControl.verify();
}
public void testWriteDocument_emptyTrack() throws Exception {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
// Set expected mock behavior
formatWriter.writeHeader();
formatWriter.writeFooter();
formatWriter.close();
mocksControl.replay();
writer.writeDocument();
assertTrue(writer.wasSuccess());
mocksControl.verify();
}
public void testWriteDocument() throws Exception {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
final Location[] locs = {
new Location("fake0"),
new Location("fake1"),
new Location("fake2"),
new Location("fake3"),
new Location("fake4"),
new Location("fake5")
};
Waypoint[] wps = { new Waypoint(), new Waypoint(), new Waypoint() };
// Fill locations with valid values
fillLocations(locs);
// Make location 3 invalid
locs[2].setLatitude(100);
assertEquals(locs.length, providerUtils.bulkInsertTrackPoints(locs, locs.length, TRACK_ID));
for (int i = 0; i < wps.length; ++i) {
Waypoint wpt = wps[i];
wpt.setTrackId(TRACK_ID);
assertNotNull(providerUtils.insertWaypoint(wpt));
wpt.setId(i + 1);
}
formatWriter.writeHeader();
// Expect reading/writing of the waypoints (except the first)
formatWriter.writeBeginWaypoints();
formatWriter.writeWaypoint(wptEq(wps[1]));
formatWriter.writeWaypoint(wptEq(wps[2]));
formatWriter.writeEndWaypoints();
// Begin the track
formatWriter.writeBeginTrack(locEq(locs[0]));
// Write locations 1-2
formatWriter.writeOpenSegment();
formatWriter.writeLocation(locEq(locs[0]));
formatWriter.writeLocation(locEq(locs[1]));
formatWriter.writeCloseSegment();
// Location 3 is not written - it's invalid
// Write locations 4-6
formatWriter.writeOpenSegment();
formatWriter.writeLocation(locEq(locs[3]));
formatWriter.writeLocation(locEq(locs[4]));
formatWriter.writeLocation(locEq(locs[5]));
formatWriter.writeCloseSegment();
// End the track
formatWriter.writeEndTrack(locEq(locs[5]));
formatWriter.writeFooter();
formatWriter.close();
mocksControl.replay();
writer.writeDocument();
assertTrue(writer.wasSuccess());
mocksControl.verify();
}
private static Waypoint wptEq(final Waypoint wpt) {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object wptObj2) {
if (wptObj2 == null || wpt == null) return wpt == wptObj2;
Waypoint wpt2 = (Waypoint) wptObj2;
return wpt.getId() == wpt2.getId();
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("wptEq(");
buffer.append(wpt);
buffer.append(")");
}
});
return null;
}
private static Location locEq(final Location loc) {
EasyMock.reportMatcher(new IArgumentMatcher() {
@Override
public boolean matches(Object locObj2) {
if (locObj2 == null || loc == null) return loc == locObj2;
Location loc2 = (Location) locObj2;
return loc.hasAccuracy() == loc2.hasAccuracy()
&& (!loc.hasAccuracy() || loc.getAccuracy() == loc2.getAccuracy())
&& loc.hasAltitude() == loc2.hasAltitude()
&& (!loc.hasAltitude() || loc.getAltitude() == loc2.getAltitude())
&& loc.hasBearing() == loc2.hasBearing()
&& (!loc.hasBearing() || loc.getBearing() == loc2.getBearing())
&& loc.hasSpeed() == loc2.hasSpeed()
&& (!loc.hasSpeed() || loc.getSpeed() == loc2.getSpeed())
&& loc.getLatitude() == loc2.getLatitude()
&& loc.getLongitude() == loc2.getLongitude()
&& loc.getTime() == loc2.getTime();
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("locEq(");
buffer.append(loc);
buffer.append(")");
}
});
return null;
}
private void fillLocations(Location... locs) {
assertTrue(locs.length < 90);
for (int i = 0; i < locs.length; i++) {
Location location = locs[i];
location.setLatitude(i + 1);
location.setLongitude(i + 1);
location.setTime(i + 1000);
}
}
}
@@ -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.docs.SendDocsActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest;
import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity;
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 "sendDocs" and "cancel" to false and false.
*/
public void testGetNextClass_notCancelNotSendDocs() {
sendRequest.setSendDocs(false);
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
assertEquals(UploadResultActivity.class, next);
}
/**
* Tests the method
* {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets
* the flags of "sendDocs" and "cancel" to true and false.
*/
public void testGetNextClass_notCancelSendDocs() {
sendRequest.setSendDocs(true);
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, false);
assertEquals(SendDocsActivity.class, next);
}
/**
* Tests the method
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
* the flags of "sendDocs" and "cancel" to true and true.
*/
public void testGetNextClass_cancelSendDocs() {
sendRequest.setSendDocs(true);
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
assertEquals(UploadResultActivity.class, next);
}
/**
* Tests the method
* {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets
* the flags of "sendDocs" and "cancel" to false and true.
*/
public void testGetNextClass_cancelNotSendDocs() {
sendRequest.setSendDocs(false);
Class<?> next = sendFusionTablesActivity.getNextClass(sendRequest, true);
assertEquals(UploadResultActivity.class, next);
}
}
@@ -0,0 +1,285 @@
/*
* 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.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import junit.framework.TestCase;
/**
* Tests {@link SendFusionTablesUtils}.
*
* @author Jimmy Shih
*/
public class SendFusionTablesUtilsTest extends TestCase {
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null track.
*/
public void testGetMapUrl_null_track() {
assertEquals(null, SendFusionTablesUtils.getMapUrl(null));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null table id.
*/
public void testGetMapUrl_null_table_id() {
Track track = new Track();
TripStatistics stats = new TripStatistics();
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
track.setStatistics(stats);
track.setTableId(null);
assertEquals(null, SendFusionTablesUtils.getMapUrl(track));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with null stats.
*/
public void testGetMapUrl_null_stats() {
Track track = new Track();
track.setStatistics(null);
track.setTableId("123");
assertEquals(null, SendFusionTablesUtils.getMapUrl(track));
}
/**
* Tests {@link SendFusionTablesUtils#getMapUrl(Track)} with a valid track.
*/
public void testGetMapUrl_valid_track() {
Track track = new Track();
TripStatistics stats = new TripStatistics();
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
track.setStatistics(stats);
track.setTableId("123");
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));
}
/**
* 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());
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with a null
* inputstream.
*/
public void testGetTableId_null() {
assertEquals(null, SendFusionTablesUtils.getTableId(null));
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with an
* inputstream containing no data.
*/
public void testGetTableId_no_data() {
InputStream inputStream = new ByteArrayInputStream(new byte[0]);
assertEquals(null, SendFusionTablesUtils.getTableId(inputStream));
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with an empty
* inputstream.
*/
public void testGetTableId_empty() {
String string = "";
InputStream inputStream = new ByteArrayInputStream(string.getBytes());
assertEquals(null, SendFusionTablesUtils.getTableId(inputStream));
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with an one
* line inputstream.
*/
public void testGetTableId_one_line() {
String string = "tableid";
InputStream inputStream = new ByteArrayInputStream(string.getBytes());
assertEquals(null, SendFusionTablesUtils.getTableId(inputStream));
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with an
* inputstream not containing "tableid".
*/
public void testGetTableId_no_table_id() {
String string = "error\n123";
InputStream inputStream = new ByteArrayInputStream(string.getBytes());
assertEquals(null, SendFusionTablesUtils.getTableId(inputStream));
}
/**
* Tests {@link SendFusionTablesUtils#getTableId(InputStream)} with a valid
* inputstream.
*/
public void testGetTableId() {
String string = "tableid\n123";
InputStream inputStream = null;
inputStream = new ByteArrayInputStream(string.getBytes());
assertEquals("123", SendFusionTablesUtils.getTableId(inputStream));
}
}
@@ -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.io.maps;
import com.google.android.apps.mytracks.io.gdata.maps.MapsMapMetadata;
import com.google.android.maps.mytracks.R;
import android.content.Intent;
import android.test.AndroidTestCase;
import android.widget.ArrayAdapter;
import java.util.ArrayList;
/**
* Tests the {@link ChooseMapActivity}.
*
* @author Youtao Liu
*/
public class ChooseMapActivityTest extends AndroidTestCase {
private static final String MAP_ID = "mapid";
private static final String MAP_TITLE = "title";
private static final String MAP_DESC = "desc";
private ArrayList<String> mapIds = new ArrayList<String>();
private ArrayList<MapsMapMetadata> mapDatas = new ArrayList<MapsMapMetadata>();
private boolean errorDialogShown = false;
private boolean progressDialogRemoved = false;
/**
* Creates a class to override some methods of {@link ChooseMapActivity} to
* makes it testable.
*
* @author youtaol
*/
public class ChooseMapActivityMock extends ChooseMapActivity {
/**
* By overriding this method, avoids to start next activity.
*/
@Override
public void startActivity(Intent intent) {}
/**
* By overriding this method, avoids to show an error dialog and set the
* show flag to true.
*/
@Override
public void showErrorDialog() {
errorDialogShown = true;
}
/**
* By overriding this method, avoids to show an error dialog and set the
* show flag to true.
*/
@Override
public void removeProgressDialog() {
progressDialogRemoved = true;
}
}
/**
* Tests the method
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* . An alert dialog should be shown when there is no map.
*/
public void testOnAsyncTaskCompleted_fail() {
ChooseMapActivityMock chooseMapActivityMock = new ChooseMapActivityMock();
errorDialogShown = false;
progressDialogRemoved = false;
chooseMapActivityMock.onAsyncTaskCompleted(false, null, null);
assertTrue(progressDialogRemoved);
assertTrue(errorDialogShown);
}
/**
* Tests the method
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* . Check the logic when there is only map.
*/
public void testOnAsyncTaskCompleted_success_oneMap() {
ChooseMapActivityMock chooseMapActivityMock = new ChooseMapActivityMock();
chooseMapActivityMock.arrayAdapter = new ArrayAdapter<ChooseMapActivity.ListItem>(getContext(),
R.layout.choose_map_item);
simulateMaps(1);
chooseMapActivityMock.onAsyncTaskCompleted(true, mapIds, mapDatas);
assertEquals(1, chooseMapActivityMock.arrayAdapter.getCount());
assertEquals(MAP_ID + "0", chooseMapActivityMock.arrayAdapter.getItem(0).getMapId());
assertEquals(MAP_TITLE + "0", chooseMapActivityMock.arrayAdapter.getItem(0).getMapData()
.getTitle());
assertEquals(MAP_DESC + "0", chooseMapActivityMock.arrayAdapter.getItem(0).getMapData()
.getDescription());
}
/**
* Tests the method
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* . Check the logic when there are 10 maps.
*/
public void testOnAsyncTaskCompleted_success_twoMaps() {
ChooseMapActivityMock chooseMapActivityMock = new ChooseMapActivityMock();
chooseMapActivityMock.arrayAdapter = new ArrayAdapter<ChooseMapActivity.ListItem>(getContext(),
R.layout.choose_map_item);
simulateMaps(10);
chooseMapActivityMock.onAsyncTaskCompleted(true, mapIds, mapDatas);
assertEquals(10, chooseMapActivityMock.arrayAdapter.getCount());
assertEquals(MAP_ID + "9", chooseMapActivityMock.arrayAdapter.getItem(9).getMapId());
assertEquals(MAP_TITLE + "9", chooseMapActivityMock.arrayAdapter.getItem(9).getMapData()
.getTitle());
assertEquals(MAP_DESC + "9", chooseMapActivityMock.arrayAdapter.getItem(9).getMapData()
.getDescription());
}
/**
* Simulates map data for the test.
*
* @param number of data should be simulated.
*/
private void simulateMaps(int number) {
mapIds = new ArrayList<String>();
mapDatas = new ArrayList<MapsMapMetadata>();
for (int i = 0; i < number; i++) {
mapIds.add(MAP_ID + i);
MapsMapMetadata metaData = new MapsMapMetadata();
metaData.setTitle(MAP_TITLE + i);
metaData.setDescription(MAP_DESC + i);
metaData.setSearchable(true);
mapDatas.add(metaData);
}
}
}
@@ -0,0 +1,199 @@
/*
* 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.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.accounts.Account;
import android.test.AndroidTestCase;
import java.util.ArrayList;
/**
* Tests {@link ChooseMapAsyncTask}.
*
* @author Youtao Liu
*/
public class ChooseMapAsyncTaskTest extends AndroidTestCase {
private ChooseMapActivity chooseMapActivityMock;
private Account account;
private static final String ACCOUNT_NAME = "AccountName";
private static final String ACCOUNT_TYPE = "AccountType";
private boolean getMapsStatus = false;
public class ChooseMapAsyncTaskMock extends ChooseMapAsyncTask {
public ChooseMapAsyncTaskMock(ChooseMapActivity activity, Account account) {
super(activity, account);
}
/**
* Creates this method to override {@link ChooseMapAsyncTask#getMaps()}.
*
* @return mock the return value of getMaps().
*/
@Override
boolean getMaps() {
return getMapsStatus;
}
}
/**
* Tests {@link ChooseMapAsyncTask#setActivity(ChooseMapActivity)} when the
* task is completed. Makes sure it calls
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* .
*/
public void testSetActivity_completed() {
setup();
chooseMapActivityMock.onAsyncTaskCompleted(false, null, null);
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTask chooseMapAsyncTask = new ChooseMapAsyncTask(chooseMapActivityMock, account);
chooseMapAsyncTask.setCompleted(true);
chooseMapAsyncTask.setActivity(chooseMapActivityMock);
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Test {@link ChooseMapAsyncTask#setActivity(ChooseMapActivity)} when the
* task is not completed. Makes sure
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* is not invoked.
*/
public void testSetActivity_notCompleted() {
setup();
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTask chooseMapAsyncTask = new ChooseMapAsyncTask(chooseMapActivityMock, account);
chooseMapAsyncTask.setCompleted(false);
chooseMapAsyncTask.setActivity(chooseMapActivityMock);
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests {@link ChooseMapAsyncTask#setActivity(ChooseMapActivity)} when the
* activity is null. Makes sure
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* is not invoked.
*/
public void testSetActivity_nullActivity() {
setup();
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTask chooseMapAsyncTask = new ChooseMapAsyncTask(chooseMapActivityMock, account);
chooseMapAsyncTask.setCompleted(true);
chooseMapAsyncTask.setActivity(null);
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests the method {@link ChooseMapAsyncTask#onPostExecute(Boolean)} when the
* result is true. Makes sure
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* is invoked.
*/
public void testOnPostExecute_trueResult() {
setup();
chooseMapActivityMock.onAsyncTaskCompleted(true, null, null);
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTask chooseMapAsyncTask = new ChooseMapAsyncTask(chooseMapActivityMock, account);
chooseMapAsyncTask.onPostExecute(true);
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests the method {@link ChooseMapAsyncTask#onPostExecute(Boolean)} when the
* result is false. Makes sure
* {@link ChooseMapActivity#onAsyncTaskCompleted(boolean, ArrayList, ArrayList)}
* is invoked.
*/
public void testOnPostExecute_falseResult() {
setup();
chooseMapActivityMock.onAsyncTaskCompleted(false, null, null);
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTask chooseMapAsyncTask = new ChooseMapAsyncTask(chooseMapActivityMock, account);
chooseMapAsyncTask.onPostExecute(false);
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests the method {@link ChooseMapAsyncTask#retryUpload()}. Make sure can
* not retry again after have retried once and failed.
*/
public void testRetryUpload() throws Exception {
setup();
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTaskMock chooseMapAsyncTaskTMock = new ChooseMapAsyncTaskMock(
chooseMapActivityMock, account);
chooseMapAsyncTaskTMock.setCanRetry(false);
getMapsStatus = true;
assertFalse(chooseMapAsyncTaskTMock.retryUpload());
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests the method {@link ChooseMapAsyncTask#retryUpload()}. Make sure can
* retry after get maps failed and never retry before.
*/
public void testRetryUpload_retryOnce() throws Exception {
setup();
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTaskMock chooseMapAsyncTaskTMock = new ChooseMapAsyncTaskMock(
chooseMapActivityMock, account);
chooseMapAsyncTaskTMock.setCanRetry(true);
getMapsStatus = false;
assertFalse(chooseMapAsyncTaskTMock.retryUpload());
// Can only retry once.
assertFalse(chooseMapAsyncTaskTMock.getCanRetry());
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Tests the method {@link ChooseMapAsyncTask#retryUpload()}. Make sure will
* not retry after get maps successfully.
*/
public void testRetryUpload_successGetMaps() throws Exception {
setup();
AndroidMock.replay(chooseMapActivityMock);
ChooseMapAsyncTaskMock chooseMapAsyncTaskTMock = new ChooseMapAsyncTaskMock(
chooseMapActivityMock, account);
chooseMapAsyncTaskTMock.setCanRetry(true);
getMapsStatus = true;
assertTrue(chooseMapAsyncTaskTMock.retryUpload());
// Can only retry once.
assertFalse(chooseMapAsyncTaskTMock.getCanRetry());
AndroidMock.verify(chooseMapActivityMock);
}
/**
* Initials setup for test.
*/
void setup() {
setupChooseMapActivityMock();
account = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
}
/**
* Create a mock object of ChooseMapActivity.
*/
@UsesMocks(ChooseMapActivity.class)
private void setupChooseMapActivityMock() {
chooseMapActivityMock = AndroidMock.createMock(ChooseMapActivity.class);
// This is used in the constructor of ChooseMapAsyncTask.
AndroidMock.expect(chooseMapActivityMock.getApplicationContext()).andReturn(getContext()).anyTimes();
}
}
@@ -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.docs.SendDocsActivity;
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 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","sendDocs" and "cancel" to true, true and false.
*/
public void testGetNextClass_notCancelSendFusionTables() {
sendRequest.setSendFusionTables(true);
sendRequest.setSendDocs(true);
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
assertEquals(SendFusionTablesActivity.class, next);
}
/**
* Tests the method
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
* of "sendFusionTables","sendDocs" and "cancel" to false, true and false.
*/
public void testGetNextClass_notCancelSendDocs() {
sendRequest.setSendFusionTables(false);
sendRequest.setSendDocs(true);
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
assertEquals(SendDocsActivity.class, next);
}
/**
* Tests the method
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
* of "sendFusionTables","sendDocs" and "cancel" to false, false and false.
*/
public void testGetNextClass_notCancelNotSend() {
sendRequest.setSendFusionTables(false);
sendRequest.setSendDocs(false);
Class<?> next = sendMapsActivity.getNextClass(sendRequest, false);
assertEquals(UploadResultActivity.class, next);
}
/**
* Tests the method
* {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags
* of "sendFusionTables","sendDocs" and "cancel" to true, true and true.
*/
public void testGetNextClass_cancelSendDocs() {
sendRequest.setSendFusionTables(true);
sendRequest.setSendDocs(true);
Class<?> next = sendMapsActivity.getNextClass(sendRequest, true);
assertEquals(UploadResultActivity.class, next);
}
}
@@ -0,0 +1,356 @@
/*
* 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.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;
private static final String MAP_ID = "MapID_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,
String chooseMapId, MyTracksProviderUtils myTracksProviderUtils) {
super(activity, trackId, account, chooseMapId, 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 the method {@link SendMapsAsyncTask#saveResult()}and makes sure the
* track is updated.
*/
public void testSaveResult() {
Track track = TrackStubUtils.createTrack(1);
track.setMapId(null);
AndroidMock.expect(myTracksProviderUtilsMock.getTrack(TRACK_ID)).andReturn(track);
myTracksProviderUtilsMock.updateTrack(track);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), sendRequest.getMapId(),
myTracksProviderUtilsMock);
sendMapsAsyncTask.saveResult();
assertEquals(sendRequest.getMapId(), track.getMapId());
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
}
/**
* 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(), null, myTracksProviderUtilsMock);
// Returns false for an exception would be thrown.
assertFalse(sendMapsAsyncTask.fetchSendMapId(track));
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
}
/**
* Tests the method {@link SendMapsAsyncTask#fetchSendMapId(Track)} when
* chooseMapId is not null. And makes sure it returns false.
*/
public void testFetchSendMapId_notNullMapID() {
Track track = TrackStubUtils.createTrack(1);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, myTracksProviderUtilsMock);
assertTrue(sendMapsAsyncTask.fetchSendMapId(track));
assertEquals(MAP_ID, sendMapsAsyncTask.getMapId());
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
}
/**
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
* cursor is null. And makes sure it returns false.
*/
public void testUploadAllTrackPoints_nullCursor() {
Track track = TrackStubUtils.createTrack(1);
AndroidMock.expect(myTracksProviderUtilsMock.getLocationsCursor(TRACK_ID, 0, -1, false))
.andReturn(null);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, myTracksProviderUtilsMock);
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock);
}
/**
* 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);
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
AndroidMock.expect(cursorMock.getCount()).andReturn(2);
AndroidMock.expect(cursorMock.moveToPosition(0)).andReturn(true);
cursorMock.close();
AndroidMock.expect(myTracksProviderUtilsMock.createLocation(cursorMock)).andReturn(
new Location("1"));
AndroidMock.expect(myTracksProviderUtilsMock.getLocationsCursor(TRACK_ID, 0, -1, false))
.andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, myTracksProviderUtilsMock);
sendMapsAsyncTask.uploadMarkerResult[0] = false;
assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track));
assertEquals(1, uploadMarkerCounter);
AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
}
/**
* 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);
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
AndroidMock.expect(cursorMock.getCount()).andReturn(2);
AndroidMock.expect(cursorMock.moveToPosition(0)).andReturn(true);
AndroidMock.expect(cursorMock.moveToPosition(1)).andReturn(true);
cursorMock.close();
AndroidMock.expect(myTracksProviderUtilsMock.createLocation(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getLocationsCursor(TRACK_ID, 0, -1, false))
.andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, 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, cursorMock);
}
/**
* 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);
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
AndroidMock.expect(cursorMock.getCount()).andReturn(2);
AndroidMock.expect(cursorMock.moveToPosition(0)).andReturn(true);
AndroidMock.expect(cursorMock.moveToPosition(1)).andReturn(true);
cursorMock.close();
AndroidMock.expect(myTracksProviderUtilsMock.createLocation(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getLocationsCursor(TRACK_ID, 0, -1, false))
.andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, 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, cursorMock);
}
/**
* Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when
* return true.
*/
@UsesMocks(Cursor.class)
public void testUploadAllTrackPoints_success() {
Track track = TrackStubUtils.createTrack(1);
Cursor cursorMock = AndroidMock.createMock(Cursor.class);
AndroidMock.expect(cursorMock.getCount()).andReturn(2);
AndroidMock.expect(cursorMock.moveToPosition(0)).andReturn(true);
AndroidMock.expect(cursorMock.moveToPosition(1)).andReturn(true);
cursorMock.close();
AndroidMock.expect(myTracksProviderUtilsMock.createLocation(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getLocationsCursor(TRACK_ID, 0, -1, false))
.andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, 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, cursorMock);
}
/**
* Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when cursor is
* null.
*/
@UsesMocks(Cursor.class)
public void testUploadWaypoints_nullCursor() {
AndroidMock.expect(
myTracksProviderUtilsMock.getWaypointsCursor(TRACK_ID, 0,
Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(null);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, 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.getWaypointsCursor(TRACK_ID, 0,
Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), MAP_ID, 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.getWaypointsCursor(TRACK_ID, 0,
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(), MAP_ID, 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));
}
}
@@ -0,0 +1,179 @@
/*
* 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.content.Track;
import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature;
import com.google.android.maps.GeoPoint;
import android.location.Location;
import java.util.ArrayList;
import junit.framework.TestCase;
/**
* Tests {@link SendMapsUtils}.
*
* @author Jimmy Shih
*/
public class SendMapsUtilsTest extends TestCase {
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with null track.
*/
public void testGetMapUrl_null_track() {
assertEquals(null, SendMapsUtils.getMapUrl(null));
}
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with null map id.
*/
public void testGetMapUrl_null_map_id() {
Track track = new Track();
track.setMapId(null);
assertEquals(null, SendMapsUtils.getMapUrl(track));
}
/**
* Tests {@link SendMapsUtils#getMapUrl(Track)} with a valid track.
*/
public void testGetMapUrl_valid_track() {
Track track = new Track();
track.setMapId("123");
assertEquals("https://maps.google.com/maps/ms?msa=0&msid=123", SendMapsUtils.getMapUrl(track));
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* GeoPoint)} with a title.
*/
public void testBuildMapsMarkerFeature_with_title() {
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
"name", "this\nmap\ndescription", "url", new GeoPoint(123, 456));
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, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(456, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* GeoPoint)} with an empty title.
*/
public void testBuildMapsMarkerFeature_empty_title() {
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
"", "description", "url", new GeoPoint(123, 456));
assertEquals(MapsFeature.MARKER, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals("description", mapFeature.getDescription());
assertEquals("url", mapFeature.getIconUrl());
assertEquals(123, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(456, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* GeoPoint)} with a null title.
*/
public void testBuildMapsMarkerFeature_null_title() {
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
null, "description", "url", new GeoPoint(123, 456));
assertEquals(MapsFeature.MARKER, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals("description", mapFeature.getDescription());
assertEquals("url", mapFeature.getIconUrl());
assertEquals(123, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(456, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* 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);
location.setLongitude(100);
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(50000000, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(100000000, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* 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);
location.setLongitude(100);
locations.add(location);
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("", locations);
assertEquals(MapsFeature.LINE, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals(0x80FF0000, mapFeature.getColor());
assertEquals(50000000, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(100000000, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* 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);
location.setLongitude(100);
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(50000000, mapFeature.getPoint(0).getLatitudeE6());
assertEquals(100000000, mapFeature.getPoint(0).getLongitudeE6());
}
/**
* Test {@link SendMapsUtils#getGeoPoint(Location)}.
*/
public void testGeoPoint() {
Location location = new Location("test");
location.setLatitude(50);
location.setLongitude(100);
GeoPoint geoPoint = SendMapsUtils.getGeoPoint(location);
assertEquals(50000000, geoPoint.getLatitudeE6());
assertEquals(100000000, geoPoint.getLongitudeE6());
}
}
@@ -0,0 +1,286 @@
/*
* 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;
final static private String ACCOUNTNAME = "testAccount1";
final static private String ACCOUNTYPE = "testType1";
final static private String MAPID = "mapId1";
@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#isSendDocs()}. The value should be set
* to false which is its default value when it is initialed in setup method.
*/
public void testIsSendDocs() {
assertEquals(false, sendRequest.isSendDocs());
sendRequest.setSendDocs(true);
assertEquals(true, sendRequest.isSendDocs());
}
/**
* Tests the method {@link SendRequest#isNewMap()}. The value should be set to
* false which is its default value when it is initialed in setup method.
*/
public void testIsNewMap() {
assertEquals(false, sendRequest.isNewMap());
sendRequest.setNewMap(true);
assertEquals(true, sendRequest.isNewMap());
}
/**
* 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#getMapId()}. The value should be set to
* null which is its default value when it is initialed in setup method.
*/
public void testGetMapId() {
assertEquals(null, sendRequest.getMapId());
sendRequest.setMapId("1");
assertEquals("1", "1");
}
/**
* 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#isDocsSuccess()}. The value should be
* set to false which is its default value when it is initialed in setup
* method.
*/
public void testIsDocsSuccess() {
assertEquals(false, sendRequest.isDocsSuccess());
sendRequest.setDocsSuccess(true);
assertEquals(true, sendRequest.isDocsSuccess());
}
/**
* Tests SendRequest.CREATOR.createFromParcel when all values are true.
*/
public void testCreateFromParcel_true() {
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
parcel.writeLong(2);
parcel.writeString("");
parcel.writeString("");
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
parcel.writeParcelable(account, 0);
parcel.writeString(MAPID);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.writeByte((byte) 1);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(2, sendRequest.getTrackId());
assertEquals("", sendRequest.getSharingAppPackageName());
assertEquals("", sendRequest.getSharingAppClassName());
assertTrue(sendRequest.isSendMaps());
assertTrue(sendRequest.isSendFusionTables());
assertTrue(sendRequest.isSendDocs());
assertTrue(sendRequest.isNewMap());
assertEquals(account, sendRequest.getAccount());
assertEquals(MAPID, sendRequest.getMapId());
assertTrue(sendRequest.isMapsSuccess());
assertTrue(sendRequest.isFusionTablesSuccess());
assertTrue(sendRequest.isDocsSuccess());
}
/**
* Tests SendRequest.CREATOR.createFromParcel when all values are false.
*/
public void testCreateFromParcel_false() {
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
parcel.writeLong(4);
parcel.writeString(null);
parcel.writeString(null);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
Account account = new Account(ACCOUNTNAME, ACCOUNTYPE);
parcel.writeParcelable(account, 0);
parcel.writeString(MAPID);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.writeByte((byte) 0);
parcel.setDataPosition(0);
sendRequest = SendRequest.CREATOR.createFromParcel(parcel);
assertEquals(4, sendRequest.getTrackId());
assertNull(sendRequest.getSharingAppPackageName());
assertNull(sendRequest.getSharingAppClassName());
assertFalse(sendRequest.isSendMaps());
assertFalse(sendRequest.isSendFusionTables());
assertFalse(sendRequest.isSendDocs());
assertFalse(sendRequest.isNewMap());
assertEquals(account, sendRequest.getAccount());
assertEquals(MAPID, sendRequest.getMapId());
assertFalse(sendRequest.isMapsSuccess());
assertFalse(sendRequest.isFusionTablesSuccess());
assertFalse(sendRequest.isDocsSuccess());
}
/**
* 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();
String sharingAppPackageName = parcel.readString();
String sharingAppClassName = parcel.readString();
boolean sendMaps = parcel.readByte() == 1;
boolean sendFusionTables = parcel.readByte() == 1;
boolean sendDocs = parcel.readByte() == 1;
boolean newMap = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
String mapId = parcel.readString();
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean docsSuccess = parcel.readByte() == 1;
assertEquals(1, trackId);
assertNull(sharingAppPackageName);
assertNull(sharingAppClassName);
assertFalse(sendMaps);
assertFalse(sendFusionTables);
assertFalse(sendDocs);
assertFalse(newMap);
assertNull(account);
assertNull(mapId);
assertFalse(mapsSuccess);
assertFalse(fusionTablesSuccess);
assertFalse(docsSuccess);
}
/**
* Tests {@link SendRequest#writeToParcel(Parcel, int)}.
*/
public void testWriteToParcel() {
sendRequest = new SendRequest(4);
sendRequest.setSharingAppPackageName("package");
sendRequest.setSharingAppClassName("class");
sendRequest.setSendMaps(true);
sendRequest.setSendFusionTables(true);
sendRequest.setSendDocs(true);
sendRequest.setNewMap(true);
Account accountNew = new Account(ACCOUNTNAME + "2", ACCOUNTYPE + "2");
sendRequest.setAccount(accountNew);
sendRequest.setMapId(MAPID);
sendRequest.setMapsSuccess(true);
sendRequest.setFusionTablesSuccess(true);
sendRequest.setDocsSuccess(true);
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
sendRequest.writeToParcel(parcel, 1);
parcel.setDataPosition(0);
long trackId = parcel.readLong();
String sharingAppPackageName = parcel.readString();
String sharingAppClassName = parcel.readString();
boolean sendMaps = parcel.readByte() == 1;
boolean sendFusionTables = parcel.readByte() == 1;
boolean sendDocs = parcel.readByte() == 1;
boolean newMap = parcel.readByte() == 1;
Parcelable account = parcel.readParcelable(null);
String mapId = parcel.readString();
boolean mapsSuccess = parcel.readByte() == 1;
boolean fusionTablesSuccess = parcel.readByte() == 1;
boolean docsSuccess = parcel.readByte() == 1;
assertEquals(4, trackId);
assertEquals("package", sharingAppPackageName);
assertEquals("class", sharingAppClassName);
assertTrue(sendMaps);
assertTrue(sendFusionTables);
assertTrue(sendDocs);
assertTrue(newMap);
assertEquals(accountNew, account);
assertEquals(MAPID, mapId);
assertTrue(mapsSuccess);
assertTrue(fusionTablesSuccess);
assertTrue(docsSuccess);
}
}
@@ -0,0 +1,140 @@
/*
* 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#prepareTrackSegment(Track, java.util.ArrayList)}
* when there is only one location in a segment.
*/
public void testPrepareTrackSegment_onlyOneLocation() {
Track trackStub = TrackStubUtils.createTrack(1);
assertFalse(SendToGoogleUtils.prepareTrackSegment(trackStub, null));
}
/**
* Tests the method
* {@link SendToGoogleUtils#prepareTrackSegment(Track, ArrayList)} when there
* is no stop time.
*/
public void testPrepareTrackSegment_noStopTime() {
Track trackStub = TrackStubUtils.createTrack(2);
assertEquals(-1L, trackStub.getStatistics().getStopTime());
ArrayList<Track> tracksArray = new ArrayList<Track>();
assertTrue(SendToGoogleUtils.prepareTrackSegment(trackStub, tracksArray));
assertEquals(trackStub, tracksArray.get(0));
// The stop time should be the time of last location
assertEquals(trackStub.getLocations().get(1).getTime(), trackStub.getStatistics().getStopTime());
}
/**
* Tests the method
* {@link SendToGoogleUtils#prepareTrackSegment(Track, java.util.ArrayList)}
* when there is stop time.
*/
public void testPrepareTrackSegment_hasStopTime() {
Track trackStub = TrackStubUtils.createTrack(2);
// Gives a margin to make sure the this time will be not same with the last
// location in the track.
long stopTime = System.currentTimeMillis() + 1000;
trackStub.getStatistics().setStopTime(stopTime);
ArrayList<Track> tracksArray = new ArrayList<Track>();
SendToGoogleUtils.prepareTrackSegment(trackStub, tracksArray);
assertEquals(trackStub, tracksArray.get(0));
assertEquals(stopTime, trackStub.getStatistics().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());
}
}
}
@@ -0,0 +1,114 @@
/*
* 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 com.google.android.maps.mytracks.R;
import android.app.Dialog;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Tests the {@link UploadResultActivity}.
*
* @author Youtao Liu
*/
public class UploadResultActivityTest
extends ActivityInstrumentationTestCase2<UploadResultActivity> {
private UploadResultActivity uploadResultActivity;
/**
* This method is necessary for ActivityInstrumentationTestCase2.
*/
public UploadResultActivityTest() {
super(UploadResultActivity.class);
}
/**
* Checks the display of dialog when send to all and all sends are successful.
*/
public void testAllSuccess() {
initialActivity(true, true, true, true, true, true);
uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_success_footer);
assertTrue(textView.isShown());
}
/**
* Checks the display of dialog when send to all and all sends are failed.
*/
public void testAllFailed() {
// Send all kinds but all failed.
initialActivity(true, true, true, false, false, false);
uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_error_footer);
assertTrue(textView.isShown());
}
/**
* Checks the display of dialog when match following items:
* <ul>
* <li>Only send to Maps and Docs.</li>
* <li>Send to Maps successful.</li>
* <li>Send to Docs failed.</li>
* </ul>
*/
public void testPartialSuccess() {
initialActivity(true, false, true, true, false, false);
uploadResultActivity.showDialog(UploadResultActivity.DIALOG_RESULT_ID);
Dialog dialog = uploadResultActivity.getDialog();
TextView textView = (TextView) dialog.findViewById(R.id.upload_result_error_footer);
assertTrue(textView.isShown());
LinearLayout mapsResult = (LinearLayout) dialog.findViewById(R.id.upload_result_maps_result);
assertTrue(mapsResult.isShown());
LinearLayout fusionTablesResult = (LinearLayout) dialog.findViewById(
R.id.upload_result_fusion_tables_result);
assertFalse(fusionTablesResult.isShown());
LinearLayout docsResult = (LinearLayout) dialog.findViewById(R.id.upload_result_docs_result);
assertTrue(docsResult.isShown());
}
/**
* Initial a {@link SendRequest} and then initials a activity to be tested.
*
* @param isSendMaps
* @param isSendFusionTables
* @param isSendDocs
* @param isMapsSuccess
* @param isFusionTablesSuccess
* @param isDocsSuccess
*/
private void initialActivity(boolean isSendMaps, boolean isSendFusionTables, boolean isSendDocs,
boolean isMapsSuccess, boolean isFusionTablesSuccess, boolean isDocsSuccess) {
Intent intent = new Intent();
SendRequest sendRequest = new SendRequest(1L);
sendRequest.setSendMaps(isSendMaps);
sendRequest.setSendFusionTables(isSendFusionTables);
sendRequest.setSendDocs(isSendDocs);
sendRequest.setMapsSuccess(isMapsSuccess);
sendRequest.setFusionTablesSuccess(isFusionTablesSuccess);
sendRequest.setDocsSuccess(isDocsSuccess);
intent.putExtra(SendRequest.SEND_REQUEST_KEY, sendRequest);
setActivityIntent(intent);
uploadResultActivity = this.getActivity();
}
}
@@ -0,0 +1,159 @@
/*
* 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.Constants;
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;
/**
* Tests for the {@link DynamicSpeedTrackPathDescriptor}.
*
* @author Youtao Liu
*/
public class DynamicSpeedTrackPathDescriptorTest extends AndroidTestCase {
private Context context;
private SharedPreferences sharedPreferences;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
}
/**
* 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#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is null.
*/
public void testOnSharedPreferenceChanged_nullKey() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
int speedMargin = dynamicSpeedTrackPathDescriptor.getSpeedMargin();
// Change value in shared preferences.
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, speedMargin + 2);
dynamicSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences, null);
assertEquals(speedMargin, dynamicSpeedTrackPathDescriptor.getSpeedMargin());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is not null, and not trackColorModeDynamicVariation.
*/
public void testOnSharedPreferenceChanged_otherKey() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
int speedMargin = dynamicSpeedTrackPathDescriptor.getSpeedMargin();
// Change value in shared preferences.
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, speedMargin + 2);
dynamicSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences, "anyKey");
assertEquals(speedMargin, dynamicSpeedTrackPathDescriptor.getSpeedMargin());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is trackColorModeDynamicVariation.
*/
public void testOnSharedPreferenceChanged_trackColorModeDynamicVariationKey() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
int speedMargin = dynamicSpeedTrackPathDescriptor.getSpeedMargin();
// Change value in shared preferences.
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, speedMargin + 2);
dynamicSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences,
PreferencesUtils.getKey(context, R.string.track_color_mode_percentage_key));
assertEquals(speedMargin + 2, dynamicSpeedTrackPathDescriptor.getSpeedMargin());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the values of speedMargin is the default value.
*/
public void testOnSharedPreferenceChanged_defaultValue() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
// Change value in shared preferences
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key,
PreferencesUtils.TRACK_COLOR_MODE_PERCENTAGE_DEFAULT);
dynamicSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences,
PreferencesUtils.getKey(context, R.string.track_color_mode_percentage_key));
// The default value of speedMargin is 25.
assertEquals(PreferencesUtils.TRACK_COLOR_MODE_PERCENTAGE_DEFAULT,
dynamicSpeedTrackPathDescriptor.getSpeedMargin());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#needsRedraw()} by wrong track
* id.
*/
public void testNeedsRedraw_WrongTrackId() {
PreferencesUtils.setLong(
context, R.string.selected_track_id_key, PreferencesUtils.SELECTED_TRACK_ID_DEFAULT);
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
assertEquals(false, dynamicSpeedTrackPathDescriptor.needsRedraw());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#needsRedraw()} 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 = { 20, 30, 30,
30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100.00) * 2) };
// 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());
}
}
}
@@ -0,0 +1,165 @@
/*
* 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.ColoredPath;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.maps.mytracks.R;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import java.util.List;
/**
* Tests for the {@link DynamicSpeedTrackPathPainter}.
*
* @author Youtao Liu
*/
public class DynamicSpeedTrackPathPainterTest extends TrackPathPainterTestCase {
private DynamicSpeedTrackPathPainter dynamicSpeedTrackPathPainter;
private TrackPathDescriptor trackPathDescriptor;
// This number must bigger than 10 to meet the requirement of test.
private static final int NUMBER_OF_LOCATIONS = 100;
private static final int LOCATIONS_PER_SEGMENT = 25;
// The maximum speed(KM/H) which is considered slow.
private static final int SLOW_SPEED_KMH = 30;
// The maximum speed(KM/H) which is considered normal.
private static final int NORMAL_SPEED_KMH = 50;
// Convert from kilometers per hour to meters per second
private static final double KMH_TO_MS = 1 / 3.6;
private static final int SLOW_SPEED_MS = (int) (SLOW_SPEED_KMH * KMH_TO_MS);
private static final int NORMAL_SPEED_MS = (int) (NORMAL_SPEED_KMH * KMH_TO_MS);
@Override
protected void setUp() throws Exception {
super.setUp();
initialTrackPathDescriptorMock();
dynamicSpeedTrackPathPainter = new DynamicSpeedTrackPathPainter(getContext(),
trackPathDescriptor);
}
/**
* Tests the method
* {@link DynamicSpeedTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, java.util.List)}
* when all locations are invalid.
*/
public void testUpdatePath_AllInvalidLocation() {
List<CachedLocation> points = createCachedLocations(NUMBER_OF_LOCATIONS, INVALID_LATITUDE, -1);
dynamicSpeedTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), 1, true, points);
AndroidMock.verify(trackPathDescriptor);
// Should be zero for there is no valid locations.
assertEquals(0, dynamicSpeedTrackPathPainter.getColoredPaths().size());
}
/**
* Tests the
* {@link DynamicSpeedTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, java.util.List)}
* when all locations are valid.
*/
public void testUpdatePath_AllValidLocation() {
List<CachedLocation> points = createCachedLocations(NUMBER_OF_LOCATIONS,
TrackStubUtils.INITIAL_LATITUDE, -1);
// Gets a number as the start index of points.
int startLocationIdx = NUMBER_OF_LOCATIONS / 2;
dynamicSpeedTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, true, points);
AndroidMock.verify(trackPathDescriptor);
assertEquals(NUMBER_OF_LOCATIONS - startLocationIdx, dynamicSpeedTrackPathPainter
.getColoredPaths().size());
}
/**
* Tests the
* {@link DynamicSpeedTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, java.util.List)}
* when all locations are valid. This test setups 4 segments with 25 points
* each. The first segment has slow speed, the second segment has normal
* speed, the third segment has fast speed, and the fourth segment has slow
* speed.
*/
public void testUpdatePath_CheckColoredPath() {
// Gets the slow speed. Divide SLOW_SPEED by 2 to make it smaller than
// SLOW_SPEED. Speed in MyTracksLocation use MS, but speed in CachedLocation
// use KMH.
int slowSpeed = SLOW_SPEED_MS / 2;
// Gets the normal speed. Makes it smaller than SLOW_SPEED and bigger than
// NORMAL_SPEED. Speed in MyTracksLocation use MS, but speed in
// CachedLocation use KMH.
int normalSpeed = (SLOW_SPEED_MS + NORMAL_SPEED_MS) / 2;
// Gets the fast speed. Multiply it by 2 to make it bigger than
// NORMAL_SPEED. Speed in MyTracksLocation use MS, but speed in
// CachedLocation use KMH.
int fastSpeed = NORMAL_SPEED_MS * 2;
// Get a number of startLocationIdx. And divide NUMBER_OF_LOCATIONS by 8 to
// make sure it is less than numberOfFirstThreeSegments.
int startLocationIdx = LOCATIONS_PER_SEGMENT / 2;
List<CachedLocation> points = createCachedLocations(LOCATIONS_PER_SEGMENT,
TrackStubUtils.INITIAL_LATITUDE, slowSpeed);
points.addAll(createCachedLocations(LOCATIONS_PER_SEGMENT, TrackStubUtils.INITIAL_LATITUDE,
normalSpeed));
points.addAll(createCachedLocations(LOCATIONS_PER_SEGMENT, TrackStubUtils.INITIAL_LATITUDE,
fastSpeed));
points.addAll(createCachedLocations(LOCATIONS_PER_SEGMENT, TrackStubUtils.INITIAL_LATITUDE,
slowSpeed));
dynamicSpeedTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, true, points);
AndroidMock.verify(trackPathDescriptor);
List<ColoredPath> coloredPath = dynamicSpeedTrackPathPainter.getColoredPaths();
assertEquals(NUMBER_OF_LOCATIONS - startLocationIdx, coloredPath.size());
// Checks different speeds with different color in the coloredPath.
for (int i = 0; i < NUMBER_OF_LOCATIONS - startLocationIdx; i++) {
if (i < LOCATIONS_PER_SEGMENT - startLocationIdx) {
// Slow.
assertEquals(getContext().getResources().getColor(R.color.slow_path), coloredPath.get(i)
.getPathPaint().getColor());
} else if (i < LOCATIONS_PER_SEGMENT * 2 - startLocationIdx) {
// Normal.
assertEquals(getContext().getResources().getColor(R.color.normal_path), coloredPath.get(i)
.getPathPaint().getColor());
} else if (i < LOCATIONS_PER_SEGMENT * 3 - startLocationIdx) {
// Fast.
assertEquals(getContext().getResources().getColor(R.color.fast_path), coloredPath.get(i)
.getPathPaint().getColor());
} else {
// Slow.
assertEquals(getContext().getResources().getColor(R.color.slow_path), coloredPath.get(i)
.getPathPaint().getColor());
}
}
}
/**
* Initials a mocked TrackPathDescriptor object.
*/
@UsesMocks(TrackPathDescriptor.class)
private void initialTrackPathDescriptorMock() {
trackPathDescriptor = AndroidMock.createMock(TrackPathDescriptor.class);
AndroidMock.expect(trackPathDescriptor.getSlowSpeed()).andReturn(SLOW_SPEED_KMH);
AndroidMock.expect(trackPathDescriptor.getNormalSpeed()).andReturn(NORMAL_SPEED_KMH);
AndroidMock.replay(trackPathDescriptor);
}
}
@@ -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.maps;
import com.google.android.apps.mytracks.Constants;
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;
/**
* Tests for the {@link DynamicSpeedTrackPathDescriptor}.
*
* @author Youtao Liu
*/
public class FixedSpeedTrackPathDescriptorTest extends AndroidTestCase {
private Context context;
private SharedPreferences sharedPreferences;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
}
/**
* Tests the initialization of slowSpeed and normalSpeed in {@link DynamicSpeedTrackPathDescriptor#DynamicSpeedTrackPathDescriptor(Context)}
* .
*/
public void testConstructor() {
int[] slowSpeedExpectations = { 0, 1, 99, PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT };
int[] normalSpeedExpectations = { 0, 1, 99, PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT };
for (int i = 0; i < slowSpeedExpectations.length; i++) {
PreferencesUtils.setInt(
context, R.string.track_color_mode_slow_key, slowSpeedExpectations[i]);
PreferencesUtils.setInt(
context, R.string.track_color_mode_medium_key, normalSpeedExpectations[i]);
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
assertEquals(slowSpeedExpectations[i], fixedSpeedTrackPathDescriptor.getSlowSpeed());
assertEquals(normalSpeedExpectations[i], fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is null.
*/
public void testOnSharedPreferenceChanged_null_key() {
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
int slowSpeed = fixedSpeedTrackPathDescriptor.getSlowSpeed();
int normalSpeed = fixedSpeedTrackPathDescriptor.getNormalSpeed();
// Change value in shared preferences
PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, slowSpeed + 2);
PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, normalSpeed + 2);
fixedSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences, null);
assertEquals(slowSpeed, fixedSpeedTrackPathDescriptor.getSlowSpeed());
assertEquals(normalSpeed, fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is not null, and not slowSpeed and not normalSpeed.
*/
public void testOnSharedPreferenceChanged_other_key() {
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
int slowSpeed = fixedSpeedTrackPathDescriptor.getSlowSpeed();
int normalSpeed = fixedSpeedTrackPathDescriptor.getNormalSpeed();
// Change value in shared preferences
PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, slowSpeed + 2);
PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, normalSpeed + 2);
fixedSpeedTrackPathDescriptor.onSharedPreferenceChanged(sharedPreferences, "anyKey");
assertEquals(slowSpeed, fixedSpeedTrackPathDescriptor.getSlowSpeed());
assertEquals(normalSpeed, fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is slowSpeed.
*/
public void testOnSharedPreferenceChanged_slowSpeedKey() {
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
int slowSpeed = fixedSpeedTrackPathDescriptor.getSlowSpeed();
// Change value in shared preferences
PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, slowSpeed + 2);
fixedSpeedTrackPathDescriptor.onSharedPreferenceChanged(
sharedPreferences, context.getString(R.string.track_color_mode_slow_key));
assertEquals(slowSpeed + 2, fixedSpeedTrackPathDescriptor.getSlowSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the key is normalSpeed.
*/
public void testOnSharedPreferenceChanged_normalSpeedKey() {
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
int normalSpeed = fixedSpeedTrackPathDescriptor.getNormalSpeed();
PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, normalSpeed + 4);
fixedSpeedTrackPathDescriptor.onSharedPreferenceChanged(
sharedPreferences, context.getString(R.string.track_color_mode_medium_key));
assertEquals(normalSpeed + 4, fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#onSharedPreferenceChanged(SharedPreferences,
* String)} when the values of slowSpeed and normalSpeed in SharedPreference
* are the default values.
*/
public void testOnSharedPreferenceChanged_defaultValue() {
FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor(
context);
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);
fixedSpeedTrackPathDescriptor.onSharedPreferenceChanged(
sharedPreferences, context.getString(R.string.track_color_mode_medium_key));
assertEquals(PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT,
fixedSpeedTrackPathDescriptor.getSlowSpeed());
assertEquals(PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT,
fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
}
@@ -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.maps;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.graphics.Path;
import java.util.List;
/**
* Tests for the {@link SingleColorTrackPathPainter}.
*
* @author Youtao Liu
*/
public class SingleColorTrackPathPainterTest extends TrackPathPainterTestCase {
private SingleColorTrackPathPainter singleColorTrackPathPainter;
private Path pathMock;
private static final int NUMBER_OF_LOCATIONS = 100;
/**
* Initials a mocked TrackPathDescriptor object and
* singleColorTrackPathPainter.
*/
@Override
@UsesMocks(Path.class)
protected void setUp() throws Exception {
super.setUp();
pathMock = AndroidMock.createStrictMock(Path.class);
singleColorTrackPathPainter = new SingleColorTrackPathPainter(getContext());
}
/**
* Tests the
* {@link SingleColorTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, List, Path)}
* method when all locations are valid.
*/
public void testUpdatePath_AllValidLocation() {
pathMock.incReserve(NUMBER_OF_LOCATIONS);
List<CachedLocation> points = createCachedLocations(NUMBER_OF_LOCATIONS,
TrackStubUtils.INITIAL_LATITUDE, -1);
// Gets a number as the start index of points.
int startLocationIdx = NUMBER_OF_LOCATIONS / 2;
for (int i = startLocationIdx; i < NUMBER_OF_LOCATIONS; i++) {
pathMock.lineTo(0, 0);
}
AndroidMock.replay(pathMock);
singleColorTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, true, points, pathMock);
AndroidMock.verify(pathMock);
}
/**
* Tests the
* {@link SingleColorTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, List, Path)}
* method when all locations are invalid.
*/
public void testUpdatePath_AllInvalidLocation() {
pathMock.incReserve(NUMBER_OF_LOCATIONS);
List<CachedLocation> points = createCachedLocations(NUMBER_OF_LOCATIONS, INVALID_LATITUDE, -1);
// Gets a random number from 1 to numberOfLocations.
int startLocationIdx = NUMBER_OF_LOCATIONS / 2;
AndroidMock.replay(pathMock);
singleColorTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, true, points, pathMock);
AndroidMock.verify(pathMock);
}
/**
* Tests the
* {@link SingleColorTrackPathPainter#updatePath(com.google.android.maps.Projection, android.graphics.Rect, int, Boolean, List, Path)}
* method when there are three segments.
*/
public void testUpdatePath_ThreeSegments() {
// First segment.
List<CachedLocation> points = createCachedLocations(NUMBER_OF_LOCATIONS,
TrackStubUtils.INITIAL_LATITUDE, -1);
points.addAll(createCachedLocations(1, INVALID_LATITUDE, -1));
// Second segment.
points.addAll(createCachedLocations(NUMBER_OF_LOCATIONS, TrackStubUtils.INITIAL_LATITUDE, -1));
points.addAll(createCachedLocations(1, INVALID_LATITUDE, -1));
// Third segment.
points.addAll(createCachedLocations(NUMBER_OF_LOCATIONS, TrackStubUtils.INITIAL_LATITUDE, -1));
// Gets a random number from 1 to numberOfLocations.
int startLocationIdx = NUMBER_OF_LOCATIONS / 2;
pathMock.incReserve(NUMBER_OF_LOCATIONS *3 + 1 +1);
for (int i = 0; i < NUMBER_OF_LOCATIONS - startLocationIdx; i++) {
pathMock.lineTo(0, 0);
}
pathMock.moveTo(0, 0);
for (int i = 0; i < NUMBER_OF_LOCATIONS - 1; i++) {
pathMock.lineTo(0, 0);
}
pathMock.moveTo(0, 0);
for (int i = 0; i < NUMBER_OF_LOCATIONS - 1; i++) {
pathMock.lineTo(0, 0);
}
AndroidMock.replay(pathMock);
singleColorTrackPathPainter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, true, points, pathMock);
AndroidMock.verify(pathMock);
}
}
@@ -0,0 +1,52 @@
/*
* 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.maps;
import android.location.Location;
/**
* Tests for the MyTracks track path descriptors and painters.
*
* @author Vangelis S.
*/
public class TrackPathDescriptorDynamicSpeedTest extends TrackPathPainterTestCase {
public void testDynamicSpeedTrackPathDescriptor() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
for (int i = 0; i < 100; ++i) {
location = new Location("gps");
location.setLatitude(20 + i / 2);
location.setLongitude(150 - i);
myTracksOverlay.addLocation(location);
}
TrackPathPainter painter = new DynamicSpeedTrackPathPainter(
getContext(), new DynamicSpeedTrackPathDescriptor(getContext()));
myTracksOverlay.setTrackPathPainter(painter);
int startLocationIdx = 0;
Boolean alwaysVisible = true;
assertNotNull(painter);
painter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible,
myTracksOverlay.getPoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
painter.drawTrack(canvas);
}
}
@@ -0,0 +1,52 @@
/*
* 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.maps;
import android.location.Location;
/**
* Tests for the MyTracks track path descriptors and painters.
*
* @author Vangelis S.
*/
public class TrackPathDescriptorFixedSpeedTest extends TrackPathPainterTestCase {
public void testFixedSpeedTrackPathDescriptor() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
for (int i = 0; i < 100; ++i) {
location = new Location("gps");
location.setLatitude(20 + i / 2);
location.setLongitude(150 - i);
myTracksOverlay.addLocation(location);
}
TrackPathPainter painter = new DynamicSpeedTrackPathPainter(
getContext(), new FixedSpeedTrackPathDescriptor(getContext()));
myTracksOverlay.setTrackPathPainter(painter);
int startLocationIdx = 0;
Boolean alwaysVisible = true;
assertNotNull(painter);
painter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible,
myTracksOverlay.getPoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
painter.drawTrack(canvas);
}
}
@@ -0,0 +1,72 @@
/*
* 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.maps;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.location.Location;
/**
* Tests for the MyTracks track path painter factory.
*
* @author Vangelis S.
*/
public class TrackPathPainterFactoryTest extends TrackPathPainterTestCase {
public void testTrackPathPainterFactory() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
for (int i = 0; i < 100; ++i) {
location = new Location("gps");
location.setLatitude(20 + i / 2);
location.setLongitude(150 - i);
myTracksOverlay.addLocation(location);
}
Context context = getContext();
testTrackPathPainterFactorySpecific(context,
R.string.settings_map_track_color_mode_single_value, SingleColorTrackPathPainter.class);
testTrackPathPainterFactorySpecific(context, R.string.settings_map_track_color_mode_fixed_value,
DynamicSpeedTrackPathPainter.class);
testTrackPathPainterFactorySpecific(context,
R.string.settings_map_track_color_mode_dynamic_value, DynamicSpeedTrackPathPainter.class);
}
private <T> void testTrackPathPainterFactorySpecific(
Context context, int track_color_mode, Class<?> c) {
PreferencesUtils.setString(
context, R.string.track_color_mode_key, context.getString(track_color_mode));
int startLocationIdx = 0;
Boolean alwaysVisible = true;
TrackPathPainter painter = TrackPathPainterFactory.getTrackPathPainter(context);
myTracksOverlay.setTrackPathPainter(painter);
assertNotNull(painter);
assertTrue(c.isInstance(painter));
painter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible,
myTracksOverlay.getPoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
painter.drawTrack(canvas);
}
}
@@ -0,0 +1,51 @@
/*
* 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.maps;
import android.location.Location;
/**
* Tests for the MyTracks track path descriptors and painters.
*
* @author Vangelis S.
*/
public class TrackPathPainterSingleColorTest extends TrackPathPainterTestCase {
public void testSimpeColorTrackPathPainter() throws Exception {
Location location = new Location("gps");
location.setLatitude(10);
for (int i = 0; i < 100; ++i) {
location = new Location("gps");
location.setLatitude(20 + i / 2);
location.setLongitude(150 - i);
myTracksOverlay.addLocation(location);
}
TrackPathPainter painter = new SingleColorTrackPathPainter(getContext());
myTracksOverlay.setTrackPathPainter(painter);
int startLocationIdx = 0;
Boolean alwaysVisible = true;
assertNotNull(painter);
painter.updatePath(myTracksOverlay.getMapProjection(mockView),
myTracksOverlay.getMapViewRect(mockView), startLocationIdx, alwaysVisible,
myTracksOverlay.getPoints());
assertNotNull(myTracksOverlay.getTrackPathPainter().getLastPath());
painter.drawTrack(canvas);
}
}
@@ -0,0 +1,76 @@
/*
* 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.maps;
import com.google.android.apps.mytracks.MapOverlay;
import com.google.android.apps.mytracks.MapOverlay.CachedLocation;
import com.google.android.apps.mytracks.MockMyTracksOverlay;
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.maps.MapView;
import android.graphics.Canvas;
import android.location.Location;
import android.test.AndroidTestCase;
import java.util.ArrayList;
import java.util.List;
/**
* Tests for the MyTracks track path descriptors and painters.
*
* @author Vangelis S.
*/
public class TrackPathPainterTestCase extends AndroidTestCase {
protected Canvas canvas;
protected MockMyTracksOverlay myTracksOverlay;
protected MapView mockView;
final int INVALID_LATITUDE = 100;
@Override
protected void setUp() throws Exception {
super.setUp();
canvas = new Canvas();
myTracksOverlay = new MockMyTracksOverlay(getContext());
// Enable drawing.
myTracksOverlay.setTrackDrawingEnabled(true);
mockView = null;
}
/**
* Creates a list of CachedLocations.
*
* @param number the number of locations
* @param latitude the latitude value of locations.
* @param speed the speed(meter per second) of locations, and will give a default valid value if
* less than zero
* @return the simulated locations
*/
List<CachedLocation> createCachedLocations(int number, double latitude, float speed) {
List<CachedLocation> points = new ArrayList<MapOverlay.CachedLocation>();
for (int i = 0; i < number; ++i) {
Location location = TrackStubUtils.createMyTracksLocation(latitude,
TrackStubUtils.INITIAL_LONGITUDE, TrackStubUtils.INITIAL_ALTITUDE);
if (speed > 0) {
location.setSpeed(speed);
}
CachedLocation cachedLocation = new CachedLocation(location);
points.add(cachedLocation);
}
return points;
}
}
@@ -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());
}
}
@@ -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;
}
}
@@ -0,0 +1,103 @@
/*
* 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 static com.google.android.testing.mocking.AndroidMock.expect;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.test.AndroidTestCase;
import java.io.File;
/**
* Tests {@link RemoveTempFilesService}.
*
* @author Sandor Dornbush
*/
public class RemoveTempFilesServiceTest extends AndroidTestCase {
private static final String DIR_NAME = "/tmp";
private static final String FILE_NAME = "foo";
private RemoveTempFilesService service;
@UsesMocks({ File.class, })
protected void setUp() throws Exception {
service = new RemoveTempFilesService();
};
/**
* Tests when the directory doesn't exists.
*/
public void test_noDir() {
File dir = AndroidMock.createMock(File.class, DIR_NAME);
expect(dir.exists()).andStubReturn(false);
AndroidMock.replay(dir);
assertEquals(0, service.cleanTempDirectory(dir));
AndroidMock.verify(dir);
}
/**
* Tests when the directory is empty.
*/
public void test_emptyDir() {
File dir = AndroidMock.createMock(File.class, DIR_NAME);
expect(dir.exists()).andStubReturn(true);
expect(dir.listFiles()).andStubReturn(new File[0]);
AndroidMock.replay(dir);
assertEquals(0, service.cleanTempDirectory(dir));
AndroidMock.verify(dir);
}
/**
* Tests when there is a new file and it shouldn't get deleted.
*/
public void test_newFile() {
File file = AndroidMock.createMock(File.class, DIR_NAME + FILE_NAME);
expect(file.lastModified()).andStubReturn(System.currentTimeMillis());
File dir = AndroidMock.createMock(File.class, DIR_NAME);
expect(dir.exists()).andStubReturn(true);
expect(dir.listFiles()).andStubReturn(new File[] { file });
AndroidMock.replay(dir, file);
assertEquals(0, service.cleanTempDirectory(dir));
AndroidMock.verify(dir, file);
}
/**
* Tests when there is an old file and it should get deleted.
*/
public void test_oldFile() {
File file = AndroidMock.createMock(File.class, DIR_NAME + FILE_NAME);
// qSet to one hour and 1 millisecond later than the current time
expect(file.lastModified()).andStubReturn(System.currentTimeMillis() - 3600001);
expect(file.delete()).andStubReturn(true);
File dir = AndroidMock.createMock(File.class, DIR_NAME);
expect(dir.exists()).andStubReturn(true);
expect(dir.listFiles()).andStubReturn(new File[] { file });
AndroidMock.replay(dir, file);
assertEquals(1, service.cleanTempDirectory(dir));
AndroidMock.verify(dir, file);
}
}
@@ -0,0 +1,64 @@
// Copyright 2012 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.services;
import android.app.Notification;
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(Notification notification) {
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);
}
}
}
@@ -0,0 +1,766 @@
/*
* 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 static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME;
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.WaypointCreationRequest;
import com.google.android.apps.mytracks.stats.TripStatistics;
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.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.
*
* @author Bartlomiej Niechwiej
*
* 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).
*/
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);
// 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.
sharedPreferences.edit().clear().apply();
// 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(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(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(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(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(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());
try {
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
fail("Expecting IllegalStateException");
} catch (IllegalStateException e) {
// Expected.
}
}
@MediumTest
public void testInsertStatisticsMarker_validLocation() throws Exception {
createDummyTrack(123L, -1L, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
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(Waypoint.TYPE_STATISTICS, wpt.getType());
assertEquals(123L, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNotNull(wpt.getStatistics());
// 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());
try {
service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
fail("Expecting IllegalStateException");
} catch (IllegalStateException e) {
// Expected.
}
}
@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(Waypoint.TYPE_WAYPOINT, wpt.getType());
assertEquals(123L, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNull(wpt.getStatistics());
}
@MediumTest
public void testWithProperties_announcementFrequencyDefault() throws Exception {
PreferencesUtils.setInt(context, R.string.announcement_frequency_key,
PreferencesUtils.ANNOUNCEMENT_FREQUENCY_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_announcementFrequencyByDistance() throws Exception {
PreferencesUtils.setInt(context, R.string.announcement_frequency_key, -1);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_announcementFrequencyByTime() throws Exception {
PreferencesUtils.setInt(context, R.string.announcement_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.min_recording_distance_key,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_minRecordingDistance() throws Exception {
PreferencesUtils.setInt(context, R.string.min_recording_distance_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.setBoolean(
context, R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_metricUnitsDisabled() throws Exception {
PreferencesUtils.setBoolean(context, R.string.metric_units_key, false);
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.min_required_accuracy_key,
PreferencesUtils.MIN_REQUIRED_ACCURACY_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_minRequiredAccuracy() throws Exception {
PreferencesUtils.setInt(context, R.string.min_required_accuracy_key, 500);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_sensorTypeDefault() throws Exception {
PreferencesUtils.setString(
context, R.string.sensor_type_key, context.getString(R.string.sensor_type_value_none));
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.setStatistics(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);
}
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.recordLocation(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.getStatistics();
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.recordLocation(location);
Thread.sleep(100);
}
}
@@ -0,0 +1,70 @@
package com.google.android.apps.mytracks.services.sensors;
import java.util.Arrays;
import com.google.android.apps.mytracks.content.Sensor;
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 = Arrays.copyOf(originalBuf, 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));
}
}
@@ -0,0 +1,46 @@
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.Constants;
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.
sharedPreferences.edit().clear().apply();
}
@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();
}
}
@@ -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 Ršttsches
*/
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());
}
}
}
}
@@ -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));
}
}
@@ -0,0 +1,32 @@
/*
* 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 StatusAnnouncerFactory}.
* These tests require Donut+ to run.
*
* @author Rodrigo Damazio
*/
public class StatusAnnouncerFactoryTest extends AndroidTestCase {
public void testCreate() {
PeriodicTaskFactory factory = new StatusAnnouncerFactory();
PeriodicTask task = factory.create(getContext());
assertTrue(task instanceof StatusAnnouncerTask);
}
}
@@ -0,0 +1,552 @@
/*
* 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;
/**
* Tests for {@link StatusAnnouncerTask}.
* 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 StatusAnnouncerTaskTest 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 StatusAnnouncerTask task;
private StatusAnnouncerTask 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({
StatusAnnouncerTask.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(StatusAnnouncerTask.class, getContext());
task = new StatusAnnouncerTask(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);
expect(tts.isLanguageAvailable(DEFAULT_LOCALE))
.andStubReturn(TextToSpeech.LANG_AVAILABLE);
expect(tts.setLanguage(DEFAULT_LOCALE))
.andReturn(TextToSpeech.LANG_AVAILABLE);
expect(tts.setSpeechRate(StatusAnnouncerTask.TTS_SPEECH_RATE))
.andReturn(TextToSpeech.SUCCESS);
AndroidMock.replay(tts);
ttsInitListener.onInit(TextToSpeech.SUCCESS);
AndroidMock.verify(mockTask, tts);
}
public void testStart_languageNotSupported() {
doStart();
OnInitListener ttsInitListener = initListenerCapture.getValue();
assertNotNull(ttsInitListener);
expect(tts.isLanguageAvailable(DEFAULT_LOCALE))
.andStubReturn(TextToSpeech.LANG_NOT_SUPPORTED);
expect(tts.setLanguage(Locale.ENGLISH))
.andReturn(TextToSpeech.LANG_AVAILABLE);
expect(tts.setSpeechRate(StatusAnnouncerTask.TTS_SPEECH_RATE))
.andReturn(TextToSpeech.SUCCESS);
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 actual announcement call
expect(tts.speak(
eq(ANNOUNCEMENT), eq(TextToSpeech.QUEUE_FLUSH),
AndroidMock.<HashMap<String, String>>isNull()))
.andReturn(TextToSpeech.SUCCESS);
// Run the announcement
AndroidMock.replay(tts);
task.runWithStatistics(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.runWithStatistics(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.runWithStatistics(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.runWithStatistics(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.runWithStatistics(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.runWithStatistics(null);
AndroidMock.verify(mockTask, tts);
}
/**
* Tests {@link StatusAnnouncerTask#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 StatusAnnouncerTask#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 StatusAnnouncerTask#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", task.getAnnounceTime(time));
}
/**
* Tests {@link StatusAnnouncerTask#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", task.getAnnounceTime(time));
}
/**
* Tests {@link StatusAnnouncerTask#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 StatusAnnouncerTask#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();
}
}
@@ -0,0 +1,117 @@
/*
* Copyright 2009 Google Inc. All Rights Reserved.
*/
package com.google.android.apps.mytracks.stats;
import junit.framework.TestCase;
/**
* Test for the DoubleBuffer class.
*
* @author Sandor Dornbush
*/
public class DoubleBufferTest extends TestCase {
/**
* Tests that the constructor leaves the buffer in a valid state.
*/
public void testConstructor() {
DoubleBuffer buffer = new DoubleBuffer(10);
assertFalse(buffer.isFull());
assertEquals(0.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(0.0, averageAndVariance[0]);
assertEquals(0.0, averageAndVariance[1]);
}
/**
* Simple test with 10 of the same values.
*/
public void testBasic() {
DoubleBuffer buffer = new DoubleBuffer(10);
for (int i = 0; i < 9; i++) {
buffer.setNext(1.0);
assertFalse(buffer.isFull());
assertEquals(1.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(1.0, averageAndVariance[0]);
assertEquals(0.0, averageAndVariance[1]);
}
buffer.setNext(1);
assertTrue(buffer.isFull());
assertEquals(1.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(1.0, averageAndVariance[0]);
assertEquals(0.0, averageAndVariance[1]);
}
/**
* Tests with 5 entries of -10 and 5 entries of 10.
*/
public void testSplit() {
DoubleBuffer buffer = new DoubleBuffer(10);
for (int i = 0; i < 5; i++) {
buffer.setNext(-10);
assertFalse(buffer.isFull());
assertEquals(-10.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(-10.0, averageAndVariance[0]);
assertEquals(0.0, averageAndVariance[1]);
}
for (int i = 1; i < 5; i++) {
buffer.setNext(10);
assertFalse(buffer.isFull());
double expectedAverage = ((i * 10.0) - 50.0) / (i + 5);
assertEquals(buffer.toString(),
expectedAverage, buffer.getAverage(), 0.01);
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(expectedAverage, averageAndVariance[0]);
}
buffer.setNext(10);
assertTrue(buffer.isFull());
assertEquals(0.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(0.0, averageAndVariance[0]);
assertEquals(100.0, averageAndVariance[1]);
}
/**
* Tests that reset leaves the buffer in a valid state.
*/
public void testReset() {
DoubleBuffer buffer = new DoubleBuffer(10);
for (int i = 0; i < 100; i++) {
buffer.setNext(i);
}
assertTrue(buffer.isFull());
buffer.reset();
assertFalse(buffer.isFull());
assertEquals(0.0, buffer.getAverage());
double[] averageAndVariance = buffer.getAverageAndVariance();
assertEquals(0.0, averageAndVariance[0]);
assertEquals(0.0, averageAndVariance[1]);
}
/**
* Tests that if a lot of items are inserted the smoothing and looping works.
*/
public void testLoop() {
DoubleBuffer buffer = new DoubleBuffer(10);
for (int i = 0; i < 1000; i++) {
buffer.setNext(i);
assertEquals(i >= 9, buffer.isFull());
if (i > 10) {
assertEquals(i - 4.5, buffer.getAverage());
}
}
}
}
@@ -0,0 +1,63 @@
/**
* Copyright 2009 Google Inc. All Rights Reserved.
*/
package com.google.android.apps.mytracks.stats;
import junit.framework.TestCase;
import java.util.Random;
/**
* This class test the ExtremityMonitor class.
*
* @author Sandor Dornbush
*/
public class ExtremityMonitorTest extends TestCase {
public ExtremityMonitorTest(String name) {
super(name);
}
public void testInitialize() {
ExtremityMonitor monitor = new ExtremityMonitor();
assertEquals(Double.POSITIVE_INFINITY, monitor.getMin());
assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax());
}
public void testSimple() {
ExtremityMonitor monitor = new ExtremityMonitor();
assertTrue(monitor.update(0));
assertTrue(monitor.update(1));
assertEquals(0.0, monitor.getMin());
assertEquals(1.0, monitor.getMax());
assertFalse(monitor.update(1));
assertFalse(monitor.update(0.5));
}
/**
* Throws a bunch of random numbers between [0,1] at the monitor.
*/
public void testRandom() {
ExtremityMonitor monitor = new ExtremityMonitor();
Random random = new Random(42);
for (int i = 0; i < 1000; i++) {
monitor.update(random.nextDouble());
}
assertTrue(monitor.getMin() < 0.1);
assertTrue(monitor.getMax() < 1.0);
assertTrue(monitor.getMin() >= 0.0);
assertTrue(monitor.getMax() > 0.9);
}
public void testReset() {
ExtremityMonitor monitor = new ExtremityMonitor();
assertTrue(monitor.update(0));
assertTrue(monitor.update(1));
monitor.reset();
assertEquals(Double.POSITIVE_INFINITY, monitor.getMin());
assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax());
assertTrue(monitor.update(0));
assertTrue(monitor.update(1));
assertEquals(0.0, monitor.getMin());
assertEquals(1.0, monitor.getMax());
}
}
@@ -0,0 +1,184 @@
// Copyright 2009 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.stats;
import com.google.android.apps.mytracks.Constants;
import android.location.Location;
import junit.framework.TestCase;
/**
* Test the the function of the TripStatisticsBuilder class.
*
* @author Sandor Dornbush
*/
public class TripStatisticsBuilderTest extends TestCase {
private TripStatisticsBuilder builder = null;
@Override
protected void setUp() throws Exception {
super.setUp();
builder = new TripStatisticsBuilder(System.currentTimeMillis());
}
public void testAddLocationSimple() throws Exception {
builder = new TripStatisticsBuilder(1000);
TripStatistics stats = builder.getStatistics();
assertEquals(0.0, builder.getSmoothedElevation());
assertEquals(Double.POSITIVE_INFINITY, stats.getMinElevation());
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxElevation());
assertEquals(0.0, stats.getMaxSpeed());
assertEquals(Double.POSITIVE_INFINITY, stats.getMinGrade());
assertEquals(Double.NEGATIVE_INFINITY, stats.getMaxGrade());
assertEquals(0.0, stats.getTotalElevationGain());
assertEquals(0, stats.getMovingTime());
assertEquals(0.0, stats.getTotalDistance());
for (int i = 0; i < 100; i++) {
Location l = new Location("test");
l.setAccuracy(1.0f);
l.setLongitude(45.0);
// Going up by 5 meters each time.
l.setAltitude(i);
// Moving by .1% of a degree latitude.
l.setLatitude(i * .001);
l.setSpeed(11.1f);
// Each time slice is 10 seconds.
long time = 1000 + 10000 * i;
l.setTime(time);
boolean moving = builder.addLocation(l, time);
assertEquals((i != 0), moving);
stats = builder.getStatistics();
assertEquals(10000 * i, stats.getTotalTime());
assertEquals(10000 * i, stats.getMovingTime());
assertEquals(i, builder.getSmoothedElevation(),
Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(0.0, stats.getMinElevation());
assertEquals(i, stats.getMaxElevation(),
Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(i, stats.getTotalElevationGain(),
Constants.ELEVATION_SMOOTHING_FACTOR);
if (i > Constants.SPEED_SMOOTHING_FACTOR) {
assertEquals(11.1f, stats.getMaxSpeed(), 0.1);
}
if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(0.009, stats.getMinGrade(), 0.0001);
assertEquals(0.009, stats.getMaxGrade(), 0.0001);
}
// 1 degree = 111 km
// 1 timeslice = 0.001 degree = 111 m
assertEquals(111.0 * i, stats.getTotalDistance(), 100);
}
}
/**
* Test that elevation works if the user is stable.
*/
public void testElevationSimple() throws Exception {
for (double elevation = 0; elevation < 1000; elevation += 10) {
builder = new TripStatisticsBuilder(System.currentTimeMillis());
for (int j = 0; j < 100; j++) {
assertEquals(0.0, builder.updateElevation(elevation));
assertEquals(elevation, builder.getSmoothedElevation());
TripStatistics data = builder.getStatistics();
assertEquals(elevation, data.getMinElevation());
assertEquals(elevation, data.getMaxElevation());
assertEquals(0.0, data.getTotalElevationGain());
}
}
}
public void testElevationGain() throws Exception {
for (double i = 0; i < 1000; i++) {
double expectedGain;
if (i < (Constants.ELEVATION_SMOOTHING_FACTOR - 1)) {
expectedGain = 0;
} else if (i < Constants.ELEVATION_SMOOTHING_FACTOR) {
expectedGain = 0.5;
} else {
expectedGain = 1.0;
}
assertEquals(expectedGain,
builder.updateElevation(i));
assertEquals(i, builder.getSmoothedElevation(), 20);
TripStatistics data = builder.getStatistics();
assertEquals(0.0, data.getMinElevation(), 0.0);
assertEquals(i, data.getMaxElevation(),
Constants.ELEVATION_SMOOTHING_FACTOR);
assertEquals(i, data.getTotalElevationGain(),
Constants.ELEVATION_SMOOTHING_FACTOR);
}
}
public void testGradeSimple() throws Exception {
for (double i = 0; i < 1000; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
builder.updateElevation(i);
builder.updateGrade(100, 100);
if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(1.0, builder.getStatistics().getMinGrade());
}
}
for (double i = 0; i < 1000; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
builder.updateElevation(i);
builder.updateGrade(100, -100);
if ((i > Constants.GRADE_SMOOTHING_FACTOR)
&& (i > Constants.ELEVATION_SMOOTHING_FACTOR)) {
assertEquals(1.0, builder.getStatistics().getMaxGrade());
assertEquals(-1.0, builder.getStatistics().getMinGrade());
}
}
}
public void testGradeIgnoreShort() throws Exception {
for (double i = 0; i < 100; i++) {
// The value of the elevation does not matter. This is just to fill the
// buffer.
builder.updateElevation(i);
builder.updateGrade(1, 100);
assertEquals(Double.NEGATIVE_INFINITY, builder.getStatistics().getMaxGrade());
assertEquals(Double.POSITIVE_INFINITY, builder.getStatistics().getMinGrade());
}
}
public void testUpdateSpeedIncludeZero() {
for (int i = 0; i < 1000; i++) {
builder.updateSpeed(i + 1000, 0.0, i, 4.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime());
}
}
public void testUpdateSpeedIngoreErrorCode() {
builder.updateSpeed(12345000, 128.0, 12344000, 0.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals(1000, builder.getStatistics().getMovingTime());
}
public void testUpdateSpeedIngoreLargeAcceleration() {
builder.updateSpeed(12345000, 100.0, 12344000, 1.0);
assertEquals(0.0, builder.getStatistics().getMaxSpeed());
assertEquals(1000, builder.getStatistics().getMovingTime());
}
public void testUpdateSpeed() {
for (int i = 0; i < 1000; i++) {
builder.updateSpeed(i + 1000, 4.0, i, 4.0);
assertEquals((i + 1) * 1000, builder.getStatistics().getMovingTime());
if (i > Constants.SPEED_SMOOTHING_FACTOR) {
assertEquals(4.0, builder.getStatistics().getMaxSpeed());
}
}
}
}
@@ -0,0 +1,105 @@
/*
* 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);
// 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(60.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());
}
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());
}
}
@@ -0,0 +1,38 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.testing;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import android.content.Context;
/**
* A fake factory for {@link MyTracksProviderUtils} which always returns a
* predefined instance.
*
* @author Rodrigo Damazio
*/
public class TestingProviderUtilsFactory extends Factory {
private MyTracksProviderUtils instance;
public TestingProviderUtilsFactory(MyTracksProviderUtils instance) {
this.instance = instance;
}
@Override
protected MyTracksProviderUtils newForContext(Context context) {
return instance;
}
public static Factory installWithInstance(MyTracksProviderUtils instance) {
Factory oldFactory = Factory.getInstance();
Factory factory = new TestingProviderUtilsFactory(instance);
MyTracksProviderUtils.Factory.overrideInstance(factory);
return oldFactory;
}
public static void restoreOldFactory(Factory factory) {
MyTracksProviderUtils.Factory.overrideInstance(factory);
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2009 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.util;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.stats.TripStatistics;
import java.util.Vector;
import junit.framework.TestCase;
/**
* Tests for the Chart URL generator.
*
* @author Sandor Dornbush
*/
public class ChartURLGeneratorTest extends TestCase {
public void testgetChartUrl() {
Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>();
Track t = new Track();
TripStatistics stats = t.getStatistics();
stats.setMinElevation(0);
stats.setMaxElevation(2000);
stats.setTotalDistance(100);
distances.add(0.0);
elevations.add(10.0);
distances.add(10.0);
elevations.add(300.0);
distances.add(20.0);
elevations.add(800.0);
distances.add(50.0);
elevations.add(1900.0);
distances.add(75.0);
elevations.add(1200.0);
distances.add(90.0);
elevations.add(700.0);
distances.add(100.0);
elevations.add(70.0);
String chart = ChartURLGenerator.getChartUrl(distances,
elevations,
t,
"Title",
true);
assertEquals(
"http://chart.apis.google.com/chart?&chs=600x350&cht=lxy&"
+ "chtt=Title&chxt=x,y&chxr=0,0,0,0|1,0.0,2100.0,300&chco=009A00&"
+ "chm=B,00AA00,0,0,0&chg=100000,14.285714285714286,1,0&"
+ "chd=e:AAGZMzf.v.5l..,ATJJYY55kkVVCI",
chart);
}
}
@@ -0,0 +1,47 @@
/*
* 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.util;
import junit.framework.TestCase;
/**
* A unit test for {@link ChartsExtendedEncoder}.
*
* @author Bartlomiej Niechwiej
*/
public class ChartsExtendedEncoderTest extends TestCase {
public void testGetEncodedValue_validArguments() {
// Valid arguments.
assertEquals("AK", ChartsExtendedEncoder.getEncodedValue(10));
assertEquals("JO", ChartsExtendedEncoder.getEncodedValue(590));
assertEquals("AA", ChartsExtendedEncoder.getEncodedValue(0));
// 64^2 = 4096.
assertEquals("..", ChartsExtendedEncoder.getEncodedValue(4095));
}
public void testGetEncodedValue_invalidArguments() {
// Invalid arguments.
assertEquals("__", ChartsExtendedEncoder.getEncodedValue(4096));
assertEquals("__", ChartsExtendedEncoder.getEncodedValue(1234564096));
assertEquals("__", ChartsExtendedEncoder.getEncodedValue(-10));
assertEquals("__", ChartsExtendedEncoder.getEncodedValue(-12324435));
}
public void testGetSeparator() {
assertEquals(",", ChartsExtendedEncoder.getSeparator());
}
}
@@ -0,0 +1,123 @@
/*
* 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.util;
import com.google.android.apps.mytracks.Constants;
import android.os.Environment;
import java.io.File;
import junit.framework.TestCase;
/**
* Tests for {@link FileUtils}.
*
* @author Rodrigo Damazio
*/
public class FileUtilsTest extends TestCase {
/**
* Tests {@link FileUtils#buildExternalDirectoryPath(String...)}.
*/
public void testBuildExternalDirectoryPath() {
String expectedName = Environment.getExternalStorageDirectory() + File.separator
+ Constants.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator
+ "c";
String dirName = FileUtils.buildExternalDirectoryPath("a", "b", "c");
assertEquals(expectedName, dirName);
}
/**
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
* file is new.
*/
public void testBuildUniqueFileName_new() {
String filename = FileUtils.buildUniqueFileName(new File("/dir"), "Filename", "ext");
assertEquals("Filename.ext", filename);
}
/**
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the
* file exists already.
*/
public void testBuildUniqueFileName_exist() {
// Expect "/default.prop" to exist on the phone/emulator
String filename = FileUtils.buildUniqueFileName(new File("/"), "default", "prop");
assertEquals("default(1).prop", filename);
}
/**
* Tests {@link FileUtils#sanitizeFileName(String)} with special characters.
* Verifies that they are sanitized.
*/
public void testSanitizeFileName() {
String name = "Swim\10ming-^across:/the/ pacific (ocean).";
String expected = "Swim_ming-^across_the_ pacific (ocean)_";
assertEquals(expected, FileUtils.sanitizeFileName(name));
}
/**
* Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in
* Chinese and Russian). Verifies that they are allowed.
*/
public void testSanitizeFileName_i18n() {
String name = "您好-привет";
String expected = "您好-привет";
assertEquals(expected, FileUtils.sanitizeFileName(name));
}
/**
* Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32
* characters. Verifies that they are allowed.
*/
public void testSanitizeFileName_special_characters() {
String name = "$%'-_@~`!(){}^#&+,;=[] ";
String expected = "$%'-_@~`!(){}^#&+,;=[] ";
assertEquals(expected, FileUtils.sanitizeFileName(name));
}
/**
* Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped
* characters in a row. Verifies that they are collapsed into one underscore.
*/
public void testSanitizeFileName_collapse() {
String name = "hello//there";
String expected = "hello_there";
assertEquals(expected, FileUtils.sanitizeFileName(name));
}
/**
* Tests {@link FileUtils#truncateFileName(File, String, String)}. Verifies
* the a long file name is truncated.
*/
public void testTruncateFileName() {
File directory = new File("/dir1/dir2/");
String suffix = ".gpx";
char[] name = new char[FileUtils.MAX_FAT32_PATH_LENGTH];
for (int i = 0; i < name.length; i++) {
name[i] = 'a';
}
String nameString = new String(name);
String truncated = FileUtils.truncateFileName(directory, nameString, suffix);
for (int i = 0; i < truncated.length(); i++) {
assertEquals('a', truncated.charAt(i));
}
assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH,
new File(directory, truncated + suffix).getPath().length());
}
}
@@ -0,0 +1,205 @@
/*
* 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.util;
import android.test.AndroidTestCase;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* Tests for {@link StringUtils}.
*
* @author Rodrigo Damazio
*/
public class StringUtilsTest extends AndroidTestCase {
/**
* Tests {@link StringUtils#formatDateTimeIso8601(long)}.
*/
public void testFormatDateTimeIso8601() {
assertEquals("1970-01-01T00:00:12.345Z", StringUtils.formatDateTimeIso8601(12345));
}
/**
* Tests {@link StringUtils#formatElapsedTime(long)}.
*/
public void testformatElapsedTime() {
// 1 second
assertEquals("00:01", StringUtils.formatElapsedTime(1000));
// 10 seconds
assertEquals("00:10", StringUtils.formatElapsedTime(10000));
// 1 minute
assertEquals("01:00", StringUtils.formatElapsedTime(60000));
// 10 minutes
assertEquals("10:00", StringUtils.formatElapsedTime(600000));
// 1 hour
assertEquals("1:00:00", StringUtils.formatElapsedTime(3600000));
// 10 hours
assertEquals("10:00:00", StringUtils.formatElapsedTime(36000000));
// 100 hours
assertEquals("100:00:00", StringUtils.formatElapsedTime(360000000));
}
/**
* Tests {@link StringUtils#formatElapsedTimeWithHour(long)}.
*/
public void testformatElapsedTimeWithHour() {
// 1 second
assertEquals("0:00:01", StringUtils.formatElapsedTimeWithHour(1000));
// 10 seconds
assertEquals("0:00:10", StringUtils.formatElapsedTimeWithHour(10000));
// 1 minute
assertEquals("0:01:00", StringUtils.formatElapsedTimeWithHour(60000));
// 10 minutes
assertEquals("0:10:00", StringUtils.formatElapsedTimeWithHour(600000));
// 1 hour
assertEquals("1:00:00", StringUtils.formatElapsedTimeWithHour(3600000));
// 10 hours
assertEquals("10:00:00", StringUtils.formatElapsedTimeWithHour(36000000));
// 100 hours
assertEquals("100:00:00", StringUtils.formatElapsedTimeWithHour(360000000));
}
/**
* Tests {@link StringUtils#formatDistance(android.content.Context, double,
* boolean)}.
*/
public void testFormatDistance() {
// A large number in metric
assertEquals("5.00 km", StringUtils.formatDistance(getContext(), 5000, true));
// A large number in imperial
assertEquals("3.11 mi", StringUtils.formatDistance(getContext(), 5000, false));
// A small number in metric
assertEquals("100.00 m", StringUtils.formatDistance(getContext(), 100, true));
// A small number in imperial
assertEquals("328.08 ft", StringUtils.formatDistance(getContext(), 100, false));
}
/**
* Tests {@link StringUtils#formatSpeed(android.content.Context, double,
* boolean, boolean)}.
*/
public void testFormatSpeed() {
// Speed in metric
assertEquals("36.00 km/h", StringUtils.formatSpeed(getContext(), 10, true, true));
// Speed in imperial
assertEquals("22.37 mi/h", StringUtils.formatSpeed(getContext(), 10, false, true));
// Pace in metric
assertEquals("1.67 min/km", StringUtils.formatSpeed(getContext(), 10, true, false));
// Pace in imperial
assertEquals("2.68 min/mi", StringUtils.formatSpeed(getContext(), 10, false, false));
// zero pace
assertEquals("0.00 min/km", StringUtils.formatSpeed(getContext(), 0, true, false));
assertEquals("0.00 min/mi", StringUtils.formatSpeed(getContext(), 0, false, false));
// speed is NaN
assertEquals("-", StringUtils.formatSpeed(getContext(), Double.NaN, true, true));
// speed is infinite
assertEquals("-", StringUtils.formatSpeed(getContext(), Double.NEGATIVE_INFINITY, true, true));
}
/**
* Tests {@link StringUtils#formatCData(String)}.
*/
public void testFormatCData() {
assertEquals("<![CDATA[hello]]>", StringUtils.formatCData("hello"));
assertEquals("<![CDATA[hello]]]]><![CDATA[>there]]>", StringUtils.formatCData("hello]]>there"));
}
/**
* Tests {@link StringUtils#getTime(String)}.
*/
public void testGetTime() {
assertGetTime("2010-05-04T03:02:01", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
}
/**
* Tests {@link StringUtils#getTime(String)} with fractional seconds.
*/
public void testGetTime_fractional() {
assertGetTime("2010-05-04T03:02:01.3", 2010, 5, 4, 3, 2, 1, 300);
assertGetTime("2010-05-04T03:02:01.35", 2010, 5, 4, 3, 2, 1, 350);
assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352);
assertGetTime("2010-05-04T03:02:01.3525Z", 2010, 5, 4, 3, 2, 1, 352);
}
/**
* Tests {@link StringUtils#getTime(String)} with time zone.
*/
public void testGetTime_timezone() {
assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01+01:00", 2010, 5, 4, 2, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01+10:30", 2010, 5, 3, 16, 32, 1, 0);
assertGetTime("2010-05-04T03:02:01-09:30", 2010, 5, 4, 12, 32, 1, 0);
assertGetTime("2010-05-04T03:02:01-05:00", 2010, 5, 4, 8, 2, 1, 0);
}
/**
* Tests {@link StringUtils#getTime(String)} with fractional seconds and time
* zone.
*/
public void testGetTime_fractionalAndTimezone() {
assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352);
assertGetTime("2010-05-04T03:02:01.47+00:00", 2010, 5, 4, 3, 2, 1, 470);
assertGetTime("2010-05-04T03:02:01.5791+03:00", 2010, 5, 4, 0, 2, 1, 579);
assertGetTime("2010-05-04T03:02:01.8-05:30", 2010, 5, 4, 8, 32, 1, 800);
}
/**
* Asserts the {@link StringUtils#getTime(String)} returns the expected
* values.
*
* @param xmlDateTime the xml date time string
* @param year the expected year
* @param month the expected month
* @param day the expected day
* @param hour the expected hour
* @param minute the expected minute
* @param second the expected second
* @param millisecond the expected milliseconds
*/
private void assertGetTime(String xmlDateTime, int year, int month, int day, int hour, int minute,
int second, int millisecond) {
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.set(year, month - 1, day, hour, minute, second);
calendar.set(GregorianCalendar.MILLISECOND, millisecond);
assertEquals(calendar.getTimeInMillis(), StringUtils.getTime(xmlDateTime));
}
/**
* Tests {@link StringUtils#getTimeParts(long)} with a positive number.
*/
public void testGetTimeParts_postive() {
int parts[] = StringUtils.getTimeParts(61000);
assertEquals(1, parts[0]);
assertEquals(1, parts[1]);
assertEquals(0, parts[2]);
}
/**
* Tests {@link StringUtils#getTimeParts(long)} with a negative number.
*/
public void testGetTimeParts_negative() {
int parts[] = StringUtils.getTimeParts(-61000);
assertEquals(-1, parts[0]);
assertEquals(-1, parts[1]);
assertEquals(0, parts[2]);
}
}
@@ -0,0 +1,69 @@
/*
* 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.util;
import com.google.android.maps.mytracks.R;
import android.test.AndroidTestCase;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Tests {@link TrackNameUtils}.
*
* @author Matthew Simmons
*/
public class TrackNameUtilsTest extends AndroidTestCase {
private static final long TRACK_ID = 1L;
private static final long START_TIME = 1288213406000L;
/**
* Tests when the track_name_key is
* settings_recording_track_name_date_local_value.
*/
public void testTrackName_date_local() {
PreferencesUtils.setString(getContext(), R.string.track_name_key,
getContext().getString(R.string.settings_recording_track_name_date_local_value));
assertEquals(StringUtils.formatDateTime(getContext(), START_TIME),
TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null));
}
/**
* Tests when the track_name_key is
* settings_recording_track_name_date_iso_8601_value.
*/
public void testTrackName_date_iso_8601() {
PreferencesUtils.setString(getContext(), R.string.track_name_key,
getContext().getString(R.string.settings_recording_track_name_date_iso_8601_value));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(TrackNameUtils.ISO_8601_FORMAT);
assertEquals(simpleDateFormat.format(new Date(START_TIME)),
TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null));
}
/**
* Tests when the track_name_key is
* settings_recording_track_name_number_value.
*/
public void testTrackName_number() {
PreferencesUtils.setString(getContext(), R.string.track_name_key,
getContext().getString(R.string.settings_recording_track_name_number_value));
assertEquals(
"Track " + TRACK_ID, TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null));
}
}