/*
 * 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();
    }

    @Override
    protected boolean allowCompilationErrors() {
        return true;
    }

    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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testDataMissing() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.DATA_MISSING, AppIndexingApiDetector.IssueType.parse("Missing data element"));
        assertEquals(""
                        + "AndroidManifest.xml:15: Error: Missing data element [GoogleAppIndexingUrlError]\n"
                        + "            <intent-filter android:label=\"@string/title_activity_fullscreen\">\n"
                        + "            ^\n"
                        + "AndroidManifest.xml:15: Warning: Missing URL [GoogleAppIndexingWarning]\n"
                        + "            <intent-filter android:label=\"@string/title_activity_fullscreen\">\n"
                        + "            ^\n"
                        + "1 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=\".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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testNoUrl() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.URL_MISSING, AppIndexingApiDetector.IssueType.parse("Missing URL for the intent filter"));
        assertEquals(""
                        + "AndroidManifest.xml:17: Error: Missing URL for the intent filter [GoogleAppIndexingUrlError]\n"
                        + "                <data />\n"
                        + "                ~~~~~~~~\n"
                        + "AndroidManifest.xml:15: Warning: Missing URL [GoogleAppIndexingWarning]\n"
                        + "            <intent-filter android:label=\"@string/title_activity_fullscreen\">\n"
                        + "            ^\n"
                        + "1 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=\".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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testMimeType() throws Exception {
        assertEquals("AndroidManifest.xml:15: Warning: Missing URL [GoogleAppIndexingWarning]\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=\".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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testNoActivity() throws Exception {
        assertEquals(
                ""
                        + "AndroidManifest.xml:5: Warning: App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VIEW intent filter. See issue explanation for more details. [GoogleAppIndexingWarning]\n"
                        + "    <application\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testNoWarningInLibraries() throws Exception {
        // Regression test for https://code.google.com/p/android/issues/detail?id=194937
        // 194937: App indexing lint check shouldn't apply to library projects
        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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n"),
                        // Mark project as library
                        source("project.properties", "android.library=true\n")));
    }

    public void testNoActionView() throws Exception {
        assertEquals(
                ""
                        + "AndroidManifest.xml:5: Warning: App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VIEW intent filter. See issue explanation for more details. [GoogleAppIndexingWarning]\n"
                        + "    <application\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"
                        + "                <category android:name=\"android.intent.category.LAUNCHER\" />\n"
                        + "            </intent-filter>\n"
                        + "        </activity>\n"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testNotBrowsable() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.NOT_BROWSABLE, AppIndexingApiDetector.IssueType.parse("Activity supporting ACTION_VIEW is not set as BROWSABLE"));
        assertEquals(""
                        + "AndroidManifest.xml:25: Warning: Activity supporting ACTION_VIEW is not set as BROWSABLE [GoogleAppIndexingWarning]\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testWrongPathPrefix() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.MISSING_SLASH, AppIndexingApiDetector.IssueType.parse("android:pathPrefix attribute should start with '/', but it is : gizmos"));
        assertEquals(""
                        + "AndroidManifest.xml:19: Error: android:pathPrefix attribute should start with '/', but it is : gizmos [GoogleAppIndexingUrlError]\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testWrongPort() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.ILLEGAL_NUMBER, AppIndexingApiDetector.IssueType.parse("android:port is not a legal number"));
        assertEquals(""
                        + "AndroidManifest.xml:19: Error: android:port is not a legal number [GoogleAppIndexingUrlError]\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testSchemeAndHostMissing() throws Exception {
        assertEquals(AppIndexingApiDetector.IssueType.SCHEME_MISSING, AppIndexingApiDetector.IssueType.parse("android:scheme is missing"));
        assertEquals(AppIndexingApiDetector.IssueType.HOST_MISSING, AppIndexingApiDetector.IssueType.parse("android:host is missing"));
        assertEquals(""
                        + "AndroidManifest.xml:17: Error: Missing URL for the intent filter [GoogleAppIndexingUrlError]\n"
                        + "                <data android:pathPrefix=\"/gizmos\" />\n"
                        + "                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                        + "AndroidManifest.xml:17: Error: android:host is missing [GoogleAppIndexingUrlError]\n"
                        + "                <data android:pathPrefix=\"/gizmos\" />\n"
                        + "                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                        + "AndroidManifest.xml:17: Error: android:scheme is missing [GoogleAppIndexingUrlError]\n"
                        + "                <data android:pathPrefix=\"/gizmos\" />\n"
                        + "                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                        + "AndroidManifest.xml:15: Warning: Missing URL [GoogleAppIndexingWarning]\n"
                        + "            <intent-filter android:label=\"@string/title_activity_fullscreen\">\n"
                        + "            ^\n"
                        + "3 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=\".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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testMultiIntentWithError() throws Exception {
        assertEquals(""
                        + "AndroidManifest.xml:20: Error: android:host is missing [GoogleAppIndexingUrlError]\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </application>\n"
                        + "\n"
                        + "</manifest>\n")));
    }

    public void testNotExported() throws Exception {
        assertEquals("AndroidManifest.xml:10: Error: Activity supporting ACTION_VIEW is not exported [GoogleAppIndexingUrlError]\n"
                        + "        <activity android:exported=\"false\"\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 android:exported=\"false\"\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"
                        + "        <meta-data android:name=\"com.google.android.gms.version\" android:value=\"@integer/google_play_services_version\" />"
                        + "    </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 [GoogleAppIndexingUrlError]\n"
                        + "                      android:pathPrefix=\"@string/path_prefix\"\n"
                        + "                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                        + "AndroidManifest.xml:19: Error: android:port is not a legal number [GoogleAppIndexingUrlError]\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"));
    }

    public void testJavaOk() throws Exception {
        assertEquals("No warnings.",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestOk.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testNoManifest() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:28: Warning: Missing support for Firebase App Indexing in the manifest [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.start(mClient, action);\n"
                        + "                         ~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:36: Warning: Missing support for Firebase App Indexing in the manifest [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.end(mClient, action);\n"
                        + "                         ~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestOk.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testNoStartEnd() throws Exception {
        assertEquals(""
                        + "src/com/example/helloworld/AppIndexingApiTest.java:11: Warning: Missing support for Firebase App Indexing API [GoogleAppIndexingApiWarning]\n"
                        + "public class AppIndexingApiTest extends Activity {\n"
                        + "             ~~~~~~~~~~~~~~~~~~\n"
                        + "0 errors, 1 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestNoStartEnd.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testStartMatch() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:27: Warning: GoogleApiClient mClient is not connected [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.start(mClient, action);\n"
                        + "                               ~~~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:27: Warning: Missing corresponding AppIndex.AppIndexApi.end method [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.start(mClient, action);\n"
                        + "                         ~~~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestStartMatch.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testEndMatch() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:33: Warning: GoogleApiClient mClient is not disconnected [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.end(mClient, action);\n"
                        + "                             ~~~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:33: Warning: Missing corresponding AppIndex.AppIndexApi.start method [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.end(mClient, action);\n"
                        + "                         ~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestEndMatch.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testViewMatch() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:26: Warning: GoogleApiClient mClient is not connected [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.view(mClient, this, APP_URI, title, WEB_URL, null);\n"
                        + "                              ~~~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:26: Warning: Missing corresponding AppIndex.AppIndexApi.end method [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.view(mClient, this, APP_URI, title, WEB_URL, null);\n"
                        + "                         ~~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestViewMatch.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testViewEndMatch() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:29: Warning: GoogleApiClient mClient is not disconnected [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.viewEnd(mClient, this, APP_URI);\n"
                        + "                                 ~~~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:29: Warning: Missing corresponding AppIndex.AppIndexApi.start method [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.viewEnd(mClient, this, APP_URI);\n"
                        + "                         ~~~~~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestViewEndMatch.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testWrongOrder() throws Exception {
        assertEquals("No warnings.",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestWrongOrder.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

    public void testGoogleApiClientAddApi() throws Exception {
        assertEquals("" + "src/com/example/helloworld/AppIndexingApiTest.java:28: Warning: GoogleApiClient mClient has not added support for App Indexing API [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.start(mClient, action);\n"
                        + "                               ~~~~~~~\n"
                        + "src/com/example/helloworld/AppIndexingApiTest.java:36: Warning: GoogleApiClient mClient has not added support for App Indexing API [GoogleAppIndexingApiWarning]\n"
                        + "    AppIndex.AppIndexApi.end(mClient, action);\n"
                        + "                             ~~~~~~~\n"
                        + "0 errors, 2 warnings\n",
                lintProject(
                        "src/com/example/helloworld/AppIndexingApiTestGoogleApiClientAddApi.java.txt=>src/com/example/helloworld/AppIndexingApiTest.java",
                        "app_indexing_api_test.xml=>AndroidManifest.xml",
                        "src/com/appindexing/AppIndex.java.txt=>src/com/google/android/gms/appindexing/AppIndex.java",
                        "src/com/appindexing/AppIndexApi.java.txt=>src/com/google/android/gms/appindexing/AppIndexApi.java",
                        "src/com/appindexing/GoogleApiClient.java.txt=>src/com/google/android/gms/common/api/GoogleApiClient.java",
                        "src/com/appindexing/Activity.java.txt=>src/com/google/android/app/Activity.java",
                        "src/com/appindexing/Api.java.txt=>src/com/google/android/gms/common/api/Api.java"));
    }

}
