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

org.gradle.api.internal.changedetection.state.DirectoryScanningIntegTest.groovy Maven / Gradle / Ivy

/*
 * Copyright 2016 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.api.internal.changedetection.state

import org.gradle.integtests.fixtures.Sample
import org.gradle.integtests.fixtures.daemon.DaemonIntegrationSpec
import org.gradle.util.GFileUtils
import org.gradle.util.Requires
import org.gradle.util.TestPrecondition
import org.junit.Rule

// This fails with Java 1.8.0_05, but succeeds with 1.8.0_74
@Requires(adhoc = { TestPrecondition.JDK7_OR_LATER.isFulfilled() && System.getProperty('java.version') != '1.8.0_05' && TestPrecondition.NOT_JDK_IBM.fulfilled })
class DirectoryScanningIntegTest extends DaemonIntegrationSpec {
    @Rule
    public final Sample sample = new Sample(testDirectoryProvider, 'dirscanning', '.')

    boolean trackLocations = false
    boolean printCounts = true

    def setup() {
        executer.withArgument("--no-search-upward")
        if (trackLocations) {
            executer.withArgument("-PtrackLocations")
        }
    }

    // read serialized counts from file and transform paths to relative paths
    private Map loadDirectoryScanCounts() {
        Map scanCounts = readSerializedFile('countDirectoryScans.ser')
        // transform into relative paths
        scanCounts.collectEntries { File dir, Integer count ->
            [GFileUtils.relativePath(testDirectory, dir), count]
        }
    }

    private Object readSerializedFile(String fileName) {
        def file = file(fileName)
        if (file.exists()) {
            return file.withInputStream {
                new ObjectInputStream(it).readObject()
            }
        }
        null
    }

    private Map> loadDirectoryScanLocations() {
        readSerializedFile('directoryScanLocations.ser')
    }

    private void printDirectoryScanLocations() {
        def locations = loadDirectoryScanLocations()
        locations?.each { k, v ->
            println "directory: ${GFileUtils.relativePath(testDirectory, k)}"
            v.each { Exception e ->
                println "Scan originated from:"
                printStackTrace(e, System.out)
                println()
            }
            println "-----------------------------------------"
        }
    }

    private void printStackTrace(Throwable exception, Appendable builder) {
        for (StackTraceElement element : exception.getStackTrace()) {
            if (element.getLineNumber() > 0) {
                builder.append(" at ")
                builder.append(element.getClassName())
                builder.append('(')
                builder.append(element.getFileName())
                builder.append(':')
                builder.append(String.valueOf(element.getLineNumber()))
                builder.append(')')
                builder.append('\n')
            }
            if (element.className == 'org.gradle.execution.DefaultBuildExecuter') {
                break
            }
        }
        builder.append('\n')
    }

    def "count directory scans for Java project with single source file"() {
        given:
        buildFile << '''
apply plugin: 'java'
'''
        file('src/main/java/Test.java') << 'class Test {}'
        expect:
        succeeds("build")
        checkDirectoryScanning()
    }

    def "count directory scans for Java project with single source file and test file"() {
        given:
        buildFile << '''
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.12'
}
'''
        file('src/main/java/Hello.java') << '''
public class Hello {
    private final String property;

    public Hello(String param) {
        this.property = param;
    }

    public String getProperty() {
        return property;
    }
}
'''
        file('src/main/test/HelloTest.java') << '''
import static org.junit.Assert.*;

public class HelloTest {
     private final Hello hello = new Hello("value");

     @org.junit.Test
     public void test() {
        assertEquals(hello.getProperty(), "value");
     }
}
'''
        expect:
        succeeds("test")
        checkDirectoryScanning()
    }

    private void checkDirectoryScanning(int maxScans = 3) {
        def scanCounts = loadDirectoryScanCounts()
        if (printCounts) {
            def valueSort = { a, b -> a.value.compareTo(b.value) }
            def mapReport = { it.sort(valueSort).collect { k, v -> "$k\t$v times" }.join('\n') }
            println "Directory scanning report:\n${mapReport(scanCounts)}"
            def cacheMisses = readSerializedFile('cacheMisses.ser')
            if (cacheMisses) {
                println "Cache misses:\n${mapReport(cacheMisses)}"
            } else {
                println "No cache misses."
            }
            def cacheHits = readSerializedFile('cacheHits.ser')
            if (cacheHits) {
                println "Cache hits:\n${mapReport(cacheHits)}"
            } else {
                println "No cache hits."
            }
        }
        if (trackLocations) {
            printDirectoryScanLocations()
        }
        scanCounts.each { String path, Integer count ->
            assert count <= maxScans: "$path has too many scans."
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy