From cb684136e56843a442820fb52ebd2208ca5f4626 Mon Sep 17 00:00:00 2001 From: George Narroway Date: Thu, 9 Jan 2020 22:54:54 +0800 Subject: [PATCH] move model helpers to their own ns --- src/mongo_driver_3/client.clj | 10 +- src/mongo_driver_3/collection.clj | 232 ++---------------------- src/mongo_driver_3/model.clj | 211 +++++++++++++++++++++ test/mongo_driver_3/collection_test.clj | 178 +----------------- test/mongo_driver_3/model_test.clj | 179 ++++++++++++++++++ 5 files changed, 411 insertions(+), 399 deletions(-) create mode 100644 src/mongo_driver_3/model.clj create mode 100644 test/mongo_driver_3/model_test.clj diff --git a/src/mongo_driver_3/client.clj b/src/mongo_driver_3/client.clj index 6eb4e47..9a6db81 100644 --- a/src/mongo_driver_3/client.clj +++ b/src/mongo_driver_3/client.clj @@ -1,6 +1,6 @@ (ns mongo-driver-3.client (:refer-clojure :exclude [find]) - (:require [mongo-driver-3.collection :as mc]) + (:require [mongo-driver-3.model :as m]) (:import (com.mongodb.client MongoClients MongoClient ClientSession MongoDatabase TransactionBody) (com.mongodb ConnectionString ClientSessionOptions TransactionOptions) (java.util.concurrent TimeUnit))) @@ -49,7 +49,7 @@ (.listCollections db session) (.listCollections db))] (if-not raw? - (map #(mc/from-document % keywordize?) (seq it)) + (map #(m/from-document % keywordize?) (seq it)) it)))) (defn list-collection-names @@ -73,9 +73,9 @@ (defn ->TransactionOptions "Coerces options map into a TransactionOptions. See `start-session` for usage." [{:keys [max-commit-time-ms] :as opts}] - (let [rp (mc/->ReadPreference opts) - rc (mc/->ReadConcern opts) - wc (mc/->WriteConcern opts)] + (let [rp (m/->ReadPreference opts) + rc (m/->ReadConcern opts) + wc (m/->WriteConcern opts)] (cond-> (TransactionOptions/builder) max-commit-time-ms (.maxCommitTime max-commit-time-ms (TimeUnit/MILLISECONDS)) diff --git a/src/mongo_driver_3/collection.clj b/src/mongo_driver_3/collection.clj index fd6f13a..b6b6f88 100644 --- a/src/mongo_driver_3/collection.clj +++ b/src/mongo_driver_3/collection.clj @@ -1,123 +1,16 @@ (ns mongo-driver-3.collection (:refer-clojure :exclude [find empty? drop]) - (:import (clojure.lang Ratio Keyword Named IPersistentMap) - (com.mongodb ReadConcern ReadPreference WriteConcern MongoNamespace) + (:require [mongo-driver-3.model :refer :all]) + (:import (com.mongodb MongoNamespace) (com.mongodb.client MongoDatabase MongoCollection ClientSession) - (com.mongodb.client.model InsertOneOptions InsertManyOptions DeleteOptions FindOneAndUpdateOptions ReturnDocument FindOneAndReplaceOptions CountOptions CreateCollectionOptions RenameCollectionOptions IndexOptions IndexModel UpdateOptions ReplaceOptions) - (java.util List Collection) - (java.util.concurrent TimeUnit) - (org.bson Document) - (org.bson.types Decimal128))) + (com.mongodb.client.model IndexModel) + (java.util List) + (org.bson Document))) (set! *warn-on-reflection* true) -;;; Conversions - -(defprotocol ConvertToDocument - (^Document document [input] "Convert from clojure to Mongo Document")) - -(extend-protocol ConvertToDocument - nil - (document [_] - nil) - - Ratio - (document [^Ratio input] - (double input)) - - Keyword - (document [^Keyword input] - (.getName input)) - - Named - (document [^Named input] - (.getName input)) - - IPersistentMap - (document [^IPersistentMap input] - (let [o (Document.)] - (doseq [[k v] input] - (.append o (document k) (document v))) - o)) - - Collection - (document [^Collection input] - (map document input)) - - Object - (document [input] - input)) - -(defprotocol ConvertFromDocument - (from-document [input keywordize?] "Converts Mongo Document to Clojure")) - -(extend-protocol ConvertFromDocument - nil - (from-document [input _] - input) - - Object - (from-document [input _] input) - - Decimal128 - (from-document [^Decimal128 input _] - (.bigDecimalValue input)) - - List - (from-document [^List input keywordize?] - (vec (map #(from-document % keywordize?) input))) - - Document - (from-document [^Document input keywordize?] - (reduce (if keywordize? - (fn [m ^String k] - (assoc m (keyword k) (from-document (.get input k) true))) - (fn [m ^String k] - (assoc m k (from-document (.get input k) false)))) - {} (.keySet input)))) - - ;;; Collection - -(def kw->ReadConcern - {:available (ReadConcern/AVAILABLE) - :default (ReadConcern/DEFAULT) - :linearizable (ReadConcern/LINEARIZABLE) - :local (ReadConcern/LOCAL) - :majority (ReadConcern/MAJORITY) - :snapshot (ReadConcern/SNAPSHOT)}) - -(defn ->ReadConcern - "Coerce `rc` into a ReadConcern if not nil. See `collection` for usage." - [{:keys [read-concern]}] - (when read-concern - (if (instance? ReadConcern read-concern) - read-concern - (or (kw->ReadConcern read-concern) (throw (IllegalArgumentException. - (str "No match for read concern of " (name read-concern)))))))) - -(defn ->ReadPreference - "Coerce `rp` into a ReadPreference if not nil. See `collection` for usage." - [{:keys [read-preference]}] - (when read-preference - (if (instance? ReadPreference read-preference) - read-preference - (ReadPreference/valueOf (name read-preference))))) - -(defn ^WriteConcern ->WriteConcern - "Coerces write-concern related options to a WriteConcern. See `collection` for usage." - [{:keys [write-concern ^Integer write-concern/w ^Long write-concern/w-timeout-ms ^Boolean write-concern/journal?]}] - (when (some some? [write-concern w w-timeout-ms journal?]) - (let [^WriteConcern wc (when write-concern - (if (instance? WriteConcern write-concern) - write-concern - (WriteConcern/valueOf (name write-concern))))] - (cond-> (or wc (WriteConcern/ACKNOWLEDGED)) - w (.withW w) - w-timeout-ms (.withWTimeout w-timeout-ms (TimeUnit/MILLISECONDS)) - (some? journal?) (.withJournal journal?))))) - (defn ^MongoCollection collection "Coerces `coll` to a MongoCollection with some options. @@ -148,9 +41,9 @@ rc (->ReadConcern opts) wc (->WriteConcern opts)] (cond-> ^MongoCollection coll' - rp (.withReadPreference rp) - rc (.withReadConcern rc) - wc (.withWriteConcern wc))))) + rp (.withReadPreference rp) + rc (.withReadConcern rc) + wc (.withWriteConcern wc))))) ;;; CRUD functions @@ -177,24 +70,14 @@ it (cond-> (if session (.aggregate (collection db coll opts) session ^List (map document pipeline)) (.aggregate (collection db coll opts) ^List (map document pipeline))) - (some? allow-disk-use?) (.allowDiskUse allow-disk-use?) - (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?) - batch-size (.batchSize batch-size))] + (some? allow-disk-use?) (.allowDiskUse allow-disk-use?) + (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?) + batch-size (.batchSize batch-size))] (if-not raw? (map (fn [x] (from-document x keywordize?)) (seq it)) it)))) -(defn ^CountOptions ->CountOptions - "Coerce options map into CountOptions. See `count-documents` for usage." - [{:keys [count-options hint limit max-time-ms skip]}] - (let [^CountOptions opts (or count-options (CountOptions.))] - (cond-> opts - hint (.hint (document hint)) - limit (.limit limit) - max-time-ms (.maxTime max-time-ms (TimeUnit/MILLISECONDS)) - skip (.skip skip)))) - (defn count-documents "Count documents in a collection, optionally matching a filter query `q`. @@ -223,12 +106,6 @@ (.countDocuments (collection db coll opts) session (document q) opts') (.countDocuments (collection db coll opts) (document q) opts'))))) -(defn ^DeleteOptions ->DeleteOptions - "Coerce options map into DeleteOptions. See `delete-one` and `delete-many` for usage." - [{:keys [delete-options]}] - (let [^DeleteOptions opts (or delete-options (DeleteOptions.))] - opts)) - (defn delete-one "Deletes a single document from a collection and returns a DeleteResult. @@ -294,10 +171,10 @@ (let [it (cond-> (if session (.find (collection db coll opts) session (document q)) (.find (collection db coll opts) (document q))) - limit (.limit limit) - skip (.skip skip) - sort (.sort (document sort)) - projection (.projection (document projection)))] + limit (.limit limit) + skip (.skip skip) + sort (.sort (document sort)) + projection (.projection (document projection)))] (if-not raw? (map (fn [x] (from-document x keywordize?)) (seq it)) @@ -312,16 +189,6 @@ ([^MongoDatabase db coll q opts] (first (find db coll q (assoc opts :limit 1 :raw? false))))) -(defn ^FindOneAndUpdateOptions ->FindOneAndUpdateOptions - "Coerce options map into FindOneAndUpdateOptions. See `find-one-and-update` for usage." - [{:keys [find-one-and-update-options upsert? return-new? sort projection]}] - (let [^FindOneAndUpdateOptions opts (or find-one-and-update-options (FindOneAndUpdateOptions.))] - (cond-> opts - (some? upsert?) (.upsert upsert?) - return-new? (.returnDocument (ReturnDocument/AFTER)) - sort (.sort (document sort)) - projection (.projection (document projection))))) - (defn find-one-and-update "Atomically find a document (at most one) and modify it. @@ -352,16 +219,6 @@ (.findOneAndUpdate (collection db coll opts) (document q) (document update) opts')) (from-document keywordize?))))) -(defn ^FindOneAndReplaceOptions ->FindOneAndReplaceOptions - "Coerce options map into FindOneAndReplaceOptions. See `find-one-and-replace` for usage." - [{:keys [find-one-and-replace-options upsert? return-new? sort projection]}] - (let [^FindOneAndReplaceOptions opts (or find-one-and-replace-options (FindOneAndReplaceOptions.))] - (cond-> opts - (some? upsert?) (.upsert upsert?) - return-new? (.returnDocument (ReturnDocument/AFTER)) - sort (.sort (document sort)) - projection (.projection (document projection))))) - (defn find-one-and-replace "Atomically find a document (at most one) and replace it. @@ -392,14 +249,6 @@ (.findOneAndReplace (collection db coll opts) (document q) (document doc) opts')) (from-document keywordize?))))) -(defn ^InsertOneOptions ->InsertOneOptions - "Coerce options map into InsertOneOptions. See `insert-one` for usage." - [{:keys [insert-one-options bypass-document-validation?]}] - (let [^InsertOneOptions opts (or insert-one-options (InsertOneOptions.))] - (when (some? bypass-document-validation?) (.bypassDocumentValidation opts bypass-document-validation?)) - - opts)) - (defn insert-one "Inserts a single document into a collection, and returns nil. If the document does not have an _id field, it will be auto-generated by the underlying driver. @@ -424,14 +273,6 @@ (.insertOne (collection db coll opts) session (document doc) opts') (.insertOne (collection db coll opts) (document doc) opts'))))) -(defn ^InsertManyOptions ->InsertManyOptions - "Coerce options map into InsertManyOptions. See `insert-many` for usage." - [{:keys [insert-many-options bypass-document-validation? ordered?]}] - (let [^InsertManyOptions opts (or insert-many-options (InsertManyOptions.))] - (cond-> opts - (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?) - (some? ordered?) (.ordered ordered?)))) - (defn insert-many "Inserts multiple documents into a collection. If a document does not have an _id field, it will be auto-generated by the underlying driver. @@ -457,14 +298,6 @@ (.insertMany (collection db coll opts) session ^List (map document docs) opts') (.insertMany (collection db coll opts) ^List (map document docs) opts'))))) -(defn ^ReplaceOptions ->ReplaceOptions - "Coerce options map into ReplaceOptions. See `replace-one` and `replace-many` for usage." - [{:keys [replace-options upsert? bypass-document-validation?]}] - (let [^ReplaceOptions opts (or replace-options (ReplaceOptions.))] - (cond-> opts - (some? upsert?) (.upsert upsert?) - (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)))) - (defn replace-one "Replace a single document in a collection and returns an UpdateResult. @@ -489,14 +322,6 @@ (.replaceOne (collection db coll opts) session (document q) (document doc) (->ReplaceOptions opts)) (.replaceOne (collection db coll opts) (document q) (document doc) (->ReplaceOptions opts))))) -(defn ^UpdateOptions ->UpdateOptions - "Coerce options map into UpdateOptions. See `update-one` and `update-many` for usage." - [{:keys [update-options upsert? bypass-document-validation?]}] - (let [^UpdateOptions opts (or update-options (UpdateOptions.))] - (cond-> opts - (some? upsert?) (.upsert upsert?) - (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)))) - (defn update-one "Updates a single document in a collection and returns an UpdateResult. @@ -547,15 +372,6 @@ ;;; Admin functions -(defn ^CreateCollectionOptions ->CreateCollectionOptions - "Coerce options map into CreateCollectionOptions. See `create` usage." - [{:keys [create-collection-options capped? max-documents max-size-bytes]}] - (let [^CreateCollectionOptions opts (or create-collection-options (CreateCollectionOptions.))] - (cond-> opts - (some? capped?) (.capped capped?) - max-documents (.maxDocuments max-documents) - max-size-bytes (.sizeInBytes max-size-bytes)))) - (defn create "Creates a collection @@ -575,13 +391,6 @@ (let [opts' (->CreateCollectionOptions opts)] (.createCollection db coll opts')))) -(defn ^RenameCollectionOptions ->RenameCollectionOptions - "Coerce options map into RenameCollectionOptions. See `rename` usage." - [{:keys [rename-collection-options drop-target?]}] - (let [^RenameCollectionOptions opts (or rename-collection-options (RenameCollectionOptions.))] - (cond-> opts - (some? drop-target?) (.dropTarget drop-target?)))) - (defn rename "Renames `coll` to `new-coll` in the same DB. @@ -608,17 +417,6 @@ [^MongoDatabase db coll] (.drop (collection db coll))) -(defn ^IndexOptions ->IndexOptions - "Coerces an options map into an IndexOptions. - - See `create-index` for usage" - [{:keys [index-options name sparse? unique?]}] - (let [^IndexOptions opts (or index-options (IndexOptions.))] - (cond-> opts - name (.name name) - (some? sparse?) (.sparse sparse?) - (some? unique?) (.unique unique?)))) - (defn create-index "Creates an index diff --git a/src/mongo_driver_3/model.clj b/src/mongo_driver_3/model.clj new file mode 100644 index 0000000..798304b --- /dev/null +++ b/src/mongo_driver_3/model.clj @@ -0,0 +1,211 @@ +(ns mongo-driver-3.model + (:import (com.mongodb.client.model CountOptions DeleteOptions ReturnDocument FindOneAndUpdateOptions InsertOneOptions ReplaceOptions UpdateOptions CreateCollectionOptions RenameCollectionOptions InsertManyOptions FindOneAndReplaceOptions IndexOptions) + (org.bson Document) + (java.util.concurrent TimeUnit) + (com.mongodb WriteConcern ReadPreference ReadConcern) + (clojure.lang Ratio Keyword Named IPersistentMap) + (java.util Collection List) + (org.bson.types Decimal128))) + +(set! *warn-on-reflection* true) + +;;; Conversions + +(defprotocol ConvertToDocument + (^Document document [input] "Convert from clojure to Mongo Document")) + +(extend-protocol ConvertToDocument + nil + (document [_] + nil) + + Ratio + (document [^Ratio input] + (double input)) + + Keyword + (document [^Keyword input] + (.getName input)) + + Named + (document [^Named input] + (.getName input)) + + IPersistentMap + (document [^IPersistentMap input] + (let [o (Document.)] + (doseq [[k v] input] + (.append o (document k) (document v))) + o)) + + Collection + (document [^Collection input] + (map document input)) + + Object + (document [input] + input)) + +(defprotocol ConvertFromDocument + (from-document [input keywordize?] "Converts Mongo Document to Clojure")) + +(extend-protocol ConvertFromDocument + nil + (from-document [input _] + input) + + Object + (from-document [input _] input) + + Decimal128 + (from-document [^Decimal128 input _] + (.bigDecimalValue input)) + + List + (from-document [^List input keywordize?] + (vec (map #(from-document % keywordize?) input))) + + Document + (from-document [^Document input keywordize?] + (reduce (if keywordize? + (fn [m ^String k] + (assoc m (keyword k) (from-document (.get input k) true))) + (fn [m ^String k] + (assoc m k (from-document (.get input k) false)))) + {} (.keySet input)))) + +;;; Config + +(def kw->ReadConcern + {:available (ReadConcern/AVAILABLE) + :default (ReadConcern/DEFAULT) + :linearizable (ReadConcern/LINEARIZABLE) + :local (ReadConcern/LOCAL) + :majority (ReadConcern/MAJORITY) + :snapshot (ReadConcern/SNAPSHOT)}) + +(defn ->ReadConcern + "Coerce `rc` into a ReadConcern if not nil. See `collection` for usage." + [{:keys [read-concern]}] + (when read-concern + (if (instance? ReadConcern read-concern) + read-concern + (or (kw->ReadConcern read-concern) (throw (IllegalArgumentException. + (str "No match for read concern of " (name read-concern)))))))) + +(defn ->ReadPreference + "Coerce `rp` into a ReadPreference if not nil. See `collection` for usage." + [{:keys [read-preference]}] + (when read-preference + (if (instance? ReadPreference read-preference) + read-preference + (ReadPreference/valueOf (name read-preference))))) + +(defn ^WriteConcern ->WriteConcern + "Coerces write-concern related options to a WriteConcern. See `collection` for usage." + [{:keys [write-concern ^Integer write-concern/w ^Long write-concern/w-timeout-ms ^Boolean write-concern/journal?]}] + (when (some some? [write-concern w w-timeout-ms journal?]) + (let [^WriteConcern wc (when write-concern + (if (instance? WriteConcern write-concern) + write-concern + (WriteConcern/valueOf (name write-concern))))] + (cond-> (or wc (WriteConcern/ACKNOWLEDGED)) + w (.withW w) + w-timeout-ms (.withWTimeout w-timeout-ms (TimeUnit/MILLISECONDS)) + (some? journal?) (.withJournal journal?))))) + +(defn ^CountOptions ->CountOptions + "Coerce options map into CountOptions. See `count-documents` for usage." + [{:keys [count-options hint limit max-time-ms skip]}] + (let [^CountOptions opts (or count-options (CountOptions.))] + (cond-> opts + hint (.hint (document hint)) + limit (.limit limit) + max-time-ms (.maxTime max-time-ms (TimeUnit/MILLISECONDS)) + skip (.skip skip)))) + +(defn ^DeleteOptions ->DeleteOptions + "Coerce options map into DeleteOptions. See `delete-one` and `delete-many` for usage." + [{:keys [delete-options]}] + (let [^DeleteOptions opts (or delete-options (DeleteOptions.))] + opts)) + +(defn ^FindOneAndReplaceOptions ->FindOneAndReplaceOptions + "Coerce options map into FindOneAndReplaceOptions. See `find-one-and-replace` for usage." + [{:keys [find-one-and-replace-options upsert? return-new? sort projection]}] + (let [^FindOneAndReplaceOptions opts (or find-one-and-replace-options (FindOneAndReplaceOptions.))] + (cond-> opts + (some? upsert?) (.upsert upsert?) + return-new? (.returnDocument (ReturnDocument/AFTER)) + sort (.sort (document sort)) + projection (.projection (document projection))))) + +(defn ^FindOneAndUpdateOptions ->FindOneAndUpdateOptions + "Coerce options map into FindOneAndUpdateOptions. See `find-one-and-update` for usage." + [{:keys [find-one-and-update-options upsert? return-new? sort projection]}] + (let [^FindOneAndUpdateOptions opts (or find-one-and-update-options (FindOneAndUpdateOptions.))] + (cond-> opts + (some? upsert?) (.upsert upsert?) + return-new? (.returnDocument (ReturnDocument/AFTER)) + sort (.sort (document sort)) + projection (.projection (document projection))))) + +(defn ^IndexOptions ->IndexOptions + "Coerces an options map into an IndexOptions. + + See `create-index` for usage" + [{:keys [index-options name sparse? unique?]}] + (let [^IndexOptions opts (or index-options (IndexOptions.))] + (cond-> opts + name (.name name) + (some? sparse?) (.sparse sparse?) + (some? unique?) (.unique unique?)))) + +(defn ^InsertManyOptions ->InsertManyOptions + "Coerce options map into InsertManyOptions. See `insert-many` for usage." + [{:keys [insert-many-options bypass-document-validation? ordered?]}] + (let [^InsertManyOptions opts (or insert-many-options (InsertManyOptions.))] + (cond-> opts + (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?) + (some? ordered?) (.ordered ordered?)))) + +(defn ^InsertOneOptions ->InsertOneOptions + "Coerce options map into InsertOneOptions. See `insert-one` for usage." + [{:keys [insert-one-options bypass-document-validation?]}] + (let [^InsertOneOptions opts (or insert-one-options (InsertOneOptions.))] + (cond-> opts + (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)))) + +(defn ^ReplaceOptions ->ReplaceOptions + "Coerce options map into ReplaceOptions. See `replace-one` and `replace-many` for usage." + [{:keys [replace-options upsert? bypass-document-validation?]}] + (let [^ReplaceOptions opts (or replace-options (ReplaceOptions.))] + (cond-> opts + (some? upsert?) (.upsert upsert?) + (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)))) + +(defn ^UpdateOptions ->UpdateOptions + "Coerce options map into UpdateOptions. See `update-one` and `update-many` for usage." + [{:keys [update-options upsert? bypass-document-validation?]}] + (let [^UpdateOptions opts (or update-options (UpdateOptions.))] + (cond-> opts + (some? upsert?) (.upsert upsert?) + (some? bypass-document-validation?) (.bypassDocumentValidation bypass-document-validation?)))) + +(defn ^CreateCollectionOptions ->CreateCollectionOptions + "Coerce options map into CreateCollectionOptions. See `create` usage." + [{:keys [create-collection-options capped? max-documents max-size-bytes]}] + (let [^CreateCollectionOptions opts (or create-collection-options (CreateCollectionOptions.))] + (cond-> opts + (some? capped?) (.capped capped?) + max-documents (.maxDocuments max-documents) + max-size-bytes (.sizeInBytes max-size-bytes)))) + +(defn ^RenameCollectionOptions ->RenameCollectionOptions + "Coerce options map into RenameCollectionOptions. See `rename` usage." + [{:keys [rename-collection-options drop-target?]}] + (let [^RenameCollectionOptions opts (or rename-collection-options (RenameCollectionOptions.))] + (cond-> opts + (some? drop-target?) (.dropTarget drop-target?)))) + + diff --git a/test/mongo_driver_3/collection_test.clj b/test/mongo_driver_3/collection_test.clj index fb92be5..ffa8932 100644 --- a/test/mongo_driver_3/collection_test.clj +++ b/test/mongo_driver_3/collection_test.clj @@ -2,186 +2,10 @@ (:require [clojure.test :refer :all] [mongo-driver-3.client :as mg] [mongo-driver-3.collection :as mc]) - (:import (com.mongodb ReadConcern ReadPreference WriteConcern) - (java.util.concurrent TimeUnit) - (com.mongodb.client.model InsertOneOptions InsertManyOptions DeleteOptions FindOneAndUpdateOptions ReturnDocument FindOneAndReplaceOptions CountOptions UpdateOptions ReplaceOptions IndexOptions CreateCollectionOptions RenameCollectionOptions) - (java.time ZoneId LocalDate LocalTime LocalDateTime) + (:import (java.time ZoneId LocalDate LocalTime LocalDateTime) (java.util Date UUID) (com.mongodb.client FindIterable))) -;;; Unit - -(deftest test->ReadConcern - (is (nil? (mc/->ReadConcern {}))) - (is (thrown? IllegalArgumentException (mc/->ReadConcern {:read-concern "invalid"}))) - (is (instance? ReadConcern (mc/->ReadConcern {:read-concern :available})))) - -(deftest test->ReadPreference - (is (nil? (mc/->ReadPreference {}))) - (is (thrown? IllegalArgumentException (mc/->ReadPreference {:read-preference "invalid"}))) - (is (instance? ReadPreference (mc/->ReadPreference {:read-preference :primary})))) - -(deftest test->WriteConcern - (is (= (WriteConcern/W1) (mc/->WriteConcern {:write-concern :w1})) "accepts kw") - (is (= (WriteConcern/W1) (mc/->WriteConcern {:write-concern (WriteConcern/W1)})) "accepts WriteConcern") - (is (= (WriteConcern/ACKNOWLEDGED) (mc/->WriteConcern {:write-concern "invalid"})) "defaults to acknowledged") - (is (= 1 (.getW (mc/->WriteConcern {:write-concern/w 1}))) "set w") - (is (= 2 (.getW (mc/->WriteConcern {:write-concern (WriteConcern/W2)})))) - (is (= 1 (.getW (mc/->WriteConcern {:write-concern (WriteConcern/W2) :write-concern/w 1}))) "prefer granular option") - (is (true? (.getJournal (mc/->WriteConcern {:write-concern/journal? true}))) "can set journal") - (is (= 77 (.getWTimeout (mc/->WriteConcern {:write-concern/w-timeout-ms 77}) (TimeUnit/MILLISECONDS))) "can set timeout")) - -(deftest test->InsertOneOptions - (is (instance? InsertOneOptions (mc/->InsertOneOptions {}))) - (is (true? (.getBypassDocumentValidation (mc/->InsertOneOptions {:bypass-document-validation? true})))) - (is (true? (.getBypassDocumentValidation (mc/->InsertOneOptions - {:insert-one-options (.bypassDocumentValidation (InsertOneOptions.) true)}))) - "configure directly") - (is (false? (.getBypassDocumentValidation (mc/->InsertOneOptions - {:insert-one-options (.bypassDocumentValidation (InsertOneOptions.) true) - :bypass-document-validation? false}))) - "can override")) - -(deftest test->ReplaceOptions - (is (instance? ReplaceOptions (mc/->ReplaceOptions {}))) - (are [expected arg] - (= expected (.isUpsert (mc/->ReplaceOptions {:upsert? arg}))) - true true - false false - false nil) (is (true? (.getBypassDocumentValidation (mc/->ReplaceOptions {:bypass-document-validation? true})))) - (is (true? (.getBypassDocumentValidation (mc/->ReplaceOptions - {:replace-options (.bypassDocumentValidation (ReplaceOptions.) true)}))) - "configure directly") - (is (false? (.getBypassDocumentValidation (mc/->ReplaceOptions - {:replace-options (.bypassDocumentValidation (ReplaceOptions.) true) - :bypass-document-validation? false}))) - "can override")) - -(deftest test->UpdateOptions - (is (instance? UpdateOptions (mc/->UpdateOptions {}))) - (are [expected arg] - (= expected (.isUpsert (mc/->UpdateOptions {:upsert? arg}))) - true true - false false - false nil) - (is (true? (.getBypassDocumentValidation (mc/->UpdateOptions {:bypass-document-validation? true})))) - (is (true? (.getBypassDocumentValidation (mc/->UpdateOptions - {:update-options (.bypassDocumentValidation (UpdateOptions.) true)}))) - "configure directly") - (is (false? (.getBypassDocumentValidation (mc/->UpdateOptions - {:update-options (.bypassDocumentValidation (UpdateOptions.) true) - :bypass-document-validation? false}))) - "can override")) - -(deftest test->InsertManyOptions - (is (instance? InsertManyOptions (mc/->InsertManyOptions {}))) - (are [expected arg] - (= expected (.getBypassDocumentValidation (mc/->InsertManyOptions {:bypass-document-validation? arg}))) - true true - false false - nil nil) - (are [expected arg] - (= expected (.isOrdered (mc/->InsertManyOptions {:ordered? arg}))) - true true - false false - true nil) - (is (true? (.getBypassDocumentValidation (mc/->InsertManyOptions - {:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)}))) - "configure directly") - (is (false? (.getBypassDocumentValidation (mc/->InsertManyOptions - {:insert-one-options (.bypassDocumentValidation (InsertManyOptions.) true) - :bypass-document-validation? false}))) - "can override")) - -(deftest test->DeleteOptions - (is (instance? DeleteOptions (mc/->DeleteOptions {}))) - (let [opts (DeleteOptions.)] - (is (= opts (mc/->DeleteOptions {:delete-options opts})) "configure directly"))) - -(deftest test->RenameCollectionOptions - (is (instance? RenameCollectionOptions (mc/->RenameCollectionOptions {}))) - (are [expected arg] - (= expected (.isDropTarget (mc/->RenameCollectionOptions {:drop-target? arg}))) - true true - false false - false nil) - (let [opts (RenameCollectionOptions.)] - (is (= opts (mc/->RenameCollectionOptions {:rename-collection-options opts})) "configure directly"))) - -(deftest test->FindOneAndUpdateOptions - (is (instance? FindOneAndUpdateOptions (mc/->FindOneAndUpdateOptions {}))) - (let [opts (FindOneAndUpdateOptions.)] - (is (= opts (mc/->FindOneAndUpdateOptions {:find-one-and-update-options opts})) "configure directly")) - (are [expected arg] - (= expected (.isUpsert (mc/->FindOneAndUpdateOptions {:upsert? arg}))) - true true - false false - false nil) - (are [expected arg] - (= expected (.getReturnDocument (mc/->FindOneAndUpdateOptions {:return-new? arg}))) - (ReturnDocument/AFTER) true - (ReturnDocument/BEFORE) false - (ReturnDocument/BEFORE) nil) - - (is (= {"_id" 1} (.getSort (mc/->FindOneAndUpdateOptions {:sort {:_id 1}})))) - (is (= {"_id" 1} (.getProjection (mc/->FindOneAndUpdateOptions {:projection {:_id 1}}))))) - -(deftest test->FindOneAndReplaceOptions - (is (instance? FindOneAndReplaceOptions (mc/->FindOneAndReplaceOptions {}))) - (let [opts (FindOneAndReplaceOptions.)] - (is (= opts (mc/->FindOneAndReplaceOptions {:find-one-and-replace-options opts})) "configure directly")) - (are [expected arg] - (= expected (.isUpsert (mc/->FindOneAndReplaceOptions {:upsert? arg}))) - true true - false false - false nil) - (are [expected arg] - (= expected (.getReturnDocument (mc/->FindOneAndReplaceOptions {:return-new? arg}))) - (ReturnDocument/AFTER) true - (ReturnDocument/BEFORE) false - (ReturnDocument/BEFORE) nil) - - (is (= {"_id" 1} (.getSort (mc/->FindOneAndReplaceOptions {:sort {:_id 1}})))) - (is (= {"_id" 1} (.getProjection (mc/->FindOneAndReplaceOptions {:projection {:_id 1}}))))) - -(deftest test->CountOptions - (is (instance? CountOptions (mc/->CountOptions {}))) - (let [opts (CountOptions.)] - (is (= opts (mc/->CountOptions {:count-options opts})) "configure directly")) - (is (= {"a" 1} (.getHint (mc/->CountOptions {:hint {:a 1}})))) - (is (= 7 (.getLimit (mc/->CountOptions {:limit 7})))) - (is (= 2 (.getSkip (mc/->CountOptions {:skip 2})))) - (is (= 42 (.getMaxTime (mc/->CountOptions {:max-time-ms 42}) (TimeUnit/MILLISECONDS))))) - -(deftest test->IndexOptions - (is (instance? IndexOptions (mc/->IndexOptions {}))) - (are [expected arg] - (= expected (.isSparse (mc/->IndexOptions {:sparse? arg}))) - true true - false false - false nil) - (are [expected arg] - (= expected (.isUnique (mc/->IndexOptions {:unique? arg}))) - true true - false false - false nil) - (let [opts (IndexOptions.)] - (is (= opts (mc/->IndexOptions {:index-options opts})) "configure directly"))) - -(deftest test->CreateCollectionOptions - (are [expected arg] - (= expected (.isCapped (mc/->CreateCollectionOptions {:capped? arg}))) - true true - false false - false nil) - (is (= 7 (.getMaxDocuments (mc/->CreateCollectionOptions {:max-documents 7})))) - (is (= 42 (.getSizeInBytes (mc/->CreateCollectionOptions {:max-size-bytes 42})))) - (let [opts (-> (CreateCollectionOptions.) (.maxDocuments 5))] - (is (= opts (mc/->CreateCollectionOptions {:create-collection-options opts})) "configure directly") - (is (= 5 (.getMaxDocuments (mc/->CreateCollectionOptions {:create-collection-options opts})))) - (is (= 7 (.getMaxDocuments (mc/->CreateCollectionOptions {:create-collection-options opts :max-documents 7}))) - "can override"))) - ;;; Integration ; docker run -it --rm -p 27017:27017 mongo:4.2 diff --git a/test/mongo_driver_3/model_test.clj b/test/mongo_driver_3/model_test.clj new file mode 100644 index 0000000..4c6653c --- /dev/null +++ b/test/mongo_driver_3/model_test.clj @@ -0,0 +1,179 @@ +(ns mongo-driver-3.model-test + (:require [clojure.test :refer :all] + [mongo-driver-3.model :as m]) + (:import (com.mongodb ReadConcern ReadPreference WriteConcern) + (java.util.concurrent TimeUnit) + (com.mongodb.client.model InsertOneOptions InsertManyOptions DeleteOptions FindOneAndUpdateOptions ReturnDocument FindOneAndReplaceOptions CountOptions UpdateOptions ReplaceOptions IndexOptions CreateCollectionOptions RenameCollectionOptions))) + +;;; Unit + +(deftest test->ReadConcern + (is (nil? (m/->ReadConcern {}))) + (is (thrown? IllegalArgumentException (m/->ReadConcern {:read-concern "invalid"}))) + (is (instance? ReadConcern (m/->ReadConcern {:read-concern :available})))) + +(deftest test->ReadPreference + (is (nil? (m/->ReadPreference {}))) + (is (thrown? IllegalArgumentException (m/->ReadPreference {:read-preference "invalid"}))) + (is (instance? ReadPreference (m/->ReadPreference {:read-preference :primary})))) + +(deftest test->WriteConcern + (is (= (WriteConcern/W1) (m/->WriteConcern {:write-concern :w1})) "accepts kw") + (is (= (WriteConcern/W1) (m/->WriteConcern {:write-concern (WriteConcern/W1)})) "accepts WriteConcern") + (is (= (WriteConcern/ACKNOWLEDGED) (m/->WriteConcern {:write-concern "invalid"})) "defaults to acknowledged") + (is (= 1 (.getW (m/->WriteConcern {:write-concern/w 1}))) "set w") + (is (= 2 (.getW (m/->WriteConcern {:write-concern (WriteConcern/W2)})))) + (is (= 1 (.getW (m/->WriteConcern {:write-concern (WriteConcern/W2) :write-concern/w 1}))) "prefer granular option") + (is (true? (.getJournal (m/->WriteConcern {:write-concern/journal? true}))) "can set journal") + (is (= 77 (.getWTimeout (m/->WriteConcern {:write-concern/w-timeout-ms 77}) (TimeUnit/MILLISECONDS))) "can set timeout")) + +(deftest test->InsertOneOptions + (is (instance? InsertOneOptions (m/->InsertOneOptions {}))) + (is (true? (.getBypassDocumentValidation (m/->InsertOneOptions {:bypass-document-validation? true})))) + (is (true? (.getBypassDocumentValidation (m/->InsertOneOptions + {:insert-one-options (.bypassDocumentValidation (InsertOneOptions.) true)}))) + "configure directly") + (is (false? (.getBypassDocumentValidation (m/->InsertOneOptions + {:insert-one-options (.bypassDocumentValidation (InsertOneOptions.) true) + :bypass-document-validation? false}))) + "can override")) + +(deftest test->ReplaceOptions + (is (instance? ReplaceOptions (m/->ReplaceOptions {}))) + (are [expected arg] + (= expected (.isUpsert (m/->ReplaceOptions {:upsert? arg}))) + true true + false false + false nil) (is (true? (.getBypassDocumentValidation (m/->ReplaceOptions {:bypass-document-validation? true})))) + (is (true? (.getBypassDocumentValidation (m/->ReplaceOptions + {:replace-options (.bypassDocumentValidation (ReplaceOptions.) true)}))) + "configure directly") + (is (false? (.getBypassDocumentValidation (m/->ReplaceOptions + {:replace-options (.bypassDocumentValidation (ReplaceOptions.) true) + :bypass-document-validation? false}))) + "can override")) + +(deftest test->UpdateOptions + (is (instance? UpdateOptions (m/->UpdateOptions {}))) + (are [expected arg] + (= expected (.isUpsert (m/->UpdateOptions {:upsert? arg}))) + true true + false false + false nil) + (is (true? (.getBypassDocumentValidation (m/->UpdateOptions {:bypass-document-validation? true})))) + (is (true? (.getBypassDocumentValidation (m/->UpdateOptions + {:update-options (.bypassDocumentValidation (UpdateOptions.) true)}))) + "configure directly") + (is (false? (.getBypassDocumentValidation (m/->UpdateOptions + {:update-options (.bypassDocumentValidation (UpdateOptions.) true) + :bypass-document-validation? false}))) + "can override")) + +(deftest test->InsertManyOptions + (is (instance? InsertManyOptions (m/->InsertManyOptions {}))) + (are [expected arg] + (= expected (.getBypassDocumentValidation (m/->InsertManyOptions {:bypass-document-validation? arg}))) + true true + false false + nil nil) + (are [expected arg] + (= expected (.isOrdered (m/->InsertManyOptions {:ordered? arg}))) + true true + false false + true nil) + (is (true? (.getBypassDocumentValidation (m/->InsertManyOptions + {:insert-many-options (.bypassDocumentValidation (InsertManyOptions.) true)}))) + "configure directly") + (is (false? (.getBypassDocumentValidation (m/->InsertManyOptions + {:insert-one-options (.bypassDocumentValidation (InsertManyOptions.) true) + :bypass-document-validation? false}))) + "can override")) + +(deftest test->DeleteOptions + (is (instance? DeleteOptions (m/->DeleteOptions {}))) + (let [opts (DeleteOptions.)] + (is (= opts (m/->DeleteOptions {:delete-options opts})) "configure directly"))) + +(deftest test->RenameCollectionOptions + (is (instance? RenameCollectionOptions (m/->RenameCollectionOptions {}))) + (are [expected arg] + (= expected (.isDropTarget (m/->RenameCollectionOptions {:drop-target? arg}))) + true true + false false + false nil) + (let [opts (RenameCollectionOptions.)] + (is (= opts (m/->RenameCollectionOptions {:rename-collection-options opts})) "configure directly"))) + +(deftest test->FindOneAndUpdateOptions + (is (instance? FindOneAndUpdateOptions (m/->FindOneAndUpdateOptions {}))) + (let [opts (FindOneAndUpdateOptions.)] + (is (= opts (m/->FindOneAndUpdateOptions {:find-one-and-update-options opts})) "configure directly")) + (are [expected arg] + (= expected (.isUpsert (m/->FindOneAndUpdateOptions {:upsert? arg}))) + true true + false false + false nil) + (are [expected arg] + (= expected (.getReturnDocument (m/->FindOneAndUpdateOptions {:return-new? arg}))) + (ReturnDocument/AFTER) true + (ReturnDocument/BEFORE) false + (ReturnDocument/BEFORE) nil) + + (is (= {"_id" 1} (.getSort (m/->FindOneAndUpdateOptions {:sort {:_id 1}})))) + (is (= {"_id" 1} (.getProjection (m/->FindOneAndUpdateOptions {:projection {:_id 1}}))))) + +(deftest test->FindOneAndReplaceOptions + (is (instance? FindOneAndReplaceOptions (m/->FindOneAndReplaceOptions {}))) + (let [opts (FindOneAndReplaceOptions.)] + (is (= opts (m/->FindOneAndReplaceOptions {:find-one-and-replace-options opts})) "configure directly")) + (are [expected arg] + (= expected (.isUpsert (m/->FindOneAndReplaceOptions {:upsert? arg}))) + true true + false false + false nil) + (are [expected arg] + (= expected (.getReturnDocument (m/->FindOneAndReplaceOptions {:return-new? arg}))) + (ReturnDocument/AFTER) true + (ReturnDocument/BEFORE) false + (ReturnDocument/BEFORE) nil) + + (is (= {"_id" 1} (.getSort (m/->FindOneAndReplaceOptions {:sort {:_id 1}})))) + (is (= {"_id" 1} (.getProjection (m/->FindOneAndReplaceOptions {:projection {:_id 1}}))))) + +(deftest test->CountOptions + (is (instance? CountOptions (m/->CountOptions {}))) + (let [opts (CountOptions.)] + (is (= opts (m/->CountOptions {:count-options opts})) "configure directly")) + (is (= {"a" 1} (.getHint (m/->CountOptions {:hint {:a 1}})))) + (is (= 7 (.getLimit (m/->CountOptions {:limit 7})))) + (is (= 2 (.getSkip (m/->CountOptions {:skip 2})))) + (is (= 42 (.getMaxTime (m/->CountOptions {:max-time-ms 42}) (TimeUnit/MILLISECONDS))))) + +(deftest test->IndexOptions + (is (instance? IndexOptions (m/->IndexOptions {}))) + (are [expected arg] + (= expected (.isSparse (m/->IndexOptions {:sparse? arg}))) + true true + false false + false nil) + (are [expected arg] + (= expected (.isUnique (m/->IndexOptions {:unique? arg}))) + true true + false false + false nil) + (let [opts (IndexOptions.)] + (is (= opts (m/->IndexOptions {:index-options opts})) "configure directly"))) + +(deftest test->CreateCollectionOptions + (are [expected arg] + (= expected (.isCapped (m/->CreateCollectionOptions {:capped? arg}))) + true true + false false + false nil) + (is (= 7 (.getMaxDocuments (m/->CreateCollectionOptions {:max-documents 7})))) + (is (= 42 (.getSizeInBytes (m/->CreateCollectionOptions {:max-size-bytes 42})))) + (let [opts (-> (CreateCollectionOptions.) (.maxDocuments 5))] + (is (= opts (m/->CreateCollectionOptions {:create-collection-options opts})) "configure directly") + (is (= 5 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts})))) + (is (= 7 (.getMaxDocuments (m/->CreateCollectionOptions {:create-collection-options opts :max-documents 7}))) + "can override"))) \ No newline at end of file