001    /*
002     * Created on Dec 23, 2007
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2007-2009 the original author or authors.
014     */
015    package org.fest.assertions;
016    
017    import static org.fest.assertions.Formatting.inBrackets;
018    import static org.fest.util.Arrays.isEmpty;
019    import static org.fest.util.Strings.concat;
020    import static org.fest.util.Systems.LINE_SEPARATOR;
021    
022    import java.io.File;
023    import java.io.IOException;
024    
025    import org.fest.assertions.FileContentComparator.LineDiff;
026    
027    /**
028     * Understands assertion methods for <code>File</code>. To create a new instance of this class use the method <code>
029     * {@link Assertions#assertThat(File)}</code>.
030     *
031     * @author David DIDIER
032     * @author Yvonne Wang
033     * @author Alex Ruiz
034     */
035    public class FileAssert extends GenericAssert<File> {
036    
037      private final FileContentComparator comparator;
038    
039      /**
040       * Creates a new <code>FileAssert</code>.
041       * @param actual the target to verify.
042       */
043      protected FileAssert(File actual) {
044        this(actual, new FileContentComparator());
045      }
046    
047      /* for testing only */
048      FileAssert(File actual, FileContentComparator comparator) {
049        super(actual);
050        this.comparator = comparator;
051      }
052    
053      /** {@inheritDoc} */
054      public FileAssert as(String description) {
055        description(description);
056        return this;
057      }
058    
059      /** {@inheritDoc} */
060      public FileAssert describedAs(String description) {
061        return as(description);
062      }
063    
064      /** {@inheritDoc} */
065      public FileAssert as(Description description) {
066        description(description);
067        return this;
068      }
069    
070      /** {@inheritDoc} */
071      public FileAssert describedAs(Description description) {
072        return as(description);
073      }
074    
075      /**
076       * Verifies that the actual <code>File</code> does not exist.
077       * @return this assertion object.
078       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
079       * @throws AssertionError if the actual <code>File</code> exists.
080       */
081      public FileAssert doesNotExist() {
082        isNotNull();
083        if (!actual.exists()) return this;
084        failIfCustomMessageIsSet();
085        throw failure(concat("file:", inBrackets(actual), " should not exist"));
086      }
087    
088      /**
089       * Verifies that the actual <code>File</code> does exist.
090       * @return this assertion object.
091       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
092       * @throws AssertionError if the actual <code>File</code> does not exist.
093       */
094      public FileAssert exists() {
095        isNotNull();
096        assertExists(actual);
097        return this;
098      }
099    
100      /**
101       * Verifies that the size of the actual <code>File</code> is equal to the given one.
102       * @param expected the expected size of the actual <code>File</code>.
103       * @return this assertion object.
104       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
105       * @throws AssertionError if the size of the actual <code>File</code> is not equal to the given one.
106       */
107      public FileAssert hasSize(long expected) {
108        isNotNull();
109        long size = actual.length();
110        if (size == expected) return this;
111        failIfCustomMessageIsSet();
112        throw failure(concat(
113              "size of file:", inBrackets(actual), " expected:", inBrackets(expected), " but was:", inBrackets(size)));
114      }
115    
116      /**
117       * Verifies that the actual <code>File</code> is a directory.
118       * @return this assertion object.
119       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
120       * @throws AssertionError if the actual <code>File</code> is not a directory.
121       */
122      public FileAssert isDirectory() {
123        isNotNull();
124        if (actual.isDirectory()) return this;
125        failIfCustomMessageIsSet();
126        throw failure(concat("file:", inBrackets(actual), " should be a directory"));
127      }
128    
129      /**
130       * Verifies that the actual <code>File</code> is equal to the given one. To verify that the actual <code>File</code>
131       * has the same content as another <code>File</code>, use <code>{@link #hasSameContentAs(File)}</code>.
132       * @param expected the given <code>File</code> to compare the actual <code>File</code> to.
133       * @return this assertion object.
134       * @throws AssertionError if the actual <code>File</code> is not equal to the given one.
135       */
136      public FileAssert isEqualTo(File expected) {
137        assertEqualTo(expected);
138        return this;
139      }
140    
141      /**
142       * Verifies that the actual <code>File</code> is a regular file.
143       * @return this assertion object.
144       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
145       * @throws AssertionError if the actual <code>File</code> is not a regular file.
146       */
147      public FileAssert isFile() {
148        isNotNull();
149        if (actual.isFile()) return this;
150        failIfCustomMessageIsSet();
151        throw failure(concat("file:", inBrackets(actual), " should be a file"));
152      }
153    
154      /**
155       * Verifies that the actual <code>File</code> is not equal to the given one.
156       * @param other the given <code>File</code> to compare the actual <code>File</code> to.
157       * @return this assertion object.
158       * @throws AssertionError if the actual <code>File</code> is equal to the given one.
159       */
160      public FileAssert isNotEqualTo(File other) {
161        assertNotEqualTo(other);
162        return this;
163      }
164    
165      /**
166       * Verifies that the actual <code>File</code> is not <code>null</code>.
167       * @return this assertion object.
168       * @throws AssertionError if the actual <code>File</code> is <code>null</code>.
169       */
170      public FileAssert isNotNull() {
171        assertNotNull();
172        return this;
173      }
174    
175      /**
176       * Verifies that the actual <code>File</code> is not the same as the given one.
177       * @param other the given <code>File</code> to compare the actual <code>File</code> to.
178       * @return this assertion object.
179       * @throws AssertionError if the actual <code>File</code> is the same as the given one.
180       */
181      public FileAssert isNotSameAs(File other) {
182        assertNotSameAs(other);
183        return this;
184      }
185    
186      /**
187       * Verifies that the actual <code>File</code> is the same as the given one.
188       * @param expected the given <code>File</code> to compare the actual <code>File</code> to.
189       * @return this assertion object.
190       * @throws AssertionError if the actual <code>File</code> is not the same as the given one.
191       */
192      public FileAssert isSameAs(File expected) {
193        assertSameAs(expected);
194        return this;
195      }
196    
197      /**
198       * Verifies that the actual <code>File</code> satisfies the given condition.
199       * @param condition the given condition.
200       * @return this assertion object.
201       * @throws NullPointerException if the given condition is <code>null</code>.
202       * @throws AssertionError if the actual <code>File</code> does not satisfy the given condition.
203       * @see #is(Condition)
204       */
205      public FileAssert satisfies(Condition<File> condition) {
206        assertSatisfies(condition);
207        return this;
208      }
209    
210      /**
211       * Verifies that the actual <code>File</code> does not satisfy the given condition.
212       * @param condition the given condition.
213       * @return this assertion object.
214       * @throws AssertionError if the actual <code>File</code> satisfies the given condition.
215       * @throws NullPointerException if the given condition is <code>null</code>.
216       * @see #isNot(Condition)
217       */
218      public FileAssert doesNotSatisfy(Condition<File> condition) {
219        assertDoesNotSatisfy(condition);
220        return this;
221      }
222    
223    
224      /**
225       * Verifies that the actual <code>File</code> satisfies the given condition.
226       * @param condition the given condition.
227       * @return this assertion object.
228       * @throws NullPointerException if the given condition is <code>null</code>.
229       * @throws AssertionError if the actual <code>File</code> does not satisfy the given condition.
230       */
231      public FileAssert is(Condition<File> condition) {
232        assertIs(condition);
233        return this;
234      }
235    
236      /**
237       * Verifies that the actual <code>File</code> does not satisfy the given condition.
238       * @param condition the given condition.
239       * @return this assertion object.
240       * @throws AssertionError if the actual <code>File</code> satisfies the given condition.
241       * @throws NullPointerException if the given condition is <code>null</code>.
242       */
243      public FileAssert isNot(Condition<File> condition) {
244        assertIsNot(condition);
245        return this;
246      }
247    
248      /**
249       * Verifies that the content of the actual <code>File</code> is equal to the content of the given one. Adapted from
250       * <a href="http://junit-addons.sourceforge.net/junitx/framework/FileAssert.html" target="_blank">FileAssert</a> (from
251       * <a href="http://sourceforge.net/projects/junit-addons">JUnit-addons</a>.)
252       * @param expected the given <code>File</code> to compare the actual <code>File</code> to.
253       * @return this assertion object.
254       * @throws NullPointerException if the file to compare to is <code>null</code>.
255       * @throws AssertionError if the the actual <code>File</code> is <code>null</code>.
256       * @throws AssertionError if the content of the actual <code>File</code> is not equal to the content of the given one.
257       */
258      public FileAssert hasSameContentAs(File expected) {
259        if (expected == null)
260          throw new NullPointerException(formattedErrorMessage("File to compare to should not be null"));
261        isNotNull();
262        assertExists(actual).assertExists(expected);
263        try {
264          LineDiff[] diffs = comparator.compareContents(actual, expected);
265          if (!isEmpty(diffs)) fail(expected, diffs);
266        } catch (IOException e) {
267          cannotCompareToExpectedFile(expected, e);
268        }
269        return this;
270      }
271    
272      private void fail(File expected, LineDiff[] diffs) {
273        failIfCustomMessageIsSet();
274        StringBuilder b = new StringBuilder();
275        b.append("file:").append(inBrackets(actual)).append(" and file:").append(inBrackets(expected))
276          .append(" do not have same contents:");
277        for (LineDiff diff : diffs) {
278          b.append(LINE_SEPARATOR).append("line:").append(inBrackets(diff.lineNumber))
279            .append(", expected:").append(inBrackets(diff.expected)).append(" but was:").append(inBrackets(diff.actual));
280        }
281        fail(b.toString());
282      }
283    
284      private void cannotCompareToExpectedFile(File expected, Exception e) {
285        failIfCustomMessageIsSet(e);
286        String message = concat(
287            "unable to compare contents of files:", inBrackets(actual), " and ", inBrackets(expected));
288        fail(message, e);
289      }
290    
291      private FileAssert assertExists(File file) {
292        if (file.exists()) return this;
293        failIfCustomMessageIsSet();
294        throw failure(concat("file:", inBrackets(file), " should exist"));
295      }
296    
297      /**
298       * Verifies that the actual <code>File</code> is a relative path.
299       * @return this assertion object.
300       * @throws AssertionError if the actual <code>File</code> is not a relative path.
301       */
302      public FileAssert isRelative() {
303        isNotNull();
304        if (!actual.isAbsolute()) return this;
305        failIfCustomMessageIsSet();
306        throw failure(concat("file:", inBrackets(actual), " should be a relative path"));
307      }
308    
309      /**
310       * Verifies that the actual <code>File</code> is an absolute path.
311       * @return this assertion object.
312       * @throws AssertionError if the actual <code>File</code> is not an absolute path.
313       */
314      public FileAssert isAbsolute() {
315        isNotNull();
316        if (actual.isAbsolute()) return this;
317        failIfCustomMessageIsSet();
318        throw failure(concat("file:", inBrackets(actual), " should be an absolute path"));
319      }
320    
321      /** {@inheritDoc} */
322      public FileAssert overridingErrorMessage(String message) {
323        replaceDefaultErrorMessagesWith(message);
324        return this;
325      }
326    }