1

I have been trying to use MavenCli, giving it ByteArrayOutpurStream-s as stdout and stderr. I have tests that verifies some records were written to those streams. As long as I have one test, all is OK. But, if I introduce another test, it fails, as nothing gets written to stdout.

Here is a snippet (Scala):

class MyIT extends SpecWithJUnit {

  sequential

  trait Ctx extends Scope {
    val outStream = new ByteArrayOutpurStream()
    val errStream = new ByteArrayOutpurStream()
    val pomDir = Files.createTempDirectory("test_pom_").toFile
    val mavenCli = new MavenCli()

    def haveWrote(str: String): Matcher[Int] = {
      contain(str) ^^ { (_: Int) => 
          new String(outStream.toByteArray, "UTF-8") aka "written records" }
    }

    def maven(pom: Elem, goals: String*): Int = {
      val pomFile = new File(pomDir, "pom.xml")

      XML.save(pomFile.getCanonicalPath, pom)

      System.setProperty(
          "maven.multiModuleProjectDirectory", 
          pomDir.getCanonicalPath)

      mavenCli.doMain(
          goals.toArray,
          pomDir.getCanonicalPath, 
          new PrintStream(outStream), 
          new PrintStream(errStream))
    }
  }


  "test 1" should {
    "write something" in new Ctx {
      val pomXml =
        <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>

          <groupId>com.company</groupId>
          <artifactId>some-artifact-id</artifactId>
          <version>1.0.0-SNAPSHOT</version>
          <description>some meaningful description</description>
          <name>some catchy name</name>
          ...
        </project>

      maven(pomXml, "clean" "validate") must haveWrote("something")
    }

    "write something else" in new Ctx {
      val pomXml =
        <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>

          <groupId>com.company</groupId>
          <artifactId>some-artifact-id</artifactId>
          <version>1.0.0-SNAPSHOT</version>
          <description>some meaningful description</description>
          <name>some catchy name</name>
          ... (different than the "write something" test)
        </project>

      maven(pomXml, "clean" "validate") must haveWrote("something else")
    }
  }
}

If I comment out "write something" test, "write something else" passes.

If I comment out "write something else" test (and uncomment "write something"), "write something" passes.

If both are uncommented and executed, one fails ("write something else", as it is sequential).

Adding println-s of outStream after maven execution, the cause seems to be that outStream is empty...

I cannot figure out why, or more importantly, how to workaround.

Any ideas?...

Thanks in advance, Ohad

Ohad
  • 242
  • 3
  • 15

1 Answers1

0

OK, I gave up the MavenCli approach in favor of Maven.execute(MavenExecutionRequest). This, by itself, didn't fix the problem, but I was able to introduce my own ExecutionListener, instead of the default ExecutionEventLogger. My execution listener logged records directly, without using any logging framework, which, seems to solve the issue.

The code now looks something like:

class MyIT extends SpecWithJUnit {

  sequential

  def plexusContainer = {
    val containerConfig = new DefaultContainerConfiguration()
      .setClassPathScanning(PlexusConstants.SCANNING_INDEX)
      .setAutoWiring(true)
      .setName("maven")
    val container = new DefaultPlexusContainer(containerConfig)

    container
  }

  def buildMavenRequest(pomFile: Path,
                        executionListener: ExecutionListener,
                        goals: String*): MavenExecutionRequest = {
    val userProperties = new Properties()
    val executionRequestPopulator = plexusContainer.lookup(classOf[MavenExecutionRequestPopulator])
    val req = new DefaultMavenExecutionRequest()
      .setPom(pomFile.toFile)
      .setBaseDirectory(pomFile.getParent.toFile)
      .setGoals(goals)
      .setInteractiveMode(false)
      .setExecutionListener(executionListener)
      .setUserProperties(userProperties)

    executionRequestPopulator.populateDefaults(req)
  }

  def maven(pomFile: Path,
            executionListener: ExecutionListener,
            goals: String*): MavenExecutionResult = {
    val mavenRequest = buildMavenRequest(pomFile, executionListener, goals: _*)
    val mvn = plexusContainer.lookup(classOf[Maven])

    mvn.execute(mavenRequest)
  }

  def readFile(filename: Path): Seq[String] = {
    Source.fromFile(filename.toString).getLines().foldLeft(Seq.empty[String]){ _ :+ _ }
  }


  trait Ctx extends Scope {
    val pomDir = Files.createTempDirectory("test_pom_").toFile
    val logFile = pomDir.resolve("test_log.log")
    val myExecutionListener = new MyExecutionListener(logFile)

    def haveWrote(str: String): Matcher[MavenExecutionResult] = {
      contain(str) ^^ { (_: MavenExecutionResult) => 
        readFile(logFile) aka "written records" }
    }
  }


  "test 1" should {
    "write something" in new Ctx {
      val pomXml =
        <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>

          <groupId>com.company</groupId>
          <artifactId>some-artifact-id</artifactId>
          <version>1.0.0-SNAPSHOT</version>
          <description>some meaningful description</description>
          <name>some catchy name</name>
          ...
        </project>

      maven(pomXml, "clean" "validate") must haveWrote("something")
    }

    "write something else" in new Ctx {
      val pomXml =
        <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://maven.apache.org/POM/4.0.0">
          <modelVersion>4.0.0</modelVersion>

          <groupId>com.company</groupId>
          <artifactId>some-artifact-id</artifactId>
          <version>1.0.0-SNAPSHOT</version>
          <description>some meaningful description</description>
          <name>some catchy name</name>
          ... (different than the "write something" test)
        </project>

      maven(pomXml, "clean" "validate") must haveWrote("something else")
    }
  }
}
Ohad
  • 242
  • 3
  • 15