001package org.eclipse.aether.internal.impl.resolution; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.IOException; 024import java.nio.file.Files; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.List; 028import java.util.Map; 029import java.util.concurrent.atomic.AtomicReference; 030 031import org.eclipse.aether.DefaultRepositorySystemSession; 032import org.eclipse.aether.RepositorySystemSession; 033import org.eclipse.aether.artifact.Artifact; 034import org.eclipse.aether.artifact.DefaultArtifact; 035import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory; 036import org.eclipse.aether.internal.test.util.TestUtils; 037import org.eclipse.aether.repository.ArtifactRepository; 038import org.eclipse.aether.resolution.ArtifactRequest; 039import org.eclipse.aether.resolution.ArtifactResult; 040import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; 041import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; 042import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector; 043import org.eclipse.aether.util.artifact.ArtifactIdUtils; 044import org.junit.Before; 045import org.junit.Test; 046 047import static org.hamcrest.MatcherAssert.assertThat; 048import static org.hamcrest.Matchers.containsString; 049import static org.hamcrest.Matchers.empty; 050import static org.hamcrest.Matchers.equalTo; 051import static org.hamcrest.Matchers.not; 052import static org.hamcrest.Matchers.notNullValue; 053 054/** 055 * UT for {@link TrustedChecksumsArtifactResolverPostProcessor}. 056 */ 057public class TrustedChecksumsArtifactResolverPostProcessorTest implements TrustedChecksumsSource 058{ 059 private static final String TRUSTED_SOURCE_NAME = "test"; 060 061 private Artifact artifactWithoutTrustedChecksum; 062 063 private Artifact artifactWithTrustedChecksum; 064 065 private String artifactTrustedChecksum; 066 067 protected DefaultRepositorySystemSession session; 068 069 protected ChecksumAlgorithmFactory checksumAlgorithmFactory = new Sha1ChecksumAlgorithmFactory(); 070 071 private TrustedChecksumsArtifactResolverPostProcessor subject; 072 073 private TrustedChecksumsSource.Writer trustedChecksumsWriter; 074 075 @Before 076 public void prepareSubject() throws IOException 077 { 078 // make the two artifacts, BOTH as resolved 079 File tmp = Files.createTempFile( "artifact", "tmp" ).toFile(); 080 artifactWithoutTrustedChecksum = new DefaultArtifact( "test:test:1.0" ).setFile( tmp ); 081 artifactWithTrustedChecksum = new DefaultArtifact( "test:test:2.0" ).setFile( tmp ); 082 artifactTrustedChecksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; // empty file 083 084 session = TestUtils.newSession(); 085 ChecksumAlgorithmFactorySelector selector = new ChecksumAlgorithmFactorySelector() 086 { 087 @Override 088 public ChecksumAlgorithmFactory select( String algorithmName ) 089 { 090 if ( checksumAlgorithmFactory.getName().equals( algorithmName ) ) 091 { 092 return checksumAlgorithmFactory; 093 } 094 throw new IllegalArgumentException("no alg factory for " + algorithmName); 095 } 096 097 @Override 098 public Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() 099 { 100 return Collections.singletonList( checksumAlgorithmFactory ); 101 } 102 }; 103 subject = new TrustedChecksumsArtifactResolverPostProcessor( selector, 104 Collections.singletonMap( TRUSTED_SOURCE_NAME, this ) ); 105 trustedChecksumsWriter = null; 106 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums", Boolean.TRUE.toString() ); 107 } 108 109 // -- TrustedChecksumsSource interface BEGIN 110 111 @Override 112 public Map<String, String> getTrustedArtifactChecksums( RepositorySystemSession session, Artifact artifact, 113 ArtifactRepository artifactRepository, 114 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories ) 115 { 116 if ( ArtifactIdUtils.toId( artifactWithTrustedChecksum ).equals( ArtifactIdUtils.toId( artifact ) ) ) 117 { 118 return Collections.singletonMap( checksumAlgorithmFactory.getName(), artifactTrustedChecksum ); 119 } 120 else 121 { 122 return Collections.emptyMap(); 123 } 124 } 125 126 @Override 127 public Writer getTrustedArtifactChecksumsWriter( RepositorySystemSession session ) 128 { 129 return trustedChecksumsWriter; 130 } 131 132 // -- TrustedChecksumsSource interface END 133 134 private ArtifactResult createArtifactResult( Artifact artifact ) 135 { 136 ArtifactResult artifactResult = new ArtifactResult( new ArtifactRequest().setArtifact( artifact ) ); 137 artifactResult.setArtifact( artifact ); 138 return artifactResult; 139 } 140 141 // UTs below 142 143 @Test 144 public void haveMatchingChecksumPass() 145 { 146 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 147 assertThat( artifactResult.isResolved(), equalTo( true ) ); 148 149 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 150 assertThat( artifactResult.isResolved(), equalTo( true ) ); 151 } 152 153 @Test 154 public void haveNoChecksumPass() 155 { 156 ArtifactResult artifactResult = createArtifactResult( artifactWithoutTrustedChecksum ); 157 assertThat( artifactResult.isResolved(), equalTo( true ) ); 158 159 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 160 assertThat( artifactResult.isResolved(), equalTo( true ) ); 161 } 162 163 @Test 164 public void haveNoChecksumFailIfMissingEnabledFail() 165 { 166 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums.failIfMissing", 167 Boolean.TRUE.toString() ); 168 ArtifactResult artifactResult = createArtifactResult( artifactWithoutTrustedChecksum ); 169 assertThat( artifactResult.isResolved(), equalTo( true ) ); 170 171 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 172 assertThat( artifactResult.isResolved(), equalTo( false ) ); 173 assertThat( artifactResult.getExceptions(), not( empty() ) ); 174 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 175 containsString( "Missing from " + TRUSTED_SOURCE_NAME + " trusted" ) ); 176 } 177 178 @Test 179 public void haveMismatchingChecksumFail() 180 { 181 artifactTrustedChecksum = "foobar"; 182 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 183 assertThat( artifactResult.isResolved(), equalTo( true ) ); 184 185 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 186 assertThat( artifactResult.isResolved(), equalTo( false ) ); 187 assertThat( artifactResult.getExceptions(), not( empty() ) ); 188 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 189 containsString( "trusted checksum mismatch" ) ); 190 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 191 containsString( TRUSTED_SOURCE_NAME + "=" + artifactTrustedChecksum ) ); 192 } 193 194 @Test 195 public void recordCalculatedChecksum() 196 { 197 AtomicReference<String> recordedChecksum = new AtomicReference<>(null); 198 this.trustedChecksumsWriter = new Writer() 199 { 200 @Override 201 public void addTrustedArtifactChecksums( Artifact artifact, ArtifactRepository artifactRepository, 202 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories, 203 Map<String, String> trustedArtifactChecksums ) 204 { 205 recordedChecksum.set( trustedArtifactChecksums.get( checksumAlgorithmFactory.getName() ) ); 206 } 207 }; 208 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums.record", 209 Boolean.TRUE.toString() ); 210 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 211 assertThat( artifactResult.isResolved(), equalTo( true ) ); 212 213 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 214 assertThat( artifactResult.isResolved(), equalTo( true ) ); 215 216 String checksum = recordedChecksum.get(); 217 assertThat( checksum, notNullValue() ); 218 assertThat( checksum, equalTo( artifactTrustedChecksum ) ); 219 } 220}