package jetbrains.mps.console.performance;

/*Generated by MPS */

import jetbrains.mps.MPSLaunch;
import jetbrains.mps.lang.test.runtime.BaseTransformationTest;
import org.junit.jupiter.api.extension.RegisterExtension;
import jetbrains.mps.lang.test.runtime.TestParametersCacheExtension;
import jetbrains.mps.lang.test.runtime.TestParametersCache;
import org.junit.jupiter.api.Test;
import jetbrains.mps.lang.test.runtime.BaseTestBody;
import jetbrains.mps.lang.test.runtime.TransformationTest;
import java.time.Duration;
import org.junit.Assert;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.checkers.IChecker;
import jetbrains.mps.errors.item.NodeReportItem;
import jetbrains.mps.project.validation.StructureChecker;
import jetbrains.mps.checkers.IAbstractChecker;
import jetbrains.mps.checkers.ModelCheckerBuilder;
import jetbrains.mps.errors.item.IssueKindReportItem;
import java.util.ArrayList;
import jetbrains.mps.checkers.SuppressErrorsChecker;
import jetbrains.mps.util.CollectConsumer;
import jetbrains.mps.progress.EmptyProgressMonitor;
import jetbrains.mps.smodel.builder.SNodeBuilder;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SConcept;

@MPSLaunch
public class SuppressErrorsPerformanceTest_Test extends BaseTransformationTest {
  @RegisterExtension
  private static final TestParametersCacheExtension ourParametersCacheExtension = new TestParametersCacheExtension(new TestParametersCache(SuppressErrorsPerformanceTest_Test.class, "${mps_home}", "r:331d12a3-ff36-4324-a0a5-3624fa05f749(jetbrains.mps.console.performance@tests)", false));

  public SuppressErrorsPerformanceTest_Test() {
    super(ourParametersCacheExtension.getParametersCache());
  }

  @Test
  public void test_testPerformance() throws Throwable {
    new TestBody(this).test_testPerformance();
  }

  /*package*/ static class TestBody extends BaseTestBody {

    /*package*/ TestBody(TransformationTest owner) {
      super(owner);
    }

    public void test_testPerformance() throws Exception {
      runWithinCommand(() -> addNodeById("5968606277575949800"));
      runWithinCommand(() -> {
        // the goal of that test is to ensure more efficient than quadratic complexity
        Duration durationA = TestBody.this.measureSuppressPerformance(4 * 1000);
        Duration durationB = TestBody.this.measureSuppressPerformance(40 * 1000);
        Assert.assertTrue(String.format("%d expected to be approximately 10 times greater that %d", durationB.toMillis(), durationA.toMillis()), durationA.multipliedBy(15).compareTo(durationB) > 0);
        Assert.assertTrue(String.format("%d expected to be greater than 5 ms", durationA.toMillis()), durationA.compareTo(Duration.ofMillis(5)) > 0);
        Assert.assertTrue(String.format("%d expected to be less than 10000 ms", durationB.toMillis()), durationB.compareTo(Duration.ofMillis(10000)) < 0);
      });
    }

    public Duration measureSuppressPerformance(int modelSize) {
      SNode var5968606277576107105 = getNodeById("5968606277576107085");
      ListSequence.fromList(SLinkOperations.getChildren(getNodeById("5968606277576107085"), LINKS.item$upGD)).clear();
      for (int i = 0; i < modelSize; i++) {
        ListSequence.fromList(SLinkOperations.getChildren(getNodeById("5968606277576107085"), LINKS.item$upGD)).addElement(createNodeResponseItem_wxn1w7_a0a0a2a5g());
      }
      SModel modelToCheck = SNodeOperations.getModel(getNodeById("5968606277576107085"));
      IChecker<SNode, NodeReportItem> structureChecker = new StructureChecker();
      long startTime = System.nanoTime();
      IAbstractChecker<ModelCheckerBuilder.ItemsToCheck, IssueKindReportItem> checker = new ModelCheckerBuilder(false).createChecker(ListSequence.fromListAndArray(new ArrayList<IChecker<?, ? extends IssueKindReportItem>>(), structureChecker, new SuppressErrorsChecker()));
      checker.check(ModelCheckerBuilder.ItemsToCheck.forSingleModel(modelToCheck), modelToCheck.getRepository(), new CollectConsumer<IssueKindReportItem>(), new EmptyProgressMonitor());
      long stopTime = System.nanoTime();
      return Duration.ofNanos(stopTime - startTime);
    }
    private static SNode createNodeResponseItem_wxn1w7_a0a0a2a5g() {
      SNodeBuilder n0 = new SNodeBuilder().init(CONCEPTS.NodeResponseItem$Xr);
      n0.forChild(LINKS.node$X2qT).initNull();
      return n0.getResult();
    }
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink item$upGD = MetaAdapterFactory.getContainmentLink(0xde1ad86d6e504a02L, 0xb306d4d17f64c375L, 0x4e3b035171a5ba02L, 0x4e3b035171b356edL, "item");
    /*package*/ static final SContainmentLink node$X2qT = MetaAdapterFactory.getContainmentLink(0xde1ad86d6e504a02L, 0xb306d4d17f64c375L, 0x4e3b035171b35c14L, 0x4e3b035171b35c15L, "node");
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept NodeResponseItem$Xr = MetaAdapterFactory.getConcept(0xde1ad86d6e504a02L, 0xb306d4d17f64c375L, 0x4e3b035171b35c14L, "jetbrains.mps.console.base.structure.NodeResponseItem");
  }
}
