Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Elmacioro committed Nov 6, 2024
1 parent 5eea22c commit b72dc6d
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cats.effect.unsafe.IORuntime
import cats.instances.future._
import com.typesafe.config.ConfigFactory
import db.util.DBIOActionInstances._
import pl.touk.nussknacker.engine.api.component.{DesignerWideComponentId, ProcessingMode}
import pl.touk.nussknacker.engine.api.component.{ComponentAdditionalConfig, DesignerWideComponentId, ProcessingMode}
import pl.touk.nussknacker.engine.api.definition.FixedExpressionValue
import pl.touk.nussknacker.engine.api.deployment.{
NoOpScenarioActivityManager,
Expand Down Expand Up @@ -120,6 +120,10 @@ object TestFactory {
Streaming.stringify -> new ScenarioResolver(sampleResolver, Streaming.stringify)
)

def additionalComponentConfigsByProcessingType
: ProcessingTypeDataProvider[Map[DesignerWideComponentId, ComponentAdditionalConfig], _] =
mapProcessingTypeDataProvider()

val modelDependencies: ModelDependencies =
ModelDependencies(
TestAdditionalUIConfigProvider.componentAdditionalConfigMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import pl.touk.nussknacker.engine.build.ScenarioBuilder
import pl.touk.nussknacker.engine.canonicalgraph.CanonicalProcess
import pl.touk.nussknacker.engine.deployment.{DeploymentData, DeploymentId, ExternalDeploymentId}
import pl.touk.nussknacker.test.base.db.WithHsqlDbTesting
import pl.touk.nussknacker.test.utils.domain.TestFactory.mapProcessingTypeDataProvider
import pl.touk.nussknacker.test.utils.domain.{ProcessTestData, TestFactory}
import pl.touk.nussknacker.test.utils.scalas.DBIOActionValues
import pl.touk.nussknacker.test.{EitherValuesDetailedMessage, PatientScalaFutures}
Expand Down Expand Up @@ -196,7 +195,7 @@ class NotificationServiceTest
mock[ProcessChangeListener],
None,
None,
mapProcessingTypeDataProvider(),
TestFactory.additionalComponentConfigsByProcessingType,
clock
) {
override protected def validateBeforeDeploy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import pl.touk.nussknacker.engine.build.ScenarioBuilder
import pl.touk.nussknacker.engine.deployment.{CustomActionResult, DeploymentId, ExternalDeploymentId}
import pl.touk.nussknacker.test.base.db.WithHsqlDbTesting
import pl.touk.nussknacker.test.base.it.WithClock
import pl.touk.nussknacker.test.config.WithSimplifiedDesignerConfig.TestProcessingType.Streaming
import pl.touk.nussknacker.test.mock.{MockDeploymentManager, TestProcessChangeListener}
import pl.touk.nussknacker.test.utils.domain.TestFactory._
import pl.touk.nussknacker.test.utils.domain.{ProcessTestData, TestFactory}
Expand Down Expand Up @@ -115,7 +116,7 @@ class DeploymentServiceSpec
listener,
scenarioStateTimeout,
deploymentCommentSettings,
mapProcessingTypeDataProvider()
additionalComponentConfigsByProcessingType
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class DeploymentServiceTest
),
dbioRunner,
clock,
mapProcessingTypeDataProvider()
TestFactory.additionalComponentConfigsByProcessingType
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ class FlinkProcessCompilerDataFactory(
): (ModelDefinitionWithClasses, EngineDictRegistry) = {
val dictRegistryFactory = loadDictRegistry(userCodeClassLoader)
val modelDefinitionWithTypes = ModelDefinitionWithClasses(
// additionalConfigsFromProvider aren't provided, as it's not needed to run the process on flink
extractModelDefinition(
userCodeClassLoader,
modelDependencies,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ object FlinkTestMain extends FlinkRunner {
val processVersion = ProcessVersion.empty.copy(processName =
ProcessName("snapshot version")
) // testing process may be unreleased, so it has no version
new FlinkTestMain(modelData, process, scenarioTestData, processVersion, DeploymentData.empty, configuration).runTest
new FlinkTestMain(
modelData,
process,
scenarioTestData,
processVersion,
DeploymentData.empty.copy(configsFromProviderWithDictionaryEditor = modelData.additionalConfigsFromProvider),
configuration
).runTest
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ import pl.touk.nussknacker.engine.process.helpers.SampleNodes._
import pl.touk.nussknacker.engine.testmode.TestProcess._
import pl.touk.nussknacker.engine.util.ThreadUtils
import pl.touk.nussknacker.engine.ModelData
import pl.touk.nussknacker.engine.api.component.{
ComponentAdditionalConfig,
DesignerWideComponentId,
ParameterAdditionalUIConfig
}
import pl.touk.nussknacker.engine.api.parameter.{ParameterName, ValueInputWithDictEditor}
import pl.touk.nussknacker.engine.graph.expression.Expression

import java.util.{Date, UUID}
import scala.concurrent.ExecutionContext.Implicits.global
Expand Down Expand Up @@ -654,6 +661,62 @@ class FlinkTestMainSpec extends AnyWordSpec with Matchers with Inside with Befor
variable(List(ComponentUseCase.TestRuntime, ComponentUseCase.TestRuntime))
)
}

"should throw exception when parameter was modified by AdditionalUiConfigProvider with dict editor and flink wasn't provided with additional config" in {
val process =
ScenarioBuilder
.streaming(scenarioName)
.source(sourceNodeId, "input")
.processor(
"eager1",
"collectingEager",
"static" -> Expression.dictKeyWithLabel("'s'", Some("s")),
"dynamic" -> "#input.id".spel
)
.emptySink("out", "valueMonitor", "Value" -> "#input.value1".spel)

val run = Future {
runFlinkTest(process, ScenarioTestData(List(createTestRecord(id = "2", value1 = 2))), useIOMonadInInterpreter)
}
val dictEditorException = intercept[IllegalStateException](Await.result(run, 10 seconds))
dictEditorException.getMessage shouldBe "DictKeyWithLabel expression can only be used with DictParameterEditor, got Some(DualParameterEditor(StringParameterEditor,RAW))"
}

"should run correctly when parameter was modified by AdditionalUiConfigProvider with dict editor and flink was provided with additional config" in {
val modifiedComponentName = "collectingEager"
val modifiedParameterName = "static"
val process =
ScenarioBuilder
.streaming(scenarioName)
.source(sourceNodeId, "input")
.processor(
"eager1",
modifiedComponentName,
modifiedParameterName -> Expression.dictKeyWithLabel("'s'", Some("s")),
"dynamic" -> "#input.id".spel
)
.emptySink("out", "valueMonitor", "Value" -> "#input.value1".spel)

val results = runFlinkTest(
process,
ScenarioTestData(List(createTestRecord(id = "2", value1 = 2))),
useIOMonadInInterpreter,
additionalConfigsFromProvider = Map(
DesignerWideComponentId("service-" + modifiedComponentName) -> ComponentAdditionalConfig(
parameterConfigs = Map(
ParameterName(modifiedParameterName) -> ParameterAdditionalUIConfig(
required = false,
initialValue = None,
hintText = None,
valueEditor = Some(ValueInputWithDictEditor("someDictId", allowOtherValue = false)),
valueCompileTimeValidation = None
)
)
)
)
)
results.exceptions should have length 0
}
}

private def createTestRecord(
Expand All @@ -667,13 +730,14 @@ class FlinkTestMainSpec extends AnyWordSpec with Matchers with Inside with Befor
process: CanonicalProcess,
scenarioTestData: ScenarioTestData,
useIOMonadInInterpreter: Boolean,
enrichDefaultConfig: Config => Config = identity
enrichDefaultConfig: Config => Config = identity,
additionalConfigsFromProvider: Map[DesignerWideComponentId, ComponentAdditionalConfig] = Map.empty
): TestResults[_] = {
val config = enrichDefaultConfig(ConfigFactory.load("application.conf"))
.withValue("globalParameters.useIOMonadInInterpreter", ConfigValueFactory.fromAnyRef(useIOMonadInInterpreter))

// We need to set context loader to avoid forking in sbt
val modelData = ModelData.duringFlinkExecution(config, Map.empty)
val modelData = ModelData.duringFlinkExecution(config, additionalConfigsFromProvider)
ThreadUtils.withThisAsContextClassLoader(getClass.getClassLoader) {
FlinkTestMain.run(modelData, process, scenarioTestData, FlinkTestConfiguration.configuration())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package pl.touk.nussknacker.engine.management.periodic

import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import pl.touk.nussknacker.engine.api.component.{
ComponentAdditionalConfig,
ComponentGroupName,
DesignerWideComponentId,
ParameterAdditionalUIConfig
}
import pl.touk.nussknacker.engine.api.definition.FixedExpressionValue
import pl.touk.nussknacker.engine.api.parameter.{ParameterName, ValueInputWithDictEditor}
import pl.touk.nussknacker.engine.management.periodic.AdditionalDictComponentConfigsExtractorTest.{
componentConfigWithDictionaryEditorInParameter,
componentConfigWithOnlyDictEditorParameters,
componentConfigWithoutDictionaryEditorInParameter
}

class AdditionalDictComponentConfigsExtractorTest extends AnyFunSuite with Matchers {

test("should filter only components and parameters with dictionary editors") {
val additionalConfig = Map(
DesignerWideComponentId("componentA") -> componentConfigWithDictionaryEditorInParameter,
DesignerWideComponentId("componentB") -> componentConfigWithoutDictionaryEditorInParameter,
)
val filteredResult =
AdditionalDictComponentConfigsExtractor.getAdditionalConfigsWithDictParametersEditors(additionalConfig)

filteredResult shouldBe Map(
DesignerWideComponentId("componentA") -> componentConfigWithOnlyDictEditorParameters
)
}

}

object AdditionalDictComponentConfigsExtractorTest {

private val parameterAWithDictEditor = (
ParameterName("parameterA"),
ParameterAdditionalUIConfig(
required = true,
initialValue = Some(FixedExpressionValue("'someInitialValueExpression'", "someInitialValueLabel")),
hintText = None,
valueEditor = Some(ValueInputWithDictEditor("someDictA", allowOtherValue = true)),
valueCompileTimeValidation = None
)
)

private val parameterBWithDictEditor = (
ParameterName("parameterB"),
ParameterAdditionalUIConfig(
required = false,
initialValue = None,
hintText = Some("someHint"),
valueEditor = Some(ValueInputWithDictEditor("someDictB", allowOtherValue = false)),
valueCompileTimeValidation = None
)
)

private val parameterWithoutDictEditor = (
ParameterName("parameterC"),
ParameterAdditionalUIConfig(
required = true,
initialValue = None,
hintText = None,
valueEditor = None,
valueCompileTimeValidation = None
)
)

private val componentConfigWithDictionaryEditorInParameter = ComponentAdditionalConfig(
parameterConfigs = Map(
parameterAWithDictEditor,
parameterBWithDictEditor,
parameterWithoutDictEditor
),
icon = Some("someIcon"),
docsUrl = Some("someDocUrl"),
componentGroup = Some(ComponentGroupName("Service"))
)

private val componentConfigWithoutDictionaryEditorInParameter = ComponentAdditionalConfig(
parameterConfigs = Map(parameterWithoutDictEditor),
icon = Some("someOtherIcon"),
docsUrl = Some("someOtherDocUrl"),
componentGroup = Some(ComponentGroupName("Service"))
)

private val componentConfigWithOnlyDictEditorParameters = ComponentAdditionalConfig(
parameterConfigs = Map(
parameterAWithDictEditor,
parameterBWithDictEditor
),
icon = Some("someIcon"),
docsUrl = Some("someDocUrl"),
componentGroup = Some(ComponentGroupName("Service"))
)

}

0 comments on commit b72dc6d

Please sign in to comment.