/*
 * Copyright 2012-present Facebook, 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.facebook.buck.android;

import static org.junit.Assert.assertEquals;

import com.facebook.buck.cpp.PrebuiltNativeLibraryBuildRule;
import com.facebook.buck.java.DefaultJavaLibraryRule;
import com.facebook.buck.java.KeystoreRule;
import com.facebook.buck.java.PrebuiltJarRule;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.testutil.RuleMap;
import com.google.common.collect.ImmutableSet;

import org.junit.Test;

public class AndroidTransitiveDependencyGraphTest {

  /**
   * This is a regression test to ensure that an additional 1 second startup cost is not
   * re-introduced to fb4a.
   */
  @Test
  public void testFindTransitiveDependencies() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    // Create an AndroidBinaryRule that transitively depends on two prebuilt JARs. One of the two
    // prebuilt JARs will be listed in the AndroidBinaryRule's no_dx list.
    PrebuiltJarRule guavaRule = ruleResolver.buildAndAddToIndex(
        PrebuiltJarRule.newPrebuiltJarRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//third_party/guava:guava"))
        .setBinaryJar("third_party/guava/guava-10.0.1.jar")
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));

    PrebuiltJarRule jsr305Rule = ruleResolver.buildAndAddToIndex(
        PrebuiltJarRule.newPrebuiltJarRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//third_party/jsr-305:jsr-305"))
        .setBinaryJar("third_party/jsr-305/jsr305.jar")
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));


    NdkLibraryRule ndkLibraryRule = ruleResolver.buildAndAddToIndex(
        NdkLibraryRule.newNdkLibraryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
            .setBuildTarget(BuildTargetFactory.newInstance("//java/com/facebook/native_library:library"))
            .addSrc("Android.mk")
            .setIsAsset(false)
            .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));

    PrebuiltNativeLibraryBuildRule prebuiltNativeLibraryBuildRule = ruleResolver.buildAndAddToIndex(
        PrebuiltNativeLibraryBuildRule.newPrebuiltNativeLibrary(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//java/com/facebook/prebuilt_native_library:library"))
        .setNativeLibsDirectory("/java/com/facebook/prebuilt_native_library/libs")
        .setIsAsset(true)
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));

    DefaultJavaLibraryRule libraryRule = ruleResolver.buildAndAddToIndex(
        DefaultJavaLibraryRule.newJavaLibraryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
            .setBuildTarget(BuildTargetFactory.newInstance("//java/src/com/facebook:example"))
            .addDep(guavaRule.getBuildTarget())
            .addDep(jsr305Rule.getBuildTarget())
            .addDep(prebuiltNativeLibraryBuildRule.getBuildTarget())
            .addDep(ndkLibraryRule.getBuildTarget()));

    AndroidResourceRule manifestRule = ruleResolver.buildAndAddToIndex(
        AndroidResourceRule.newAndroidResourceRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//java/src/com/facebook:res"))
        .setManifestFile("java/src/com/facebook/module/AndroidManifest.xml")
        .setAssetsDirectory("assets/"));

    BuildTarget keystoreTarget = BuildTargetFactory.newInstance("//keystore:debug");
    ruleResolver.buildAndAddToIndex(
        KeystoreRule.newKeystoreBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(keystoreTarget)
        .setStore("keystore/debug.keystore")
        .setProperties("keystore/debug.keystore.properties"));

    AndroidBinaryRule binaryRule = ruleResolver.buildAndAddToIndex(
        AndroidBinaryRule.newAndroidBinaryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//java/src/com/facebook:app"))
        .addDep(libraryRule.getBuildTarget())
        .addDep(manifestRule.getBuildTarget())
        .addBuildRuleToExcludeFromDex(BuildTargetFactory.newInstance("//third_party/guava:guava"))
        .setManifest("java/src/com/facebook/AndroidManifest.xml")
        .setTarget("Google Inc.:Google APIs:16")
        .setKeystore(keystoreTarget));

    // Verify that the correct transitive dependencies are found.
    DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
    AndroidTransitiveDependencies transitiveDeps = binaryRule.findTransitiveDependencies(graph);
    AndroidDexTransitiveDependencies dexTransitiveDeps =
    		binaryRule.findDexTransitiveDependencies(graph);
    assertEquals(
        "Because guava was passed to no_dx, it should not be in the classpathEntriesToDex list",
        ImmutableSet.of("third_party/jsr-305/jsr305.jar"),
        dexTransitiveDeps.classpathEntriesToDex);
    assertEquals(
        "Because guava was passed to no_dx, it should not be treated as a third-party JAR whose " +
            "resources need to be extracted and repacked in the APK. If this is done, then code in " +
            "the guava-10.0.1.dex.1.jar in the APK's assets/ folder may try to load the resource " +
            "from the APK as a ZipFileEntry rather than as a resource within guava-10.0.1.dex.1.jar. " +
            "Loading a resource in this way could take substantially longer. Specifically, this was " +
            "observed to take over one second longer to load the resource in fb4a. Because the " +
            "resource was loaded on startup, this introduced a substantial regression in the startup " +
            "time for the fb4a app.",
        ImmutableSet.of("third_party/jsr-305/jsr305.jar"),
        dexTransitiveDeps.pathsToThirdPartyJars);
    assertEquals(
        "Because assets directory was passed an AndroidResourceRule it should be added to the " +
            "transitive dependencies",
        ImmutableSet.of("assets/"),
        transitiveDeps.assetsDirectories);
    assertEquals(
        "Because manifest file was passed an AndroidResourceRule it should be added to the " +
            "transitive dependencies",
        ImmutableSet.of("java/src/com/facebook/module/AndroidManifest.xml"),
        transitiveDeps.manifestFiles);
    assertEquals(
        "Because a native library was declared as a dependency, it should be added to the " +
            "transitive dependencies.",
        ImmutableSet.of(ndkLibraryRule.getPathToOutputFile()),
        transitiveDeps.nativeLibsZips);
    assertEquals(
        "Because a prebuilt native library  was declared as a dependency (and asset), it should " +
            "be added to the transitive dependecies.",
        ImmutableSet.of(prebuiltNativeLibraryBuildRule.getPathToOutputFile()),
        transitiveDeps.nativeLibAssetsZips);
  }
}
