All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.marvelution.test.jenkins.HudsonRule Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2012-present Marvelution B.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.marvelution.test.jenkins;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import hudson.model.Job;
import hudson.model.TopLevelItem;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.AuthorizationMatrixProperty;
import hudson.security.Permission;
import hudson.security.ProjectMatrixAuthorizationStrategy;
import hudson.security.csrf.CrumbIssuer;
import hudson.security.csrf.DefaultCrumbIssuer;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.PostMethod;
import org.junit.Ignore;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.HudsonHomeLoader;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.LenientRunnable;
import org.jvnet.hudson.test.recipes.Recipe;

/**
 * {@link TestRule} ported implementation of the {@link HudsonTestCase} to use it with JUnit 4 and later
 *
 * @author Mark Rekveld
 * @since 1.6.0
 */
@Ignore("This is used as a TestRule and not a TestCase")
public class HudsonRule extends HudsonTestCase implements TestRule {

	private final ThreadLocal description = new ThreadLocal<>();
	public static final String ALICE = "alice";
	public static final String BOB = "bob";
	public static final String CHARLIE = "charlie";
	public static final String MARK = "mark";

	@Override
	public Statement apply(final Statement base, final Description description) {
		return new Statement() {
			@Override
			public void evaluate() throws Throwable {
				HudsonRule.this.description.set(description);
				with(new HudsonRuleHomeLoader(description));
				// Setup Hudson
				setUp();
				// Create the default users
				User.get(ALICE, true);
				User.get(BOB, true);
				User.get(CHARLIE, true);
				User.get(MARK, true);
				// so that test code has all the access to the system
				SecurityContextHolder.getContext().setAuthentication(ACL.SYSTEM);
				// apply the dummy security realm with project matrix authz strategy
				hudson.setSecurityRealm(createDummySecurityRealm());
				hudson.setAuthorizationStrategy(new ProjectMatrixAuthorizationStrategy());
				try {
					base.evaluate();
				} finally {
					tearDown();
				}
			}
		};
	}

	@Override
	@SuppressWarnings("unchecked")
	protected void recipe() throws Exception {
		recipeLoadCurrentPlugin();
		// Load method defined recipes
		for (final Annotation annotation : description.get().getAnnotations()) {
			Recipe recipe = annotation.annotationType().getAnnotation(Recipe.class);
			if (recipe != null) {
				final Recipe.Runner runner = recipe.value().newInstance();
				recipes.add(runner);
				tearDowns.add(new LenientRunnable() {
					public void run() throws Exception {
						runner.tearDown(HudsonRule.this, annotation);
					}
				});
				runner.setup(this, annotation);
			}
		}
	}

	public URI getURI() {
		try {
			return getURL().toURI();
		} catch (URISyntaxException | IOException e) {
			throw new IllegalStateException("Cannot get root URI for Hudson instance", e);
		}
	}

	public void useCrumbs(boolean use) {
		hudson.setCrumbIssuer(use ? new DefaultCrumbIssuer(true) : null);
	}

	public void addAuthorization(Permission permission, String... users) throws Exception {
		ProjectMatrixAuthorizationStrategy authorizationStrategy = (ProjectMatrixAuthorizationStrategy) hudson.getAuthorizationStrategy();
		for (String user : users) {
			authorizationStrategy.add(permission, user);
		}
	}

	public void addJobAuthorization(Job job, Permission permission, String... users) throws Exception {
		addAuthorization(Permission.READ, users);
		Map> permissions = new HashMap<>();
		AuthorizationMatrixProperty authorizationMatrix = job.getProperty(AuthorizationMatrixProperty.class);
		if (authorizationMatrix != null) {
			permissions.putAll(authorizationMatrix.getGrantedPermissions());
			job.removeProperty(authorizationMatrix);
		}
		if (permissions.containsKey(permission)) {
			permissions.get(permission).addAll(Arrays.asList(users));
		} else {
			permissions.put(permission, new HashSet<>(Arrays.asList(users)));
		}
		job.addProperty(new AuthorizationMatrixProperty(permissions));
	}

	public  T createProject(Class type, String name) throws Exception {
		return hudson.createProject(type, name);
	}

	public void addBasicAuthentication(HttpClient httpClient, String username) {
		addBasicAuthentication(httpClient, username, username);
	}

	public void addBasicAuthentication(HttpClient httpClient, String username, String password) {
		httpClient.getParams().setAuthenticationPreemptive(true);
		httpClient.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
	}

	public void addCrumbPostHeader(HttpMethod httpMethod) {
		if (httpMethod instanceof PostMethod) {
			CrumbIssuer crumbIssuer = hudson.getCrumbIssuer();
			httpMethod.addRequestHeader(crumbIssuer.getCrumbRequestField(), crumbIssuer.getCrumb());
		}
	}

	private static class HudsonRuleHomeLoader implements HudsonHomeLoader {

		private final Description description;

		private HudsonRuleHomeLoader(Description description) {
			this.description = description;
		}

		@Override
		public File allocate() throws Exception {
			Path path = Paths.get(System.getProperty("hudson.test.home.base.directory"), description.getClassName(),
			                      description.getMethodName());
			Files.deleteIfExists(path);
			return Files.createDirectories(path).toFile();
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy