Custom detekt rule for logger usage check
[dcaegen2/collectors/hv-ves.git] / build / hv-collector-analysis / src / test / kotlin / org / onap / dcae / collectors / veshv / analysis / SuboptimalLoggerUsageTest.kt
1 /*
2  * ============LICENSE_START=======================================================
3  * dcaegen2-collectors-veshv
4  * ================================================================================
5  * Copyright (C) 2018 NOKIA
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.dcae.collectors.veshv.analysis
21
22 import io.gitlab.arturbosch.detekt.api.Config
23 import io.gitlab.arturbosch.detekt.test.TestConfig
24 import io.gitlab.arturbosch.detekt.test.assertThat
25 import io.gitlab.arturbosch.detekt.test.compileAndLint
26 import org.jetbrains.spek.api.Spek
27 import org.jetbrains.spek.api.dsl.describe
28 import org.jetbrains.spek.api.dsl.it
29 import org.jetbrains.spek.api.dsl.xdescribe
30
31 /**
32  * @author Piotr Jaszczyk <piotr.jaszczyk></piotr.jaszczyk>@nokia.com>
33  * @since November 2018
34  */
35 internal class SuboptimalLoggerUsageTest : Spek({
36
37     fun checkPassingCase(code: String, cut: SuboptimalLoggerUsage = SuboptimalLoggerUsage(Config.empty)) {
38         describe(code) {
39             val findings = cut.compileAndLint(CodeSamples.code(code))
40
41             it("should pass") {
42                 assertThat(findings).isEmpty()
43             }
44         }
45     }
46
47     fun checkFailingCase(code: String, cut: SuboptimalLoggerUsage = SuboptimalLoggerUsage(Config.empty)) {
48         describe(code) {
49             val findings = cut.compileAndLint(CodeSamples.code(code))
50
51             it("should fail") {
52                 assertThat(findings).isNotEmpty()
53             }
54         }
55     }
56
57     describe("passing cases") {
58         checkPassingCase(CodeSamples.noConcatCall)
59         checkPassingCase(CodeSamples.exceptionCall)
60         checkPassingCase(CodeSamples.lambdaCall)
61         checkPassingCase(CodeSamples.lambdaFunctionCall)
62         checkPassingCase(CodeSamples.lambdaExceptionCall)
63     }
64
65
66     describe("failing cases") {
67         checkFailingCase(CodeSamples.plainConcatCall)
68         checkFailingCase(CodeSamples.expansionCall)
69         checkFailingCase(CodeSamples.plainConcatExceptionCall)
70         checkFailingCase(CodeSamples.expansionExceptionCall)
71     }
72
73     describe("custom configuration") {
74         val cut = SuboptimalLoggerUsage(TestConfig(mapOf("loggerNames" to "l,lo", "loggingMethodNames" to "print")))
75         val strangeLogger = """
76             val l = object {
77                 fun print(m: String) { }
78             }
79             val lo = l
80         """.trimIndent()
81
82         checkPassingCase(CodeSamples.plainConcatCall, cut)
83
84         checkPassingCase("""
85             $strangeLogger
86             l.print("n")""".trimIndent(), cut)
87
88         checkFailingCase("""
89             $strangeLogger
90             l.print("n=" + n)""".trimIndent(), cut)
91
92         checkFailingCase("""
93             $strangeLogger
94             lo.print("n=${'$'}n")""".trimIndent(), cut)
95     }
96 })
97
98 object CodeSamples {
99     private val codeBefore = """
100         object logger {
101             fun debug(msg: String) { println(msg) }
102             fun debug(msg: String, ex: Throwable) { println(msg + ". Cause: " + ex) }
103             fun debug(msg: () -> String) { println(msg()) }
104             fun debug(ex: Throwable, msg: () -> String) { println(msg() + ". Cause: " + ex) }
105         }
106
107         fun execute(n: Integer) {
108             val ex = Exception()
109
110     """.trimIndent()
111     private const val codeAfter = """}"""
112
113     const val noConcatCall = """logger.debug("Executing...")"""
114     const val exceptionCall = """logger.debug("Fail", ex)"""
115     const val lambdaCall = """logger.debug{ "n=${'$'}n" }"""
116     const val lambdaFunctionCall = """logger.debug { n.toString() }"""
117     const val lambdaExceptionCall = """logger.debug(ex) { "epic fail on n=" + n }"""
118
119     const val plainConcatCall = """logger.debug("n=" + n)"""
120     const val expansionCall = """logger.debug("n=${'$'}n")"""
121     const val plainConcatExceptionCall = """logger.debug("Fail. n=" + n, ex)"""
122     const val expansionExceptionCall = """logger.debug("Fail. n=${'$'}n", ex)"""
123
124
125     fun code(core: String) = codeBefore + core + codeAfter
126 }