"Fossies" - the Fresh Open Source Software Archive

Member "gradle-8.1.1/subprojects/normalization-java/src/test/groovy/org/gradle/api/internal/changedetection/state/AbiExtractingClasspathResourceHasherTest.groovy" (20 Apr 2023, 6382 Bytes) of package /linux/misc/gradle-8.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Java source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright 2021 the original author or authors.
    3  *
    4  * Licensed under the Apache License, Version 2.0 (the "License");
    5  * you may not use this file except in compliance with the License.
    6  * You may obtain a copy of the License at
    7  *
    8  *      http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 package org.gradle.api.internal.changedetection.state
   18 
   19 import org.apache.commons.io.IOUtils
   20 import org.gradle.api.internal.file.archive.ZipEntry
   21 import org.gradle.internal.fingerprint.hashing.ConfigurableNormalizer
   22 import org.gradle.internal.fingerprint.hashing.RegularFileSnapshotContext
   23 import org.gradle.internal.fingerprint.hashing.ZipEntryContext
   24 import org.gradle.internal.hash.HashCode
   25 import org.gradle.internal.hash.Hashing
   26 import org.gradle.internal.normalization.java.ApiClassExtractor
   27 import org.gradle.internal.snapshot.RegularFileSnapshot
   28 import org.junit.Rule
   29 import org.junit.rules.TemporaryFolder
   30 import spock.lang.Issue
   31 import spock.lang.Specification
   32 
   33 class AbiExtractingClasspathResourceHasherTest extends Specification {
   34     @Rule
   35     TemporaryFolder temporaryDirectory = new TemporaryFolder()
   36 
   37     def setup() {
   38         temporaryDirectory.create()
   39     }
   40 
   41     def "api class extractors affect the configuration hash"() {
   42         def apiClassExtractor1 = Mock(ApiClassExtractor)
   43         def apiClassExtractor2 = Mock(ApiClassExtractor)
   44 
   45         def resourceHasher1 = AbiExtractingClasspathResourceHasher.withFallback(apiClassExtractor1)
   46         def resourceHasher2 = AbiExtractingClasspathResourceHasher.withFallback(apiClassExtractor2)
   47 
   48         when:
   49         def configurationHash1 = configurationHashOf(resourceHasher1)
   50         def configurationHash2 = configurationHashOf(resourceHasher2)
   51 
   52         then:
   53         configurationHash1 != configurationHash2
   54 
   55         1 * apiClassExtractor1.appendConfigurationToHasher(_) >> { args -> args[0].putString("first") }
   56         1 * apiClassExtractor2.appendConfigurationToHasher(_) >> { args -> args[0].putString("second") }
   57     }
   58 
   59     @Issue("https://github.com/gradle/gradle/issues/20398")
   60     def "falls back to full file hash when abi extraction fails for a regular file"() {
   61         def apiClassExtractor = Mock(ApiClassExtractor)
   62 
   63         def resourceHasher = AbiExtractingClasspathResourceHasher.withFallback(apiClassExtractor)
   64         def fileSnapshotContext = Mock(RegularFileSnapshotContext)
   65         def fileSnapshot = Mock(RegularFileSnapshot)
   66 
   67         given:
   68         def file = temporaryDirectory.newFile('String.class')
   69         file.bytes = bytesOf(String.class)
   70 
   71         when:
   72         resourceHasher.hash(fileSnapshotContext)
   73 
   74         then:
   75         1 * fileSnapshotContext.getSnapshot() >> fileSnapshot
   76         2 * fileSnapshot.getName() >> file.name
   77         1 * fileSnapshot.getAbsolutePath() >> file.absolutePath
   78         1 * apiClassExtractor.extractApiClassFrom(_) >> { args -> throw new Exception("Boom!") }
   79 
   80         and:
   81         1 * fileSnapshot.getHash()
   82 
   83         and:
   84         noExceptionThrown()
   85     }
   86 
   87     @Issue("https://github.com/gradle/gradle/issues/20398")
   88     def "falls back to full zip entry hash when abi extraction fails for a zip entry"() {
   89         def apiClassExtractor = Mock(ApiClassExtractor)
   90 
   91         def resourceHasher = AbiExtractingClasspathResourceHasher.withFallback(apiClassExtractor)
   92         def zipEntryContext = Mock(ZipEntryContext)
   93         def zipEntry = Mock(ZipEntry)
   94         def classContent = bytesOf(String.class)
   95 
   96         when:
   97         def hash = resourceHasher.hash(zipEntryContext)
   98 
   99         then:
  100         1 * zipEntryContext.getEntry() >> zipEntry
  101         2 * zipEntry.getName() >> 'String.class'
  102         1 * zipEntry.getContent() >> classContent
  103         1 * apiClassExtractor.extractApiClassFrom(_) >> { args -> throw new Exception("Boom!") }
  104 
  105         and:
  106         hash == Hashing.hashBytes(classContent)
  107 
  108         and:
  109         noExceptionThrown()
  110     }
  111 
  112     def "does not fall back to full file hash when fallback is not requested and abi extraction fails for a regular file"() {
  113         def apiClassExtractor = Mock(ApiClassExtractor)
  114 
  115         def resourceHasher = AbiExtractingClasspathResourceHasher.withoutFallback(apiClassExtractor)
  116         def fileSnapshotContext = Mock(RegularFileSnapshotContext)
  117         def fileSnapshot = Mock(RegularFileSnapshot)
  118 
  119         given:
  120         def file = temporaryDirectory.newFile('String.class')
  121         file.bytes = bytesOf(String.class)
  122 
  123         when:
  124         resourceHasher.hash(fileSnapshotContext)
  125 
  126         then:
  127         1 * fileSnapshotContext.getSnapshot() >> fileSnapshot
  128         1 * fileSnapshot.getName() >> file.name
  129         1 * fileSnapshot.getAbsolutePath() >> file.absolutePath
  130         1 * apiClassExtractor.extractApiClassFrom(_) >> { args -> throw new Exception("Boom!") }
  131 
  132         and:
  133         def e = thrown(Exception)
  134         e.message == "Boom!"
  135     }
  136 
  137     def "does not fall back to full zip entry hashing when fallback is not requested and abi extraction fails for a zip entry"() {
  138         def apiClassExtractor = Mock(ApiClassExtractor)
  139 
  140         def resourceHasher = AbiExtractingClasspathResourceHasher.withoutFallback(apiClassExtractor)
  141         def zipEntryContext = Mock(ZipEntryContext)
  142         def zipEntry = Mock(ZipEntry)
  143 
  144         when:
  145         resourceHasher.hash(zipEntryContext)
  146 
  147         then:
  148         1 * zipEntryContext.getEntry() >> zipEntry
  149         2 * zipEntry.getName() >> 'String.class'
  150         1 * zipEntry.getContent() >> bytesOf(String.class)
  151         1 * apiClassExtractor.extractApiClassFrom(_) >> { args -> throw new Exception("Boom!") }
  152 
  153         and:
  154         def e = thrown(Exception)
  155         e.message == "Boom!"
  156     }
  157 
  158     private static HashCode configurationHashOf(ConfigurableNormalizer normalizer) {
  159         def hasher = Hashing.md5().newHasher()
  160         normalizer.appendConfigurationToHasher(hasher)
  161         return hasher.hash()
  162     }
  163 
  164     private static byte[] bytesOf(Class<?> clazz) {
  165         String classFile = "/${clazz.getName().replaceAll('\\.', '/')}.class"
  166         return IOUtils.toByteArray(clazz.getResource(classFile).openStream())
  167     }
  168 }