Skip to content

Commit

Permalink
Merge branch 'main' into rh/correct-documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
CodingDepot authored Apr 10, 2024
2 parents d367d84 + f0eef46 commit 88ddea0
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,24 @@ import kotlin.reflect.full.findAnnotation
private fun CokoRule.toReportingDescriptor() = ReportingDescriptor(
id = toString(),
name = name,
shortDescription = findAnnotation<Rule>()?.shortDescription?.let { desc ->
MultiformatMessageString(
text = desc
)
shortDescription = findAnnotation<Rule>()?.let {
MultiformatMessageString(text = it.shortDescription)
},
fullDescription = findAnnotation<Rule>()?.let {
MultiformatMessageString(text = it.description)
},
defaultConfiguration = findAnnotation<Rule>()?.let {
ReportingConfiguration(level = it.severity.toResultLevel())
},
fullDescription = findAnnotation<Rule>()?.description?.let { desc ->
MultiformatMessageString(
text = desc
help = findAnnotation<Rule>()?.let {
MultiformatMessageString(text = it.help)
},
properties = findAnnotation<Rule>()?.let {
PropertyBag(
tags = it.tags.toSet(),
map = emptyMap()
)
},
defaultConfiguration = ReportingConfiguration(level = findAnnotation<Rule>()?.severity?.toResultLevel()),
help = findAnnotation<Rule>()?.help?.let { desc -> MultiformatMessageString(text = desc) },
properties = PropertyBag(
tags = findAnnotation<Rule>()?.tags?.toList()
)
// TODO: add precision, severity
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
/*
* Copyright (c) 2024, Fraunhofer AISEC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.aisec.codyze.specificationLanguages.coko.dsl

import de.fraunhofer.aisec.codyze.backends.cpg.CPGConfiguration
import de.fraunhofer.aisec.codyze.backends.cpg.coko.CokoCpgBackend
import de.fraunhofer.aisec.codyze.specificationLanguages.coko.core.CokoRule
import de.fraunhofer.aisec.codyze.specificationLanguages.coko.core.Evaluator
import de.fraunhofer.aisec.codyze.specificationLanguages.coko.core.dsl.Severity
import de.fraunhofer.aisec.codyze.specificationLanguages.coko.core.toResultLevel
import de.fraunhofer.aisec.codyze.specificationLanguages.coko.dsl.host.CokoExecutor
import de.fraunhofer.aisec.cpg.passes.EdgeCachePass
import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import kotlin.io.path.toPath
import kotlin.reflect.KParameter
import kotlin.reflect.KType
import kotlin.reflect.KTypeParameter
import kotlin.reflect.KVisibility

class CokoSarifBuilderTest {

private val cpgConfiguration =
CPGConfiguration(
source = emptyList(),
useUnityBuild = false,
debugParser = false,
disableCleanup = false,
codeInNodes = true,
matchCommentsToNodes = false,
processAnnotations = false,
failOnError = false,
useParallelFrontends = false,
defaultPasses = true,
additionalLanguages = setOf(),
symbols = mapOf(),
includeBlocklist = listOf(),
includePaths = listOf(),
includeAllowlist = listOf(),
loadIncludes = false,
passes = listOf(UnreachableEOGPass::class, EdgeCachePass::class),
)

private val cokoRulewithoutRuleAnnotation = object : CokoRule {
override val annotations: List<Annotation>
get() = emptyList()
override val name: String
get() = "norule"

// remaining methods are not required in this test
override val isAbstract: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isExternal: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isFinal: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isInfix: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isInline: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isOpen: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isOperator: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val isSuspend: Boolean
get() = throw UnsupportedOperationException("Not required for this test")
override val parameters: List<KParameter>
get() = throw UnsupportedOperationException("Not required for this test")
override val returnType: KType
get() = throw UnsupportedOperationException("Not required for this test")
override val typeParameters: List<KTypeParameter>
get() = throw UnsupportedOperationException("Not required for this test")
override val visibility: KVisibility?
get() = throw UnsupportedOperationException("Not required for this test")

override fun call(vararg args: Any?): Evaluator =
throw UnsupportedOperationException("Not required for this test")

override fun callBy(args: Map<KParameter, Any?>): Evaluator =
throw UnsupportedOperationException("Not required for this test")
}

@Test
fun `test empty rules list causes empty reportingDescriptors list`() {
val backend = CokoCpgBackend(cpgConfiguration)
val csb = CokoSarifBuilder(rules = emptyList(), backend = backend)

assertTrue(csb.reportingDescriptors.isEmpty())
}

@Test
fun `test spec without rule annotation`() {
val backend = CokoCpgBackend(cpgConfiguration)
val csb = CokoSarifBuilder(rules = listOf(cokoRulewithoutRuleAnnotation), backend = backend)

val reportingDescriptor = csb.reportingDescriptors.first()
assertNotNull(reportingDescriptor)
assertNull(reportingDescriptor.shortDescription)
assertNull(reportingDescriptor.fullDescription)
assertNull(reportingDescriptor.defaultConfiguration)
assertNull(reportingDescriptor.help)
assertNull(reportingDescriptor.properties)
}

@Test
fun `test rule with default shortDescription`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruledefaults.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val shortDescription = csb.reportingDescriptors.first().shortDescription
assertNotNull(shortDescription)
assertTrue(shortDescription?.text!!.isEmpty())
}

@Test
fun `test rule with some shortDescription`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruleshortdescription.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val shortDescription = csb.reportingDescriptors.first().shortDescription
assertNotNull(shortDescription)
assertEquals(shortDescription?.text, "test")
}

@Test
fun `test rule with default description`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruledefaults.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val fullDescription = csb.reportingDescriptors.first().fullDescription
assertNotNull(fullDescription)
assertTrue(fullDescription?.text!!.isEmpty())
}

@Test
fun `test rule with some description`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/rulefulldescription.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val fullDescription = csb.reportingDescriptors.first().fullDescription
assertNotNull(fullDescription)
assertEquals(fullDescription?.text, "some description")
}

@Test
fun `test rule with default severity`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruledefaults.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val defaultConfiguration = csb.reportingDescriptors.first().defaultConfiguration
assertNotNull(defaultConfiguration)

val level = defaultConfiguration?.level
assertNotNull(level)
assertTrue(level == Severity.WARNING.toResultLevel())
}

@Test
fun `test rule with some severity`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruleseverity.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val defaultConfiguration = csb.reportingDescriptors.first().defaultConfiguration
assertNotNull(defaultConfiguration)

val level = defaultConfiguration?.level
assertNotNull(level)
assertTrue(level != Severity.WARNING.toResultLevel())
}

@Test
fun `test rule with default help`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruledefaults.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val help = csb.reportingDescriptors.first().help
assertNotNull(help)
assertTrue(help?.text!!.isEmpty())
}

@Test
fun `test rule with some help`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/rulehelp.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val help = csb.reportingDescriptors.first().help
assertNotNull(help)
assertEquals(help?.text, "some help")
}

@Test
fun `test rule with default empty tags`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruledefaults.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val alternative = csb.reportingDescriptors.first().properties?.tags?.let { assertTrue(it.isEmpty()) }
assertNotNull(alternative)
}

@Test
fun `test rules with some tags`() {
val specFiles = listOfNotNull(
CokoSarifBuilderTest::class.java.classLoader
.getResource("sarif/ruletags.codyze.kts")
).map { it.toURI().toPath() }

val backend = CokoCpgBackend(cpgConfiguration)
val specEvaluator = CokoExecutor.compileScriptsIntoSpecEvaluator(backend = backend, specFiles = specFiles)
val csb = CokoSarifBuilder(rules = specEvaluator.rules, backend = backend)

val alternative = csb.reportingDescriptors.first().properties?.tags?.let { assertTrue(it.isNotEmpty()) }
assertNotNull(alternative)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule()
fun rule() =
Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule(description = "some description")
fun rule() =
Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule(help = "some help")
fun rule() =
Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule(severity = Severity.INFO)
fun rule() =
Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule(shortDescription = "test")
fun rule() =
Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@Rule(tags = ["one", "two"])
fun rule() =
Unit
8 changes: 4 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[versions]
kotlin = "1.9.23"
cpg = "8.1.2"
koin = "3.5.3"
koin-test = "3.5.3"
koin = "3.5.4"
koin-test = "3.5.4"
detekt = "1.23.6"
spotless = "6.25.0"
dokka = "1.9.20"


[libraries]
sarif4k = { module = "io.github.detekt.sarif4k:sarif4k", version = "0.5.0"} # The code can be found here: https://github.com/detekt/sarif4k. It was generated using https://app.quicktype.io/
sarif4k = { module = "io.github.detekt.sarif4k:sarif4k", version = "0.6.0"} # The code can be found here: https://github.com/detekt/sarif4k. It was generated using https://app.quicktype.io/
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.6.3"}
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin"}

Expand All @@ -28,7 +28,7 @@ cpg-language-java = { module = "de.fraunhofer.aisec:cpg-language-java", version.
#cpg-analysis = { module = "com.github.Fraunhofer-AISEC.cpg:cpg-analysis", version.ref = "cpg"}
#cpg-language-go = { module = "com.github.Fraunhofer-AISEC.cpg:cpg-language-go", version.ref = "cpg"}

kotlin-logging = { module = "io.github.oshai:kotlin-logging-jvm", version = "6.0.3" }
kotlin-logging = { module = "io.github.oshai:kotlin-logging-jvm", version = "6.0.4" }
log4j-impl = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version = "2.23.1"}
clikt = { module = "com.github.ajalt.clikt:clikt", version = "4.3.0"}
koin = { module = "io.insert-koin:koin-core", version.ref = "koin"}
Expand Down

0 comments on commit 88ddea0

Please sign in to comment.