Disabled external gits
This commit is contained in:
		
							
								
								
									
										38
									
								
								cs320-clp/test/scala/amyc/test/CodegenTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								cs320-clp/test/scala/amyc/test/CodegenTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream
 | 
			
		||||
 | 
			
		||||
import amyc.analyzer.{NameAnalyzer, TypeChecker}
 | 
			
		||||
import amyc.codegen._
 | 
			
		||||
import amyc.parsing._
 | 
			
		||||
import amyc.utils._
 | 
			
		||||
import amyc.wasm.Module
 | 
			
		||||
 | 
			
		||||
import scala.collection.JavaConverters._
 | 
			
		||||
import scala.sys.process._
 | 
			
		||||
 | 
			
		||||
class CodegenTests extends ExecutionTests {
 | 
			
		||||
 | 
			
		||||
  object CodePrinterExecutor extends Pipeline[Module, Unit] {
 | 
			
		||||
    def run(ctx: Context)(m: Module) = {
 | 
			
		||||
      CodePrinter.run(ctx)(m)
 | 
			
		||||
      val fileName = s"${m.name}.js"
 | 
			
		||||
 | 
			
		||||
      // Consume all standard input!
 | 
			
		||||
      val input = Console.in.lines.iterator().asScala.toList.mkString("\n")
 | 
			
		||||
      val inputS = new ByteArrayInputStream(input.getBytes("UTF-8"))
 | 
			
		||||
 | 
			
		||||
      val exitCode = s"nodejs wasmout/$fileName" #< inputS ! ProcessLogger(Console.out.println, Console.err.println)
 | 
			
		||||
      if (exitCode != 0)
 | 
			
		||||
        throw AmycFatalError("Nonzero code returned from nodejs")
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val pipeline =
 | 
			
		||||
    Lexer andThen
 | 
			
		||||
    Parser andThen
 | 
			
		||||
    NameAnalyzer andThen
 | 
			
		||||
    TypeChecker andThen
 | 
			
		||||
    CodeGen andThen
 | 
			
		||||
    CodePrinterExecutor
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								cs320-clp/test/scala/amyc/test/CompilerTest.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								cs320-clp/test/scala/amyc/test/CompilerTest.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.util.stream.Collectors
 | 
			
		||||
 | 
			
		||||
import amyc.utils._
 | 
			
		||||
import org.junit.Assert.fail
 | 
			
		||||
 | 
			
		||||
abstract class CompilerTest extends TestUtils {
 | 
			
		||||
  private def runPipeline(pipeline: Pipeline[List[File], Unit], fileNames: List[String]) = {
 | 
			
		||||
    val ctx = Context(new Reporter, fileNames)
 | 
			
		||||
    val files = ctx.files.map(new File(_))
 | 
			
		||||
    pipeline.run(ctx)(files)
 | 
			
		||||
    ctx.reporter.terminateIfErrors()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private def runPipelineRedirected(
 | 
			
		||||
    pipeline: Pipeline[List[File], Unit],
 | 
			
		||||
    compiledFiles: List[String],
 | 
			
		||||
    input: String
 | 
			
		||||
  ): String = {
 | 
			
		||||
    testWithRedirectedIO(runPipeline(pipeline, compiledFiles), input)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private def assertEqual(output: String, expected: String) = {
 | 
			
		||||
    val rejectLine = (s: String) =>
 | 
			
		||||
      s.isEmpty ||
 | 
			
		||||
        s.startsWith("[ Info  ]") ||
 | 
			
		||||
        s.startsWith("[Warning]") ||
 | 
			
		||||
        s.startsWith("[ Error ]") ||
 | 
			
		||||
        s.startsWith("[ Fatal ]")
 | 
			
		||||
    def filtered(s: String) = s.lines.filter(rejectLine(_)==false).collect(Collectors.joining("\n"));
 | 
			
		||||
    val filteredOutput = filtered(output)
 | 
			
		||||
    val filteredExpected = filtered(expected)
 | 
			
		||||
    if (filteredOutput != filteredExpected) {
 | 
			
		||||
      val sb = new StringBuffer()
 | 
			
		||||
      sb.append("\nOutput is different:\n")
 | 
			
		||||
      sb.append("\nOutput: \n")
 | 
			
		||||
      sb.append(filteredOutput)
 | 
			
		||||
      sb.append("\n\nExpected output: \n")
 | 
			
		||||
      sb.append(filteredExpected)
 | 
			
		||||
      sb.append("\n")
 | 
			
		||||
      fail(sb.toString)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected def compareOutputs(
 | 
			
		||||
    pipeline: Pipeline[List[File], Unit],
 | 
			
		||||
    compiledFiles: List[String],
 | 
			
		||||
    expectedFile: String,
 | 
			
		||||
    input: String = ""
 | 
			
		||||
  ) = {
 | 
			
		||||
    try {
 | 
			
		||||
      val output = runPipelineRedirected(pipeline, compiledFiles, input)
 | 
			
		||||
      val expected = scala.io.Source.fromFile(new File(expectedFile)).mkString
 | 
			
		||||
      assertEqual(output, expected)
 | 
			
		||||
    } catch {
 | 
			
		||||
      // We only want to catch AmyFatalError gracefully, the rest can propagate
 | 
			
		||||
      case AmycFatalError(msg) =>
 | 
			
		||||
        fail(s"\n  $msg\n")
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected def demandPass(
 | 
			
		||||
    pipeline: Pipeline[List[File], Unit],
 | 
			
		||||
    compiledFiles: List[String],
 | 
			
		||||
    input: String = ""
 | 
			
		||||
  ) = {
 | 
			
		||||
    try {
 | 
			
		||||
      runPipelineRedirected(pipeline, compiledFiles, input)
 | 
			
		||||
    } catch {
 | 
			
		||||
      case AmycFatalError(msg) =>
 | 
			
		||||
        fail(s"\n  $msg\n")
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected def demandFailure(
 | 
			
		||||
    pipeline: Pipeline[List[File], Unit],
 | 
			
		||||
    compiledFiles: List[String],
 | 
			
		||||
    input: String = ""
 | 
			
		||||
  ) = {
 | 
			
		||||
    try {
 | 
			
		||||
      runPipelineRedirected(pipeline, compiledFiles, input)
 | 
			
		||||
      fail("Test should fail but it passed!")
 | 
			
		||||
    } catch {
 | 
			
		||||
      case AmycFatalError(_) =>
 | 
			
		||||
      // Ok, this is what we wanted. Other exceptions should propagate though
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								cs320-clp/test/scala/amyc/test/ExecutionTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cs320-clp/test/scala/amyc/test/ExecutionTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
abstract class ExecutionTests extends TestSuite {
 | 
			
		||||
 | 
			
		||||
  val baseDir = "interpreter"
 | 
			
		||||
 | 
			
		||||
  val outputExt = "txt"
 | 
			
		||||
 | 
			
		||||
  @Test def testEmptyObject = shouldOutput("EmptyObject")
 | 
			
		||||
 | 
			
		||||
  @Test def testMinimalError = shouldFail("MinimalError")
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								cs320-clp/test/scala/amyc/test/LexerTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								cs320-clp/test/scala/amyc/test/LexerTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import amyc.parsing._
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
class LexerTests extends TestSuite {
 | 
			
		||||
  val pipeline = Lexer andThen DisplayTokens
 | 
			
		||||
 | 
			
		||||
  val baseDir = "lexer"
 | 
			
		||||
 | 
			
		||||
  val outputExt = "txt"
 | 
			
		||||
 | 
			
		||||
  @Test def testKeywords = shouldOutput("Keywords")
 | 
			
		||||
 | 
			
		||||
  @Test def testSingleAmp = shouldFail("SingleAmp")
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								cs320-clp/test/scala/amyc/test/NameAnalyzerTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cs320-clp/test/scala/amyc/test/NameAnalyzerTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import amyc.analyzer.{NameAnalyzer, SymbolTable}
 | 
			
		||||
import amyc.ast.SymbolicTreeModule.Program
 | 
			
		||||
import amyc.ast.{Identifier, SymbolicPrinter}
 | 
			
		||||
import amyc.parsing._
 | 
			
		||||
import amyc.utils._
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
import scala.language.implicitConversions
 | 
			
		||||
 | 
			
		||||
class NameAnalyzerTests extends TestSuite {
 | 
			
		||||
  // A little hackery to overcome that Identifier names do not refresh over pipeline runs...
 | 
			
		||||
  private class TestUniquePrinter extends SymbolicPrinter {
 | 
			
		||||
    private val counter = new UniqueCounter[String]
 | 
			
		||||
    private val map = scala.collection.mutable.Map[Identifier, Int]()
 | 
			
		||||
    override implicit def printName(name: Identifier)(implicit printUniqueIds: Boolean): Document = {
 | 
			
		||||
      if (printUniqueIds) {
 | 
			
		||||
        val id = map.getOrElseUpdate(name, counter.next(name.name))
 | 
			
		||||
        s"${name.name}_$id"
 | 
			
		||||
      } else {
 | 
			
		||||
        name.name
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private val treePrinterS: Pipeline[(Program, SymbolTable), Unit] = {
 | 
			
		||||
    new Pipeline[(Program, SymbolTable), Unit] {
 | 
			
		||||
      def run(ctx: Context)(v: (Program, SymbolTable)) = {
 | 
			
		||||
        println((new TestUniquePrinter)(v._1)(true))
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val pipeline = Lexer andThen Parser andThen NameAnalyzer andThen treePrinterS
 | 
			
		||||
 | 
			
		||||
  val baseDir = "nameAnalyzer"
 | 
			
		||||
 | 
			
		||||
  val outputExt = "scala"
 | 
			
		||||
 | 
			
		||||
  @Test def testParamAndLocal = shouldOutput("ParamAndLocal")
 | 
			
		||||
 | 
			
		||||
  @Test def testArgumentNumberFunction = shouldFail("ArgumentNumberFunction")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								cs320-clp/test/scala/amyc/test/ParserTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								cs320-clp/test/scala/amyc/test/ParserTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import amyc.parsing._
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
class ParserTests extends TestSuite with amyc.MainHelpers {
 | 
			
		||||
  val pipeline = Lexer andThen Parser andThen treePrinterN("")
 | 
			
		||||
 | 
			
		||||
  val baseDir = "parser"
 | 
			
		||||
 | 
			
		||||
  val outputExt = "scala"
 | 
			
		||||
 | 
			
		||||
  @Test def testEmpty = shouldOutput("Empty")
 | 
			
		||||
  @Test def testLiterals = shouldOutput("Literals")
 | 
			
		||||
 | 
			
		||||
  @Test def testEmptyFile = shouldFail("EmptyFile")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								cs320-clp/test/scala/amyc/test/TestSuite.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								cs320-clp/test/scala/amyc/test/TestSuite.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
import amyc.utils.Pipeline
 | 
			
		||||
 | 
			
		||||
abstract class TestSuite extends CompilerTest {
 | 
			
		||||
  val pipeline: Pipeline[List[File], Unit]
 | 
			
		||||
 | 
			
		||||
  val baseDir: String
 | 
			
		||||
  lazy val effectiveBaseDir: String =
 | 
			
		||||
    // getClass.getResource(s"/$baseDir").getPath
 | 
			
		||||
    s"test/resources/$baseDir"
 | 
			
		||||
 | 
			
		||||
  val passing = "passing"
 | 
			
		||||
  val failing = "failing"
 | 
			
		||||
  val outputs = "outputs"
 | 
			
		||||
 | 
			
		||||
  val outputExt: String
 | 
			
		||||
 | 
			
		||||
  def shouldOutput(inputFiles: List[String], outputFile: String, input: String = ""): Unit = {
 | 
			
		||||
    compareOutputs(
 | 
			
		||||
      pipeline,
 | 
			
		||||
      inputFiles map (f => s"$effectiveBaseDir/$passing/$f.scala"),
 | 
			
		||||
      s"$effectiveBaseDir/$outputs/$outputFile.$outputExt",
 | 
			
		||||
      input
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def shouldOutput(inputFile: String): Unit = {
 | 
			
		||||
    shouldOutput(List(inputFile), inputFile)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def shouldFail(inputFiles: List[String], input: String = ""): Unit = {
 | 
			
		||||
    demandFailure(
 | 
			
		||||
      pipeline,
 | 
			
		||||
      inputFiles map (f => s"$effectiveBaseDir/$failing/$f.scala"),
 | 
			
		||||
      input
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def shouldFail(inputFile: String): Unit = {
 | 
			
		||||
    shouldFail(List(inputFile))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def shouldPass(inputFiles: List[String], input: String = ""): Unit = {
 | 
			
		||||
    demandPass(pipeline, inputFiles map (f => s"$effectiveBaseDir/$passing/$f.scala"), input)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def shouldPass(inputFile: String): Unit = {
 | 
			
		||||
    shouldPass(List(inputFile))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								cs320-clp/test/scala/amyc/test/TestUtils.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								cs320-clp/test/scala/amyc/test/TestUtils.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import java.io._
 | 
			
		||||
 | 
			
		||||
/** Some utilities for running tests */
 | 
			
		||||
trait TestUtils {
 | 
			
		||||
  /** Run test,
 | 
			
		||||
    * with input also redirected from a String,
 | 
			
		||||
    * and output is redirected to a local StringBuilder.
 | 
			
		||||
    */
 | 
			
		||||
  def testWithRedirectedIO[T](test: => T, input: String): String = {
 | 
			
		||||
    import scala.Console._
 | 
			
		||||
    val inputS  = new StringReader(input)
 | 
			
		||||
    val outputS = new ByteArrayOutputStream()
 | 
			
		||||
    withOut(outputS) {
 | 
			
		||||
      withErr(outputS) {
 | 
			
		||||
        withIn(inputS) {
 | 
			
		||||
          test
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    outputS.toString()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								cs320-clp/test/scala/amyc/test/TyperTests.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								cs320-clp/test/scala/amyc/test/TyperTests.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
package amyc.test
 | 
			
		||||
 | 
			
		||||
import amyc.analyzer.{NameAnalyzer, TypeChecker}
 | 
			
		||||
import amyc.parsing._
 | 
			
		||||
import amyc.utils._
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
class TyperTests extends TestSuite {
 | 
			
		||||
  // We need a unit pipeline
 | 
			
		||||
  private def unit[A]: Pipeline[A, Unit] = {
 | 
			
		||||
    new Pipeline[A, Unit] {
 | 
			
		||||
      def run(ctx: Context)(v: A) = ()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val pipeline = Lexer andThen Parser andThen NameAnalyzer andThen TypeChecker andThen unit
 | 
			
		||||
 | 
			
		||||
  val baseDir = "typer"
 | 
			
		||||
 | 
			
		||||
  val outputExt = "" // No output files for typechecking
 | 
			
		||||
 | 
			
		||||
  @Test def testArithError1 = shouldFail("ArithError1")
 | 
			
		||||
 | 
			
		||||
  @Test def testArithmetic = shouldPass("Arithmetic")
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user