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-2011 the original author or authors.
014     */
015    package org.fest.assertions;
016    
017    import static org.fest.assertions.Formatting.*;
018    import static org.fest.util.Arrays.isEmpty;
019    import static org.fest.util.Systems.LINE_SEPARATOR;
020    
021    import java.io.File;
022    import java.io.IOException;
023    
024    import org.fest.assertions.FileContentComparator.LineDiff;
025    
026    /**
027     * Assertions for <code>{@link File}</code>.
028     * <p>
029     * To create a new instance of this class invoke <code>{@link Assertions#assertThat(File)}</code>.
030     * </p>
031     *
032     * @author David DIDIER
033     * @author Yvonne Wang
034     * @author Alex Ruiz
035     */
036    public class FileAssert extends GenericAssert<FileAssert, File> {
037    
038      private final FileContentComparator comparator;
039    
040      /**
041       * Creates a new <code>FileAssert</code>.
042       * @param actual the target to verify.
043       */
044      protected FileAssert(File actual) {
045        this(actual, new FileContentComparator());
046      }
047    
048      /* for testing only */
049      FileAssert(File actual, FileContentComparator comparator) {
050        super(FileAssert.class, actual);
051        this.comparator = comparator;
052      }
053    
054      /**
055       * Verifies that the actual {@code File} does not exist.
056       * @return this assertion object.
057       * @throws AssertionError if the the actual {@code File} is {@code null}.
058       * @throws AssertionError if the actual {@code File} exists.
059       */
060      public FileAssert doesNotExist() {
061        isNotNull();
062        if (!actual.exists()) return this;
063        failIfCustomMessageIsSet();
064        throw failure(format("file:<%s> should not exist", actual));
065      }
066    
067      /**
068       * Verifies that the actual {@code File} does exist.
069       * @return this assertion object.
070       * @throws AssertionError if the the actual {@code File} is {@code null}.
071       * @throws AssertionError if the actual {@code File} does not exist.
072       */
073      public FileAssert exists() {
074        isNotNull();
075        assertExists(actual);
076        return this;
077      }
078    
079      /**
080       * Verifies that the size of the actual {@code File} is equal to the given one.
081       * @param expected the expected size of the actual {@code File}.
082       * @return this assertion object.
083       * @throws AssertionError if the the actual {@code File} is {@code null}.
084       * @throws AssertionError if the size of the actual {@code File} is not equal to the given one.
085       */
086      public FileAssert hasSize(long expected) {
087        isNotNull();
088        long size = actual.length();
089        if (size == expected) return this;
090        failIfCustomMessageIsSet();
091        throw failure(format("size of file:<%s> expected:<%s> but was:<%s>", actual, expected, size));
092      }
093    
094      /**
095       * Verifies that the actual {@code File} is a directory.
096       * @return this assertion object.
097       * @throws AssertionError if the the actual {@code File} is {@code null}.
098       * @throws AssertionError if the actual {@code File} is not a directory.
099       */
100      public FileAssert isDirectory() {
101        isNotNull();
102        if (actual.isDirectory()) return this;
103        failIfCustomMessageIsSet();
104        throw failure(format("file:<%s> should be a directory", actual));
105      }
106    
107      /**
108       * Verifies that the actual {@code File} is a regular file.
109       * @return this assertion object.
110       * @throws AssertionError if the the actual {@code File} is {@code null}.
111       * @throws AssertionError if the actual {@code File} is not a regular file.
112       */
113      public FileAssert isFile() {
114        isNotNull();
115        if (actual.isFile()) return this;
116        failIfCustomMessageIsSet();
117        throw failure(format("file:<%s> should be a file", actual));
118      }
119    
120      /**
121       * Verifies that the content of the actual {@code File} is equal to the content of the given one. Adapted from
122       * <a href="http://junit-addons.sourceforge.net/junitx/framework/FileAssert.html" target="_blank">FileAssert</a> (from
123       * <a href="http://sourceforge.net/projects/junit-addons">JUnit-addons</a>.)
124       * @param expected the given {@code File} to compare the actual {@code File} to.
125       * @return this assertion object.
126       * @throws NullPointerException if the file to compare to is {@code null}.
127       * @throws AssertionError if the the actual {@code File} is {@code null}.
128       * @throws AssertionError if the content of the actual {@code File} is not equal to the content of the given one.
129       */
130      public FileAssert hasSameContentAs(File expected) {
131        if (expected == null) throw new NullPointerException(formattedErrorMessage("File to compare to should not be null"));
132        isNotNull();
133        assertExists(actual).assertExists(expected);
134        try {
135          LineDiff[] diffs = comparator.compareContents(actual, expected);
136          if (!isEmpty(diffs)) fail(expected, diffs);
137        } catch (IOException e) {
138          cannotCompareToExpectedFile(expected, e);
139        }
140        return this;
141      }
142    
143      private void fail(File expected, LineDiff[] diffs) {
144        failIfCustomMessageIsSet();
145        StringBuilder b = new StringBuilder();
146        b.append("file:").append(inBrackets(actual)).append(" and file:").append(inBrackets(expected))
147          .append(" do not have same contents:");
148        for (LineDiff diff : diffs) {
149          b.append(LINE_SEPARATOR).append("line:").append(inBrackets(diff.lineNumber))
150            .append(", expected:").append(inBrackets(diff.expected)).append(" but was:").append(inBrackets(diff.actual));
151        }
152        fail(b.toString());
153      }
154    
155      private void cannotCompareToExpectedFile(File expected, Exception e) {
156        failIfCustomMessageIsSet(e);
157        String message = format("unable to compare contents of files:<%s> and <%s>", actual, expected);
158        fail(message, e);
159      }
160    
161      private FileAssert assertExists(File file) {
162        if (file.exists()) return this;
163        failIfCustomMessageIsSet();
164        throw failure(format("file:<%s> should exist", file));
165      }
166    
167      /**
168       * Verifies that the actual {@code File} is a relative path.
169       * @return this assertion object.
170       * @throws AssertionError if the actual {@code File} is not a relative path.
171       */
172      public FileAssert isRelative() {
173        isNotNull();
174        if (!actual.isAbsolute()) return this;
175        failIfCustomMessageIsSet();
176        throw failure(format("file:<%s> should be a relative path", actual));
177      }
178    
179      /**
180       * Verifies that the actual {@code File} is an absolute path.
181       * @return this assertion object.
182       * @throws AssertionError if the actual {@code File} is not an absolute path.
183       */
184      public FileAssert isAbsolute() {
185        isNotNull();
186        if (actual.isAbsolute()) return this;
187        failIfCustomMessageIsSet();
188        throw failure(format("file:<%s> should be an absolute path", actual));
189      }
190    }