| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * 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.android.tools.lint.checks; |
| |
| import com.android.tools.lint.detector.api.Detector; |
| |
| @SuppressWarnings("javadoc") |
| public class AppIndexingApiDetectorTest extends AbstractCheckTest { |
| |
| @Override |
| protected Detector getDetector() { |
| return new AppIndexingApiDetector(); |
| } |
| |
| public void testOk() throws Exception { |
| assertEquals("No warnings.", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:host=\"example.com\"\n" |
| + " android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testDataMissing() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:15: Error: Missing data node? [AppIndexingError]\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " ^\n" |
| + "1 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testNoUrl() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:17: Error: Missing URL for the intent filter? [AppIndexingError]\n" |
| + " <data />\n" |
| + " ~~~~~~~~\n" |
| + "1 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testMimeType() throws Exception { |
| assertEquals("No warnings.", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:mimeType=\"mimetype\" /> " |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| |
| public void testNoActivity() throws Exception { |
| assertEquals( |
| "No warnings.", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testNotBrowsable() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:25: Warning: Activity supporting ACTION_VIEW is not set as BROWSABLE [AppIndexingWarning]\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " ^\n" |
| + "0 errors, 1 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".MainActivity\"\n" |
| + " android:label=\"@string/app_name\" >\n" |
| + " <intent-filter>\n" |
| + " <action android:name=\"android.intent.action.MAIN\" />\n" |
| + "\n" |
| + " <category android:name=\"android.intent.category.LAUNCHER\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + "\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:host=\"example.com\"\n" |
| + " android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testWrongPathPrefix() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:19: Error: android:pathPrefix attribute should start with '/', but it is : gizmos [AppIndexingError]\n" |
| + " android:pathPrefix=\"gizmos\" />\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "1 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:host=\"example.com\"\n" |
| + " android:pathPrefix=\"gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testWrongPort() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:19: Error: android:port is not a legal number [AppIndexingError]\n" |
| + " android:port=\"ABCD\"\n" |
| + " ~~~~~~~~~~~~~~~~~~~\n" |
| + "1 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:host=\"example.com\"\n" |
| + " android:port=\"ABCD\"\n" |
| + " android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testSchemeAndHostMissing() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:17: Error: Missing URL for the intent filter? [AppIndexingError]\n" |
| + " <data android:pathPrefix=\"/gizmos\" />\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "AndroidManifest.xml:17: Error: android:host missing [AppIndexingError]\n" |
| + " <data android:pathPrefix=\"/gizmos\" />\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "AndroidManifest.xml:17: Error: android:scheme missing [AppIndexingError]\n" |
| + " <data android:pathPrefix=\"/gizmos\" />\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "3 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testMultiData() throws Exception { |
| assertEquals("No warnings.", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\" />\n" |
| + " <data android:host=\"example.com\" />\n" |
| + " <data android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testMultiIntent() throws Exception { |
| assertEquals("No warnings.", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter>\n" |
| + " <action android:name=\"android.intent.action.MAIN\" />\n" |
| + " <category android:name=\"android.intent.category.LAUNCHER\" />\n" |
| + " </intent-filter>" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:host=\"example.com\"\n" |
| + " android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testMultiIntentWithError() throws Exception { |
| assertEquals("" |
| + "AndroidManifest.xml:20: Error: android:host missing [AppIndexingError]\n" |
| + " <data android:scheme=\"http\"\n" |
| + " ^\n" |
| + "1 errors, 0 warnings\n", |
| lintProject(xml("AndroidManifest.xml", "" |
| + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" |
| + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" |
| + " package=\"com.example.helloworld\" >\n" |
| + "\n" |
| + " <application\n" |
| + " android:allowBackup=\"true\"\n" |
| + " android:icon=\"@mipmap/ic_launcher\"\n" |
| + " android:label=\"@string/app_name\"\n" |
| + " android:theme=\"@style/AppTheme\" >\n" |
| + " <activity\n" |
| + " android:name=\".FullscreenActivity\"\n" |
| + " android:configChanges=\"orientation|keyboardHidden|screenSize\"\n" |
| + " android:label=\"@string/title_activity_fullscreen\"\n" |
| + " android:theme=\"@style/FullscreenTheme\" >\n" |
| + " <intent-filter>\n" |
| + " <action android:name=\"android.intent.action.MAIN\" />\n" |
| + " <category android:name=\"android.intent.category.LAUNCHER\" />\n" |
| + " </intent-filter>" |
| + " <intent-filter android:label=\"@string/title_activity_fullscreen\">\n" |
| + " <action android:name=\"android.intent.action.VIEW\" />\n" |
| + " <data android:scheme=\"http\"\n" |
| + " android:pathPrefix=\"/gizmos\" />\n" |
| + " <category android:name=\"android.intent.category.DEFAULT\" />\n" |
| + " <category android:name=\"android.intent.category.BROWSABLE\" />\n" |
| + " </intent-filter>\n" |
| + " </activity>\n" |
| + " </application>\n" |
| + "\n" |
| + "</manifest>\n"))); |
| } |
| |
| public void testOkWithResource() throws Exception { |
| assertEquals("No warnings.", |
| lintProjectIncrementally( |
| "AndroidManifest.xml", |
| "appindexing_manifest.xml=>AndroidManifest.xml", |
| "res/values/appindexing_strings.xml")); |
| } |
| |
| public void testWrongWithResource() throws Exception { |
| assertEquals("" + "AndroidManifest.xml:18: Error: android:pathPrefix attribute should start with '/', but it is : pathprefix [AppIndexingError]\n" |
| + " android:pathPrefix=\"@string/path_prefix\"\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "AndroidManifest.xml:19: Error: android:port is not a legal number [AppIndexingError]\n" |
| + " android:port=\"@string/port\"/>\n" |
| + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" |
| + "2 errors, 0 warnings\n", |
| lintProjectIncrementally( |
| "AndroidManifest.xml", |
| "appindexing_manifest.xml=>AndroidManifest.xml", |
| "res/values/appindexing_wrong_strings.xml")); |
| } |
| } |