Add track category and marker category in KmlTrackWriter.

This commit is contained in:
Jimmy Shih
2012-12-21 13:34:48 -08:00
commit 068dadf10f
821 changed files with 69853 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=".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="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
+6
View File
@@ -0,0 +1,6 @@
<factorypath>
<factorypathentry kind="WKSPJAR" id="/MyTracksTest/libs/AndroidMockGenerator.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="ANDROID_SDK/platforms/android-17/android.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,418 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
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.explicitlyClosedAutoCloseable=ignore
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.includeNullInfoFromAsserts=disabled
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.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
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.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=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.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=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.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=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.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field.count_dependent=1585|-1|1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable.count_dependent=1585|-1|1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method.count_dependent=1585|-1|1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package.count_dependent=1585|-1|1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=1040
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter.count_dependent=1040|-1|1040
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=1585
org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type.count_dependent=1585|-1|1585
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression.count_dependent=16|-1|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_binary_expression.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments=16
org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments.count_dependent=16|-1|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_enum_constants.count_dependent=0|-1|0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_field_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_for_statement=16
org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments=16
org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_local_variable_declaration=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_multiple_fields.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_new_anonymous_class=0
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration.count_dependent=16|-1|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_selector_in_method_invocation.count_dependent=16|-1|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_enum_declaration.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration.count_dependent=16|-1|16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration.count_dependent=16|-1|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.comment_new_line_at_start_of_html_paragraph=true
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.force_if_else_statement_brace=false
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
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_comment_prefix=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=false
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.sort_local_variable_annotations=false
org.eclipse.jdt.core.formatter.sort_member_annotations=false
org.eclipse.jdt.core.formatter.sort_package_annotations=false
org.eclipse.jdt.core.formatter.sort_parameter_annotations=false
org.eclipse.jdt.core.formatter.sort_type_annotations=false
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_comment_inline_tags=false
org.eclipse.jdt.core.formatter.wrap_non_simple_local_variable_annotation=true
org.eclipse.jdt.core.formatter.wrap_non_simple_member_annotation=true
org.eclipse.jdt.core.formatter.wrap_non_simple_package_annotation=true
org.eclipse.jdt.core.formatter.wrap_non_simple_parameter_annotation=false
org.eclipse.jdt.core.formatter.wrap_non_simple_type_annotation=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.formatter.wrap_prefer_two_fragments=false
@@ -0,0 +1,61 @@
#Tue Jul 17 10:22:39 PDT 2012
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_My Tracks
formatter_settings_version=13
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
+39
View File
@@ -0,0 +1,39 @@
<?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" />
<instrumentation
android:name="com.google.android.apps.mytracks.endtoendtest.EndToEndTestRunner"
android:targetPackage="com.google.android.maps.mytracks" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
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=android-17
+1
View File
@@ -0,0 +1 @@
This hidden file is here to ensure there is a res folder.
@@ -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,91 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track;
import android.location.Location;
/**
* Commons utilities for creating stubs of track, location. The class will be
* enriched if needs more similar stubs for test.
*
* @author Youtao Liu
*/
public class TrackStubUtils {
static final String LOCATION_PROVIDER = "gps";
public static final double INITIAL_LATITUDE = 22;
public static final double INITIAL_LONGITUDE = 22;
public static final double INITIAL_ALTITUDE = 22;
static final float INITIAL_ACCURACY = 5;
static final float INITIAL_SPEED = 10;
public static final long INITIAL_TIME = 1000L;
static final float INITIAL_BEARING = 3.0f;
// Used to change the value of latitude, longitude, and altitude.
static final double DIFFERENCE = 0.01;
/**
* Gets a a {@link Track} stub with specified number of locations.
*
* @param numberOfLocations the number of locations for the track
* @return a track stub.
*/
public static Track createTrack(int numberOfLocations) {
Track track = new Track();
for (int i = 0; i < numberOfLocations; i++) {
track.addLocation(createMyTracksLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE
+ i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE));
}
return track;
}
/**
* Create a MyTracks location with default values.
*
* @return a track stub.
*/
public static MyTracksLocation createMyTracksLocation() {
return createMyTracksLocation(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE);
}
/**
* Creates a {@link MyTracksLocation} stub with specified values.
*
* @return a MyTracksLocation stub.
*/
public static MyTracksLocation createMyTracksLocation(double latitude, double longitude,
double altitude) {
// Initial Location
Location loc = new Location(LOCATION_PROVIDER);
loc.setLatitude(latitude);
loc.setLongitude(longitude);
loc.setAltitude(altitude);
loc.setAccuracy(INITIAL_ACCURACY);
loc.setSpeed(INITIAL_SPEED);
loc.setTime(INITIAL_TIME);
loc.setBearing(INITIAL_BEARING);
SensorDataSet sd = SensorDataSet.newBuilder().build();
MyTracksLocation myTracksLocation = new MyTracksLocation(loc, sd);
return myTracksLocation;
}
}
@@ -0,0 +1,214 @@
/*
* 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.setTripStatistics(stats);
track.setCategory("hiking");
String expected = "Created by"
+ " <a href='http://www.google.com/mobile/mytracks'>Google My Tracks</a> on Android.<p>"
+ "Name: -<br>"
+ "Activity type: hiking<br>"
+ "Description: -<br>"
+ "Total distance: 20.00 km (12.4 mi)<br>"
+ "Total time: 10:00<br>"
+ "Moving time: 05:00<br>"
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
+ "Average pace: 0.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(TripStatistics)}.
*/
public void testGenerateWaypointDescription() {
Waypoint waypoint = new Waypoint();
TripStatistics stats = new TripStatistics();
stats.setTotalDistance(20000);
stats.setTotalTime(600000);
stats.setMovingTime(300000);
stats.setMaxSpeed(100);
stats.setMaxElevation(550);
stats.setMinElevation(-500);
stats.setTotalElevationGain(6000);
stats.setMaxGrade(0.42);
stats.setMinGrade(0.11);
stats.setStartTime(START_TIME);
waypoint.setTripStatistics(stats);
String expected = "Total distance: 20.00 km (12.4 mi)\n"
+ "Total time: 10:00\n"
+ "Moving time: 05:00\n"
+ "Average speed: 120.00 km/h (74.6 mi/h)\n"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)\n"
+ "Max speed: 360.00 km/h (223.7 mi/h)\n"
+ "Average pace: 0.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.getTripStatistics()));
}
/**
* Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder,
* int, String)}.
*/
public void testWriteDistance() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeDistance(1100, builder, R.string.description_total_distance, "<br>");
assertEquals("Total distance: 1.10 km (0.7 mi)<br>", builder.toString());
}
/**
* Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int,
* String)}.
*/
public void testWriteTime() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeTime(1000, builder, R.string.description_total_time, "<br>");
assertEquals("Total time: 00:01<br>", builder.toString());
}
/**
* Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder,
* int, String)}.
*/
public void testWriteSpeed() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeSpeed(1.1, builder, R.string.description_average_speed, "\n");
assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString());
}
/**
* Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder,
* int, String)}.
*/
public void testWriteElevation() {
StringBuilder builder = new StringBuilder();
descriptionGenerator.writeElevation(4.2, builder, R.string.description_min_elevation, "<br>");
assertEquals("Min elevation: 4 m (14 ft)<br>", builder.toString());
}
/**
* Tests {@link DescriptionGeneratorImpl#writePace(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,196 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.MyTracksProvider.DatabaseHelper;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.test.AndroidTestCase;
/**
* A unit test for {@link MyTracksProvider}.
*
* @author Youtao Liu
*/
public class MyTracksProviderTest extends AndroidTestCase {
private SQLiteDatabase db;
private MyTracksProvider myTracksProvider;
private String DATABASE_NAME = "mytrackstest.db";
@Override
protected void setUp() throws Exception {
getContext().deleteDatabase(DATABASE_NAME);
db = (new DatabaseHelper(getContext(), DATABASE_NAME)).getWritableDatabase();
myTracksProvider = new MyTracksProvider();
super.setUp();
}
/**
* Tests the method {@link MyTracksProvider.DatabaseHelper#onCreate()}.
*/
public void testDatabaseHelper_OnCreate() {
assertTrue(checkTable(TrackPointsColumns.TABLE_NAME));
assertTrue(checkTable(TracksColumns.TABLE_NAME));
assertTrue(checkTable(WaypointsColumns.TABLE_NAME));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is less than 17.
*/
public void testDatabaseHelper_onUpgrade_Version16() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
dropTable(WaypointsColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 16, 20);
assertTrue(checkTable(TrackPointsColumns.TABLE_NAME));
assertTrue(checkTable(TracksColumns.TABLE_NAME));
assertTrue(checkTable(WaypointsColumns.TABLE_NAME));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 17.
*/
public void testDatabaseHelper_onUpgrade_Version17() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 17, 20);
assertTrue(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 18.
*/
public void testDatabaseHelper_onUpgrade_Version18() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 18, 20);
assertFalse(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
}
/**
* Tests the method
* {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, int)}
* when version is 19.
*/
public void testDatabaseHelper_onUpgrade_Version19() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
// Make two table is only contains one normal integer column.
dropTable(TrackPointsColumns.TABLE_NAME);
dropTable(TracksColumns.TABLE_NAME);
createEmptyTable(TrackPointsColumns.TABLE_NAME);
createEmptyTable(TracksColumns.TABLE_NAME);
databaseHelper.onUpgrade(db, 19, 20);
assertFalse(isColumnExisted(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR));
assertFalse(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.TABLEID));
assertTrue(isColumnExisted(TracksColumns.TABLE_NAME, TracksColumns.ICON));
}
/**
* Tests the method {@link MyTracksProvider#onCreate()}.
*/
public void testOnCreate() {
assertTrue(myTracksProvider.onCreate(getContext()));
}
/**
* Tests the method {@link MyTracksProvider#getType(Uri)}.
*/
public void testGetType() {
assertEquals(TrackPointsColumns.CONTENT_TYPE,
myTracksProvider.getType(TrackPointsColumns.CONTENT_URI));
assertEquals(TracksColumns.CONTENT_TYPE, myTracksProvider.getType(TracksColumns.CONTENT_URI));
assertEquals(WaypointsColumns.CONTENT_TYPE,
myTracksProvider.getType(WaypointsColumns.CONTENT_URI));
}
/**
* Creates an table only contains one column.
*
* @param table the name of table
*/
private void createEmptyTable(String table) {
db.execSQL("CREATE TABLE " + table + " (test INTEGER)");
}
/**
* Drops a table in database.
*
* @param table
*/
private void dropTable(String table) {
db.execSQL("Drop TABLE " + table);
}
/**
* Checks whether a table is existed.
*
* @param table the name of table
* @return true means the table has existed
*/
private boolean checkTable(String table) {
try {
db.rawQuery("select count(*) from " + table, null);
return true;
} catch (Exception e) {
return false;
}
}
/**
* Checks whether a column in a table is existed by whether can order by the
* column.
*
* @param table the name of table
* @param column the name of column
* @return true means the column has existed
*/
private boolean isColumnExisted(String table, String column) {
try {
db.execSQL("SElECT count(*) from " + table + " order by " + column);
} catch (Exception e) {
if (e.getMessage().indexOf("no such column") > -1) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,908 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.location.Location;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A unit test for {@link MyTracksProviderUtilsImpl}.
*
* @author Bartlomiej Niechwiej
* @author Youtao Liu
*/
public class MyTracksProviderUtilsImplTest extends AndroidTestCase {
private Context context;
private MyTracksProviderUtils providerUtils;
private static final String NAME_PREFIX = "test name";
private static final String MOCK_DESC = "Mock Next Waypoint Desc!";
private static final String TEST_DESC = "Test Desc!";
private static final String TEST_DESC_NEW = "Test Desc new!";
private double INITIAL_LATITUDE = 37.0;
private double INITIAL_LONGITUDE = -57.0;
private double ALTITUDE_INTERVAL = 2.5;
@Override
protected void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver = new MockContentResolver();
RenamingDelegatingContext targetContext = new RenamingDelegatingContext(
getContext(), getContext(), "test.");
context = new MockContext(mockContentResolver, targetContext);
MyTracksProvider provider = new MyTracksProvider();
provider.attachInfo(context, null);
mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider);
setContext(context);
providerUtils = MyTracksProviderUtils.Factory.get(context);
providerUtils.deleteAllTracks();
}
public void testLocationIterator_noPoints() {
testIterator(1, 0, 1, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_customFactory() {
final Location location = new Location("test_location");
final AtomicInteger counter = new AtomicInteger();
testIterator(1, 15, 4, false, new LocationFactory() {
@Override
public Location createLocation() {
counter.incrementAndGet();
return location;
}
});
// Make sure we were called exactly as many times as we had track points.
assertEquals(15, counter.get());
}
public void testLocationIterator_nullFactory() {
try {
testIterator(1, 15, 4, false, null);
fail("Expecting IllegalArgumentException");
} catch (IllegalArgumentException e) {
// Expected.
}
}
public void testLocationIterator_noBatchAscending() {
testIterator(1, 50, 100, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 50, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_noBatchDescending() {
testIterator(1, 50, 100, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 50, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_batchAscending() {
testIterator(1, 50, 11, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 25, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_batchDescending() {
testIterator(1, 50, 11, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
testIterator(2, 50, 25, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
public void testLocationIterator_largeTrack() {
testIterator(1, 20000, 2000, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
}
private List<Location> testIterator(long trackId, int numPoints, int batchSize,
boolean descending, LocationFactory locationFactory) {
long lastPointId = initializeTrack(trackId, numPoints);
((MyTracksProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize);
List<Location> locations = new ArrayList<Location>(numPoints);
LocationIterator it = providerUtils.getTrackPointLocationIterator(
trackId, -1L, descending, locationFactory);
try {
while (it.hasNext()) {
Location loc = it.next();
assertNotNull(loc);
locations.add(loc);
// Make sure the IDs are returned in the right order.
assertEquals(descending ? lastPointId - locations.size() + 1
: lastPointId - numPoints + locations.size(), it.getLocationId());
}
assertEquals(numPoints, locations.size());
} finally {
it.close();
}
return locations;
}
private long initializeTrack(long id, int numPoints) {
Track track = new Track();
track.setId(id);
track.setName("Test: " + id);
track.setNumberOfPoints(numPoints);
providerUtils.insertTrack(track);
track = providerUtils.getTrack(id);
assertNotNull(track);
Location[] locations = new Location[numPoints];
for (int i = 0; i < numPoints; ++i) {
Location loc = new Location("test");
loc.setLatitude(37.0 + (double) i / 10000.0);
loc.setLongitude(57.0 - (double) i / 10000.0);
loc.setAccuracy((float) i / 100.0f);
loc.setAltitude(i * 2.5);
locations[i] = loc;
}
providerUtils.bulkInsertTrackPoint(locations, numPoints, id);
// Load all inserted locations.
long lastPointId = -1;
int counter = 0;
LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false,
MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
try {
while (it.hasNext()) {
it.next();
lastPointId = it.getLocationId();
counter++;
}
} finally {
it.close();
}
assertTrue(numPoints == 0 || lastPointId > 0);
assertEquals(numPoints, track.getNumberOfPoints());
assertEquals(numPoints, counter);
return lastPointId;
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#createTrack(Cursor)}.
*/
@UsesMocks(Cursor.class)
public void testCreateTrack() {
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
int startColumnIndex = 1;
int columnIndex = startColumnIndex;
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns._ID))
.andReturn(columnIndex++);
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).andReturn(
columnIndex++);
columnIndex = startColumnIndex;
// Id
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
// Name
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
long trackId = System.currentTimeMillis();
columnIndex = startColumnIndex;
// Id
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
// Name
String name = NAME_PREFIX + Long.toString(trackId);
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
AndroidMock.replay(cursorMock);
Track track = providerUtils.createTrack(cursorMock);
assertEquals(trackId, track.getId());
assertEquals(name, track.getName());
AndroidMock.verify(cursorMock);
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#deleteAllTracks()}
*/
public void testDeleteAllTracks() {
// Insert track, points and waypoint at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
Waypoint waypoint = new Waypoint();
providerUtils.insertWaypoint(waypoint);
ContentResolver contentResolver = context.getContentResolver();
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
TracksColumns._ID);
assertEquals(1, tracksCursor.getCount());
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
null, TrackPointsColumns._ID);
assertEquals(10, tracksPointsCursor.getCount());
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
null, WaypointsColumns._ID);
assertEquals(1, waypointCursor.getCount());
// Delete all.
providerUtils.deleteAllTracks();
// Check whether all have been deleted.
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
TracksColumns._ID);
assertEquals(0, tracksCursor.getCount());
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
null, TrackPointsColumns._ID);
assertEquals(0, tracksPointsCursor.getCount());
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
null, WaypointsColumns._ID);
assertEquals(0, waypointCursor.getCount());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#deleteTrack(long)}.
*/
public void testDeleteTrack() {
// Insert three tracks, points of two tracks and way point of one track.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
insertTrackWithLocations(getTrack(trackId + 1, 10));
insertTrackWithLocations(getTrack(trackId + 2, 10));
Waypoint waypoint = new Waypoint();
waypoint.setTrackId(trackId);
providerUtils.insertWaypoint(waypoint);
ContentResolver contentResolver = context.getContentResolver();
Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
TracksColumns._ID);
assertEquals(3, tracksCursor.getCount());
Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
null, TrackPointsColumns._ID);
assertEquals(20, tracksPointsCursor.getCount());
Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
null, WaypointsColumns._ID);
assertEquals(1, waypointCursor.getCount());
// Delete one track.
providerUtils.deleteTrack(trackId);
// Check whether all data of a track has been deleted.
tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null,
TracksColumns._ID);
assertEquals(2, tracksCursor.getCount());
tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null,
null, TrackPointsColumns._ID);
assertEquals(20, tracksPointsCursor.getCount());
waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null,
null, WaypointsColumns._ID);
assertEquals(0, waypointCursor.getCount());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getAllTracks()}
*/
public void testGetAllTracks() {
int initialTrackNumber = providerUtils.getAllTracks().size();
long trackId = System.currentTimeMillis();
providerUtils.insertTrack(getTrack(trackId, 0));
List<Track> allTracks = providerUtils.getAllTracks();
assertEquals(initialTrackNumber + 1, allTracks.size());
assertEquals(trackId, allTracks.get(allTracks.size() - 1).getId());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrack()}
*/
public void testGetLastTrack() {
long trackId = System.currentTimeMillis();
providerUtils.insertTrack(getTrack(trackId, 0));
assertEquals(trackId, providerUtils.getLastTrack().getId());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getTrack(long)}
*/
public void testGetTrack() {
long trackId = System.currentTimeMillis();
providerUtils.insertTrack(getTrack(trackId, 0));
assertNotNull(providerUtils.getTrack(trackId));
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#updateTrack(Track)}
*/
public void testUpdateTrack() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 0);
String nameOld = "name1";
String nameNew = "name2";
track.setName(nameOld);
providerUtils.insertTrack(track);
assertEquals(nameOld, providerUtils.getTrack(trackId).getName());
track.setName(nameNew);
providerUtils.updateTrack(track);
assertEquals(nameNew, providerUtils.getTrack(trackId).getName());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#createContentValues(Waypoint)}.
*/
public void testCreateContentValues_waypoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
// Bottom
long startTime = 1000L;
// AverageSpeed
double minGrade = -20.11;
TripStatistics statistics = new TripStatistics();
statistics.setStartTime(startTime);
statistics.setStopTime(2500L);
statistics.setTotalTime(1500L);
statistics.setMovingTime(700L);
statistics.setTotalDistance(750.0);
statistics.setTotalElevationGain(50.0);
statistics.setMaxSpeed(60.0);
statistics.setMaxElevation(1250.0);
statistics.setMinElevation(1200.0);
statistics.setMaxGrade(15.0);
statistics.setMinGrade(minGrade);
statistics.setBounds(-10000, 20000, 30000, -40000);
// Insert at first.
Waypoint waypoint = new Waypoint();
waypoint.setDescription(TEST_DESC);
waypoint.setType(WaypointType.STATISTICS);
waypoint.setTripStatistics(statistics);
Location loc = new Location("test");
loc.setLatitude(22);
loc.setLongitude(22);
loc.setAccuracy((float) 1 / 100.0f);
loc.setAltitude(2.5);
waypoint.setLocation(loc);
providerUtils.insertWaypoint(waypoint);
MyTracksProviderUtilsImpl myTracksProviderUtilsImpl = new MyTracksProviderUtilsImpl(
new MockContentResolver());
long waypointId = System.currentTimeMillis();
waypoint.setId(waypointId);
ContentValues contentValues = myTracksProviderUtilsImpl.createContentValues(waypoint);
assertEquals(waypointId, contentValues.get(WaypointsColumns._ID));
assertEquals(22 * 1000000, contentValues.get(WaypointsColumns.LONGITUDE));
assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION));
assertEquals(startTime, contentValues.get(WaypointsColumns.STARTTIME));
assertEquals(minGrade, contentValues.get(WaypointsColumns.MINGRADE));
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#createWaypoint(Cursor)}.
*/
@UsesMocks(Cursor.class)
public void testCreateWaypoint() {
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
int startColumnIndex = 1;
int columnIndex = startColumnIndex;
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns._ID))
.andReturn(columnIndex++);
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.NAME)).andReturn(
columnIndex++);
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.TRACKID)).andReturn(
columnIndex++);
columnIndex = startColumnIndex;
// Id
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
// Name
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
// trackIdIndex
AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false);
long id = System.currentTimeMillis();
columnIndex = startColumnIndex;
// Id
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(id);
// Name
String name = NAME_PREFIX + Long.toString(id);
AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name);
// trackIdIndex
long trackId = 11L;
AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId);
AndroidMock.replay(cursorMock);
Waypoint waypoint = providerUtils.createWaypoint(cursorMock);
assertEquals(id, waypoint.getId());
assertEquals(name, waypoint.getName());
assertEquals(trackId, waypoint.getTrackId());
AndroidMock.verify(cursorMock);
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(long, DescriptionGenerator)}
* when there is only one waypoint in the track.
*/
public void testDeleteWaypoint_onlyOneWayPoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
// Insert at first.
Waypoint waypoint1 = new Waypoint();
waypoint1.setDescription(TEST_DESC);
waypoint1.setTrackId(trackId);
waypoint1.setType(WaypointType.STATISTICS);
providerUtils.insertWaypoint(waypoint1);
// Delete
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
@Override
public String generateWaypointDescription(TripStatistics tripStatistics) {
return MyTracksProviderUtilsImplTest.MOCK_DESC;
}
@Override
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
Vector<Double> elevations, boolean html) {
return null;
}
};
providerUtils.deleteWaypoint(1, descriptionGenerator);
assertNull(providerUtils.getWaypoint(1));
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#deleteWaypoint(long, DescriptionGenerator)}
* when there is more than one waypoint in the track.
*/
public void testDeleteWaypoint_hasNextWayPoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
TripStatistics statistics = new TripStatistics();
statistics.setStartTime(1000L);
statistics.setStopTime(2500L);
statistics.setTotalTime(1500L);
statistics.setMovingTime(700L);
statistics.setTotalDistance(750.0);
statistics.setTotalElevationGain(50.0);
statistics.setMaxSpeed(60.0);
statistics.setMaxElevation(1250.0);
statistics.setMinElevation(1200.0);
statistics.setMaxGrade(15.0);
statistics.setMinGrade(-25.0);
statistics.setBounds(-10000, 20000, 30000, -40000);
// Insert at first.
Waypoint waypoint1 = new Waypoint();
waypoint1.setDescription(Long.toString(trackId));
waypoint1.setTrackId(trackId);
waypoint1.setType(WaypointType.STATISTICS);
waypoint1.setTripStatistics(statistics);
providerUtils.insertWaypoint(waypoint1);
Waypoint waypoint2 = new Waypoint();
waypoint2.setDescription(Long.toString(trackId));
waypoint2.setTrackId(trackId);
waypoint2.setType(WaypointType.STATISTICS);
waypoint2.setTripStatistics(statistics);
providerUtils.insertWaypoint(waypoint2);
// Delete
DescriptionGenerator descriptionGenerator = new DescriptionGenerator() {
@Override
public String generateWaypointDescription(TripStatistics tripStatistics) {
return MyTracksProviderUtilsImplTest.MOCK_DESC;
}
@Override
public String generateTrackDescription(Track aTrack, Vector<Double> distances,
Vector<Double> elevations, boolean html) {
return null;
}
};
providerUtils.deleteWaypoint(1, descriptionGenerator);
assertNull(providerUtils.getWaypoint(1));
assertEquals(MyTracksProviderUtilsImplTest.MOCK_DESC, providerUtils.getWaypoint(2)
.getDescription());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstWaypointId(long)}.
*/
public void testGetFirstWaypointId() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
Waypoint waypoint1 = new Waypoint();
waypoint1.setTrackId(trackId);
Waypoint waypoint2 = new Waypoint();
waypoint2.setTrackId(trackId);
providerUtils.insertWaypoint(waypoint1);
providerUtils.insertWaypoint(waypoint2);
assertEquals(-1L, providerUtils.getFirstWaypointId(-1));
assertEquals(1L, providerUtils.getFirstWaypointId(trackId));
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getNextWaypointNumber(long, WaypointType)}.
*/
public void testGetNextWaypointNumber() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
Waypoint waypoint1 = new Waypoint();
waypoint1.setType(WaypointType.STATISTICS);
waypoint1.setTrackId(trackId);
Waypoint waypoint2 = new Waypoint();
waypoint2.setType(WaypointType.WAYPOINT);
waypoint2.setTrackId(trackId);
Waypoint waypoint3 = new Waypoint();
waypoint3.setType(WaypointType.STATISTICS);
waypoint3.setTrackId(trackId);
Waypoint waypoint4 = new Waypoint();
waypoint4.setType(WaypointType.WAYPOINT);
waypoint4.setTrackId(trackId);
providerUtils.insertWaypoint(waypoint1);
providerUtils.insertWaypoint(waypoint2);
providerUtils.insertWaypoint(waypoint3);
providerUtils.insertWaypoint(waypoint4);
assertEquals(2, providerUtils.getNextWaypointNumber(trackId, WaypointType.STATISTICS));
assertEquals(3, providerUtils.getNextWaypointNumber(trackId, WaypointType.WAYPOINT));
}
/**
* Tests the method
* {@link MyTracksProviderUtils#getLastWaypoint(long, WaypointType)}.
*/
public void testGetLastStatisticsWaypoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
Waypoint waypoint1 = new Waypoint();
waypoint1.setTrackId(trackId);
waypoint1.setType(WaypointType.STATISTICS);
waypoint1.setDescription("Desc1");
Waypoint waypoint2 = new Waypoint();
waypoint2.setTrackId(trackId);
waypoint2.setType(WaypointType.STATISTICS);
waypoint2.setDescription("Desc2");
Waypoint waypoint3 = new Waypoint();
waypoint3.setTrackId(trackId);
waypoint3.setType(WaypointType.WAYPOINT);
waypoint3.setDescription("Desc3");
providerUtils.insertWaypoint(waypoint1);
providerUtils.insertWaypoint(waypoint2);
providerUtils.insertWaypoint(waypoint3);
assertEquals("Desc2", providerUtils.getLastWaypoint(trackId, WaypointType.STATISTICS).getDescription());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#insertWaypoint(Waypoint)} and
* {@link MyTracksProviderUtilsImpl#getWaypoint(long)}.
*/
public void testInsertAndGetWaypoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
Waypoint waypoint = new Waypoint();
waypoint.setDescription(TEST_DESC);
waypoint.setTrackId(trackId);
providerUtils.insertWaypoint(waypoint);
assertEquals(TEST_DESC, providerUtils.getWaypoint(1).getDescription());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#updateWaypoint(Waypoint)}.
*/
public void testUpdateWaypoint() {
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
providerUtils.insertTrack(track);
// Insert at first.
Waypoint waypoint = new Waypoint();
waypoint.setDescription(TEST_DESC);
waypoint.setTrackId(trackId);
providerUtils.insertWaypoint(waypoint);
// Update
waypoint = providerUtils.getWaypoint(1);
waypoint.setDescription(TEST_DESC_NEW);
providerUtils.updateWaypoint(waypoint);
assertEquals(TEST_DESC_NEW, providerUtils.getWaypoint(1).getDescription());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#bulkInsertTrackPoint(Location[],
* int, long)}.
*/
public void testBulkInsertTrackPoint() {
// Insert track, point at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), -1, trackId);
assertEquals(20, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), 8, trackId);
assertEquals(28, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#createTrackPoint(Cursor)}.
*/
@UsesMocks(Cursor.class)
public void testCreateTrackPoint() {
Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class);
// Set index.
int index = 1;
// Id
AndroidMock.expect(cursorMock.getColumnIndex(TrackPointsColumns._ID)).andReturn(index++);
// Longitude
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE)).andReturn(
index++);
// Latitude
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE)).andReturn(
index++);
// Time
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.TIME))
.andReturn(index++);
// Speed
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn(
index++);
// Sensor
AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR)).andReturn(
index++);
// Set return value of isNull().
index = 2;
// Longitude
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
// Latitude
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
// Time
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
// Speed
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
// Sensor
AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false);
// Set return value of isNull().
index = 2;
// Longitude
int longitude = 11;
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(longitude * 1000000);
// Latitude.
int latitude = 22;
AndroidMock.expect(cursorMock.getInt(index++)).andReturn(latitude * 1000000);
// Time
long time = System.currentTimeMillis();
AndroidMock.expect(cursorMock.getLong(index++)).andReturn(time);
// Speed
float speed = 2.2f;
AndroidMock.expect(cursorMock.getFloat(index++)).andReturn(speed);
// Sensor
byte[] sensor = "Sensor state".getBytes();
AndroidMock.expect(cursorMock.getBlob(index++)).andReturn(sensor);
AndroidMock.replay(cursorMock);
Location location = providerUtils.createTrackPoint(cursorMock);
assertEquals((double) longitude, location.getLongitude());
assertEquals((double) latitude, location.getLatitude());
assertEquals(time, location.getTime());
assertEquals(speed, location.getSpeed());
AndroidMock.verify(cursorMock);
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#insertTrackPoint(Location, long)}.
*/
public void testInsertTrackPoint() {
// Insert track, point at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
providerUtils.insertTrackPoint(createLocation(22), trackId);
assertEquals(11, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount());
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getFirstTrackPointId(long)}.
*/
public void testGetFirstTrackPointId() {
// Insert track, point at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
assertEquals(1, providerUtils.getFirstTrackPointId(trackId));
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getLastTrackPointId(long)}.
*/
public void testGetLastTrackPointId() {
// Insert track, point at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
assertEquals(10, providerUtils.getLastTrackPointId(trackId));
}
/**
* Tests the method {@link MyTracksProviderUtilsImpl#getLastValidTrackPoint(long)}.
*/
public void testGetLastValidTrackPoint() {
// Insert track, points at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
Location lastLocation = providerUtils.getLastValidTrackPoint(trackId);
checkLocation(9, lastLocation);
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
* in descending.
*/
public void testGetTrackPointCursor_desc() {
// Insert track, points at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, true);
assertEquals(2, cursor.getCount());
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)}
* in ascending.
*/
public void testGetTrackPointCursor_asc() {
// Insert track, points at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, false);
assertEquals(5, cursor.getCount());
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
* in descending.
*/
public void testGetTrackPointLocationIterator_desc() {
// Insert track, points at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
long startTrackPointId = 2L;
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
startTrackPointId, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
for (int i = 1; i >= 0; i--) {
assertTrue(locationIterator.hasNext());
Location location = locationIterator.next();
assertEquals(2 + (i - 1), locationIterator.getLocationId());
checkLocation(i, location);
}
assertFalse(locationIterator.hasNext());
}
/**
* Tests the method
* {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)}
* in ascending.
*/
public void testGetTrackPointLocationIterator_asc() {
// Insert track, point at first.
long trackId = System.currentTimeMillis();
Track track = getTrack(trackId, 10);
insertTrackWithLocations(track);
long startTrackPointId = 2L;
LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId,
startTrackPointId, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
for (int i = 1; i < 10; i++) {
assertTrue(locationIterator.hasNext());
Location location = locationIterator.next();
assertEquals(2 + (i - 1), locationIterator.getLocationId());
checkLocation(i, location);
}
assertFalse(locationIterator.hasNext());
}
/**
* Simulates a track which is used for testing.
*
* @param id the id of the track
* @param numPoints the location number in the track
* @return the simulated track
*/
private Track getTrack(long id,int numPoints) {
Track track = new Track();
track.setId(id);
track.setName("Test: " + id);
track.setNumberOfPoints(numPoints);
for(int i = 0; i < numPoints; i++) {
track.addLocation(createLocation(i));
}
return track;
}
/**
* Creates a location.
* @param i the index to set the value of location.
* @return created location
*/
private Location createLocation(int i) {
Location loc = new Location("test");
loc.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0);
loc.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
loc.setAccuracy((float) i / 100.0f);
loc.setAltitude(i * ALTITUDE_INTERVAL);
return loc;
}
/**
* Checks the value of a location.
*
* @param i the index of this location which created in the method
* {@link MyTracksProviderUtilsImplTest#getTrack(long, int)}
* @param location the location to be checked
*/
private void checkLocation(int i, Location location) {
assertEquals(INITIAL_LATITUDE + (double) i / 10000.0, location.getLatitude());
assertEquals(INITIAL_LONGITUDE - (double) i / 10000.0, location.getLongitude());
assertEquals((float) i / 100.0f, location.getAccuracy());
assertEquals(i * ALTITUDE_INTERVAL, location.getAltitude());
}
/**
* Inserts a track with locations into the database.
*
* @param track track to be inserted
*/
private void insertTrackWithLocations(Track track) {
providerUtils.insertTrack(track);
providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), track
.getLocations().size(), track.getId());
}
}
@@ -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.getTripStatistics();
if (hoursAgo > 0) {
// Started twice hoursAgo, so the average time is hoursAgo.
stats.setStartTime(NOW - hoursAgo * 1000L * 60L * 60L * 2);
stats.setStopTime(NOW);
}
int latitude = (int) ((HERE.getLatitude() + distance) * 1E6);
int longitude = (int) ((HERE.getLongitude() + distance) * 1E6);
stats.setBounds(latitude, longitude, latitude, longitude);
Uri uri = providerUtils.insertTrack(track);
return ContentUris.parseId(uri);
}
private long insertTrack(String title, String description, String category) {
return insertTrack(title, description, category, 0, -1);
}
private long insertTrack(String title, double distance) {
return insertTrack(title, "", "", distance, -1);
}
private long insertTrack(String title, long hoursAgo) {
return insertTrack(title, "", "", 0.0, hoursAgo);
}
private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) {
Waypoint waypoint = new Waypoint();
waypoint.setName(title);
waypoint.setDescription(description);
waypoint.setCategory(category);
waypoint.setTrackId(trackId);
Location location = new Location(HERE);
location.setLatitude(location.getLatitude() + distance);
location.setLongitude(location.getLongitude() + distance);
if (hoursAgo >= 0) {
location.setTime(NOW - hoursAgo * 1000L * 60L * 60L);
}
waypoint.setLocation(location);
Uri uri = providerUtils.insertWaypoint(waypoint);
return ContentUris.parseId(uri);
}
private long insertWaypoint(String title, String description, String category) {
return insertWaypoint(title, description, category, 0.0, -1, -1);
}
private long insertWaypoint(String title, double distance) {
return insertWaypoint(title, "", "", distance, -1, -1);
}
private long insertWaypoint(String title, long hoursAgo) {
return insertWaypoint(title, "", "", 0.0, hoursAgo, -1);
}
private long insertWaypoint(String title, long hoursAgo, long trackId) {
return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId);
}
public void testSearchText() {
// Insert 7 tracks (purposefully out of result order):
// - one which won't match
// - one which will match the description
// - one which will match the category
// - one which will match the title
// - one which will match in title and category
// - one which will match in title and description
// - one which will match in all fields
insertTrack("bb", "cc", "dd");
long descriptionMatchId = insertTrack("bb", "aa", "cc");
long categoryMatchId = insertTrack("bb", "cc", "aa");
long titleMatchId = insertTrack("aa", "bb", "cc");
long titleCategoryMatchId = insertTrack("aa", "bb", "ca");
long titleDescriptionMatchId = insertTrack("aa", "ba", "cc");
long allMatchId = insertTrack("aa", "ba", "ca");
SearchQuery query = new SearchQuery("a", null, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Title > Description > Category.
assertTrackResults(results,
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
categoryMatchId);
}
public void testSearchWaypointText() {
// Insert 7 waypoints (purposefully out of result order):
// - one which won't match
// - one which will match the description
// - one which will match the category
// - one which will match the title
// - one which will match in title and category
// - one which will match in title and description
// - one which will match in all fields
insertWaypoint("bb", "cc", "dd");
long descriptionMatchId = insertWaypoint("bb", "aa", "cc");
long categoryMatchId = insertWaypoint("bb", "cc", "aa");
long titleMatchId = insertWaypoint("aa", "bb", "cc");
long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca");
long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc");
long allMatchId = insertWaypoint("aa", "ba", "ca");
SearchQuery query = new SearchQuery("a", null, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Title > Description > Category.
assertWaypointResults(results,
allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId,
categoryMatchId);
}
public void testSearchMixedText() {
// Insert 5 entries (purposefully out of result order):
// - one waypoint which will match by description
// - one waypoint which won't match
// - one waypoint which will match by title
// - one track which won't match
// - one track which will match by title
long descriptionWaypointId = insertWaypoint("bb", "aa", "cc");
insertWaypoint("bb", "cc", "dd");
long titleWaypointId = insertWaypoint("aa", "bb", "cc");
insertTrack("bb", "cc", "dd");
long trackId = insertTrack("aa", "bb", "cc");
SearchQuery query = new SearchQuery("a", null, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Title > Description > Category.
assertEquals(results.toString(), 3, results.size());
assertTrackResult(trackId, results.get(0));
assertWaypointResult(titleWaypointId, results.get(1));
assertWaypointResult(descriptionWaypointId, results.get(2));
}
public void testSearchTrackDistance() {
// All results match text, but they're at difference distances from the user.
long farFarAwayId = insertTrack("aa", 0.3);
long nearId = insertTrack("ab", 0.1);
long farId = insertTrack("ac", 0.2);
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Distance order.
assertTrackResults(results, nearId, farId, farFarAwayId);
}
public void testSearchWaypointDistance() {
// All results match text, but they're at difference distances from the user.
long farFarAwayId = insertWaypoint("aa", 0.3);
long nearId = insertWaypoint("ab", 0.1);
long farId = insertWaypoint("ac", 0.2);
SearchQuery query = new SearchQuery("a", HERE, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Distance order.
assertWaypointResults(results, nearId, farId, farFarAwayId);
}
public void testSearchTrackRecent() {
// All results match text, but they're were recorded at different times.
long oldestId = insertTrack("aa", 3);
long recentId = insertTrack("ab", 1);
long oldId = insertTrack("ac", 2);
SearchQuery query = new SearchQuery("a", null, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Reverse time order.
assertTrackResults(results, recentId, oldId, oldestId);
}
public void testSearchWaypointRecent() {
// All results match text, but they're were recorded at different times.
long oldestId = insertWaypoint("aa", 2);
long recentId = insertWaypoint("ab", 0);
long oldId = insertWaypoint("ac", 1);
SearchQuery query = new SearchQuery("a", null, -1, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Reverse time order.
assertWaypointResults(results, recentId, oldId, oldestId);
}
public void testSearchCurrentTrack() {
// All results match text, but one of them is the current track.
long currentId = insertTrack("ab", 1);
long otherId = insertTrack("aa", 1);
SearchQuery query = new SearchQuery("a", null, currentId, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Current track should be demoted.
assertTrackResults(results, otherId, currentId);
}
public void testSearchCurrentTrackWaypoint() {
// All results match text, but one of them is in the current track.
long otherId = insertWaypoint("aa", 1, 456);
long currentId = insertWaypoint("ab", 1, 123);
SearchQuery query = new SearchQuery("a", null, 123, NOW);
ArrayList<ScoredResult> results = new ArrayList<ScoredResult>(engine.search(query));
// Waypoint in current track should be promoted.
assertWaypointResults(results, currentId, otherId);
}
private void assertTrackResult(long trackId, ScoredResult result) {
assertNotNull("Not a track", result.track);
assertNull("Ambiguous result", result.waypoint);
assertEquals(trackId, result.track.getId());
}
private void assertTrackResults(List<ScoredResult> results, long... trackIds) {
String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results;
assertEquals(results.size(), trackIds.length);
for (int i = 0; i < results.size(); i++) {
ScoredResult result = results.get(i);
assertNotNull(errMsg, result.track);
assertNull(errMsg, result.waypoint);
assertEquals(errMsg, trackIds[i], result.track.getId());
}
}
private void assertWaypointResult(long waypointId, ScoredResult result) {
assertNotNull("Not a waypoint", result.waypoint);
assertNull("Ambiguous result", result.track);
assertEquals(waypointId, result.waypoint.getId());
}
private void assertWaypointResults(List<ScoredResult> results, long... waypointIds) {
String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results;
assertEquals(results.size(), waypointIds.length);
for (int i = 0; i < results.size(); i++) {
ScoredResult result = results.get(i);
assertNotNull(errMsg, result.waypoint);
assertNull(errMsg, result.track);
assertEquals(errMsg, waypointIds[i], result.waypoint.getId());
}
}
}
@@ -0,0 +1,963 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import static com.google.android.testing.mocking.AndroidMock.capture;
import static com.google.android.testing.mocking.AndroidMock.eq;
import static com.google.android.testing.mocking.AndroidMock.expect;
import static com.google.android.testing.mocking.AndroidMock.isA;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.apps.mytracks.content.DataSourceManager.CurrentLocationListener;
import com.google.android.apps.mytracks.content.DataSourceManager.HeadingListener;
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.TrackDataListener.LocationState;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.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 MockContext context;
private SharedPreferences sharedPreferences;
private MyTracksProviderUtils myTracksProviderUtils;
private DataSource dataSource;
private TrackDataManager trackDataManager;
private TrackDataHub trackDataHub;
private TrackDataListener trackDataListener1;
private TrackDataListener trackDataListener2;
private Capture<OnSharedPreferenceChangeListener> preferenceChangeListenerCapture = new Capture<
SharedPreferences.OnSharedPreferenceChangeListener>();
private float declination;
@UsesMocks({ MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class })
@Override
protected void setUp() throws Exception {
super.setUp();
context = new MockContext(new MockContentResolver(), new RenamingDelegatingContext(
getContext(), getContext(), "test."));
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
dataSource = AndroidMock.createMock(DataSource.class, context);
trackDataManager = new TrackDataManager();
trackDataHub = new TrackDataHub(
context, trackDataManager, myTracksProviderUtils, TARGET_POINTS) {
@Override
protected DataSource newDataSource() {
return dataSource;
}
@Override
protected void runInHanderThread(Runnable runnable) {
// Run everything in the same thread
runnable.run();
}
@Override
protected float getDeclination(Location location, long timestamp) {
return declination;
}
};
trackDataListener1 = AndroidMock.createStrictMock(
"trackDataListener1", TrackDataListener.class);
trackDataListener2 = AndroidMock.createStrictMock(
"trackDataListener2", 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(dataSource);
// Expect everything to be unregistered.
dataSource.unregisterContentObserver(isA(ContentObserver.class));
AndroidMock.expectLastCall().times(3);
dataSource.unregisterLocationListener(isA(LocationListener.class));
dataSource.unregisterHeadingListener(isA(SensorEventListener.class));
dataSource.unregisterOnSharedPreferenceChangeListener(
isA(OnSharedPreferenceChangeListener.class));
dataSource.close();
AndroidMock.replay(dataSource);
trackDataHub.stop();
trackDataHub = null;
super.tearDown();
}
/**
* Tests registering for tracks table update.
*/
public void testTracksTableUpdate() {
// Register two listeners
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
Track track = new Track();
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TracksColumns.CONTENT_URI), capture(contentObserverCapture));
trackDataListener1.onTrackUpdated(track);
trackDataListener2.onTrackUpdated(track);
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
trackDataHub.registerTrackDataListener(
trackDataListener2, EnumSet.of(TrackDataType.TRACKS_TABLE));
verifyAndReset();
// Causes tracks table update
ContentObserver contentObserver = contentObserverCapture.getValue();
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
trackDataListener1.onTrackUpdated(track);
trackDataListener2.onTrackUpdated(track);
replay();
contentObserver.onChange(false);
verifyAndReset();
// Unregister one listener
expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track);
trackDataListener2.onTrackUpdated(track);
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener1);
contentObserver.onChange(false);
verifyAndReset();
// Unregister the second listener
dataSource.unregisterContentObserver(contentObserver);
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener2);
contentObserver.onChange(false);
verifyAndReset();
}
/**
* Tests registering for waypoints table update.
*/
public void testWaypointsTableUpdate() {
Waypoint waypoint1 = new Waypoint();
Waypoint waypoint2 = new Waypoint();
Waypoint waypoint3 = new Waypoint();
Waypoint waypoint4 = new Waypoint();
Location location = new Location("gps");
location.setLatitude(10.0);
location.setLongitude(8.0);
waypoint1.setLocation(location);
waypoint2.setLocation(location);
waypoint3.setLocation(location);
waypoint4.setLocation(location);
// Register two listeners
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
expect(myTracksProviderUtils.getWaypointCursor(
eq(TRACK_ID), AndroidMock.leq(-1L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(2));
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint1).andReturn(waypoint2);
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(WaypointsColumns.CONTENT_URI), capture(contentObserverCapture));
trackDataListener1.clearWaypoints();
trackDataListener2.clearWaypoints();
trackDataListener1.onNewWaypoint(waypoint1);
trackDataListener2.onNewWaypoint(waypoint1);
trackDataListener1.onNewWaypoint(waypoint2);
trackDataListener2.onNewWaypoint(waypoint2);
trackDataListener1.onNewWaypointsDone();
trackDataListener2.onNewWaypointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
trackDataHub.registerTrackDataListener(
trackDataListener2, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
verifyAndReset();
// Cause waypoints table update
ContentObserver contentObserver = contentObserverCapture.getValue();
expect(myTracksProviderUtils.getWaypointCursor(
eq(TRACK_ID), AndroidMock.leq(-1L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(3));
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3);
trackDataListener1.clearWaypoints();
trackDataListener2.clearWaypoints();
trackDataListener1.onNewWaypoint(waypoint1);
trackDataListener2.onNewWaypoint(waypoint1);
trackDataListener1.onNewWaypoint(waypoint2);
trackDataListener2.onNewWaypoint(waypoint2);
trackDataListener1.onNewWaypoint(waypoint3);
trackDataListener2.onNewWaypoint(waypoint3);
trackDataListener1.onNewWaypointsDone();
trackDataListener2.onNewWaypointsDone();
replay();
contentObserver.onChange(false);
verifyAndReset();
// Unregister one listener
expect(myTracksProviderUtils.getWaypointCursor(
eq(TRACK_ID), AndroidMock.leq(-1L), eq(Constants.MAX_DISPLAYED_WAYPOINTS_POINTS)))
.andStubAnswer(new FixedSizeCursorAnswer(4));
expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class)))
.andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3).andReturn(waypoint4);
trackDataListener2.clearWaypoints();
trackDataListener2.onNewWaypoint(waypoint1);
trackDataListener2.onNewWaypoint(waypoint2);
trackDataListener2.onNewWaypoint(waypoint3);
trackDataListener2.onNewWaypoint(waypoint4);
trackDataListener2.onNewWaypointsDone();
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener1);
contentObserver.onChange(false);
verifyAndReset();
// Unregister the second listener
dataSource.unregisterContentObserver(contentObserver);
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener2);
contentObserver.onChange(false);
verifyAndReset();
}
/**
* Tests track points table update.
*/
public void testTrackPointsTableUpdate() {
// Register one listener
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
// Register a second listener
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
trackDataListener2.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener2);
trackDataListener2.onNewTrackPointsDone();
replay();
trackDataHub.registerTrackDataListener(
trackDataListener2, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
// Deliver more points - should go to both listeners without clearing
ContentObserver contentObserver = contentObserverCapture.getValue();
locationIterator = new FixedSizeLocationIterator(11, 10, 1);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(20L);
locationIterator.expectLocationsDelivered(trackDataListener1);
locationIterator.expectLocationsDelivered(trackDataListener2);
trackDataListener1.onNewTrackPointsDone();
trackDataListener2.onNewTrackPointsDone();
replay();
contentObserver.onChange(false);
verifyAndReset();
// Unregister one listener and change track
locationIterator = new FixedSizeLocationIterator(101, 10);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(110L);
trackDataListener2.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener2);
trackDataListener2.onNewTrackPointsDone();
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener1);
trackDataHub.loadTrack(TRACK_ID + 1);
verifyAndReset();
}
/**
* Tests track points table update with registering the same listener.
*/
public void testTrackPointsTableUpdate_reRegister() {
// Register one listener
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
// Unregister the listener
ContentObserver observer = contentObserverCapture.getValue();
dataSource.unregisterContentObserver(observer);
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener1);
verifyAndReset();
// Register again
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
}
/**
* Tests tracks point able change. Register a listener after a track change.
*/
public void testTrackPointsTableUpdate_reRegisterAfterTrackChange() {
// Register one listener
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
// Unregister the listener
ContentObserver observer = observerCapture.getValue();
dataSource.unregisterContentObserver(observer);
replay();
trackDataHub.unregisterTrackDataListener(trackDataListener1);
verifyAndReset();
// Register the listener after a new track
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
locationIterator = new FixedSizeLocationIterator(1, 10);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class)))
.andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(10L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.loadTrack(TRACK_ID + 1);
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
}
/**
* Tests track points table update with large track sampling.
*/
public void testTrackPointsTableUpdate_largeTrackSampling() {
Capture<ContentObserver> contentObserverCapture = new Capture<ContentObserver>();
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture));
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(200L);
AndroidMock.expectLastCall().anyTimes();
FixedSizeLocationIterator locationIterator1 = new FixedSizeLocationIterator(
1, 200, 4, 25, 71, 120);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator1);
FixedSizeLocationIterator locationIterator2 = new FixedSizeLocationIterator(
1, 200, 4, 25, 71, 120);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator2);
trackDataListener1.clearTrackPoints();
locationIterator1.expectSampledLocationsDelivered(trackDataListener1, 4, false);
trackDataListener1.onNewTrackPointsDone();
trackDataListener2.clearTrackPoints();
locationIterator2.expectSampledLocationsDelivered(trackDataListener2, 4, true);
trackDataListener2.onNewTrackPointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
trackDataHub.registerTrackDataListener(trackDataListener2, EnumSet.of(
TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE, TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE));
verifyAndReset();
}
/**
* Tests track points table update with resampling.
*/
public void testTrackPointsTableUpdate_resampling() {
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
dataSource.registerContentObserver(
eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture));
// Deliver 30 points (no sampling happens)
FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(30L);
trackDataListener1.clearTrackPoints();
locationIterator.expectLocationsDelivered(trackDataListener1);
trackDataListener1.onNewTrackPointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE));
verifyAndReset();
// Now deliver 30 more (incrementally sampled)
ContentObserver observer = observerCapture.getValue();
locationIterator = new FixedSizeLocationIterator(31, 30);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(31L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(60L);
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
trackDataListener1.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
// Now another 30 (triggers resampling)
locationIterator = new FixedSizeLocationIterator(1, 90);
expect(myTracksProviderUtils.getTrackPointLocationIterator(
eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(90L);
trackDataListener1.clearTrackPoints();
locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false);
trackDataListener1.onNewTrackPointsDone();
replay();
observer.onChange(false);
verifyAndReset();
}
/**
* Tests headings change.
*/
public void testHeadingsChange() throws Exception {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<SensorEventListener> sensorEventListenerCapture = new Capture<SensorEventListener>();
dataSource.registerHeadingListener(capture(sensorEventListenerCapture));
Capture<LocationListener> locationListenerCapture = new Capture<LocationListener>();
dataSource.registerLocationListener(capture(locationListenerCapture));
SensorEvent event = newSensorEvent();
// Expect location state changed
trackDataListener1.onLocationStateChanged(isA(LocationState.class));
AndroidMock.expectLastCall().anyTimes();
// First, get a dummy heading update
trackDataListener1.onHeadingChanged(0.0);
// Second, get a heading update without known location
trackDataListener1.onHeadingChanged(42.0f);
replay();
// Register one listener and update heading value
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.HEADING, TrackDataType.LOCATION));
SensorEventListener sensorListener = sensorEventListenerCapture.getValue();
LocationListener locationListener = locationListenerCapture.getValue();
event.values[0] = 42.0f;
sensorListener.onSensorChanged(event);
verifyAndReset();
// Expect location state changed
trackDataListener1.onLocationStateChanged(isA(LocationState.class));
AndroidMock.expectLastCall().anyTimes();
// Expect location changed
trackDataListener1.onLocationChanged(isA(Location.class));
AndroidMock.expectLastCall().anyTimes();
// Expect a heading update with declination
trackDataListener1.onHeadingChanged(52.0);
AndroidMock.expect(dataSource.isAllowed()).andReturn(true);
replay();
// Update location and sensor
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();
trackDataListener1.onHeadingChanged(52.0);
replay();
/*
* Change declination. Should still get the old value since the declination
* is only updated once an hour.
*/
declination = 20.0f;
sensorListener.onSensorChanged(event);
verifyAndReset();
}
/**
* Tests preferences change.
*/
public void testPreferencesChange() throws Exception {
// Register two listeners
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
PreferencesUtils.setInt(context, R.string.min_recording_distance_key,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
expect(trackDataListener1.onMetricUnitsChanged(true)).andReturn(false);
expect(trackDataListener1.onReportSpeedChanged(true)).andReturn(false);
expect(trackDataListener1.onMinRecordingDistanceChanged(
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT)).andReturn(false);
expect(trackDataListener2.onMetricUnitsChanged(true)).andReturn(false);
expect(trackDataListener2.onReportSpeedChanged(true)).andReturn(false);
expect(trackDataListener2.onMinRecordingDistanceChanged(
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT)).andReturn(false);
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.PREFERENCE));
trackDataHub.registerTrackDataListener(
trackDataListener2, EnumSet.of(TrackDataType.PREFERENCE));
verifyAndReset();
// Change report speed to false
expect(trackDataListener1.onReportSpeedChanged(false)).andReturn(false);
expect(trackDataListener2.onReportSpeedChanged(false)).andReturn(false);
replay();
PreferencesUtils.setBoolean(context, R.string.report_speed_key, false);
OnSharedPreferenceChangeListener listener = preferenceChangeListenerCapture.getValue();
listener.onSharedPreferenceChanged(
sharedPreferences, PreferencesUtils.getKey(context, R.string.report_speed_key));
verifyAndReset();
// Change metric units to false
expect(trackDataListener1.onMetricUnitsChanged(false)).andReturn(false);
expect(trackDataListener2.onMetricUnitsChanged(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();
}
/**
* Creates a new sensor event.
*/
private SensorEvent newSensorEvent() throws Exception {
Constructor<SensorEvent> constructor = SensorEvent.class.getDeclaredConstructor(int.class);
constructor.setAccessible(true);
return constructor.newInstance(3);
}
/**
* Replays mocks.
*/
private void replay() {
AndroidMock.replay(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
}
/**
* Verifies and resets mocks.
*/
private void verifyAndReset() {
AndroidMock.verify(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
AndroidMock.reset(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2);
}
/**
* Fixed size cursor answer.
*
* @author Jimmy Shih
*/
private static class FixedSizeCursorAnswer implements IAnswer<Cursor> {
private final int size;
public FixedSizeCursorAnswer(int size) {
this.size = size;
}
@Override
public Cursor answer() throws Throwable {
MatrixCursor cursor = new MatrixCursor(new String[] { BaseColumns._ID });
for (long i = 0; i < size; i++) {
cursor.addRow(new Object[] { i });
}
return cursor;
}
}
/**
* Fixed size location iterator.
*
* @author Jimmy Shih
*/
private static class FixedSizeLocationIterator implements LocationIterator {
private final long startId;
private final Location[] locations;
private final Set<Integer> splitIndexSet = new HashSet<Integer>();
private int currentIndex = -1;
public FixedSizeLocationIterator(long startId, int size) {
this(startId, size, null);
}
public FixedSizeLocationIterator(long startId, int size, int... splitIndexes) {
this.startId = startId;
this.locations = new Location[size];
for (int i = 0; i < size; i++) {
Location location = new Location("gps");
location.setLatitude(-15.0 + i / 1000.0);
location.setLongitude(37 + i / 1000.0);
location.setAltitude(i);
locations[i] = location;
}
if (splitIndexes != null) {
for (int splitIndex : splitIndexes) {
splitIndexSet.add(splitIndex);
Location splitLocation = locations[splitIndex];
splitLocation.setLatitude(100.0);
splitLocation.setLongitude(200.0);
}
}
}
public void expectLocationsDelivered(TrackDataListener listener) {
for (int i = 0; i < locations.length; i++) {
if (splitIndexSet.contains(i)) {
listener.onSegmentSplit(locations[i]);
} else {
listener.onSampledInTrackPoint(locations[i]);
}
}
}
public void expectSampledLocationsDelivered(
TrackDataListener listener, int sampleFrequency, boolean includeSampledOut) {
boolean includeNext = false;
for (int i = 0; i < locations.length; i++) {
if (splitIndexSet.contains(i)) {
listener.onSegmentSplit(locations[i]);
includeNext = true;
} else if (includeNext || (i % sampleFrequency == 0)) {
listener.onSampledInTrackPoint(locations[i]);
includeNext = false;
} else if (includeSampledOut) {
listener.onSampledOutTrackPoint(locations[i]);
}
}
}
@Override
public boolean hasNext() {
return currentIndex < locations.length - 1;
}
@Override
public Location next() {
currentIndex++;
return locations[currentIndex];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public long getLocationId() {
return startId + currentIndex;
}
@Override
public void close() {
// Do nothing
}
}
/**
* Tests the method {@link TrackDataHub#start()}.
*/
public void testRegisterSelectedTrackListener() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Track track = TrackStubUtils.createTrack(1);
expect(myTracksProviderUtils.getTrack(capture(new Capture<Long>()))).andReturn(track);
// Make the track id is unique.
PreferencesUtils.setLong(context, R.string.recording_track_id_key, System.currentTimeMillis());
trackDataListener1.onSelectedTrackChanged(track);
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.SELECTED_TRACK));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()}.
*/
public void testRegisterTracksTableListener() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture));
Track track = TrackStubUtils.createTrack(1);
expect(myTracksProviderUtils.getTrack(capture(new Capture<Long>()))).andReturn(track);
// Make the track id is unique.
PreferencesUtils.setLong(context, R.string.recording_track_id_key, System.currentTimeMillis());
trackDataListener1.onTrackUpdated(track);
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()}.
*/
public void testRegisterWaypointsTableListener() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<ContentObserver> observerCapture = new Capture<ContentObserver>();
dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture));
expect(myTracksProviderUtils.getWaypointCursor(
capture(new Capture<Long>()), capture(new Capture<Long>()),
capture(new Capture<Integer>()))).andReturn(null);
trackDataListener1.clearWaypoints();
trackDataListener1.onNewWaypointsDone();
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(
trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()} when no last seen location.
*/
public void testRegisterLocationListener_noLastSeenLocation() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<CurrentLocationListener> currentLocationListener = new Capture<
CurrentLocationListener>();
dataSource.registerLocationListener(capture(currentLocationListener));
trackDataListener1.onLocationStateChanged(capture(new Capture<LocationState>()));
replay();
trackDataHub.setLastSeenLocation(null);
trackDataHub.start();
trackDataHub.registerTrackDataListener(trackDataListener1, EnumSet.of(TrackDataType.LOCATION));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()} when has last seen location.
*/
public void testRegisterLocationListener_hasLastSeenLocation() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<CurrentLocationListener> currentLocationListener = new Capture<
CurrentLocationListener>();
dataSource.registerLocationListener(capture(currentLocationListener));
trackDataListener1.onLocationStateChanged(capture(new Capture<LocationState>()));
trackDataListener1.onLocationChanged(capture(new Capture<Location>()));
replay();
trackDataHub.setLastSeenLocation(new Location("gps"));
trackDataHub.start();
trackDataHub.registerTrackDataListener(trackDataListener1, EnumSet.of(TrackDataType.LOCATION));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()}. This method would also cover
* some logic of {@link TrackDataHub#notifyHeadingChanged(float)}.
*/
public void testRegisterHeadingListener() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<HeadingListener> compassListener = new Capture<HeadingListener>();
dataSource.registerHeadingListener(capture(compassListener));
trackDataListener1.onHeadingChanged(capture(new Capture<Float>()));
replay();
trackDataHub.start();
trackDataHub.registerTrackDataListener(trackDataListener1, EnumSet.of(TrackDataType.HEADING));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
* the key is R.string.min_required_accuracy_key.
*/
public void testNotifyPreferenceChanged_minRequiredAccuracy() {
int value = 1;
PreferencesUtils.setInt(context, R.string.min_required_accuracy_key, value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.min_required_accuracy_key));
assertEquals(value, trackDataHub.getMinRequiredAccuracy());
PreferencesUtils.setInt(context, R.string.min_required_accuracy_key, value + 1);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.min_required_accuracy_key));
assertEquals(value + 1, trackDataHub.getMinRequiredAccuracy());
}
/**
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
* the key is R.string.metric_units_key.
*/
public void testNotifyPreferenceChanged_metricUnitsNoNotify() {
boolean value = false;
PreferencesUtils.setBoolean(context, R.string.metric_units_key, value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.metric_units_key));
assertEquals(value, trackDataHub.isMetricUnits());
PreferencesUtils.setBoolean(context, R.string.metric_units_key, !value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.metric_units_key));
assertEquals(!value, trackDataHub.isMetricUnits());
}
/**
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
* the key is R.string.metric_units_key.
*/
public void testNotifyPreferenceChanged_reportSpeedNoNotify() {
boolean value = false;
PreferencesUtils.setBoolean(context, R.string.report_speed_key, value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.report_speed_key));
assertEquals(value, trackDataHub.isReportSpeed());
PreferencesUtils.setBoolean(context, R.string.report_speed_key, !value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.report_speed_key));
assertEquals(!value, trackDataHub.isReportSpeed());
}
/**
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
* the key is R.string.selected_track_id_key and no listener is registered.
*/
public void testNotifyPreferenceChanged_trackIdNoListener() {
long value = 1;
PreferencesUtils.setLong(context, R.string.selected_track_id_key, value);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.selected_track_id_key));
assertEquals(value, trackDataHub.getSelectedTrackId());
PreferencesUtils.setLong(context, R.string.selected_track_id_key, value + 1);
trackDataHub.notifyPreferenceChanged(PreferencesUtils
.getKey(context, R.string.selected_track_id_key));
assertEquals(value + 1, trackDataHub.getSelectedTrackId());
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
import android.os.Parcel;
import android.test.AndroidTestCase;
/**
* Tests for the WaypointCreationRequest class.
* {@link WaypointCreationRequest}
*
* @author Sandor Dornbush
*/
public class WaypointCreationRequestTest extends AndroidTestCase {
public void testTypeParceling() {
WaypointCreationRequest original = WaypointCreationRequest.DEFAULT_WAYPOINT;
Parcel p = Parcel.obtain();
original.writeToParcel(p, 0);
p.setDataPosition(0);
WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p);
assertEquals(original.getType(), copy.getType());
assertFalse(copy.isTrackStatistics());
assertNull(copy.getName());
assertNull(copy.getDescription());
assertNull(copy.getIconUrl());
}
public void testAllAttributesParceling() {
WaypointCreationRequest original = new WaypointCreationRequest(
WaypointType.WAYPOINT, false, "name", "category", "description", "img.png");
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,365 @@
/*
* 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()));
chartFragment.setTripStatisticsUpdater(TrackStubUtils.INITIAL_TIME);
}
/**
* Tests the logic to get the incorrect values of sensor in
* {@link ChartFragment#fillDataPoint(Location, double[])}
*/
public void testFillDataPoint_sensorIncorrect() {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
// No input.
double[] point = fillDataPointTestHelper(myTracksLocation);
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
// Input incorrect state.
// Creates SensorData.
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
.setValue(100).setState(Sensor.SensorState.NONE);
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
.setValue(101).setState(Sensor.SensorState.NONE);
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
.setValue(102).setState(Sensor.SensorState.NONE);
// Creates SensorDataSet.
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
sensorDataSet = sensorDataSet.toBuilder()
.setHeartRate(heartRateData)
.setCadence(cadenceData)
.setPower(powerData)
.build();
myTracksLocation.setSensorDataSet(sensorDataSet);
// Test.
point = fillDataPointTestHelper(myTracksLocation);
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
}
/**
* Tests the logic to get the correct values of sensor in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
*/
public void testFillDataPoint_sensorCorrect() {
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
// No input.
double[] point = fillDataPointTestHelper(myTracksLocation);
assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]);
assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]);
// Creates SensorData.
Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder()
.setValue(100).setState(Sensor.SensorState.SENDING);
Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder()
.setValue(101).setState(Sensor.SensorState.SENDING);
Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder()
.setValue(102).setState(Sensor.SensorState.SENDING);
// Creates SensorDataSet.
SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet();
sensorDataSet = sensorDataSet.toBuilder()
.setHeartRate(heartRateData)
.setCadence(cadenceData)
.setPower(powerData)
.build();
myTracksLocation.setSensorDataSet(sensorDataSet);
// Test.
point = fillDataPointTestHelper(myTracksLocation);
assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1]);
assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1]);
assertEquals(102.0, point[ChartView.POWER_SERIES + 1]);
}
/**
* Tests the logic to get the value of metric Distance in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
*/
public void testFillDataPoint_distanceMetric() {
// By distance.
chartFragment.setChartByDistance(true);
// Resets last location and writes first location.
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[0]);
// The second is a same location, just different time.
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals(0.0, point[0]);
// The third location is a new location, and use metric.
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
myTracksLocation3.setLatitude(23);
point = fillDataPointTestHelper(myTracksLocation3);
// Computes the distance between Latitude 22 and 23.
float[] results = new float[4];
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
double distance1 = results[0] * UnitConversions.M_TO_KM;
assertEquals(distance1, point[0]);
// The fourth location is a new location, and use metric.
MyTracksLocation myTracksLocation4 = TrackStubUtils.createMyTracksLocation();
myTracksLocation4.setLatitude(24);
point = fillDataPointTestHelper(myTracksLocation4);
// Computes the distance between Latitude 23 and 24.
Location.distanceBetween(myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(),
myTracksLocation4.getLatitude(), myTracksLocation4.getLongitude(), results);
double distance2 = results[0] * UnitConversions.M_TO_KM;
assertEquals((distance1 + distance2), point[0]);
}
/**
* Tests the logic to get the value of imperial Distance in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
*/
public void testFillDataPoint_distanceImperial() {
// By distance.
chartFragment.setChartByDistance(true);
// Setups to use imperial.
chartFragment.setMetricUnits(false);
// The first is a same location, just different time.
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[0]);
// The second location is a new location, and use imperial.
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
myTracksLocation2.setLatitude(23);
point = fillDataPointTestHelper(myTracksLocation2);
/*
* Computes the distance between Latitude 22 and 23. And for we set using
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
*/
float[] results = new float[4];
Location.distanceBetween(myTracksLocation1.getLatitude(), myTracksLocation1.getLongitude(),
myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), results);
double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
assertEquals(distance1, point[0]);
// The third location is a new location, and use imperial.
MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation();
myTracksLocation3.setLatitude(24);
point = fillDataPointTestHelper(myTracksLocation3);
/*
* Computes the distance between Latitude 23 and 24. And for we set using
* imperial, the distance should be multiplied by UnitConversions.KM_TO_MI.
*/
Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(),
myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results);
double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI;
assertEquals(distance1 + distance2, point[0]);
}
/**
* Tests the logic to get the values of time in
* {@link ChartFragment#fillDataPoint(Location, double[])}.
*/
public void testFillDataPoint_time() {
// By time
chartFragment.setChartByDistance(false);
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[0]);
long timeSpan = 222;
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
myTracksLocation2.setTime(myTracksLocation1.getTime() + timeSpan);
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals((double) timeSpan, point[0]);
}
/**
* Tests the logic to get the value of elevation in
* {@link ChartFragment#fillDataPoint(Location, double[])} by one and two
* points.
*/
public void testFillDataPoint_elevation() {
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
/*
* At first, clear old points of elevation, so give true to the second
* parameter. Then only one value INITIALLONGTITUDE in buffer.
*/
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1]);
/*
* Send another value to buffer, now there are two values, INITIALALTITUDE
* and INITIALALTITUDE * 2.
*/
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
myTracksLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2);
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0,
point[ChartView.ELEVATION_SERIES + 1]);
}
/**
* Tests the logic to get the value of speed in
* {@link ChartFragment#fillDataPoint(Location, double[])}. In this test,
* firstly remove all points in memory, and then fill in two points one by
* one. The speed values of these points are 129, 130.
*/
public void testFillDataPoint_speed() {
/*
* At first, clear old points of speed, so give true to the second
* parameter. It will not be filled in to the speed buffer.
*/
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
myTracksLocation1.setSpeed(128.5f);
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
/*
* Tests the logic when both metricUnits and reportSpeed are true.This
* location will be filled into speed buffer.
*/
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
/*
* Add a time span here to make sure the second point is valid, the value
* 222 here is doesn't matter.
*/
myTracksLocation2.setTime(myTracksLocation1.getTime() + 222);
myTracksLocation2.setSpeed(130);
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1]);
}
/**
* Tests the logic to compute speed when use Imperial.
*/
public void testFillDataPoint_speedImperial() {
// Setups to use imperial.
chartFragment.setMetricUnits(false);
// First data point is not added to the speed buffer
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
myTracksLocation1.setSpeed(100.0f);
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
/*
* Add a time span here to make sure the second point is valid and the speed is valid.
*
* Speed is valid if:
* speedDifference > Constants.MAX_ACCELERATION * timeDifference
* speedDifference = 102 -100
* timeDifference = 222
*/
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
myTracksLocation2.setSpeed(102);
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI,
point[ChartView.SPEED_SERIES + 1]);
}
/**
* Tests the logic to get pace value when reportSpeed is false.
*/
public void testFillDataPoint_pace_nonZeroSpeed() {
// Setups reportSpeed to false.
chartFragment.setReportSpeed(false);
// First data point is not added to the speed buffer
MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation();
myTracksLocation1.setSpeed(100.0f);
double[] point = fillDataPointTestHelper(myTracksLocation1);
assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]);
MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation();
/*
* Add a time span here to make sure the second point is valid and the speed is valid.
*
* Speed is valid if:
* speedDifference > Constants.MAX_ACCELERATION * timeDifference
* speedDifference = 102 -100
* timeDifference = 222
*/
myTracksLocation2.setTime(myTracksLocation2.getTime() + 222);
myTracksLocation2.setSpeed(102);
point = fillDataPointTestHelper(myTracksLocation2);
assertEquals(
HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1]);
}
/**
* Tests the logic to get pace value when reportSpeed is false and average
* speed is zero.
*/
public void testFillDataPoint_pace_zeroSpeed() {
// Setups reportSpeed to false.
chartFragment.setReportSpeed(false);
MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation();
myTracksLocation.setSpeed(0);
double[] point = fillDataPointTestHelper(myTracksLocation);
assertEquals(0.0, point[ChartView.PACE_SERIES + 1]);
}
/**
* Helper method to test fillDataPoint.
*
* @param location location to fill
* @return data of this location
*/
private double[] fillDataPointTestHelper(Location location) {
double[] point = new double[ChartView.NUM_SERIES + 1];
chartFragment.fillDataPoint(location, point);
return point;
}
}
@@ -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,212 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.test.AndroidTestCase;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Tests for {@link PreferenceBackupHelper}.
*
* @author Rodrigo Damazio
*/
public class PreferenceBackupHelperTest extends AndroidTestCase {
private Map<String, ?> preferenceValues;
private SharedPreferences preferences;
private PreferenceBackupHelper preferenceBackupHelper;
/**
* Mock shared preferences editor which does not persist state.
*/
private class MockPreferenceEditor implements SharedPreferences.Editor {
private Map<String, Object> newPreferences = new HashMap<String, Object>(preferenceValues);
@Override
public Editor clear() {
newPreferences.clear();
return this;
}
@Override
public boolean commit() {
apply();
return true;
}
@Override
public void apply() {
preferenceValues = newPreferences;
}
@Override
public Editor putBoolean(String key, boolean value) {
return put(key, value);
}
@Override
public Editor putFloat(String key, float value) {
return put(key, value);
}
@Override
public Editor putInt(String key, int value) {
return put(key, value);
}
@Override
public Editor putLong(String key, long value) {
return put(key, value);
}
@Override
public Editor putString(String key, String value) {
return put(key, value);
}
public Editor putStringSet(String key, Set<String> value) {
return put(key, value);
}
private <T> Editor put(String key, T value) {
newPreferences.put(key, value);
return this;
}
@Override
public Editor remove(String key) {
newPreferences.remove(key);
return this;
}
}
/**
* Mock shared preferences which does not persist state.
*/
private class MockPreferences implements SharedPreferences {
@Override
public boolean contains(String key) {
return preferenceValues.containsKey(key);
}
@Override
public Editor edit() {
return new MockPreferenceEditor();
}
@Override
public Map<String, ?> getAll() {
return preferenceValues;
}
@Override
public boolean getBoolean(String key, boolean defValue) {
return get(key, defValue);
}
@Override
public float getFloat(String key, float defValue) {
return get(key, defValue);
}
@Override
public int getInt(String key, int defValue) {
return get(key, defValue);
}
@Override
public long getLong(String key, long defValue) {
return get(key, defValue);
}
@Override
public String getString(String key, String defValue) {
return get(key, defValue);
}
public Set<String> getStringSet(String key, Set<String> defValue) {
return get(key, defValue);
}
@Override
public void registerOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void unregisterOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
private <T> T get(String key, T defValue) {
Object value = preferenceValues.get(key);
if (value == null) return defValue;
return (T) value;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
preferenceValues = new HashMap<String, Object>();
preferences = new MockPreferences();
preferenceBackupHelper = new PreferenceBackupHelper(getContext());
}
public void testExportImportPreferences() throws Exception {
// Populate with some initial values
Editor editor = preferences.edit();
editor.clear();
editor.putBoolean("bool1", true);
editor.putBoolean("bool2", false);
editor.putFloat("flt1", 3.14f);
editor.putInt("int1", 42);
editor.putLong("long1", 123456789L);
editor.putString("str1", "lolcat");
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
// Export it
byte[] exported = preferenceBackupHelper.exportPreferences(preferences);
// Mess with the previous values
editor = preferences.edit();
editor.clear();
editor.putString("str2", "Shouldn't be there after restore");
editor.putBoolean("bool2", true);
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
// Import it back
preferenceBackupHelper.importPreferences(exported, preferences);
assertFalse(preferences.contains("str2"));
assertTrue(preferences.getBoolean("bool1", false));
assertFalse(preferences.getBoolean("bool2", true));
assertEquals(3.14f, preferences.getFloat("flt1", 0.0f));
assertEquals(42, preferences.getInt("int1", 0));
assertEquals(123456789L, preferences.getLong("long1", 0));
assertEquals("lolcat", preferences.getString("str1", ""));
}
}
@@ -0,0 +1,248 @@
/*
* 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>"
+ "<gsx:fusiontable><![CDATA[-]]></gsx:fusiontable>"
+ "</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>"
+ "<gsx:fusiontable><![CDATA[-]]></gsx:fusiontable>"
+ "</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.setTripStatistics(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)");
String expectedPoint1 = getExpectedLine("1", "1", "0.0", "0.0", "0.0", "0.0", "0", "0",
"1970-01-01T00:00:00.000Z", "100.0", "200.0", "300.0");
String expectedPoint2 = getExpectedLine("1", "2", "1.0", "-1.0", "10.0", "100.0", "1,000",
"10,000", "1970-01-01T00:01:40.000Z", "101.0", "201.0", "301.0");
String expectedPoint3 = getExpectedLine("2", "1", "2.0", "-2.0", "20.0", "200.0", "2,000",
"20,000", "1970-01-01T00:03:20.000Z", "102.0", "202.0", "302.0");
String expectedPoint4 = getExpectedLine("2", "2", "3.0", "-3.0", "30.0", "300.0", "3,000",
"30,000", "1970-01-01T00:05:00.000Z", "103.0", "203.0", "303.0");
String expected = expectedTrackHeader + expectedTrack + "\n"
+ expectedMarkerHeader + expectedMarker1 + expectedMarker2 + "\n"
+ expectedPointHeader + expectedPoint1 + expectedPoint2 + expectedPoint3 + expectedPoint4;
CsvTrackWriter 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,476 @@
/*
* 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.MyTracksProviderUtils.Factory;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory;
import com.google.android.apps.mytracks.util.PreferencesUtils;
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.Locale;
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_0 = "blablub";
private static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer";
private static final String TRACK_NAME_1 = "another track";
private static final String TRACK_DESCRIPTION_1 = "another description";
private static final double TRACK_LATITUDE = 48.768364;
private static final double TRACK_LONGITUDE = 9.177886;
private static final double TRACK_ELEVATION = 324.0;
private static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z";
private static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123";
private static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123";
private static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123";
private static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat(
"yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
private static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
static {
/*
* We can't omit the timezones in the test, otherwise it'll use the local
* timezone and fail depending on where the test runner is.
*/
SimpleTimeZone utc = new SimpleTimeZone(0, "UTC");
DATE_FORMAT_0.setTimeZone(utc);
DATE_FORMAT_1.setTimeZone(utc);
}
private static String getNameAndDescription(String name, String description) {
return "<name><![CDATA[" + name + "]]></name>" + "<desc><![CDATA[" + description + "]]></desc>";
}
private static String getTrackPoint(int index, String time) {
String latitude = Double.toString(TRACK_LATITUDE + index);
String longitude = Double.toString(TRACK_LONGITUDE + index);
String elevation = Double.toString(TRACK_ELEVATION + index);
StringBuffer buffer = new StringBuffer();
buffer.append(
"<trkpt lat=\"" + latitude + "\" lon=\"" + longitude + "\"><ele>" + elevation + "</ele>");
if (time != null) {
buffer.append("<time>" + time + "</time>");
}
buffer.append("</trkpt>");
return buffer.toString();
}
private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "<gpx><trk>"
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "<gpx><trk>"
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
+ getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "</trkseg><trkseg>"
+ getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + "</trkseg></trk></gpx>";
private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "<gpx><trk>"
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
+ getTrackPoint(0, null) + getTrackPoint(1, null) + "</trkseg><trkseg>"
+ getTrackPoint(2, null) + getTrackPoint(3, null) + "</trkseg></trk></gpx>";
private static final String VALID_TWO_TRACKS_GPX = "<gpx><trk>"
+ getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "<trkseg>"
+ getTrackPoint(0, TRACK_TIME_0) + "</trkseg></trk><trk>"
+ getNameAndDescription(TRACK_NAME_1, TRACK_DESCRIPTION_1) + "<trkseg>"
+ getTrackPoint(1, TRACK_TIME_1) + "</trkseg></trk></gpx>";
private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring(
0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50);
private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
Double.toString(TRACK_LATITUDE), "1000.0");
private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
TRACK_TIME_0, "invalid");
private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
Double.toString(TRACK_ELEVATION), "invalid");
private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
Double.toString(TRACK_LATITUDE), "invalid");
private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll(
Double.toString(TRACK_LONGITUDE), "invalid");
private static final long TRACK_ID_0 = 1;
private static final long TRACK_ID_1 = 2;
private static final long TRACK_POINT_ID_0 = 1;
private static final long TRACK_POINT_ID_1 = 2;
private static final long TRACK_POINT_ID_3 = 4;
private static final long WAYPOINT_ID_0 = 1;
private static final Uri TRACK_ID_0_URI = ContentUris.appendId(
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build();
private static final Uri TRACK_ID_1_URI = ContentUris.appendId(
TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_1).build();
private static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId(
WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build();
private MyTracksProviderUtils myTracksProviderUtils;
private Factory oldMyTracksProviderUtilsFactory;
@UsesMocks(MyTracksProviderUtils.class)
@Override
protected void setUp() throws Exception {
super.setUp();
myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class);
oldMyTracksProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance(
myTracksProviderUtils);
}
@Override
protected void tearDown() throws Exception {
TestingProviderUtilsFactory.restoreOldFactory(oldMyTracksProviderUtilsFactory);
super.tearDown();
}
/**
* Tests one track with one segment.
*/
public void testOneTrackOneSegment() throws Exception {
Capture<Track> track = new Capture<Track>();
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_0_URI);
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
// A flush happens at the end
expect(myTracksProviderUtils.bulkInsertTrackPoint(
LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1);
expectUpdateTrack(track, true, TRACK_ID_0);
AndroidMock.replay(myTracksProviderUtils);
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes());
long[] trackIds = GpxImporter.importGPXFile(getContext(), inputStream, myTracksProviderUtils,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
assertEquals(1, trackIds.length);
assertEquals(TRACK_ID_0, trackIds[0]);
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime());
AndroidMock.verify(myTracksProviderUtils);
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0);
}
/**
* Tests one track with two segments.
*/
public void testOneTrackTwoSegments() throws Exception {
Capture<Track> track = new Capture<Track>();
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_0_URI);
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
// A flush happens at the end
expect(myTracksProviderUtils.bulkInsertTrackPoint(
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
expectUpdateTrack(track, true, TRACK_ID_0);
AndroidMock.replay(myTracksProviderUtils);
InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes());
long[] trackIds = GpxImporter.importGPXFile(getContext(), inputStream, myTracksProviderUtils,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
assertEquals(1, trackIds.length);
assertEquals(TRACK_ID_0, trackIds[0]);
long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime();
long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime();
long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime();
long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime();
assertEquals(
time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime());
AndroidMock.verify(myTracksProviderUtils);
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0,
DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
}
/**
* Tests one track with two segments, but no time in the track points.
*/
public void testOneTrackTwoSegmentsNoTime() throws Exception {
Capture<Track> track = new Capture<Track>();
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_0_URI);
expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0);
// A flush happens at the end
expect(myTracksProviderUtils.bulkInsertTrackPoint(
(Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3);
expectUpdateTrack(track, true, TRACK_ID_0);
AndroidMock.replay(myTracksProviderUtils);
InputStream inputStream = new ByteArrayInputStream(
VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes());
long[] trackIds = GpxImporter.importGPXFile(getContext(), inputStream, myTracksProviderUtils,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
assertEquals(1, trackIds.length);
assertEquals(TRACK_ID_0, trackIds[0]);
assertEquals(0, track.getValue().getTripStatistics().getTotalTime());
AndroidMock.verify(myTracksProviderUtils);
verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L);
}
/**
* Tests two tracks.
*/
public void testTwoTracks() throws Exception {
Capture<Track> track0 = new Capture<Track>();
Capture<Track> track1 = new Capture<Track>();
Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime());
Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime());
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_0_URI);
expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0);
expectUpdateTrack(track0, false, TRACK_ID_0);
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_1_URI);
expectFirstTrackPoint(location1, TRACK_ID_1, TRACK_POINT_ID_1);
expectUpdateTrack(track1, true, TRACK_ID_1);
AndroidMock.replay(myTracksProviderUtils);
InputStream inputStream = new ByteArrayInputStream(VALID_TWO_TRACKS_GPX.getBytes());
long[] trackIds = GpxImporter.importGPXFile(getContext(), inputStream, myTracksProviderUtils,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
assertEquals(2, trackIds.length);
assertEquals(TRACK_ID_0, trackIds[0]);
assertEquals(TRACK_ID_1, trackIds[1]);
AndroidMock.verify(myTracksProviderUtils);
}
/**
* Test an invalid xml input.
*/
public void testInvalidXml() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_XML_GPX);
}
/**
* Test an invalid location.
*/
public void testInvalidLocation() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_LOCATION_GPX);
}
/**
* Test an invalid time.
*/
public void testInvalidTime() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_TIME_GPX);
}
/**
* Test an invalid altitude.
*/
public void testInvalidAltitude() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_ALTITUDE_GPX);
}
/**
* Test an invalid latitude.
*/
public void testInvalidLatitude() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_LATITUDE_GPX);
}
/**
* Test an invalid longitude.
*/
public void testInvalidLongitude() throws ParserConfigurationException, IOException {
testInvalidGpx(INVALID_LONGITUDE_GPX);
}
private void testInvalidGpx(String xml) throws ParserConfigurationException, IOException {
expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject()))
.andReturn(TRACK_ID_0_URI);
// For the following, use StubReturn since we don't care whether they are
// invoked or not.
expect(myTracksProviderUtils.bulkInsertTrackPoint(
(Location[]) AndroidMock.anyObject(), AndroidMock.anyInt(), AndroidMock.anyLong()))
.andStubReturn(1);
expect(myTracksProviderUtils.getFirstTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0);
myTracksProviderUtils.deleteTrack(TRACK_ID_0);
AndroidMock.replay(myTracksProviderUtils);
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
try {
GpxImporter.importGPXFile(getContext(), inputStream, myTracksProviderUtils,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
} catch (SAXException e) {
// expected
}
AndroidMock.verify(myTracksProviderUtils);
}
private Location createLocation(int index, long time) {
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(TRACK_LATITUDE + index);
location.setLongitude(TRACK_LONGITUDE + index);
location.setAltitude(TRACK_ELEVATION + index);
location.setTime(time);
return location;
}
/**
* Expects the first track point to be added.
*
* @param location the location
* @param trackId the track id
* @param trackPointId the track point id
*/
private void expectFirstTrackPoint(Location location, long trackId, long trackPointId) {
expect(myTracksProviderUtils.bulkInsertTrackPoint(
location != null ? LocationsMatcher.eqLoc(location) : (Location[]) AndroidMock.anyObject(),
eq(1), eq(trackId))).andReturn(1);
expect(myTracksProviderUtils.getFirstTrackPointId(trackId)).andReturn(trackPointId);
expect(myTracksProviderUtils.getLastTrackPointId(trackId)).andReturn(trackPointId);
}
/**
* Expects the track to be updated.
*
* @param track the track
* @param lastTrack true if it is the last track in the gpx
* @param trackId the track id
*/
private void expectUpdateTrack(Capture<Track> track, boolean lastTrack, long trackId) {
myTracksProviderUtils.updateTrack(AndroidMock.capture(track));
expect(myTracksProviderUtils.insertWaypoint((Waypoint) AndroidMock.anyObject()))
.andReturn(WAYPOINT_ID_O_URI);
if (lastTrack) {
// Return null to not add waypoints
expect(myTracksProviderUtils.getTrack(trackId)).andReturn(null);
}
}
private void verifyTrack(Track track, String name, String description, long time) {
assertEquals(name, track.getName());
assertEquals(description, track.getDescription());
if (time != -1L) {
assertEquals(time, track.getTripStatistics().getStartTime());
}
assertNotSame(-1, track.getStartId());
assertNotSame(-1, track.getStopId());
}
/**
* 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,126 @@
/*
* 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.stats.TripStatistics;
import android.location.Location;
import java.util.List;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Tests for {@link KmlTrackWriter}.
*
* @author Rodrigo Damazio
*/
public class KmlTrackWriterTest extends 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(TripStatistics tripStatistics) {
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"));
// There are 3 placemarks - start, track, and end
List<Element> placemarkTags = getChildElements(docTag, "Placemark", 3);
assertTagIsPlacemark(
placemarkTags.get(0), TRACK_NAME + " (Start)", "", location1);
assertTagIsPlacemark(
placemarkTags.get(2), TRACK_NAME + " (End)", FULL_TRACK_DESCRIPTION, location4);
List<Element> folderTag = getChildElements(docTag, "Folder", 1);
List<Element> folderPlacemarkTags = getChildElements(folderTag.get(0), "Placemark", 2);
assertTagIsPlacemark(
folderPlacemarkTags.get(0), WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2);
assertTagIsPlacemark(
folderPlacemarkTags.get(1), WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3);
Element trackPlacemarkTag = placemarkTags.get(1);
assertEquals(TRACK_NAME, getChildTextValue(trackPlacemarkTag, "name"));
assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackPlacemarkTag, "description"));
Element multiTrackTag = getChildElement(trackPlacemarkTag, "gx:MultiTrack");
List<Element> trackTags = getChildElements(multiTrackTag, "gx:Track", 2);
assertTagHasPoints(trackTags.get(0), location1, location2);
assertTagHasPoints(trackTags.get(1), location3, location4);
}
/**
* Asserts that the given tag is a placemark with the given properties.
*
* @param tag the tag
* @param name the expected placemark name
* @param description the expected placemark description
* @param location the expected placemark location
*/
private void assertTagIsPlacemark(
Element tag, String name, String description, Location location) {
assertEquals(name, getChildTextValue(tag, "name"));
if (description != null && !description.equals("")) {
assertEquals(description, getChildTextValue(tag, "description"));
}
Element pointTag = getChildElement(tag, "Point");
String expected = location.getLongitude() + "," + location.getLatitude() + ","
+ location.getAltitude();
String actual = getChildTextValue(pointTag, "coordinates");
assertEquals(expected, actual);
}
/**
* Asserts that the given tag has a list of "gx:coord" subtags matching the
* expected locations.
*
* @param tag the parent tag
* @param locations list of expected locations
*/
private void assertTagHasPoints(Element tag, Location... locations) {
List<Element> coordTags = getChildElements(tag, "gx:coord", locations.length);
for (int i = 0; i < locations.length; i++) {
Location location = locations[i];
String expected = location.getLongitude() + " " + location.getLatitude() + " "
+ location.getAltitude();
String actual = coordTags.get(i).getFirstChild().getTextContent();
assertEquals(expected, actual);
}
}
}
@@ -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,217 @@
// 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.SensorDataSet sensorDataSet = Sensor.SensorDataSet.newBuilder().setPower(power)
.setCadence(cadence).setHeartRate(heartRate).build();
location.setSensorDataSet(sensorDataSet);
}
}
/**
* Makes the right sequence of calls to the writer in order to write the fake
* track in {@link #track}.
*
* @param 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,393 @@
// 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.writeBeginTrack(null);
formatWriter.writeEndTrack(null);
formatWriter.writeFooter();
formatWriter.close();
mocksControl.replay();
writer.writeDocument();
assertTrue(writer.wasSuccess());
mocksControl.verify();
}
/**
* Tests when a track only contains invalid locations. Make sure an empty
* track is written.
*/
public void testWriteDocument_oneInvalidLocation() throws Exception {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
Location[] locs = { new Location("fake0") };
fillLocations(locs);
// Make location invalid
locs[0].setLatitude(100);
assertEquals(locs.length, providerUtils.bulkInsertTrackPoint(locs, locs.length, TRACK_ID));
formatWriter.writeHeader();
formatWriter.writeBeginTrack(null);
formatWriter.writeEndTrack(null);
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.bulkInsertTrackPoint(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,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.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.setTripStatistics(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.setTripStatistics(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();
track.setNumberOfPoints(2);
TripStatistics stats = new TripStatistics();
stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6);
track.setTripStatistics(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.getTrackPointCursor(TRACK_ID, -1L, -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.createTrackPoint(cursorMock)).andReturn(
new Location("1"));
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointCursor(TRACK_ID, -1L, -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.createTrackPoint(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointCursor(TRACK_ID, -1L, -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.createTrackPoint(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointCursor(TRACK_ID, -1L, -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.createTrackPoint(cursorMock))
.andReturn(new Location("1")).times(2);
AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointCursor(TRACK_ID, -1L, -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.getWaypointCursor(TRACK_ID, -1L,
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.getWaypointCursor(TRACK_ID, -1L,
Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), 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.getWaypointCursor(TRACK_ID, -1L,
Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock);
Waypoint waypoint = new Waypoint();
waypoint.setLocation(TrackStubUtils.createMyTracksLocation());
AndroidMock.expect(myTracksProviderUtilsMock.createWaypoint(cursorMock)).andReturn(waypoint)
.times(1);
AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock);
SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock,
sendRequest.getTrackId(), sendRequest.getAccount(), 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,175 @@
/*
* 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 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,
* Location)} with a title.
*/
public void testBuildMapsMarkerFeature_with_title() {
Location location = new Location("test");
location.setLatitude(123.0);
location.setLongitude(456.0);
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
"name", "this\nmap\ndescription", "url", location);
assertEquals(MapsFeature.MARKER, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("name", mapFeature.getTitle());
assertEquals("this<br>map<br>description", mapFeature.getDescription());
assertEquals("url", mapFeature.getIconUrl());
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* Location)} with an empty title.
*/
public void testBuildMapsMarkerFeature_empty_title() {
Location location = new Location("test");
location.setLatitude(123.0);
location.setLongitude(456.0);
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
"", "description", "url", location);
assertEquals(MapsFeature.MARKER, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals("description", mapFeature.getDescription());
assertEquals("url", mapFeature.getIconUrl());
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
}
/**
* Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String,
* Location)} with a null title.
*/
public void testBuildMapsMarkerFeature_null_title() {
Location location = new Location("test");
location.setLatitude(123.0);
location.setLongitude(456.0);
MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature(
null, "description", "url", location);
assertEquals(MapsFeature.MARKER, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals("description", mapFeature.getDescription());
assertEquals("url", mapFeature.getIconUrl());
assertEquals(123.0, mapFeature.getPoint(0).getLatitude());
assertEquals(456.0, mapFeature.getPoint(0).getLongitude());
}
/**
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
* title.
*/
public void testBuildMapsLineFeature_with_title() {
ArrayList<Location> locations = new ArrayList<Location>();
Location location = new Location("test");
location.setLatitude(50.0);
location.setLongitude(100.0);
locations.add(location);
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("name", locations);
assertEquals(MapsFeature.LINE, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("name", mapFeature.getTitle());
assertEquals(0x80FF0000, mapFeature.getColor());
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
}
/**
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with an
* empty title.
*/
public void testBuildMapsLineFeature_empty_title() {
ArrayList<Location> locations = new ArrayList<Location>();
Location location = new Location("test");
location.setLatitude(50.0);
location.setLongitude(100.0);
locations.add(location);
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("", locations);
assertEquals(MapsFeature.LINE, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals(0x80FF0000, mapFeature.getColor());
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
}
/**
* Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a
* null title.
*/
public void testBuildMapsLineFeature_null_title() {
ArrayList<Location> locations = new ArrayList<Location>();
Location location = new Location("test");
location.setLatitude(50.0);
location.setLongitude(100.0);
locations.add(location);
MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature(null, locations);
assertEquals(MapsFeature.LINE, mapFeature.getType());
assertNotNull(mapFeature.getAndroidId());
assertEquals("-", mapFeature.getTitle());
assertEquals(0x80FF0000, mapFeature.getColor());
assertEquals(50.0, mapFeature.getPoint(0).getLatitude());
assertEquals(100.0, mapFeature.getPoint(0).getLongitude());
}
}
@@ -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,124 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.io.sendtogoogle;
/**
* Tests the {@link SendToGoogleUtils}.
*
* @author Youtao Liu
*/
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.Track;
import android.location.Location;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
public class SendToGoogleUtilsTest extends TestCase {
private final static long TRACK_ID = 1L;
private final static String TRACK_CATEGORY = "trackCategory";
private final static String TRACK_NAME = "trackName";
private final static double DIFFERENCE = 0.02;
private final static double INVALID_LATITUDE = 91;
/**
* Tests the method
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)}
* when there is only one location in a segment.
*/
public void testPrepareTrackSegment_onlyOneLocation() {
Track segment = TrackStubUtils.createTrack(1);
assertFalse(SendToGoogleUtils.endSegment(segment, -1L, null));
}
/**
* Tests the method
* {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)} when there
* is no stop time.
*/
public void testPrepareTrackSegment_noStopTime() {
Track segment = TrackStubUtils.createTrack(2);
assertEquals(-1L, segment.getTripStatistics().getStopTime());
ArrayList<Track> tracksArray = new ArrayList<Track>();
assertTrue(SendToGoogleUtils.endSegment(
segment, segment.getLocations().get(1).getTime(), tracksArray));
assertEquals(segment, tracksArray.get(0));
// The stop time should be the time of last location
assertEquals(
segment.getLocations().get(1).getTime(), segment.getTripStatistics().getStopTime());
}
/**
* Tests the method
* {@link SendToGoogleUtils#prepareLocations(Track, java.util.List)} .
*/
public void testPrepareLocations() {
Track trackStub = TrackStubUtils.createTrack(2);
trackStub.setId(TRACK_ID);
trackStub.setName(TRACK_NAME);
trackStub.setCategory(TRACK_CATEGORY);
List<Location> locationsArray = new ArrayList<Location>();
// Adds 100 location to List.
for (int i = 0; i < 100; i++) {
// Use this variable as a flag to make all points in the track can be kept
// after run the LocationUtils#decimate(Track, double) with
// Ramer–Douglas–Peucker algorithm.
double latitude = TrackStubUtils.INITIAL_LATITUDE;
if (i % 2 == 0) {
latitude -= DIFFERENCE * (i % 10);
}
// Inserts 9 points which have wrong latitude, so would have 10 segments.
if (i % 10 == 0 && i > 0) {
MyTracksLocation location = TrackStubUtils.createMyTracksLocation();
location.setLatitude(INVALID_LATITUDE);
locationsArray.add(location);
} else {
locationsArray.add(TrackStubUtils.createMyTracksLocation(latitude,
TrackStubUtils.INITIAL_LONGITUDE + DIFFERENCE * (i % 10),
TrackStubUtils.INITIAL_ALTITUDE + DIFFERENCE * (i % 10)));
}
}
ArrayList<Track> result = SendToGoogleUtils.prepareLocations(trackStub, locationsArray);
assertEquals(10, result.size());
// Checks all segments.
for (int i = 0; i < 10; i++) {
Track segmentOne = result.get(i);
assertEquals(TRACK_ID, segmentOne.getId());
assertEquals(TRACK_NAME, segmentOne.getName());
assertEquals(TRACK_CATEGORY, segmentOne.getCategory());
}
// Checks all locations in the first segment.
for (int j = 0; j < 9; j++) {
double latitude = TrackStubUtils.INITIAL_LATITUDE;
if (j % 2 == 0) {
latitude -= DIFFERENCE * (j % 10);
}
Location oneLocation = result.get(0).getLocations().get(j);
assertEquals(TrackStubUtils.createMyTracksLocation().getAltitude() + DIFFERENCE * (j % 10),
oneLocation.getAltitude());
assertEquals(latitude, oneLocation.getLatitude());
assertEquals(TrackStubUtils.createMyTracksLocation().getLongitude() + DIFFERENCE * (j % 10),
oneLocation.getLongitude());
}
}
}
@@ -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.io.sendtogoogle;
import com.google.android.maps.mytracks.R;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Tests the {@link UploadResultActivity}.
*
* @author Youtao Liu
*/
public class UploadResultActivityTest extends
ActivityInstrumentationTestCase2<UploadResultActivity> {
private UploadResultActivity uploadResultActivity;
private TextView errorFooter;
private TextView successFooter;
private LinearLayout mapsResult;
private LinearLayout fusionTablesResult;
private LinearLayout docsResult;
private ImageView mapsResultIcon;
private ImageView fusionTablesResultIcon;
private ImageView docsResultIcon;
private String successTitle;
private String errorTitle;
/**
* 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);
createDialogAndGetViews();
assertEquals(View.VISIBLE, successFooter.getVisibility());
assertEquals(View.GONE, errorFooter.getVisibility());
assertEquals(View.VISIBLE, mapsResult.getVisibility());
assertEquals(View.VISIBLE, fusionTablesResult.getVisibility());
assertEquals(View.VISIBLE, docsResult.getVisibility());
assertEquals(successTitle, mapsResultIcon.getContentDescription());
assertEquals(successTitle, fusionTablesResultIcon.getContentDescription());
assertEquals(successTitle, docsResultIcon.getContentDescription());
}
/**
* 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);
createDialogAndGetViews();
assertEquals(View.GONE, successFooter.getVisibility());
assertEquals(View.VISIBLE, errorFooter.getVisibility());
assertEquals(View.VISIBLE, mapsResult.getVisibility());
assertEquals(View.VISIBLE, fusionTablesResult.getVisibility());
assertEquals(View.VISIBLE, docsResult.getVisibility());
assertEquals(errorTitle, mapsResultIcon.getContentDescription());
assertEquals(errorTitle, fusionTablesResultIcon.getContentDescription());
assertEquals(errorTitle, docsResultIcon.getContentDescription());
}
/**
* 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);
createDialogAndGetViews();
assertEquals(View.VISIBLE, errorFooter.getVisibility());
assertEquals(View.VISIBLE, mapsResult.getVisibility());
assertEquals(View.GONE, fusionTablesResult.getVisibility());
assertEquals(View.VISIBLE, docsResult.getVisibility());
assertEquals(successTitle, mapsResultIcon.getContentDescription());
assertEquals(errorTitle, docsResultIcon.getContentDescription());
}
/**
* Initials 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();
successTitle = uploadResultActivity.getString(R.string.generic_success_title);
errorTitle = uploadResultActivity.getString(R.string.generic_error_title);
}
/**
* Creates result dialog and gets views in the dialog.
*/
private void createDialogAndGetViews() {
uploadResultActivity.onCreateDialog(UploadResultActivity.DIALOG_RESULT_ID);
View view = uploadResultActivity.view;
errorFooter = (TextView) view.findViewById(R.id.upload_result_error_footer);
successFooter = (TextView) view.findViewById(R.id.upload_result_success_footer);
mapsResult = (LinearLayout) view.findViewById(R.id.upload_result_maps_result);
fusionTablesResult = (LinearLayout) view.findViewById(R.id.upload_result_fusion_tables_result);
docsResult = (LinearLayout) view.findViewById(R.id.upload_result_docs_result);
mapsResultIcon = (ImageView) view.findViewById(R.id.upload_result_maps_result_icon);
fusionTablesResultIcon = (ImageView) view
.findViewById(R.id.upload_result_fusion_tables_result_icon);
docsResultIcon = (ImageView) view.findViewById(R.id.upload_result_docs_result_icon);
}
}
@@ -0,0 +1,116 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.test.AndroidTestCase;
/**
* Tests for the {@link DynamicSpeedTrackPathDescriptor}.
*
* @author Youtao Liu
*/
public class DynamicSpeedTrackPathDescriptorTest extends AndroidTestCase {
private Context context;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
}
/**
* Tests the method {@link DynamicSpeedTrackPathDescriptor#getSpeedMargin()}
* with zero, normal and illegal value.
*/
public void testGetSpeedMargin() {
// The default value of speedMargin is 25.
int[] expectations = { 0, 50, 99, 25 };
// Test
for (int i = 0; i < expectations.length; i++) {
PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, expectations[i]);
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
assertEquals(expectations[i], dynamicSpeedTrackPathDescriptor.getSpeedMargin());
}
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#getSlowSpeed()}.
*/
public void testGetSlowSpeed() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
assertEquals(45, dynamicSpeedTrackPathDescriptor.getSlowSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#getNormalSpeed()}.
*/
public void testGetNormalSpeed() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
assertEquals(55, dynamicSpeedTrackPathDescriptor.getNormalSpeed());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#updateState()} 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.updateState());
}
/**
* Tests {@link DynamicSpeedTrackPathDescriptor#updateState()} by different
* averageMovingSpeed.
*/
public void testIsDiffereceSignificant() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
double[] averageMovingSpeeds = { 0, 30, 30, 30 };
double[] newAverageMovingSpeed = { 20, 30,
// Difference is less than CRITICAL_DIFFERENCE_PERCENTAGE
30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100) / 2),
// Difference is more than CRITICAL_DIFFERENCE_PERCENTAGE
30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100.00) * 2) };
boolean[] expectedValues = { true, false, false, true };
double[] expectedAverageMovingSpeed = { 0, 30, 30, 30 };
// Test
for (int i = 0; i < newAverageMovingSpeed.length; i++) {
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(averageMovingSpeeds[i]);
assertEquals(expectedValues[i], dynamicSpeedTrackPathDescriptor.isDifferenceSignificant(
averageMovingSpeeds[i], newAverageMovingSpeed[i]));
assertEquals(expectedAverageMovingSpeed[i],
dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed());
}
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.test.AndroidTestCase;
/**
* Tests for the {@link DynamicSpeedTrackPathDescriptor}.
*
* @author Youtao Liu
*/
public class FixedSpeedTrackPathDescriptorTest extends AndroidTestCase {
private Context context;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
}
/**
* 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 FixedSpeedTrackPathDescriptor#getSlowSpeed()} and
* {@link FixedSpeedTrackPathDescriptor#getNormalSpeed()}.
*/
public void testGetSpeed() {
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);
assertEquals(slowSpeed, fixedSpeedTrackPathDescriptor.getSlowSpeed());
assertEquals(normalSpeed, fixedSpeedTrackPathDescriptor.getNormalSpeed());
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.maps;
import android.content.Context;
import android.test.AndroidTestCase;
/**
* Tests for the {@link MultiColorTrackPath}.
*
* @author Youtao Liu
*/
public class MultiColorTrackPathTest extends AndroidTestCase {
private MultiColorTrackPath multiColorTrackPath;
private Context context;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
}
/**
* Tests the {@link MultiColorTrackPath#getColor(int)} when use dynamic speed
* track path descriptor.
*/
public void testGetColor_DynamicSpeedTrackPathDescriptor() {
DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor(
context);
dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50);
dynamicSpeedTrackPathDescriptor.setSpeedMargin(10);
multiColorTrackPath = new MultiColorTrackPath(context, dynamicSpeedTrackPathDescriptor);
// Slow speed should be below 45 (10% of 50), and fast speed should be above
// 55 (10% of 50).
assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(5));
assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(44));
assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(50));
assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(54));
assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(56));
assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(100));
assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getNormalColor());
assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getFastColor());
}
}
@@ -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,793 @@
/*
* 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.Waypoint.WaypointType;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.test.RenamingDelegatingContext;
import android.test.ServiceTestCase;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.mock.MockCursor;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Tests for the MyTracks track recording service.
*
* @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);
MockContentProvider googleSettingsProvider = new MockContentProvider(context) {
@Override
public Bundle call(String method, String arg, Bundle extras) {
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
MockCursor mockCursor = new MockCursor() {
@Override
public int getCount() {
return 1;
}
@Override
public boolean moveToNext() {
return true;
}
@Override
public String getString(int columnIndex) {
return MyTracksLocationManager.USE_LOCATION_FOR_SERVICES_ON;
}
@Override
public void close() {}
};
return mockCursor;
}
};
mockContentResolver.addProvider("com.google.settings", googleSettingsProvider);
// Set the context
setContext(context);
providerUtils = MyTracksProviderUtils.Factory.get(context);
SharedPreferences sharedPreferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
// Let's use default values.
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear());
// Disable auto resume by default.
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, 0);
// No recording track.
PreferencesUtils.setLong(
context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
}
@SmallTest
public void testStartable() {
startService(createStartIntent());
assertNotNull(getService());
}
@MediumTest
public void testBindable() {
IBinder service = bindService(createStartIntent());
assertNotNull(service);
}
@MediumTest
public void testResumeAfterReboot_shouldResume() throws Exception {
// Insert a dummy track and mark it as recording track.
createDummyTrack(123L, System.currentTimeMillis(), true);
// Clear the number of attempts and set the timeout to 10 min.
updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT,
PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT);
// Start the service in "resume" mode (simulates the on-reboot action).
Intent startIntent = createStartIntent();
startIntent.putExtra(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());
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
assertEquals(-1L, waypointId);
}
@MediumTest
public void testInsertStatisticsMarker_validLocation() throws Exception {
createDummyTrack(123L, -1L, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
assertFalse(service.isPaused());
insertLocation(service);
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
assertEquals(2, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS));
Waypoint wpt = providerUtils.getWaypoint(2);
assertEquals(getContext().getString(R.string.marker_statistics_icon_url), wpt.getIcon());
assertEquals(getContext().getString(R.string.marker_split_name_format, 1), wpt.getName());
assertEquals(WaypointType.STATISTICS, wpt.getType());
assertEquals(123L, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNotNull(wpt.getTripStatistics());
// TODO check the rest of the params.
// TODO: Check waypoint 2.
}
@MediumTest
public void testInsertWaypointMarker_noRecordingTrack() throws Exception {
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
assertEquals(-1L, waypointId);
}
@MediumTest
public void testInsertWaypointMarker_validWaypoint() throws Exception {
createDummyTrack(123L, -1L, true);
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertTrue(service.isRecording());
insertLocation(service);
assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT));
Waypoint wpt = providerUtils.getWaypoint(1);
assertEquals(getContext().getString(R.string.marker_waypoint_icon_url),
wpt.getIcon());
assertEquals(getContext().getString(R.string.marker_name_format, 1), wpt.getName());
assertEquals(WaypointType.WAYPOINT, wpt.getType());
assertEquals(123L, wpt.getTrackId());
assertEquals(0.0, wpt.getLength());
assertNotNull(wpt.getLocation());
assertNull(wpt.getTripStatistics());
}
@MediumTest
public void testWithProperties_voiceFrequencyDefault() throws Exception {
PreferencesUtils.setInt(context, R.string.voice_frequency_key,
PreferencesUtils.VOICE_FREQUENCY_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_voiceFrequencyByDistance() throws Exception {
PreferencesUtils.setInt(context, R.string.voice_frequency_key, -1);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_voiceFrequencyByTime() throws Exception {
PreferencesUtils.setInt(context, R.string.voice_frequency_key, 1);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_maxRecordingDistanceDefault() throws Exception {
PreferencesUtils.setInt(context, R.string.max_recording_distance_key,
PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_maxRecordingDistance() throws Exception {
PreferencesUtils.setInt(context, R.string.max_recording_distance_key, 50);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_minRecordingDistanceDefault() throws Exception {
PreferencesUtils.setInt(context, R.string.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, PreferencesUtils.SENSOR_TYPE_DEFAULT);
fullRecordingSession();
}
@MediumTest
public void testWithProperties_sensorTypeZephyr() throws Exception {
PreferencesUtils.setString(
context, R.string.sensor_type_key, context.getString(R.string.sensor_type_value_zephyr));
fullRecordingSession();
}
private ITrackRecordingService bindAndGetService(Intent intent) {
ITrackRecordingService service = ITrackRecordingService.Stub.asInterface(
bindService(intent));
assertNotNull(service);
return service;
}
private Track createDummyTrack(long id, long stopTime, boolean isRecording) {
Track dummyTrack = new Track();
dummyTrack.setId(id);
dummyTrack.setName("Dummy Track");
TripStatistics tripStatistics = new TripStatistics();
tripStatistics.setStopTime(stopTime);
dummyTrack.setTripStatistics(tripStatistics);
addTrack(dummyTrack, isRecording);
return dummyTrack;
}
private void updateAutoResumePrefs(int attempts, int timeoutMins) {
PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts);
PreferencesUtils.setInt(context, R.string.auto_resume_track_timeout_key, timeoutMins);
}
private Intent createStartIntent() {
Intent startIntent = new Intent();
startIntent.setClass(context, TrackRecordingService.class);
return startIntent;
}
private void addTrack(Track track, boolean isRecording) {
assertTrue(track.getId() >= 0);
providerUtils.insertTrack(track);
assertEquals(track.getId(), providerUtils.getTrack(track.getId()).getId());
PreferencesUtils.setLong(context, R.string.recording_track_id_key, isRecording ? track.getId()
: PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording);
}
private void fullRecordingSession() throws Exception {
ITrackRecordingService service = bindAndGetService(createStartIntent());
assertFalse(service.isRecording());
// Start a track.
long id = service.startNewTrack();
assertTrue(id >= 0);
assertTrue(service.isRecording());
Track track = providerUtils.getTrack(id);
assertNotNull(track);
assertEquals(id, track.getId());
assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key));
assertEquals(id, service.getRecordingTrackId());
// Insert a few points, markers and statistics.
long startTime = System.currentTimeMillis();
for (int i = 0; i < 30; i++) {
Location loc = new Location("gps");
loc.setLongitude(35.0f + i / 10.0f);
loc.setLatitude(45.0f - i / 5.0f);
loc.setAccuracy(5);
loc.setSpeed(10);
loc.setTime(startTime + i * 10000);
loc.setBearing(3.0f);
service.insertTrackPoint(loc);
if (i % 10 == 0) {
service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS);
} else if (i % 7 == 0) {
service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT);
}
}
// Stop the track. Validate if it has correct data.
service.endCurrentTrack();
assertFalse(service.isRecording());
assertEquals(-1L, service.getRecordingTrackId());
track = providerUtils.getTrack(id);
assertNotNull(track);
assertEquals(id, track.getId());
TripStatistics tripStatistics = track.getTripStatistics();
assertNotNull(tripStatistics);
assertTrue(tripStatistics.getStartTime() > 0);
assertTrue(tripStatistics.getStopTime() >= tripStatistics.getStartTime());
}
/**
* Inserts a location and waits for 100ms.
*
* @param trackRecordingService the track recording service
*/
private void insertLocation(ITrackRecordingService trackRecordingService)
throws RemoteException, InterruptedException {
Location location = new Location("gps");
location.setLongitude(35.0f);
location.setLatitude(45.0f);
location.setAccuracy(5);
location.setSpeed(10);
location.setTime(System.currentTimeMillis());
location.setBearing(3.0f);
trackRecordingService.insertTrackPoint(location);
Thread.sleep(200);
}
}
@@ -0,0 +1,69 @@
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import junit.framework.TestCase;
public class PolarMessageParserTest extends TestCase {
PolarMessageParser parser = new PolarMessageParser();
// A complete and valid Polar HxM packet
// FE08F701D1001104FE08F702D1001104
private final byte[] originalBuf =
{(byte) 0xFE, 0x08, (byte) 0xF7, 0x01, (byte) 0xD1, 0x00, 0x11, 0x04, (byte) 0xFE, 0x08,
(byte) 0xF7, 0x02, (byte) 0xD1, 0x00, 0x11, 0x04};
private byte[] buf;
public void setUp() {
buf = ApiAdapterFactory.getApiAdapter().copyByteArray(originalBuf, 0, originalBuf.length);
}
public void testIsValid() {
assertTrue(parser.isValid(buf));
}
public void testIsValid_invalidHeader() {
// Invalidate header.
buf[0] = 0x03;
assertFalse(parser.isValid(buf));
}
public void testIsValid_invalidCheckbyte() {
// Invalidate checkbyte.
buf[2] = 0x03;
assertFalse(parser.isValid(buf));
}
public void testIsValid_invalidSequence() {
// Invalidate sequence.
buf[3] = 0x11;
assertFalse(parser.isValid(buf));
}
public void testParseBuffer() {
buf[5] = 70;
Sensor.SensorDataSet sds = parser.parseBuffer(buf);
assertTrue(sds.hasHeartRate());
assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING);
assertEquals(70, sds.getHeartRate().getValue());
}
public void testFindNextAlignment_offset() {
// The first 4 bytes are garbage
buf = new byte[originalBuf.length + 4];
buf[0] = 4;
buf[1] = 2;
buf[2] = 4;
buf[3] = 2;
// Then the valid message.
System.arraycopy(originalBuf, 0, buf, 4, originalBuf.length);
assertEquals(4, parser.findNextAlignment(buf));
}
public void testFindNextAlignment_invalid() {
buf[0] = 0;
assertEquals(-1, parser.findNextAlignment(buf));
}
}
@@ -0,0 +1,47 @@
package com.google.android.apps.mytracks.services.sensors;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
public class SensorManagerFactoryTest extends AndroidTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
SharedPreferences sharedPreferences = getContext().getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
// Let's use default values.
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear());
}
@SmallTest
public void testDefaultSettings() throws Exception {
assertNull(SensorManagerFactory.getSystemSensorManager(getContext()));
}
@SmallTest
public void testCreateZephyr() throws Exception {
assertClassForName(ZephyrSensorManager.class, R.string.sensor_type_value_zephyr);
}
@SmallTest
public void testCreatePolar() throws Exception {
assertClassForName(PolarSensorManager.class, R.string.sensor_type_value_polar);
}
private void assertClassForName(Class<?> c, int i) {
PreferencesUtils.setString(getContext(), R.string.sensor_type_key, getContext().getString(i));
SensorManager sm = SensorManagerFactory.getSystemSensorManager(getContext());
assertNotNull(sm);
assertTrue(c.isInstance(sm));
SensorManagerFactory.releaseSystemSensorManager();
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.sensors;
import junit.framework.TestCase;
/**
* @author Dominik Rottsches
*/
public class StrideReadingsTest extends TestCase {
public void testNoReadingOnStartup() {
StrideReadings strideReadings = new StrideReadings();
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
}
public void testAverageCadenceAvailable() {
StrideReadings strideReadings = new StrideReadings();
// 2 steps / second => Cadence is 120 / minute
for (int i = 1; i <= 30; i++) {
strideReadings.updateStrideReading(i*2);
if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) {
assertEquals(120, strideReadings.getCadence());
} else {
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
}
}
}
/**
* Tests for correct calculation after rolling over at 128 strides,
* just like the HxM seems to do it.
*/
public void testRollover() {
StrideReadings strideReadings = new StrideReadings();
// 1 step per second => Cadence is 60 / minute
// Updating readings counting upwards from initialStrides -
// initialStrides set to a value below 128 to ensure rollover.
int initialStrides = 128 - StrideReadings.NUM_READINGS_FOR_AVERAGE - 5;
for (int i = 1; i <= StrideReadings.NUM_READINGS_FOR_AVERAGE + 10; i++) {
strideReadings.updateStrideReading((initialStrides + i) % 128);
if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) {
assertEquals(60, strideReadings.getCadence());
} else {
assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence());
}
}
}
}
@@ -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,33 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.tasks;
import android.test.AndroidTestCase;
/**
* Tests for {@link AnnouncementPeriodicTaskFactory}.
* These tests require Donut+ to run.
*
* @author Rodrigo Damazio
*/
public class AnnouncementPeriodicTaskFactoryTest extends AndroidTestCase {
public void testCreate() {
PeriodicTaskFactory factory = new AnnouncementPeriodicTaskFactory();
PeriodicTask task = factory.create(getContext());
assertTrue(task instanceof AnnouncementPeriodicTask);
}
}
@@ -0,0 +1,533 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.tasks;
import static com.google.android.testing.mocking.AndroidMock.capture;
import static com.google.android.testing.mocking.AndroidMock.eq;
import static com.google.android.testing.mocking.AndroidMock.expect;
import static com.google.android.testing.mocking.AndroidMock.same;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import org.easymock.Capture;
import org.easymock.EasyMock;
/**
* Tests for {@link AnnouncementPeriodicTask}.
* WARNING: I'm not responsible if your eyes start bleeding while reading this
* code. You have been warned. It's still better than no test, though.
*
* @author Rodrigo Damazio
*/
public class AnnouncementPeriodicTaskTest extends AndroidTestCase {
// Use something other than our hardcoded value
private static final Locale DEFAULT_LOCALE = Locale.KOREAN;
private static final String ANNOUNCEMENT = "I can haz cheeseburger?";
private Locale oldDefaultLocale;
private AnnouncementPeriodicTask task;
private AnnouncementPeriodicTask mockTask;
private Capture<OnInitListener> initListenerCapture;
private Capture<PhoneStateListener> phoneListenerCapture;
private TextToSpeechDelegate ttsDelegate;
private TextToSpeechInterface tts;
/**
* Mockable interface that we delegate TTS calls to.
*/
interface TextToSpeechInterface {
int addEarcon(String earcon, String packagename, int resourceId);
int addEarcon(String earcon, String filename);
int addSpeech(String text, String packagename, int resourceId);
int addSpeech(String text, String filename);
boolean areDefaultsEnforced();
String getDefaultEngine();
Locale getLanguage();
int isLanguageAvailable(Locale loc);
boolean isSpeaking();
int playEarcon(String earcon, int queueMode,
HashMap<String, String> params);
int playSilence(long durationInMs, int queueMode,
HashMap<String, String> params);
int setEngineByPackageName(String enginePackageName);
int setLanguage(Locale loc);
int setOnUtteranceCompletedListener(OnUtteranceCompletedListener listener);
int setPitch(float pitch);
int setSpeechRate(float speechRate);
void shutdown();
int speak(String text, int queueMode, HashMap<String, String> params);
int stop();
int synthesizeToFile(String text, HashMap<String, String> params,
String filename);
}
/**
* Subclass of {@link TextToSpeech} which delegates calls to the interface
* above.
* The logic here is stupid and the author is ashamed of having to write it
* like this, but basically the issue is that TextToSpeech cannot be mocked
* without running its constructor, its constructor runs async operations
* which call other methods (and then if the methods are part of a mock we'd
* have to set a behavior, but we can't 'cause the object hasn't been fully
* built yet).
* The logic is that calls made during the constructor (when tts is not yet
* set) will go up to the original class, but after tts is set we'll forward
* them all to the mock.
*/
private class TextToSpeechDelegate
extends TextToSpeech implements TextToSpeechInterface {
public TextToSpeechDelegate(Context context, OnInitListener listener) {
super(context, listener);
}
@Override
public int addEarcon(String earcon, String packagename, int resourceId) {
if (tts == null) {
return super.addEarcon(earcon, packagename, resourceId);
}
return tts.addEarcon(earcon, packagename, resourceId);
}
@Override
public int addEarcon(String earcon, String filename) {
if (tts == null) {
return super.addEarcon(earcon, filename);
}
return tts.addEarcon(earcon, filename);
}
@Override
public int addSpeech(String text, String packagename, int resourceId) {
if (tts == null) {
return super.addSpeech(text, packagename, resourceId);
}
return tts.addSpeech(text, packagename, resourceId);
}
@Override
public int addSpeech(String text, String filename) {
if (tts == null) {
return super.addSpeech(text, filename);
}
return tts.addSpeech(text, filename);
}
@Override
public Locale getLanguage() {
if (tts == null) {
return super.getLanguage();
}
return tts.getLanguage();
}
@Override
public int isLanguageAvailable(Locale loc) {
if (tts == null) {
return super.isLanguageAvailable(loc);
}
return tts.isLanguageAvailable(loc);
}
@Override
public boolean isSpeaking() {
if (tts == null) {
return super.isSpeaking();
}
return tts.isSpeaking();
}
@Override
public int playEarcon(String earcon, int queueMode,
HashMap<String, String> params) {
if (tts == null) {
return super.playEarcon(earcon, queueMode, params);
}
return tts.playEarcon(earcon, queueMode, params);
}
@Override
public int playSilence(long durationInMs, int queueMode,
HashMap<String, String> params) {
if (tts == null) {
return super.playSilence(durationInMs, queueMode, params);
}
return tts.playSilence(durationInMs, queueMode, params);
}
@Override
public int setLanguage(Locale loc) {
if (tts == null) {
return super.setLanguage(loc);
}
return tts.setLanguage(loc);
}
@Override
public int setOnUtteranceCompletedListener(
OnUtteranceCompletedListener listener) {
if (tts == null) {
return super.setOnUtteranceCompletedListener(listener);
}
return tts.setOnUtteranceCompletedListener(listener);
}
@Override
public int setPitch(float pitch) {
if (tts == null) {
return super.setPitch(pitch);
}
return tts.setPitch(pitch);
}
@Override
public int setSpeechRate(float speechRate) {
if (tts == null) {
return super.setSpeechRate(speechRate);
}
return tts.setSpeechRate(speechRate);
}
@Override
public void shutdown() {
if (tts == null) {
super.shutdown();
return;
}
tts.shutdown();
}
@Override
public int speak(
String text, int queueMode, HashMap<String, String> params) {
if (tts == null) {
return super.speak(text, queueMode, params);
}
return tts.speak(text, queueMode, params);
}
@Override
public int stop() {
if (tts == null) {
return super.stop();
}
return tts.stop();
}
@Override
public int synthesizeToFile(String text, HashMap<String, String> params,
String filename) {
if (tts == null) {
return super.synthesizeToFile(text, params, filename);
}
return tts.synthesizeToFile(text, params, filename);
}
}
@UsesMocks({
AnnouncementPeriodicTask.class,
StringUtils.class,
})
@Override
protected void setUp() throws Exception {
super.setUp();
oldDefaultLocale = Locale.getDefault();
Locale.setDefault(DEFAULT_LOCALE);
// Eww, the effort required just to mock TextToSpeech is insane
final AtomicBoolean listenerCalled = new AtomicBoolean();
OnInitListener blockingListener = new OnInitListener() {
@Override
public void onInit(int status) {
synchronized (this) {
listenerCalled.set(true);
notify();
}
}
};
ttsDelegate = new TextToSpeechDelegate(getContext(), blockingListener);
// Wait for all async operations done in the constructor to finish.
synchronized (blockingListener) {
while (!listenerCalled.get()) {
// Releases the synchronized lock until we're woken up.
blockingListener.wait();
}
}
// Phew, done, now we can start forwarding calls
tts = AndroidMock.createMock(TextToSpeechInterface.class);
initListenerCapture = new Capture<OnInitListener>();
phoneListenerCapture = new Capture<PhoneStateListener>();
// Create a partial forwarding mock
mockTask = AndroidMock.createMock(AnnouncementPeriodicTask.class, getContext());
task = new AnnouncementPeriodicTask(getContext()) {
@Override
protected TextToSpeech newTextToSpeech(Context ctx,
OnInitListener onInitListener) {
return mockTask.newTextToSpeech(ctx, onInitListener);
}
@Override
protected String getAnnouncement(TripStatistics stats) {
return mockTask.getAnnouncement(stats);
}
@Override
protected void listenToPhoneState(
PhoneStateListener listener, int events) {
mockTask.listenToPhoneState(listener, events);
}
};
}
@Override
protected void tearDown() {
Locale.setDefault(oldDefaultLocale);
}
public void testStart() {
doStart();
OnInitListener ttsInitListener = initListenerCapture.getValue();
assertNotNull(ttsInitListener);
AndroidMock.replay(tts);
ttsInitListener.onInit(TextToSpeech.SUCCESS);
AndroidMock.verify(mockTask, tts);
}
public void testStart_notReady() {
doStart();
OnInitListener ttsInitListener = initListenerCapture.getValue();
assertNotNull(ttsInitListener);
AndroidMock.replay(tts);
ttsInitListener.onInit(TextToSpeech.ERROR);
AndroidMock.verify(mockTask, tts);
}
public void testShutdown() {
// First, start
doStart();
AndroidMock.verify(mockTask);
AndroidMock.reset(mockTask);
// Then, shut down
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
mockTask.listenToPhoneState(
same(phoneListener), eq(PhoneStateListener.LISTEN_NONE));
tts.shutdown();
AndroidMock.replay(mockTask, tts);
task.shutdown();
AndroidMock.verify(mockTask, tts);
}
public void testRun() throws Exception {
// Expect service data calls
TripStatistics stats = new TripStatistics();
// Expect announcement building call
expect(mockTask.getAnnouncement(same(stats))).andStubReturn(ANNOUNCEMENT);
// Put task in "ready" state
startTask(TextToSpeech.SUCCESS);
expect(tts.isLanguageAvailable(DEFAULT_LOCALE)).andStubReturn(TextToSpeech.LANG_AVAILABLE);
expect(tts.setLanguage(DEFAULT_LOCALE)).andReturn(TextToSpeech.LANG_AVAILABLE);
expect(tts.setSpeechRate(AnnouncementPeriodicTask.TTS_SPEECH_RATE)).andReturn(
TextToSpeech.SUCCESS);
expect(tts.setOnUtteranceCompletedListener((OnUtteranceCompletedListener) EasyMock.anyObject()))
.andReturn(0);
// Expect actual announcement call
expect(
tts.speak(eq(ANNOUNCEMENT), eq(TextToSpeech.QUEUE_FLUSH),
eq(AnnouncementPeriodicTask.SPEECH_PARAMS))).andReturn(0);
// Run the announcement
AndroidMock.replay(tts);
task.announce(stats);
AndroidMock.verify(mockTask, tts);
}
public void testRun_notReady() throws Exception {
// Put task in "not ready" state
startTask(TextToSpeech.ERROR);
// Run the announcement
AndroidMock.replay(tts);
task.run(null);
AndroidMock.verify(mockTask, tts);
}
public void testRun_duringCall() throws Exception {
startTask(TextToSpeech.SUCCESS);
expect(tts.isSpeaking()).andStubReturn(false);
// Run the announcement
AndroidMock.replay(tts);
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, null);
task.run(null);
AndroidMock.verify(mockTask, tts);
}
public void testRun_ringWhileSpeaking() throws Exception {
startTask(TextToSpeech.SUCCESS);
expect(tts.isSpeaking()).andStubReturn(true);
expect(tts.stop()).andReturn(TextToSpeech.SUCCESS);
AndroidMock.replay(tts);
// Update the state to ringing - this should stop the current announcement.
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
// Run the announcement - this should do nothing.
task.run(null);
AndroidMock.verify(mockTask, tts);
}
public void testRun_whileRinging() throws Exception {
startTask(TextToSpeech.SUCCESS);
expect(tts.isSpeaking()).andStubReturn(false);
// Run the announcement
AndroidMock.replay(tts);
PhoneStateListener phoneListener = phoneListenerCapture.getValue();
phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null);
task.run(null);
AndroidMock.verify(mockTask, tts);
}
public void testRun_noService() throws Exception {
startTask(TextToSpeech.SUCCESS);
// Run the announcement
AndroidMock.replay(tts);
task.run(null);
AndroidMock.verify(mockTask, tts);
}
public void testRun_noStats() throws Exception {
// Expect service data calls
startTask(TextToSpeech.SUCCESS);
// Run the announcement
AndroidMock.replay(tts);
task.run(null);
AndroidMock.verify(mockTask, tts);
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time zero.
*/
public void testGetAnnounceTime_time_zero() {
long time = 0; // 0 seconds
assertEquals("0 minutes 0 seconds", task.getAnnounceTime(time));
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time one.
*/
public void testGetAnnounceTime_time_one() {
long time = 1 * 1000; // 1 second
assertEquals("0 minutes 1 second", task.getAnnounceTime(time));
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
* numbers with the hour unit.
*/
public void testGetAnnounceTime_singular_has_hour() {
long time = (1 * 60 * 60 * 1000) + (1 * 60 * 1000) + (1 * 1000); // 1 hour 1 minute 1 second
assertEquals("1 hour 1 minute 1 second", task.getAnnounceTime(time));
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
* with the hour unit.
*/
public void testGetAnnounceTime_plural_has_hour() {
long time = (2 * 60 * 60 * 1000) + (2 * 60 * 1000) + (2 * 1000); // 2 hours 2 minutes 2 seconds
assertEquals("2 hours 2 minutes 2 seconds", task.getAnnounceTime(time));
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular
* numbers without the hour unit.
*/
public void testGetAnnounceTime_singular_no_hour() {
long time = (1 * 60 * 1000) + (1 * 1000); // 1 minute 1 second
assertEquals("1 minute 1 second", task.getAnnounceTime(time));
}
/**
* Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers
* without the hour unit.
*/
public void testGetAnnounceTime_plural_no_hour() {
long time = (2 * 60 * 1000) + (2 * 1000); // 2 minutes 2 seconds
assertEquals("2 minutes 2 seconds", task.getAnnounceTime(time));
}
private void startTask(int state) {
AndroidMock.resetToNice(tts);
AndroidMock.replay(tts);
doStart();
OnInitListener ttsInitListener = initListenerCapture.getValue();
ttsInitListener.onInit(state);
AndroidMock.resetToDefault(tts);
}
private void doStart() {
mockTask.listenToPhoneState(capture(phoneListenerCapture),
eq(PhoneStateListener.LISTEN_CALL_STATE));
expect(mockTask.newTextToSpeech(
same(getContext()), capture(initListenerCapture)))
.andStubReturn(ttsDelegate);
AndroidMock.replay(mockTask);
task.start();
}
}
@@ -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,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,221 @@
// Copyright 2009 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.stats;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import android.location.Location;
import junit.framework.TestCase;
/**
* Tests {@link TripStatisticsUpdater}.
*
* @author Sandor Dornbush
*/
public class TripStatisticsUpdaterTest extends TestCase {
private static final long ONE_SECOND = 1000;
private static final long TEN_SECONDS = 10 * ONE_SECOND;
private TripStatisticsUpdater tripStatisticsUpdater = null;
@Override
protected void setUp() throws Exception {
tripStatisticsUpdater = new TripStatisticsUpdater(System.currentTimeMillis());
}
public void testAddLocationSimple() throws Exception {
long startTime = 1000;
tripStatisticsUpdater = new TripStatisticsUpdater(startTime);
TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics();
assertEquals(0.0, tripStatisticsUpdater.getSmoothedElevation());
assertEquals(Double.POSITIVE_INFINITY, tripStatistics.getMinElevation());
assertEquals(Double.NEGATIVE_INFINITY, tripStatistics.getMaxElevation());
assertEquals(0.0, tripStatistics.getMaxSpeed());
assertEquals(Double.POSITIVE_INFINITY, tripStatistics.getMinGrade());
assertEquals(Double.NEGATIVE_INFINITY, tripStatistics.getMaxGrade());
assertEquals(0.0, tripStatistics.getTotalElevationGain());
assertEquals(0, tripStatistics.getMovingTime());
assertEquals(0.0, tripStatistics.getTotalDistance());
float speed = 11.1f;
for (int i = 0; i < 100; i++) {
Location location = new Location("test");
location.setAccuracy(1.0f);
location.setLongitude(45.0);
// Going up by 1 meter each time.
location.setAltitude(i);
// Moving by .001 degree latitude (111 meters)
location.setLatitude(i * .001);
location.setSpeed(speed);
// Each time slice is 10 seconds.
location.setTime(startTime + i * TEN_SECONDS);
tripStatisticsUpdater.addLocation(location, PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
tripStatistics = tripStatisticsUpdater.getTripStatistics();
assertEquals(i * TEN_SECONDS, tripStatistics.getTotalTime());
assertEquals(i * TEN_SECONDS, tripStatistics.getMovingTime());
assertEquals(i, tripStatisticsUpdater.getSmoothedElevation(),
Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(0.0, tripStatistics.getMinElevation());
assertEquals(i, tripStatistics.getMaxElevation(), Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(i, tripStatistics.getTotalElevationGain(), Constants.ELEVATION_SMOOTHING_FACTOR);
if (i >= Constants.SPEED_SMOOTHING_FACTOR) {
assertEquals(speed, tripStatistics.getMaxSpeed(), 0.1);
}
if (i >= Constants.DISTANCE_SMOOTHING_FACTOR && i >= Constants.ELEVATION_SMOOTHING_FACTOR) {
// 1 m / 111 m = .009
assertEquals(0.009, tripStatistics.getMinGrade(), 0.0001);
assertEquals(0.009, tripStatistics.getMaxGrade(), 0.0001);
}
assertEquals(i * 111.0, tripStatistics.getTotalDistance(), 100);
}
}
/**
* Tests {@link TripStatisticsUpdater#updateElevation(double)} with constant
* elevations.
*/
public void testElevationSimple() throws Exception {
for (double elevation = 0; elevation < 1000; elevation += 10) {
tripStatisticsUpdater = new TripStatisticsUpdater(System.currentTimeMillis());
for (int i = 0; i < 100; i++) {
assertEquals(0.0, tripStatisticsUpdater.updateElevation(elevation));
assertEquals(elevation, tripStatisticsUpdater.getSmoothedElevation());
TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics();
assertEquals(elevation, tripStatistics.getMinElevation());
assertEquals(elevation, tripStatistics.getMaxElevation());
assertEquals(0.0, tripStatistics.getTotalElevationGain());
}
}
}
/**
* Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with
* elevation gain.
*/
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, tripStatisticsUpdater.updateElevation(i));
assertEquals(i, tripStatisticsUpdater.getSmoothedElevation(),
Constants.ELEVATION_SMOOTHING_FACTOR / 2);
TripStatistics data = tripStatisticsUpdater.getTripStatistics();
assertEquals(0.0, data.getMinElevation());
assertEquals(i, data.getMaxElevation(), Constants.ELEVATION_SMOOTHING_FACTOR / 2);
assertEquals(i, data.getTotalElevationGain(), Constants.ELEVATION_SMOOTHING_FACTOR);
}
}
/**
* Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with grade
* of 1 and -1.
*/
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
* elevation buffer.
*/
tripStatisticsUpdater.updateElevation(i);
tripStatisticsUpdater.updateGrade(100, 100);
if (i >= Constants.GRADE_SMOOTHING_FACTOR && i >= Constants.ELEVATION_SMOOTHING_FACTOR) {
assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMaxGrade());
assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMinGrade());
}
}
for (double i = 0; i < 1000; i++) {
/*
* The value of the elevation does not matter. This is just to fill the
* elevation buffer.
*/
tripStatisticsUpdater.updateElevation(i);
tripStatisticsUpdater.updateGrade(100, -100);
if (i >= Constants.GRADE_SMOOTHING_FACTOR && i >= Constants.ELEVATION_SMOOTHING_FACTOR) {
assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMaxGrade());
assertEquals(-1.0, tripStatisticsUpdater.getTripStatistics().getMinGrade());
}
}
}
/**
* Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with
* distance of 1. The grade should get ignored.
*/
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
* elevation buffer.
*/
tripStatisticsUpdater.updateElevation(i);
tripStatisticsUpdater.updateGrade(1, 100);
assertEquals(
Double.NEGATIVE_INFINITY, tripStatisticsUpdater.getTripStatistics().getMaxGrade());
assertEquals(
Double.POSITIVE_INFINITY, tripStatisticsUpdater.getTripStatistics().getMinGrade());
}
}
/**
* Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)}
* with speed of zero.
*/
public void testUpdateSpeedIncludeZero() {
for (int i = 0; i < 1000; i++) {
tripStatisticsUpdater.updateSpeed(i + ONE_SECOND, 0.0, i, 4.0);
assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed());
}
}
/**
* Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)}
* with the error code 128. The speed should get ignored.
*/
public void testUpdateSpeedIngoreErrorCode() {
long time = 12344000;
tripStatisticsUpdater.updateSpeed(time + ONE_SECOND, 128.0, time, 0.0);
assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed());
}
/**
* Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)}
* with a large speed change. The speed should get ignored.
*/
public void testUpdateSpeedIngoreLargeAcceleration() {
long time = 12344000;
tripStatisticsUpdater.updateSpeed(time + ONE_SECOND, 100.0, time, 1.0);
assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed());
}
/**
* Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)}
* with constant speed.
*/
public void testUpdateSpeed() {
double speed = 4.0;
for (int i = 0; i < 1000; i++) {
tripStatisticsUpdater.updateSpeed(i + ONE_SECOND, speed, i, speed);
if (i >= Constants.SPEED_SMOOTHING_FACTOR) {
assertEquals(speed, tripStatisticsUpdater.getTripStatistics().getMaxSpeed());
}
}
}
}
@@ -0,0 +1,38 @@
// Copyright 2010 Google Inc. All Rights Reserved.
package com.google.android.apps.mytracks.testing;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
import android.content.Context;
/**
* A fake factory for {@link MyTracksProviderUtils} which always returns a
* predefined instance.
*
* @author Rodrigo Damazio
*/
public class TestingProviderUtilsFactory extends Factory {
private MyTracksProviderUtils instance;
public TestingProviderUtilsFactory(MyTracksProviderUtils instance) {
this.instance = instance;
}
@Override
protected MyTracksProviderUtils newForContext(Context context) {
return instance;
}
public static Factory installWithInstance(MyTracksProviderUtils instance) {
Factory oldFactory = Factory.getInstance();
Factory factory = new TestingProviderUtilsFactory(instance);
MyTracksProviderUtils.Factory.overrideInstance(factory);
return oldFactory;
}
public static void restoreOldFactory(Factory factory) {
MyTracksProviderUtils.Factory.overrideInstance(factory);
}
}
@@ -0,0 +1,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.getTripStatistics();
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));
}
}