Skip to content

Commit

Permalink
bugfix: Addresses comments from PR #64
Browse files Browse the repository at this point in the history
  • Loading branch information
Michał Grabowski committed Feb 12, 2025
1 parent ce1b5ff commit aa1e1d7
Showing 1 changed file with 41 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.avsystem.scex.compiler

import com.avsystem.scex.Expression
import com.avsystem.scex.compiler.CodeGeneration.{TypedVariables, escapedChar}
import com.avsystem.scex.compiler.JavaScexCompilerTest.SuspiciousCharsAllowedInVariableNames
import com.avsystem.scex.compiler.ScexCompiler.CompilationFailedException
import com.avsystem.scex.japi.{ScalaTypeTokens, XmlFriendlyJavaScexCompiler}
import com.avsystem.scex.util.{PredefinedAccessSpecs, SimpleContext}
import com.avsystem.scex.validation.SymbolValidator.MemberAccessSpec
import org.scalatest.funsuite.AnyFunSuite

/**
Expand All @@ -15,90 +17,79 @@ class JavaScexCompilerTest extends AnyFunSuite with CompilationTest {
override protected def createCompiler = new XmlFriendlyJavaScexCompiler(new ScexSettings)

test("typed variables test") {
// given a context with a valid typed variable
val acl = PredefinedAccessSpecs.basicOperations
val context = SimpleContext(())
context.setTypedVariable("someDouble", math.Pi)

// given expression that uses the typed variable
val expr = "#someDouble.toDegrees"
// given a valid type variable & an expression that uses the typed variable
val variableName = "someDouble"
val expr = s"#$variableName.toDegrees"

// then expression is compiled without errors
val cexpr = compiler.buildExpression
.contextType(ScalaTypeTokens.create[SimpleContext[Unit]])
.resultType(classOf[Double])
.expression(expr)
.template(false)
.variableClass("someDouble", classOf[Double])
.profile(createProfile(acl))
.get
val compiledExpr = compileExpression(expr, variableName)

// when expression is evaluated
val result = cexpr(context)
// when expression is evaluated with valid value in context
val context = initContextWithTypedVariable(variableName, math.Pi)
val result = compiledExpr(context)

// then the result is correct
assert(math.Pi.toDegrees == result)
}

TypedVariables.IllegalCharsInVarName.foreach { char =>
test(s"typed variables fail if char [code=${char.toInt}, escaped=${escapedChar(char)}] is in var name test") {
// given a context with a typed variable with illegal char in name
val acl = PredefinedAccessSpecs.basicOperations
val variableName = s"JP2NadajePoRazPierwszy$char"
val context = SimpleContext(())
context.setTypedVariable(variableName, math.Pi)

// given expression that uses the typed variable
// given a typed variable with illegal char in name & an expression that uses the typed variable
val variableName = s"2varName$char"
val expr = s"#`$variableName`.toDegrees"

// then compilation should fail
withClue(s"[code=${char.toInt}] character in variable name [$variableName] should not be allowed") {
assertThrows[CompilationFailedException] {
compiler.buildExpression
.contextType(ScalaTypeTokens.create[SimpleContext[Unit]])
.resultType(classOf[Double])
.expression(expr)
.template(false)
.variableClass(variableName, classOf[Double])
.profile(createProfile(acl))
.get
compileExpression(expr, variableName)
}
}
}
}

SuspiciousCharsAllowedInVariableNames.foreach { char =>
test(s"typed variables work if char [code=$char.toInt] is in var name test") {
// given a context with a typed variable with non-standard characters in name
val acl = PredefinedAccessSpecs.basicOperations
val variableName = s"""2JPZnowuNadaje$char"""
val context = SimpleContext(())
context.setTypedVariable(variableName, math.Pi)

// given expression that uses the typed variable
// given a typed variable with valid name & an expression that uses the typed variable
val variableName = s"""2varName$char"""
val expr = s"#`$variableName`.toDegrees"

// then expression is compiled without errors
val cexpr = compiler.buildExpression
.contextType(ScalaTypeTokens.create[SimpleContext[Unit]])
.resultType(classOf[Double])
.expression(expr)
.template(false)
.variableClass(variableName, classOf[Double])
.profile(createProfile(acl))
.get
val compiledExpr = compileExpression(expr, variableName)

// when expression is evaluated
val result = cexpr(context)
// when expression is evaluated with valid value in context
val context = initContextWithTypedVariable(variableName, math.Pi)
val result = compiledExpr(context)

// then the result is correct
assert(math.Pi.toDegrees == result)
}
}

private def initContextWithTypedVariable(
variableName: String,
value: Double
): SimpleContext[Unit] = {
val ctx = SimpleContext(())
ctx.setTypedVariable(variableName, value)
ctx
}

private def compileExpression(
expr: String,
variableName: String,
acl: List[MemberAccessSpec] = PredefinedAccessSpecs.basicOperations
): Expression[SimpleContext[Unit], Double] =
compiler.buildExpression
.contextType(ScalaTypeTokens.create[SimpleContext[Unit]])
.resultType(classOf[Double])
.expression(expr)
.template(false)
.variableClass(variableName, classOf[Double])
.profile(createProfile(acl))
.get
}

object JavaScexCompilerTest {
// These characters caused compilation errors if they were put in variable names until v1.35 release
// These characters caused compilation errors if they were put in typed variable names until v1.35 release
private val SuspiciousCharsAllowedInVariableNames: Seq[Char] = Seq(' ', '\t', '@', '/')
}

0 comments on commit aa1e1d7

Please sign in to comment.