Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9664f169 authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "Linter for spaces in test function names." into udc-dev

parents 0110ea13 75830e6a
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,8 @@ class SystemUIIssueRegistry : IssueRegistry() {
                SoftwareBitmapDetector.ISSUE,
                SoftwareBitmapDetector.ISSUE,
                NonInjectedServiceDetector.ISSUE,
                NonInjectedServiceDetector.ISSUE,
                StaticSettingsProviderDetector.ISSUE,
                StaticSettingsProviderDetector.ISSUE,
                DemotingTestWithoutBugDetector.ISSUE
                DemotingTestWithoutBugDetector.ISSUE,
                TestFunctionNameViolationDetector.ISSUE,
            )
            )


    override val api: Int
    override val api: Int
+89 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * 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.android.internal.systemui.lint

import com.android.tools.lint.detector.api.AnnotationInfo
import com.android.tools.lint.detector.api.AnnotationUsageInfo
import com.android.tools.lint.detector.api.AnnotationUsageType
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import org.jetbrains.uast.UElement
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.kotlin.KotlinUAnnotation
import org.jetbrains.uast.kotlin.KotlinUMethod

/**
 * Detects test function naming violations regarding use of the backtick-wrapped space-allowed
 * feature of Kotlin functions.
 */
class TestFunctionNameViolationDetector : Detector(), SourceCodeScanner {

    override fun applicableAnnotations(): List<String> = listOf(ANNOTATION)
    override fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean = true

    @Suppress("UnstableApiUsage")
    override fun visitAnnotationUsage(
        context: JavaContext,
        element: UElement,
        annotationInfo: AnnotationInfo,
        usageInfo: AnnotationUsageInfo,
    ) {
        (element as? KotlinUAnnotation)?.getParentOfType(KotlinUMethod::class.java)?.let { method ->
            if (method.name.contains(" ")) {
                context.report(
                    issue = ISSUE,
                    scope = method.nameIdentifier,
                    location = context.getLocation(method.nameIdentifier),
                    message =
                        "Spaces are not allowed in test names. Use pascalCase_withUnderScores" +
                            " instead.",
                )
            }
        }
    }

    companion object {
        private const val ANNOTATION = "org.junit.Test"

        @JvmStatic
        val ISSUE =
            Issue.create(
                id = "TestFunctionNameViolation",
                briefDescription = "Spaces not allowed in test function names.",
                explanation =
                    """
                    We don't allow test function names because it leads to issues with our test
                    harness system (for example, see b/277739595). Please use
                    pascalCase_withUnderScores instead.
                """,
                category = Category.TESTING,
                priority = 8,
                severity = Severity.FATAL,
                implementation =
                    Implementation(
                        TestFunctionNameViolationDetector::class.java,
                        Scope.JAVA_FILE_SCOPE,
                    ),
            )
    }
}
+103 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * 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.android.internal.systemui.lint

import com.android.tools.lint.checks.infrastructure.TestFile
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Issue
import org.junit.Test

@Suppress("UnstableApiUsage")
class TestFunctionNameViolationDetectorTest : SystemUILintDetectorTest() {
    override fun getDetector(): Detector {
        return TestFunctionNameViolationDetector()
    }

    override fun getIssues(): List<Issue> {
        return listOf(
            TestFunctionNameViolationDetector.ISSUE,
        )
    }

    @Test
    fun violations() {
        lint()
            .files(
                kotlin(
                    """
                    package test.pkg.name

                    import org.junit.Test

                    class MyTest {
                        @Test
                        fun `illegal test name - violation should be detected`() {
                            // some test code here.
                        }

                        @Test
                        fun legitimateTestName_doesNotViolate() {
                            // some test code here.
                        }

                        fun helperFunction_doesNotViolate() {
                            // some code.
                        }

                        fun `helper function - does not violate`() {
                            // some code.
                        }
                    }
                """
                        .trimIndent()
                ),
                testAnnotationStub,
            )
            .issues(
                TestFunctionNameViolationDetector.ISSUE,
            )
            .run()
            .expectWarningCount(0)
            .expect(
                """
                src/test/pkg/name/MyTest.kt:7: Error: Spaces are not allowed in test names. Use pascalCase_withUnderScores instead. [TestFunctionNameViolation]
                    fun `illegal test name - violation should be detected`() {
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                1 errors, 0 warnings
                """
            )
    }

    companion object {
        private val testAnnotationStub: TestFile =
            kotlin(
                """
                package org.junit

                import java.lang.annotation.ElementType
                import java.lang.annotation.Retention
                import java.lang.annotation.RetentionPolicy
                import java.lang.annotation.Target

                @Retention(RetentionPolicy.RUNTIME)
                @Target({ElementType.METHOD})
                annotation class Test
            """
            )
    }
}