<commit_before>// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.env.python.testing;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.configurations.RuntimeConfigurationWarning;
import com.intellij.execution.testframework.sm.ServiceMessageBuilder;
import com.intellij.execution.testframework.sm.runner.GeneralIdBasedToSMTRunnerEventsConvertor;
import com.intellij.execution.testframework.sm.runner.ui.MockPrinter;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.testFramework.EdtTestUtil;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import com.jetbrains.env.EnvTestTagsRequired;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.env.ut.PyUnitTestProcessRunner;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonHelper;
import com.jetbrains.python.console.PythonConsoleView;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.run.targetBasedConfiguration.PyRunTargetVariant;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdk.flavors.IronPythonSdkFlavor;
import com.jetbrains.python.testing.ConfigurationTarget;
import com.jetbrains.python.testing.PyUnitTestConfiguration;
import com.jetbrains.python.testing.PyUnitTestFactory;
import com.jetbrains.python.testing.PythonTestConfigurationsModel;
import com.jetbrains.python.tools.sdkTools.SdkCreationType;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.intellij.testFramework.assertions.Assertions.assertThat;
import static com.jetbrains.env.ut.PyScriptTestProcessRunner.TEST_TARGET_PREFIX;
import static org.junit.Assert.assertEquals;

/**
 * @author traff
 */
public final class PythonUnitTestingTest extends PythonUnitTestingLikeTest<PyUnitTestProcessRunner> {

  @Test(expected = RuntimeConfigurationWarning.class)
  public void testEmptyValidation() {
    new ConfigurationTarget("", PyRunTargetVariant.PATH).checkValid();
  }

  @Test(expected = RuntimeConfigurationError.class)
  public void testPythonValidation() {
    new ConfigurationTarget("c:/bad/", PyRunTargetVariant.PYTHON).checkValid();
  }

  @Test
  public void testValidationOk() {
    new ConfigurationTarget("foo.bar", PyRunTargetVariant.PYTHON).checkValid();
  }

  ///PY-31827
  @Test
  public void testNameChanged() {
    runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/nameChanged", "test_name_changed.py") {

      @Override
      protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner,
                                      @NotNull final String stdout,
                                      @NotNull final String stderr,
                                      @NotNull final String all,
                                      final int exitCode) {
        assertEquals("Test should not lead to errors, but:" + stderr, 0, exitCode);
      }
    });
  }

  /**
   * Run tests, delete file and click "rerun" should throw exception and display error since test ids do not point to correct PSI
   * from that moment
   */
  @Test
  public void testCantRerun() {
    startMessagesCapture();

    runPythonTest(
      new PyUnitTestLikeProcessWithConsoleTestTask<PyUnitTestProcessRunner>("/testRunner/env/unit", "test_with_skips_and_errors.py",
                                                                            this::createTestRunner) {

        @Override
        protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner,
                                        @NotNull final String stdout,
                                        @NotNull final String stderr,
                                        @NotNull final String all, int exitCode) {
          assert runner.getFailedTestsCount() > 0 : "We need failed tests to test broken rerun";

          startMessagesCapture();

          EdtTestUtil.runInEdtAndWait(() -> {
            deleteAllTestFiles(myFixture);
            runner.rerunFailedTests();
          });

          final List<Throwable> throwables = getCapturesMessages().first;
          assertThat(throwables)
            .describedAs("Exception shall be thrown")
            .isNotEmpty();
          final Throwable exception = throwables.get(0);
          assertThat(exception).isInstanceOf(ExecutionException.class);
          assertThat(exception.getMessage()).isEqualTo(PyBundle.message("runcfg.tests.cant_rerun"));
          assertThat(getCapturesMessages().second)
            .describedAs("No messages displayed for exception")
            .isNotEmpty();

          stopMessageCapture();
        }
      });
  }

  @Test
  public void testTcMessageEscaped() {
    final String[] messages = {
      "Hello\n",
      ServiceMessageBuilder.testStarted("myTest").toString(),
      ServiceMessageBuilder.testStdOut("myTest").addAttribute("out", "I am\n").toString(),
      ServiceMessageBuilder.testFinished("myTest").toString(),
      "PyCharm"
    };

    runPythonTest(new PyExecutionFixtureTestTask(null) {
      @Override
      public void runTestOn(@NotNull final String sdkHome, @Nullable Sdk existingSdk) throws Exception {
        final Project project = myFixture.getProject();
        final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
        EdtTestUtil.runInEdtAndWait(() -> {
          final PythonConsoleView console = new PythonConsoleView(project, "test", sdk, true);
          Disposer.register(myFixture.getModule(), console);
          console.getComponent(); //To init editor

          Arrays.stream(messages).forEach((s) -> console.print(s, ConsoleViewContentType.NORMAL_OUTPUT));
          console.flushDeferredText();
          assertEquals("TC messages filtered in wrong way", "Hello\nI am\nPyCharm", console.getText());
        });
      }
    });
  }

  @Test
  public void testSysPathOrder() {
    runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/sysPath", "test.py") {<commit_msg>Fix test (call dispose() in finally)<commit_after>// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.env.python.testing;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.configurations.RuntimeConfigurationWarning;
import com.intellij.execution.testframework.sm.ServiceMessageBuilder;
import com.intellij.execution.testframework.sm.runner.GeneralIdBasedToSMTRunnerEventsConvertor;
import com.intellij.execution.testframework.sm.runner.ui.MockPrinter;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.testFramework.EdtTestUtil;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import com.jetbrains.env.EnvTestTagsRequired;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.env.ut.PyUnitTestProcessRunner;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PythonHelper;
import com.jetbrains.python.console.PythonConsoleView;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.run.targetBasedConfiguration.PyRunTargetVariant;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdk.flavors.IronPythonSdkFlavor;
import com.jetbrains.python.testing.ConfigurationTarget;
import com.jetbrains.python.testing.PyUnitTestConfiguration;
import com.jetbrains.python.testing.PyUnitTestFactory;
import com.jetbrains.python.testing.PythonTestConfigurationsModel;
import com.jetbrains.python.tools.sdkTools.SdkCreationType;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.intellij.testFramework.assertions.Assertions.assertThat;
import static com.jetbrains.env.ut.PyScriptTestProcessRunner.TEST_TARGET_PREFIX;
import static org.junit.Assert.assertEquals;

/**
 * @author traff
 */
public final class PythonUnitTestingTest extends PythonUnitTestingLikeTest<PyUnitTestProcessRunner> {

  @Test(expected = RuntimeConfigurationWarning.class)
  public void testEmptyValidation() {
    new ConfigurationTarget("", PyRunTargetVariant.PATH).checkValid();
  }

  @Test(expected = RuntimeConfigurationError.class)
  public void testPythonValidation() {
    new ConfigurationTarget("c:/bad/", PyRunTargetVariant.PYTHON).checkValid();
  }

  @Test
  public void testValidationOk() {
    new ConfigurationTarget("foo.bar", PyRunTargetVariant.PYTHON).checkValid();
  }

  ///PY-31827
  @Test
  public void testNameChanged() {
    runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/nameChanged", "test_name_changed.py") {

      @Override
      protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner,
                                      @NotNull final String stdout,
                                      @NotNull final String stderr,
                                      @NotNull final String all,
                                      final int exitCode) {
        assertEquals("Test should not lead to errors, but:" + stderr, 0, exitCode);
      }
    });
  }

  /**
   * Run tests, delete file and click "rerun" should throw exception and display error since test ids do not point to correct PSI
   * from that moment
   */
  @Test
  public void testCantRerun() {
    startMessagesCapture();

    runPythonTest(
      new PyUnitTestLikeProcessWithConsoleTestTask<PyUnitTestProcessRunner>("/testRunner/env/unit", "test_with_skips_and_errors.py",
                                                                            this::createTestRunner) {

        @Override
        protected void checkTestResults(@NotNull final PyUnitTestProcessRunner runner,
                                        @NotNull final String stdout,
                                        @NotNull final String stderr,
                                        @NotNull final String all, int exitCode) {
          assert runner.getFailedTestsCount() > 0 : "We need failed tests to test broken rerun";

          startMessagesCapture();

          EdtTestUtil.runInEdtAndWait(() -> {
            deleteAllTestFiles(myFixture);
            runner.rerunFailedTests();
          });

          final List<Throwable> throwables = getCapturesMessages().first;
          assertThat(throwables)
            .describedAs("Exception shall be thrown")
            .isNotEmpty();
          final Throwable exception = throwables.get(0);
          assertThat(exception).isInstanceOf(ExecutionException.class);
          assertThat(exception.getMessage()).isEqualTo(PyBundle.message("runcfg.tests.cant_rerun"));
          assertThat(getCapturesMessages().second)
            .describedAs("No messages displayed for exception")
            .isNotEmpty();

          stopMessageCapture();
        }
      });
  }

  @Test
  public void testTcMessageEscaped() {
    final String[] messages = {
      "Hello\n",
      ServiceMessageBuilder.testStarted("myTest").toString(),
      ServiceMessageBuilder.testStdOut("myTest").addAttribute("out", "I am\n").toString(),
      ServiceMessageBuilder.testFinished("myTest").toString(),
      "PyCharm"
    };

    runPythonTest(new PyExecutionFixtureTestTask(null) {
      @Override
      public void runTestOn(@NotNull final String sdkHome, @Nullable Sdk existingSdk) throws Exception {
        final Project project = myFixture.getProject();
        final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
        EdtTestUtil.runInEdtAndWait(() -> {
          final PythonConsoleView console = new PythonConsoleView(project, "test", sdk, true);

          console.getComponent(); //To init editor

          Arrays.stream(messages).forEach((s) -> console.print(s, ConsoleViewContentType.NORMAL_OUTPUT));
          console.flushDeferredText();
          try {
            assertEquals("TC messages filtered in wrong way", "Hello\nI am\nPyCharm", console.getText());
          }finally {
            Disposer.dispose(console);
          }
        });
      }
    });
  }

  @Test
  public void testSysPathOrder() {
    runPythonTest(new PyUnitTestProcessWithConsoleTestTask("testRunner/env/unit/sysPath", "test.py") {
{'fraction_non_alphanumeric': 0.09516739662979734, 'fraction_numerical': 0.0026724073936604557, 'mean_word_length': 3.3997387328543436, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3318234', 'n_tokens_mistral': 3724, 'n_tokens_neox': 3584, 'n_words': 714}