package io.jenkins.tools.pluginmanager.cli; import io.jenkins.tools.pluginmanager.config.Config; import io.jenkins.tools.pluginmanager.config.PluginInputException; import io.jenkins.tools.pluginmanager.config.Settings; import io.jenkins.tools.pluginmanager.impl.Plugin; import io.jenkins.tools.pluginmanager.impl.PluginDependencyStrategyException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.whenNew; import static org.mockito.Mockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({CliOptions.class, System.class}) public class CliOptionsTest { private CliOptions options; private CmdLineParser parser; List<Plugin> txtRequestedPlugins; private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); private final PrintStream originalOut = System.out; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Before public void createParser() throws CmdLineException { options = new CliOptions(); parser = new CmdLineParser(options); //corresponds to plugins in plugin.txt txtRequestedPlugins = new ArrayList<>(); txtRequestedPlugins.add(new Plugin("google-api-client-plugin", "latest", "https://updates.jenkins.io/latest/google-api-client-plugin.hpi", null)); txtRequestedPlugins.add(new Plugin("git", "latest", null, null)); txtRequestedPlugins.add(new Plugin("job-import-plugin", "2.1", null, null)); txtRequestedPlugins.add(new Plugin("docker", "latest", null, null)); txtRequestedPlugins.add(new Plugin("cloudbees-bitbucket-branch-source", "2.4.4", null, null)); txtRequestedPlugins.add(new Plugin("script-security", "latest", "http://ftp-chi.osuosl.org/pub/jenkins/plugins/script-security/1.56/script-security.hpi", null)); txtRequestedPlugins.add(new Plugin("workflow-step-api", "2.19-rc289.d09828a05a74", null, "org.jenkins-ci.plugins.workflow")); txtRequestedPlugins.add(new Plugin("matrix-project", "latest", null, null)); txtRequestedPlugins.add(new Plugin("junit", "experimental", null, null)); txtRequestedPlugins.add(new Plugin("credentials", "2.2.0", "http://ftp-chi.osuosl.org/pub/jenkins/plugins/credentials/2.2.0/credentials.hpi", null)); txtRequestedPlugins.add(new Plugin("blueocean", "latest", null, null)); System.setOut(new PrintStream(outContent)); } @Test public void setupDefaultsTest() throws CmdLineException { parser.parseArgument(); mockStatic(System.class); when(System.getenv("JENKINS_UC")).thenReturn(""); when(System.getenv("JENKINS_UC_EXPERIMENTAL")).thenReturn(""); when(System.getenv("JENKINS_INCREMENTALS_REPO_MIRROR")).thenReturn(""); when(System.getenv("JENKINS_PLUGIN_INFO")).thenReturn(""); Config cfg = options.setup(); assertEquals(Settings.DEFAULT_PLUGIN_DIR_LOCATION, cfg.getPluginDir().toString()); assertEquals(Settings.DEFAULT_WAR, cfg.getJenkinsWar()); assertEquals(false, cfg.isShowAllWarnings()); assertEquals(false, cfg.isShowWarnings()); assertEquals(Settings.DEFAULT_UPDATE_CENTER_LOCATION, cfg.getJenkinsUc().toString()); assertEquals(Settings.DEFAULT_EXPERIMENTAL_UPDATE_CENTER_LOCATION, cfg.getJenkinsUcExperimental().toString()); assertEquals(Settings.DEFAULT_INCREMENTALS_REPO_MIRROR_LOCATION, cfg.getJenkinsIncrementalsRepoMirror().toString()); assertEquals(Settings.DEFAULT_PLUGIN_INFO_LOCATION, cfg.getJenkinsPluginInfo().toString()); } @Test public void setupAliasTest() throws CmdLineException, IOException, URISyntaxException { File pluginTxtFile = new File(this.getClass().getResource("/emptyplugins.txt").toURI()); File jenkinsWar = new File(this.getClass().getResource("/jenkinstest.war").toURI()); File pluginDir = temporaryFolder.newFolder("plugins"); parser.parseArgument("-f", pluginTxtFile.toString(), "-d", pluginDir.toString(), "-w", jenkinsWar.toString(), "-p", "display-url-api::https://updates.jenkins.io/download/plugins/display-url-api/1.0/display-url-api.hpi"); Plugin displayUrlPlugin = new Plugin("display-url-api", "latest", "https://updates.jenkins.io/download/plugins/display-url-api/1.0/display-url-api.hpi", null); Config cfg = options.setup(); assertEquals(pluginDir, cfg.getPluginDir()); assertEquals(jenkinsWar.toString(), cfg.getJenkinsWar()); assertEquals(1, cfg.getPlugins().size()); assertEquals(displayUrlPlugin.toString(), cfg.getPlugins().get(0).toString()); } @Test public void setupPluginsTest() throws CmdLineException, IOException, URISyntaxException { File pluginTxtFile = new File(this.getClass().getResource("/plugins.txt").toURI()); File pluginFile = temporaryFolder.newFile("plugins.txt"); FileUtils.copyFile(pluginTxtFile, pluginFile); parser.parseArgument("--plugin-file", pluginFile.toString(), "--plugins", "ssh-slaves:1.10 mailer cobertura:experimental"); List<Plugin> requestedPlugins = new ArrayList<>(txtRequestedPlugins); requestedPlugins.add(new Plugin("ssh-slaves", "1.10", null, null)); requestedPlugins.add(new Plugin("mailer", "latest", null, null)); requestedPlugins.add(new Plugin("cobertura", "experimental", null, null)); Config cfg = options.setup(); assertEquals(requestedPlugins.size(), cfg.getPlugins().size()); List<String> cfgPluginInfo = new ArrayList<>(); List<String> requestedPluginInfo = new ArrayList<>(); for (Plugin p : cfg.getPlugins()) { cfgPluginInfo.add(p.toString()); } for (Plugin p : requestedPlugins) { requestedPluginInfo.add(p.toString()); } Collections.sort(cfgPluginInfo); Collections.sort(requestedPluginInfo); assertEquals(requestedPluginInfo, cfgPluginInfo); } @Test public void setupPluginsTest2() throws CmdLineException, IOException, URISyntaxException { File pluginTxtFile = new File(this.getClass().getResource("/plugins.yaml").toURI()); File pluginFile = temporaryFolder.newFile("plugins.yaml"); FileUtils.copyFile(pluginTxtFile, pluginFile); parser.parseArgument("--plugin-file", pluginFile.toString(), "--plugins", "ssh-slaves:1.10 mailer cobertura:experimental"); List<Plugin> requestedPlugins = new ArrayList<>(txtRequestedPlugins); requestedPlugins.add(new Plugin("ssh-slaves", "1.10", null, null)); requestedPlugins.add(new Plugin("mailer", "latest", null, null)); requestedPlugins.add(new Plugin("cobertura", "experimental", null, null)); Config cfg = options.setup(); assertEquals(requestedPlugins.size(), cfg.getPlugins().size()); List<String> cfgPluginInfo = new ArrayList<>(); List<String> requestedPluginInfo = new ArrayList<>(); for (Plugin p : cfg.getPlugins()) { cfgPluginInfo.add(p.toString()); } for (Plugin p : requestedPlugins) { requestedPluginInfo.add(p.toString()); } Collections.sort(cfgPluginInfo); Collections.sort(requestedPluginInfo); assertEquals(requestedPluginInfo, cfgPluginInfo); } @Test(expected = PluginInputException.class) public void setupPluginsBadExtension() throws CmdLineException, IOException, URISyntaxException { File pluginTxtFile = new File(this.getClass().getResource("/plugins.t").toURI()); File pluginFile = temporaryFolder.newFile("plugins.t"); FileUtils.copyFile(pluginTxtFile, pluginFile); parser.parseArgument("--plugin-file", pluginFile.toString()); Config cfg = options.setup(); } @Test public void setupWarTest() throws CmdLineException { String jenkinsWar = this.getClass().getResource("/jenkinstest.war").toString(); parser.parseArgument("--war", jenkinsWar); Config cfg = options.setup(); assertEquals(jenkinsWar, cfg.getJenkinsWar()); } @Test public void setupPluginDirTest() throws CmdLineException, IOException { String pluginDir = temporaryFolder.newFolder("plugins").toString(); parser.parseArgument("--plugin-download-directory", pluginDir); Config cfg = options.setup(); assertEquals(pluginDir, cfg.getPluginDir().toString()); } @Test public void setupUpdateCenterCliTest() throws CmdLineException { String ucEnvVar = "https://updates.jenkins.io/env"; String experimentalUcEnvVar = "https://updates.jenkins.io/experimental/env"; String incrementalsEnvVar = "https://repo.jenkins-ci.org/incrementals/env"; String pluginInfoEnvVar = "https://updates.jenkins.io/current/plugin-versions/env"; mockStatic(System.class); when(System.getenv("JENKINS_UC")).thenReturn(ucEnvVar); when(System.getenv("JENKINS_UC_EXPERIMENTAL")).thenReturn(experimentalUcEnvVar); when(System.getenv("JENKINS_INCREMENTALS_REPO_MIRROR")).thenReturn(incrementalsEnvVar); when(System.getenv("JENKINS_PLUGIN_INFO")).thenReturn(pluginInfoEnvVar); String ucCli = "https://updates.jenkins.io/cli"; String experiementalCli = "https://updates.jenkins.io/experimental/cli"; String incrementalsCli = "https://repo.jenkins-ci.org/incrementals/cli"; String pluginInfoCli = "https://updates.jenkins.io/current/plugin-versions/cli"; parser.parseArgument("--jenkins-update-center", ucCli, "--jenkins-experimental-update-center", experiementalCli, "--jenkins-incrementals-repo-mirror", incrementalsCli, "--jenkins-plugin-info", pluginInfoCli); Config cfg = options.setup(); // Cli options should override environment variables assertEquals(ucCli, cfg.getJenkinsUc().toString()); assertEquals(experiementalCli, cfg.getJenkinsUcExperimental().toString()); assertEquals(incrementalsCli, cfg.getJenkinsIncrementalsRepoMirror().toString()); assertEquals(pluginInfoCli, cfg.getJenkinsPluginInfo().toString()); } @Test public void setupUpdateCenterEnvVarTest() throws CmdLineException { String ucEnvVar = "https://updates.jenkins.io/env"; String experimentalUcEnvVar = "https://updates.jenkins.io/experimental/env"; String incrementalsEnvVar = "https://repo.jenkins-ci.org/incrementals/env"; String pluginInfoEnvVar = "https://updates.jenkins.io/current/plugin-versions/env"; mockStatic(System.class); when(System.getenv("JENKINS_UC")).thenReturn(ucEnvVar); when(System.getenv("JENKINS_UC_EXPERIMENTAL")).thenReturn(experimentalUcEnvVar); when(System.getenv("JENKINS_INCREMENTALS_REPO_MIRROR")).thenReturn(incrementalsEnvVar); when(System.getenv("JENKINS_PLUGIN_INFO")).thenReturn(pluginInfoEnvVar); Config cfg = options.setup(); assertEquals(ucEnvVar, cfg.getJenkinsUc().toString()); assertEquals(experimentalUcEnvVar, cfg.getJenkinsUcExperimental().toString()); assertEquals(incrementalsEnvVar, cfg.getJenkinsIncrementalsRepoMirror().toString()); assertEquals(pluginInfoEnvVar, cfg.getJenkinsPluginInfo().toString()); } @Test public void setupSecurityWarningsTest() throws CmdLineException { parser.parseArgument("--view-all-security-warnings", "--view-security-warnings"); Config cfg = options.setup(); assertEquals(true, cfg.isShowAllWarnings()); assertEquals(true, cfg.isShowWarnings()); } @Test public void showVersionTest() throws Exception { parser.parseArgument("--version"); String version = "testVersion"; Properties properties = mock(Properties.class); whenNew(Properties.class).withNoArguments().thenReturn(properties); when(properties.getProperty(any(String.class))).thenReturn(version); options.showVersion(); assertEquals(version, outContent.toString().trim()); ByteArrayOutputStream aliasVersionOut = new ByteArrayOutputStream(); System.setOut(new PrintStream(aliasVersionOut)); parser.parseArgument("-v"); options.showVersion(); assertEquals(version, aliasVersionOut.toString().trim()); } @Test(expected = VersionNotFoundException.class) public void showVersionErrorTest() throws CmdLineException { ByteArrayOutputStream nullPropertiesOut = new ByteArrayOutputStream(); System.setOut(new PrintStream(nullPropertiesOut)); CliOptions cliOptionsSpy = spy(options); parser.parseArgument("--version"); doReturn(null).when(cliOptionsSpy).getPropertiesInputStream(any(String.class)); cliOptionsSpy.showVersion(); } @Test public void noDownloadTest() throws CmdLineException { parser.parseArgument("--no-download"); Config cfg = options.setup(); assertEquals(false, cfg.doDownload()); } @Test public void downloadTest() throws CmdLineException { parser.parseArgument(); Config cfg = options.setup(); assertEquals(true, cfg.doDownload()); } @Test public void useLatestSpecifiedTest() throws CmdLineException { parser.parseArgument("--latest-specified"); Config cfg = options.setup(); assertEquals(true, cfg.isUseLatestSpecified()); } @Test public void useNotLatestSpecifiedTest() throws CmdLineException { parser.parseArgument(); Config cfg = options.setup(); assertEquals(false, cfg.isUseLatestSpecified()); } @Test public void useLatestTest() throws CmdLineException { parser.parseArgument("--latest"); Config cfg = options.setup(); assertEquals(true, cfg.isUseLatestAll()); } @Test public void useNotLatestTest() throws CmdLineException { parser.parseArgument(); Config cfg = options.setup(); assertEquals(false, cfg.isUseLatestAll()); } @Test (expected = PluginDependencyStrategyException.class) public void useLatestSpecifiedAndLatestAllTest() throws CmdLineException { parser.parseArgument("--latest", "--latest-specified"); Config cfg = options.setup(); } @After public void restoreStream() { System.setOut(originalOut); } }