All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.performance.generator.FileContentGenerator.groovy Maven / Gradle / Ivy

There is a newer version: 8.11.1
Show newest version
/*
 * Copyright 2017 the original author or authors.
 *
 * 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 org.gradle.performance.generator

import groovy.transform.CompileStatic
import org.gradle.test.fixtures.dsl.GradleDsl
import org.gradle.test.fixtures.language.Language

import static org.gradle.test.fixtures.dsl.GradleDsl.KOTLIN

@CompileStatic
abstract class FileContentGenerator {
    static FileContentGenerator forConfig(TestProjectGeneratorConfiguration config) {
        switch (config.dsl) {
            case KOTLIN:
                return new KotlinDslFileContentGenerator(config)
            case GradleDsl.GROOVY:
                return new GroovyDslFileContentGenerator(config)
            default:
                throw new IllegalStateException("Should not be here!")
        }
    }

    protected final TestProjectGeneratorConfiguration config

    FileContentGenerator(TestProjectGeneratorConfiguration config) {
        this.config = config
    }

    String generateVersionCatalog() {
        return """
        [libraries]
        groovy = "org.codehaus.groovy:groovy:2.5.22"
        testng = "org.testng:testng:6.4"
        junit = "junit:junit:4.13"

        ${config.externalApiDependencies
            .collect { "${it.key} = \"${it.value}\"" }
            .join("\n        ")}
        ${config.externalImplementationDependencies
            .collect { "${it.key} = \"${it.value}\"" }
            .join("\n        ")}
        """
    }

    String generateBuildGradle(Language language, Integer subProjectNumber, DependencyTree dependencyTree) {
        def isRoot = subProjectNumber == null
        if (isRoot && config.subProjects > 0) {
            if (config.compositeBuild) {
                return """
                ${createTaskThatDependsOnAllIncludedBuildsTaskWithSameName('clean')}
                ${createTaskThatDependsOnAllIncludedBuildsTaskWithSameName('assemble')}
                """
            }
            return ""
        }
        return """
        plugins {
            ${config.plugins.collect { decideOnJavaPlugin(it, dependencyTree.hasParentProject(subProjectNumber)) }.join("\n        ")}
        }

        group = "org.gradle.test.performance"
        version = "2.0"

        repositories {
            ${config.repositories.join("\n            ")}
        }

        ${dependenciesBlock('api', 'implementation', 'testImplementation', subProjectNumber, dependencyTree)}

        dependencies{
        ${
            language == Language.GROOVY ? versionCatalogDependencyDeclaration('implementation', 'groovy') : ""
        }
        }


        ${tasksConfiguration()}
        """
    }

    String generateSettingsGradle(boolean isRoot) {
        if (config.compositeBuild) {
            if (!isRoot) {
                return ""
            }
            return (0..config.subProjects - 1).collect {
                if (config.compositeBuild.usePredefinedPublications()) {
                    """
                    includeBuild("project$it") {
                        dependencySubstitution {
                            substitute(module("org.gradle.test.performance:project${it}")).using(project(":"))
                        }
                    }
                    """
                } else {
                    "includeBuild(\"project$it\")"
                }
            }.join("\n")
        } else {
            if (!isRoot) {
                return null
            }

            String includedProjects = ""
            if (config.subProjects != 0) {
                includedProjects = """
                    ${(0..config.subProjects - 1).collect { "include(\"project$it\")" }.join("\n")}
                """
            }

            return includedProjects + generateEnableFeaturePreviewCode()
        }
    }

    abstract protected String generateEnableFeaturePreviewCode()

    String generateGradleProperties(boolean isRoot) {
        if (!isRoot && !config.compositeBuild) {
            return null
        }
        """
        org.gradle.jvmargs=-Xms${config.daemonMemory} -Xmx${config.daemonMemory} -Dfile.encoding=UTF-8
        org.gradle.parallel=${config.parallel}
        org.gradle.workers.max=${config.maxWorkers}
        compilerMemory=${config.compilerMemory}
        testRunnerMemory=${config.testRunnerMemory}
        testForkEvery=${config.testForkEvery}
        ${->
            config.systemProperties.entrySet().collect { "systemProp.${it.key}=${it.value}" }.join("\n")
        }
        """
    }

    String generatePomXML(Integer subProjectNumber, DependencyTree dependencyTree) {
        def body = ""
        def isParent = subProjectNumber == null || config.subProjects == 0
        def hasSources = subProjectNumber != null || config.subProjects == 0
        if (isParent) {
            if (config.subProjects != 0) {
                body += """
                    
                        ${(0..config.subProjects - 1).collect { "project$it" }.join("\n                ")}
                    
                """
            }
            body += """
            
                
                    
                        org.apache.maven.plugins
                        maven-compiler-plugin
                        3.8.0
                        
                            1.8
                            1.8
                            true
                            ${config.compilerMemory}
                            ${config.compilerMemory}
                        
                    
                    
                        org.apache.maven.plugins
                        maven-surefire-plugin
                        2.19.1
                        
                            ${config.maxParallelForks}
                            true
                            -Xms${config.testRunnerMemory} -Xmx${config.testRunnerMemory}
                        
                    
                    
                        org.apache.maven.plugins
                        maven-surefire-report-plugin
                        2.19.1
                        
                            
                                test-report
                                
                                    report-only
                                
                                test
                            
                        
                    
                
            
            """
        } else {
            body += """
                
                    org.gradle.test.performance
                    project
                    1.0
                
            """
        }
        if (hasSources) {
            def subProjectNumbers = dependencyTree.getChildProjectIds(subProjectNumber)
            def subProjectDependencies = ''
            if (subProjectNumbers?.size() > 0) {
                subProjectDependencies = subProjectNumbers.collect { convertToPomDependency("org.gradle.test.performance:project$it:1.0") }.join("")
            }
            body += """
            
                ${config.externalApiDependencies.values().collect { convertToPomDependency(it) }.join("")}
                ${config.externalImplementationDependencies.values().collect { convertToPomDependency(it) }.join("")}
                ${convertToPomDependency('junit:junit:4.13', 'test')}
                ${subProjectDependencies}
            
            """
        }
        """
        
            4.0.0
            org.gradle.test.performance
            project${subProjectNumber == null ? '' : subProjectNumber}
            ${hasSources ? 'jar' : 'pom'}
            1.0
            $body
        
        """
    }

    String generatePerformanceScenarios(boolean isRoot) {
        if (isRoot) {
            def fileToChange = config.fileToChangeByScenario['assemble']
            """
                nonAbiChange {
                  tasks = ["assemble"]
                  apply-non-abi-change-to = "${fileToChange}"
                  maven {
                    targets = ["clean", "package", "-Dmaven.test.skip=true", "-T", "4"]
                  }
                  bazel {
                    targets = ["build", "//..."]
                  }
                }

                abiChange {
                  tasks = ["assemble"]
                  apply-abi-change-to = "${fileToChange}"
                  maven {
                    targets = ["clean", "package", "-Dmaven.test.skip=true", "-T", "4"]
                  }
                  bazel {
                    targets = ["build", "//..."]
                  }
                }

                cleanAssemble {
                  tasks = ["clean", "assemble"]
                   maven {
                    targets = ["clean", "package", "-Dmaven.test.skip=true", "-T", "4"]
                  }
                }

                cleanAssembleCached {
                  tasks = ["clean", "assemble"]
                  gradle-args = ["--build-cache"]
                }

                cleanBuild {
                  tasks = ["clean", "build"]
                  maven {
                    targets = ["clean", "package", "-T", "4"]
                  }
                }

                cleanBuildCached {
                  tasks = ["clean", "build"]
                  maven {
                    targets = ["clean", "package", "-T", "4"]
                  }
                  gradle-args = ["--build-cache"]
                }

                incrementalCompile {
                  tasks = ["compileJava"]
                   maven {
                    targets = ["compile", "-T", "4"]
                  }
                  apply-non-abi-change-to = "${fileToChange}"
                }

                incrementalTest {
                  tasks = ["build"]
                  apply-non-abi-change-to = "${fileToChange}"
                   maven {
                    targets = ["test", "-T", "4"]
                  }
                }

                cleanTest {
                  tasks = ["clean", "test"]
                  maven {
                    targets = ["clean", "test", "-T", "4"]
                  }
                }

                cleanTestCached {
                  tasks = ["clean", "test"]
                  gradle-args = ["--build-cache"]
                }

            """.stripIndent()
        }
    }

    String generateProductionClassFile(Integer subProjectNumber, int classNumber, DependencyTree dependencyTree) {
        def properties = ''
        def ownPackageName = packageName(classNumber, subProjectNumber)
        def imports = ''
        def children = dependencyTree.getTransitiveChildClassIds(classNumber)
        (0..Math.max(propertyCount, children.size()) - 1).each {
            def propertyType
            if (it < children.size()) {
                def childNumber = children.get(it)
                propertyType = "Production${childNumber}"
                def childPackageName = packageName(childNumber, config.subProjects == 0 ? null : dependencyTree.getProjectIdForClass(childNumber))
                if (childPackageName != ownPackageName) {
                    imports += imports == '' ? '\n        ' : ''
                    imports += "import ${childPackageName}.Production${childNumber};\n        "
                }
            } else {
                propertyType = "String"
            }
            properties += """
            private $propertyType property$it;

            public $propertyType getProperty$it() {
                return property$it;
            }

            public void setProperty$it($propertyType value) {
                property$it = value;
            }
            """
        }

        """
        package ${ownPackageName};
        ${imports}
        public class Production$classNumber {
            $properties
        }
        """
    }

    String generateTestClassFile(Integer subProjectNumber, int classNumber, DependencyTree dependencyTree) {
        def testMethods = ""
        def ownPackageName = packageName(classNumber, subProjectNumber)
        def imports = ''
        def children = dependencyTree.getTransitiveChildClassIds(classNumber)
        (0..Math.max(propertyCount, children.size()) - 1).each {
            def propertyType
            def propertyValue
            if (it < children.size()) {
                def childNumber = children.get(it)
                propertyType = "Production${childNumber}"
                propertyValue = "new Production${childNumber}()"
                def childPackageName = packageName(childNumber, config.subProjects == 0 ? null : dependencyTree.getProjectIdForClass(childNumber))
                if (childPackageName != ownPackageName) {
                    imports += imports == '' ? '\n        ' : ''
                    imports += "import ${childPackageName}.Production${childNumber};\n        "
                }
            } else {
                propertyType = "String"
                propertyValue = '"value"'
            }
            testMethods += """
            @Test
            public void testProperty$it() {
                $propertyType value = $propertyValue;
                objectUnderTest.setProperty$it(value);
                assertEquals(value, objectUnderTest.getProperty$it());
            }
            """
        }

        """
        package ${packageName(classNumber, subProjectNumber)};
        ${imports}
        import org.${config.useTestNG ? 'testng.annotations' : 'junit'}.Test;
        import static org.${config.useTestNG ? 'testng' : 'junit'}.Assert.*;

        public class Test$classNumber {
            Production$classNumber objectUnderTest = new Production$classNumber();
            $testMethods
        }
        """
    }

    def packageName(int classNumber, Integer subProjectNumber = null, String separator = '.') {
        def projectPackage = subProjectNumber == null ? "" : "${separator}project$subProjectNumber"
        def subPackage = "${separator}p${(int) (classNumber / 20)}"
        "org${separator}gradle${separator}test${separator}performance${separator}${config.projectName.toLowerCase()}${projectPackage}$subPackage"
    }

    protected final int getPropertyCount() {
        Math.ceil((double) config.minLinesOfCodePerSourceFile / 10)
    }

    protected final String decideOnJavaPlugin(String plugin, Boolean projectHasParents) {
        if (plugin.contains('java')) {
            if (projectHasParents) {
                return """
                    ${pluginBlockApply("java-library")}
                """
            } else {
                return pluginBlockApply("java")
            }
        }
        return pluginBlockApply(plugin)
    }

    private dependenciesBlock(String api, String implementation, String testImplementation, Integer subProjectNumber, DependencyTree dependencyTree) {
        def hasParent = dependencyTree.hasParentProject(subProjectNumber)
        def subProjectNumbers = dependencyTree.getChildProjectIds(subProjectNumber)
        def subProjectDependencies = ''
        if (subProjectNumbers?.size() > 0) {
            def abiProjectNumber = subProjectNumbers.get(DependencyTree.API_DEPENDENCY_INDEX)
            subProjectDependencies = subProjectNumbers.collect {
                it == abiProjectNumber ? projectDependencyDeclaration(hasParent ? api : implementation, abiProjectNumber) : projectDependencyDeclaration(implementation, it)
            }.join("\n            ")
        }
        def block = """
                    ${config.externalApiDependencies.keySet().collect { versionCatalogDependencyDeclaration(hasParent ? api : implementation, it) }.join("\n            ")}
                    ${config.externalImplementationDependencies.keySet().collect { versionCatalogDependencyDeclaration(implementation, it) }.join("\n            ")}
                    ${versionCatalogDependencyDeclaration(testImplementation, config.useTestNG ? 'testng' : 'junit')}

                    $subProjectDependencies
        """
        return """
            dependencies {
                $block
            }
        """
    }

    protected final convertToPomDependency(String dependency, String scope = 'compile') {
        def parts = dependency.split(':')
        def groupId = parts[0]
        def artifactId = parts[1]
        def version = parts[2]
        """
                
                    $groupId
                    $artifactId
                    $version
                    $scope
                """
    }


    protected abstract String tasksConfiguration()

    protected abstract String pluginBlockApply(String plugin)

    protected abstract String createTaskThatDependsOnAllIncludedBuildsTaskWithSameName(String taskName)


    protected abstract String versionCatalogDependencyDeclaration(String configuration, String alias)

    protected abstract String projectDependencyDeclaration(String configuration, int projectNumber)

    protected final String dependency(int projectNumber) {
        if (config.compositeBuild) {
            return "\"org.gradle.test.performance:project${projectNumber}:1.0\""
        }
        return "project(\":project${projectNumber}\")"
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy