GridFS tests now pass, plus API improvements that make sense for 2.0

This commit is contained in:
Michael Klishin 2014-05-10 17:34:22 -04:00
parent a7cceebe9c
commit 56eebda3fd
3 changed files with 184 additions and 165 deletions

View file

@ -38,7 +38,7 @@
;; API ;; API
;; ;;
(defn ^com.mongodb.MongoClient connect (defn ^MongoClient connect
"Connects to MongoDB. When used without arguments, connects to "Connects to MongoDB. When used without arguments, connects to
Arguments: Arguments:
@ -79,7 +79,7 @@
(set (.getDatabaseNames conn))) (set (.getDatabaseNames conn)))
(defn ^com.mongodb.DB get-db (defn ^DB get-db
"Get database reference by name. "Get database reference by name.
EXAMPLES EXAMPLES
@ -93,6 +93,15 @@
[^MongoClient conn ^String db] [^MongoClient conn ^String db]
(.dropDatabase conn db)) (.dropDatabase conn db))
(defn ^GridFS get-gridfs
"Get GridFS for the given database.
EXAMPLES
(monger.core/get-gridfs connection \"myapp_production\")"
[^MongoClient conn ^String name]
(GridFS. (.getDB conn name)))
(defn server-address (defn server-address
([^String hostname] ([^String hostname]
(ServerAddress. hostname)) (ServerAddress. hostname))

View file

@ -20,7 +20,7 @@
(:import [com.mongodb DB DBObject] (:import [com.mongodb DB DBObject]
org.bson.types.ObjectId org.bson.types.ObjectId
[com.mongodb.gridfs GridFS GridFSInputFile] [com.mongodb.gridfs GridFS GridFSInputFile]
[java.io InputStream File])) [java.io InputStream ByteArrayInputStream File]))
;; ;;
;; Implementation ;; Implementation
@ -50,42 +50,49 @@
(remove fs {})) (remove fs {}))
(defn all-files (defn all-files
[^GridFS fs query] ([^GridFS fs]
(.getFileList fs query)) (.getFileList fs (to-db-object {})))
([^GridFS fs query]
(.getFileList fs query)))
(def ^{:private true} converter (def ^{:private true} converter
(fpartial from-db-object true)) (fpartial from-db-object true))
(defn files-as-maps (defn files-as-maps
[^GridFS fs query] ([^GridFS fs]
(map converter (all-files fs (to-db-object query)))) (files-as-maps fs {}))
([^GridFS fs query]
(map converter (all-files fs (to-db-object query)))))
;; ;;
;; Plumbing (low-level API) ;; Plumbing (low-level API)
;; ;;
(defprotocol GridFSInputFileFactory (defprotocol InputStreamFactory
(^com.mongodb.gridfs.GridFSInputFile make-input-file [input] "Makes GridFSInputFile out of the given input")) (^InputStream to-input-stream [input] "Makes InputStream out of the given input"))
(extend byte-array-type (extend byte-array-type
GridFSInputFileFactory InputStreamFactory
{:make-input-file (fn [^bytes input] {:to-input-stream (fn [^bytes input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* input))}) (ByteArrayInputStream. input))})
(extend-protocol GridFSInputFileFactory (extend-protocol InputStreamFactory
String String
(make-input-file [^String input] (to-input-stream [^String input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream (io/make-input-stream input {:encoding "UTF-8"}))) (io/make-input-stream input {:encoding "UTF-8"}))
File File
(make-input-file [^File input] (to-input-stream [^File input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream (io/make-input-stream input {:encoding "UTF-8"}))) (io/make-input-stream input {:encoding "UTF-8"}))
InputStream InputStream
(make-input-file [^InputStream input] (to-input-stream [^InputStream input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream input))) input))
(defn ^GridFSInputFile make-input-file
[^GridFS fs input]
(.createFile fs (to-input-stream input)))
(defmacro store (defmacro store
[^GridFSInputFile input & body] [^GridFSInputFile input & body]
@ -93,9 +100,8 @@
(.save f# GridFS/DEFAULT_CHUNKSIZE) (.save f# GridFS/DEFAULT_CHUNKSIZE)
(from-db-object f# true))) (from-db-object f# true)))
;; ;;
;; "New" DSL, a higher-level API ;; Higher-level API
;; ;;
(defn save (defn save
@ -132,6 +138,14 @@
[^GridFS fs query] [^GridFS fs query]
(.find fs (to-db-object query))) (.find fs (to-db-object query)))
(defn find-by-filename
[^GridFS fs ^String filename]
(.find fs (to-db-object {"filename" filename})))
(defn find-by-md5
[^GridFS fs ^String md5]
(.find fs (to-db-object {"md5" md5})))
(defn find-one (defn find-one
[^GridFS fs query] [^GridFS fs query]
(.findOne fs (to-db-object query))) (.findOne fs (to-db-object query)))

View file

@ -1,107 +1,104 @@
(ns monger.test.gridfs-test (ns monger.test.gridfs-test
(:refer-clojure :exclude [count remove find]) (:refer-clojure :exclude [count remove find])
(:require [monger.gridfs :as gridfs] (:require [monger.gridfs :as gridfs]
[monger.test.helper :as helper]
[clojure.java.io :as io] [clojure.java.io :as io]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.core :refer [count]] [monger.core :as mg :refer [count]]
[monger.test.fixtures :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[monger.conversion :refer :all] [monger.conversion :refer :all]
[monger.gridfs :refer [store make-input-file store-file filename content-type metadata]]) [monger.gridfs :refer [store make-input-file store-file filename content-type metadata]])
(:import [java.io InputStream File FileInputStream] (:import [java.io InputStream File FileInputStream]
[com.mongodb.gridfs GridFS GridFSInputFile GridFSDBFile])) [com.mongodb.gridfs GridFS GridFSInputFile GridFSDBFile]))
(defn purge-gridfs* (let [conn (mg/connect)
db (mg/get-db conn "monger-test")
fs (mg/get-gridfs conn "monger-test")]
(defn purge-gridfs*
[] []
(gridfs/remove-all)) (gridfs/remove-all fs))
(defn purge-gridfs (defn purge-gridfs
[f] [f]
(gridfs/remove-all) (gridfs/remove-all fs)
(f) (f)
(gridfs/remove-all)) (gridfs/remove-all fs))
(use-fixtures :each purge-gridfs) (use-fixtures :each purge-gridfs)
(helper/connect!) (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-relative-fs-paths
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-relative-fs-paths
(let [input "./test/resources/mongo/js/mapfun1.js"] (let [input "./test/resources/mongo/js/mapfun1.js"]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store (make-input-file input) (store (make-input-file fs input)
(.setFilename "monger.test.gridfs.file1") (.setFilename "monger.test.gridfs.file1")
(.setContentType "application/octet-stream")) (.setContentType "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-file-instances (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-file-instances
(let [input (io/as-file "./test/resources/mongo/js/mapfun1.js")] (let [input (io/as-file "./test/resources/mongo/js/mapfun1.js")]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file2") (filename "monger.test.gridfs.file2")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-bytes-to-gridfs (deftest ^{:gridfs true} test-storing-bytes-to-gridfs
(let [input (.getBytes "A string") (let [input (.getBytes "A string")
md {:format "raw" :source "AwesomeCamera D95"} md {:format "raw" :source "AwesomeCamera D95"}
fname "monger.test.gridfs.file3" fname "monger.test.gridfs.file3"
ct "application/octet-stream"] ct "application/octet-stream"]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename fname) (filename fname)
(metadata md) (metadata md)
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(let [f (first (gridfs/files-as-maps))] (let [f (first (gridfs/files-as-maps fs))]
(is (= ct (:contentType f))) (is (= ct (:contentType f)))
(is (= fname (:filename f))) (is (= fname (:filename f)))
(is (= md (:metadata f)))) (is (= md (:metadata f))))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-absolute-fs-paths (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-absolute-fs-paths
(let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-absolute-fs-paths") (let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-absolute-fs-paths")
_ (spit tmp-file "Some content") _ (spit tmp-file "Some content")
input (.getAbsolutePath tmp-file)] input (.getAbsolutePath tmp-file)]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file4") (filename "monger.test.gridfs.file4")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-input-stream (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-input-stream
(let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-input-stream") (let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-input-stream")
_ (spit tmp-file "Some other content")] _ (spit tmp-file "Some other content")]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file (FileInputStream. tmp-file)) (store-file fs
(make-input-file (FileInputStream. tmp-file))
(filename "monger.test.gridfs.file4b") (filename "monger.test.gridfs.file4b")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-finding-individual-files-on-gridfs (deftest ^{:gridfs true} test-finding-individual-files-on-gridfs
(testing "gridfs/find-one" (testing "gridfs/find-one"
(purge-gridfs*) (purge-gridfs*)
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
fname "monger.test.gridfs.file5" fname "monger.test.gridfs.file5"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored (store-file (make-input-file input) stored (store-file (make-input-file fs input)
(filename fname) (filename fname)
(content-type ct))] (content-type ct))]
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(is (:_id stored)) (is (:_id stored))
(is (:uploadDate stored)) (is (:uploadDate stored))
(is (= 62 (:length stored))) (is (= 62 (:length stored)))
(is (= md5 (:md5 stored))) (is (= md5 (:md5 stored)))
(is (= fname (:filename stored))) (is (= fname (:filename stored)))
(is (= ct (:contentType stored))) (is (= ct (:contentType stored)))
(are [a b] (is (= a (:md5 (from-db-object (gridfs/find-one b) true)))) (are [a b] (is (= a (:md5 (from-db-object (gridfs/find-one fs b) true))))
md5 (:_id stored) md5 {:_id (:_id stored)}
md5 fname
md5 (to-db-object {:md5 md5})))) md5 (to-db-object {:md5 md5}))))
(testing "gridfs/find-one-as-map" (testing "gridfs/find-one-as-map"
(purge-gridfs*) (purge-gridfs*)
@ -109,39 +106,38 @@
ct "binary/octet-stream" ct "binary/octet-stream"
fname "monger.test.gridfs.file6" fname "monger.test.gridfs.file6"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored (store-file (make-input-file input) stored (store-file (make-input-file fs input)
(filename fname) (filename fname)
(metadata (to-db-object {:meta "data"})) (metadata (to-db-object {:meta "data"}))
(content-type ct))] (content-type ct))]
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(is (:_id stored)) (is (:_id stored))
(is (:uploadDate stored)) (is (:uploadDate stored))
(is (= 62 (:length stored))) (is (= 62 (:length stored)))
(is (= md5 (:md5 stored))) (is (= md5 (:md5 stored)))
(is (= fname (:filename stored))) (is (= fname (:filename stored)))
(is (= ct (:contentType stored))) (is (= ct (:contentType stored)))
(let [m (gridfs/find-one-as-map {:filename fname})] (let [m (gridfs/find-one-as-map fs {:filename fname})]
(is (= {:meta "data"} (:metadata m)))) (is (= {:meta "data"} (:metadata m))))
(are [a query] (is (= a (:md5 (gridfs/find-one-as-map query)))) (are [a query] (is (= a (:md5 (gridfs/find-one-as-map fs query))))
md5 (:_id stored) md5 {:_id (:_id stored)}
md5 fname
md5 {:md5 md5})))) md5 {:md5 md5}))))
(deftest ^{:gridfs true} test-finding-multiple-files-on-gridfs (deftest ^{:gridfs true} test-finding-multiple-files-on-gridfs
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored1 (store-file (make-input-file input) stored1 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file6") (filename "monger.test.gridfs.file6")
(content-type ct)) (content-type ct))
stored2 (store-file (make-input-file input) stored2 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file7") (filename "monger.test.gridfs.file7")
(content-type ct)) (content-type ct))
list1 (gridfs/find "monger.test.gridfs.file6") list1 (gridfs/find-by-filename fs "monger.test.gridfs.file6")
list2 (gridfs/find "monger.test.gridfs.file7") list2 (gridfs/find-by-filename fs "monger.test.gridfs.file7")
list3 (gridfs/find "888000___.monger.test.gridfs.file") list3 (gridfs/find-by-filename fs "888000___.monger.test.gridfs.file")
list4 (gridfs/find { :md5 md5 })] list4 (gridfs/find-by-md5 fs md5)]
(is (= 2 (count (gridfs/all-files)))) (is (= 2 (count (gridfs/all-files fs))))
(are [a b] (is (= (map #(.get ^GridFSDBFile % "_id") a) (are [a b] (is (= (map #(.get ^GridFSDBFile % "_id") a)
(map :_id b))) (map :_id b)))
list1 [stored1] list1 [stored1]
@ -150,18 +146,18 @@
list4 [stored1 stored2]))) list4 [stored1 stored2])))
(deftest ^{:gridfs true} test-removing-multiple-files-from-gridfs (deftest ^{:gridfs true} test-removing-multiple-files-from-gridfs
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored1 (store-file (make-input-file input) stored1 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file8") (filename "monger.test.gridfs.file8")
(content-type ct)) (content-type ct))
stored2 (store-file (make-input-file input) stored2 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file9") (filename "monger.test.gridfs.file9")
(content-type ct))] (content-type ct))]
(is (= 2 (count (gridfs/all-files)))) (is (= 2 (count (gridfs/all-files fs))))
(gridfs/remove { :filename "monger.test.gridfs.file8" }) (gridfs/remove fs { :filename "monger.test.gridfs.file8" })
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(gridfs/remove { :md5 md5 }) (gridfs/remove fs { :md5 md5 })
(is (= 0 (count (gridfs/all-files)))))) (is (= 0 (count (gridfs/all-files fs)))))))