diff --git a/.editorconfig b/.editorconfig index 03e22d69f1b..78092e35a49 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,16 @@ root = true [*] +charset = utf-8 end_of_line = lf insert_final_newline = true [*.{kt,kts}] indent_style = space indent_size = 2 + +ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL +ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ +ij_kotlin_name_count_to_use_star_import = 2147483647 +ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 +ij_kotlin_packages_to_use_import_on_demand = unset diff --git a/kotlin-power-assert-plugin/build.gradle.kts b/kotlin-power-assert-plugin/build.gradle.kts index eedd1cb82d7..8be2694da57 100644 --- a/kotlin-power-assert-plugin/build.gradle.kts +++ b/kotlin-power-assert-plugin/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { kapt("com.google.auto.service:auto-service:1.0.1") compileOnly("com.google.auto.service:auto-service-annotations:1.0.1") - testImplementation(kotlin("test-junit")) + testImplementation(kotlin("test-junit5")) testImplementation("org.jetbrains.kotlin:kotlin-compiler-embeddable") testImplementation("com.github.tschuchortdev:kotlin-compile-testing:1.4.6") } @@ -24,6 +24,10 @@ tasks.withType { kotlinOptions.jvmTarget = "1.8" } +tasks.withType { + useJUnitPlatform() +} + tasks.dokka { outputFormat = "html" outputDirectory = "$buildDir/javadoc" diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/PowerAssertCallTransformer.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/PowerAssertCallTransformer.kt index f3a838fe779..7e4567a8e3c 100644 --- a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/PowerAssertCallTransformer.kt +++ b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/PowerAssertCallTransformer.kt @@ -18,6 +18,7 @@ package com.bnorm.power import com.bnorm.power.delegate.FunctionDelegate import com.bnorm.power.delegate.LambdaFunctionDelegate +import com.bnorm.power.delegate.SamConversionLambdaFunctionDelegate import com.bnorm.power.delegate.SimpleFunctionDelegate import com.bnorm.power.diagram.IrTemporaryVariable import com.bnorm.power.diagram.Node @@ -26,40 +27,44 @@ import com.bnorm.power.diagram.buildTree import com.bnorm.power.diagram.info import com.bnorm.power.diagram.irDiagramString import com.bnorm.power.diagram.substring -import com.bnorm.power.internal.ReturnableBlockTransformer import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext -import org.jetbrains.kotlin.backend.common.ir.asInlinable -import org.jetbrains.kotlin.backend.common.ir.inline import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.backend.js.utils.asString -import org.jetbrains.kotlin.ir.builders.irBlock +import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irString import org.jetbrains.kotlin.ir.builders.parent import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.declarations.path import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation +import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeArgument import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl +import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.isBoolean import org.jetbrains.kotlin.ir.types.isSubtypeOf +import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols +import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.isFunctionOrKFunction import org.jetbrains.kotlin.ir.util.kotlinFqName -import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.ir.util.parentClassOrNull import org.jetbrains.kotlin.name.FqName class PowerAssertCallTransformer( @@ -122,10 +127,6 @@ class PowerAssertCallTransformer( val symbol = currentScope!!.scope.scopeOwnerSymbol val builder = DeclarationIrBuilder(context, symbol, expression.startOffset, expression.endOffset) return builder.diagram(expression, delegate, messageArgument, roots) -// .also { println(expression.dump()) } -// .also { println(it.dump()) } -// .also { println(expression.dumpKotlinLike()) } -// .also { println(it.dumpKotlinLike()) } } private fun DeclarationIrBuilder.diagram( @@ -138,7 +139,8 @@ class PowerAssertCallTransformer( variables: List = listOf() ): IrExpression { if (index >= roots.size) { - val prefix = buildMessagePrefix(messageArgument, roots, original)?.deepCopyWithSymbols(parent) + val prefix = buildMessagePrefix(messageArgument, delegate.messageParameter, roots, original) + ?.deepCopyWithSymbols(parent) val diagram = irDiagramString(file, fileSource, prefix, original, variables) return delegate.buildCall(this, original, arguments, diagram) } else { @@ -157,18 +159,30 @@ class PowerAssertCallTransformer( private fun DeclarationIrBuilder.buildMessagePrefix( messageArgument: IrExpression?, + messageParameter: IrValueParameter, roots: List, original: IrCall ): IrExpression? { return when { messageArgument is IrConst<*> -> messageArgument messageArgument is IrStringConcatenation -> messageArgument - messageArgument != null -> irBlock { - +messageArgument.deepCopyWithSymbols(parent) - .asInlinable(this) - .inline(parent) - .patchDeclarationParents(scope.getLocalDeclarationParent()) - }.transform(ReturnableBlockTransformer(context, scope.scopeOwnerSymbol), null) + messageArgument is IrGetValue -> { + if (messageArgument.type.isAssignableTo(context.irBuiltIns.stringType)) { + return messageArgument + } else { + val invoke = messageParameter.type.classOrNull!!.functions + .filter { !it.owner.isFakeOverride } // TODO best way to find single access method? + .single() + irCall(invoke).apply { dispatchReceiver = messageArgument } + } + } + // Kotlin Lambda or SAMs conversion lambda + messageArgument is IrFunctionExpression || messageArgument is IrTypeOperatorCall -> { + val invoke = messageParameter.type.classOrNull!!.functions + .filter { !it.owner.isFakeOverride } // TODO best way to find single access method? + .single() + irCall(invoke).apply { dispatchReceiver = messageArgument } + } // TODO what should the default message be? roots.size == 1 && original.getValueArgument(0)!!.type.isBoolean() -> irString("Assertion failed") else -> null @@ -179,7 +193,18 @@ class PowerAssertCallTransformer( val values = function.valueParameters if (values.isEmpty()) return emptyList() - return context.referenceFunctions(function.kotlinFqName) + // Java static functions require searching by class + val parentClassFunctions = ( + function.parentClassOrNull + ?.let { context.referenceClass(it.kotlinFqName) } + ?.functions ?: emptySequence() + ) + .filter { it.owner.kotlinFqName == function.kotlinFqName } + .toList() + val possible = (context.referenceFunctions(function.kotlinFqName) + parentClassFunctions) + .distinct() + + return possible .mapNotNull { overload -> val parameters = overload.owner.valueParameters if (parameters.size !in values.size..values.size + 1) return@mapNotNull null @@ -189,8 +214,10 @@ class PowerAssertCallTransformer( val messageParameter = parameters.last() return@mapNotNull when { - isStringSupertype(messageParameter.type) -> SimpleFunctionDelegate(overload) + isStringSupertype(messageParameter.type) -> SimpleFunctionDelegate(overload, messageParameter) isStringFunction(messageParameter.type) -> LambdaFunctionDelegate(overload, messageParameter) + isStringJavaSupplierFunction(messageParameter.type) -> + SamConversionLambdaFunctionDelegate(overload, messageParameter) else -> null } } @@ -199,6 +226,12 @@ class PowerAssertCallTransformer( private fun isStringFunction(type: IrType): Boolean = type.isFunctionOrKFunction() && type is IrSimpleType && (type.arguments.size == 1 && isStringSupertype(type.arguments.first())) + private fun isStringJavaSupplierFunction(type: IrType): Boolean { + val javaSupplier = context.referenceClass(FqName("java.util.function.Supplier")) + return javaSupplier != null && type.isSubtypeOfClass(javaSupplier) && + type is IrSimpleType && (type.arguments.size == 1 && isStringSupertype(type.arguments.first())) + } + private fun isStringSupertype(argument: IrTypeArgument): Boolean = argument is IrTypeProjection && isStringSupertype(argument.type) diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/FunctionDelegate.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/FunctionDelegate.kt index 956527f47b8..f0cb155ae77 100644 --- a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/FunctionDelegate.kt +++ b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/FunctionDelegate.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.parent import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol @@ -27,6 +28,7 @@ import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols interface FunctionDelegate { val function: IrFunction + val messageParameter: IrValueParameter fun buildCall( builder: IrBuilderWithScope, diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/LambdaFunctionDelegate.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/LambdaFunctionDelegate.kt index d18bab6df73..b2db4479aca 100644 --- a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/LambdaFunctionDelegate.kt +++ b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/LambdaFunctionDelegate.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol class LambdaFunctionDelegate( private val overload: IrSimpleFunctionSymbol, - private val messageParameter: IrValueParameter + override val messageParameter: IrValueParameter, ) : FunctionDelegate { override val function = overload.owner diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SamConversionLambdaFunctionDelegate.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SamConversionLambdaFunctionDelegate.kt new file mode 100644 index 00000000000..62e1a6da3bf --- /dev/null +++ b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SamConversionLambdaFunctionDelegate.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 Brian Norman + * + * 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 com.bnorm.power.delegate + +import com.bnorm.power.irLambda +import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.builders.typeOperator +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol + +class SamConversionLambdaFunctionDelegate( + private val overload: IrSimpleFunctionSymbol, + override val messageParameter: IrValueParameter, +) : FunctionDelegate { + override val function = overload.owner + + override fun buildCall( + builder: IrBuilderWithScope, + original: IrCall, + arguments: List, + message: IrExpression + ): IrExpression = with(builder) { + val lambda = irLambda(context.irBuiltIns.stringType, messageParameter.type) { + +irReturn(message) + } + val expression = typeOperator(messageParameter.type, lambda, IrTypeOperator.SAM_CONVERSION, messageParameter.type) + irCallCopy(overload, original, arguments, expression) + } +} diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SimpleFunctionDelegate.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SimpleFunctionDelegate.kt index 186da244b66..9e82956565c 100644 --- a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SimpleFunctionDelegate.kt +++ b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/delegate/SimpleFunctionDelegate.kt @@ -17,12 +17,14 @@ package com.bnorm.power.delegate import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol class SimpleFunctionDelegate( - private val overload: IrSimpleFunctionSymbol + private val overload: IrSimpleFunctionSymbol, + override val messageParameter: IrValueParameter, ) : FunctionDelegate { override val function = overload.owner diff --git a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/internal/ReturnableBlockTransformer.kt b/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/internal/ReturnableBlockTransformer.kt deleted file mode 100644 index f5df2377e6e..00000000000 --- a/kotlin-power-assert-plugin/src/main/kotlin/com/bnorm/power/internal/ReturnableBlockTransformer.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - * - * Copied from https://github.com/JetBrains/kotlin/blob/1.4.20/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/ReturnableBlockLowering.kt - */ - -package com.bnorm.power.internal - -import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder -import org.jetbrains.kotlin.backend.common.lower.irComposite -import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.transformStatement - -// TODO Remove when inlining works correctly on Kotlin/JS and Kotlin/Native -class ReturnableBlockTransformer(val context: IrGeneratorContext, val containerSymbol: IrSymbol? = null) : IrElementTransformerVoidWithContext() { - private var labelCnt = 0 - private val returnMap = mutableMapOf IrExpression>() - - override fun visitReturn(expression: IrReturn): IrExpression { - expression.transformChildrenVoid() - return returnMap[expression.returnTargetSymbol]?.invoke(expression) ?: expression - } - - override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { - if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression) - - val scopeSymbol = currentScope?.scope?.scopeOwnerSymbol ?: containerSymbol - val builder = DeclarationIrBuilder(context, scopeSymbol!!) - val variable by lazy { - builder.scope.createTmpVariable(expression.type, "tmp\$ret\$${labelCnt++}", true) - } - - val loop by lazy { - IrDoWhileLoopImpl( - expression.startOffset, - expression.endOffset, - context.irBuiltIns.unitType, - expression.origin - ).apply { - label = "l\$ret\$${labelCnt++}" - condition = builder.irBoolean(false) - } - } - - var hasReturned = false - - returnMap[expression.symbol] = { returnExpression -> - hasReturned = true - builder.irComposite(returnExpression) { - +irSet(variable.symbol, returnExpression.value) - +irBreak(loop) - } - } - - val newStatements = expression.statements.mapIndexed { i, s -> - if (i == expression.statements.lastIndex && s is IrReturn && s.returnTargetSymbol == expression.symbol) { - s.transformChildrenVoid() - if (!hasReturned) s.value else { - builder.irSet(variable.symbol, s.value) - } - } else { - s.transformStatement(this) - } - } - - returnMap.remove(expression.symbol) - - if (!hasReturned) { - return IrCompositeImpl( - expression.startOffset, - expression.endOffset, - expression.type, - expression.origin, - newStatements - ) - } else { - loop.body = IrBlockImpl( - expression.startOffset, - expression.endOffset, - context.irBuiltIns.unitType, - expression.origin, - newStatements - ) - - return builder.irComposite(expression, expression.origin) { - +variable - +loop - +irGet(variable) - } - } - } -} diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/ArithmeticExpressionTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/ArithmeticExpressionTest.kt index 1b9c9c30ae4..54adad9f94b 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/ArithmeticExpressionTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/ArithmeticExpressionTest.kt @@ -16,7 +16,7 @@ package com.bnorm.power -import org.junit.Test +import kotlin.test.Test import kotlin.test.assertEquals class ArithmeticExpressionTest { diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/test.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertTest.kt similarity index 96% rename from kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/test.kt rename to kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertTest.kt index 556305bea79..a4726792610 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/test.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertTest.kt @@ -17,9 +17,9 @@ package com.bnorm.power import org.jetbrains.kotlin.name.FqName -import org.junit.Test +import kotlin.test.Test -class CompilerTest { +class AssertTest { @Test fun memberFunctions() { assertMessage( @@ -77,6 +77,23 @@ assert(1 == 2) { "Not equal" } ) } + @Test + fun customLocalVariableMessage() { + assertMessage( + """ +fun main() { + val lambda = { "Not equal" } + assert(1 == 2, lambda) +}""", + """ + Not equal + assert(1 == 2, lambda) + | + false + """.trimIndent() + ) + } + @Test fun booleanExpressionsShortCircuit() { assertMessage( diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/DebugFunctionTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/DebugFunctionTest.kt index d720e3e744d..bf2c63669ea 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/DebugFunctionTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/DebugFunctionTest.kt @@ -19,10 +19,10 @@ package com.bnorm.power import com.tschuchort.compiletesting.KotlinCompilation import com.tschuchort.compiletesting.SourceFile import org.jetbrains.kotlin.name.FqName -import org.junit.Test import java.io.ByteArrayOutputStream import java.io.PrintStream import java.lang.reflect.InvocationTargetException +import kotlin.test.Test import kotlin.test.assertEquals class DebugFunctionTest { diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/Junit5AssertionsTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/Junit5AssertionsTest.kt new file mode 100644 index 00000000000..a95873a1073 --- /dev/null +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/Junit5AssertionsTest.kt @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2021 Brian Norman + * + * 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 com.bnorm.power + +import org.jetbrains.kotlin.name.FqName +import kotlin.test.Test + +class Junit5AssertionsTest { + @Test + fun `test JUnit5 Assertions#assertTrue transformation`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertTrue + + fun main() { + assertTrue(1 != 1) + }""", + """ + Assertion failed + assertTrue(1 != 1) + | + false ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertTrue"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertTrue transformation with message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertTrue + + fun main() { + assertTrue(1 != 1, "Message:") + }""", + """ + Message: + assertTrue(1 != 1, "Message:") + | + false ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertTrue"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertTrue transformation with local variable message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertTrue + + fun main() { + val message = "Message:" + assertTrue(1 != 1, message) + }""", + """ + Message: + assertTrue(1 != 1, message) + | + false ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertTrue"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertTrue transformation with message supplier`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertTrue + + fun main() { + assertTrue(1 != 1) { "Message:" } + }""", + """ + Message: + assertTrue(1 != 1) { "Message:" } + | + false ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertTrue"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertTrue transformation with local variable message supplier`() { + assertMessage( + """ + import java.util.function.Supplier + import org.junit.jupiter.api.Assertions.assertTrue + + fun main() { + val supplier = Supplier { "Message:" } + assertTrue(1 != 1, supplier) + }""", + """ + Message: + assertTrue(1 != 1, supplier) + | + false ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertTrue"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertFalse transformation`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertFalse + + fun main() { + assertFalse(1 == 1) + }""", + """ + Assertion failed + assertFalse(1 == 1) + | + true ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertFalse"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertFalse transformation with message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertFalse + + fun main() { + assertFalse(1 == 1, "Message:") + }""", + """ + Message: + assertFalse(1 == 1, "Message:") + | + true ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertFalse"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertFalse transformation with local variable message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertFalse + + fun main() { + val message = "Message:" + assertFalse(1 == 1, message) + }""", + """ + Message: + assertFalse(1 == 1, message) + | + true ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertFalse"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertFalse transformation with message supplier`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertFalse + + fun main() { + assertFalse(1 == 1) { "Message:" } + }""", + """ + Message: + assertFalse(1 == 1) { "Message:" } + | + true ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertFalse"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertFalse transformation with local variable message supplier`() { + assertMessage( + """ + import java.util.function.Supplier + import org.junit.jupiter.api.Assertions.assertFalse + + fun main() { + val supplier = Supplier { "Message:" } + assertFalse(1 == 1, supplier) + }""", + """ + Message: + assertFalse(1 == 1, supplier) + | + true ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertFalse"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertEquals transformation`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + assertEquals(greeting, name) + }""", + """ + assertEquals(greeting, name) + | | + | World + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertEquals"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertEquals transformation with message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + assertEquals(greeting, name, "Message:") + }""", + """ + Message: + assertEquals(greeting, name, "Message:") + | | + | World + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertEquals"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertEquals transformation with local variable message`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + val message = "Message:" + assertEquals(greeting, name, message) + }""", + """ + Message: + assertEquals(greeting, name, message) + | | + | World + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertEquals"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertEquals transformation with message supplier`() { + assertMessage( + """ + import org.junit.jupiter.api.Assertions.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + assertEquals(greeting, name) { "Message:" } + }""", + """ + Message: + assertEquals(greeting, name) { "Message:" } + | | + | World + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertEquals"))) + ) + } + + @Test + fun `test JUnit5 Assertions#assertEquals transformation with local variable message supplier`() { + assertMessage( + """ + import java.util.function.Supplier + import org.junit.jupiter.api.Assertions.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + val supplier = Supplier { "Message:" } + assertEquals(greeting, name, supplier) + }""", + """ + Message: + assertEquals(greeting, name, supplier) + | | + | World + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("org.junit.jupiter.api.Assertions.assertEquals"))) + ) + } +} diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertLibraryTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/KotlinTestAssertTest.kt similarity index 63% rename from kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertLibraryTest.kt rename to kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/KotlinTestAssertTest.kt index 4f67a686e1f..5032dcee952 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/AssertLibraryTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/KotlinTestAssertTest.kt @@ -17,9 +17,9 @@ package com.bnorm.power import org.jetbrains.kotlin.name.FqName -import org.junit.Test +import kotlin.test.Test -class AssertLibraryTest { +class KotlinTestAssertTest { @Test fun `test assertTrue transformation`() { assertMessage( @@ -58,6 +58,26 @@ class AssertLibraryTest { ) } + @Test + fun `test assertTrue transformation with local variable message`() { + assertMessage( + """ + import kotlin.test.assertTrue + + fun main() { + val message = "Message:" + assertTrue(1 != 1, message) + }""", + """ + Message: + assertTrue(1 != 1, message) + | + false + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertTrue"))) + ) + } + @Test fun `test assertFalse transformation`() { assertMessage( @@ -96,6 +116,26 @@ class AssertLibraryTest { ) } + @Test + fun `test assertFalse transformation with local variable message`() { + assertMessage( + """ + import kotlin.test.assertFalse + + fun main() { + val message = "Message:" + assertFalse(1 == 1, message) + }""", + """ + Message: + assertFalse(1 == 1, message) + | + true + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertFalse"))) + ) + } + @Test fun `test assertEquals transformation`() { assertMessage( @@ -111,7 +151,7 @@ class AssertLibraryTest { assertEquals(greeting, name) | | | World - Hello expected:<[Hello]> but was:<[World]> + Hello ==> expected: but was: """.trimIndent(), PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertEquals"))) ) @@ -133,7 +173,30 @@ class AssertLibraryTest { assertEquals(greeting, name, "Message:") | | | World - Hello expected:<[Hello]> but was:<[World]> + Hello ==> expected: but was: + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertEquals"))) + ) + } + + @Test + fun `test assertEquals transformation with local variable message`() { + assertMessage( + """ + import kotlin.test.assertEquals + + fun main() { + val greeting = "Hello" + val name = "World" + val message = "Message:" + assertEquals(greeting, name, message) + }""", + """ + Message: + assertEquals(greeting, name, message) + | | + | World + Hello ==> expected: but was: """.trimIndent(), PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertEquals"))) ) @@ -152,7 +215,7 @@ class AssertLibraryTest { """ assertNotNull(name) | - null + null ==> expected: not """.trimIndent(), PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertNotNull"))) ) @@ -172,7 +235,28 @@ class AssertLibraryTest { Message: assertNotNull(name, "Message:") | - null + null ==> expected: not + """.trimIndent(), + PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertNotNull"))) + ) + } + + @Test + fun `test assertNotNull transformation with local variable message`() { + assertMessage( + """ + import kotlin.test.assertNotNull + + fun main() { + val name: String? = null + val message = "Message:" + assertNotNull(name, message) + }""", + """ + Message: + assertNotNull(name, message) + | + null ==> expected: not """.trimIndent(), PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertNotNull"))) ) diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/LamdaTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/LamdaTest.kt index 9e2dce2f85e..763dc1f90ae 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/LamdaTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/LamdaTest.kt @@ -17,7 +17,7 @@ package com.bnorm.power import org.jetbrains.kotlin.name.FqName -import org.junit.Test +import kotlin.test.Test class LamdaTest { @Test diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/MultiParameterFunctionTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/MultiParameterFunctionTest.kt index 1a2ce2b21d1..88072af6064 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/MultiParameterFunctionTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/MultiParameterFunctionTest.kt @@ -19,10 +19,10 @@ package com.bnorm.power import com.tschuchort.compiletesting.KotlinCompilation import com.tschuchort.compiletesting.SourceFile import org.jetbrains.kotlin.name.FqName -import org.junit.Test import java.io.ByteArrayOutputStream import java.io.PrintStream import java.lang.reflect.InvocationTargetException +import kotlin.test.Test import kotlin.test.assertEquals class MultiParameterFunctionTest { diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/RegexMatchTest.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/RegexMatchTest.kt index 8207d6bfd29..ca23e36f646 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/RegexMatchTest.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/RegexMatchTest.kt @@ -16,7 +16,7 @@ package com.bnorm.power -import org.junit.Test +import kotlin.test.Test import kotlin.test.assertEquals class RegexMatchTest { diff --git a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/compiler.kt b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/compiler.kt index cfc28e034e9..01570df154a 100644 --- a/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/compiler.kt +++ b/kotlin-power-assert-plugin/src/test/kotlin/com/bnorm/power/compiler.kt @@ -62,7 +62,7 @@ fun executeAssertion( } fail("should have thrown assertion") } catch (t: Throwable) { - return t.message!! + return t.message ?: "" } } diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index 09de93c4719..da6a027d5b1 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -32,7 +32,7 @@ kotlin { } val jvmTest by getting { dependencies { - implementation(kotlin("test-junit")) + implementation(kotlin("test-junit5")) } } val jsTest by getting { @@ -49,6 +49,10 @@ kotlin { } } +tasks.withType { + useJUnitPlatform() +} + configure { functions = listOf( "kotlin.assert",