/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jenkins.install;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.mockito.Mockito;
import hudson.Main;
import hudson.model.UpdateCenter;
import hudson.model.UpdateCenter.DownloadJob.Failure;
import hudson.model.UpdateCenter.DownloadJob.InstallationStatus;
import hudson.model.UpdateCenter.DownloadJob.Installing;
import hudson.model.UpdateCenter.DownloadJob.Pending;
import hudson.model.UpdateCenter.DownloadJob.Success;
import hudson.model.UpdateCenter.UpdateCenterJob;
import hudson.model.UpdateSite;
import jenkins.model.Jenkins;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
* Test
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class InstallUtilTest {
@Rule
public JenkinsRule jenkinsRule = new JenkinsRule();
@Before
public void setup() {
// JenkinsRule will have created the last exec file (indirectly),
// so remove it so we can fake the tests.
InstallUtil.getLastExecVersionFile().delete();
// Disable the unit test flag.
Main.isUnitTest = false;
}
@After
public void tearDown() {
// Reset the unit test flag back to its default.
Main.isUnitTest = true;
}
/**
* Test jenkins startup sequences and the changes to the startup type..
*/
@Test
public void test_typeTransitions() {
// A new test instance sets up security first
Assert.assertEquals(InstallState.INITIAL_SECURITY_SETUP, InstallUtil.getNextInstallState(InstallState.UNKNOWN));
// And proceeds to the new state
Assert.assertEquals(InstallState.NEW, InstallUtil.getNextInstallState(InstallState.INITIAL_SECURITY_SETUP));
// Save the last exec version. This will only be done by Jenkins after one of:
// 1. A successful run of the install wizard.
// 2. A success upgrade.
// 3. A successful restart.
InstallUtil.saveLastExecVersion();
// Fudge things a little now, pretending there's a restart...
// Now if we ask what is the InstallState, we should be told it's a RESTART because
// the install wizard is complete and the version matches the currently executing
// Jenkins version.
Assert.assertEquals(InstallState.RESTART, InstallUtil.getNextInstallState(InstallState.UNKNOWN));
// Fudge things again, changing the stored version to something old, faking an upgrade...
InstallUtil.saveLastExecVersion("1.584");
Assert.assertEquals(InstallState.UPGRADE, InstallUtil.getNextInstallState(InstallState.UNKNOWN));
// Fudge things yet again, changing the stored version to something very very new, faking a downgrade...
InstallUtil.saveLastExecVersion("1000.0");
Assert.assertEquals(InstallState.DOWNGRADE, InstallUtil.getNextInstallState(InstallState.UNKNOWN));
}
/**
* Test jenkins startup sequences and the changes to the startup type..
*/
@Test
public void test_getLastExecVersion() throws Exception {
// Delete the config file, forcing getLastExecVersion to return
// the default/unset version value.
InstallUtil.getConfigFile().delete();
Assert.assertEquals("1.0", InstallUtil.getLastExecVersion());
// Set the version to some stupid value and check again. This time,
// getLastExecVersion should read it from the file.
setStoredVersion("9.123");
Assert.assertEquals("9.123", InstallUtil.getLastExecVersion());
}
private void setStoredVersion(String version) throws Exception {
Field versionField = Jenkins.class.getDeclaredField("version");
versionField.setAccessible(true);
versionField.set(jenkinsRule.jenkins, version);
Assert.assertEquals(version, Jenkins.getStoredVersion().toString());
// Force a save of the config.xml
jenkinsRule.jenkins.save();
}
/**
* Validate proper statuses are persisted and install status is cleared when invoking appropriate methods on {@link InstallUtil}
*/
@Test
public void testSaveAndRestoreInstallingPlugins() throws Exception {
final List<UpdateCenterJob> updates = new ArrayList<>();
final Map<String,String> nameMap = new HashMap<>();
new UpdateCenter() { // inner classes...
{
new UpdateSite("foo", "http://omg.org") {
{
for(String name : Arrays.asList("pending-plug:Pending", "installing-plug:Installing", "failure-plug:Failure", "success-plug:Success")) {
String statusType = name.split(":")[1];
name = name.split(":")[0];
InstallationStatus status;
if("Success".equals(statusType)) {
status = Mockito.mock(Success.class);
}
else if("Failure".equals(statusType)) {
status = Mockito.mock(Failure.class);
}
else if("Installing".equals(statusType)) {
status = Mockito.mock(Installing.class);
}
else {
status = Mockito.mock(Pending.class);
}
nameMap.put(statusType, status.getClass().getSimpleName());
JSONObject json = new JSONObject();
json.put("name", name);
json.put("version", "1.1");
json.put("url", "http://google.com");
json.put("dependencies", new JSONArray());
Plugin p = new Plugin(getId(), json);
InstallationJob job = new InstallationJob(p, null, null, false);
job.status = status;
job.setCorrelationId(UUID.randomUUID()); // this indicates the plugin was 'directly selected'
updates.add(job);
}
}
};
}
};
InstallUtil.persistInstallStatus(updates);
Map<String,String> persisted = InstallUtil.getPersistedInstallStatus();
Assert.assertEquals(nameMap.get("Pending"), persisted.get("pending-plug"));
Assert.assertEquals("Pending", persisted.get("installing-plug")); // only marked as success/fail after successful install
Assert.assertEquals(nameMap.get("Failure"), persisted.get("failure-plug"));
Assert.assertEquals(nameMap.get("Success"), persisted.get("success-plug"));
InstallUtil.clearInstallStatus();
persisted = InstallUtil.getPersistedInstallStatus();
Assert.assertNull(persisted); // should be deleted
}
}