/*
 * 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.assertTrue;

import com.facebook.buck.java.Keystore;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.FakeBuildRuleParams;
import com.facebook.buck.testutil.MoreAsserts;
import com.facebook.buck.testutil.RuleMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;

import org.junit.Test;


public class AndroidResourceRuleTest {

  @Test
  public void testGetInputsToCompareToOutput() {
    // Create an android_library rule with all sorts of input files that it depends on. If any of
    // these files is modified, then this rule should not be cached.
    BuildTarget buildTarget = new BuildTarget("//java/src/com/facebook/base", "res");
    BuildRuleParams buildRuleParams = new FakeBuildRuleParams(
        buildTarget,
        ImmutableSortedSet.<BuildRule>of());
    AndroidResourceRule androidResourceRule = new AndroidResourceRule(
        buildRuleParams,
        "java/src/com/facebook/base/res",
        ImmutableSortedSet.of(
            "java/src/com/facebook/base/res/drawable/E.xml",
            "java/src/com/facebook/base/res/drawable/A.xml",
            "java/src/com/facebook/base/res/drawable/C.xml"),
        "com.facebook",
        "java/src/com/facebook/base/assets",
        ImmutableSortedSet.of(
            "java/src/com/facebook/base/assets/drawable/F.xml",
            "java/src/com/facebook/base/assets/drawable/B.xml",
            "java/src/com/facebook/base/assets/drawable/D.xml"),
        "java/src/com/facebook/base/AndroidManifest.xml");

    // Test getInputsToCompareToOutput().
    MoreAsserts.assertIterablesEquals(
        "getInputsToCompareToOutput() should return an alphabetically sorted list of all input " +
        "files that contribute to this android_resource() rule.",
        ImmutableList.of(
            "java/src/com/facebook/base/res/drawable/A.xml",
            "java/src/com/facebook/base/res/drawable/C.xml",
            "java/src/com/facebook/base/res/drawable/E.xml",
            "java/src/com/facebook/base/assets/drawable/B.xml",
            "java/src/com/facebook/base/assets/drawable/D.xml",
            "java/src/com/facebook/base/assets/drawable/F.xml",
            "java/src/com/facebook/base/AndroidManifest.xml"),
        androidResourceRule.getInputsToCompareToOutput());
  }

  /**
   * Create the following dependency graph of {@link AndroidResourceRule}s:
   * <pre>
   *    A
   *  / | \
   * B  |  D
   *  \ | /
   *    C
   * </pre>
   * Note that an ordinary breadth-first traversal would yield either {@code A B C D} or
   * {@code A D C B}. However, either of these would be <em>wrong</em> in this case because we need
   * to be sure that we perform a topological sort, the resulting traversal of which is either
   * {@code A B D C} or {@code A D B C}.
   * <p>
   * We choose these letters in particular.
   */
  @Test
  public void testGetAndroidResourceDeps() {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();
    AndroidResourceRule c = ruleResolver.buildAndAddToIndex(
        AndroidResourceRule.newAndroidResourceRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
            .setBuildTarget(BuildTargetFactory.newInstance("//:c"))
            .setRes("res_c")
            .setRDotJavaPackage("com.facebook"));

    AndroidResourceRule b = ruleResolver.buildAndAddToIndex(
        AndroidResourceRule.newAndroidResourceRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//:b"))
        .setRes("res_b")
        .setRDotJavaPackage("com.facebook")
        .addDep(BuildTargetFactory.newInstance("//:c")));

    AndroidResourceRule d = ruleResolver.buildAndAddToIndex(
        AndroidResourceRule.newAndroidResourceRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
            .setBuildTarget(BuildTargetFactory.newInstance("//:d"))
            .setRes("res_d")
            .setRDotJavaPackage("com.facebook")
            .addDep(BuildTargetFactory.newInstance("//:c")));

    AndroidResourceRule a = ruleResolver.buildAndAddToIndex(
        AndroidResourceRule.newAndroidResourceRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//:a"))
        .setRes("res_a")
        .setRDotJavaPackage("com.facebook")
        .addDep(BuildTargetFactory.newInstance("//:b"))
        .addDep(BuildTargetFactory.newInstance("//:c"))
        .addDep(BuildTargetFactory.newInstance("//:d")));

    DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
    ImmutableList<HasAndroidResourceDeps> deps = UberRDotJavaUtil.getAndroidResourceDeps(a, graph);

    // Note that a topological sort for a DAG is not guaranteed to be unique. In this particular
    // case, there are two possible valid outcomes.
    ImmutableList<AndroidResourceRule> validResult1 = ImmutableList.of(a, b, d, c);
    ImmutableList<AndroidResourceRule> validResult2 = ImmutableList.of(a, d, b, c);

    assertTrue(
        String.format(
            "Topological sort %s should be either %s or %s", deps, validResult1, validResult2),
        deps.equals(validResult1) || deps.equals(validResult2));

    // Introduce an AndroidBinaryRule that depends on A and C and verify that the same topological
    // sort results. This verifies that both AndroidResourceRule.getAndroidResourceDeps does the
    // right thing when it gets a non-AndroidResourceRule as well as an AndroidResourceRule.
    BuildTarget keystoreTarget = BuildTargetFactory.newInstance("//keystore:debug");
    ruleResolver.buildAndAddToIndex(
        Keystore.newKeystoreBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(keystoreTarget)
        .setStore("keystore/debug.keystore")
        .setProperties("keystore/debug.keystore.properties")
        .addVisibilityPattern(BuildTargetPattern.MATCH_ALL));
    AndroidBinaryRule e = ruleResolver.buildAndAddToIndex(
        AndroidBinaryRule.newAndroidBinaryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
        .setBuildTarget(BuildTargetFactory.newInstance("//:e"))
        .setManifest("AndroidManfiest.xml")
        .setTarget("Google Inc.:Google APIs:16")
        .setKeystore(keystoreTarget)
        .addDep(BuildTargetFactory.newInstance("//:a"))
        .addDep(BuildTargetFactory.newInstance("//:c")));

    DependencyGraph graph2 = RuleMap.createGraphFromBuildRules(ruleResolver);
    ImmutableList<HasAndroidResourceDeps> deps2 = UberRDotJavaUtil.getAndroidResourceDeps(e, graph2);
    assertTrue(
        String.format(
            "Topological sort %s should be either %s or %s", deps, validResult1, validResult2),
            deps2.equals(validResult1) || deps2.equals(validResult2));
  }
}
