1c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/*
2c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Copyright 2007 the original author or authors.
3c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair *
4c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Licensed under the Apache License, Version 2.0 (the "License");
5c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * you may not use this file except in compliance with the License.
6c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * You may obtain a copy of the License at
7c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair *
8c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair *      http://www.apache.org/licenses/LICENSE-2.0
9c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair *
10c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Unless required by applicable law or agreed to in writing, software
11c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * distributed under the License is distributed on an "AS IS" BASIS,
12c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * See the License for the specific language governing permissions and
14c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * limitations under the License.
15c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */
16c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpackage org.mockftpserver.core.session;
17c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
18c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.apache.log4j.Logger;
19c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.command.Command;
20c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.command.CommandHandler;
21c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.command.CommandNames;
22c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.command.ConnectCommandHandler;
23c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.command.InvocationRecord;
24c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.core.socket.StubSocket;
25c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.stub.command.AbstractStubCommandHandler;
26c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport org.mockftpserver.test.AbstractTest;
27c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
28c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.ByteArrayInputStream;
29c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.ByteArrayOutputStream;
30c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.io.InputStream;
31c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.HashMap;
32c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.ListResourceBundle;
33c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.Map;
34c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairimport java.util.ResourceBundle;
35c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
36c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair/**
37c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * Tests for the DefaultSession class that require the session (thread) to be running/active.
38c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair *
39c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @author Chris Mair
40c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair * @version $Revision$ - $Date$
41c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair */
42c1de24f1bfa6699e54b069e300af5e4246b34a34chrismairpublic final class DefaultSession_RunTest extends AbstractTest {
43c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
44c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private static final Logger LOG = Logger.getLogger(DefaultSession_RunTest.class);
45c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private static final Command COMMAND = new Command("USER", EMPTY);
46c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private static final int REPLY_CODE = 100;
47c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private static final String REPLY_TEXT = "sample text description";
48c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
49c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private DefaultSession session;
50c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private ByteArrayOutputStream outputStream;
51c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private Map commandHandlerMap;
52c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private StubSocket stubSocket;
53c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private boolean commandHandled = false;
54c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private String commandToRegister = COMMAND.getName();
55c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
56c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    protected void setUp() throws Exception {
57c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        super.setUp();
58c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        commandHandlerMap = new HashMap();
59c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        outputStream = new ByteArrayOutputStream();
60c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
61c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
62c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testInvocationOfCommandHandler() throws Exception {
63c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        AbstractStubCommandHandler commandHandler = new AbstractStubCommandHandler() {
64c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session cmdSession, InvocationRecord invocationRecord) {
65c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                assertEquals("command", COMMAND, command);
66c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                assertSame("session", session, cmdSession);
67c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                assertEquals("InvocationRecord: command", COMMAND, invocationRecord.getCommand());
68c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                assertEquals("InvocationRecord: clientHost", DEFAULT_HOST, invocationRecord.getClientHost());
69c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
70c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
71c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
72c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, "");
73c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
74c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
75c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testClose() throws Exception {
76c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
77c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
78c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.close();
79c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
80c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
81c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
82c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, "");
83c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        assertFalse("socket should not be closed", stubSocket.isClosed());
84c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
85c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
86c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testGetClientHost() throws Exception {
87c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
88c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
89c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
90c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
91c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
92c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, "");
93c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        LOG.info("clientHost=" + session.getClientHost());
94c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        assertEquals("clientHost", DEFAULT_HOST, session.getClientHost());
95c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
96c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
97c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testSendReply_NullReplyText() throws Exception {
98c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
99c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
100c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.sendReply(REPLY_CODE, null);
101c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
102c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
103c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
104c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, Integer.toString(REPLY_CODE));
105c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
106c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
107c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testSendReply_TrimReplyText() throws Exception {
108c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
109c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
110c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.sendReply(REPLY_CODE, " " + REPLY_TEXT + " ");
111c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
112c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
113c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
114c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);
115c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
116c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
117c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testSendReply_MultiLineText() throws Exception {
118c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        final String MULTILINE_REPLY_TEXT = "abc\ndef\nghi\njkl";
119c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        final String FORMATTED_MULTILINE_REPLY_TEXT = "123-abc\ndef\nghi\n123 jkl";
120c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
121c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
122c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
123c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.sendReply(123, MULTILINE_REPLY_TEXT);
124c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
125c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
126c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
127c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, FORMATTED_MULTILINE_REPLY_TEXT);
128c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
129c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
130c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testSendReply_ReplyText() throws Exception {
131c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
132c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
133c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.sendReply(REPLY_CODE, REPLY_TEXT);
134c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
135c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
136c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
137c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, REPLY_CODE + " " + REPLY_TEXT);
138c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
139c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
140c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    public void testUnrecognizedCommand() throws Exception {
141c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        // Register a handler for unsupported commands
142c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        CommandHandler commandHandler = new AbstractStubCommandHandler() {
143c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) {
144c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                session.sendReply(502, "Unsupported");
145c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                commandHandled = true;
146c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
147c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
148c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        // Register the UNSUPPORTED command handler instead of the command that will be sent. So when we
149c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        // send the regular command, it will trigger the handling for unsupported/unrecognized commands.
150c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        commandToRegister = CommandNames.UNSUPPORTED;
151c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        runCommandAndVerifyOutput(commandHandler, "502 Unsupported");
152c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
153c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
154c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    // -------------------------------------------------------------------------
155c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    // Internal Helper Methods
156c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    // -------------------------------------------------------------------------
157c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
158c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    /**
159c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * Create and return a DefaultSession and define the specified CommandHandler. Also, save the
160c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * StubSocket being used in the stubSocket attribute.
161c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     *
162c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @param commandHandler - define this CommandHandler within the commandHandlerMap
163c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @return the DefaultSession
164c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     */
165c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private DefaultSession createDefaultSession(CommandHandler commandHandler) {
166c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        stubSocket = createTestSocket(COMMAND.getName());
167c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        commandHandlerMap.put(commandToRegister, commandHandler);
168c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
169c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        ConnectCommandHandler connectCommandHandler = new ConnectCommandHandler();
170c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
171c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        ResourceBundle replyTextBundle = new ListResourceBundle() {
172c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            protected Object[][] getContents() {
173c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                return new Object[][]{
174c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                        {"220", "Reply for 220"},
175c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                };
176c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            }
177c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        };
178c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        connectCommandHandler.setReplyTextBundle(replyTextBundle);
179c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        commandHandlerMap.put(CommandNames.CONNECT, connectCommandHandler);
180c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
181c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        return new DefaultSession(stubSocket, commandHandlerMap);
182c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
183c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
184c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    /**
185c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * Create and return a StubSocket that reads from an InputStream with the specified contents and
186c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * writes to the predefined outputStrean ByteArrayOutputStream.
187c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     *
188c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @param inputStreamContents - the contents of the input stream
189c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @return the StubSocket
190c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     */
191c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private StubSocket createTestSocket(String inputStreamContents) {
192c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        InputStream inputStream = new ByteArrayInputStream(inputStreamContents.getBytes());
193c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        return new StubSocket(DEFAULT_HOST, inputStream, outputStream);
194c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
195c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
196c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    /**
197c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * Run the command represented by the CommandHandler and verify that the session output from the
198c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * control socket contains the expected output text.
199c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     *
200c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @param commandHandler - the CommandHandler to invoke
201c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @param expectedOutput - the text expected within the session output
202c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     * @throws InterruptedException - if the thread sleep is interrupted
203c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair     */
204c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    private void runCommandAndVerifyOutput(CommandHandler commandHandler, String expectedOutput)
205c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            throws InterruptedException {
206c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        session = createDefaultSession(commandHandler);
207c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
208c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        Thread thread = new Thread(session);
209c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        thread.start();
210c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
211c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        for (int i = 0; !commandHandled && i < 10; i++) {
212c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair            Thread.sleep(50L);
213c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        }
214c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
215c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        session.close();
216c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        thread.join();
217c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
218c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        assertEquals("commandHandled", true, commandHandled);
219c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
220c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        String output = outputStream.toString();
221c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        LOG.info("output=[" + output.trim() + "]");
222c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        assertTrue("line ends with \\r\\n",
223c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair                output.charAt(output.length() - 2) == '\r' && output.charAt(output.length() - 1) == '\n');
224c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair        assertTrue("output: expected [" + expectedOutput + "]", output.indexOf(expectedOutput) != -1);
225c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair    }
226c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair
227c1de24f1bfa6699e54b069e300af5e4246b34a34chrismair}
228