View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.maven;
6   
7   import com.google.common.base.Joiner;
8   import com.qulice.spi.Environment;
9   import com.qulice.spi.ValidationException;
10  import java.util.Collection;
11  import java.util.Collections;
12  import java.util.HashSet;
13  import java.util.Set;
14  import org.apache.maven.artifact.Artifact;
15  import org.apache.maven.plugin.testing.stubs.ArtifactStub;
16  import org.apache.maven.project.MavenProject;
17  import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
18  import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
19  import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  
23  /**
24   * Test case for {@link DependenciesValidator} class.
25   *
26   * @since 0.3
27   */
28  final class DependenciesValidatorTest {
29      /**
30       * Plexus role.
31       */
32      private static final String ROLE =
33          ProjectDependencyAnalyzer.class.getName();
34  
35      /**
36       * Plexus hint.
37       */
38      private static final String HINT = "default";
39  
40      /**
41       * Compile scope.
42       */
43      private static final String SCOPE = "compile";
44  
45      /**
46       * Jar type.
47       */
48      private static final String TYPE = "jar";
49  
50      /**
51       * DependencyValidator can pass on when no violations are found.
52       *
53       * @throws Exception If something wrong happens inside
54       */
55      @Test
56      void passesIfNoDependencyProblemsFound() throws Exception {
57          final ProjectDependencyAnalysis analysis =
58              new ProjectDependencyAnalysis();
59          final ProjectDependencyAnalyzer analyzer =
60              new FakeProjectDependencyAnalyzer(analysis);
61          final MavenEnvironment env = new MavenEnvironmentMocker().inPlexus(
62              DependenciesValidatorTest.ROLE,
63              DependenciesValidatorTest.HINT,
64              analyzer
65          ).mock();
66          new DependenciesValidator().validate(env);
67      }
68  
69      /**
70       * DependencyValidator can catch dependency problems.
71       *
72       * @throws Exception If something wrong happens inside
73       */
74      @Test
75      void catchesDependencyProblemsAndThrowsException() throws Exception {
76          final ArtifactStub artifact = new ArtifactStub();
77          artifact.setGroupId("group");
78          artifact.setArtifactId("artifact");
79          artifact.setScope(DependenciesValidatorTest.SCOPE);
80          artifact.setVersion("2.3.4");
81          artifact.setType(DependenciesValidatorTest.TYPE);
82          final Set<Artifact> unused = new HashSet<>();
83          unused.add(artifact);
84          final ProjectDependencyAnalysis analysis =
85              new ProjectDependencyAnalysis(
86                  Collections.emptySet(), unused, Collections.emptySet()
87              );
88          final ProjectDependencyAnalyzer analyzer =
89              new FakeProjectDependencyAnalyzer(analysis);
90          final MavenEnvironment env = new MavenEnvironmentMocker().inPlexus(
91              DependenciesValidatorTest.ROLE,
92              DependenciesValidatorTest.HINT,
93              analyzer
94          ).mock();
95          Assertions.assertThrows(
96              ValidationException.class,
97              () -> new DependenciesValidator().validate(env)
98          );
99      }
100 
101     /**
102      * DependencyValidator can ignore runtime scope dependencies.
103      *
104      * @throws Exception If something wrong happens inside
105      */
106     @Test
107     void ignoresRuntimeScope() throws Exception {
108         final ArtifactStub artifact = new ArtifactStub();
109         artifact.setGroupId("group");
110         artifact.setArtifactId("artifact");
111         artifact.setScope("runtime");
112         artifact.setVersion("2.3.4");
113         artifact.setType(DependenciesValidatorTest.TYPE);
114         final Set<Artifact> unused = new HashSet<>();
115         unused.add(artifact);
116         final ProjectDependencyAnalysis analysis =
117             new ProjectDependencyAnalysis(
118                 Collections.emptySet(), Collections.emptySet(), unused
119             );
120         final ProjectDependencyAnalyzer analyzer =
121             new FakeProjectDependencyAnalyzer(analysis);
122         final MavenEnvironment env = new MavenEnvironmentMocker().inPlexus(
123             DependenciesValidatorTest.ROLE,
124             DependenciesValidatorTest.HINT,
125             analyzer
126         ).mock();
127         new DependenciesValidator().validate(env);
128     }
129 
130     /**
131      * DependencyValidator can exclude used undeclared dependencies.
132      *
133      * @throws Exception If something wrong happens inside
134      */
135     @Test
136     void excludesUsedUndeclaredDependencies() throws Exception {
137         final Set<Artifact> used = new HashSet<>();
138         final ArtifactStub artifact = new ArtifactStub();
139         artifact.setGroupId("group");
140         artifact.setArtifactId("artifact");
141         artifact.setScope(DependenciesValidatorTest.SCOPE);
142         artifact.setVersion("2.3.4");
143         artifact.setType(DependenciesValidatorTest.TYPE);
144         used.add(artifact);
145         final ProjectDependencyAnalysis analysis =
146             new ProjectDependencyAnalysis(
147                 Collections.emptySet(), used, Collections.emptySet()
148             );
149         final ProjectDependencyAnalyzer analyzer =
150             new FakeProjectDependencyAnalyzer(analysis);
151         final MavenEnvironment env = new MavenEnvironmentMocker().inPlexus(
152             DependenciesValidatorTest.ROLE,
153             DependenciesValidatorTest.HINT,
154             analyzer
155         ).mock();
156         new DependenciesValidator().validate(
157             new MavenEnvironment.Wrap(
158                 new Environment.Mock().withExcludes(
159                     Joiner.on(':').join(
160                         artifact.getGroupId(), artifact.getArtifactId()
161                     )
162                 ), env
163             )
164         );
165     }
166 
167     /**
168      * DependencyValidator can exclude unused declared dependencies.
169      *
170      * @throws Exception If something wrong happens inside
171      */
172     @Test
173     void excludesUnusedDeclaredDependencies() throws Exception {
174         final Set<Artifact> unused = new HashSet<>();
175         final ArtifactStub artifact = new ArtifactStub();
176         artifact.setGroupId("othergroup");
177         artifact.setArtifactId("otherartifact");
178         artifact.setScope(DependenciesValidatorTest.SCOPE);
179         artifact.setVersion("1.2.3");
180         artifact.setType(DependenciesValidatorTest.TYPE);
181         unused.add(artifact);
182         final ProjectDependencyAnalysis analysis =
183             new ProjectDependencyAnalysis(
184                 Collections.emptySet(), Collections.emptySet(), unused
185             );
186         final ProjectDependencyAnalyzer analyzer =
187             new FakeProjectDependencyAnalyzer(analysis);
188         final MavenEnvironment env = new MavenEnvironmentMocker().inPlexus(
189             DependenciesValidatorTest.ROLE,
190             DependenciesValidatorTest.HINT,
191             analyzer
192         ).mock();
193         new DependenciesValidator().validate(
194             new MavenEnvironment.Wrap(
195                 new Environment.Mock().withExcludes(
196                     Joiner.on(':').join(
197                         artifact.getGroupId(), artifact.getArtifactId()
198                     )
199                 ), env
200             )
201         );
202     }
203 
204     /**
205      * FakeProjectDependencyAnalyzer.
206      *
207      * A mock to ProjectDependencyAnalyzer.
208      *
209      * @since 0.24.1
210      */
211     private static final class FakeProjectDependencyAnalyzer
212         implements ProjectDependencyAnalyzer {
213         /**
214          * ProjectDependencyAnalysis.
215          */
216         private final ProjectDependencyAnalysis analysis;
217 
218         FakeProjectDependencyAnalyzer(
219             final ProjectDependencyAnalysis alysis
220         ) {
221             this.analysis = alysis;
222         }
223 
224         @Override
225         public ProjectDependencyAnalysis analyze(
226             final MavenProject project,
227             final Collection<String> collection
228         ) throws ProjectDependencyAnalyzerException {
229             return this.analysis;
230         }
231     }
232 }