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 java.util.stream.Collectors.toList; 048import static org.hamcrest.MatcherAssert.assertThat; 049import static org.hamcrest.Matchers.containsString; 050import static org.hamcrest.Matchers.empty; 051import static org.hamcrest.Matchers.equalTo; 052import static org.hamcrest.Matchers.not; 053import static org.hamcrest.Matchers.notNullValue; 054 055/** 056 * UT for {@link TrustedChecksumsArtifactResolverPostProcessor}. 057 */ 058public class TrustedChecksumsArtifactResolverPostProcessorTest implements TrustedChecksumsSource 059{ 060 private static final String TRUSTED_SOURCE_NAME = "test"; 061 062 private Artifact artifactWithoutTrustedChecksum; 063 064 private Artifact artifactWithTrustedChecksum; 065 066 private String artifactTrustedChecksum; 067 068 protected DefaultRepositorySystemSession session; 069 070 protected ChecksumAlgorithmFactory checksumAlgorithmFactory = new Sha1ChecksumAlgorithmFactory(); 071 072 private TrustedChecksumsArtifactResolverPostProcessor subject; 073 074 private TrustedChecksumsSource.Writer trustedChecksumsWriter; 075 076 @Before 077 public void prepareSubject() throws IOException 078 { 079 // make the two artifacts, BOTH as resolved 080 File tmp = Files.createTempFile( "artifact", "tmp" ).toFile(); 081 artifactWithoutTrustedChecksum = new DefaultArtifact( "test:test:1.0" ).setFile( tmp ); 082 artifactWithTrustedChecksum = new DefaultArtifact( "test:test:2.0" ).setFile( tmp ); 083 artifactTrustedChecksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709"; // empty file 084 085 session = TestUtils.newSession(); 086 ChecksumAlgorithmFactorySelector selector = new ChecksumAlgorithmFactorySelector() 087 { 088 @Override 089 public ChecksumAlgorithmFactory select( String algorithmName ) 090 { 091 if ( checksumAlgorithmFactory.getName().equals( algorithmName ) ) 092 { 093 return checksumAlgorithmFactory; 094 } 095 throw new IllegalArgumentException("no alg factory for " + algorithmName); 096 } 097 098 @Override 099 public List<ChecksumAlgorithmFactory> selectList( Collection<String> algorithmNames ) 100 { 101 return algorithmNames.stream() 102 .map( this::select ) 103 .collect( toList() ); 104 } 105 106 @Override 107 public Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() 108 { 109 return Collections.singletonList( checksumAlgorithmFactory ); 110 } 111 }; 112 subject = new TrustedChecksumsArtifactResolverPostProcessor( selector, 113 Collections.singletonMap( TRUSTED_SOURCE_NAME, this ) ); 114 trustedChecksumsWriter = null; 115 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums", Boolean.TRUE.toString() ); 116 } 117 118 // -- TrustedChecksumsSource interface BEGIN 119 120 @Override 121 public Map<String, String> getTrustedArtifactChecksums( RepositorySystemSession session, Artifact artifact, 122 ArtifactRepository artifactRepository, 123 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories ) 124 { 125 if ( ArtifactIdUtils.toId( artifactWithTrustedChecksum ).equals( ArtifactIdUtils.toId( artifact ) ) ) 126 { 127 return Collections.singletonMap( checksumAlgorithmFactory.getName(), artifactTrustedChecksum ); 128 } 129 else 130 { 131 return Collections.emptyMap(); 132 } 133 } 134 135 @Override 136 public Writer getTrustedArtifactChecksumsWriter( RepositorySystemSession session ) 137 { 138 return trustedChecksumsWriter; 139 } 140 141 // -- TrustedChecksumsSource interface END 142 143 private ArtifactResult createArtifactResult( Artifact artifact ) 144 { 145 ArtifactResult artifactResult = new ArtifactResult( new ArtifactRequest().setArtifact( artifact ) ); 146 artifactResult.setArtifact( artifact ); 147 return artifactResult; 148 } 149 150 // UTs below 151 152 @Test 153 public void haveMatchingChecksumPass() 154 { 155 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 156 assertThat( artifactResult.isResolved(), equalTo( true ) ); 157 158 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 159 assertThat( artifactResult.isResolved(), equalTo( true ) ); 160 } 161 162 @Test 163 public void haveNoChecksumPass() 164 { 165 ArtifactResult artifactResult = createArtifactResult( artifactWithoutTrustedChecksum ); 166 assertThat( artifactResult.isResolved(), equalTo( true ) ); 167 168 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 169 assertThat( artifactResult.isResolved(), equalTo( true ) ); 170 } 171 172 @Test 173 public void haveNoChecksumFailIfMissingEnabledFail() 174 { 175 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums.failIfMissing", 176 Boolean.TRUE.toString() ); 177 ArtifactResult artifactResult = createArtifactResult( artifactWithoutTrustedChecksum ); 178 assertThat( artifactResult.isResolved(), equalTo( true ) ); 179 180 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 181 assertThat( artifactResult.isResolved(), equalTo( false ) ); 182 assertThat( artifactResult.getExceptions(), not( empty() ) ); 183 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 184 containsString( "Missing from " + TRUSTED_SOURCE_NAME + " trusted" ) ); 185 } 186 187 @Test 188 public void haveMismatchingChecksumFail() 189 { 190 artifactTrustedChecksum = "foobar"; 191 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 192 assertThat( artifactResult.isResolved(), equalTo( true ) ); 193 194 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 195 assertThat( artifactResult.isResolved(), equalTo( false ) ); 196 assertThat( artifactResult.getExceptions(), not( empty() ) ); 197 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 198 containsString( "trusted checksum mismatch" ) ); 199 assertThat( artifactResult.getExceptions().get( 0 ).getMessage(), 200 containsString( TRUSTED_SOURCE_NAME + "=" + artifactTrustedChecksum ) ); 201 } 202 203 @Test 204 public void recordCalculatedChecksum() 205 { 206 AtomicReference<String> recordedChecksum = new AtomicReference<>(null); 207 this.trustedChecksumsWriter = new Writer() 208 { 209 @Override 210 public void addTrustedArtifactChecksums( Artifact artifact, ArtifactRepository artifactRepository, 211 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories, 212 Map<String, String> trustedArtifactChecksums ) 213 { 214 recordedChecksum.set( trustedArtifactChecksums.get( checksumAlgorithmFactory.getName() ) ); 215 } 216 }; 217 session.setConfigProperty( "aether.artifactResolver.postProcessor.trustedChecksums.record", 218 Boolean.TRUE.toString() ); 219 ArtifactResult artifactResult = createArtifactResult( artifactWithTrustedChecksum ); 220 assertThat( artifactResult.isResolved(), equalTo( true ) ); 221 222 subject.postProcess( session, Collections.singletonList( artifactResult ) ); 223 assertThat( artifactResult.isResolved(), equalTo( true ) ); 224 225 String checksum = recordedChecksum.get(); 226 assertThat( checksum, notNullValue() ); 227 assertThat( checksum, equalTo( artifactTrustedChecksum ) ); 228 } 229}