package net.ossindex.gradle.audit; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import net.ossindex.gradle.AuditExtensions; import net.ossindex.gradle.OssIndexPlugin; import net.ossindex.gradle.input.ArtifactGatherer; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.plugins.ExtensionContainer; import org.junit.Test; import static org.gradle.internal.impldep.org.junit.Assert.assertEquals; import static org.gradle.internal.impldep.org.testng.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * A series of tests that simulate the operation of gradle and ensure that appropriate proxy arguments are * passed to the DependencyAuditor. */ public class ProxyTests { private static final String PROXY_HOST = "example.com"; private static final Integer PROXY_PORT = 8080; private static final String PROXY_USER = "username"; private static final String PROXY_PASS = "password"; private static final String NON_PROXY_HOSTS = "ossindex.net|ossindex.sonatype.org"; /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. * If the dependency auditor receives proxy information it is passed directly to the OSS Index request * library. */ @Test public void noProxyTest() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Project project = mockProject(); OssIndexPlugin plugin = new OssIndexPlugin(); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory).getDependencyAuditor(null, Collections.EMPTY_SET, Collections.EMPTY_LIST); } /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. */ @Test public void settingsProxyIT() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException { Project project = mockProject(); AuditExtensions settings = new AuditExtensions(project); settings.proxyScheme = "http"; settings.proxyHost = PROXY_HOST; settings.proxyPort = PROXY_PORT; settings.proxyUser = PROXY_USER; settings.proxyPassword = PROXY_PASS; settings.nonProxyHosts = null; OssIndexPlugin plugin = new OssIndexPlugin(); Field field = OssIndexPlugin.class.getDeclaredField("settings"); try { field.setAccessible(true); field.set(plugin, settings); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory) .getDependencyAuditor(null, Collections.EMPTY_SET, Collections.singletonList(getExpectedProxy("http"))); } finally { field.set(plugin, null); } } /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. */ @Test public void httpLocalProxyTest() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { Project project = mockProject(); // Mock the proxy being provided as project properties mockLocalProxy(project, "http"); OssIndexPlugin plugin = new OssIndexPlugin(); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory).getDependencyAuditor(null, Collections.EMPTY_SET, Collections.singletonList(getExpectedProxy("http"))); } /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. */ @Test public void httpsLocalProxyTest() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Project project = mockProject(); // Mock the proxy being provided as project properties mockLocalProxy(project, "https"); OssIndexPlugin plugin = new OssIndexPlugin(); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory).getDependencyAuditor(null, Collections.EMPTY_SET, Collections.singletonList(getExpectedProxy("https"))); } /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. */ @Test public void httpSystemProxyTest() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { Project project = mockProject(); // Mock the proxy being provided as project properties mockSystemProxy(project, "http"); OssIndexPlugin plugin = new OssIndexPlugin(); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory).getDependencyAuditor(null, Collections.EMPTY_SET, Collections.singletonList(getExpectedProxy("http"))); } /** * Ensure that OssIndexPlugin properly assembles the proxy argument and passes it to the DependencyAuditor. */ @Test public void httpsSystemProxyTest() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Project project = mockProject(); // Mock the proxy being provided as project properties mockSystemProxy(project, "https"); OssIndexPlugin plugin = new OssIndexPlugin(); AuditorFactory factory = mockAuditorFactory(); plugin.setAuditorFactory(factory); // Simulate the process the gradle runs runGradleSimulation(project, plugin); verify(factory).getDependencyAuditor(null, Collections.EMPTY_SET, Collections.singletonList(getExpectedProxy("https"))); } /** * Mock the factory used by the auditor. The factory was specifically created to simplify unit tests. The factory * allows the assembly of: * * - The artifact gatherer. This is normally provided by gradle, but needs mocking for testing purposes. * - The dependency auditor. For normal usage this is directly instantiated. */ private AuditorFactory mockAuditorFactory() { AuditorFactory factory = mock(AuditorFactory.class); ArtifactGatherer gatherer = mock(ArtifactGatherer.class); when(gatherer.gatherResolvedArtifacts(any())).thenReturn(Collections.EMPTY_SET); when(factory.getGatherer()).thenReturn(gatherer); DependencyAuditor auditor = mock(DependencyAuditor.class); when(factory.getDependencyAuditor(eq(null), any(), any())).thenReturn(auditor); return factory; } /** * Assemble the gradle project with appropriate task. */ private Project mockProject() { Project project = mock(Project.class); ExtensionContainer extension = mock(ExtensionContainer.class); when(project.getExtensions()).thenReturn(extension); when(project.getDisplayName()).thenReturn("Mock Mock"); Task audit = mock(Task.class); when(audit.getProject()).thenReturn(project); when(project.task("audit")).thenReturn(audit); return project; } /** * Mock the project properties for a specified proxy */ private void mockLocalProxy(final Project project, final String scheme) { when(project.hasProperty(scheme + ".proxyHost")).thenReturn(true); when(project.findProperty(scheme + ".proxyHost")).thenReturn(PROXY_HOST); when(project.findProperty(scheme + ".proxyPort")).thenReturn(PROXY_PORT.toString()); when(project.findProperty(scheme + ".proxyUser")).thenReturn(PROXY_USER); when(project.findProperty(scheme + ".proxyPassword")).thenReturn(PROXY_PASS); when(project.findProperty(scheme + ".nonProxyHosts")).thenReturn(null); } /** * Mock the project properties for a specified proxy */ private void mockSystemProxy(final Project project, final String scheme) { when(project.hasProperty("systemProp." + scheme + ".proxyHost")).thenReturn(true); when(project.findProperty("systemProp." + scheme + ".proxyHost")).thenReturn(PROXY_HOST); when(project.findProperty("systemProp." + scheme + ".proxyPort")).thenReturn(PROXY_PORT.toString()); when(project.findProperty("systemProp." + scheme + ".proxyUser")).thenReturn(PROXY_USER); when(project.findProperty("systemProp." + scheme + ".proxyPassword")).thenReturn(PROXY_PASS); when(project.findProperty("systemProp." + scheme + ".nonProxyHosts")).thenReturn(null); } /** * The proxy expected as part of the test */ private Proxy getExpectedProxy(final String scheme) { Proxy proxy = new Proxy(); proxy.setHost(PROXY_HOST); proxy.setPort(PROXY_PORT); proxy.setUser(PROXY_USER); proxy.setPassword(PROXY_PASS); proxy.setNonProxyHosts(null); return proxy; } /** * Simulate gradle operations * * This is a terrible hack that shortcuts the internal workings of gradle to allow some simple tests to work */ private void runGradleSimulation(final Project project, final OssIndexPlugin plugin) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { plugin.apply(project); Method method = OssIndexPlugin.class.getDeclaredMethod("doAudit", Task.class); method.setAccessible(true); method.invoke(plugin, project.task("audit")); } }