Skip to content

Go support #1757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f07741a
Merge actual UTBot Go
egiptipavel Jan 2, 2023
faf7567
Make it mandatory to select tested functions
egiptipavel Jan 3, 2023
ad3caf6
Fix generating test file for function without parameters and return v…
egiptipavel Jan 3, 2023
f212dfe
Add logs
egiptipavel Jan 3, 2023
5ddfc0f
Delete changing name of function in body of modified function
egiptipavel Jan 6, 2023
65b22b3
Support struct type from other packages
egiptipavel Jan 10, 2023
fda59dd
Fix bugs, refactoring
egiptipavel Jan 12, 2023
698e73b
Fix bug with initializing unexported struct fields
egiptipavel Jan 13, 2023
b11c98a
Fast fuzzing for primitives and arrays
egiptipavel Jan 23, 2023
bc1230e
Change property 'requiredImports to function 'getRequiredImports'
egiptipavel Jan 23, 2023
0eb489f
Add support for integer types with implementation-specific size
egiptipavel Jan 23, 2023
9146949
Change logs
egiptipavel Jan 23, 2023
16d7f13
Add test generation for functions without parameters and return values
egiptipavel Jan 23, 2023
d6d22b0
Add support for test generation for function with error as result type
egiptipavel Jan 24, 2023
a937775
Refactor GoUtModel' and GoTypeId's
egiptipavel Jan 24, 2023
defc0f5
Fix test generation with panics
egiptipavel Jan 24, 2023
ea9468b
Add all function execution timeout
egiptipavel Jan 24, 2023
727dacc
Change files, where will be merge conflict
egiptipavel Jan 24, 2023
880cff8
Change logic of timeout for execution of all functions
egiptipavel Jan 25, 2023
a82d001
Add isCanceled indicator
egiptipavel Jan 25, 2023
64e5983
Update README and samples
egiptipavel Jan 25, 2023
0569f60
Increase timeout for worker connection and handle case when worker fa…
egiptipavel Jan 27, 2023
ac4849b
Delete unnecessary files
egiptipavel Jan 27, 2023
af2fefc
Do fast fuzzing for structs, delete old fuzzing
egiptipavel Jan 30, 2023
286a62a
Change name of method canBeEqual to isComparable
egiptipavel Feb 3, 2023
7cba22e
Rid off all dependencies of core-api
egiptipavel Feb 5, 2023
8b33be1
Rewrite documentation
egiptipavel Feb 5, 2023
de389c0
Fix equals and hashCode methods in GoStructTypeId and GoInterfaceTypeId
egiptipavel Feb 6, 2023
b026658
Small refactoring
egiptipavel Feb 6, 2023
3c7031b
Add necessary enviroments to process
egiptipavel Feb 6, 2023
b1530cd
Change path separator for windows to system-dependent path separator
egiptipavel Feb 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ideVersion=222.4167.29

pythonIde=IC,IU,PC,PY
jsIde=IU,PY,WS
goIde=IU

# In order to run Android Studion instead of Intellij Community, specify the path to your Android Studio installation
#androidStudioPath=your_path_to_android_studio
Expand All @@ -15,6 +16,9 @@ jsIde=IU,PY,WS
pythonCommunityPluginVersion=222.4167.37
pythonUltimatePluginVersion=222.4167.37

# Version numbers: https://plugins.jetbrains.com/plugin/9568-go/versions
goPluginVersion=222.4167.21

kotlinPluginVersion=222-1.7.20-release-201-IJ4167.29

junit5Version=5.8.0-RC1
Expand Down
7 changes: 7 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ val ideType: String by settings
val pythonIde: String by settings
val jsIde: String by settings
val includeRiderInBuild: String by settings
val goIde: String by settings

pluginManagement {
resolutionStrategy {
Expand Down Expand Up @@ -59,3 +60,9 @@ if (jsIde.split(",").contains(ideType)) {
include("utbot-cli-js")
include("utbot-intellij-js")
}

if (goIde.split(",").contains(ideType)) {
include("utbot-go")
include("utbot-cli-go")
include("utbot-intellij-go")
}
77 changes: 77 additions & 0 deletions utbot-cli-go/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11
freeCompilerArgs += ["-Xallow-result-return-type", "-Xsam-conversions=class"]
}
}

tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_11
}

configurations {
fetchInstrumentationJar
}

dependencies {
implementation project(':utbot-framework')
implementation project(':utbot-cli')
implementation project(':utbot-go')

// Without this dependency testng tests do not run.
implementation group: 'com.beust', name: 'jcommander', version: '1.48'
implementation group: 'org.junit.platform', name: 'junit-platform-console-standalone', version: junit4PlatformVersion
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlinLoggingVersion
implementation group: 'com.github.ajalt.clikt', name: 'clikt', version: cliktVersion
implementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: junit5Version
implementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junit5Version
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4j2Version
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4j2Version
implementation group: 'org.jacoco', name: 'org.jacoco.report', version: jacocoVersion
//noinspection GroovyAssignabilityCheck
fetchInstrumentationJar project(path: ':utbot-instrumentation', configuration: 'instrumentationArchive')

implementation 'com.beust:klaxon:5.5' // to read and write JSON
}

processResources {
from(configurations.fetchInstrumentationJar) {
into "lib"
}
}

task createProperties(dependsOn: processResources) {
doLast {
new File("$buildDir/resources/main/version.properties").withWriter { w ->
Properties properties = new Properties()
//noinspection GroovyAssignabilityCheck
properties['version'] = project.version.toString()
properties.store w, null
}
}
}

classes {
dependsOn createProperties
}

jar {
manifest {
attributes 'Main-Class': 'org.utbot.cli.go.ApplicationKt'
attributes 'Bundle-SymbolicName': 'org.utbot.cli.go'
attributes 'Bundle-Version': "${project.version}"
attributes 'Implementation-Title': 'UtBot Go CLI'
attributes 'JAR-Type': 'Fat JAR'
}

archiveVersion.set(project.version as String)

dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}

duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

36 changes: 36 additions & 0 deletions utbot-cli-go/src/main/kotlin/org/utbot/cli/go/Application.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.utbot.cli.go

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.versionOption
import com.github.ajalt.clikt.parameters.types.enum
import org.slf4j.event.Level
import org.utbot.cli.getVersion
import org.utbot.cli.setVerbosity
import kotlin.system.exitProcess
import org.utbot.cli.go.commands.GenerateGoTestsCommand
import org.utbot.cli.go.commands.RunGoTestsCommand

class UtBotCli : CliktCommand(name = "UnitTestBot Go Command Line Interface") {
private val verbosity by option("--verbosity", help = "Changes verbosity level, case insensitive")
.enum<Level>(ignoreCase = true)
.default(Level.INFO)

override fun run() = setVerbosity(verbosity)

init {
versionOption(getVersion())
}
}

fun main(args: Array<String>) = try {
UtBotCli().subcommands(
GenerateGoTestsCommand(),
RunGoTestsCommand(),
).main(args)
} catch (ex: Throwable) {
ex.printStackTrace()
exitProcess(1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.utbot.cli.go.commands

import com.beust.klaxon.Json

internal data class Position(@Json(index = 1) val line: Int, @Json(index = 2) val column: Int)

internal data class CodeRegion(@Json(index = 1) val start: Position, @Json(index = 2) val end: Position)

internal data class CoveredSourceFile(
@Json(index = 1) val sourceFileName: String,
@Json(index = 2) val covered: List<CodeRegion>,
@Json(index = 3) val uncovered: List<CodeRegion>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package org.utbot.cli.go.commands

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.types.long
import mu.KotlinLogging
import org.utbot.cli.go.logic.CliGoUtTestsGenerationController
import org.utbot.cli.go.util.durationInMillis
import org.utbot.cli.go.util.now
import org.utbot.cli.go.util.toAbsolutePath
import org.utbot.go.logic.GoUtTestsGenerationConfig
import java.nio.file.Files
import java.nio.file.Paths

private val logger = KotlinLogging.logger {}

class GenerateGoTestsCommand :
CliktCommand(name = "generateGo", help = "Generates tests for the specified Go source file") {

private val sourceFile: String by option(
"-s", "--source",
help = "Specifies Go source file to generate tests for"
)
.required()
.check("Must exist and ends with *.go suffix") {
it.endsWith(".go") && Files.exists(Paths.get(it))
}

private val selectedFunctionsNames: List<String> by option(
"-f", "--function",
help = StringBuilder()
.append("Specifies function name to generate tests for. ")
.append("Can be used multiple times to select multiple functions at the same time.")
.toString()
)
.multiple(required = true)

private val goExecutablePath: String by option(
"-go", "--go-path",
help = "Specifies path to Go executable. For example, it could be [/usr/local/go/bin/go] for some systems"
)
.required() // TODO: attempt to find it if not specified

private val eachFunctionExecutionTimeoutMillis: Long by option(
"-et", "--each-execution-timeout",
help = StringBuilder()
.append("Specifies a timeout in milliseconds for each fuzzed function execution.")
.append("Default is ${GoUtTestsGenerationConfig.DEFAULT_EACH_EXECUTION_TIMEOUT_MILLIS} ms")
.toString()
)
.long()
.default(GoUtTestsGenerationConfig.DEFAULT_EACH_EXECUTION_TIMEOUT_MILLIS)
.check("Must be positive") { it > 0 }

private val allFunctionExecutionTimeoutMillis: Long by option(
"-at", "--all-execution-timeout",
help = StringBuilder()
.append("Specifies a timeout in milliseconds for all fuzzed function execution.")
.append("Default is ${GoUtTestsGenerationConfig.DEFAULT_ALL_EXECUTION_TIMEOUT_MILLIS} ms")
.toString()
)
.long()
.default(GoUtTestsGenerationConfig.DEFAULT_ALL_EXECUTION_TIMEOUT_MILLIS)
.check("Must be positive") { it > 0 }

private val printToStdOut: Boolean by option(
"-p",
"--print-test",
help = "Specifies whether a test should be printed out to StdOut. Is disabled by default"
)
.flag(default = false)

private val overwriteTestFiles: Boolean by option(
"-w",
"--overwrite",
help = "Specifies whether to overwrite the output test file if it already exists. Is disabled by default"
)
.flag(default = false)

override fun run() {
val sourceFileAbsolutePath = sourceFile.toAbsolutePath()
val goExecutableAbsolutePath = goExecutablePath.toAbsolutePath()

val testsGenerationStarted = now()
logger.info { "Test file generation for [$sourceFile] - started" }
try {
CliGoUtTestsGenerationController(
printToStdOut = printToStdOut,
overwriteTestFiles = overwriteTestFiles
).generateTests(
mapOf(sourceFileAbsolutePath to selectedFunctionsNames),
GoUtTestsGenerationConfig(
goExecutableAbsolutePath,
eachFunctionExecutionTimeoutMillis,
allFunctionExecutionTimeoutMillis
)
)
} catch (t: Throwable) {
logger.error { "An error has occurred while generating test for snippet $sourceFile: $t" }
throw t
} finally {
val duration = durationInMillis(testsGenerationStarted)
logger.info { "Test file generation for [$sourceFile] - completed in [$duration] (ms)" }
}
}
}
Loading