hudson.tasks.junit.TestObject.java Source code

Java tutorial

Introduction

Here is the source code for hudson.tasks.junit.TestObject.java

Source

/*
 * The MIT License
 * 
 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts
 * 
 * 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 hudson.tasks.junit;

import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractModelObject;
import hudson.model.Action;
import hudson.model.Api;
import hudson.model.Build;
import hudson.model.Item;
import hudson.model.Messages;
import hudson.model.Result;
import hudson.model.Run;
import hudson.util.ChartUtil;
import hudson.util.ColorPalette;
import hudson.util.DataSetBuilder;
import hudson.util.ShiftedCategoryAxis;
import hudson.util.StackedAreaRenderer2;

import java.awt.Color;
import java.awt.Paint;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import javax.servlet.ServletException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.StackedAreaRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.ui.RectangleInsets;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.ExportedBean;

/**
 * Base class for all test result objects.
 * 
 * @author Kohsuke Kawaguchi
 */
@ExportedBean
public abstract class TestObject extends AbstractModelObject implements Serializable {
    private volatile transient String id;

    public AbstractBuild<?, ?> getOwner() {
        return getParent().getOwner();
    }

    /**
     * Reverse pointer of {@link TabulatedResult#getChildren()}.
     */
    public abstract TestObject getParent();

    public String getId() {
        if (id == null) {
            id = getParent().getId() + "/" + getSafeName();
        }
        return id;
    }

    /**
     * Returns url relative to TestResult
     */
    public String getUrl() {
        return getId();
    }

    public TestResult getTestResult() {
        return getParent().getTestResult();
    }

    public TestResultAction getTestResultAction() {
        return getOwner().getAction(TestResultAction.class);
    }

    public List<TestAction> getTestActions() {
        return getTestResultAction().getActions(this);
    }

    public <T> T getTestAction(Class<T> klazz) {
        for (TestAction action : getTestActions()) {
            if (klazz.isAssignableFrom(action.getClass())) {
                return klazz.cast(action);
            }
        }
        return null;
    }

    /**
     * Gets the counter part of this {@link TestObject} in the previous run.
     * 
     * @return null if no such counter part exists.
     */
    public abstract TestObject getPreviousResult();

    public abstract TestObject getResultInBuild(AbstractBuild<?, ?> build);

    /**
     * Time took to run this test. In seconds.
     */
    public abstract float getDuration();

    /**
     * Returns the string representation of the {@link #getDuration()}, in a
     * human readable format.
     */
    public String getDurationString() {
        return Util.getTimeSpanString((long) (getDuration() * 1000));
    }

    public String getDescription() {
        return getTestResultAction().getDescription(this);
    }

    public void setDescription(String description) {
        getTestResultAction().setDescription(this, description);
    }

    /**
     * Exposes this object through the remote API.
     */
    public Api getApi() {
        return new Api(this);
    }

    /**
     * Gets the name of this object.
     */
    public/* abstract */String getName() {
        return "";
    }

    /**
     * Gets the version of {@link #getName()} that's URL-safe.
     */
    public String getSafeName() {
        return safe(getName());
    }

    public String getSearchUrl() {
        return getSafeName();
    }

    /**
     * #2988: uniquifies a {@link #getSafeName} amongst children of the parent.
     */
    protected final synchronized String uniquifyName(Collection<? extends TestObject> siblings, String base) {
        String uniquified = base;
        int sequence = 1;
        for (TestObject sibling : siblings) {
            if (sibling != this && uniquified.equals(UNIQUIFIED_NAMES.get(sibling))) {
                uniquified = base + '_' + ++sequence;
            }
        }
        UNIQUIFIED_NAMES.put(this, uniquified);
        return uniquified;
    }

    private static final Map<TestObject, String> UNIQUIFIED_NAMES = new WeakHashMap<TestObject, String>();

    /**
     * Replaces URL-unsafe characters.
     */
    protected static String safe(String s) {
        // 3 replace calls is still 2-3x faster than a regex replaceAll
        return s.replace('/', '_').replace('\\', '_').replace(':', '_');
    }

    /**
     * Gets the total number of passed tests.
     */
    public abstract int getPassCount();

    /**
     * Gets the total number of failed tests.
     */
    public abstract int getFailCount();

    /**
     * Gets the total number of skipped tests.
     */
    public abstract int getSkipCount();

    /**
     * Gets the total number of tests.
     */
    public final int getTotalCount() {
        return getPassCount() + getFailCount() + getSkipCount();
    }

    public History getHistory() {
        return new History(this);
    }

    public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) {
        for (Action a : getTestActions()) {
            if (a == null)
                continue; // be defensive
            String urlName = a.getUrlName();
            if (urlName == null)
                continue;
            if (urlName.equals(token))
                return a;
        }
        return null;
    }

    public synchronized HttpResponse doSubmitDescription(@QueryParameter String description)
            throws IOException, ServletException {
        getOwner().checkPermission(Item.BUILD);

        setDescription(description);
        getOwner().save();

        return new HttpRedirect(".");
    }

    private static final long serialVersionUID = 1L;
}