project/ScroogeRunner.scala (228 lines of code) (raw):

import sbt._ import Keys._ import java.io.File // Runs the freshly-built Scrooge binary (used for integration tests and benchmarking) // How to run: `sbt genTestThrift` or `sbt genBenchmarkThrift` object ScroogeRunner { val apacheJavaNamespace = """-n thrift.defaults=thrift.apache_java_defaults |-n thrift.colors=thrift.apache_java_colors |-n thrift.test=thrift.apache_java_test |-n thrift.test1=thrift.apache_java_test1 |-n thrift.test2=thrift.apache_java_test2 |-n thrift.collision=thrift.apache_java_collision |-n thrift.def.default=thrift.apache_java_def.default_ns |-n foo=apache_java_foo |-n bar=apache_java_bar |-n com.fake=com.apache_java_fake |-n com.twitter.scrooge.integration_scala=com.twitter.scrooge.integration_apache |--default-java-namespace apache_java_thrift """.stripMargin val androidNamespace = """-n thrift.defaults=thrift.android_defaults |-n thrift.colors=thrift.android_colors |-n thrift.test=thrift.android_test |-n thrift.test1=thrift.android_test1 |-n thrift.test2=thrift.android_test2 |-n thrift.collision=thrift.android_collision |-n thrift.constants=thrift.android_constants |-n thrift.def.default=thrift.android_def.default |-n foo=android_foo |-n bar=android_bar |-n com.fake=com.android_fake |-n com.twitter.scrooge.integration_scala=com.twitter.scrooge.integration_android |--default-java-namespace android_thrift_default_namespace """.stripMargin sealed abstract class Language(val scroogeName: String, val defaultNamespace: String) case object Scala extends Language("scala", "") case object ApacheJava extends Language("java", apacheJavaNamespace) case object Android extends Language("android", androidNamespace) class Runner(out: Keys.TaskStreams, cp: Classpath, outputDir: File) { def run( language: Language, namespace: String, finagle: Boolean = true, args: String, genAdapt: Boolean = true ): Unit = { val finagleArg = if (finagle) "--finagle" else "" val adaptArg = if (genAdapt) "--gen-adapt" else "" val command = s"java -cp ${cp.files.absString} com.twitter.scrooge.Main --verbose $finagleArg $adaptArg " + s" -d ${outputDir.getAbsolutePath} -l ${language.scroogeName} $namespace $args" val result: Int = scala.sys.process.Process(command) ! out.log if (result != 0) { out.log.error("Scrooge run failed. Tried to run:") out.log.error(command) throw new RuntimeException("Scrooge run failed.") } } def runScrooge(languages: Seq[Language], args: String, genAdapt: Boolean = true) = languages foreach { lang => run(lang, lang.defaultNamespace, finagle = true, genAdapt = genAdapt, args = args) } def section(description: String)(f: => Unit) = { out.log.info(s"Running Scrooge on $description") f } def filesInDir(dir: String) = recursiveListFiles(new File(dir)).map(_.toString).filter(_.endsWith(".thrift")) def recursiveListFiles(f: File): Array[File] = { val these = f.listFiles these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles) } def filesGenerated: Seq[File] = (outputDir ** "*.scala").get.toSeq ++ (outputDir ** "*.java").get.toSeq } val genAdaptiveScroogeTestThrift = TaskKey[Seq[File]]( "genAdaptiveScroogeTestThrift", "Uses Scrooge to generate code from thrift sources, for use in Adaptive Scrooge tests") val genAdaptiveScroogeTestThriftTask = genAdaptiveScroogeTestThrift := { val base = baseDirectory.value val runner = new Runner(streams.value, dependencyClasspath.value, sourceManaged.value) import runner._ val files = filesInDir(s"$base/src/test/thrift") mkString " " runScrooge(Seq(Scala), files) filesGenerated } val genTestThrift = TaskKey[Seq[File]]( "genTestThrift", "Uses Scrooge to generate code from thrift sources, for use in tests") val genTestThriftTask = genTestThrift := { val base = baseDirectory.value val runner = new Runner(streams.value, dependencyClasspath.value, sourceManaged.value) import runner._ section("defaults/") { val files = filesInDir(s"$base/src/test/thrift/defaults") mkString " " runScrooge(Seq(ApacheJava, Scala, Android), files) } section("relative/") { val files = filesInDir(s"$base/src/test/thrift/relative") .filter(_.contains("include")) mkString " " runScrooge(Seq(Scala, Android), files) val file = s"$base/src/test/thrift/relative/candy.thrift" val importArg = s"--include-path $base/src/test/thrift/relative/dir2${File.pathSeparator}$base/src/test/thrift/relative/dir3" runScrooge(Seq(Scala, Android), s"$file $importArg") } val airportThriftFiles = filesInDir(s"$base/src/test/thrift/airport") mkString " " section("airport/ for Finagle usage") { runScrooge(Seq(Scala, Android), airportThriftFiles) } section("airport/ for vanilla usage") { val scalaVanillaNamespace = """-n thrift.test=vanilla.test |-n thrift.test1=vanilla.test1 |-n thrift.test2=vanilla.test2 """.stripMargin val androidVanillaNamespace = """-n androidthrift.test=vanilla_android.test |-n androidthrift.test1=vanilla_android.test1 |-n androidthrift.test2=vanilla_android.test2 """.stripMargin run( language = Scala, namespace = scalaVanillaNamespace, finagle = false, args = airportThriftFiles) run( language = Android, namespace = androidVanillaNamespace, finagle = false, args = airportThriftFiles) } section("namespace/ with bar and java_bar as default namespace") { val files = filesInDir(s"$base/src/test/thrift/namespace") mkString " " run( language = Scala, namespace = s"${Scala.defaultNamespace} --default-java-namespace bar", args = files) run( language = Android, namespace = s"${Android.defaultNamespace} --default-java-namespace android_bar", args = files) } section("integration/") { val files = filesInDir(s"$base/src/test/thrift/integration") mkString " " val androidFiles = (filesInDir(s"$base/src/test/thrift/integration") ++ filesInDir( s"$base/src/test/thrift/android_integration")) mkString " " run( language = Scala, namespace = s"${Scala.defaultNamespace} -n thrift.test=com.twitter.scrooge.integration_scala", args = s"--disable-strict $files") run( language = ApacheJava, namespace = s"${ApacheJava.defaultNamespace} -n thrift.test=com.twitter.scrooge.integration_apache", args = s"--disable-strict $files") run( language = Android, namespace = s"${Android.defaultNamespace} -n thrift.test=com.twitter.scrooge.integration_android", args = s"--disable-strict $androidFiles" ) } section("finagle_integration/") { val files = filesInDir(s"$base/src/test/thrift/finagle_integration") mkString " " run( language = Scala, namespace = s"${Scala.defaultNamespace} -n thrift.test=com.twitter.scrooge.finagle_integration.thriftscala", args = s"--disable-strict $files" ) run( language = ApacheJava, namespace = s"${ApacheJava.defaultNamespace} -n thrift.test=com.twitter.scrooge.finagle_integration.thriftjava", args = s"--disable-strict $files" ) } section("standalone/") { val scalaFiles = filesInDir(s"$base/src/test/thrift/standalone") mkString " " val javaFiles = s"$base/src/test/thrift/standalone/constructorRequired.thrift " + s"$base/src/test/thrift/standalone/enumSet.thrift " + s"$base/src/test/thrift/standalone/exception_fields.thrift " + s"$base/src/test/thrift/standalone/passthrough.thrift " + s"$base/src/test/thrift/standalone/validations.thrift " runScrooge(Seq(Scala), scalaFiles) runScrooge(Seq(Android), javaFiles) runScrooge(Seq(ApacheJava), s"--java-passthrough $javaFiles") } section("scala/") { val files = filesInDir(s"$base/src/test/thrift/scala") mkString " " runScrooge(Seq(ApacheJava, Scala), files) } section("constant_sets.thrift") { val file = s"$base/src/test/thrift/constant_sets.thrift" runScrooge(Seq(Scala, Android), file) } filesGenerated } val genBenchmarkThrift = TaskKey[Seq[File]]( "genBenchmarkThrift", "Uses Scrooge to generate sources to use in benchmarking") val genBenchmarkThriftTask = genBenchmarkThrift := { val base = baseDirectory.value val runner = new Runner(streams.value, dependencyClasspath.value, sourceManaged.value) import runner._ section("benchmark/") { val files = filesInDir(s"$base/src/main/thrift") mkString " " runScrooge(Seq(Scala, Android), files) } filesGenerated } val genSerializerTestThrift = TaskKey[Seq[File]]( "genSerializerTestThrift", "Uses Scrooge to generate sources to use in serializer tests") val genSerializerTestThriftTask = genSerializerTestThrift := { val base = baseDirectory.value val runner = new Runner(streams.value, dependencyClasspath.value, sourceManaged.value) import runner._ section("serializer/") { val files = filesInDir(s"$base/src/test/thrift") mkString " " runScrooge(Seq(Scala), files) } filesGenerated } }