com.xpn.xwiki.web.DownloadActionTest.java Source code

Java tutorial

Introduction

Here is the source code for com.xpn.xwiki.web.DownloadActionTest.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package com.xpn.xwiki.web;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.ArrayUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.jmock.Expectations;
import org.junit.Assert;
import org.junit.Test;
import org.xwiki.model.reference.DocumentReference;

import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiAttachment;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.plugin.XWikiPluginManager;
import com.xpn.xwiki.test.AbstractBridgedComponentTestCase;

/**
 * Validate {@link DownloadAction}.
 * 
 * @version $Id: 1068bb0948d23510161f991ad9b911031854ebc4 $
 */
public class DownloadActionTest extends AbstractBridgedComponentTestCase {
    /** Mocked global XWiki object. */
    private XWiki xwiki;

    /** Mocked context document. */
    private XWikiDocument document;

    /** Mocked client request. */
    private XWikiRequest request;

    /** Mocked client response. */
    private XWikiResponse response;

    /** Mocked engine context. */
    private XWikiEngineContext ec;

    /** A mocked output stream where the output file data is being written. */
    private ServletOutputStream out;

    /** The action being tested. */
    private DownloadAction action = new DownloadAction();

    /** The content of the file being downloaded in most of the tests. */
    private byte[] fileContent = "abcdefghijklmn".getBytes(XWiki.DEFAULT_ENCODING);

    /** The name of the attachment being downloaded in most of the tests. */
    private static final String DEFAULT_FILE_NAME = "file.txt";

    /** The URI requested in most of the tests. */
    private static final String DEFAULT_URI = "/xwiki/bin/download/space/page/file.txt";

    /**
     * Default constructor.
     * 
     * @throws UnsupportedEncodingException if UTF-8 is not available, so never
     */
    public DownloadActionTest() throws UnsupportedEncodingException {
        // Empty, needed for declaring the exception thrown while initializing fileContent
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();

        this.xwiki = getMockery().mock(XWiki.class);
        getContext().setWiki(this.xwiki);
        this.request = getMockery().mock(XWikiRequest.class);
        getContext().setRequest(this.request);
        this.response = getMockery().mock(XWikiResponse.class);
        getContext().setResponse(this.response);
        this.ec = getMockery().mock(XWikiEngineContext.class);
        getContext().setEngineContext(this.ec);
        this.out = getMockery().mock(ServletOutputStream.class);

        final XWikiPluginManager pluginManager = new XWikiPluginManager();
        pluginManager.initInterface();

        this.document = new XWikiDocument(new DocumentReference("wiki", "space", "page"));
        getContext().setDoc(this.document);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.xwiki).getPluginManager();
                will(returnValue(pluginManager));
                allowing(DownloadActionTest.this.ec).getMimeType(with("file.txt"));
                will(returnValue("text/plain"));
                allowing(DownloadActionTest.this.response).setCharacterEncoding(with(""));
                allowing(DownloadActionTest.this.response).getOutputStream();
                will(returnValue(DownloadActionTest.this.out));
            }
        });
    }

    @Test
    public void testNormalDownload() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testIfModifiedSinceBefore() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, null, d.getTime() - 1000l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testIfModifiedSinceSame() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, null, d.getTime());
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_NOT_MODIFIED));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testIfModifiedSinceAfter() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, null, d.getTime() + 1000l);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_NOT_MODIFIED));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test(expected = XWikiException.class)
    public void testDownloadMissingFile() throws XWikiException, IOException {
        setRequestExpectations("/xwiki/bin/download/space/page/nofile.txt", null, null, null, -1l);
        this.action.render(getContext());
    }

    @Test
    public void testDownloadById() throws XWikiException, IOException {
        final Date d = new Date();
        XWikiAttachment att;
        for (byte i = 0; i < 10; ++i) {
            att = new XWikiAttachment(this.document, "file." + i + ".txt");
            byte[] content = new byte[1];
            content[0] = (byte) ('0' + i);
            att.setContent(new ByteArrayInputStream(content));
            att.setDate(d);
            this.document.getAttachmentList().add(att);
        }

        setRequestExpectations("/xwiki/bin/download/space/page/file.2.txt", "5", null, null, -1l);
        setResponseExpectations(d.getTime(), 1, "text/plain", "inline; filename*=utf-8''file.5.txt");
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.ec).getMimeType(with("file.5.txt"));
                will(returnValue("text/plain"));

                allowing(DownloadActionTest.this.out).write(with(new BaseMatcher<byte[]>() {
                    @Override
                    public boolean matches(Object other) {
                        if (!(other instanceof byte[])) {
                            return false;
                        }
                        byte[] otherByteArray = (byte[]) other;
                        return (otherByteArray[0] == '5');
                    }

                    @Override
                    public void describeTo(Description desc) {
                        desc.appendValue(new byte[] { '5' });
                    }
                }), with(0), with(1));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test(expected = XWikiException.class)
    public void testDownloadByWrongId() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, "42", null, null, -1l);
        this.action.render(getContext());
    }

    @Test
    public void testDownloadByInvalidId() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, "two", null, null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test(expected = XWikiException.class)
    public void testDownloadWithIncompletePath() throws XWikiException, IOException {
        setRequestExpectations("/xwiki/bin/download/", null, null, null, -1l);
        this.action.render(getContext());
    }

    @Test
    public void testDifferentMimeType() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, "file.png");
        setRequestExpectations("/xwiki/bin/download/space/page/file.png", null, null, null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length, "image/png",
                "inline; filename*=utf-8''file.png");
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.ec).getMimeType(with("file.png"));
                will(returnValue("image/png"));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testForceDownload() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, "1", null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length, "text/plain",
                "attachment; filename*=utf-8''file.txt");
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testRealDate() throws XWikiException, IOException {
        final Date d = new Date(411757300000l);
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testNameWithSpacesEncodedWithPlus() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, "file name.txt");
        setRequestExpectations("/xwiki/bin/download/space/page/file+name.txt", null, null, null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length, "text/plain",
                "inline; filename*=utf-8''file%20name.txt");
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.ec).getMimeType(with("file name.txt"));
                will(returnValue("text/plain"));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testNameWithSpacesEncodedWithPercent() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, "file name.txt");
        setRequestExpectations("/xwiki/bin/download/space/page/file%20name.txt", null, "1", null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length, "text/plain",
                "attachment; filename*=utf-8''file%20name.txt");
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.ec).getMimeType(with("file name.txt"));
                will(returnValue("text/plain"));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testNameWithNonAsciiChars() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, "file\u021B.txt");
        setRequestExpectations("/xwiki/bin/download/space/page/file%C8%9B.txt", null, "1", null, -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length, "text/plain",
                "attachment; filename*=utf-8''file%C8%9B.txt");
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.ec).getMimeType(with("file\u021B.txt"));
                will(returnValue("text/plain"));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testValidStartRange() throws XWikiException, IOException {
        // This test expects bytes 0, 1, 2 and 3 from the file.
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=0-3", -1l);
        setResponseExpectations(d.getTime(), 4);
        setOutputExpectations(0, 4);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 0-3/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testValidMiddleRange() throws XWikiException, IOException {
        // This test expects bytes 3, 4 and 5 from the file.
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=3-5", -1l);
        setResponseExpectations(d.getTime(), 3);
        setOutputExpectations(3, 6);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 3-5/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testValidEndRange() throws XWikiException, IOException {
        // This test expects bytes 9, 10, 11, 12 and 13 from the file.
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=9-13", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length - 9);
        setOutputExpectations(9, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 9-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testOneByteRange() throws XWikiException, IOException {
        // This test expects the last four bytes (10, 11, 12 and 13) from the file
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=0-0", -1l);
        setResponseExpectations(d.getTime(), 1);
        setOutputExpectations(0, 1);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 0-0/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testRestRange() throws XWikiException, IOException {
        // This test expects bytes from 11 to the end of the file (11, 12 and 13)
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=11-", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length - 11);
        setOutputExpectations(11, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 11-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testFullRestRange() throws XWikiException, IOException {
        // This test expects the whole file
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=0-", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 0-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testTailRange() throws XWikiException, IOException {
        // This test expects the last four bytes (10, 11, 12 and 13) from the file
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=-4", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length - 10);
        setOutputExpectations(10, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 10-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testFullTailRange() throws XWikiException, IOException {
        // This test expects the whole file
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=-14", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 0-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testOverflowingTailRange() throws XWikiException, IOException {
        // This test expects the whole file, although the client requested more
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=-40", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 0-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testValidOverflowingRange() throws XWikiException, IOException {
        // This test expects bytes 9, 10, 11, 12 and 13 from the file, although 14 and 15 are requested as well.
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=9-15", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length - 9);
        setOutputExpectations(9, this.fileContent.length);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setStatus(with(HttpServletResponse.SC_PARTIAL_CONTENT));
                one(DownloadActionTest.this.response).setHeader(with("Content-Range"),
                        with("bytes 9-13/" + DownloadActionTest.this.fileContent.length));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testInvalidSwappedRange() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=9-5", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testInvalidRange() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=all", -1l);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testOutsideRange() throws XWikiException, IOException {
        // This test expects a 416 response
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=129-145", -1l);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response)
                        .setStatus(with(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testOutsideRestRange() throws XWikiException, IOException {
        // This test expects a 416 response
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=129-", -1L);
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response)
                        .setStatus(with(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE));
            }
        });
        Assert.assertNull(this.action.render(getContext()));
    }

    @Test
    public void testEmptyRange() throws XWikiException, IOException {
        final Date d = new Date();
        createAttachment(d, DEFAULT_FILE_NAME);
        setRequestExpectations(DEFAULT_URI, null, null, "bytes=-", -1L);
        setResponseExpectations(d.getTime(), this.fileContent.length);
        setOutputExpectations(0, this.fileContent.length);
        Assert.assertNull(this.action.render(getContext()));
    }

    private void createAttachment(Date d, String name) throws IOException {
        XWikiAttachment filetxt = new XWikiAttachment(this.document, name);
        filetxt.setContent(new ByteArrayInputStream(this.fileContent));
        filetxt.setDate(d);
        this.document.getAttachmentList().add(filetxt);
    }

    private void setRequestExpectations(final String uri, final String id, final String forceDownload,
            final String range, final long modifiedSince) {
        getMockery().checking(new Expectations() {
            {
                allowing(DownloadActionTest.this.request).getRequestURI();
                will(returnValue(uri));
                allowing(DownloadActionTest.this.request).getParameter(with("id"));
                will(returnValue(id));
                allowing(DownloadActionTest.this.request).getDateHeader(with("If-Modified-Since"));
                will(returnValue(modifiedSince));
                allowing(DownloadActionTest.this.request).getParameter(with("force-download"));
                will(returnValue(forceDownload));
                allowing(DownloadActionTest.this.request).getHeader(with("Range"));
                will(returnValue(range));
            }
        });
    }

    private void setResponseExpectations(final long modified, final int length) {
        setResponseExpectations(modified, length, "text/plain", "inline; filename*=utf-8''file.txt");
    }

    private void setResponseExpectations(final long modified, final int length, final String mime,
            final String disposition) {
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.response).setContentType(with(mime));
                one(DownloadActionTest.this.response).setHeader(with("Accept-Ranges"), with("bytes"));
                one(DownloadActionTest.this.response).addHeader(with("Content-disposition"), with(disposition));
                one(DownloadActionTest.this.response).setDateHeader(with("Last-Modified"), with(modified));
                one(DownloadActionTest.this.response).setContentLength(with(length));
            }
        });
    }

    private void setOutputExpectations(final int start, final int end) throws IOException {
        getMockery().checking(new Expectations() {
            {
                one(DownloadActionTest.this.out).write(with(new BaseMatcher<byte[]>() {
                    @Override
                    public boolean matches(Object other) {
                        if (!(other instanceof byte[])) {
                            return false;
                        }
                        byte[] otherByteArray = (byte[]) other;
                        for (int i = start; i < end; ++i) {
                            if (otherByteArray[i - start] != DownloadActionTest.this.fileContent[i]) {
                                return false;
                            }
                        }
                        return true;
                    }

                    @Override
                    public void describeTo(Description desc) {
                        desc.appendValue(ArrayUtils.subarray(DownloadActionTest.this.fileContent, start, end));
                    }
                }), with(0), with(end - start));

            }
        });
    }
}