// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.skylark.util;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.skylark.SkylarkModules;
import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
import com.google.devtools.build.lib.rules.platform.PlatformCommon;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.Environment.Phase;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.SkylarkUtils;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
import com.google.devtools.build.lib.testutil.TestConstants;
import java.util.List;
import org.junit.Before;

/**
 * A class to contain the common functionality for Skylark tests.
 */
public abstract class SkylarkTestCase extends BuildViewTestCase {

  // We don't have multiple inheritance, so we fake it.
  protected EvaluationTestCase ev;

  @Before
  public final void setUpEvaluator() throws Exception {
    ev = createEvaluationTestCase();
    ev.initialize();
  }

  protected EvaluationTestCase createEvaluationTestCase() {
    return new EvaluationTestCase() {
      @Override
      public Environment newEnvironment() throws Exception {
        List<Class<?>> modules =
            new ImmutableList.Builder<Class<?>>()
                .addAll(SkylarkModules.MODULES)
                .add(PlatformCommon.class)
                .build();
        Environment env =
            Environment.builder(mutability)
                .useDefaultSemantics()
                .setEventHandler(getEventHandler())
                .setGlobals(SkylarkModules.getGlobals(modules))
                .setPhase(Phase.LOADING)
                .build()
                .setupDynamic(
                    PackageFactory.PKG_CONTEXT,
                    // This dummy pkgContext works because no Skylark unit test attempts to actually
                    // create rules. Creating actual rules is tested in SkylarkIntegrationTest.
                    new PackageContext(null, null, getEventHandler(), null));
        SkylarkUtils.setToolsRepository(env, TestConstants.TOOLS_REPOSITORY);
        return env;
      }
    };
  }

  protected Object eval(String... input) throws Exception {
    return ev.eval(input);
  }

  protected void update(String name, Object value) throws Exception {
    ev.update(name, value);
  }

  protected Object lookup(String name) throws Exception {
    return ev.lookup(name);
  }

  protected void checkEvalError(String msg, String... input) throws Exception {
    ev.checkEvalError(msg, input);
  }

  protected void checkEvalErrorContains(String msg, String... input) throws Exception {
    ev.checkEvalErrorContains(msg, input);
  }

  protected SkylarkRuleContext dummyRuleContext() throws Exception {
    return createRuleContext("//foo:foo");
  }

  protected SkylarkRuleContext createRuleContext(String label) throws Exception {
    return new SkylarkRuleContext(getRuleContextForSkylark(getConfiguredTarget(label)), null,
        getSkylarkSemantics());
  }

  protected Object evalRuleContextCode(String... lines) throws Exception {
    return evalRuleContextCode(dummyRuleContext(), lines);
  }

  /**
   * RuleContext can't be null, SkylarkBuiltInFunctions checks it.
   * However not all built in functions use it, if usesRuleContext == false
   * the wrapping function won't need a ruleContext parameter.
   */
  protected Object evalRuleContextCode(SkylarkRuleContext ruleContext, String... code)
      throws Exception {
    setUpEvaluator();
    if (ruleContext != null) {
      update("ruleContext", ruleContext);
    }
    return eval(code);
  }

  protected void assertArtifactFilenames(Iterable<Artifact> artifacts, String... expected) {
    ImmutableList.Builder<String> artifactFilenames = ImmutableList.builder();
    for (Artifact artifact : artifacts) {
      artifactFilenames.add(artifact.getFilename());
    }
    assertThat(artifactFilenames.build()).containsAllIn(Lists.newArrayList(expected));
  }

  protected Object evalRuleClassCode(String... lines) throws Exception {
    setUpEvaluator();
    return eval("def impl(ctx): return None\n" + Joiner.on("\n").join(lines));
  }

  protected void checkError(SkylarkRuleContext ruleContext, String errorMsg, String... lines)
      throws Exception {
    try {
      evalRuleContextCode(ruleContext, lines);
      fail();
    } catch (EvalException e) {
      assertThat(e).hasMessage(errorMsg);
    }
  }

  protected void checkErrorStartsWith(
      SkylarkRuleContext ruleContext, String errorMsg, String... lines) throws Exception {
    try {
      evalRuleContextCode(ruleContext, lines);
      fail();
    } catch (EvalException e) {
      assertThat(e).hasMessageThat().startsWith(errorMsg);
    }
  }

  protected void checkErrorContains(String errorMsg, String... lines) throws Exception {
    ev.setFailFast(false);
    try {
      eval(lines);
      fail("checkErrorContains(String, String...): There was no error");
    } catch (EvalException e) {
      assertThat(e).hasMessageThat().contains(errorMsg);
    }
  }

  protected void checkErrorContains(
      SkylarkRuleContext ruleContext, String errorMsg, String... lines) throws Exception {
    try {
      evalRuleContextCode(ruleContext, lines);
      fail("checkErrorContains(SkylarkRuleContext, String, String...): There was no error");
    } catch (EvalException e) {
      assertThat(e).hasMessageThat().contains(errorMsg);
    }
  }
}
