/******************************************************************************* * Copyright (c) 2014, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.team.build.internal.hjplugin.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.util.Locale; import java.util.Map; 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 com.ibm.team.build.internal.hjplugin.BuildResultInfo; import com.ibm.team.build.internal.hjplugin.RTCBuildResultSetupTask; import com.ibm.team.build.internal.hjplugin.RTCChangeLogParser; import com.ibm.team.build.internal.hjplugin.RTCChangeLogSet; import com.ibm.team.build.internal.hjplugin.RTCFacadeFactory.RTCFacadeWrapper; import com.ibm.team.build.internal.hjplugin.RTCLoginInfo; import com.ibm.team.build.internal.hjplugin.tests.utils.AbstractTestCase; import com.ibm.team.build.internal.hjplugin.tests.utils.FileUtils; import com.ibm.team.build.internal.hjplugin.tests.utils.Utils; import hudson.model.TaskListener; import hudson.remoting.RemoteOutputStream; import hudson.util.Secret; import hudson.util.StreamTaskListener; public class RTCBuildTaskIT extends AbstractTestCase { @Rule public JenkinsRule r = new JenkinsRule(); private static final String FAKE_UUID = "_kkmC4NWiEdylmcAI5HeTUQ"; //$NON-NLS-1$ private RTCFacadeWrapper testingFacade; private File sandboxDir; @Before public void setUp() throws Exception { if (Config.DEFAULT.isConfigured()) { testingFacade = Utils.getTestingFacade(); File tempDir = new File(System.getProperty("java.io.tmpdir")); File buildTestDir = new File(tempDir, "HJPluginTests"); sandboxDir = new File(buildTestDir, getUniqueName()); sandboxDir.mkdirs(); sandboxDir.deleteOnExit(); Assert.assertTrue(sandboxDir.exists()); } } @After public void tearDown() throws Exception { // delete the sandbox after Hudson/Jenkins is shutdown if (Config.DEFAULT.isConfigured()) { FileUtils.delete(sandboxDir); } } /** * Tests that BuildResultSetupTask knows when to setup locally * @throws Exception */ @Test public void testLocalInvocation() throws Exception { if (Config.DEFAULT.isConfigured()) { RTCLoginInfo loginInfo = Config.DEFAULT.getLoginInfo(); TaskListener listener = new StreamTaskListener(System.out, null); RTCBuildResultSetupTask task = new RTCBuildResultSetupTask( "Testing " + getUniqueName(), Config.DEFAULT.getToolkit(), loginInfo.getServerUri(), Config.DEFAULT.getUserID(), Secret.fromString(Config.DEFAULT.getPassword()).getEncryptedValue(), loginInfo.getTimeout(), false, null, null, getUniqueName(), listener, true, false, Locale.getDefault()); // using workspace and no build defn means task can run locally (no RTC calls) assertNotNull(task.localInvocation()); task = new RTCBuildResultSetupTask( "Testing " + getUniqueName(), Config.DEFAULT.getToolkit(), loginInfo.getServerUri(), loginInfo.getUserId(), Secret.fromString(loginInfo.getPassword()).getEncryptedValue(), loginInfo.getTimeout(), false, null, FAKE_UUID, getUniqueName(), listener, true, false, Locale.getDefault()); // we have a build result so we have to get info from it - run on slave assertNull(task.localInvocation()); task = new RTCBuildResultSetupTask( "Testing " + getUniqueName(), Config.DEFAULT.getToolkit(), loginInfo.getServerUri(), loginInfo.getUserId(), Secret.fromString(loginInfo.getPassword()).getEncryptedValue(), loginInfo.getTimeout(), true, getUniqueName(), null, getUniqueName(), listener, true, false, Locale.getDefault()); // we have a build definition so need to create a result - run on slave assertNull(task.localInvocation()); } } /** * There are existing detailed tests for RepositoryConnection api called to figure out * changes and add build result contributions. This test is to ensure that the tasks call * those API to start a build initiated but only queued by RTC * @throws Exception */ @Test public void testBuildResultContributionsStartingBuild() throws Exception { // test add snapshot contribution (happens during checkout) // test add workspace contribution (happens during checkout) // test build activity added (happens during checkout) // test workitems associated with build result (during checkout) if (Config.DEFAULT.isConfigured()) { RTCLoginInfo loginInfo = Config.DEFAULT.getLoginInfo(); String baselineSetName = "Snapshot_" + getUniqueName(); String workspaceName = getUniqueName(); String componentName = getUniqueName(); String buildDefinitionId = getUniqueName(); @SuppressWarnings("unchecked") Map<String, String> setupArtifacts = (Map<String, String>) testingFacade .invoke("setupBuildResultContributionsInQueuedBuild", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, String.class, // workspaceName, String.class, // componentName String.class}, // buildDefinitionId loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), workspaceName, componentName, buildDefinitionId); String buildResultUUID = setupArtifacts.get("buildResultItemId"); assertNotNull(buildResultUUID); // make sure we are testing what we think we are if (Config.DEFAULT.isSetUpOnly()) { return; } try { TaskListener listener = new StreamTaskListener(System.out, null); // We have no build result, but we do have a build definition // The task should create a build result and we own its lifecycle RTCBuildResultSetupTask task = new RTCBuildResultSetupTask( "Testing " + getUniqueName(), Config.DEFAULT.getToolkit(), loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), true, buildDefinitionId, buildResultUUID, // no build result getUniqueName(), listener, true, false, Locale.getDefault()); assertNull(task.localInvocation()); BuildResultInfo buildResultInfo = task.invoke(sandboxDir, null); assertTrue(buildResultInfo.ownLifeCycle()); assertEquals(buildResultUUID, buildResultInfo.getBuildResultUUID()); File changeLogFile = new File(sandboxDir, "RTCChangeLogFile"); FileOutputStream changeLog = new FileOutputStream(changeLogFile); RemoteOutputStream remoteChangeLog = new RemoteOutputStream(changeLog); Utils.acceptAndLoad(testingFacade, loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), buildResultInfo.getBuildResultUUID(), null, sandboxDir.getAbsolutePath(), remoteChangeLog, baselineSetName, listener, Locale.getDefault()); // parse the change report and ensure the expected components are reported. RTCChangeLogParser parser = new RTCChangeLogParser(); FileReader changeLogReader = new FileReader(changeLogFile); RTCChangeLogSet result = (RTCChangeLogSet) parser.parse(null, null, changeLogReader); // verify the result Assert.assertNotNull(result.getBaselineSetItemId()); setupArtifacts.put("baselineSetItemId", result.getBaselineSetItemId()); // Verify the build result testingFacade.invoke( "verifyBuildResultContributions", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, Map.class}, // listener loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), setupArtifacts); } finally { // clean up testingFacade.invoke( "tearDown", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, Map.class}, // setupArtifacts loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), setupArtifacts); } } } /** * There are existing detailed tests for RepositoryConnection api called to figure out * changes and add build result contributions. This test is to ensure that the tasks call * those API to setup the build result & do the checkout * @throws Exception */ @Test public void testBuildResultContributions() throws Exception { // test add snapshot contribution (happens during checkout) // test add workspace contribution (happens during checkout) // test build activity added (happens during checkout) // test workitems associated with build result (during checkout) if (Config.DEFAULT.isConfigured()) { RTCLoginInfo loginInfo = Config.DEFAULT.getLoginInfo(); String baselineSetName = getUniqueName("Snapshot"); String workspaceName = getUniqueName("Workspace"); String componentName = getUniqueName("Component"); String buildDefinitionId = getUniqueName("BuildDefinition"); @SuppressWarnings("unchecked") Map<String, String> setupArtifacts = (Map<String, String>) testingFacade .invoke("setupBuildResultContributions", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, String.class, // workspaceName, String.class, // componentName String.class}, // buildDefinitionId loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), workspaceName, componentName, buildDefinitionId); if (Config.DEFAULT.isSetUpOnly()) { return; } try { TaskListener listener = new StreamTaskListener(System.out, null); // We have no build result, but we do have a build definition // The task should create a build result and we own its lifecycle RTCBuildResultSetupTask task = new RTCBuildResultSetupTask( "Testing " + getUniqueName(), Config.DEFAULT.getToolkit(), loginInfo.getServerUri(), loginInfo.getUserId(), Secret.fromString(loginInfo.getPassword()).getEncryptedValue(), loginInfo.getTimeout(), true, buildDefinitionId, null, // no build result getUniqueName(), listener, true, false, Locale.getDefault()); assertNull(task.localInvocation()); BuildResultInfo buildResultInfo = task.invoke(sandboxDir, null); assertTrue(buildResultInfo.ownLifeCycle()); assertNotNull(buildResultInfo.getBuildResultUUID()); // record build result so it gets cleaned up on test end setupArtifacts.put("buildResultItemId", buildResultInfo.getBuildResultUUID()); File changeLogFile = new File(sandboxDir, "RTCChangeLogFile"); FileOutputStream changeLog = new FileOutputStream(changeLogFile); RemoteOutputStream remoteChangeLog = new RemoteOutputStream(changeLog); Utils.acceptAndLoad(testingFacade, loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), buildResultInfo.getBuildResultUUID(), null, sandboxDir.getAbsolutePath(), remoteChangeLog, baselineSetName, listener, Locale.getDefault()); // parse the change report and ensure the expected components are reported. RTCChangeLogParser parser = new RTCChangeLogParser(); FileReader changeLogReader = new FileReader(changeLogFile); RTCChangeLogSet result = (RTCChangeLogSet) parser.parse(null, null, changeLogReader); // verify the result Assert.assertNotNull(result.getBaselineSetItemId()); setupArtifacts.put("baselineSetItemId", result.getBaselineSetItemId()); // Verify the build result testingFacade.invoke( "verifyBuildResultContributions", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, Map.class}, // listener loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), setupArtifacts); } finally { // clean up testingFacade.invoke( "tearDown", new Class[] { String.class, // serverURL, String.class, // userId, String.class, // password, int.class, // timeout, Map.class}, // setupArtifacts loginInfo.getServerUri(), loginInfo.getUserId(), loginInfo.getPassword(), loginInfo.getTimeout(), setupArtifacts); } } } }