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
32import org.mockftpserver.test.StubResourceBundle
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 replyTextBundle
56    private fileSystem
57    private userAccount
58
59    //-------------------------------------------------------------------------
60    // Tests
61    //-------------------------------------------------------------------------
62
63    void testHandleCommand() {
64        def command = new Command("C1", ["abc"])
65        commandHandler.handleCommand(command, session)
66        assert commandHandler.handled
67
68        assertHandleCommandReplyCode(new CommandSyntaxException(""), ReplyCodes.COMMAND_SYNTAX_ERROR)
69        assertHandleCommandReplyCode(new IllegalStateException(""), ReplyCodes.ILLEGAL_STATE)
70        assertHandleCommandReplyCode(new NotLoggedInException(""), ReplyCodes.NOT_LOGGED_IN)
71        assertHandleCommandReplyCode(new InvalidFilenameException(""), ReplyCodes.FILENAME_NOT_VALID)
72
73        shouldFail { commandHandler.handleCommand(null, session) }
74        shouldFail { commandHandler.handleCommand(command, null) }
75    }
76
77    void testHandleCommand_FileSystemException() {
78        assertHandleCommandReplyCode(new FileSystemException(PATH, ''), ReplyCodes.READ_FILE_ERROR, PATH)
79        commandHandler.replyCodeForFileSystemException = ReplyCodes.WRITE_FILE_ERROR
80        assertHandleCommandReplyCode(new FileSystemException(PATH, ''), ReplyCodes.WRITE_FILE_ERROR, PATH)
81    }
82
83    void testSendReply() {
84        commandHandler.sendReply(session, REPLY_CODE)
85        assert session.sentReplies[0] == [REPLY_CODE, MSG], session.sentReplies[0]
86
87        commandHandler.sendReply(session, REPLY_CODE, [ARG])
88        assert session.sentReplies[1] == [REPLY_CODE, MSG_WITH_ARG], session.sentReplies[0]
89
90        shouldFailWithMessageContaining('session') { commandHandler.sendReply(null, REPLY_CODE) }
91        shouldFailWithMessageContaining('reply code') { commandHandler.sendReply(session, 0) }
92    }
93
94    void testSendReply_MessageKey() {
95        commandHandler.sendReply(session, REPLY_CODE, MESSAGE_KEY)
96        assert session.sentReplies[0] == [REPLY_CODE, MSG_FOR_KEY], session.sentReplies[0]
97
98        shouldFailWithMessageContaining('session') { commandHandler.sendReply(null, REPLY_CODE, MESSAGE_KEY) }
99        shouldFailWithMessageContaining('reply code') { commandHandler.sendReply(session, 0, MESSAGE_KEY) }
100    }
101
102    void testSendReply_NullMessageKey() {
103        commandHandler.sendReply(session, REPLY_CODE, null, null)
104        assert session.sentReplies[0] == [REPLY_CODE, MSG_INTERNAL_ERROR], session.sentReplies[0]
105    }
106
107    void testAssertValidReplyCode() {
108        commandHandler.assertValidReplyCode(1)        // no exception expected
109        shouldFail { commandHandler.assertValidReplyCode(0) }
110    }
111
112    void testGetRequiredSessionAttribute() {
113        shouldFail(IllegalStateException) { commandHandler.getRequiredSessionAttribute(session, "undefined") }
114
115        session.setAttribute("abc", "not empty")
116        commandHandler.getRequiredSessionAttribute(session, "abc") // no exception
117
118        session.setAttribute("abc", "")
119        commandHandler.getRequiredSessionAttribute(session, "abc") // no exception
120    }
121
122    void testVerifyLoggedIn() {
123        shouldFail(NotLoggedInException) { commandHandler.verifyLoggedIn(session) }
124        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)
125        commandHandler.verifyLoggedIn(session)        // no exception expected
126    }
127
128    void testGetUserAccount() {
129        assert commandHandler.getUserAccount(session) == null
130        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)
131        assert commandHandler.getUserAccount(session)
132    }
133
134    void testVerifyFileSystemCondition() {
135        commandHandler.verifyFileSystemCondition(true, PATH, '')    // no exception expected
136        shouldFail(FileSystemException) { commandHandler.verifyFileSystemCondition(false, PATH, '') }
137    }
138
139    void testGetRealPath() {
140        assert commandHandler.getRealPath(session, "/xxx") == "/xxx"
141
142        session.setAttribute(SessionKeys.CURRENT_DIRECTORY, "/usr/me")
143        assert commandHandler.getRealPath(session, null) == "/usr/me"
144        assert commandHandler.getRealPath(session, "/xxx") == "/xxx"
145        assert commandHandler.getRealPath(session, "xxx") == "/usr/me/xxx"
146    }
147
148    //-------------------------------------------------------------------------
149    // Test Setup
150    //-------------------------------------------------------------------------
151
152    void setUp() {
153        super.setUp()
154        commandHandler = new TestFakeCommandHandler()
155        session = new StubSession()
156        serverConfiguration = new StubServerConfiguration()
157        replyTextBundle = new StubResourceBundle()
158        userAccount = new UserAccount()
159        fileSystem = new UnixFakeFileSystem()
160        serverConfiguration.setFileSystem(fileSystem)
161
162        replyTextBundle.put(REPLY_CODE as String, MSG)
163        replyTextBundle.put(MESSAGE_KEY as String, MSG_FOR_KEY)
164        replyTextBundle.put(INTERNAL_ERROR as String, MSG_INTERNAL_ERROR)
165
166        commandHandler.serverConfiguration = serverConfiguration
167        commandHandler.replyTextBundle = replyTextBundle
168    }
169
170    //-------------------------------------------------------------------------
171    // Helper Methods
172    //-------------------------------------------------------------------------
173
174    /**
175     * Assert that when the CommandHandler handleCommand() method throws the
176     * specified exception, that the expected reply is sent through the session.
177     */
178    private void assertHandleCommandReplyCode(Throwable exception, int expected, text = null) {
179        commandHandler.exception = exception
180        def command = new Command("C1", ["abc"])
181        session.sentReplies.clear()
182        commandHandler.handleCommand(command, session)
183        def sentReply = session.sentReplies[0][0]
184        assert sentReply == expected
185        if (text) {
186            def sentMessage = session.sentReplies[0][1]
187            assert sentMessage.contains(text), "sentMessage=[$sentMessage] text=[$text]"
188        }
189    }
190
191}
192
193/**
194 * Concrete subclass of AbstractFakeCommandHandler for testing
195 */
196class TestFakeCommandHandler extends AbstractFakeCommandHandler {
197    boolean handled = false
198    def exception
199
200    protected void handle(Command command, Session session) {
201        if (exception) {
202            throw exception
203        }
204        this.handled = true
205    }
206}