1ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair/*
2ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Copyright 2008 the original author or authors.
3ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *
4ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Licensed under the Apache License, Version 2.0 (the "License");
5ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * you may not use this file except in compliance with the License.
6ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * You may obtain a copy of the License at
7ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *
8ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *      http://www.apache.org/licenses/LICENSE-2.0
9ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *
10ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Unless required by applicable law or agreed to in writing, software
11ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * distributed under the License is distributed on an "AS IS" BASIS,
12ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * See the License for the specific language governing permissions and
14ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * limitations under the License.
15ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */
16ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairpackage org.mockftpserver.fake.command
17ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
18ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.Command
19ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.CommandHandler
20ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.command.ReplyCodes
21ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.session.SessionKeys
22ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.core.session.StubSession
23ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.StubServerConfiguration
24ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.UserAccount
25ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.filesystem.DirectoryEntry
26ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.filesystem.FileEntry
27ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.filesystem.FileSystemException
28ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.fake.filesystem.TestUnixFakeFileSystem
29ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairimport org.mockftpserver.test.AbstractGroovyTest
30ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
31ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair/**
32ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * Abstract superclass for CommandHandler tests
33ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *
34ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @version $Revision$ - $Date$
35ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair *
36ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair * @author Chris Mair
37ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair */
38ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismairabstract class AbstractFakeCommandHandlerTest extends AbstractGroovyTest {
39ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
40ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected static final ERROR_MESSAGE_KEY = 'msgkey'
41ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
42ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected session
43ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected serverConfiguration
44ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected commandHandler
45ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected fileSystem
46ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected userAccount
47ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
48ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /** Set this to false to skip the test that verifies that the CommandHandler requires a logged in user             */
49ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    boolean testNotLoggedIn = true
50ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
51ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
52ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    // Tests (common to all subclasses)
53ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
54ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
55ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    void testHandleCommand_ServerConfigurationIsNull() {
56ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.serverConfiguration = null
57ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def command = createValidCommand()
58ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        shouldFailWithMessageContaining("serverConfiguration") { commandHandler.handleCommand(command, session) }
59ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
60ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
61ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    void testHandleCommand_CommandIsNull() {
62ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        shouldFailWithMessageContaining("command") { commandHandler.handleCommand(null, session) }
63ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
64ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
65ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    void testHandleCommand_SessionIsNull() {
66ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def command = createValidCommand()
67ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        shouldFailWithMessageContaining("session") { commandHandler.handleCommand(command, null) }
68ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
69ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
70ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    void testHandleCommand_NotLoggedIn() {
71ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        if (getProperty('testNotLoggedIn')) {
72ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            def command = createValidCommand()
73ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            session.removeAttribute(SessionKeys.USER_ACCOUNT)
74ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            commandHandler.handleCommand(command, session)
75ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            assertSessionReply(ReplyCodes.NOT_LOGGED_IN)
76ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        }
77ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
78ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
79ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
80ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    // Abstract Method Declarations (must be implemented by all subclasses)
81ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
82ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
83ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
84ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Create and return a new instance of the CommandHandler class under test. Concrete subclasses must implement.
85ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
86ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    abstract CommandHandler createCommandHandler()
87ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
88ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
89ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Create and return a valid instance of the Command for the CommandHandler class
90ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * under test. Concrete subclasses must implement.
91ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
92ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    abstract Command createValidCommand()
93ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
94ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
95ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    // Test Setup
96ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
97ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
98ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    void setUp() {
99ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        super.setUp()
100ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        session = new StubSession()
101ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        serverConfiguration = new StubServerConfiguration()
102ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        fileSystem = new TestUnixFakeFileSystem()
103ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        fileSystem.createParentDirectoriesAutomatically = true
104ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        serverConfiguration.setFileSystem(fileSystem)
105ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
106ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        userAccount = new UserAccount()
107ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)
108ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
109ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler = createCommandHandler()
110ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.serverConfiguration = serverConfiguration
111ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
112ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
113ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
114ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    // Helper Methods
115ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    //-------------------------------------------------------------------------
116ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
117ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
118ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Perform a test of the handleCommand() method on the specified command
119ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * parameters, which are missing a required parameter for this CommandHandler.
120ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
121ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected void testHandleCommand_MissingRequiredParameter(List commandParameters) {
122ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.handleCommand(createCommand(commandParameters), session)
123ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReply(ReplyCodes.COMMAND_SYNTAX_ERROR)
124ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
125ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
126ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
127ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Perform a test of the handleCommand() method on the specified command
128ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * parameters, which are missing a required parameter for this CommandHandler.
129ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
130ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected testHandleCommand_MissingRequiredSessionAttribute() {
131ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def command = createValidCommand()
132ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.handleCommand(command, session)
133ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReply(ReplyCodes.ILLEGAL_STATE)
134ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
135ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
136ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
137ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @return a new Command with the specified parameters for this CommandHandler
138ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
139ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected Command createCommand(List commandParameters) {
140ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        new Command(createValidCommand().name, commandParameters)
141ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
142ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
143ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
144ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Invoke the handleCommand() method for the current CommandHandler, passing in
145ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * the specified parameters
146ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param parameters - the List of command parameters; may be empty, but not null
147ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
148ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected void handleCommand(List parameters) {
149ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.handleCommand(createCommand(parameters), session)
150ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
151ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
152ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
153ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Assert that the specified reply code and message containing text was sent through the session.
154ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param expectedReplyCode - the expected reply code
155ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param text - the text expected within the reply message; defaults to the reply code as a String
156ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @deprecated
157ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
158ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected assertSessionReply(int expectedReplyCode, text = expectedReplyCode as String) {
159ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReply(0, expectedReplyCode, text)
160ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
161ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
162ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
163ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Assert that the specified reply code and message containing text was sent through the session.
164ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param replyIndex - the index of the reply to compare
165ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param expectedReplyCode - the expected reply code
166ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param text - the text expected within the reply message; defaults to the reply code as a String
167ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
168ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected assertSessionReply(int replyIndex, int expectedReplyCode, text = expectedReplyCode as String) {
169ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        LOG.info(session)
170ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        String actualMessage = session.getReplyMessage(replyIndex)
171ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def actualReplyCode = session.getReplyCode(replyIndex)
172ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assert actualReplyCode == expectedReplyCode
173ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        if (text instanceof List) {
174ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            text.each { assert actualMessage.contains(it), "[$actualMessage] does not contain [$it]" }
175ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        }
176ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        else {
177ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            assert actualMessage.contains(text), "[$actualMessage] does not contain [$text]"
178ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        }
179ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
180ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
181ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
182ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Assert that the specified reply codes were sent through the session.
183ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param replyCodes - the List of expected sent reply codes
184ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
185ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected assertSessionReplies(List replyCodes) {
186ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        LOG.info(session)
187ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        replyCodes.eachWithIndex {replyCode, replyIndex ->
188ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair            assertSessionReply(replyIndex, replyCode)
189ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        }
190ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
191ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
192ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
193ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Assert that the specified data was sent through the session.
194ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param expectedData - the expected data
195ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
196ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected assertSessionData(String expectedData) {
197ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def actual = session.sentData[0]
198ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assert actual != null, "No data for index [0] sent for $session"
199ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assert actual == expectedData
200ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
201ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
202ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
203ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Execute the handleCommand() method with the specified parameters and
204ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * assert that the standard SEND DATA replies were sent through the session.
205ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param parameters - the command parameters to use; defaults to []
206ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param finalReplyCode - the expected final reply code; defaults to ReplyCodes.TRANSFER_DATA_FINAL_OK
207ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
208ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected handleCommandAndVerifySendDataReplies(parameters = [], int finalReplyCode = ReplyCodes.TRANSFER_DATA_FINAL_OK) {
209ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        handleCommand(parameters)
210ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReplies([ReplyCodes.TRANSFER_DATA_INITIAL_OK, finalReplyCode])
211ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
212ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
213ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
214ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Execute the handleCommand() method with the specified parameters and
215ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * assert that the standard SEND DATA replies were sent through the session.
216ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param parameters - the command parameters to use
217ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param initialReplyMessageKey - the expected reply message key for the initial reply
218ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param finalReplyMessageKey -  the expected reply message key for the final reply
219ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param finalReplyCode - the expected final reply code; defaults to ReplyCodes.TRANSFER_DATA_FINAL_OK
220ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
221ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected handleCommandAndVerifySendDataReplies(parameters, String initialReplyMessageKey, String finalReplyMessageKey, int finalReplyCode = ReplyCodes.TRANSFER_DATA_FINAL_OK) {
222ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        handleCommand(parameters)
223ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReply(0, ReplyCodes.TRANSFER_DATA_INITIAL_OK, initialReplyMessageKey)
224ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        assertSessionReply(1, finalReplyCode, finalReplyMessageKey)
225ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
226ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
227ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
228ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Override the named method for the specified object instance
229ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param object - the object instance
230ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param methodName - the name of the method to override
231ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param newMethod - the Closure representing the new method for this single instance
232ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
233ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected void overrideMethod(object, String methodName, Closure newMethod) {
234ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        LOG.info("Overriding method [$methodName] for class [${object.class}]")
235ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def emc = new ExpandoMetaClass(object.class, false)
236ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        emc."$methodName" = newMethod
237ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        emc.initialize()
238ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        object.metaClass = emc
239ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
240ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
241ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
242ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Override the named method (that takes a single String arg) of the fileSystem object to throw a (generic) FileSystemException
243ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param methodName - the name of the fileSystem method to override
244ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
245ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected void overrideMethodToThrowFileSystemException(String methodName) {
246ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        def newMethod = {String path -> throw new FileSystemException("Error thrown by method [$methodName]", ERROR_MESSAGE_KEY) }
247ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        overrideMethod(fileSystem, methodName, newMethod)
248ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
249ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
250ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
251ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Set the current directory within the session
252ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param path - the new path value for the current directory
253ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
254ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected void setCurrentDirectory(String path) {
255ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        session.setAttribute(SessionKeys.CURRENT_DIRECTORY, path)
256ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
257ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
258ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
259ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Convenience method to return the end-of-line character(s) for the current CommandHandler.
260ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
261ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected endOfLine() {
262ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        commandHandler.endOfLine()
263ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
264ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
265ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
266ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Create a new directory entry with the specified path in the file system
267ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param path - the path of the new directory entry
268ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @return the newly created DirectoryEntry
269ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
270ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected DirectoryEntry createDirectory(String path) {
271ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        DirectoryEntry entry = new DirectoryEntry(path)
272ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        fileSystem.add(entry)
273ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        return entry
274ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
275ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
276ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    /**
277ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * Create a new file entry with the specified path in the file system
278ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param path - the path of the new file entry
279ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @param contents - the contents for the file; defaults to null
280ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     * @return the newly created FileEntry
281ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair     */
282ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    protected FileEntry createFile(String path, contents = null) {
283ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        FileEntry entry = new FileEntry(path: path, contents: contents)
284ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        fileSystem.add(entry)
285ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair        return entry
286ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair    }
287ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair
288ad39334d4c363c6ada5863d0bb3184f5f4699d69chrismair}