<commit_before>/* sbt -- Simple Build Tool
 * Copyright 2009  <NAME>
 */

package sbt
package test

import java.io.File

import scala.util.control.NonFatal
import sbt.internal.scripted._
import sbt.io.{ DirectoryFilter, HiddenFileFilter, IO }
import sbt.io.IO.wrapNull
import sbt.io.FileFilter._
import sbt.internal.io.Resources
import sbt.internal.util.{ BufferedLogger, ConsoleLogger, FullLogger }
import sbt.util.{ AbstractLogger, Logger }

import scala.collection.mutable
import scala.collection.parallel.mutable.ParSeq

final class ScriptedTests(resourceBaseDirectory: File,
                          bufferLog: Boolean,
                          launcher: File,
                          launchOpts: Seq[String]) {
  import sbt.io.syntax._
  import ScriptedTests._
  private val testResources = new Resources(resourceBaseDirectory)

  val ScriptFilename = "test"
  val PendingScriptFilename = "pending"

  def scriptedTest(group: String, name: String, log: xsbti.Logger): Seq[TestRunner] =
    scriptedTest(group, name, Logger.xlog2Log(log))
  def scriptedTest(group: String, name: String, log: Logger): Seq[TestRunner] =
    singleScriptedTest(group, name, emptyCallback, log)

  /** Returns a sequence of test runners that have to be applied in the call site. */
  def singleScriptedTest(group: String,
                         name: String,
                         prescripted: File => Unit,
                         log: Logger): Seq[TestRunner] = {

    // Test group and names may be file filters (like '*')
    for (groupDir <- (resourceBaseDirectory * group).get; nme <- (groupDir * name).get) yield {
      val g = groupDir.getName
      val n = nme.getName
      val label = s"$g / $n"
      () =>
        {
          println(s"Running $label")
          val result = testResources.readWriteResourceDirectory(g, n) { testDirectory =>
            val buffer = new BufferedLogger(new FullLogger(log))
            val singleTestRunner = () => {
              val handlers = createScriptedHandlers(testDirectory, buffer)
              val runner = new BatchScriptRunner
              val states = new mutable.HashMap[StatementHandler, Any]()
              commonRunTest(label, testDirectory, prescripted, handlers, runner, states, buffer)
            }
            runOrHandleDisabled(label, testDirectory, singleTestRunner, buffer)
          }
          Seq(result)
        }
    }
  }

  private def createScriptedHandlers(testDir: File,
                                     buffered: Logger): Map[Char, StatementHandler] = {
    val fileHandler = new FileCommands(testDir)
    val sbtHandler = new SbtHandler(testDir, launcher, buffered, launchOpts)
    Map('$' -> fileHandler, '>' -> sbtHandler, '#' -> CommentHandler)
  }

  /** Returns a sequence of test runners that have to be applied in the call site. */
  def batchScriptedRunner(
      testGroupAndNames: Seq[(String, String)],
      prescripted: File => Unit,
      log: Logger
  ): Seq[TestRunner] = {
    // Test group and names may be file filters (like '*')
    val groupAndNameDirs = {
      for {
        (group, name) <- testGroupAndNames
        groupDir <- resourceBaseDirectory.*(group).get
        testDir <- groupDir.*(name).get
      } yield (groupDir, testDir)
    }

    val labelsAndDirs = groupAndNameDirs.map {
      case (groupDir, nameDir) =>
        val groupName = groupDir.getName
        val testName = nameDir.getName
        val testLabel = s"$groupName / $testName"
        val testDirectory = testResources.readOnlyResourceDirectory(groupName, testName)
        testLabel -> testDirectory
    }

    val batchSeed = labelsAndDirs.size / 4
    val batchSize = if (batchSeed == 0) labelsAndDirs.size else batchSeed
    Seq(labelsAndDirs).map { batch => () =>
      IO.withTemporaryDirectory(runBatchedTests(batch, _, prescripted, log))
    }.toList
  }

  /** Defines the batch execution of scripted tests.
   *
   * Scripted tests are run one after the other one recycling the handlers, under
   * the assumption that handlers do not produce side effects that can change scripted
   * tests' behaviours.
   *
   * In batch mode, the test runner performs these operations between executions:
   *
   * 1. Delete previous test files in the common test directory.
   * 2. Copy over next test files to the common test directory.
   * 3. Reload the sbt handler.
   *
   * @param groupedTests The labels and directories of the tests to run.
   * @param tempTestDir The common test directory.
   * @param preHook The hook to run before scripted execution.
   * @param log The logger.
   */
  private def runBatchedTests(
      groupedTests: Seq[(String, File)],
      tempTestDir: File,
      preHook: File => Unit,
      log: Logger
  ): Seq[Option[String]] = {

    val runner = new BatchScriptRunner
    val buffer = new BufferedLogger(new FullLogger(log))
    val handlers = createScriptedHandlers(tempTestDir, buffer)
    val states = new BatchScriptRunner.States
    val seqHandlers = handlers.values.toList
    runner.initStates(states, seqHandlers)

    def runBatchTests = {
      groupedTests.map {
        case (label, originalDir) =>
          println(s"Running $label")
          // Copy test's contents and reload the sbt instance to pick them up
          IO.copyDirectory(originalDir, tempTestDir)

          val runTest = () => {
            // Reload and initialize (to reload contents of .sbtrc files)
            val sbtHandler = handlers.getOrElse('>', sys.error("Missing sbt handler."))
            val statement =
              Statement(";reload;initialize", Nil, successExpected = true, line = -1)
            runner.processStatement(sbtHandler.asInstanceOf[SbtHandler], statement, states)
            commonRunTest(label, tempTestDir, preHook, handlers, runner, states, buffer)
          }

          // Run the test and delete files (except global that holds local scala jars)
          val result = runOrHandleDisabled(label, tempTestDir, runTest, buffer)
          IO.delete(tempTestDir.*("*" -- "global").get)
          result
      }
    }

    try runBatchTests
    finally runner.cleanUpHandlers(seqHandlers, states)
  }

  private def runOrHandleDisabled(
      label: String,
      testDirectory: File,
      runTest: () => Option[String],
      log: Logger
  ): Option[String] = {<commit_msg>Use scripted hook to run reload<commit_after>/* sbt -- Simple Build Tool
 * Copyright 2009  <NAME>
 */

package sbt
package test

import java.io.File

import scala.util.control.NonFatal
import sbt.internal.scripted._
import sbt.io.{ DirectoryFilter, HiddenFileFilter, IO }
import sbt.io.IO.wrapNull
import sbt.io.FileFilter._
import sbt.internal.io.Resources
import sbt.internal.util.{ BufferedLogger, ConsoleLogger, FullLogger }
import sbt.util.{ AbstractLogger, Logger }

import scala.collection.mutable
import scala.collection.parallel.mutable.ParSeq

final class ScriptedTests(resourceBaseDirectory: File,
                          bufferLog: Boolean,
                          launcher: File,
                          launchOpts: Seq[String]) {
  import sbt.io.syntax._
  import ScriptedTests._
  private val testResources = new Resources(resourceBaseDirectory)

  val ScriptFilename = "test"
  val PendingScriptFilename = "pending"

  def scriptedTest(group: String, name: String, log: xsbti.Logger): Seq[TestRunner] =
    scriptedTest(group, name, Logger.xlog2Log(log))
  def scriptedTest(group: String, name: String, log: Logger): Seq[TestRunner] =
    singleScriptedTest(group, name, emptyCallback, log)

  /** Returns a sequence of test runners that have to be applied in the call site. */
  def singleScriptedTest(group: String,
                         name: String,
                         prescripted: File => Unit,
                         log: Logger): Seq[TestRunner] = {

    // Test group and names may be file filters (like '*')
    for (groupDir <- (resourceBaseDirectory * group).get; nme <- (groupDir * name).get) yield {
      val g = groupDir.getName
      val n = nme.getName
      val label = s"$g / $n"
      () =>
        {
          println(s"Running $label")
          val result = testResources.readWriteResourceDirectory(g, n) { testDirectory =>
            val buffer = new BufferedLogger(new FullLogger(log))
            val singleTestRunner = () => {
              val handlers = createScriptedHandlers(testDirectory, buffer)
              val runner = new BatchScriptRunner
              val states = new mutable.HashMap[StatementHandler, Any]()
              commonRunTest(label, testDirectory, prescripted, handlers, runner, states, buffer)
            }
            runOrHandleDisabled(label, testDirectory, singleTestRunner, buffer)
          }
          Seq(result)
        }
    }
  }

  private def createScriptedHandlers(testDir: File,
                                     buffered: Logger): Map[Char, StatementHandler] = {
    val fileHandler = new FileCommands(testDir)
    val sbtHandler = new SbtHandler(testDir, launcher, buffered, launchOpts)
    Map('$' -> fileHandler, '>' -> sbtHandler, '#' -> CommentHandler)
  }

  /** Returns a sequence of test runners that have to be applied in the call site. */
  def batchScriptedRunner(
      testGroupAndNames: Seq[(String, String)],
      prescripted: File => Unit,
      log: Logger
  ): Seq[TestRunner] = {
    // Test group and names may be file filters (like '*')
    val groupAndNameDirs = {
      for {
        (group, name) <- testGroupAndNames
        groupDir <- resourceBaseDirectory.*(group).get
        testDir <- groupDir.*(name).get
      } yield (groupDir, testDir)
    }

    val labelsAndDirs = groupAndNameDirs.map {
      case (groupDir, nameDir) =>
        val groupName = groupDir.getName
        val testName = nameDir.getName
        val testLabel = s"$groupName / $testName"
        val testDirectory = testResources.readOnlyResourceDirectory(groupName, testName)
        testLabel -> testDirectory
    }

    val batchSeed = labelsAndDirs.size / 4
    val batchSize = if (batchSeed == 0) labelsAndDirs.size else batchSeed
    Seq(labelsAndDirs).map { batch => () =>
      IO.withTemporaryDirectory(runBatchedTests(batch, _, prescripted, log))
    }.toList
  }

  /** Defines the batch execution of scripted tests.
   *
   * Scripted tests are run one after the other one recycling the handlers, under
   * the assumption that handlers do not produce side effects that can change scripted
   * tests' behaviours.
   *
   * In batch mode, the test runner performs these operations between executions:
   *
   * 1. Delete previous test files in the common test directory.
   * 2. Copy over next test files to the common test directory.
   * 3. Reload the sbt handler.
   *
   * @param groupedTests The labels and directories of the tests to run.
   * @param tempTestDir The common test directory.
   * @param preHook The hook to run before scripted execution.
   * @param log The logger.
   */
  private def runBatchedTests(
      groupedTests: Seq[(String, File)],
      tempTestDir: File,
      preHook: File => Unit,
      log: Logger
  ): Seq[Option[String]] = {

    val runner = new BatchScriptRunner
    val buffer = new BufferedLogger(new FullLogger(log))
    val handlers = createScriptedHandlers(tempTestDir, buffer)
    val states = new BatchScriptRunner.States
    val seqHandlers = handlers.values.toList
    runner.initStates(states, seqHandlers)

    def runBatchTests = {
      groupedTests.map {
        case (label, originalDir) =>
          println(s"Running $label")
          // Copy test's contents and reload the sbt instance to pick them up
          IO.copyDirectory(originalDir, tempTestDir)

          val runTest = () => {
            // Reload and initialize (to reload contents of .sbtrc files)
            val sbtHandler = handlers.getOrElse('>', sys.error("Missing sbt handler."))
            val statement =
              Statement(";reload;initialize", Nil, successExpected = true, line = -1)
            // Run reload inside the hook to reuse error handling for pending tests
            val wrapHook = (file: File) => {
              preHook(file)
              runner.processStatement(sbtHandler.asInstanceOf[SbtHandler], statement, states)
            }
            commonRunTest(label, tempTestDir, wrapHook, handlers, runner, states, buffer)
          }

          // Run the test and delete files (except global that holds local scala jars)
          val result = runOrHandleDisabled(label, tempTestDir, runTest, buffer)
          IO.delete(tempTestDir.*("*" -- "global").get)
          result
      }
    }

    try runBatchTests
    finally runner.cleanUpHandlers(seqHandlers, states)
  }

  private def runOrHandleDisabled(
      label: String,
      testDirectory: File,
      runTest: () => Option[String],
      log: Logger
  ): Option[String] = {
{'fraction_non_alphanumeric': 0.09347250350521888, 'fraction_numerical': 0.0017136625642623462, 'mean_word_length': 2.632993774759479, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4438114', 'n_tokens_mistral': 3644, 'n_tokens_neox': 3518, 'n_words': 1076}