rlm@10: ; Copyright (c) Rich Hickey. All rights reserved. rlm@10: ; The use and distribution terms for this software are covered by the rlm@10: ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: ; which can be found in the file epl-v10.html at the root of this distribution. rlm@10: ; By using this software in any fashion, you are agreeing to be bound by rlm@10: ; the terms of this license. rlm@10: ; You must not remove this notice, or any other, from this software. rlm@10: rlm@10: (ns clojure.test-clojure.java.io rlm@10: (:use clojure.test clojure.java.io) rlm@10: (:import (java.io File BufferedInputStream rlm@10: FileInputStream InputStreamReader InputStream rlm@10: FileOutputStream OutputStreamWriter OutputStream rlm@10: ByteArrayInputStream ByteArrayOutputStream) rlm@10: (java.net URL URI Socket ServerSocket))) rlm@10: rlm@10: (defn temp-file rlm@10: [prefix suffix] rlm@10: (doto (File/createTempFile prefix suffix) rlm@10: (.deleteOnExit))) rlm@10: rlm@10: (deftest test-spit-and-slurp rlm@10: (let [f (temp-file "clojure.java.io" "test")] rlm@10: (spit f "foobar") rlm@10: (is (= "foobar" (slurp f))) rlm@10: (spit f "foobar" :encoding "UTF-16") rlm@10: (is (= "foobar" (slurp f :encoding "UTF-16"))) rlm@10: (testing "deprecated arity" rlm@10: (is (= rlm@10: "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).\n" rlm@10: (with-out-str rlm@10: (is (= "foobar" (slurp f "UTF-16"))))))))) rlm@10: rlm@10: (deftest test-streams-defaults rlm@10: (let [f (temp-file "clojure.java.io" "test-reader-writer") rlm@10: content "testing"] rlm@10: (try rlm@10: (is (thrown? Exception (reader (Object.)))) rlm@10: (is (thrown? Exception (writer (Object.)))) rlm@10: rlm@10: (are [write-to read-from] (= content (do rlm@10: (spit write-to content :encoding "UTF-8") rlm@10: (slurp read-from :encoding "UTF-8"))) rlm@10: f f rlm@10: (.getAbsolutePath f) (.getAbsolutePath f) rlm@10: (.toURL f) (.toURL f) rlm@10: (.toURI f) (.toURI f) rlm@10: (FileOutputStream. f) (FileInputStream. f) rlm@10: (OutputStreamWriter. (FileOutputStream. f) "UTF-8") (reader f :encoding "UTF-8") rlm@10: f (FileInputStream. f) rlm@10: (writer f :encoding "UTF-8") (InputStreamReader. (FileInputStream. f) "UTF-8")) rlm@10: rlm@10: (is (= content (slurp (.getBytes content "UTF-8")))) rlm@10: (is (= content (slurp (.toCharArray content)))) rlm@10: (finally rlm@10: (.delete f))))) rlm@10: rlm@10: (defn bytes-should-equal [byte-array-1 byte-array-2 msg] rlm@10: (is (= @#'clojure.java.io/byte-array-type (class byte-array-1) (class byte-array-2)) msg) rlm@10: (is (= (into [] byte-array-1) (into [] byte-array-2)) msg)) rlm@10: rlm@10: (defn data-fixture rlm@10: "in memory fixture data for tests" rlm@10: [encoding] rlm@10: (let [bs (.getBytes "hello" encoding) rlm@10: cs (.toCharArray "hello") rlm@10: i (ByteArrayInputStream. bs) rlm@10: r (InputStreamReader. i) rlm@10: o (ByteArrayOutputStream.) rlm@10: w (OutputStreamWriter. o)] rlm@10: {:bs bs rlm@10: :i i rlm@10: :r r rlm@10: :o o rlm@10: :s "hello" rlm@10: :cs cs rlm@10: :w w})) rlm@10: rlm@10: (deftest test-copy rlm@10: (dorun rlm@10: (for [{:keys [in out flush] :as test} rlm@10: [{:in :i :out :o} rlm@10: {:in :i :out :w} rlm@10: {:in :r :out :o} rlm@10: {:in :r :out :w} rlm@10: {:in :cs :out :o} rlm@10: {:in :cs :out :w} rlm@10: {:in :bs :out :o} rlm@10: {:in :bs :out :w}] rlm@10: rlm@10: opts rlm@10: [{} {:buffer-size 256}]] rlm@10: (let [{:keys [s o] :as d} (data-fixture "UTF-8")] rlm@10: (apply copy (in d) (out d) (flatten (vec opts))) rlm@10: #_(when (= out :w) (.flush (:w d))) rlm@10: (.flush (out d)) rlm@10: (bytes-should-equal (.getBytes s "UTF-8") rlm@10: (.toByteArray o) rlm@10: (str "combination " test opts)))))) rlm@10: rlm@10: (deftest test-copy-encodings rlm@10: (testing "from inputstream UTF-16 to writer UTF-8" rlm@10: (let [{:keys [i s o w bs]} (data-fixture "UTF-16")] rlm@10: (copy i w :encoding "UTF-16") rlm@10: (.flush w) rlm@10: (bytes-should-equal (.getBytes s "UTF-8") (.toByteArray o) ""))) rlm@10: (testing "from reader UTF-8 to output-stream UTF-16" rlm@10: (let [{:keys [r o s]} (data-fixture "UTF-8")] rlm@10: (copy r o :encoding "UTF-16") rlm@10: (bytes-should-equal (.getBytes s "UTF-16") (.toByteArray o) "")))) rlm@10: rlm@10: (deftest test-as-file rlm@10: (are [result input] (= result (as-file input)) rlm@10: (File. "foo") "foo" rlm@10: (File. "bar") (File. "bar") rlm@10: (File. "baz") (URL. "file:baz") rlm@10: (File. "quux") (URI. "file:quux") rlm@10: nil nil)) rlm@10: rlm@10: (deftest test-file rlm@10: (are [result args] (= (File. result) (apply file args)) rlm@10: "foo" ["foo"] rlm@10: "foo/bar" ["foo" "bar"] rlm@10: "foo/bar/baz" ["foo" "bar" "baz"])) rlm@10: (deftest test-as-url rlm@10: (are [file-part input] (= (URL. (str "file:" file-part)) (as-url input)) rlm@10: "foo" "file:foo" rlm@10: "baz" (URL. "file:baz") rlm@10: "quux" (URI. "file:quux")) rlm@10: (is (nil? (as-url nil)))) rlm@10: rlm@10: (deftest test-delete-file rlm@10: (let [file (temp-file "test" "deletion") rlm@10: not-file (File. (str (java.util.UUID/randomUUID)))] rlm@10: (delete-file (.getAbsolutePath file)) rlm@10: (is (not (.exists file))) rlm@10: (is (thrown? java.io.IOException (delete-file not-file))) rlm@10: (is (= :silently (delete-file not-file :silently))))) rlm@10: rlm@10: (deftest test-as-relative-path rlm@10: (testing "strings" rlm@10: (is (= "foo" (as-relative-path "foo")))) rlm@10: (testing "absolute path strings are forbidden" rlm@10: (is (thrown? IllegalArgumentException (as-relative-path (.getAbsolutePath (File. "baz")))))) rlm@10: (testing "relative File paths" rlm@10: (is (= "bar" (as-relative-path (File. "bar"))))) rlm@10: (testing "absolute File paths are forbidden" rlm@10: (is (thrown? IllegalArgumentException (as-relative-path (File. (.getAbsolutePath (File. "quux")))))))) rlm@10: rlm@10: (defn stream-should-have [stream expected-bytes msg] rlm@10: (let [actual-bytes (byte-array (alength expected-bytes))] rlm@10: (.read stream actual-bytes) rlm@10: (is (= -1 (.read stream)) (str msg " : should be end of stream")) rlm@10: (is (= (seq expected-bytes) (seq actual-bytes)) (str msg " : byte arrays should match")))) rlm@10: rlm@10: (deftest test-input-stream rlm@10: (let [file (temp-file "test-input-stream" "txt") rlm@10: bytes (.getBytes "foobar")] rlm@10: (spit file "foobar") rlm@10: (doseq [[expr msg] rlm@10: [[file File] rlm@10: [(FileInputStream. file) FileInputStream] rlm@10: [(BufferedInputStream. (FileInputStream. file)) BufferedInputStream] rlm@10: [(.. file toURI) URI] rlm@10: [(.. file toURI toURL) URL] rlm@10: [(.. file toURI toURL toString) "URL as String"] rlm@10: [(.. file toString) "File as String"]]] rlm@10: (with-open [s (input-stream expr)] rlm@10: (stream-should-have s bytes msg))))) rlm@10: rlm@10: (deftest test-streams-buffering rlm@10: (let [data (.getBytes "")] rlm@10: (is (instance? java.io.BufferedReader (reader data))) rlm@10: (is (instance? java.io.BufferedWriter (writer (java.io.ByteArrayOutputStream.)))) rlm@10: (is (instance? java.io.BufferedInputStream (input-stream data))) rlm@10: (is (instance? java.io.BufferedOutputStream (output-stream (java.io.ByteArrayOutputStream.)))))) rlm@10: rlm@10: (deftest test-resource rlm@10: (is (nil? (resource "non/existent/resource"))) rlm@10: (is (instance? URL (resource "clojure/core.clj"))) rlm@10: (let [file (temp-file "test-resource" "txt") rlm@10: url (as-url (.getParentFile file)) rlm@10: loader (java.net.URLClassLoader. (into-array [url]))] rlm@10: (is (nil? (resource "non/existent/resource" loader))) rlm@10: (is (instance? URL (resource (.getName file) loader))))) rlm@10: rlm@10: (deftest test-make-parents rlm@10: (let [tmp (System/getProperty "java.io.tmpdir")] rlm@10: (delete-file (file tmp "test-make-parents" "child" "grandchild") :silently) rlm@10: (delete-file (file tmp "test-make-parents" "child") :silently) rlm@10: (delete-file (file tmp "test-make-parents") :silently) rlm@10: (make-parents tmp "test-make-parents" "child" "grandchild") rlm@10: (is (.isDirectory (file tmp "test-make-parents" "child"))) rlm@10: (is (not (.isDirectory (file tmp "test-make-parents" "child" "grandchild")))) rlm@10: (delete-file (file tmp "test-make-parents" "child")) rlm@10: (delete-file (file tmp "test-make-parents")))) rlm@10: rlm@10: (deftest test-socket-iofactory rlm@10: (let [port 65321 rlm@10: server-socket (ServerSocket. port) rlm@10: client-socket (Socket. "localhost" port)] rlm@10: (try rlm@10: (is (instance? InputStream (input-stream client-socket))) rlm@10: (is (instance? OutputStream (output-stream client-socket))) rlm@10: (finally (.close server-socket) rlm@10: (.close client-socket)))))