1/*
2 * Copyright 2008 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.mockftpserver.fake.command
17
18import org.mockftpserver.core.CommandSyntaxException
19import org.mockftpserver.core.IllegalStateException
20import org.mockftpserver.core.NotLoggedInException
21import org.mockftpserver.core.command.Command
22import org.mockftpserver.core.command.ReplyCodes
23import org.mockftpserver.core.session.Session
24import org.mockftpserver.core.session.SessionKeys
25import org.mockftpserver.core.session.StubSession
26import org.mockftpserver.fake.StubServerConfiguration
27import org.mockftpserver.fake.UserAccount
28import org.mockftpserver.fake.filesystem.FileSystemException
29import org.mockftpserver.fake.filesystem.InvalidFilenameException
30import org.mockftpserver.fake.filesystem.UnixFakeFileSystem
31import org.mockftpserver.test.AbstractGroovyTest
32
33
34/**
35 * Tests for AbstractFakeCommandHandler
36 *
37 * @version $Revision$ - $Date$
38 *
39 * @author Chris Mair
40 */
41class AbstractFakeCommandHandlerClassTest extends AbstractGroovyTest {
42
43    static PATH = "some/path"
44    static REPLY_CODE = 99
45    static MESSAGE_KEY = "99.WithFilename"
46    static ARG = "ABC"
47    static MSG = "text {0}"
48    static MSG_WITH_ARG = "text ABC"
49    static MSG_FOR_KEY = "some other message"
50    static INTERNAL_ERROR = AbstractFakeCommandHandler.INTERNAL_ERROR_KEY
51    static MSG_INTERNAL_ERROR = "internal error message {0}"
52    private AbstractFakeCommandHandler commandHandler
53    private session
54    private serverConfiguration
55    private fileSystem
56    private userAccount
57
58    //-------------------------------------------------------------------------
59    // Tests
60    //-------------------------------------------------------------------------
61
62    void testHandleCommand() {
63        def command = new Command("C1", ["abc"])
64        commandHandler.handleCommand(command, session)
65        assert commandHandler.handled
66
67        assertHandleCommandReplyCode(new CommandSyntaxException(""), ReplyCodes.COMMAND_SYNTAX_ERROR)
68        assertHandleCommandReplyCode(new IllegalStateException(""), ReplyCodes.ILLEGAL_STATE)
69        assertHandleCommandReplyCode(new NotLoggedInException(""), ReplyCodes.NOT_LOGGED_IN)
70        assertHandleCommandReplyCode(new InvalidFilenameException(""), ReplyCodes.FILENAME_NOT_VALID)
71
72        shouldFail { commandHandler.handleCommand(null, session) }
73        shouldFail { commandHandler.handleCommand(command, null) }
74    }
75
76    void testHandleCommand_FileSystemException() {
77        assertHandleCommandReplyCode(new FileSystemException(PATH, ''), ReplyCodes.READ_FILE_ERROR, PATH)
78        commandHandler.replyCodeForFileSystemException = ReplyCodes.WRITE_FILE_ERROR
79        assertHandleCommandReplyCode(new FileSystemException(PATH, ''), ReplyCodes.WRITE_FILE_ERROR, PATH)
80    }
81
82    void testSendReply() {
83        commandHandler.sendReply(session, REPLY_CODE)
84        assert session.sentReplies[0] == [REPLY_CODE, MSG], session.sentReplies[0]
85
86        commandHandler.sendReply(session, REPLY_CODE, [ARG])
87        assert session.sentReplies[1] == [REPLY_CODE, MSG_WITH_ARG], session.sentReplies[0]
88
89        shouldFailWithMessageContaining('session') { commandHandler.sendReply(null, REPLY_CODE) }
90        shouldFailWithMessageContaining('replyCode') { commandHandler.sendReply(session, 0) }
91    }
92
93    void testSendReply_MessageKey() {
94        commandHandler.sendReply(session, REPLY_CODE, MESSAGE_KEY)
95        assert session.sentReplies[0] == [REPLY_CODE, MSG_FOR_KEY], session.sentReplies[0]
96
97        shouldFailWithMessageContaining('session') { commandHandler.sendReply(null, REPLY_CODE, MESSAGE_KEY) }
98        shouldFailWithMessageContaining('replyCode') { commandHandler.sendReply(session, 0, MESSAGE_KEY) }
99    }
100
101    void testSendReply_NullMessageKey() {
102        commandHandler.sendReply(session, REPLY_CODE, null, null)
103        assert session.sentReplies[0] == [REPLY_CODE, MSG_INTERNAL_ERROR], session.sentReplies[0]
104    }
105
106    void testAssertValidReplyCode() {
107        commandHandler.assertValidReplyCode(1)        // no exception expected
108        shouldFail { commandHandler.assertValidReplyCode(0) }
109    }
110
111    void testGetRequiredSessionAttribute() {
112        shouldFail(IllegalStateException) { commandHandler.getRequiredSessionAttribute(session, "undefined") }
113
114        session.setAttribute("abc", "not empty")
115        commandHandler.getRequiredSessionAttribute(session, "abc") // no exception
116
117        session.setAttribute("abc", "")
118        commandHandler.getRequiredSessionAttribute(session, "abc") // no exception
119    }
120
121    void testVerifyLoggedIn() {
122        shouldFail(NotLoggedInException) { commandHandler.verifyLoggedIn(session) }
123        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)
124        commandHandler.verifyLoggedIn(session)        // no exception expected
125    }
126
127    void testGetUserAccount() {
128        assert commandHandler.getUserAccount(session) == null
129        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)
130        assert commandHandler.getUserAccount(session)
131    }
132
133    void testVerifyFileSystemCondition() {
134        commandHandler.verifyFileSystemCondition(true, PATH, '')    // no exception expected
135        shouldFail(FileSystemException) { commandHandler.verifyFileSystemCondition(false, PATH, '') }
136    }
137
138    void testGetRealPath() {
139        assert commandHandler.getRealPath(session, "/xxx") == "/xxx"
140
141        session.setAttribute(SessionKeys.CURRENT_DIRECTORY, "/usr/me")
142        assert commandHandler.getRealPath(session, null) == "/usr/me"
143        assert commandHandler.getRealPath(session, "/xxx") == "/xxx"
144        assert commandHandler.getRealPath(session, "xxx") == "/usr/me/xxx"
145    }
146
147    //-------------------------------------------------------------------------
148    // Test Setup
149    //-------------------------------------------------------------------------
150
151    void setUp() {
152        super.setUp()
153        commandHandler = new TestFakeCommandHandler()
154        session = new StubSession()
155        serverConfiguration = new StubServerConfiguration()
156        userAccount = new UserAccount()
157        fileSystem = new UnixFakeFileSystem()
158        serverConfiguration.setFileSystem(fileSystem)
159
160        serverConfiguration.setTextForKey(REPLY_CODE, MSG)
161        serverConfiguration.setTextForKey(MESSAGE_KEY, MSG_FOR_KEY)
162        serverConfiguration.setTextForKey(INTERNAL_ERROR, MSG_INTERNAL_ERROR)
163
164        commandHandler.serverConfiguration = serverConfiguration
165    }
166
167    //-------------------------------------------------------------------------
168    // Helper Methods
169    //-------------------------------------------------------------------------
170
171    /**
172     * Assert that when the CommandHandler handleCommand() method throws the
173     * specified exception, that the expected reply is sent through the session.
174     */
175    private void assertHandleCommandReplyCode(Throwable exception, int expected, text = null) {
176        commandHandler.exception = exception
177        def command = new Command("C1", ["abc"])
178        session.sentReplies.clear()
179        commandHandler.handleCommand(command, session)
180        def sentReply = session.sentReplies[0][0]
181        assert sentReply == expected
182        if (text) {
183            def sentMessage = session.sentReplies[0][1]
184            assert sentMessage.contains(text), "sentMessage=[$sentMessage] text=[$text]"
185        }
186    }
187
188}
189
190/**
191 * Concrete subclass of AbstractFakeCommandHandler for testing
192 */
193class TestFakeCommandHandler extends AbstractFakeCommandHandler {
194    boolean handled = false
195    def exception
196
197    protected void handle(Command command, Session session) {
198        if (exception) {
199            throw exception
200        }
201        this.handled = true
202    }
203}