Skip to content

Commit

Permalink
Make riddl-testkit work
Browse files Browse the repository at this point in the history
  • Loading branch information
reidspencer committed Nov 3, 2024
1 parent 1f99f00 commit fad24ef
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 127 deletions.
21 changes: 13 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ lazy val license = ALv2(yyyy = "2019-2025", copyrightOwner = "Ossum Inc.", licen

def cpDep(cp: CrossProject): CrossClasspathDependency = cp % "compile->compile;test->test"
def pDep(p: Project): ClasspathDependency = p % "compile->compile;test->test"
def tkDep(cp: CrossProject): CrossClasspathDependency = cp % "compile->compile;test->test"

lazy val riddl: Project = Root("riddl", startYr = startYear /*, license = "Apache-2.0" */ )
.configure(With.noPublishing, With.git, With.dynver, With.noMiMa)
Expand Down Expand Up @@ -90,7 +91,7 @@ lazy val utilsJS = utils_cp.js
val Language = config("language")
lazy val language_cp: CrossProject = CrossModule("language", "riddl-language")(JVM, JS)
.dependsOn(cpDep(utils_cp))
.configure(With.typical, With.publishing, With.headerLicense("Apache-2.0"))
.configure(With.typical, With.headerLicense("Apache-2.0"))
.settings(
description := "Abstract Syntax Tree and basic RIDDL language parser",
scalacOptions ++= Seq("-explain", "--explain-types", "--explain-cyclic", "--no-warnings"),
Expand Down Expand Up @@ -129,7 +130,7 @@ lazy val languageJS = language_cp.js.dependsOn(utilsJS)
val Passes = config("passes")
lazy val passes_cp = CrossModule("passes", "riddl-passes")(JVM, JS)
.dependsOn(cpDep(utils_cp), cpDep(language_cp))
.configure(With.typical, With.publishing, With.headerLicense("Apache-2.0"))
.configure(With.typical, With.headerLicense("Apache-2.0"))
.settings(
Test / parallelExecution := false,
scalacOptions ++= Seq("-explain", "--explain-types", "--explain-cyclic"),
Expand Down Expand Up @@ -163,17 +164,22 @@ lazy val testkit_cp = CrossModule("testkit", "riddl-testkit")(JVM, JS)
.settings(
description := "Testing kit for RIDDL language and passes"
)
.dependsOn(language_cp % "compile->test;test->test", passes_cp % "compile->test;test->test")
.dependsOn(tkDep(utils_cp), tkDep(language_cp), tkDep(passes_cp))
.jvmSettings(
libraryDependencies ++= Seq(
"org.scalactic" %% "scalactic" % V.scalatest,
"org.scalatest" %% "scalatest" % V.scalatest,
"org.scalactic" %% "scalactic" % V.scalatest % Test,
"org.scalatest" %% "scalatest" % V.scalatest % Test
"org.scalatest" %% "scalatest" % V.scalatest
)
)
.jsConfigure(With.js("RIDDL: language", withCommonJSModule = true))
.jsConfigure(With.publishing)
.jsSettings(
// scalacOptions ++= Seq("-rewrite", "-source", "3.4-migration"),
libraryDependencies ++= Seq(
"org.scalactic" %%% "scalactic" % V.scalatest,
"org.scalatest" %%% "scalatest" % V.scalatest
)
)
val testkit = testkit_cp.jvm
val testkitJS = testkit_cp.js

Expand All @@ -196,7 +202,7 @@ val diagramsJS = diagrams_cp.js

lazy val riddlLib_cp: CrossProject = CrossModule("riddlLib", "riddl-lib")(JS, JVM)
.dependsOn(cpDep(utils_cp), cpDep(language_cp), cpDep(passes_cp), cpDep(diagrams_cp))
.configure(With.scala3,With.publishing)
.configure(With.scala3, With.publishing)
.settings(
description := "Bundling of essential RIDDL libraries"
)
Expand Down Expand Up @@ -261,7 +267,6 @@ val Riddlc = config("riddlc")
lazy val riddlc: Project = Program("riddlc", "riddlc")
.configure(With.typical, With.publishing, With.headerLicense("Apache-2.0"))
.configure(With.coverage(50.0))
.configure(With.publishing)
.configure(With.noMiMa)
.dependsOn(
utils,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ object Folding {

/** Folding with state from an element of type V
*
* @param parent
* The parent node of CV which must be its direct container
* @param child
* The node to fold through
* @param state
* Initial value of arbitrary type `S`` that can be used to fold the nodes into and provides the result type
* @param container
* The container node of CV which must be its direct container
* @param empty
* The initial empty state of the result. this is a "fold" after all :)
* @foldIt
* The function that folds eacy entry in `container`
* @param f
* The folding function which takes 3 arguments and returns an `S` (list the initial `state`)
* @tparam S
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,27 @@ import scala.scalajs.js.annotation.*
/** An extensible version of the Top Level Parser. */

trait ExtensibleTopLevelParser(using PlatformContext)
extends ProcessorParser
with DomainParser
with AdaptorParser
with ApplicationParser
with ContextParser
with EntityParser
with EpicParser
with FunctionParser
with ModuleParser
with NebulaParser
with ProjectorParser
with RepositoryParser
with RootParser
with SagaParser
with StreamingParser
with StatementParser
with ParsingContext {
extends ProcessorParser,
AdaptorParser,
ApplicationParser,
ContextParser,
DomainParser,
EntityParser,
EpicParser,
FunctionParser,
ModuleParser,
NebulaParser,
ProjectorParser,
RepositoryParser,
RootParser,
SagaParser,
StreamingParser,
StatementParser,
ParsingContext {

def input: RiddlParserInput
def withVerboseFailures: Boolean

private def doParse[E <: Parent: ClassTag](rule: P[?] => P[E]): Either[Messages, E] = {
parseRule[E](input, rule, withVerboseFailures) {
(result: Either[Messages, E], input: RiddlParserInput, index: Int) =>
Expand All @@ -53,7 +53,7 @@ trait ExtensibleTopLevelParser(using PlatformContext)
error(At(input, index), s"Parser could not translate '${input.origin}' after $index characters")
end if
result
case _ @ Right(wrongNode) =>
case _ @Right(wrongNode) =>
val expected = classTag[E].runtimeClass
val actual = wrongNode.getClass
error(At(input, index), s"Parser did not yield a ${expected.getSimpleName} but ${actual.getSimpleName}")
Expand All @@ -71,4 +71,31 @@ trait ExtensibleTopLevelParser(using PlatformContext)
case r @ Right(root) => Right(root -> this.getURLs)
}
}

protected def parserFor[T <: Definition: ClassTag]: P[?] => P[T] = {
val parser: P[?] => P[?] = classTag[T].runtimeClass match {
case x if x == classOf[Type] => typeDef(_)
case x if x == classOf[Domain] => domain(_)
case x if x == classOf[Context] => context(_)
case x if x == classOf[Entity] => entity(_)
case x if x == classOf[Adaptor] => adaptor(_)
case x if x == classOf[Invariant] => invariant(_)
case x if x == classOf[Function] => function(_)
case x if x == classOf[Streamlet] => streamlet(_)
case x if x == classOf[Saga] => saga(_)
case x if x == classOf[Repository] => repository(_)
case x if x == classOf[Projector] => projector(_)
case x if x == classOf[Epic] => epic(_)
case x if x == classOf[Connector] => connector(_)
case x if x == classOf[Module] => module(_)
case x if x == classOf[Nebula] => nebula(_)
case x if x == classOf[Root] => root(_)
case _ =>
throw new RuntimeException(
s"No parser defined for ${classTag[T].runtimeClass}"
)
}
parser.asInstanceOf[P[?] => P[T]]
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import com.ossuminc.riddl.utils.{AbstractTestingBasisWithTestData, CommonOptions
import fastparse.*

import scala.annotation.unused
import scala.concurrent.duration.DurationInt

import scala.reflect.*

/** A helper class for testing the parser */
trait AbstractParsingTest(using PlatformContext) extends AbstractTestingBasisWithTestData {

case class StringParser(content: String, testCase: String = "unknown test case") extends ExtensibleTopLevelParser():
val input: RiddlParserInput = RiddlParserInput(content, testCase)
val withVerboseFailures: Boolean = true
val withVerboseFailures: Boolean = true
end StringParser

def parse[T <: RiddlValue, U <: RiddlValue](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ case class TestParser(
input: RiddlParserInput,
throwOnError: Boolean = false,
withVerboseFailures: Boolean = true
)(using PlatformContext) extends ExtensibleTopLevelParser
)(using PlatformContext)
extends ExtensibleTopLevelParser
with Matchers {

def expect[CT <: RiddlValue](
parser: P[?] => P[CT],
withVerboseFailures: Boolean = false
Expand Down Expand Up @@ -52,31 +53,6 @@ case class TestParser(
expect[T](parser).map(x => extract(x) -> input)
}

protected def parserFor[T <: Definition: ClassTag]: P[?] => P[T] = {
val parser: P[?] => P[?] = classTag[T].runtimeClass match {
case x if x == classOf[AST.Type] => typeDef(_)
case x if x == classOf[AST.Domain] => domain(_)
case x if x == classOf[AST.Context] => context(_)
case x if x == classOf[AST.Entity] => entity(_)
case x if x == classOf[AST.Adaptor] => adaptor(_)
case x if x == classOf[AST.Invariant] => invariant(_)
case x if x == classOf[AST.Function] => function(_)
case x if x == classOf[AST.Streamlet] => streamlet(_)
case x if x == classOf[AST.Saga] => saga(_)
case x if x == classOf[AST.Repository] => repository(_)
case x if x == classOf[AST.Projector] => projector(_)
case x if x == classOf[AST.Epic] => epic(_)
case x if x == classOf[AST.Connector] => connector(_)
case x if x == classOf[AST.Module] => module(_)
case x if x == classOf[AST.Root] => root(_)
case _ =>
throw new RuntimeException(
s"No parser defined for ${classTag[T].runtimeClass}"
)
}
parser.asInstanceOf[P[?] => P[T]]
}

def parseTopLevelDomains: Either[Messages, Root] = {
parseRoot
}
Expand Down Expand Up @@ -105,12 +81,12 @@ case class TestParser(
def parseDomainDefinition[TO <: RiddlValue](
extract: Domain => TO
): Either[Messages, (TO, RiddlParserInput)] = {
parse[Domain, TO](domain(_), extract)
parse[Domain, TO](parserFor[Domain], extract)
}

def parseContextDefinition[TO <: RiddlValue](
extract: Context => TO
): Either[Messages, (TO, RiddlParserInput)] = {
parse[Context, TO](context(_), extract)
parse[Context, TO](parserFor[Context], extract)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ package com.ossuminc.riddl.passes.validate
import com.ossuminc.riddl.language.AST.*
import com.ossuminc.riddl.language.At
import com.ossuminc.riddl.language.Messages
import com.ossuminc.riddl.utils.{pc, ec}
import com.ossuminc.riddl.utils.pc

import scala.math.abs
import scala.collection.mutable

trait StreamingValidation extends TypeValidation {
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "0.16.5")
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "0.17.0-1-875cb28e-20241102-1842")

// This enables sbt-bloop to create bloop config files for Metals editors
// Uncomment locally if you use metals, otherwise don't slow down other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
package com.ossuminc.riddl.testkit

import com.ossuminc.riddl.language.parsing
import com.ossuminc.riddl.language.parsing.AbstractParsingTest
import com.ossuminc.riddl.utils.{pc,ec}
import org.scalatest.Suite

class ParsingTestTest extends ParsingTest {
class ParsingTestTest extends AbstractParsingTest {
val delegate: Suite = new parsing.ParsingTestTest {}
delegate.execute()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ package com.ossuminc.riddl.testkit

import com.ossuminc.riddl.language.parsing.RiddlParserInput
import com.ossuminc.riddl.passes.stats.StatsPass
import com.ossuminc.riddl.passes.AbstractRunPassTest

import com.ossuminc.riddl.utils.{pc, ec}
import com.ossuminc.riddl.utils.{Await, URL}
import org.scalatest.TestData

import java.util.concurrent.TimeUnit
import scala.concurrent.duration.FiniteDuration

class RunPassTestTest extends RunPassTest {
class RunPassTestTest extends AbstractRunPassTest {
"RunPassTestTest" should {
"work for stats pass" in { (td: TestData) =>
val url = URL.fromCwdPath("passes/jvm/src/test/input/rbbq.riddl")
val inputFuture = RiddlParserInput.fromURL(url, td)
inputFuture.map { input =>
val result = runPassesWith(input, StatsPass.creator())
if result.messages.hasErrors then
fail(result.messages.justErrors.format)
else
succeed
}
Await.result(inputFuture, 10)
val url = URL.fromCwdPath("passes/jvm/src/test/input/rbbq.riddl")
val inputFuture = RiddlParserInput.fromURL(url, td)
inputFuture.map { input =>
val result = runPassesWith(input, StatsPass.creator())
if result.messages.hasErrors then fail(result.messages.justErrors.format)
else succeed
}
Await.result(inputFuture, 10)
}
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit fad24ef

Please sign in to comment.