// 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 com.google.common.collect.ImmutableMap;
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.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.BazelStarlarkContext;
import com.google.devtools.build.lib.packages.SymbolGenerator;
import com.google.devtools.build.lib.rules.platform.PlatformCommon;
import com.google.devtools.build.lib.syntax.Module;
import com.google.devtools.build.lib.syntax.SkylarkUtils;
import com.google.devtools.build.lib.syntax.SkylarkUtils.Phase;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
import com.google.devtools.build.lib.testutil.TestConstants;
import org.junit.Before;

/**
 * A class to contain the common functionality for analysis-phase Skylark tests. The less stuff
 * here, the better.
 */
public abstract class SkylarkTestCase extends BuildViewTestCase {

  protected EvaluationTestCase ev;

  // Subclasses must call this method after change SkylarkSemantics (among other things).
  @Before
  public final void reset() throws Exception {
    ev = createEvaluationTestCase();
  }

  private EvaluationTestCase createEvaluationTestCase() throws Exception {
    // Set up globals.
    ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
    SkylarkModules.addSkylarkGlobalsToBuilder(env);
    Starlark.addModule(env, new PlatformCommon());
    Module globals = Module.createForBuiltins(env.build());

    EvaluationTestCase ev =
        new EvaluationTestCase() {
          @Override
          public StarlarkThread newStarlarkThread() throws Exception {
            StarlarkThread thread =
                StarlarkThread.builder(mutability)
                    .setSemantics(getSkylarkSemantics())
                    .setEventHandler(getEventHandler())
                    .setGlobals(
                        globals.withLabel(
                            Label.parseAbsoluteUnchecked("//test:label", /*defaultToMain=*/ false)))
                    .build();

            SkylarkUtils.setPhase(thread, Phase.LOADING);

            // This StarlarkThread has no PackageContext, so attempts to create a rule will fail.
            // Rule creation is tested by SkylarkIntegrationTest.

            new BazelStarlarkContext(
                    TestConstants.TOOLS_REPOSITORY,
                    /*fragmentNameToClass=*/ null,
                    /*repoMapping=*/ ImmutableMap.of(),
                    new SymbolGenerator<>(new Object()),
                    /*analysisRuleLabel=*/ null)
                .storeInThread(thread);

            return thread;
          }
        };
    ev.initialize();
    return ev;
  }

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

  protected final void exec(String... lines) throws Exception {
    ev.exec(lines);
  }

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

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

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

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

  // Disable BuildViewTestCase's overload to avoid unintended calls.
  @Override
  protected final Event checkError(String x, String y) throws Exception {
    throw new IllegalStateException("wrong method");
  }

}
