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.filesystem
17
18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory;
20import org.mockftpserver.core.util.IoUtil
21
22/**
23 * Tests for FileEntry
24 *
25 * @version $Revision$ - $Date$
26 *
27 * @author Chris Mair
28 */
29public class FileEntryTest extends AbstractFileSystemEntryTestCase {
30
31    private static final LOG = LoggerFactory.getLogger(FileEntryTest)
32    private static final CONTENTS = "abc 123 %^& xxx"
33
34    private FileEntry entry
35
36    void testConstructorWithStringContents() {
37        entry = new FileEntry(PATH, CONTENTS)
38        verifyContents(CONTENTS)
39    }
40
41    void testSettingContentsFromString() {
42        entry.setContents(CONTENTS)
43        verifyContents(CONTENTS)
44    }
45
46    void testSettingContentsFromBytes() {
47        byte[] contents = CONTENTS.getBytes()
48        entry.setContents(contents)
49        // Now corrupt the original byte array to make sure the file entry is not affected
50        contents[1] = (byte) '#'
51        verifyContents(CONTENTS)
52    }
53
54    void testSetContents_BytesNotInCharSet() {
55        byte[] contents = [65, -99, 91, -115] as byte[]
56        entry.setContents(contents)
57        verifyContents(contents)
58    }
59
60    void testSetContents_NullString() {
61        entry.setContents((String) null)
62        assert entry.size == 0
63    }
64
65    void testSetContents_NullBytes() {
66        entry.setContents((byte[]) null)
67        assert entry.size == 0
68    }
69
70    void testCreateOutputStream() {
71        // New, empty file
72        OutputStream out = entry.createOutputStream(false)
73        out.write(CONTENTS.getBytes())
74        verifyContents(CONTENTS)
75
76        // Another OutputStream, append=false
77        out = entry.createOutputStream(false)
78        out.write(CONTENTS.getBytes())
79        verifyContents(CONTENTS)
80
81        // Another OutputStream, append=true
82        out = entry.createOutputStream(true)
83        out.write(CONTENTS.getBytes())
84        verifyContents(CONTENTS + CONTENTS)
85
86        // Set contents directly
87        final String NEW_CONTENTS = ",./'\t\r[]-\n="
88        entry.setContents(NEW_CONTENTS)
89        verifyContents(NEW_CONTENTS)
90
91        // New OutputStream, append=true (so should append to contents we set directly)
92        out = entry.createOutputStream(true)
93        out.write(CONTENTS.getBytes())
94        verifyContents(NEW_CONTENTS + CONTENTS)
95
96        // Yet another OutputStream, append=true (so should append to accumulated contents)
97        OutputStream out2 = entry.createOutputStream(true)
98        out2.write(CONTENTS.getBytes())
99        out2.close()       // should have no effect
100        verifyContents(NEW_CONTENTS + CONTENTS + CONTENTS)
101
102        // Write with the previous OutputStream (simulate 2 OututStreams writing "concurrently")
103        out.write(NEW_CONTENTS.getBytes())
104        verifyContents(NEW_CONTENTS + CONTENTS + CONTENTS + NEW_CONTENTS)
105    }
106
107    void testCreateInputStream_NullContents() {
108        verifyContents("")
109    }
110
111    void testCloneWithNewPath() {
112        entry.lastModified = LAST_MODIFIED
113        entry.owner = USER
114        entry.group = GROUP
115        entry.permissions = PERMISSIONS
116        entry.setContents('abc')
117        def clone = entry.cloneWithNewPath(NEW_PATH)
118
119        assert !clone.is(entry)
120        assert clone.path == NEW_PATH
121        assert clone.lastModified == LAST_MODIFIED
122        assert clone.owner == USER
123        assert clone.group == GROUP
124        assert clone.permissions == PERMISSIONS
125        assert clone.createInputStream().text == 'abc'
126        assert !clone.directory
127    }
128
129    void testCloneWithNewPath_WriteToOutputStream() {
130        def outputStream = entry.createOutputStream(false)
131        outputStream.withWriter { writer -> writer.write('ABCDEF') }
132        def clone = entry.cloneWithNewPath(NEW_PATH)
133
134        assert !clone.is(entry)
135        assert clone.path == NEW_PATH
136        assert clone.createInputStream().text == 'ABCDEF'
137        assert !clone.directory
138    }
139
140//    void testEquals() {
141//        assert entry.equals(entry)
142//        assert entry.equals(new FileEntry(path:PATH, lastModified:LAST_MODIFIED))
143//        assert entry.equals(new FileEntry(path:PATH, lastModified:new Date())) // lastModified ignored
144//
145//        assert !entry.equals(new FileEntry("xyz", lastModified:LAST_MODIFIED))
146//        assert !entry.equals(new FileEntry(path:PATH, contents:'abc', lastModified:LAST_MODIFIED))
147//        assert !entry.equals("ABC")
148//        assert !entry.equals(null)
149//    }
150//
151//    void testHashCode() {
152//        assert entry.hashCode() == entry.hashCode()
153//        assert entry.hashCode() == new FileEntry(path:PATH, contents:'abc', lastModified:LAST_MODIFIED).hashCode()
154//        assert entry.hashCode() == new FileEntry(path:PATH, contents:'abc', new Date()).hashCode()  // lastModified ignored
155//
156//        assert entry.hashCode() != new FileEntry(path:PATH, contents:'abc', lastModified:LAST_MODIFIED).hashCode()
157//        assert entry.hashCode() != new FileEntry(path:PATH, contents:'abcdef', lastModified:LAST_MODIFIED).hashCode()
158//
159//        assert entry.hashCode() == new DirectoryEntry(path:PATH, lastModified:LAST_MODIFIED).hashCode()
160//    }
161
162    //-------------------------------------------------------------------------
163    // Implementation of Required Abstract Methods
164    //-------------------------------------------------------------------------
165
166    /**
167     * @see org.mockftpserver.fake.filesystem.AbstractFileSystemEntryTestCase#getImplementationClass()
168     */
169    protected Class getImplementationClass() {
170        return FileEntry.class
171    }
172
173    /**
174     * @see org.mockftpserver.fake.filesystem.AbstractFileSystemEntryTestCase#isDirectory()
175     */
176    protected boolean isDirectory() {
177        return false
178    }
179
180    //-------------------------------------------------------------------------
181    // Test setup
182    //-------------------------------------------------------------------------
183
184    void setUp() {
185        super.setUp()
186        entry = new FileEntry(PATH)
187    }
188
189    //-------------------------------------------------------------------------
190    // Internal Helper Methods
191    //-------------------------------------------------------------------------
192
193    /**
194     * Verify the expected contents of the file entry, read from its InputSteam
195     * @param expectedContents - the expected contents, as a String
196     * @throws IOException
197     */
198    private void verifyContents(String expectedContents) {
199        LOG.info("expectedContents=$expectedContents")
200        verifyContents(expectedContents.bytes)
201    }
202
203    /**
204     * Verify the expected contents of the file entry, read from its InputSteam
205     * @param expectedContents - the expected contents, as a byte[]
206     * @throws IOException
207     */
208    private void verifyContents(byte[] expectedContents) {
209        byte[] bytes = IoUtil.readBytes(entry.createInputStream())
210        def bytesAsList = bytes as List
211        LOG.info("bytes=$bytesAsList")
212        assert bytes == expectedContents, "actual=$bytesAsList  expected=${expectedContents as byte[]}"
213        assert entry.getSize() == expectedContents.length
214    }
215
216}
217