diff options
author | Stuart Halloway <stu@thinkrelevance.com> | 2010-05-11 11:56:21 -0400 |
---|---|---|
committer | Stuart Halloway <stu@thinkrelevance.com> | 2010-05-20 21:25:19 -0400 |
commit | cd8fc7c11213fbe99355bc8d27455b01d8d50c82 (patch) | |
tree | b50a7ba970a0f0af350266b64c0ad7fda366ac9e | |
parent | 4f729ba2432d8ffbe7c2f74f680b472e528cba4c (diff) |
promote clojure.contrib.io to clojure.java.io (with api changes)
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
-rw-r--r-- | src/clj/clojure/core.clj | 50 | ||||
-rw-r--r-- | src/clj/clojure/java/io.clj | 429 | ||||
-rw-r--r-- | test/clojure/test_clojure.clj | 1 | ||||
-rw-r--r-- | test/clojure/test_clojure/java/io.clj | 185 | ||||
-rw-r--r-- | test/clojure/test_clojure/metadata.clj | 3 |
5 files changed, 650 insertions, 18 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 4c466c56..0a2a39ae 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -3918,23 +3918,6 @@ {:added "1.0"} [v] (instance? clojure.lang.Var v)) -(defn slurp - "Reads the file named by f using the encoding enc into a string - and returns it." - {:added "1.0"} - ([f] (slurp f (.name (java.nio.charset.Charset/defaultCharset)))) - ([^String f ^String enc] - (with-open [r (new java.io.BufferedReader - (new java.io.InputStreamReader - (new java.io.FileInputStream f) enc))] - (let [sb (new StringBuilder)] - (loop [c (.read r)] - (if (neg? c) - (str sb) - (do - (.append sb (char c)) - (recur (.read r))))))))) - (defn subs "Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive." @@ -5338,6 +5321,39 @@ (let [s (seq coll)] (clojure.core.protocols/internal-reduce s f val)))) +(require '[clojure.java.io :as jio]) + +(defn- normalize-slurp-opts + [opts] + (if (string? (first opts)) + (do + (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") + [:encoding (first opts)]) + opts)) + +(defn slurp + "Reads the file named by f using the encoding enc into a string + and returns it." + {:added "1.0"} + ([f & opts] + (let [opts (normalize-slurp-opts opts) + sb (StringBuilder.)] + (with-open [#^java.io.Reader r (apply jio/reader f opts)] + (loop [c (.read r)] + (if (neg? c) + (str sb) + (do + (.append sb (char c)) + (recur (.read r))))))))) + +(defn spit + "Opposite of slurp. Opens f with writer, writes content, then + closes f." + {:added "1.2"} + [f content & options] + (with-open [#^java.io.Writer w (apply jio/writer f options)] + (.write w content))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; (defn future-call "Takes a function of no args and yields a future object that will diff --git a/src/clj/clojure/java/io.clj b/src/clj/clojure/java/io.clj new file mode 100644 index 00000000..bed18bc9 --- /dev/null +++ b/src/clj/clojure/java/io.clj @@ -0,0 +1,429 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns + ^{:author "Stuart Sierra, Chas Emerick, Stuart Halloway", + :doc "This file defines polymorphic I/O utility functions for Clojure."} + clojure.java.io + (:import + (java.io Reader InputStream InputStreamReader PushbackReader + BufferedReader File OutputStream + OutputStreamWriter BufferedWriter Writer + FileInputStream FileOutputStream ByteArrayOutputStream + StringReader ByteArrayInputStream + BufferedInputStream BufferedOutputStream + CharArrayReader Closeable) + (java.net URI URL MalformedURLException Socket))) + +(def + ^{:doc "Type object for a Java primitive byte array." + :private true + } + byte-array-type (class (make-array Byte/TYPE 0))) + +(def + ^{:doc "Type object for a Java primitive char array." + :private true} + char-array-type (class (make-array Character/TYPE 0))) + +(defprotocol ^{:added "1.2"} Coercions + "Coerce between various 'resource-namish' things." + (as-file [x] "Coerce argument to a file.") + (as-url [x] "Coerce argument to a URL.")) + +(extend-protocol Coercions + nil + (as-file [_] nil) + (as-url [_] nil) + + String + (as-file [s] (File. s)) + (as-url [s] (URL. s)) + + File + (as-file [f] f) + (as-url [f] (.toURL f)) + + URL + (as-url [u] u) + (as-file [u] + (if (= "file" (.getProtocol u)) + (as-file (.getPath u)) + (throw (IllegalArgumentException. "Not a file: " u)))) + + URI + (as-url [u] (.toURL u)) + (as-file [u] (as-file (as-url u)))) + +(defprotocol IOFactory + (make-reader [x opts]) + (make-writer [x opts]) + (make-input-stream [x opts]) + (make-output-stream [x opts])) + +(defn ^Reader reader + "Attempts to coerce its argument into an open java.io.Reader. + The default implementations of this protocol always return a + java.io.BufferedReader. + + Default implementations are provided for Reader, BufferedReader, + InputStream, File, URI, URL, Socket, byte arrays, character arrays, + and String. + + If argument is a String, it tries to resolve it first as a URI, then + as a local file name. URIs with a 'file' protocol are converted to + local file names. + + Should be used inside with-open to ensure the Reader is properly + closed." + {:added "1.2"} + [x & opts] + (make-reader x (when opts (apply hash-map opts)))) + +(defn ^Writer writer + "Attempts to coerce its argument into an open java.io.Writer. + The default implementations of this protocol always return a + java.io.BufferedWriter. + + Default implementations are provided for Writer, BufferedWriter, + OutputStream, File, URI, URL, Socket, and String. + + If the argument is a String, it tries to resolve it first as a URI, then + as a local file name. URIs with a 'file' protocol are converted to + local file names. + + Should be used inside with-open to ensure the Writer is properly + closed." + {:added "1.2"} + [x & opts] + (make-writer x (when opts (apply hash-map opts)))) + +(defn ^InputStream input-stream + "Attempts to coerce its argument into an open java.io.InputStream. + The default implementations of this protocol always return a + java.io.BufferedInputStream. + + Default implementations are defined for OutputStream, File, URI, URL, + Socket, byte array, and String arguments. + + If the argument is a String, it tries to resolve it first as a URI, then + as a local file name. URIs with a 'file' protocol are converted to + local file names. + + Should be used inside with-open to ensure the InputStream is properly + closed." + {:added "1.2"} + [x & opts] + (make-input-stream x (when opts (apply hash-map opts)))) + +(defn ^OutputStream output-stream + "Attempts to coerce its argument into an open java.io.OutputStream. + The default implementations of this protocol always return a + java.io.BufferedOutputStream. + + Default implementations are defined for OutputStream, File, URI, URL, + Socket, and String arguments. + + If the argument is a String, it tries to resolve it first as a URI, then + as a local file name. URIs with a 'file' protocol are converted to + local file names. + + Should be used inside with-open to ensure the OutputStream is + properly closed." + {:added "1.2"} + [x & opts] + (make-output-stream x (when opts (apply hash-map opts)))) + +(defn- ^Boolean append? [opts] + (boolean (:append opts))) + +(defn- ^String encoding [opts] + (or (:encoding opts) "UTF-8")) + +(defn- buffer-size [opts] + (or (:buffer-size opts) 1024)) + +(def default-streams-impl + {:make-reader (fn [x opts] (make-reader (make-input-stream x opts) opts)) + :make-writer (fn [x opts] (make-writer (make-output-stream x opts) opts)) + :make-input-stream (fn [x opts] + (throw (IllegalArgumentException. + (str "Cannot open <" (pr-str x) "> as an InputStream.")))) + :make-output-stream (fn [x opts] + (throw (IllegalArgumentException. + (str "Cannot open <" (pr-str x) "> as an OutputStream."))))}) + +(defn- inputstream->reader + [^InputStream is opts] + (make-reader (InputStreamReader. is (encoding opts)) opts)) + +(defn- outputstream->writer + [^OutputStream os opts] + (make-writer (OutputStreamWriter. os (encoding opts)) opts)) + +(extend BufferedInputStream + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [x opts] x) + :make-reader inputstream->reader)) + +(extend InputStream + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [x opts] (BufferedInputStream. x)) + :make-reader inputstream->reader)) + +(extend Reader + IOFactory + (assoc default-streams-impl + :make-reader (fn [x opts] (BufferedReader. x)))) + +(extend BufferedReader + IOFactory + (assoc default-streams-impl + :make-reader (fn [x opts] x))) + +(extend Writer + IOFactory + (assoc default-streams-impl + :make-writer (fn [x opts] (BufferedWriter. x)))) + +(extend BufferedWriter + IOFactory + (assoc default-streams-impl + :make-writer (fn [x opts] x))) + +(extend OutputStream + IOFactory + (assoc default-streams-impl + :make-output-stream (fn [x opts] (BufferedOutputStream. x)) + :make-writer outputstream->writer)) + +(extend BufferedOutputStream + IOFactory + (assoc default-streams-impl + :make-output-stream (fn [x opts] x) + :make-writer outputstream->writer)) + +(extend File + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [^File x opts] (make-input-stream (FileInputStream. x) opts)) + :make-output-stream (fn [^File x opts] (make-output-stream (FileOutputStream. x (append? opts)) opts)))) + +(extend URL + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [^URL x opts] + (make-input-stream + (if (= "file" (.getProtocol x)) + (FileInputStream. (.getPath x)) + (.openStream x)) opts)) + :make-output-stream (fn [^URL x opts] + (if (= "file" (.getProtocol x)) + (make-output-stream (File. (.getPath x)) opts) + (throw (IllegalArgumentException. (str "Can not write to non-file URL <" x ">"))))))) + +(extend URI + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [^URI x opts] (make-input-stream (.toURL x) opts)) + :make-output-stream (fn [^URI x opts] (make-output-stream (.toURL x) opts)))) + +(extend String + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [^String x opts] + (try + (make-input-stream (URL. x) opts) + (catch MalformedURLException e + (make-input-stream (File. x) opts)))) + :make-output-stream (fn [^String x opts] + (try + (make-output-stream (URL. x) opts) + (catch MalformedURLException err + (make-output-stream (File. x) opts)))))) + +(extend Socket + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [^Socket x opts] (.getInputStream x)) + :output-stream (fn [^Socket x opts] (output-stream (.getOutputStream x) opts)))) + +(extend byte-array-type + IOFactory + (assoc default-streams-impl + :make-input-stream (fn [x opts] (make-input-stream (ByteArrayInputStream. x) opts)))) + +(extend char-array-type + IOFactory + (assoc default-streams-impl + :make-reader (fn [x opts] (make-reader (CharArrayReader. x) opts)))) + +(extend Object + IOFactory + default-streams-impl) + +(defmulti + #^{:doc "Internal helper for copy" + :private true + :arglists '([input output opts])} + do-copy + (fn [input output opts] [(type input) (type output)])) + +(defmethod do-copy [InputStream OutputStream] [#^InputStream input #^OutputStream output opts] + (let [buffer (make-array Byte/TYPE (buffer-size opts))] + (loop [] + (let [size (.read input buffer)] + (when (pos? size) + (do (.write output buffer 0 size) + (recur))))))) + +(defmethod do-copy [InputStream Writer] [#^InputStream input #^Writer output opts] + (let [#^"[B" buffer (make-array Byte/TYPE (buffer-size opts))] + (loop [] + (let [size (.read input buffer)] + (when (pos? size) + (let [chars (.toCharArray (String. buffer 0 size (encoding opts)))] + (do (.write output chars) + (recur)))))))) + +(defmethod do-copy [InputStream File] [#^InputStream input #^File output opts] + (with-open [out (FileOutputStream. output)] + (do-copy input out opts))) + +(defmethod do-copy [Reader OutputStream] [#^Reader input #^OutputStream output opts] + (let [#^"[C" buffer (make-array Character/TYPE (buffer-size opts))] + (loop [] + (let [size (.read input buffer)] + (when (pos? size) + (let [bytes (.getBytes (String. buffer 0 size) (encoding opts))] + (do (.write output bytes) + (recur)))))))) + +(defmethod do-copy [Reader Writer] [#^Reader input #^Writer output opts] + (let [#^"[C" buffer (make-array Character/TYPE (buffer-size opts))] + (loop [] + (let [size (.read input buffer)] + (when (pos? size) + (do (.write output buffer 0 size) + (recur))))))) + +(defmethod do-copy [Reader File] [#^Reader input #^File output opts] + (with-open [out (FileOutputStream. output)] + (do-copy input out opts))) + +(defmethod do-copy [File OutputStream] [#^File input #^OutputStream output opts] + (with-open [in (FileInputStream. input)] + (do-copy in output opts))) + +(defmethod do-copy [File Writer] [#^File input #^Writer output opts] + (with-open [in (FileInputStream. input)] + (do-copy in output opts))) + +(defmethod do-copy [File File] [#^File input #^File output opts] + (with-open [in (FileInputStream. input) + out (FileOutputStream. output)] + (do-copy in out opts))) + +(defmethod do-copy [String OutputStream] [#^String input #^OutputStream output opts] + (do-copy (StringReader. input) output opts)) + +(defmethod do-copy [String Writer] [#^String input #^Writer output opts] + (do-copy (StringReader. input) output opts)) + +(defmethod do-copy [String File] [#^String input #^File output opts] + (do-copy (StringReader. input) output opts)) + +(defmethod do-copy [char-array-type OutputStream] [input #^OutputStream output opts] + (do-copy (CharArrayReader. input) output opts)) + +(defmethod do-copy [char-array-type Writer] [input #^Writer output opts] + (do-copy (CharArrayReader. input) output opts)) + +(defmethod do-copy [char-array-type File] [input #^File output opts] + (do-copy (CharArrayReader. input) output opts)) + +(defmethod do-copy [byte-array-type OutputStream] [#^"[B" input #^OutputStream output opts] + (do-copy (ByteArrayInputStream. input) output opts)) + +(defmethod do-copy [byte-array-type Writer] [#^"[B" input #^Writer output opts] + (do-copy (ByteArrayInputStream. input) output opts)) + +(defmethod do-copy [byte-array-type File] [#^"[B" input #^Writer output opts] + (do-copy (ByteArrayInputStream. input) output opts)) + +(defn copy + "Copies input to output. Returns nil or throws IOException. + Input may be an InputStream, Reader, File, byte[], or String. + Output may be an OutputStream, Writer, or File. + + Options are key/value pairs and may be one of + + :buffer-size buffer size to use, default is 1024. + :encoding encoding to use if converting between + byte and char streams. + + Does not close any streams except those it opens itself + (on a File)." + {:added "1.2"} + [input output & opts] + (do-copy input output (when opts (apply hash-map opts)))) + +(defn ^String as-relative-path + "Take an as-file-able thing and return a string if it is + a relative path, else IllegalArgumentException." + {:added "1.2"} + [x] + (let [^File f (as-file x)] + (if (.isAbsolute f) + (throw (IllegalArgumentException. (str f " is not a relative path"))) + (.getPath f)))) + +(defn ^File file + "Returns a java.io.File from string or file args." + {:added "1.2"} + ([arg] + (as-file arg)) + ([parent child] + (File. ^File (as-file parent) ^String (as-relative-path child))) + ([parent child & more] + (reduce file (file parent child) more))) + +(defn delete-file + "Delete file f. Raise an exception if it fails unless silently is true." + {:added "1.2"} + [f & [silently]] + (or (.delete (file f)) + silently + (throw (java.io.IOException. (str "Couldn't delete " f))))) + +(defn delete-file-recursively + "Delete file f. If it's a directory, recursively delete all its contents. + Raise an exception if any deletion fails unless silently is true." + {:added "1.2"} + [f & [silently]] + (let [f (file f)] + (if (.isDirectory f) + (doseq [child (.listFiles f)] + (delete-file-recursively child silently))) + (delete-file f silently))) + +(defn make-parents + "Create all parent directories of file. Pass extra args + as you would to file." + {:added "1.2"} + [f & more] + (.mkdirs (.getParentFile ^File (apply file f more)))) + +(defn ^URL resource + "Returns the URL for a named resource. Use the context class loader + if no loader is specified." + {:added "1.2"} + ([n] (resource n (.getContextClassLoader (Thread/currentThread)))) + ([n ^ClassLoader loader] (.getResource loader n))) diff --git a/test/clojure/test_clojure.clj b/test/clojure/test_clojure.clj index 9dd0bde2..9bde9009 100644 --- a/test/clojure/test_clojure.clj +++ b/test/clojure/test_clojure.clj @@ -57,6 +57,7 @@ :serialization :rt :repl + :java.io ]) (def test-namespaces diff --git a/test/clojure/test_clojure/java/io.clj b/test/clojure/test_clojure/java/io.clj new file mode 100644 index 00000000..b42d26db --- /dev/null +++ b/test/clojure/test_clojure/java/io.clj @@ -0,0 +1,185 @@ +(ns clojure.test-clojure.java.io + (:use clojure.test clojure.java.io) + (:import (java.io File FileInputStream BufferedInputStream + FileOutputStream OutputStreamWriter InputStreamReader + ByteArrayInputStream ByteArrayOutputStream) + (java.net URL URI))) + +(defn temp-file + [prefix suffix] + (doto (File/createTempFile prefix suffix) + (.deleteOnExit))) + +(deftest test-spit-and-slurp + (let [f (temp-file "clojure.contrib" "text")] + (spit f "foobar") + (is (= "foobar" (slurp f))) + (spit f "foobar" :encoding "UTF-16") + (is (= "foobar" (slurp f :encoding "UTF-16"))) + (testing "deprecated arity" + (is (= + "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).\n" + (with-out-str + (is (= "foobar" (slurp f "UTF-16"))))))))) + +(deftest test-streams-defaults + (let [f (temp-file "clojure.contrib" "test-reader-writer") + content "testing"] + (try + (is (thrown? Exception (reader (Object.)))) + (is (thrown? Exception (writer (Object.)))) + + (are [write-to read-from] (= content (do + (spit write-to content :encoding "UTF-8") + (slurp read-from :encoding "UTF-8"))) + f f + (.getAbsolutePath f) (.getAbsolutePath f) + (.toURL f) (.toURL f) + (.toURI f) (.toURI f) + (FileOutputStream. f) (FileInputStream. f) + (OutputStreamWriter. (FileOutputStream. f) "UTF-8") (reader f :encoding "UTF-8") + f (FileInputStream. f) + (writer f :encoding "UTF-8") (InputStreamReader. (FileInputStream. f) "UTF-8")) + + (is (= content (slurp (.getBytes content "UTF-8")))) + (is (= content (slurp (.toCharArray content)))) + (finally + (.delete f))))) + +(defn bytes-should-equal [byte-array-1 byte-array-2 msg] + (is (= @#'clojure.java.io/byte-array-type (class byte-array-1) (class byte-array-2)) msg) + (is (= (into [] byte-array-1) (into [] byte-array-2)) msg)) + +(defn data-fixture + "in memory fixture data for tests" + [encoding] + (let [bs (.getBytes "hello" encoding) + cs (.toCharArray "hello") + i (ByteArrayInputStream. bs) + r (InputStreamReader. i) + o (ByteArrayOutputStream.) + w (OutputStreamWriter. o)] + {:bs bs + :i i + :r r + :o o + :s "hello" + :cs cs + :w w})) + +(deftest test-copy + (dorun + (for [{:keys [in out flush] :as test} + [{:in :i :out :o} + {:in :i :out :w} + {:in :r :out :o} + {:in :r :out :w} + {:in :cs :out :o} + {:in :cs :out :w} + {:in :bs :out :o} + {:in :bs :out :w}] + + opts + [{} {:buffer-size 256}]] + (let [{:keys [s o] :as d} (data-fixture "UTF-8")] + (apply copy (in d) (out d) (flatten (vec opts))) + #_(when (= out :w) (.flush (:w d))) + (.flush (out d)) + (bytes-should-equal (.getBytes s "UTF-8") + (.toByteArray o) + (str "combination " test opts)))))) + +(deftest test-copy-encodings + (testing "from inputstream UTF-16 to writer UTF-8" + (let [{:keys [i s o w bs]} (data-fixture "UTF-16")] + (copy i w :encoding "UTF-16") + (.flush w) + (bytes-should-equal (.getBytes s "UTF-8") (.toByteArray o) ""))) + (testing "from reader UTF-8 to output-stream UTF-16" + (let [{:keys [r o s]} (data-fixture "UTF-8")] + (copy r o :encoding "UTF-16") + (bytes-should-equal (.getBytes s "UTF-16") (.toByteArray o) "")))) + +(deftest test-as-file + (are [result input] (= result (as-file input)) + (File. "foo") "foo" + (File. "bar") (File. "bar") + (File. "baz") (URL. "file:baz") + (File. "quux") (URI. "file:quux") + nil nil)) + +(deftest test-file + (are [result args] (= (File. result) (apply file args)) + "foo" ["foo"] + "foo/bar" ["foo" "bar"] + "foo/bar/baz" ["foo" "bar" "baz"])) +(deftest test-as-url + (are [file-part input] (= (URL. (str "file:" file-part)) (as-url input)) + "foo" "file:foo" + "/foo" (File. "/foo") + "baz" (URL. "file:baz") + "quux" (URI. "file:quux")) + (is (nil? (as-url nil)))) + +(deftest test-delete-file + (let [file (temp-file "test" "deletion") + not-file (File. (str (java.util.UUID/randomUUID)))] + (delete-file (.getAbsolutePath file)) + (is (not (.exists file))) + (is (thrown? java.io.IOException (delete-file not-file))) + (is (= :silently (delete-file not-file :silently))))) + +(deftest test-as-relative-path + (testing "strings" + (is (= "foo" (as-relative-path "foo")))) + (testing "absolute path strings are forbidden" + (is (thrown? IllegalArgumentException (as-relative-path (str File/separator "baz"))))) + (testing "relative File paths" + (is (= "bar" (as-relative-path (File. "bar"))))) + (testing "absolute File paths are forbidden" + (is (thrown? IllegalArgumentException (as-relative-path (File. (str File/separator "quux"))))))) + +(defn stream-should-have [stream expected-bytes msg] + (let [actual-bytes (byte-array (alength expected-bytes))] + (.read stream actual-bytes) + (is (= -1 (.read stream)) (str msg " : should be end of stream")) + (is (= (seq expected-bytes) (seq actual-bytes)) (str msg " : byte arrays should match")))) + +(deftest test-input-stream + (let [file (temp-file "test-input-stream" "txt") + bytes (.getBytes "foobar")] + (spit file "foobar") + (doseq [[expr msg] + [[file File] + [(FileInputStream. file) FileInputStream] + [(BufferedInputStream. (FileInputStream. file)) BufferedInputStream] + [(.. file toURI) URI] + [(.. file toURI toURL) URL] + [(.. file toURI toURL toString) "URL as String"] + [(.. file toString) "File as String"]]] + (with-open [s (input-stream expr)] + (stream-should-have s bytes msg))))) + +(deftest test-streams-buffering + (let [data (.getBytes "")] + (is (instance? java.io.BufferedReader (reader data))) + (is (instance? java.io.BufferedWriter (writer (java.io.ByteArrayOutputStream.)))) + (is (instance? java.io.BufferedInputStream (input-stream data))) + (is (instance? java.io.BufferedOutputStream (output-stream (java.io.ByteArrayOutputStream.)))))) + +(deftest test-resource + (is (nil? (resource "non/existent/resource"))) + (is (instance? URL (resource "clojure/core.clj"))) + (let [file (temp-file "test-resource" "txt") + url (as-url (.getParentFile file)) + loader (java.net.URLClassLoader. (into-array [url]))] + (is (nil? (resource "non/existent/resource" loader))) + (is (instance? URL (resource (.getName file) loader))))) + +(deftest test-make-parents + (let [tmp (System/getProperty "java.io.tmpdir")] + (delete-file-recursively (file tmp "test-make-parents") :silently) + (make-parents tmp "test-make-parents" "child" "grandchild") + (is (.isDirectory (file tmp "test-make-parents" "child"))) + (is (not (.isDirectory (file tmp "test-make-parents" "child" "grandchild")))) + (delete-file-recursively (file tmp "test-make-parents")))) diff --git a/test/clojure/test_clojure/metadata.clj b/test/clojure/test_clojure/metadata.clj index d3a35f24..53919e9d 100644 --- a/test/clojure/test_clojure/metadata.clj +++ b/test/clojure/test_clojure/metadata.clj @@ -20,7 +20,8 @@ clojure.test clojure.walk clojure.xml - clojure.zip]) + clojure.zip + clojure.java.io]) (doseq [ns public-namespaces] (require ns)) |