diff --git a/ChangeLog.md b/ChangeLog.md index 99e3363..a6f681d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,19 @@ +## Changes between Neocons 2.1.0 and 3.0.0 + +Neocons no longer uses a dynamic var to hold the state of the connection. +This leads to significant changes to the API as the connection has to be +passed to functions. The position of the connection argument is always the +first argument for the sake of consistency. + +Additionally `connect!` function in `clojurewerkz.neocons.rest` no longer +exists. This has been replaced by function `connect` in `clojurewerkz.neocons.rest`. +The `connect` function has the same arguments as the `connect!` function +only it returns a `Connection` record. + +The `Connection` record has a key called `:options` which can be used to pass +additional parameters to be used by [clj-http](https://github.com/dakrone/clj-http) +like `debug`. + ## Changes between Neocons 2.0.0 and 2.1.0-beta1 ### Clojure 1.6 diff --git a/project.clj b/project.clj index c1e04ef..137d71a 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject clojurewerkz/neocons "2.1.0-beta1-SNAPSHOT" +(defproject clojurewerkz/neocons "3.0.0-SNAPSHOT" :description "Neocons is a feature rich idiomatic Clojure client for the Neo4J REST API" :url "http://clojureneo4j.info" :license {:name "Eclipse Public License"} diff --git a/src/clojure/clojurewerkz/neocons/rest.clj b/src/clojure/clojurewerkz/neocons/rest.clj index a4a2da6..23614c0 100644 --- a/src/clojure/clojurewerkz/neocons/rest.clj +++ b/src/clojure/clojurewerkz/neocons/rest.clj @@ -18,56 +18,58 @@ ;; ;; Implementation ;; +(defrecord Neo4JEndpoint + [version + node-uri + relationships-uri + node-index-uri + relationship-index-uri + relationship-types-uri + batch-uri + extensions-info-uri + extensions + reference-node-uri + uri + cypher-uri + transaction-uri]) + +(defrecord Connection [^Neo4JEndpoint endpoint http-auth options]) + (defn- env-var [^String s] (get (System/getenv) s)) (def ^{:private true} - global-options {:throw-entire-message? true}) + global-options {:throw-entire-message? true + :accept :json}) + +(defn- get-options + [^Connection connection options] + (merge global-options (:http-auth connection) (:options connection) options)) -(def ^{:private true} - http-authentication-options {}) (defn GET - [^String uri & {:as options}] + [^Connection connection ^String uri & {:as options}] (io! - (http/get uri (merge global-options http-authentication-options options {:accept :json})))) + (http/get uri (get-options connection options)))) (defn POST - [^String uri &{:keys [body] :as options}] + [^Connection connection ^String uri &{:keys [body] :as options}] (io! - (http/post uri (merge global-options http-authentication-options options {:accept :json :content-type :json :body body})))) + (http/post uri (merge (get-options connection options) + {:content-type :json :body body})))) (defn PUT - [^String uri &{:keys [body] :as options}] + [^Connection connection ^String uri &{:keys [body] :as options}] (io! - (http/put uri (merge global-options http-authentication-options options {:accept :json :content-type :json :body body})))) + (http/put uri (merge (get-options connection options) + {:content-type :json :body body})))) (defn DELETE - [^String uri &{:keys [body] :as options}] + [^Connection connection ^String uri &{:keys [body] :as options}] (io! - (http/delete uri (merge global-options http-authentication-options options {:accept :json})))) - - - - -(defrecord Neo4JEndpoint - [version - node-uri - relationships-uri - node-index-uri - relationship-index-uri - relationship-types-uri - batch-uri - extensions-info-uri - extensions - reference-node-uri - uri - cypher-uri - transaction-uri]) - -(def ^{:dynamic true} *endpoint*) + (http/delete uri (get-options connection options)))) ;; ;; API @@ -82,32 +84,31 @@ password (env-var "NEO4J_PASSWORD")] (connect uri login password))) ([^String uri login password] - (let [{ :keys [status body] } (if (and login password) - (GET uri :basic-auth [login password]) - (GET uri))] + (let [basic-auth (if (and login password) + {:basic-auth [login password]} + {}) + {:keys [status body]} (GET (map->Connection + {:http-auth basic-auth :options {}}) + uri)] (if (success? status) - (let [payload (json/decode body true)] - (alter-var-root (var http-authentication-options) (constantly { :basic-auth [login password] })) - (Neo4JEndpoint. (:neo4j_version payload) - (:node payload) - (str uri (if (.endsWith uri "/") - "relationship" - "/relationship")) - (:node_index payload) - (:relationship_index payload) - (:relationship_types payload) - (:batch payload) - (:extensions_info payload) - (:extensions payload) - (:reference_node payload) - (maybe-append uri "/") - (:cypher payload) - (:transaction payload) - )))))) - -(defn connect! - "Like connect but also mutates *endpoint* state to store the connection" - ([uri] - (alter-var-root (var *endpoint*) (fn [_] (connect uri)))) - ([uri login password] - (alter-var-root (var *endpoint*) (fn [_] (connect uri login password))))) + (let [payload (json/decode body true) + http-auth (:basic-auth basic-auth) + endpoint (Neo4JEndpoint. (:neo4j_version payload) + (:node payload) + (str uri (if (.endsWith uri "/") + "relationship" + "/relationship")) + (:node_index payload) + (:relationship_index payload) + (:relationship_types payload) + (:batch payload) + (:extensions_info payload) + (:extensions payload) + (:reference_node payload) + (maybe-append uri "/") + (:cypher payload) + (:transaction payload))] + (map->Connection + {:endpoint endpoint + :options {} + :http-auth http-auth})))))) diff --git a/src/clojure/clojurewerkz/neocons/rest/batch.clj b/src/clojure/clojurewerkz/neocons/rest/batch.clj index 4b85675..fbc54c2 100644 --- a/src/clojure/clojurewerkz/neocons/rest/batch.clj +++ b/src/clojure/clojurewerkz/neocons/rest/batch.clj @@ -12,7 +12,8 @@ "Batch operation execution" (:require [clojurewerkz.neocons.rest :as rest] [clojurewerkz.neocons.rest.records :as rec] - [cheshire.core :as json])) + [cheshire.core :as json]) + (:import clojurewerkz.neocons.rest.Connection)) @@ -35,7 +36,8 @@ If you need to insert a batch of nodes at once, consider using neocons.rest.nodes/create-batch. See http://docs.neo4j.org/chunked/milestone/rest-api-batch-ops.html for more information." - [ops] - (let [{:keys [status headers body]} (rest/POST (:batch-uri rest/*endpoint*) :body (json/encode ops)) + [^Connection connection ops] + (let [{:keys [status headers body]} (rest/POST connection (get-in connection [:endpoint :batch-uri]) + :body (json/encode ops)) payload (map :body (json/decode body true))] (map rec/instantiate-record-from payload))) diff --git a/src/clojure/clojurewerkz/neocons/rest/constraints.clj b/src/clojure/clojurewerkz/neocons/rest/constraints.clj index 76b2b1a..897aab5 100644 --- a/src/clojure/clojurewerkz/neocons/rest/constraints.clj +++ b/src/clojure/clojurewerkz/neocons/rest/constraints.clj @@ -14,30 +14,33 @@ [cheshire.core :as json] [clojurewerkz.neocons.rest.conversion :as conv] [clojurewerkz.support.http.statuses :refer [missing?]]) + (:import clojurewerkz.neocons.rest.Connection) (:refer-clojure :exclude [rest])) (defn- get-url - [^String label] - (str (:uri rest/*endpoint*) "schema/constraint/" (conv/encode-kw-to-string label))) + [^Connection connection ^String label] + (str (get-in connection [:endpoint :uri]) "schema/constraint/" (conv/encode-kw-to-string label))) (defn- get-uniqueness-url - [label] - (str (get-url label) "/uniqueness")) + [^Connection connection label] + (str (get-url connection label) "/uniqueness")) (defn create-unique "Creates a unique constraint on a given label and property. See http://docs.neo4j.org/chunked/milestone/rest-api-schema-constraints.html#rest-api-create-uniqueness-constraint" - [label property] + [^Connection connection label property] (let [req-body (json/encode {"property_keys" [(conv/kw-to-string property)]}) - {:keys [status headers body]} (rest/POST (get-uniqueness-url label) :body req-body)] + {:keys [status headers body]} (rest/POST connection (get-uniqueness-url connection label) + :body req-body)] (when-not (missing? status) (conv/map-values-to-kw (json/decode body true) [:label :property-keys])))) (defn- get-uniquess-constraints - [label ^String uri] - (let [{:keys [status headers body]} (rest/GET (str (get-url label) uri))] + [^Connection connection label ^String uri] + (let [{:keys [status headers body]} (rest/GET connection (str (get-url connection label) + uri))] (when-not (missing? status) (map #(conv/map-values-to-kw % [:label :property-keys]) @@ -49,10 +52,10 @@ See http://docs.neo4j.org/chunked/milestone/rest-api-schema-constraints.html#rest-api-get-all-uniqueness-constraints-for-a-label and http://docs.neo4j.org/chunked/milestone/rest-api-schema-constraints.html#rest-api-get-all-constraints-for-a-label" - ([label] - (get-uniquess-constraints label "/uniqueness")) - ([label property] - (get-uniquess-constraints label (str "/uniqueness/" (conv/encode-kw-to-string property))))) + ([^Connection connection label] + (get-uniquess-constraints connection label "/uniqueness")) + ([^Connection connection label property] + (get-uniquess-constraints connection label (str "/uniqueness/" (conv/encode-kw-to-string property))))) (defn get-all "Gets information about all the different constraints associated with a label. @@ -60,15 +63,13 @@ If no label is passed, gets information about all the constraints. http://docs.neo4j.org/chunked/milestone/rest-api-schema-constraints.html#rest-api-get-all-constraints" - ([] - (get-uniquess-constraints "" "")) - ([label] - (get-uniquess-constraints label ""))) + ([^Connection connection ] + (get-uniquess-constraints connection "" "")) + ([^Connection connection label] + (get-uniquess-constraints connection label ""))) (defn drop-unique "Drops an existing uniquenss constraint on an label and property. See http://docs.neo4j.org/chunked/milestone/rest-api-schema-constraints.html#rest-api-drop-constraint" - - [label property] - (rest/DELETE (str (get-uniqueness-url label) "/" (conv/encode-kw-to-string property)))) - + [^Connection connection label property] + (rest/DELETE connection (str (get-uniqueness-url connection label) "/" (conv/encode-kw-to-string property)))) diff --git a/src/clojure/clojurewerkz/neocons/rest/cypher.clj b/src/clojure/clojurewerkz/neocons/rest/cypher.clj index 3bb794b..29024aa 100644 --- a/src/clojure/clojurewerkz/neocons/rest/cypher.clj +++ b/src/clojure/clojurewerkz/neocons/rest/cypher.clj @@ -16,7 +16,7 @@ [clojurewerkz.neocons.rest.helpers :refer :all] [clojurewerkz.neocons.rest.records :refer :all]) (:import [java.net URI URL] - clojurewerkz.neocons.rest.Neo4JEndpoint + clojurewerkz.neocons.rest.Connection clojurewerkz.neocons.rest.records.CypherQueryResponse)) ;; @@ -24,8 +24,8 @@ ;; (defn cypher-query-location-for - [^Neo4JEndpoint endpoint] - (:cypher-uri endpoint)) + [^Connection connection] + (get-in connection [:endpoint :cypher-uri])) @@ -44,12 +44,12 @@ (defn query "Performs a Cypher query, returning columns and rows separately (the way Neo4J REST API does)" - ([^String q] - (query q {})) - ([^String q params] - (let [{:keys [status headers body]} (rest/POST (cypher-query-location-for rest/*endpoint*) :body (json/encode {:query q :params params}))] - (if (missing? status) - nil + ([^Connection connection ^String q] + (query connection q {})) + ([^Connection connection ^String q params] + (let [{:keys [status headers body]} (rest/POST connection (cypher-query-location-for connection) + :body (json/encode {:query q :params params}))] + (when-not (missing? status) (instantiate-cypher-query-response-from (json/decode body true)))))) (def ^{:doc "Performs a Cypher query, returning result formatted as a table (using tableize)"} diff --git a/src/clojure/clojurewerkz/neocons/rest/index.clj b/src/clojure/clojurewerkz/neocons/rest/index.clj index a3a8b68..09eb328 100644 --- a/src/clojure/clojurewerkz/neocons/rest/index.clj +++ b/src/clojure/clojurewerkz/neocons/rest/index.clj @@ -14,18 +14,20 @@ [cheshire.core :as json] [clojurewerkz.neocons.rest.conversion :as conv] [clojurewerkz.support.http.statuses :refer [missing?]]) + (:import [clojurewerkz.neocons.rest Connection]) (:refer-clojure :exclude [drop])) (defn- get-url - [label] - (str (:uri rest/*endpoint*) "schema/index/" (conv/kw-to-string label))) + [^Connection connection label] + (str (get-in connection [:endpoint :uri]) "schema/index/" (conv/kw-to-string label))) (defn create "Creates an index on a given label and property. See http://docs.neo4j.org/chunked/milestone/rest-api-schema-indexes.html#rest-api-create-index" - [label property] + [^Connection connection label property] (let [req-body (json/encode {"property_keys" [(conv/kw-to-string property)]}) - {:keys [status headers body]} (rest/POST (get-url label) :body req-body)] + {:keys [status headers body]} (rest/POST connection (get-url connection label) + :body req-body)] (when-not (missing? status) (conv/map-values-to-kw (json/decode body true) @@ -35,13 +37,13 @@ "Gets all indices for a given label. See http://docs.neo4j.org/chunked/milestone/rest-api-schema-indexes.html#rest-api-list-indexes-for-a-label" - [label] - (let [{:keys [status headers body]} (rest/GET (get-url label))] + [^Connection connection label] + (let [{:keys [status headers body]} (rest/GET connection (get-url connection label))] (when-not (missing? status) (json/decode body true)))) (defn drop "Drops an index on an existing label and property. See http://docs.neo4j.org/chunked/milestone/rest-api-schema-indexes.html#rest-api-list-indexes-for-a-label" - [label property] - (rest/DELETE (str (get-url label) "/" (conv/kw-to-string property)))) + [^Connection connection label property] + (rest/DELETE connection (str (get-url connection label) "/" (conv/kw-to-string property)))) diff --git a/src/clojure/clojurewerkz/neocons/rest/labels.clj b/src/clojure/clojurewerkz/neocons/rest/labels.clj index d2f725d..7dd31ec 100644 --- a/src/clojure/clojurewerkz/neocons/rest/labels.clj +++ b/src/clojure/clojurewerkz/neocons/rest/labels.clj @@ -17,7 +17,8 @@ [clojurewerkz.neocons.rest.conversion :as conv] [clojurewerkz.neocons.rest.records :as records] [clojurewerkz.support.http.statuses :refer [missing?]]) - (:refer-clojure :exclude [replace remove rest])) + (:import [clojurewerkz.neocons.rest Connection]) + (:refer-clojure :exclude [node replace remove rest])) (defn- get-location-url [node] @@ -26,30 +27,33 @@ (defn add "Adds a string label or a list of labels (string or keyword) to a node. See http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-adding-a-label-to-a-node" - [node labels] + [^Connection connection node labels] (rest/POST + connection (get-location-url node) :body (json/encode (conv/kw-to-string labels)))) (defn replace "This removes any existing labels for the node and adds the labels passes to the function. See http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-replacing-labels-on-a-node" - [node labels] + [^Connection connection node labels] (conv/string-to-kw (rest/PUT + connection (get-location-url node) :body (json/encode labels)))) (defn remove "This removes the specified label from the node. See http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-removing-a-label-from-a-node" - [node label] + [^Connection connection node label] (rest/DELETE - (str (get-location-url node) "/" (conv/encode-kw-to-string label)))) + connection + (str (get-location-url node) "/" (conv/encode-kw-to-string label)))) (defn- get-labels - [^String uri] - (let [{:keys [status headers body]} (rest/GET uri)] + [^Connection connection ^String uri] + (let [{:keys [status headers body]} (rest/GET connection uri)] (when-not (missing? status) (conv/string-to-kw (json/decode body true))))) @@ -60,14 +64,14 @@ See http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-listing-labels-for-a-node and http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-list-all-labels" - ([] - (get-labels (str (:uri rest/*endpoint*) "labels"))) - ([node] - (get-labels (get-location-url node)))) + ([^Connection connection] + (get-labels connection (str (get-in connection [:endpoint :uri]) "labels"))) + ([^Connection connection node] + (get-labels connection (get-location-url node)))) (defn- encode-params - [^String label ^String x y] - (str (:uri rest/*endpoint*) + [^Connection connection ^String label ^String x y] + (str (get-in connection [:endpoint :uri]) "label/" (conv/encode-kw-to-string label) "/nodes" @@ -83,10 +87,10 @@ You can also pass a property name and value you want to filter the nodes on. See http://docs.neo4j.org/chunked/milestone/rest-api-node-labels.html#rest-api-get-nodes-by-label-and-property" - ([label] - (get-all-nodes label nil nil)) - ([label prop-name prop-value] - (let [base-uri (encode-params label prop-name prop-value) - {:keys [status headers body]} (rest/GET base-uri)] + ([^Connection connection label] + (get-all-nodes connection label nil nil)) + ([^Connection connection label prop-name prop-value] + (let [base-uri (encode-params connection label prop-name prop-value) + {:keys [status headers body]} (rest/GET connection base-uri)] (when-not (missing? status) (map records/instantiate-node-from (json/decode body true)))))) diff --git a/src/clojure/clojurewerkz/neocons/rest/nodes.clj b/src/clojure/clojurewerkz/neocons/rest/nodes.clj index caae9d1..bb56a90 100644 --- a/src/clojure/clojurewerkz/neocons/rest/nodes.clj +++ b/src/clojure/clojurewerkz/neocons/rest/nodes.clj @@ -13,7 +13,6 @@ [cheshire.core :as json] [clojurewerkz.neocons.rest :as rest] [clojurewerkz.neocons.rest.relationships :as relationships] - [clojurewerkz.neocons.rest.paths :as paths] [clojurewerkz.neocons.rest.cypher :as cypher] [clojurewerkz.support.http.statuses :refer :all] [clojurewerkz.neocons.rest.helpers :refer :all] @@ -21,7 +20,7 @@ [clojure.string :refer [join]] [clojurewerkz.neocons.rest.conversion :refer [to-id]]) (:import [java.net URI URL] - clojurewerkz.neocons.rest.Neo4JEndpoint + [clojurewerkz.neocons.rest Connection] [clojurewerkz.neocons.rest.records Node Relationship Index] clojure.lang.Named) (:refer-clojure :exclude [get find])) @@ -40,17 +39,17 @@ (declare add-to-index) (defn create "Creates and returns a node with given properties. 0-arity creates a node without properties." - ([] - (create {})) - ([data] - (let [{:keys [status headers body]} (rest/POST (:node-uri rest/*endpoint*) :body (json/encode data)) + ([^Connection connection] + (create connection {})) + ([^Connection connection data] + (let [{:keys [status headers body]} (rest/POST connection (get-in connection [:endpoint :node-uri]) :body (json/encode data)) payload (json/decode body true) location (:self payload)] (Node. (extract-id location) location data (:relationships payload) (:create_relationship payload)))) - ([data indexes] - (let [node (create data)] + ([^Connection connection data indexes] + (let [node (create connection data)] (doseq [[idx [k v]] indexes] - (add-to-index node idx k v)) + (add-to-index connection node idx k v)) node))) (defn create-unique-in-index @@ -60,10 +59,10 @@ only a single request. For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-unique-indexes.html section (19.8.1)" - [idx k v data] + [^Connection connection idx k v data] (let [req-body (json/encode {:key k :value v :properties data}) - uri (str (url-with-path (:node-index-uri rest/*endpoint*) idx) "?unique") - {:keys [status headers body]} (rest/POST uri :body req-body) + uri (str (url-with-path (get-in connection [:endpoint :node-index-uri]) idx) "?unique") + {:keys [status headers body]} (rest/POST connection uri :body req-body) payload (json/decode body true) location (:self payload)] (Node. (extract-id location) location (:data payload) (:relationships payload) (:create_relationship payload)))) @@ -73,25 +72,25 @@ of nodes. This function returns a lazy sequence of results, so you may need to force it using clojure.core/doall" - [xs] + [^Connection connection xs] (let [batched (doall (reduce (fn [acc x] (conj acc {:body x :to "/node" :method "POST"})) [] xs)) - {:keys [status headers body]} (rest/POST (:batch-uri rest/*endpoint*) :body (json/encode batched)) + {:keys [status headers body]} (rest/POST connection (get-in connection [:endpoint :batch-uri]) :body (json/encode batched)) payload (map :body (json/decode body true))] (map instantiate-node-from payload))) (defn get "Fetches a node by id" - [^long id] - (let [{:keys [status body]} (rest/GET (node-location-for rest/*endpoint* id)) + [^Connection connection ^long id] + (let [{:keys [status body]} (rest/GET connection (node-location-for (:endpoint connection) id)) payload (json/decode body true)] (instantiate-node-from payload id))) (defn get-properties - [^long id] - (let [{:keys [status headers body]} (rest/GET (node-properties-location-for rest/*endpoint* id))] + [^Connection connection ^long id] + (let [{:keys [status headers body]} (rest/GET connection (node-properties-location-for (:endpoint connection) id))] (case (long status) 200 (json/decode body true) 204 {} @@ -102,77 +101,108 @@ This is a non-standard operation that requires Cypher support as well as support for that very feature by Cypher itself (Neo4j Server versions 1.6.3 and later)." - ([coll] - (let [{:keys [data]} (cypher/query "START x = node({ids}) RETURN x" {:ids coll})] + ([^Connection connection coll] + (let [{:keys [data]} (cypher/query connection "START x = node({ids}) RETURN x" {:ids coll})] (map (comp instantiate-node-from first) data)))) (defn ^{:deprecated true} multi-get "Fetches multiple nodes by id. Deprecated, please use get-many instead." - [coll] - (apply get-many coll)) - -(defprotocol MutatingOperations - (delete [node] "Deletes a node. The node must have no relationships") - (destroy [node] "Deletes a node and all of its relationships") - (update [node data] "Updates a node's data (properties)") - (set-property [node prop value] "Sets a single property on the given node")) - -(extend-protocol MutatingOperations - Node - (delete [^Node node] - (delete (:id node))) - (destroy [^Node node] - (relationships/purge-all node) - (delete (:id node))) - (update [^Node node data] - (update (:id node) data)) - (set-property [^Node node prop value] - (set-property (:id node) prop value)) - - Long - (delete [^long id] - (let [{:keys [status headers]} (rest/DELETE (node-location-for rest/*endpoint* id))] + [^Connection connection coll] + (apply get-many connection coll)) + + +(defmulti update + "Updated a node's data (properties)" + (fn [_ node _] + (class node))) + +(defmethod update Node + [^Connection connection ^Node node data] + (update connection (:id node) data)) + +(defmethod update Long + [^Connection connection ^long id data] + (rest/PUT connection (node-properties-location-for (:endpoint connection) id) :body (json/encode data)) + data) + + +(defmulti delete + "Deletes a node. The node must have no relationships" + (fn [_ node] + (class node))) + +(defmethod delete Node + [^Connection connection ^Node node] + (delete connection (:id node))) + +(defmethod delete Long + [^Connection connection ^long id] + (let [{:keys [status headers]} (rest/DELETE connection (node-location-for (:endpoint connection) id))] [id status])) - (destroy [^long id] - ;; a little hack. Relationships purging implementation only needs - ;; id to be set on Node so we don't have to fetch the entire set of properties. MK. - (relationships/purge-all (Node. id nil nil nil nil)) - (delete id)) - (update [^long id data] - (rest/PUT (node-properties-location-for rest/*endpoint* id) :body (json/encode data)) - data) - (set-property [^long id prop value] - (rest/PUT (node-property-location-for rest/*endpoint* id prop) :body (json/encode value)) - value)) + + +(defmulti destroy + "Deletes a node and all of its relationships" + (fn [_ node] + (class node))) + +(defmethod destroy Node + [^Connection connection ^Node node] + (relationships/purge-all connection node) + (delete connection (:id node))) + +(defmethod destroy Long + [^Connection connection ^long id] + ;; a little hack. Relationships purging implementation only needs + ;; id to be set on Node so we don't have to fetch the entire set of properties. MK. + (relationships/purge-all connection (Node. id nil nil nil nil)) + (delete connection id)) + + +(defmulti set-property + "Sets a single property on the given node" + (fn [_ node _ _] + (class node))) + +(defmethod set-property Node + [^Connection connection ^Node node prop value] + (set-property connection (:id node) prop value)) + +(defmethod set-property Long + [^Connection connection ^long id prop value] + (rest/PUT connection (node-property-location-for (:endpoint connection) id prop) :body (json/encode value)) + value) + (defn delete-many "Deletes multiple nodes" - [xs] + [^Connection connection xs] (comment Once 1.8 is out, we should migrate this to mutating Cypher to avoid doing N requests) (doseq [x xs] - (delete x))) + (delete connection x))) (defn destroy-many "Destroys multiple nodes and all of their relationships" - [xs] + [^Connection connection xs] (comment Once 1.8 is out, we should migrate this to mutating Cypher to avoid doing N requests) (doseq [x xs] - (destroy x))) + (destroy connection x))) (defn delete-properties - [^long id] - (let [{:keys [status headers]} (rest/PUT (node-properties-location-for rest/*endpoint* id))] + [^Connection connection ^long id] + (let [{:keys [status headers]} (rest/PUT connection (node-properties-location-for (:endpoint connection) id))] [id status])) (defn create-index "Creates a new node index. Indexes are used for fast lookups by a property or full text search query." - ([^String s] - (let [{:keys [body]} (rest/POST (:node-index-uri rest/*endpoint*) :body (json/encode {:name (name s)})) + ([^Connection connection ^String s] + (let [{:keys [body]} (rest/POST connection (get-in connection [:endpoint :node-index-uri]) + :body (json/encode {:name (name s)})) payload (json/decode body true)] (Index. (name s) (:template payload) "lucene" "exact"))) - ([^String s configuration] - (let [{:keys [body]} (rest/POST (:node-index-uri rest/*endpoint*) + ([^Connection connection ^String s configuration] + (let [{:keys [body]} (rest/POST connection (get-in connection [:endpoint :node-index-uri]) :query-string (if (:unique configuration) {"unique" "true"} {}) @@ -182,15 +212,15 @@ (defn delete-index "Deletes a node index" - [^String s] - (let [{:keys [status]} (rest/DELETE (node-index-location-for rest/*endpoint* s))] + [^Connection connection ^String s] + (let [{:keys [status]} (rest/DELETE connection (node-index-location-for (:endpoint connection) s))] [s status])) (defn all-indexes "Returns all node indices" - [] - (let [{:keys [status body]} (rest/GET (:node-index-uri rest/*endpoint*))] + [^Connection connection] + (let [{:keys [status body]} (rest/GET connection (get-in connection [:endpoint :node-index-uri]))] (if (= 204 (long status)) [] (map (fn [[idx props]] (Index. (name idx) (:template props) (:provider props) (:type props))) @@ -199,38 +229,40 @@ (defn add-to-index "Adds the given node to the index" - ([node idx ^String key value] - (add-to-index node idx key value false)) - ([node idx ^String key value unique?] + ([^Connection connection node idx ^String key value] + (add-to-index connection node idx key value false)) + ([^Connection connection node idx ^String key value unique?] (let [id (to-id node) - req-body (json/encode {:key (name key) :value value :uri (node-location-for rest/*endpoint* (to-id node))}) - {:keys [status body]} (rest/POST (node-index-location-for rest/*endpoint* idx) :body req-body :query-string (if unique? - {"unique" "true"} - {})) + req-body (json/encode {:key (name key) :value value :uri (node-location-for (:endpoint connection) (to-id node))}) + {:keys [status body]} (rest/POST connection (node-index-location-for (:endpoint connection) idx) + :body req-body + :query-string (if unique? + {"unique" "true"} + {})) payload (json/decode body true)] (instantiate-node-from payload id)))) (defn delete-from-index "Deletes the given node from index" - ([node idx] + ([^Connection connection node idx] (let [id (to-id node) - {:keys [status]} (rest/DELETE (node-in-index-location-for rest/*endpoint* id idx))] + {:keys [status]} (rest/DELETE connection (node-in-index-location-for (:endpoint connection) id idx))] [id status])) - ([node idx key] + ([^Connection connection node idx key] (let [id (to-id node) - {:keys [status]} (rest/DELETE (node-in-index-location-for rest/*endpoint* id idx key))] + {:keys [status]} (rest/DELETE connection (node-in-index-location-for (:endpoint connection) id idx key))] [id status])) - ([node idx key value] + ([^Connection connection node idx key value] (let [id (to-id node) - {:keys [status]} (rest/DELETE (node-in-index-location-for rest/*endpoint* id idx key value))] + {:keys [status]} (rest/DELETE connection (node-in-index-location-for (:endpoint connection) id idx key value))] [id status]))) (defn fetch-from "Fetches a node from given URI. Exactly like clojurewerkz.neocons.rest.nodes/get but takes a URI instead of an id." - [^String uri] - (let [{:keys [status body]} (rest/GET uri) + [^Connection connection ^String uri] + (let [{:keys [status body]} (rest/GET connection uri) payload (json/decode body true) id (extract-id uri)] (instantiate-node-from payload id))) @@ -238,66 +270,68 @@ (defn find "Finds nodes using the index" - ([^String key value] - (let [{:keys [status body]} (rest/GET (auto-node-index-lookup-location-for rest/*endpoint* key value)) + ([^Connection connection ^String key value] + (let [{:keys [status body]} (rest/GET connection (auto-node-index-lookup-location-for (:endpoint connection) key value)) xs (json/decode body true)] - (map (fn [doc] (fetch-from (:indexed doc))) xs))) - ([^String idx ^String key value] - (let [{:keys [status body]} (rest/GET (node-index-lookup-location-for rest/*endpoint* idx key value)) + (map (fn [doc] (fetch-from connection (:indexed doc))) xs))) + ([^Connection connection ^String idx ^String key value] + (let [{:keys [status body]} (rest/GET connection (node-index-lookup-location-for (:endpoint connection) idx key value)) xs (json/decode body true)] - (map (fn [doc] (fetch-from (:indexed doc))) xs)))) + (map (fn [doc] (fetch-from connection (:indexed doc))) xs)))) (defn find-one "Finds a single node using the index" - [^String idx ^String key value] - (let [{:keys [status body]} (rest/GET (node-index-lookup-location-for rest/*endpoint* idx key value)) + [^Connection connection ^String idx ^String key value] + (let [{:keys [status body]} (rest/GET connection (node-index-lookup-location-for (:endpoint connection) idx key value)) [node] (json/decode body true)] (when node - (fetch-from (:indexed node))))) + (fetch-from connection (:indexed node))))) (defn query "Finds nodes using full text search query" - ([^String query] - (let [{:keys [status body]} (rest/GET (auto-node-index-location-for rest/*endpoint*) :query-params {"query" query}) + ([^Connection connection ^String query] + (let [{:keys [status body]} (rest/GET connection (auto-node-index-location-for (:endpoint connection)) + :query-params {"query" query}) xs (json/decode body true)] - (map (fn [doc] (instantiate-node-from doc)) xs))) - ([^String idx ^String query] - (let [{:keys [status body]} (rest/GET (node-index-location-for rest/*endpoint* idx) :query-params {"query" query}) + (map instantiate-node-from xs))) + ([^Connection connection ^String idx ^String query] + (let [{:keys [status body]} (rest/GET connection (node-index-location-for (:endpoint connection) idx) + :query-params {"query" query}) xs (json/decode body true)] - (map (fn [doc] (instantiate-node-from doc)) xs)))) + (map instantiate-node-from xs)))) (defn traverse "Performs node traversal" - ([id & {:keys [order relationships - uniqueness prune-evaluator - return-filter max-depth] :or {order "breadth_first" - uniqueness "node_global" - prune-evaluator {:language "builtin" :name "none"} - return-filter {:language "builtin" :name "all"}}}] + ([^Connection connection id & {:keys [order relationships + uniqueness prune-evaluator + return-filter max-depth] :or {order "breadth_first" + uniqueness "node_global" + prune-evaluator {:language "builtin" :name "none"} + return-filter {:language "builtin" :name "all"}}}] (let [request-body {:order order :relationships relationships :uniqueness uniqueness :prune_evaluator prune-evaluator :return_filter return-filter :max_depth max-depth} - {:keys [status body]} (rest/POST (node-traverse-location-for rest/*endpoint* id) :body (json/encode request-body)) + {:keys [status body]} (rest/POST connection (node-traverse-location-for (:endpoint connection) id) + :body (json/encode request-body)) xs (json/decode body true)] - (map (fn [doc] - (instantiate-node-from doc)) xs)))) + (map instantiate-node-from xs)))) (defn all-connected-out "Returns all nodes given node has outgoing (outbound) relationships with" - [id &{:keys [types]}] - (let [rels (relationships/outgoing-for (get id) :types types) + [^Connection connection id &{:keys [types]}] + (let [rels (relationships/outgoing-for connection (get connection id) :types types) ids (set (map #(extract-id (:end %)) rels))] - (get-many ids))) + (get-many connection ids))) (defn connected-out? "Returns true if given node has outgoing (outbound) relationships with the other node" - [id other-id &{:keys [types]}] - (let [rels (relationships/outgoing-for (get id) :types types) + [^Connection connection id other-id &{:keys [types]}] + (let [rels (relationships/outgoing-for connection (get connection id) :types types) uris (set (map :end rels))] - (uris (node-location-for rest/*endpoint* other-id)))) + (uris (node-location-for (:endpoint connection) other-id)))) diff --git a/src/clojure/clojurewerkz/neocons/rest/paths.clj b/src/clojure/clojurewerkz/neocons/rest/paths.clj index ebde29b..f649ee9 100644 --- a/src/clojure/clojurewerkz/neocons/rest/paths.clj +++ b/src/clojure/clojurewerkz/neocons/rest/paths.clj @@ -10,7 +10,7 @@ (ns clojurewerkz.neocons.rest.paths (:import [java.net URI URL] - clojurewerkz.neocons.rest.Neo4JEndpoint + clojurewerkz.neocons.rest.Connection [clojurewerkz.neocons.rest.records Node Relationship Path]) (:require [cheshire.core :as json] [clojurewerkz.neocons.rest :as rest] @@ -30,91 +30,107 @@ ;; (defn traverse - ([id & { :keys [order relationships uniqueness prune-evaluator return-filter max-depth] :or { - order "breadth_first" - uniqueness "none" - prune-evaluator { :language "builtin" :name "none" } - return-filter { :language "builtin" :name "all" } - } }] + ([^Connection connection id & {:keys [order relationships uniqueness prune-evaluator return-filter max-depth] + :or {order "breadth_first" + uniqueness "none" + prune-evaluator {:language "builtin" :name "none"} + return-filter {:language "builtin" :name "all"}}}] (check-not-nil! id "id must not be nil") - (let [request-body { - :order order + (let [request-body {:order order :relationships relationships :uniqueness uniqueness :prune_evaluator prune-evaluator :return_filter return-filter - :max_depth max-depth - } - { :keys [status body] } (rest/POST (path-traverse-location-for rest/*endpoint* id) :body (json/encode request-body)) + :max_depth max-depth} + { :keys [status body] } (rest/POST connection (path-traverse-location-for (:endpoint connection) id) + :body (json/encode request-body)) xs (json/decode body true)] - (map (fn [doc] - (instantiate-path-from doc)) xs)))) + (map instantiate-path-from xs)))) (defn all-shortest-between - ([from to & { :keys [relationships max-depth] }] + ([^Connection connection from to & { :keys [relationships max-depth] }] (check-not-nil! from "from argument must not be nil") (check-not-nil! to "to argument must not be nil") - (let [request-body { - :to (node-location-for rest/*endpoint* to) + (let [request-body {:to (node-location-for (:endpoint connection) to) :relationships relationships :max_depth max-depth - :algorithm "shortestPath" - } - { :keys [status body] } (rest/POST (paths-location-for rest/*endpoint* from) :body (json/encode request-body)) + :algorithm "shortestPath"} + { :keys [status body] } (rest/POST connection (paths-location-for (:endpoint connection) from) + :body (json/encode request-body)) xs (json/decode body true)] - (map (fn [doc] - (instantiate-path-from doc)) (json/decode body true))))) + (map instantiate-path-from (json/decode body true))))) (defn shortest-between - ([from to & { :keys [relationships max-depth] }] + ([^Connection connection from to & { :keys [relationships max-depth] }] (check-not-nil! from "from argument must not be nil") (check-not-nil! to "to argument must not be nil") - (let [request-body { - :to (node-location-for rest/*endpoint* to) + (let [request-body {:to (node-location-for (:endpoint connection) to) :relationships relationships :max_depth max-depth - :algorithm "shortestPath" - } - { :keys [status body] } (rest/POST (path-location-for rest/*endpoint* from) :body (json/encode request-body) :throw-exceptions false)] - (if (or (missing? status) - (server-error? status)) - nil + :algorithm "shortestPath"} + { :keys [status body] } (rest/POST connection (path-location-for (:endpoint connection) from) + :body (json/encode request-body) + :throw-exceptions false)] + (when-not (or (missing? status) + (server-error? status)) (instantiate-path-from (json/decode body true)))))) (defn exists-between? - [from to &{ :keys [relationships max-depth prune-evaluator uniqueness] }] + [^Connection connection from to &{ :keys [relationships max-depth prune-evaluator uniqueness] }] (check-not-nil! from "from argument must not be nil") (check-not-nil! to "to argument must not be nil") - (not (nil? (shortest-between from to :relationships relationships :max-depth max-depth :prune-evaluator prune-evaluator :uniqueness uniqueness)))) + (not (nil? (shortest-between connection from to :relationships relationships :max-depth max-depth :prune-evaluator prune-evaluator :uniqueness uniqueness)))) -(defprotocol PathPredicates - (included-in? [obj path] "Returns true if path includes given obj which can be a node or a relationship") - (node-in? [node path] "Returns true if path includes given node") - (relationship-in? [rel path] "Returns true if path includes given relationship")) +(declare node-in?) +(declare relationship-in?) -(extend-protocol PathPredicates - Long - (node-in? [^long node ^Path path] - (let [uri (node-location-for rest/*endpoint* node)] +(defmulti included-in? + "Returns true if path includes given obj which can be a node or a relationship" + (fn [_ obj _] + (class obj))) + +(defmethod included-in? Node + [^Connection connection ^Node node ^Path path] + (node-in? connection (:id node) path)) + +(defmethod included-in? Relationship + [^Connection connection ^Relationship rel ^Path path] + (relationship-in? connection (:id rel) path)) + + +(defmulti node-in? + "Returns true if path includes given node" + (fn [_ obj _] + (class obj))) + +(defmethod node-in? Node + [^Connection connection ^Node node ^Path path] + (node-in? connection (:id node) path)) + +(defmethod node-in? Long + [^Connection connection ^long node ^Path path] + (let [uri (node-location-for (:endpoint connection) node)] (some (fn [u] (= uri u)) (:nodes path)))) - (relationship-in? [^long rel ^Path path] - (let [uri (rel-location-for rest/*endpoint* rel)] + + +(defmulti relationship-in? + "Returns true if path includes given relationship" + (fn [_ obj _] + (class obj))) + + +(defmethod relationship-in? Long + [^Connection connection ^long rel ^Path path] + (let [uri (rel-location-for (:endpoint connection) rel)] (some (fn [u] (= uri u)) (:relationships path)))) - Node - (included-in? [^Node node ^Path path] - (node-in? (:id node) path)) - (node-in? [^Node node ^Path path] - (node-in? (:id node) path)) - - Relationship - (included-in? [^Relationship rel ^Path path] - (relationship-in? (:id rel) path)) - (relationship-in? [^Relationship rel ^Path path] - (relationship-in? (:id rel) path))) + +(defmethod relationship-in? Relationship + [^Connection connection ^Relationship rel ^Path path] + (relationship-in? connection (:id rel) path)) diff --git a/src/clojure/clojurewerkz/neocons/rest/relationships.clj b/src/clojure/clojurewerkz/neocons/rest/relationships.clj index 8819423..5d699ae 100644 --- a/src/clojure/clojurewerkz/neocons/rest/relationships.clj +++ b/src/clojure/clojurewerkz/neocons/rest/relationships.clj @@ -20,7 +20,7 @@ [clojure.string :refer [join]] [clojurewerkz.neocons.rest.conversion :refer [to-id]]) (:import [java.net URI URL] - clojurewerkz.neocons.rest.Neo4JEndpoint + [clojurewerkz.neocons.rest Connection Neo4JEndpoint] [clojurewerkz.neocons.rest.records Node Relationship Index])) ;; @@ -39,11 +39,10 @@ (str (:node-uri endpoint) "/" (to-id node) "/relationships/")) (defn- relationships-for - [^Node node kind types] - (let [{ :keys [status headers body] } (rest/GET (relationships-location-for rest/*endpoint* node kind types)) + [^Connection connection ^Node node kind types] + (let [{ :keys [status headers body] } (rest/GET connection (relationships-location-for (:endpoint connection) node kind types)) xs (json/decode body true)] - (if (missing? status) - nil + (when-not (missing? status) (map instantiate-rel-from xs)))) @@ -53,15 +52,16 @@ (defn create "Creates a relationship of given type between two nodes. " - ([^Node from ^Node to rel-type] - (create from to rel-type {})) - ([^Node from ^Node to rel-type data] + ([^Connection connection ^Node from ^Node to rel-type] + (create connection from to rel-type {})) + ([^Connection connection ^Node from ^Node to rel-type data] ;; these (or ...)s here are necessary because Neo4J REST API returns nodes in different format when fetched via nodes/get ;; and found via index. We have to account for that. MK. - (let [{:keys [status headers body]} (rest/POST (or (:create-relationship-uri from) - (create-relationship-location-for rest/*endpoint* from)) + (let [{:keys [status headers body]} (rest/POST connection (or (:create-relationship-uri from) + (create-relationship-location-for (:endpoint connection) from)) :body (json/encode {:to (or (:location-uri to) - (node-location-for rest/*endpoint* (to-id to))) :type rel-type :data data})) + (node-location-for (:endpoint connection) (to-id to))) + :type rel-type :data data})) payload (json/decode body true)] (instantiate-rel-from payload)))) @@ -72,17 +72,17 @@ only a single request. For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-unique-indexes.html (section 19.8.4)" - ([^Node from ^Node to rel-type idx k v] - (create-unique-in-index from to rel-type idx k v {})) - ([^Node from ^Node to rel-type idx k v data] - (let [uri (str (url-with-path (:relationship-index-uri rest/*endpoint*) idx) "/?unique") - body {:key k + ([^Connection connection ^Node from ^Node to rel-type idx k v] + (create-unique-in-index connection from to rel-type idx k v {})) + ([^Connection connection ^Node from ^Node to rel-type idx k v data] + (let [uri (str (url-with-path (get-in connection [:endpoint :relationship-index-uri]) idx) "/?unique") + body {:key k :value v - :start (or (:location-uri from) (node-location-for rest/*endpoint* (to-id from))) - :end (or (:location-uri to) (node-location-for rest/*endpoint* (to-id to))) + :start (or (:location-uri from) (node-location-for (:endpoint connection) (to-id from))) + :end (or (:location-uri to) (node-location-for (:endpoint connection) (to-id to))) :type rel-type :properties data} - {:keys [status headers body]} (rest/POST uri :body (json/encode body)) + {:keys [status headers body]} (rest/POST connection uri :body (json/encode body)) payload (json/decode body true)] (instantiate-rel-from payload)))) @@ -92,33 +92,34 @@ This function should be used when number of relationships that need to be created is moderately high (dozens and more), otherwise it would be less efficient than using clojure.core/map over the same sequence of nodes" - ([^Node from xs rel-type] + ([^Connection connection ^Node from xs rel-type] (pmap (fn [^Node n] - (create from n rel-type)) xs)) - ([^Node from xs rel-type data] + (create connection from n rel-type)) xs)) + ([^Connection connection ^Node from xs rel-type data] (pmap (fn [^Node n] - (create from n rel-type data)) xs))) + (create connection from n rel-type data)) xs))) (declare outgoing-for) (defn maybe-create "Creates a relationship of given type between two nodes, unless it already exists" - ([from to rel-type] - (maybe-create from to rel-type {})) - ([from to rel-type data] - (if (paths/exists-between? (to-id from) (to-id to) :relationships [{:type (name rel-type) :direction "out"}] :max-depth 1) - (let [rels (outgoing-for from :types [rel-type]) - uri (node-location-for rest/*endpoint* (to-id to))] + ([^Connection connection from to rel-type] + (maybe-create connection from to rel-type {})) + ([^Connection connection from to rel-type data] + (if (paths/exists-between? connection (to-id from) (to-id to) + :relationships [{:type (name rel-type) :direction "out"}] + :max-depth 1) + (let [rels (outgoing-for connection from :types [rel-type]) + uri (node-location-for (:endpoint connection) (to-id to))] (first (filter #(= (:end %) uri) rels))) - (create from to rel-type data)))) + (create connection from to rel-type data)))) (defn get "Fetches relationship by id" - [^long id] - (let [{:keys [status headers body]} (rest/GET (rel-location-for rest/*endpoint* id)) + [^Connection connection ^long id] + (let [{:keys [status headers body]} (rest/GET connection (rel-location-for (:endpoint connection) id)) payload (json/decode body true)] - (if (missing? status) - nil + (when-not (missing? status) (instantiate-rel-from payload id)))) (defn get-many @@ -126,14 +127,14 @@ This is a non-standard operation that requires Cypher support as well as support for that very feature by Cypher itself (Neo4j Server versions 1.6.3 and later)." - ([coll] - (let [{:keys [data]} (cypher/query "START x = relationship({ids}) RETURN x" {:ids coll})] + ([^Connection connection coll] + (let [{:keys [data]} (cypher/query connection "START x = relationship({ids}) RETURN x" {:ids coll})] (map (comp instantiate-rel-from first) data)))) (defn delete "Deletes relationship by id" - [rel] - (let [{:keys [status headers]} (rest/DELETE (rel-location-for rest/*endpoint* (to-id rel)))] + [^Connection connection rel] + (let [{:keys [status headers]} (rest/DELETE connection (rel-location-for (:endpoint connection) (to-id rel)))] (if (or (missing? status) (conflict? status)) [nil status] @@ -141,40 +142,40 @@ (defn maybe-delete "Deletes relationship by id but only if it exists. Otherwise, does nothing and returns nil" - [^long id] - (if-let [n (get id)] - (delete id))) + [^Connection connection ^long id] + (if-let [n (get connection id)] + (delete connection id))) (defn delete-many "Deletes multiple relationships by id." - [ids] + [^Connection connection ids] (comment Once 1.8 is out, we should migrate this to mutating Cypher to avoid doing N requests) (doseq [id ids] - (delete id))) + (delete connection id))) (declare first-outgoing-between) (defn maybe-delete-outgoing "Deletes outgoing relationship of given type between two nodes but only if it exists. Otherwise, does nothing and returns nil" - ([^long id] - (if-let [n (get id)] - (delete id))) - ([from to rels] - (if-let [rel (first-outgoing-between from to rels)] - (delete (to-id rel))))) + ([^Connection connection ^long id] + (if-let [n (get connection id)] + (delete connection id))) + ([^Connection connection from to rels] + (if-let [rel (first-outgoing-between connection from to rels)] + (delete connection (to-id rel))))) (defn update "Updates relationship data by id" - [rel data] - (rest/PUT (rel-properties-location-for rest/*endpoint* rel) :body (json/encode data)) + [^Connection connection rel data] + (rest/PUT connection (rel-properties-location-for (:endpoint connection) rel) :body (json/encode data)) data) (defn delete-property "Deletes a property from relationship with the given id" - [^long id prop] - (rest/DELETE (rel-property-location-for rest/*endpoint* id prop)) + [^Connection connection ^long id prop] + (rest/DELETE connection (rel-property-location-for (:endpoint connection) id prop)) nil) @@ -198,12 +199,13 @@ (defn create-index "Creates a new relationship index. Indexes are used for fast lookups by a property or full text search query." - ([^String s] - (let [{:keys [body]} (rest/POST (:relationship-index-uri rest/*endpoint*) :body (json/encode {:name (name s)})) + ([^Connection connection ^String s] + (let [{:keys [body]} (rest/POST connection (get-in connection [:endpoint :relationship-index-uri]) + :body (json/encode {:name (name s)})) payload (json/decode body true)] (Index. (name s) (:template payload) "lucene" "exact"))) - ([^String s configuration] - (let [{:keys [body]} (rest/POST (:relationship-index-uri rest/*endpoint*) + ([^Connection connection ^String s configuration] + (let [{:keys [body]} (rest/POST connection (get-in connection [:endpoint :relationship-index-uri]) :query-string (if (:unique configuration) {"unique" "true"} {}) @@ -214,15 +216,15 @@ (defn delete-index "Deletes a relationship index" - [^String s] - (let [{:keys [status]} (rest/DELETE (rel-index-location-for rest/*endpoint* s))] + [^Connection connection ^String s] + (let [{:keys [status]} (rest/DELETE connection (rel-index-location-for (:endpoint connection) s))] [s status])) (defn all-indexes "Returns all relationship indices" - [] - (let [{:keys [status body]} (rest/GET (:relationship-index-uri rest/*endpoint*))] + [^Connection connection] + (let [{:keys [status body]} (rest/GET connection (get-in connection [:endpoint :relationship-index-uri]))] (if (= 204 (long status)) [] (map (fn [[idx props]] (Index. (name idx) (:template props) (:provider props) (:type props))) @@ -231,38 +233,39 @@ (defn add-to-index "Adds the given rel to the index" - ([rel idx key value] - (add-to-index rel idx key value false)) - ([rel idx key value unique?] + ([^Connection connection rel idx key value] + (add-to-index connection rel idx key value false)) + ([^Connection connection rel idx key value unique?] (let [id (to-id rel) - req-body (json/encode {:key key :value value :uri (rel-location-for rest/*endpoint* (to-id rel))}) - {:keys [status body]} (rest/POST (rel-index-location-for rest/*endpoint* idx) :body req-body :query-string (if unique? - {"unique" "true"} - {})) + req-body (json/encode {:key key :value value :uri (rel-location-for (:endpoint connection) (to-id rel))}) + {:keys [status body]} (rest/POST connection (rel-index-location-for (:endpoint connection) idx) + :body req-body :query-string (if unique? + {"unique" "true"} + {})) payload (json/decode body true)] (instantiate-rel-from payload id)))) (defn delete-from-index "Deletes the given rel from index" - ([rel idx] + ([^Connection connection rel idx] (let [id (to-id rel) - {:keys [status]} (rest/DELETE (rel-in-index-location-for rest/*endpoint* id idx))] + {:keys [status]} (rest/DELETE connection (rel-in-index-location-for (:endpoint connection) id idx))] [id status])) - ([rel idx key] + ([^Connection connection rel idx key] (let [id (to-id rel) - {:keys [status]} (rest/DELETE (rel-in-index-location-for rest/*endpoint* id idx key))] + {:keys [status]} (rest/DELETE connection (rel-in-index-location-for (:endpoint connection) id idx key))] [id status])) - ([rel idx key value] + ([^Connection connection rel idx key value] (let [id (to-id rel) - {:keys [status]} (rest/DELETE (rel-in-index-location-for rest/*endpoint* id idx key value))] + {:keys [status]} (rest/DELETE connection (rel-in-index-location-for (:endpoint connection) id idx key value))] [id status]))) (defn fetch-from "Fetches a relationships from given URI. Exactly like clojurewerkz.neocons.rest.relationships/get but takes a URI instead of an id." - [^String uri] - (let [{:keys [status body]} (rest/GET uri) + [^Connection connection ^String uri] + (let [{:keys [status body]} (rest/GET connection uri) payload (json/decode body true) id (extract-id uri)] (instantiate-rel-from payload id))) @@ -270,34 +273,34 @@ (defn find "Finds relationships using the index" - ([^String key value] - (let [{:keys [status body]} (rest/GET (auto-rel-index-lookup-location-for rest/*endpoint* key value)) + ([^Connection connection ^String key value] + (let [{:keys [status body]} (rest/GET connection (auto-rel-index-lookup-location-for (:endpoint connection) key value)) xs (json/decode body true)] - (map (fn [doc] (fetch-from (:indexed doc))) xs))) - ([^String idx key value] - (let [{:keys [status body]} (rest/GET (rel-index-lookup-location-for rest/*endpoint* idx key value)) + (map (fn [doc] (fetch-from connection (:indexed doc))) xs))) + ([^Connection connection ^String idx key value] + (let [{:keys [status body]} (rest/GET connection (rel-index-lookup-location-for (:endpoint connection) idx key value)) xs (json/decode body true)] - (map (fn [doc] (fetch-from (:indexed doc))) xs)))) + (map (fn [doc] (fetch-from connection (:indexed doc))) xs)))) (defn find-one "Finds a single relationship using the index" - [^String idx key value] - (let [{:keys [status body]} (rest/GET (rel-index-lookup-location-for rest/*endpoint* idx key value)) + [^Connection connection ^String idx key value] + (let [{:keys [status body]} (rest/GET connection (rel-index-lookup-location-for (:endpoint connection) idx key value)) [rel] (json/decode body true)] (when rel - (fetch-from (:indexed rel))))) + (fetch-from connection (:indexed rel))))) (defn query "Finds relationships using full text search query" - ([^String query] - (let [{:keys [status body]} (rest/GET (auto-rel-index-location-for rest/*endpoint*) :query-params {"query" query}) + ([^Connection connection ^String query] + (let [{:keys [status body]} (rest/GET connection (auto-rel-index-location-for (:endpoint connection)) :query-params {"query" query}) xs (json/decode body true)] - (map (fn [doc] (instantiate-rel-from doc)) xs))) - ([^String idx ^String query] - (let [{:keys [status body]} (rest/GET (rel-index-location-for rest/*endpoint* idx) :query-params {"query" query}) + (map instantiate-rel-from xs))) + ([^Connection connection ^String idx ^String query] + (let [{:keys [status body]} (rest/GET connection (rel-index-location-for (:endpoint connection) idx) :query-params {"query" query}) xs (json/decode body true)] - (map (fn [doc] (instantiate-rel-from doc)) xs)))) + (map instantiate-rel-from xs)))) ;; @@ -306,65 +309,65 @@ (defn all-for "Returns all relationships for given node" - [^Node node &{ :keys [types] }] - (relationships-for node :all types)) + [^Connection connection ^Node node &{ :keys [types] }] + (relationships-for connection node :all types)) (defn all-ids-for "Returns ids of all relationships for the given node" - [^Node node &{ :keys [types] }] - (map :id (all-for node :types types))) + [^Connection connection ^Node node &{ :keys [types] }] + (map :id (all-for connection node :types types))) (defn incoming-for "Returns incoming (inbound) relationships for the given node" - [^Node node &{ :keys [types] }] - (relationships-for node :in types)) + [^Connection connection ^Node node &{ :keys [types] }] + (relationships-for connection node :in types)) (defn outgoing-for "Returns all outgoing (outbound) relationships for the given node" - [^Node node &{ :keys [types] }] - (relationships-for node :out types)) + [^Connection connection ^Node node &{ :keys [types] }] + (relationships-for connection node :out types)) (defn outgoing-ids-for "Returns ids of all outgoing (outbound) relationships for given node." - [^Node node &{:keys [types]}] - (map :id (outgoing-for node :types types))) + [^Connection connection ^Node node &{:keys [types]}] + (map :id (outgoing-for connection node :types types))) (defn all-outgoing-between "Returns all outgoing (outbound) relationships of given relationship types between two nodes" - ([^Node from ^Node to rels] - (if (paths/exists-between? (:id from) (:id to) :relationships rels :max-depth 1) - (let [rels (outgoing-for from :types rels) - uri (node-location-for rest/*endpoint* (:id to))] + ([^Connection connection ^Node from ^Node to rels] + (if (paths/exists-between? connection (:id from) (:id to) :relationships rels :max-depth 1) + (let [rels (outgoing-for connection from :types rels) + uri (node-location-for (:endpoint connection) (:id to))] (filter #(= (:end %) uri) rels)) []))) (defn first-outgoing-between "Returns first outgoing (outbound) relationships of given relationship types between two nodes" - ([^Node from ^Node to types] - (first (all-outgoing-between from to types)))) + ([^Connection connection ^Node from ^Node to types] + (first (all-outgoing-between connection from to types)))) (defn purge-all "Deletes all relationships for given node. Usually used before deleting the node, because Neo4J won't allow nodes with relationships to be deleted. Nodes are deleted sequentially to avoid node locking problems with Neo4J Server before 1.8" - ([^Node node] - (delete-many (all-ids-for node)))) + ([^Connection connection ^Node node] + (delete-many connection (all-ids-for connection node)))) (defn purge-outgoing "Deletes all outgoing relationships for given node. Nodes are deleted sequentially to avoid node locking problems with Neo4J Server before 1.8" - ([^Node node] - (delete-many (outgoing-ids-for node))) - ([^Node node &{:keys [types]}] - (delete-many (outgoing-ids-for node :types types)))) + ([^Connection connection ^Node node] + (delete-many connection (outgoing-ids-for connection node))) + ([^Connection connection ^Node node &{:keys [types]}] + (delete-many connection (outgoing-ids-for connection node :types types)))) (defn replace-outgoing "Deletes outgoing relationships of the node `from` with given type, then creates new relationships of the same type with `xs` nodes" - ([^Node from xs rel-type] - (purge-outgoing from :types [rel-type]) - (create-many from xs rel-type))) + ([^Connection connection ^Node from xs rel-type] + (purge-outgoing connection from :types [rel-type]) + (create-many connection from xs rel-type))) ;; @@ -373,24 +376,24 @@ (defn all-types "Returns all relationship types that exists in the entire database" - [] - (let [{ :keys [_ _ body] } (rest/GET (:relationship-types-uri rest/*endpoint*))] + [^Connection connection] + (let [{ :keys [_ _ body] } (rest/GET connection (:relationship-types-uri (:endpoint connection)))] (json/decode body true))) (defn traverse "Performs relationships traversal" - ([id & { :keys [order relationships uniqueness prune-evaluator return-filter max-depth] :or {order "breadth_first" - uniqueness "node_global" - prune-evaluator {:language "builtin" :name "none"} - return-filter {:language "builtin" :name "all"}}}] + ([^Connection connection id & {:keys [order relationships uniqueness prune-evaluator return-filter max-depth] + :or {order "breadth_first" + uniqueness "node_global" + prune-evaluator {:language "builtin" :name "none"} + return-filter {:language "builtin" :name "all"}}}] (let [request-body {:order order :relationships relationships :uniqueness uniqueness :prune_evaluator prune-evaluator :return_filter return-filter :max_depth max-depth} - {:keys [status body]} (rest/POST (rel-traverse-location-for rest/*endpoint* id) :body (json/encode request-body)) + {:keys [status body]} (rest/POST connection (rel-traverse-location-for (:endpoint connection) id) :body (json/encode request-body)) xs (json/decode body true)] - (map (fn [doc] - (instantiate-rel-from doc)) xs)))) + (map instantiate-rel-from xs)))) diff --git a/src/clojure/clojurewerkz/neocons/rest/spatial.clj b/src/clojure/clojurewerkz/neocons/rest/spatial.clj index b4d3360..36c9f5c 100644 --- a/src/clojure/clojurewerkz/neocons/rest/spatial.clj +++ b/src/clojure/clojurewerkz/neocons/rest/spatial.clj @@ -15,7 +15,7 @@ [clojurewerkz.neocons.rest.helpers :refer :all] [clojurewerkz.neocons.rest.records :refer :all]) (:import [java.net URI URL] - clojurewerkz.neocons.rest.Neo4JEndpoint)) + [clojurewerkz.neocons.rest Connection Neo4JEndpoint])) ;; ;; Implementation @@ -26,9 +26,9 @@ (str (:uri endpoint) "ext/SpatialPlugin/graphdb/" action)) (defn- post-spatial - [item-type body] - (let [{:keys [status headers body]} (rest/POST - (spatial-location-for rest/*endpoint* item-type) + [^Connection connection item-type body] + (let [{:keys [status headers body]} (rest/POST connection + (spatial-location-for (:endpoint connection) item-type) :body (json/encode body)) payload (json/decode body true)] (map instantiate-node-from payload))) @@ -39,18 +39,22 @@ (defn add-simple-point-layer "Add a new point layer to the spatial index" - ([layer lat lon] - (first (post-spatial "addSimplePointLayer" {:layer layer :lat lat :lon lon}))) - ([layer] - (first (post-spatial "addSimplePointLayer" {:layer layer})))) + ([^Connection connection layer lat lon] + (first (post-spatial connection "addSimplePointLayer" {:layer layer :lat lat :lon lon}))) + ([^Connection connection layer] + (first (post-spatial connection "addSimplePointLayer" {:layer layer})))) (defn add-node-to-layer "Add a node with the appropriate latitude and longitude properties to the given layer" - [layer node] - (first (post-spatial "addNodeToLayer" {:layer layer :node (node-location-for rest/*endpoint* (:id node))}))) + [^Connection connection layer node] + (first (post-spatial connection "addNodeToLayer" {:layer layer + :node (node-location-for (:endpoint connection) (:id node))}))) (defn find-within-distance "Find all points in the layer within a given distance of the given point" - [layer point-x point-y distance-in-km] - (post-spatial "findGeometriesWithinDistance" {:layer layer :pointX point-x :pointY point-y :distanceInKm distance-in-km})) + [^Connection connection layer point-x point-y distance-in-km] + (post-spatial connection "findGeometriesWithinDistance" {:layer layer + :pointX point-x + :pointY point-y + :distanceInKm distance-in-km})) diff --git a/src/clojure/clojurewerkz/neocons/rest/transaction.clj b/src/clojure/clojurewerkz/neocons/rest/transaction.clj index ddc40fc..034ee54 100644 --- a/src/clojure/clojurewerkz/neocons/rest/transaction.clj +++ b/src/clojure/clojurewerkz/neocons/rest/transaction.clj @@ -14,6 +14,7 @@ [clojurewerkz.neocons.rest.records :as records] [cheshire.core :as json] [clojurewerkz.support.http.statuses :refer [missing?]]) + (:import [clojurewerkz.neocons.rest Connection]) (:refer-clojure :exclude [rest])) @@ -42,9 +43,9 @@ (throw (Exception. (str "Transaction failed and rolled back. Error: " error)))))) (defn- make-request - [xs uri] + [^Connection conn xs uri] (let [req-body (json/encode (tx-payload-from xs)) - {:keys [status headers body]} (rest/POST uri :body req-body) + {:keys [status headers body]} (rest/POST conn uri :body req-body) payload (json/decode body true)] (raise-on-any-errors payload) [status headers payload])) @@ -53,38 +54,40 @@ [payload] (map records/instantiate-cypher-query-response-from (:results payload))) + (defn- real-execute - [transaction xs uri] - (let [[status headers payload] (make-request xs uri)] - (if (missing? status) - nil + [^Connection conn transaction xs uri] + (let [[status headers payload] (make-request conn xs uri)] + (when-not (missing? status) [(instantiate-transaction (:commit payload) (:location transaction) (get-in payload [:transaction :expires])) (make-cypher-responses payload)]))) + (defn begin "Starts a transaction with the given cypher statements and returns a transaction record along with the result of the cypher statements. 0-arity function call starts a transaction without any cypher statements. For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html#rest-api-begin-a-transaction" - ([] - (begin [])) - ([xs] - (let [[status headers payload] (make-request xs (:transaction-uri rest/*endpoint*)) - neo-trans (instantiate-transaction - (:commit payload) - (headers "location") - (get-in payload [:transaction :expires]))] - (if (missing? status) - nil + ([^Connection connection] + (begin connection [])) + ([^Connection connection xs] + (let [[status headers payload] (make-request connection xs (get-in connection [:endpoint :transaction-uri])) + neo-trans (instantiate-transaction + (:commit payload) + (headers "location") + (get-in payload [:transaction :expires]))] + (when-not (missing? status) [neo-trans (make-cypher-responses payload)])))) + (defn begin-tx "Starts a transaction without any cypher statements and returns it." - [] - (first (begin []))) + [^Connection connection] + (first (begin connection []))) + (defn execute "Executes cypher statements in an existing transaction and returns the new transaction record along @@ -93,8 +96,8 @@ For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html#rest-api-execute-statements-in-an-open-transaction" - ([transaction] (execute transaction [])) - ([transaction xs] (real-execute transaction xs (:location transaction)))) + ([^Connection connection transaction] (execute connection transaction [])) + ([^Connection connection transaction xs] (real-execute connection transaction xs (:location transaction)))) (defn commit "Commits an existing transaction with optional cypher statements which are applied @@ -102,10 +105,10 @@ For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html#rest-api-commit-an-open-transaction" - ([transaction] - (commit transaction [])) - ([transaction xs] - (let [[_ result] (real-execute transaction xs (:commit transaction))] + ([^Connection connection transaction] + (commit connection transaction [])) + ([^Connection connection transaction xs] + (let [[_ result] (real-execute connection transaction xs (:commit transaction))] result))) (defn rollback @@ -113,8 +116,8 @@ For more information, see http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html#rest-api-rollback-an-open-transaction" - [transaction] - (let [{:keys [status headers body]} (rest/DELETE (:location transaction)) + [^Connection connection transaction] + (let [{:keys [status headers body]} (rest/DELETE connection (:location transaction)) payload (json/decode body true)] (raise-on-any-errors payload) (:results payload))) @@ -126,12 +129,12 @@ A simple example is given below: - (tx/in-transaction + (tx/in-transaction connection (tx/statement \"CREATE (n {props}) RETURN n\" {:props {:name \"My Node\"}}) (tx/statement \"CREATE (n {props}) RETURN n\" {:props {:name \"My Another Node\"}}))" - [ & coll] - (let [uri (str (:transaction-uri rest/*endpoint*) "/commit") - [status headers payload] (make-request coll uri)] + [^Connection connection & coll] + (let [uri (str (get-in connection [:endpoint :transaction-uri]) "/commit") + [status headers payload] (make-request connection coll uri)] (raise-on-any-errors payload) (when-not (missing? status) (make-cypher-responses payload)))) @@ -149,17 +152,18 @@ (let [transaction (tx/begin-tx)] (tx/with-transaction + connection transaction true - (let [[_ result] (tx/execute transaction [(tx/statement \"CREATE (n) RETURN ID(n)\")])] + (let [[_ result] (tx/execute connection transaction [(tx/statement \"CREATE (n) RETURN ID(n)\")])] (println result))))" - [transaction commit-on-success? & body] + [^Connection connection transaction commit-on-success? & body] `(try (let [ret# (do ~@body)] (when ~commit-on-success? - (commit ~transaction)) + (commit ~connection ~transaction)) ret#) (catch Exception e# ((when-not (re-find #"Transaction failed and rolled back" (. e# getMessage)) - (rollback ~transaction)) + (rollback ~connection ~transaction)) (throw e#))))) diff --git a/test/clojurewerkz/neocons/rest/test/basic_http_authentication_test.clj b/test/clojurewerkz/neocons/rest/test/basic_http_authentication_test.clj index 49bef32..783cf7f 100644 --- a/test/clojurewerkz/neocons/rest/test/basic_http_authentication_test.clj +++ b/test/clojurewerkz/neocons/rest/test/basic_http_authentication_test.clj @@ -36,14 +36,14 @@ (do (deftest ^{:http-auth true} test-connection-and-discovery-using-user-info-in-string-uri (try - (neorest/connect! "http://neocons:incorrec7-pazzwd@neo4j-proxy.local/db/data/") + (neorest/connect "http://neocons:incorrec7-pazzwd@neo4j-proxy.local/db/data/") (catch Exception e (let [d (.getData e)] (is (= (-> d :object :status) 401)))))) - (deftest ^{:http-auth true} test-connection-and-discovery-using-user-info-in-string-uri + (deftest ^{:http-auth true} test-connection-and-discovery-using-user-info-in-string-uri-2 (try - (neorest/connect! "http://neocons:SEcRe7@neo4j-proxy.local/db/data/") + (neorest/connect "http://neocons:SEcRe7@neo4j-proxy.local/db/data/") (catch Exception e (let [d (.getData e)] (println d) @@ -53,29 +53,28 @@ neo4j-password (get (System/getenv) "NEO4J_PASSWORD")] (when (and neo4j-login neo4j-password) (deftest ^{:http-auth true} test-connection-and-discovery-with-http-credentials-provided-via-env-variables - (neorest/connect! "http://neo4j-proxy.local/db/data/") - (is (:version neorest/*endpoint*)) - (is (:node-uri neorest/*endpoint*)) - (is (:batch-uri neorest/*endpoint*)) - (is (:relationship-types-uri neorest/*endpoint*))))) + (let [conn (neorest/connect "http://neo4j-proxy.local/db/data/")] + (is (:version (:endpoint conn))) + (is (:node-uri (:endpoint conn))) + (is (:batch-uri (:endpoint conn))) + (is (:relationship-types-uri (:endpoint conn))))))) (deftest ^{:http-auth true} test-connection-and-discovery-with-provided-http-credentials - (neorest/connect! "http://neo4j-proxy.local/db/data/" "neocons" "SEcRe7") - (is (:version neorest/*endpoint*)) - (is (:node-uri neorest/*endpoint*)) - (is (:batch-uri neorest/*endpoint*)) - (is (:relationship-types-uri neorest/*endpoint*))) - - (neorest/connect! "http://localhost:7474/db/data/" "neocons" "SEcRe7") + (let [conn (neorest/connect "http://neo4j-proxy.local/db/data/" "neocons" "SEcRe7")] + (is (:version (:endpoint conn))) + (is (:node-uri (:endpoint conn))) + (is (:batch-uri (:endpoint conn))) + (is (:relationship-types-uri (:endpoint conn))))) - (deftest ^{:http-auth true} test-creating-and-immediately-accessing-a-node-without-properties-with-http-auth - (let [created-node (nodes/create) - fetched-node (nodes/get (:id created-node))] - (is (= (:id created-node) (:id fetched-node))))) + (let [conn (neorest/connect "http://localhost:7474/db/data/" "neocons" "SEcRe7")] + (deftest ^{:http-auth true} test-creating-and-immediately-accessing-a-node-without-properties-with-http-auth + (let [created-node (nodes/create conn) + fetched-node (nodes/get conn (:id created-node))] + (is (= (:id created-node) (:id fetched-node))))) - (deftest ^{:http-auth true} test-creating-and-immediately-accessing-a-node-with-properties-with-http-auth - (let [data { :key "value" } - created-node (nodes/create data) - fetched-node (nodes/get (:id created-node))] - (is (= (:id created-node) (:id fetched-node))) - (is (= (:data created-node) data)))))) + (deftest ^{:http-auth true} test-creating-and-immediately-accessing-a-node-with-properties-with-http-auth + (let [data { :key "value" } + created-node (nodes/create conn data) + fetched-node (nodes/get conn (:id created-node))] + (is (= (:id created-node) (:id fetched-node))) + (is (= (:data created-node) data))))))) diff --git a/test/clojurewerkz/neocons/rest/test/batch_operations_test.clj b/test/clojurewerkz/neocons/rest/test/batch_operations_test.clj index 17f66cc..a1bcee5 100644 --- a/test/clojurewerkz/neocons/rest/test/batch_operations_test.clj +++ b/test/clojurewerkz/neocons/rest/test/batch_operations_test.clj @@ -12,20 +12,21 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nn] [clojurewerkz.neocons.rest.batch :as b] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [clojurewerkz.neocons.rest.test.common :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) (deftest ^{:batching true} test-basic-batching-of-inserts (let [n 100 rng (range 0 n) xs (doall (map (fn [x] {:n x}) rng)) - nodes (doall (nn/create-batch xs))] + nodes (doall (nn/create-batch *connection* xs))] ;; ensure that we aren't tripped by laziness (is (= (count nodes) n)) (is (= (count (map :id nodes)) n)) - (nn/delete-many (vec nodes)))) + (nn/delete-many *connection* (vec nodes)))) @@ -44,5 +45,5 @@ :data {} :type "knows"} :id 2}] - res (doall (b/perform ops))] + res (doall (b/perform *connection* ops))] (is (= (count res) (count ops))))) diff --git a/test/clojurewerkz/neocons/rest/test/common.clj b/test/clojurewerkz/neocons/rest/test/common.clj new file mode 100644 index 0000000..01923b3 --- /dev/null +++ b/test/clojurewerkz/neocons/rest/test/common.clj @@ -0,0 +1,9 @@ +(ns clojurewerkz.neocons.rest.test.common + (:require [clojurewerkz.neocons.rest :as neorest])) + +(def ^{:dynamic true} *connection*) + +(defn once-fixture + [f] + (binding [*connection* (neorest/connect "http://localhost:7474/db/data/")] + (f))) diff --git a/test/clojurewerkz/neocons/rest/test/connection_test.clj b/test/clojurewerkz/neocons/rest/test/connection_test.clj index bebc8bc..0bdb1c9 100644 --- a/test/clojurewerkz/neocons/rest/test/connection_test.clj +++ b/test/clojurewerkz/neocons/rest/test/connection_test.clj @@ -13,7 +13,6 @@ [clojure.test :refer :all])) (println (str "Using Clojure version " *clojure-version*)) -(neorest/connect! "http://localhost:7474/db/data/") ;; @@ -21,16 +20,9 @@ ;; (deftest test-connection-and-discovery-using-connect-with-string-uri - (let [endpoint (neorest/connect "http://localhost:7474/db/data/")] + (let [connection (neorest/connect "http://localhost:7474/db/data/") + endpoint (:endpoint connection)] (is (:version endpoint)) (is (:node-uri endpoint)) (is (:batch-uri endpoint)) (is (:relationship-types-uri endpoint)))) - - -(deftest test-connection-and-discovery-using-connect!-with-string-uri - (neorest/connect! "http://localhost:7474/db/data/") - (is (:version neorest/*endpoint*)) - (is (:node-uri neorest/*endpoint*)) - (is (:batch-uri neorest/*endpoint*)) - (is (:relationship-types-uri neorest/*endpoint*))) diff --git a/test/clojurewerkz/neocons/rest/test/constraints_test.clj b/test/clojurewerkz/neocons/rest/test/constraints_test.clj index ee28442..2b848ed 100644 --- a/test/clojurewerkz/neocons/rest/test/constraints_test.clj +++ b/test/clojurewerkz/neocons/rest/test/constraints_test.clj @@ -12,25 +12,26 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.constraints :as cts] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [clojurewerkz.neocons.rest.test.common :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) (def dummy-label :DummyPerson) -(def dummy-constraint {:label dummy-label :property-keys [:name] :type "UNIQUENESS"}) +(def dummy-constraint {:label dummy-label :property_keys ["name"] :type "UNIQUENESS"}) -(deftest ^{:edge-features true} test-constraints +(deftest test-constraints (try - (let [a (cts/create-unique dummy-label :name)] + (let [a (cts/create-unique *connection* dummy-label :name)] (is (= a dummy-constraint)) (Thread/sleep 3000)) (catch Exception e (.getMessage e)) (finally - (is (= (cts/get-unique dummy-label :name) [dummy-constraint])) - (is (contains? (set (cts/get-unique dummy-label)) dummy-constraint)) - (is (contains? (set (cts/get-all dummy-label)) dummy-constraint)) - (is (contains? (set (cts/get-all)) dummy-constraint)) - (cts/drop-unique dummy-label :name) + (is (= (cts/get-unique *connection* dummy-label :name) [dummy-constraint])) + (is (contains? (set (cts/get-unique *connection* dummy-label)) dummy-constraint)) + (is (contains? (set (cts/get-all *connection* dummy-label)) dummy-constraint)) + (is (contains? (set (cts/get-all *connection*)) dummy-constraint)) + (cts/drop-unique *connection* dummy-label :name) (is (not (contains? - (set (cts/get-unique dummy-label)) + (set (cts/get-unique *connection* dummy-label)) dummy-constraint)))))) diff --git a/test/clojurewerkz/neocons/rest/test/cypher_test.clj b/test/clojurewerkz/neocons/rest/test/cypher_test.clj index 9683f7f..88062e2 100644 --- a/test/clojurewerkz/neocons/rest/test/cypher_test.clj +++ b/test/clojurewerkz/neocons/rest/test/cypher_test.clj @@ -17,10 +17,11 @@ [clojure.test :refer :all] [clojure.set :refer [subset?]] [clojure.pprint :refer [pprint]] - [clojurewerkz.neocons.rest.records :refer [instantiate-node-from instantiate-rel-from instantiate-path-from]])) + [clojurewerkz.neocons.rest.records :refer [instantiate-node-from instantiate-rel-from instantiate-path-from]] + [clojurewerkz.neocons.rest.test.common :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) ;; ;; Cypher queries @@ -32,16 +33,16 @@ (= (:data a) (:data b)))) (deftest ^{:cypher true} test-cypher-query-example1 - (let [john (nodes/create {:name "John"}) - sarah (nodes/create {:name "Sarah"}) - joe (nodes/create {:name "Joe"}) - maria (nodes/create {:name "Maria"}) - steve (nodes/create {:name "Steve"}) - rel1 (rel/create john sarah :friend) - rel2 (rel/create john joe :friend) - rel3 (rel/create sarah maria :friend) - rel4 (rel/create joe steve :friend) - {:keys [data columns]} (cy/query "START john=node({sid}) MATCH john-[:friend]->()-[:friend]->fof RETURN john, fof" {:sid (:id john)}) + (let [john (nodes/create *connection* {:name "John"}) + sarah (nodes/create *connection* {:name "Sarah"}) + joe (nodes/create *connection* {:name "Joe"}) + maria (nodes/create *connection* {:name "Maria"}) + steve (nodes/create *connection* {:name "Steve"}) + rel1 (rel/create *connection* john sarah :friend) + rel2 (rel/create *connection* john joe :friend) + rel3 (rel/create *connection* sarah maria :friend) + rel4 (rel/create *connection* joe steve :friend) + {:keys [data columns]} (cy/query *connection* "START john=node({sid}) MATCH john-[:friend]->()-[:friend]->fof RETURN john, fof" {:sid (:id john)}) row1 (map instantiate-node-from (first data)) row2 (map instantiate-node-from (second data))] (is (= 2 (count data))) @@ -53,55 +54,55 @@ (deftest ^{:cypher true} test-cypher-query-example2 - (let [john (nodes/create {:name "John"}) - sarah (nodes/create {:name "Sarah"}) - rel1 (rel/create john sarah :friend) - [row1] (cy/tquery "START x = node({sid}) MATCH path = (x--friend) RETURN path, friend.name" {:sid (:id john)}) + (let [john (nodes/create *connection* {:name "John"}) + sarah (nodes/create *connection* {:name "Sarah"}) + rel1 (rel/create *connection* john sarah :friend) + [row1] (cy/tquery *connection* "START x = node({sid}) MATCH path = (x--friend) RETURN path, friend.name" {:sid (:id john)}) path (instantiate-path-from (get row1 "path"))] - (is (paths/included-in? john path)) - (is (paths/included-in? sarah path)) + (is (paths/included-in? *connection* john path)) + (is (paths/included-in? *connection* sarah path)) (is (= "Sarah" (get row1 "friend.name"))))) (deftest ^{:cypher true} test-cypher-query-example3 - (let [john (nodes/create { :name "John" :age 27 }) - sarah (nodes/create { :name "Sarah" :age 28 }) - rel1 (rel/create john sarah :friend) + (let [john (nodes/create *connection* { :name "John" :age 27 }) + sarah (nodes/create *connection* { :name "Sarah" :age 28 }) + rel1 (rel/create *connection* john sarah :friend) ids (map :id [john sarah]) - response (cy/tquery "START x = node({ids}) RETURN x.name, x.age" { :ids ids })] + response (cy/tquery *connection* "START x = node({ids}) RETURN x.name, x.age" { :ids ids })] (is (= [{"x.name" "John" "x.age" 27} {"x.name" "Sarah" "x.age" 28}] response)))) (deftest ^{:cypher true} test-cypher-query-example4 - (let [john (nodes/create { :name "John" }) - sarah (nodes/create { :name "Sarah" }) + (let [john (nodes/create *connection* { :name "John" }) + sarah (nodes/create *connection* { :name "Sarah" }) ids (map :id [john sarah]) - {:keys [data columns]} (cy/query "START x = node({ids}) RETURN x" {:ids ids})] + {:keys [data columns]} (cy/query *connection* "START x = node({ids}) RETURN x" {:ids ids})] (is (= ids (vec (map (comp :id instantiate-node-from first) data)))))) (deftest ^{:cypher true} test-cypher-query-example5 - (let [john (nodes/create { :name "John" }) - sarah (nodes/create { :name "Sarah" }) + (let [john (nodes/create *connection* { :name "John" }) + sarah (nodes/create *connection* { :name "Sarah" }) ids (vec (map :id [sarah john]))] - (is (= ids (vec (map :id (nodes/get-many ids))))))) + (is (= ids (vec (map :id (nodes/get-many *connection* ids))))))) (deftest ^{:cypher true} test-cypher-query-example6 - (let [john (nodes/create { :name "John" }) - sarah (nodes/create { :name "Sarah" }) - tim (nodes/create { :name "Tim" }) - rel1 (rel/create john sarah :friend) - rel2 (rel/create sarah tim :friend) + (let [john (nodes/create *connection* { :name "John" }) + sarah (nodes/create *connection* { :name "Sarah" }) + tim (nodes/create *connection* { :name "Tim" }) + rel1 (rel/create *connection* john sarah :friend) + rel2 (rel/create *connection* sarah tim :friend) ids (vec (map :id [rel1 rel2]))] - (is (= ids (vec (map :id (rel/get-many ids))))))) + (is (= ids (vec (map :id (rel/get-many *connection* ids))))))) (deftest ^{:cypher true} test-cypher-tquery - (let [john (nodes/create { :name "John" :age 27 }) - sarah (nodes/create { :name "Sarah" :age 28 }) - rel1 (rel/create john sarah :friend) + (let [john (nodes/create *connection* { :name "John" :age 27 }) + sarah (nodes/create *connection* { :name "Sarah" :age 28 }) + rel1 (rel/create *connection* john sarah :friend) ids (map :id [john sarah])] (is (= [{"x.name" "John" "x.age" 27} {"x.name" "Sarah" "x.age" 28}] - (vec (cy/tquery "START x = node({ids}) RETURN x.name, x.age" { :ids ids })))))) + (vec (cy/tquery *connection* "START x = node({ids}) RETURN x.name, x.age" { :ids ids })))))) (deftest ^{:cypher true} test-tableize diff --git a/test/clojurewerkz/neocons/rest/test/index_test.clj b/test/clojurewerkz/neocons/rest/test/index_test.clj index f2d3a70..5b6bbf0 100644 --- a/test/clojurewerkz/neocons/rest/test/index_test.clj +++ b/test/clojurewerkz/neocons/rest/test/index_test.clj @@ -12,19 +12,20 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.index :as idx] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [clojurewerkz.neocons.rest.test.common :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) (def dummy-label :DummyPerson) -(deftest ^{:edge-features true} test-indexes - (if (= (idx/get-all dummy-label) []) - (let [a (idx/create dummy-label :name)] +(deftest test-indexes + (if (= (idx/get-all *connection* dummy-label) []) + (let [a (idx/create *connection* dummy-label :name)] (is (= a {:label dummy-label, :property_keys ["name"]})) - (idx/drop dummy-label :name) - (is (= (idx/get-all dummy-label) []))) - (let [b (idx/drop dummy-label :name)] - (is (= [] (idx/get-all dummy-label))) - (is (=(idx/create dummy-label :name) + (idx/drop *connection* dummy-label :name) + (is (= (idx/get-all *connection* dummy-label) []))) + (let [b (idx/drop *connection* dummy-label :name)] + (is (= [] (idx/get-all *connection* dummy-label))) + (is (=(idx/create *connection* dummy-label :name) {:label dummy-label, :property_keys ["name"]}))))) diff --git a/test/clojurewerkz/neocons/rest/test/indexing_test.clj b/test/clojurewerkz/neocons/rest/test/indexing_test.clj index 9f7c71d..bd766c5 100644 --- a/test/clojurewerkz/neocons/rest/test/indexing_test.clj +++ b/test/clojurewerkz/neocons/rest/test/indexing_test.clj @@ -12,9 +12,10 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.relationships :as rels] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) ;; ;; Indexes @@ -22,228 +23,228 @@ (deftest ^{:indexing true} test-create-a-new-node-index-with-default-configuration (let [name "node-index-1-default-configuration"] - (nodes/create-index name))) + (nodes/create-index *connection* name))) (deftest ^{:indexing true} test-create-a-new-rel-index-with-default-configuration (let [name "rel-index-1-default-configuration"] - (rels/create-index name))) + (rels/create-index *connection* name))) (deftest ^{:indexing true} test-create-a-new-node-index-with-explicit-configuration (let [name "test-create-a-new-node-index-with-explicit-configuration-node-index-1" conf {:type "fulltext" :provider "lucene"}] - (nodes/create-index name conf) - (nodes/delete-index name))) + (nodes/create-index *connection* name conf) + (nodes/delete-index *connection* name))) (deftest ^{:indexing true} test-create-a-new-unique-node-index-with-explicit-configuration (let [name "node-index-2b" conf {:unique true}] - (nodes/create-index name conf) - (nodes/delete-index name))) + (nodes/create-index *connection* name conf) + (nodes/delete-index *connection* name))) (deftest ^{:indexing true} test-create-a-new-rel-index-with-explicit-configuration (let [name "rel-index-2" conf {:type "fulltext" :provider "lucene"}] - (rels/create-index name conf))) + (rels/create-index *connection* name conf))) (deftest ^{:indexing true} test-create-a-new-unique-rel-index-with-explicit-configuration (let [name "rel-index-2b" conf {:unique true :provider "lucene" :type "fulltext"}] - (rels/create-index name conf))) + (rels/create-index *connection* name conf))) (deftest ^{:indexing true} test-listing-node-indexes (let [name "node-index-3" - idx (nodes/create-index name) - list (nodes/all-indexes)] + idx (nodes/create-index *connection* name) + list (nodes/all-indexes *connection*)] (is (some (fn [i] (= name (:name i))) list)))) (deftest ^{:indexing true} test-listing-rel-indexes (let [name "rel-index-3" - idx (rels/create-index name) - list (rels/all-indexes)] + idx (rels/create-index *connection* name) + list (rels/all-indexes *connection*)] (is (some (fn [i] (= name (:name i))) list)))) (deftest ^{:indexing true} test-creating-and-immediately-deleting-a-node-index (let [name "node-index-4-default-configuration" - idx (nodes/create-index name)] + idx (nodes/create-index *connection* name)] (is (= name (:name idx))) - (nodes/delete-index name))) + (nodes/delete-index *connection* name))) (deftest ^{:indexing true} test-creating-and-immediately-deleting-a-rel-index (let [name "rel-index-4-default-configuration" - idx (rels/create-index name)] + idx (rels/create-index *connection* name)] (is (= name (:name idx))) - (rels/delete-index name))) + (rels/delete-index *connection* name))) (deftest ^{:indexing true} test-adding-a-node-to-index - (let [idx (nodes/create-index "uris") + (let [idx (nodes/create-index *connection* "uris") uri "http://arstechnica.com" - home (nodes/create {:uri uri})] - (nodes/add-to-index (:id home) (:name idx) "uri" uri))) + home (nodes/create *connection* {:uri uri})] + (nodes/add-to-index *connection* (:id home) (:name idx) "uri" uri))) (deftest ^{:indexing true} test-adding-a-node-to-index-with-value-with-spaces - (let [idx (nodes/create-index "things") + (let [idx (nodes/create-index *connection* "things") s "a value with spaces" k "a key with spaces" - n (nodes/create {:value s}) - _ (nodes/add-to-index (:id n) (:name idx) k s) - n' (nodes/find-one (:name idx) k s)] + n (nodes/create *connection* {:value s}) + _ (nodes/add-to-index *connection* (:id n) (:name idx) k s) + n' (nodes/find-one *connection* (:name idx) k s)] (is (= s (-> n' :data :value))))) (deftest ^{:indexing true} test-adding-a-node-to-index-with-value-with-colons - (let [idx (nodes/create-index "things") + (let [idx (nodes/create-index *connection* "things") s "a:value with spaces" k "a:key with spaces" - n (nodes/create {:value s}) - _ (nodes/add-to-index (:id n) (:name idx) k s) - n' (nodes/find-one (:name idx) k s)] + n (nodes/create *connection* {:value s}) + _ (nodes/add-to-index *connection* (:id n) (:name idx) k s) + n' (nodes/find-one *connection* (:name idx) k s)] (is (= s (-> n' :data :value))))) (deftest ^{:indexing true} test-adding-a-node-to-index-as-unique - (let [idx (nodes/create-index "uris") + (let [idx (nodes/create-index *connection* "uris") uri "http://arstechnica.com" - home (nodes/create {:uri uri})] - (nodes/add-to-index home (:name idx) "uri" uri true) - (nodes/add-to-index home (:name idx) "uri" uri true))) + home (nodes/create *connection* {:uri uri})] + (nodes/add-to-index *connection* home (:name idx) "uri" uri true) + (nodes/add-to-index *connection* home (:name idx) "uri" uri true))) (deftest ^{:indexing true} test-adding-a-rel-to-index - (let [idx (rels/create-index "uris") + (let [idx (rels/create-index *connection* "uris") uri1 "http://arstechnica.com" - page1 (nodes/create {:uri uri1}) + page1 (nodes/create *connection* {:uri uri1}) uri2 "http://apple.com/ipad" - page2 (nodes/create {:uri uri2}) - rel (rels/create page1 page2 :links)] - (rels/add-to-index (:id rel) (:name idx) "active" "true"))) + page2 (nodes/create *connection* {:uri uri2}) + rel (rels/create *connection* page1 page2 :links)] + (rels/add-to-index *connection* (:id rel) (:name idx) "active" "true"))) (deftest ^{:indexing true} test-adding-a-rel-to-index-as-unique - (let [idx (rels/create-index "uris") + (let [idx (rels/create-index *connection* "uris") uri1 "http://arstechnica.com" - page1 (nodes/create {:uri uri1}) + page1 (nodes/create *connection* {:uri uri1}) uri2 "http://apple.com/ipad" - page2 (nodes/create {:uri uri2}) - rel (rels/create page1 page2 :links)] - (rels/add-to-index rel (:name idx) "active" "true" true))) + page2 (nodes/create *connection* {:uri uri2}) + rel (rels/create *connection* page1 page2 :links)] + (rels/add-to-index *connection* rel (:name idx) "active" "true" true))) (deftest ^{:indexing true} test-removing-a-node-from-index - (let [idx (nodes/create-index "uris") + (let [idx (nodes/create-index *connection* "uris") uri "http://arstechnica.com" - home (nodes/create {:uri uri})] - (nodes/add-to-index (:id home) (:name idx) "uri" uri) - (nodes/delete-from-index (:id home) (:name idx)))) + home (nodes/create *connection* {:uri uri})] + (nodes/add-to-index *connection* (:id home) (:name idx) "uri" uri) + (nodes/delete-from-index *connection* (:id home) (:name idx)))) (deftest ^{:indexing true} test-removing-a-rel-from-index - (let [idx (rels/create-index "uris") + (let [idx (rels/create-index *connection* "uris") uri1 "http://arstechnica.com" - page1 (nodes/create {:uri uri1}) + page1 (nodes/create *connection* {:uri uri1}) uri2 "http://apple.com/ipad" - page2 (nodes/create {:uri uri2}) - rel (rels/create page1 page2 :links)] - (rels/add-to-index (:id rel) (:name idx) "active" "true") - (rels/delete-from-index (:id rel) (:name idx)))) + page2 (nodes/create *connection* {:uri uri2}) + rel (rels/create *connection* page1 page2 :links)] + (rels/add-to-index *connection* (:id rel) (:name idx) "active" "true") + (rels/delete-from-index *connection* (:id rel) (:name idx)))) (deftest ^{:indexing true} test-removing-a-node-and-key-from-index - (let [idx (nodes/create-index "uris, urls and so on") + (let [idx (nodes/create-index *connection* "uris, urls and so on") uri "http://arstechnica.com" - home (nodes/create {:uri uri})] - (nodes/add-to-index (:id home) (:name idx) "uri" uri) - (nodes/delete-from-index (:id home) (:name idx) "uri"))) + home (nodes/create *connection* {:uri uri})] + (nodes/add-to-index *connection* (:id home) (:name idx) "uri" uri) + (nodes/delete-from-index *connection* (:id home) (:name idx) "uri"))) (deftest ^{:indexing true} test-removing-a-rel-and-key-from-index - (let [idx (rels/create-index "uris") + (let [idx (rels/create-index *connection* "uris") uri1 "http://arstechnica.com" - page1 (nodes/create {:uri uri1}) + page1 (nodes/create *connection* {:uri uri1}) uri2 "http://apple.com/ipad" - page2 (nodes/create {:uri uri2}) - rel (rels/create page1 page2 :links)] - (rels/add-to-index (:id rel) (:name idx) "active" "true") - (rels/delete-from-index (:id rel) (:name idx) "active"))) + page2 (nodes/create *connection* {:uri uri2}) + rel (rels/create *connection* page1 page2 :links)] + (rels/add-to-index *connection* (:id rel) (:name idx) "active" "true") + (rels/delete-from-index *connection* (:id rel) (:name idx) "active"))) (deftest ^{:indexing true} test-removing-a-node-key-and-value-from-index - (let [idx (nodes/create-index "locations") - home (nodes/create {:lat 20.0})] - (nodes/add-to-index (:id home) (:name idx) "lat" 20.0) - (nodes/delete-from-index (:id home) (:name idx) "lat" 20.0))) + (let [idx (nodes/create-index *connection* "locations") + home (nodes/create *connection* {:lat 20.0})] + (nodes/add-to-index *connection* (:id home) (:name idx) "lat" 20.0) + (nodes/delete-from-index *connection* (:id home) (:name idx) "lat" 20.0))) (deftest ^{:indexing true} test-finding-nodes-using-an-index - (let [node1 (nodes/create {:name "Wired"}) - node2 (nodes/create {:name "Craigslist"}) + (let [node1 (nodes/create *connection* {:name "Wired"}) + node2 (nodes/create *connection* {:name "Craigslist"}) url1 "http://wired.com" url2 "http://craigslist.org" - idx (nodes/create-index "by-url")] - (nodes/delete-from-index (:id node1) (:name idx) "url") - (nodes/delete-from-index (:id node2) (:name idx) "url") - (nodes/add-to-index (:id node1) (:name idx) "url" url1) - (nodes/add-to-index (:id node2) (:name idx) "url" url2) - (let [ids (set (map :id (nodes/find (:name idx) "url" url1)))] + idx (nodes/create-index *connection* "by-url")] + (nodes/delete-from-index *connection* (:id node1) (:name idx) "url") + (nodes/delete-from-index *connection* (:id node2) (:name idx) "url") + (nodes/add-to-index *connection* (:id node1) (:name idx) "url" url1) + (nodes/add-to-index *connection* (:id node2) (:name idx) "url" url2) + (let [ids (set (map :id (nodes/find *connection* (:name idx) "url" url1)))] (is (ids (:id node1))) (is (not (ids (:id node2))))))) (deftest ^{:indexing true} test-finding-rels-using-an-index - (let [node1 (nodes/create {:name "Wired" :url "http://wired.com"}) + (let [node1 (nodes/create *connection* {:name "Wired" :url "http://wired.com"}) url "http://craigslist.org" - node2 (nodes/create {:name "Craigslist" :url url}) - idx (rels/create-index "by-target-url") - rel (rels/create node1 node2 :links {:url url})] - (rels/delete-from-index (:id rel) (:name idx) "target-url") - (rels/add-to-index (:id rel) (:name idx) "target-url" url) - (let [ids (set (map :id (rels/find (:name idx) "target-url" url)))] + node2 (nodes/create *connection* {:name "Craigslist" :url url}) + idx (rels/create-index *connection* "by-target-url") + rel (rels/create *connection* node1 node2 :links {:url url})] + (rels/delete-from-index *connection* (:id rel) (:name idx) "target-url") + (rels/add-to-index *connection* (:id rel) (:name idx) "target-url" url) + (let [ids (set (map :id (rels/find *connection* (:name idx) "target-url" url)))] (is (ids (:id rel)))))) (deftest ^{:indexing true} test-finding-a-node-with-url-unsafe-key-to-index - (let [idx (nodes/create-index "uris") + (let [idx (nodes/create-index *connection* "uris") uri "http://arstechnica.com/search/?query=Diablo+III" - home (nodes/create {:uri uri})] - (nodes/add-to-index (:id home) (:name idx) "uri" uri) - (nodes/find-one (:name idx) "uri" uri) - (nodes/delete-from-index (:id home) (:name idx)))) + home (nodes/create *connection* {:uri uri})] + (nodes/add-to-index *connection* (:id home) (:name idx) "uri" uri) + (nodes/find-one *connection* (:name idx) "uri" uri) + (nodes/delete-from-index *connection* (:id home) (:name idx)))) (deftest ^{:indexing true} test-removing-a-node-removes-it-from-indexes (try - (nodes/create-index "by-url") + (nodes/create-index *connection* "by-url") (catch Exception e (comment We need to make sure we wipe previously created index with a different configuration, ignore cases when it simply does not exist))) - (let [node1 (nodes/create {:name "Wired"}) + (let [node1 (nodes/create *connection* {:name "Wired"}) url1 "http://wired.com" - idx (nodes/create-index "by-url")] - (nodes/delete-from-index (:id node1) (:name idx) "url") - (nodes/add-to-index (:id node1) (:name idx) "url" url1) - (nodes/delete (:id node1)) - (let [ids (set (map :id (nodes/find (:name idx) "url" url1)))] + idx (nodes/create-index *connection* "by-url")] + (nodes/delete-from-index *connection* (:id node1) (:name idx) "url") + (nodes/add-to-index *connection* (:id node1) (:name idx) "url" url1) + (nodes/delete *connection* (:id node1)) + (let [ids (set (map :id (nodes/find *connection* (:name idx) "url" url1)))] (is (not (ids (:id node1))))))) (deftest ^{:indexing true} test-finding-nodes-using-full-text-search-queries-over-index (try - (nodes/delete-index "companies") + (nodes/delete-index *connection* "companies") (catch Exception e (comment We need to make sure we wipe previously created index with a different configuration, ignore cases when it simply does not exist))) - (let [puma (nodes/create {:name "Puma" :hq-location "Herzogenaurach, Germany"}) - apple (nodes/create {:name "Apple" :hq-location "Cupertino, CA, USA"}) - idx (nodes/create-index "companies" {:type :fulltext})] - (nodes/delete-from-index (:id puma) (:name idx)) - (nodes/delete-from-index (:id apple) (:name idx)) - (nodes/add-to-index (:id puma) (:name idx) "country" "Germany") - (nodes/add-to-index (:id apple) (:name idx) "country" "United States of America") - (let [ids (set (map :id (nodes/query (:name idx) "country:Germany")))] + (let [puma (nodes/create *connection* {:name "Puma" :hq-location "Herzogenaurach, Germany"}) + apple (nodes/create *connection* {:name "Apple" :hq-location "Cupertino, CA, USA"}) + idx (nodes/create-index *connection* "companies" {:type :fulltext})] + (nodes/delete-from-index *connection* (:id puma) (:name idx)) + (nodes/delete-from-index *connection* (:id apple) (:name idx)) + (nodes/add-to-index *connection* (:id puma) (:name idx) "country" "Germany") + (nodes/add-to-index *connection* (:id apple) (:name idx) "country" "United States of America") + (let [ids (set (map :id (nodes/query *connection* (:name idx) "country:Germany")))] (is (ids (:id puma))) (is (not (ids (:id apple))))) - (nodes/delete-index "companies"))) + (nodes/delete-index *connection* "companies"))) (deftest ^{:indexing true} test-finding-nodes-using-full-text-search-queries-over-index-example2 (try - (nodes/delete-index "companies") + (nodes/delete-index *connection* "companies") (catch Exception e - (comment We need to make sure we wipe previously created index with a different configuration, ignore cases when it simply does not exist))) - (let [neocons (nodes/create {:name "Neocons" :description "Neocons is an idiomatic Clojure client for the Neo4J Server REST interface"}) - monger (nodes/create {:name "Monger" :description "Monger is a Clojure MongoDB driver for a more civilized age"}) - idx (nodes/create-index "companies" {:type :fulltext :provider "lucene"})] - (nodes/delete-from-index (:id neocons) (:name idx)) - (nodes/delete-from-index (:id monger) (:name idx)) - (nodes/add-to-index (:id neocons) (:name idx) "description" "Neocons is an idiomatic Clojure client for the Neo4J Server REST interface") - (nodes/add-to-index (:id monger) (:name idx) "description" "Monger is a Clojure MongoDB driver for a more civilized age") - (let [ids (set (map :id (nodes/query (:name idx) "description:*civilized*")))] + (comment We need to make sure we wipe previously created index with a different configuration, ignore cases when it simply does not exist))) + (let [neocons (nodes/create *connection* {:name "Neocons" :description "Neocons is an idiomatic Clojure client for the Neo4J Server REST interface"}) + monger (nodes/create *connection* {:name "Monger" :description "Monger is a Clojure MongoDB driver for a more civilized age"}) + idx (nodes/create-index *connection* "companies" {:type :fulltext :provider "lucene"})] + (nodes/delete-from-index *connection* (:id neocons) (:name idx)) + (nodes/delete-from-index *connection* (:id monger) (:name idx)) + (nodes/add-to-index *connection* (:id neocons) (:name idx) "description" "Neocons is an idiomatic Clojure client for the Neo4J Server REST interface") + (nodes/add-to-index *connection* (:id monger) (:name idx) "description" "Monger is a Clojure MongoDB driver for a more civilized age") + (let [ids (set (map :id (nodes/query *connection* (:name idx) "description:*civilized*")))] (is (ids (:id monger))) (is (not (ids (:id neocons))))) - (nodes/delete-index "companies"))) + (nodes/delete-index *connection* "companies"))) diff --git a/test/clojurewerkz/neocons/rest/test/integration_test.clj b/test/clojurewerkz/neocons/rest/test/integration_test.clj index cd851c6..3e87108 100644 --- a/test/clojurewerkz/neocons/rest/test/integration_test.clj +++ b/test/clojurewerkz/neocons/rest/test/integration_test.clj @@ -13,9 +13,10 @@ [clojurewerkz.neocons.rest.nodes :as nn] [clojurewerkz.neocons.rest.relationships :as nr] [clojurewerkz.neocons.rest.paths :as np] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) ;; @@ -24,43 +25,43 @@ ;; (deftest ^{:examples true} test-example1 - (let [homepage (nn/create {:url "http://clojurewerkz.org/"}) - community (nn/create {:url "http://clojurewerkz.org/articles/community.html"}) - about (nn/create {:url "http://clojurewerkz.org/articles/about.html"}) - projects (nn/create {:url "http://clojurewerkz.org/articles/projects.html"}) - rel1 (nr/create homepage community :links) - rel2 (nr/create homepage about :links) + (let [homepage (nn/create *connection* {:url "http://clojurewerkz.org/"}) + community (nn/create *connection* {:url "http://clojurewerkz.org/articles/community.html"}) + about (nn/create *connection* {:url "http://clojurewerkz.org/articles/about.html"}) + projects (nn/create *connection* {:url "http://clojurewerkz.org/articles/projects.html"}) + rel1 (nr/create *connection* homepage community :links) + rel2 (nr/create *connection* homepage about :links) rt {:type :links :direction :out}] - (is (np/exists-between? (:id homepage) (:id community) :relationships [rt])) - (is (np/exists-between? (:id homepage) (:id about) :relationships [rt])) - (is (not (np/exists-between? (:id homepage) (:id projects) :relationships [rt]))) - (nr/replace-outgoing homepage [projects] :links) + (is (np/exists-between? *connection* (:id homepage) (:id community) :relationships [rt])) + (is (np/exists-between? *connection* (:id homepage) (:id about) :relationships [rt])) + (is (not (np/exists-between? *connection* (:id homepage) (:id projects) :relationships [rt]))) + (nr/replace-outgoing *connection* homepage [projects] :links) ;; give graph DB a moment to be updated, even on less powerful CI VMs. MK. (Thread/sleep 150) - (is (np/exists-between? (:id homepage) (:id projects) :relationships [rt])) - (is (not (np/exists-between? (:id homepage) (:id community) :relationships [rt]))) - (is (not (np/exists-between? (:id homepage) (:id about) :relationships [rt]))) - (nn/destroy-many [homepage community about projects]))) + (is (np/exists-between? *connection* (:id homepage) (:id projects) :relationships [rt])) + (is (not (np/exists-between? *connection* (:id homepage) (:id community) :relationships [rt]))) + (is (not (np/exists-between? *connection* (:id homepage) (:id about) :relationships [rt]))) + (nn/destroy-many *connection* [homepage community about projects]))) (deftest ^{:examples true} test-example2 - (nn/create-index "by-url" {:type "exact"}) - (nn/create-index "roots" {:type "exact"}) - (let [homepage (nn/create {:url "http://clojurewerkz.org/"} {"roots" ["root" true]}) - community (nn/create {:url "http://clojurewerkz.org/articles/community.html"} + (nn/create-index *connection* "by-url" {:type "exact"}) + (nn/create-index *connection* "roots" {:type "exact"}) + (let [homepage (nn/create *connection* {:url "http://clojurewerkz.org/"} {"roots" ["root" true]}) + community (nn/create *connection* {:url "http://clojurewerkz.org/articles/community.html"} {"by-url" [:url "http://clojurewerkz.org/articles/community.html"]}) - _ (nn/add-to-index homepage "by-url" :url "http://clojurewerkz.org/") - homepage-alt (nn/find-one "by-url" "url" "http://clojurewerkz.org/") - root-alt (nn/find-one "roots" "root" true) - community-alt (nn/find-one "by-url" "url" "http://clojurewerkz.org/articles/community.html")] + _ (nn/add-to-index *connection* homepage "by-url" :url "http://clojurewerkz.org/") + homepage-alt (nn/find-one *connection* "by-url" "url" "http://clojurewerkz.org/") + root-alt (nn/find-one *connection* "roots" "root" true) + community-alt (nn/find-one *connection* "by-url" "url" "http://clojurewerkz.org/articles/community.html")] (is (= (:id homepage) (:id homepage-alt) (:id root-alt))) (is (= (:id community) (:id community-alt))) - (is (nil? (nn/find-one "by-url" "url" "http://example99.com"))) + (is (nil? (nn/find-one *connection* "by-url" "url" "http://example99.com"))) ;; Neo4J REST API returns nodes in different format via index and regular GET. Make sure we handle ;; both cases. - (nr/create homepage-alt community-alt :links) - (nn/delete-index "by-url") - (nn/delete-index "roots") - (nn/destroy-many [community-alt homepage-alt]))) + (nr/create *connection* homepage-alt community-alt :links) + (nn/delete-index *connection* "by-url") + (nn/delete-index *connection* "roots") + (nn/destroy-many *connection* [community-alt homepage-alt]))) diff --git a/test/clojurewerkz/neocons/rest/test/labels_test.clj b/test/clojurewerkz/neocons/rest/test/labels_test.clj index 988a653..0a9a2a5 100644 --- a/test/clojurewerkz/neocons/rest/test/labels_test.clj +++ b/test/clojurewerkz/neocons/rest/test/labels_test.clj @@ -12,56 +12,58 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.labels :as labels] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) -(deftest ^{:edge-features true} test-creating-one-label - (let [n (nodes/create)] - (is (= (labels/get-all-labels n) [])) - (labels/add n :MyLabel) - (is (= (labels/get-all-labels n) [:MyLabel])))) -(deftest ^{:edge-features true} test-creating-multiple-label - (let [n (nodes/create)] - (labels/add n [:MyLabel :MyOtherLabel]) - (is (= (labels/get-all-labels n) [:MyLabel :MyOtherLabel])))) +(deftest test-creating-one-label + (let [n (nodes/create *connection*)] + (is (= (labels/get-all-labels *connection* n) [])) + (labels/add *connection* n :MyLabel) + (is (= (labels/get-all-labels *connection* n) [:MyLabel])))) -(deftest ^{:edge-features true} test-creating-invalid-label - (let [n (nodes/create)] +(deftest test-creating-multiple-label + (let [n (nodes/create *connection*)] + (labels/add *connection* n [:MyLabel :MyOtherLabel]) + (is (= (labels/get-all-labels *connection* n) [:MyLabel :MyOtherLabel])))) + +(deftest test-creating-invalid-label + (let [n (nodes/create *connection*)] (is (thrown-with-msg? Exception #"Unable to add label" - (labels/add n ""))))) + (labels/add *connection* n ""))))) -(deftest ^{:edge-features true} test-replacing-label - (let [n (nodes/create)] - (labels/add n :MyLabel) - (labels/replace n [:MyOtherLabel :MyThirdLabel]) - (is (= (labels/get-all-labels n) [:MyOtherLabel :MyThirdLabel])))) +(deftest test-replacing-label + (let [n (nodes/create *connection*)] + (labels/add *connection* n :MyLabel) + (labels/replace *connection* n [:MyOtherLabel :MyThirdLabel]) + (is (= (labels/get-all-labels *connection* n) [:MyOtherLabel :MyThirdLabel])))) -(deftest ^{:edge-features true} test-deleting-label - (let [n (nodes/create)] - (labels/add n :MyLabel) - (labels/remove n :MyLabel) - (is (= (labels/get-all-labels n) [])))) +(deftest test-deleting-label + (let [n (nodes/create *connection*)] + (labels/add *connection* n :MyLabel) + (labels/remove *connection* n :MyLabel) + (is (= (labels/get-all-labels *connection* n) [])))) -(deftest ^{:edge-features true} test-get-all-nodes-with-label - (let [n (nodes/create)] - (labels/add n :MyLabel) - (is (some #(= (:id %) (:id n)) (labels/get-all-nodes :MyLabel))))) +(deftest test-get-all-nodes-with-label + (let [n (nodes/create *connection*)] + (labels/add *connection* n :MyLabel) + (is (some #(= (:id %) (:id n)) (labels/get-all-nodes *connection* :MyLabel))))) -(deftest ^{:edge-features true} test-get-all-nodes-with-label-and-property - (let [n (nodes/create {"name" "bob ross"})] - (labels/add n :MyLabel) - (is (some #(= (:id %) (:id n)) (labels/get-all-nodes :MyLabel :name "bob ross"))))) +(deftest test-get-all-nodes-with-label-and-property + (let [n (nodes/create *connection* {"name" "bob ross"})] + (labels/add *connection* n :MyLabel) + (is (some #(= (:id %) (:id n)) (labels/get-all-nodes *connection* :MyLabel :name "bob ross"))))) -(deftest ^{:edge-features true} test-get-all-labels - (let [n (nodes/create)] - (labels/add n :MyLabel) - (is (some #(= % :MyLabel) (labels/get-all-labels))))) +(deftest test-get-all-labels + (let [n (nodes/create *connection*)] + (labels/add *connection* n :MyLabel) + (is (some #(= % :MyLabel) (labels/get-all-labels *connection*))))) -(deftest ^{:edge-features true} test-creating-delete-one-strange-label - (let [n (nodes/create)] - (is (= (labels/get-all-labels n) [])) - (labels/add n "A&B") - (labels/remove n "A&B") - (is (= (labels/get-all-labels n) [])))) +(deftest test-creating-delete-one-strange-label + (let [n (nodes/create *connection*)] + (is (= (labels/get-all-labels *connection* n) [])) + (labels/add *connection* n "A&B") + (labels/remove *connection* n "A&B") + (is (= (labels/get-all-labels *connection* n) [])))) diff --git a/test/clojurewerkz/neocons/rest/test/mutating_cypher_test.clj b/test/clojurewerkz/neocons/rest/test/mutating_cypher_test.clj index b91859c..29f1341 100644 --- a/test/clojurewerkz/neocons/rest/test/mutating_cypher_test.clj +++ b/test/clojurewerkz/neocons/rest/test/mutating_cypher_test.clj @@ -15,15 +15,16 @@ [clojurewerkz.neocons.rest.relationships :as rel] clojurewerkz.neocons.rest.records [clojurewerkz.neocons.rest.cypher :as cy] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all]) (:import clojurewerkz.neocons.rest.records.Node)) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) (defn- exists? [^Node node] (try - (nodes/get (:id node)) + (nodes/get *connection* (:id node)) true (catch Exception e false))) @@ -38,47 +39,47 @@ (deftest ^{:cypher true} test-creating-a-node-via-mutating-cypher (testing "without node properties" - (let [response (cy/tquery "CREATE (n) RETURN n")] + (let [response (cy/tquery *connection* "CREATE (n) RETURN n")] (is (empty? (get-in (first response) ["n" :data]))))) (testing "with node properties" - (let [response (cy/tquery "CREATE (n {name: 'Neocons', type: 'client', language: 'Clojure'}) RETURN n")] + (let [response (cy/tquery *connection* "CREATE (n {name: 'Neocons', type: 'client', language: 'Clojure'}) RETURN n")] (is (= {:name "Neocons" :language "Clojure" :type "client"} (get-in (first response) ["n" :data]))))) (testing "with node properties passed as a map" (let [props {:name "Neocons" :language "Clojure" :type "client"} - response (cy/tquery "CREATE (n {props}) RETURN n" {:props props})] + response (cy/tquery *connection* "CREATE (n {props}) RETURN n" {:props props})] (is (= props (get-in (first response) ["n" :data])))))) (deftest ^{:cypher true} test-creating-a-relationship-between-nodes-via-mutating-cypher - (let [n1 (nodes/create) - n2 (nodes/create) - [{r "r"}] (cy/tquery "START n1 = node({id1}), n2 = node({id2}) CREATE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) + (let [n1 (nodes/create *connection*) + n2 (nodes/create *connection*) + [{r "r"}] (cy/tquery *connection* "START n1 = node({id1}), n2 = node({id2}) CREATE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) :id2 (:id n2)}) - xs (rel/all-outgoing-between n1 n2 ["knows"])] + xs (rel/all-outgoing-between *connection* n1 n2 ["knows"])] (is (= 1 (count xs))) (is (rel/starts-with? r (:id n1))) (is (rel/ends-with? r (:id n2))))) (deftest ^{:cypher true} test-creating-a-relationship-between-nodes-if-it-does-not-exist - (let [n1 (nodes/create) - n2 (nodes/create) - [{r "r"}] (cy/tquery "START n1 = node({id1}), n2 = node({id2}) CREATE UNIQUE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) + (let [n1 (nodes/create *connection*) + n2 (nodes/create *connection*) + [{r "r"}] (cy/tquery *connection* "START n1 = node({id1}), n2 = node({id2}) CREATE UNIQUE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) :id2 (:id n2)}) - _ (cy/tquery "START n1 = node({id1}), n2 = node({id2}) CREATE UNIQUE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) + _ (cy/tquery *connection* "START n1 = node({id1}), n2 = node({id2}) CREATE UNIQUE n1-[r:knows]->n2 RETURN r" {:id1 (:id n1) :id2 (:id n2)}) - xs (rel/all-outgoing-between n1 n2 ["knows"])] + xs (rel/all-outgoing-between *connection* n1 n2 ["knows"])] (is (= 1 (count xs))) (is (rel/starts-with? r (:id n1))) (is (rel/ends-with? r (:id n2))))) (deftest ^{:cypher true} test-purging-a-node-via-mutating-cypher-case1 - (let [john (nodes/create {:name "John" :age 28 :location "New York City, NY"}) - beth (nodes/create {:name "Elizabeth" :age 30 :location "Chicago, IL"}) - gael (nodes/create {:name "Gaël" :age 31 :location "Montpellier"}) - rel1 (rel/create john beth :knows) - rel2 (rel/create john gael :knows)] + (let [john (nodes/create *connection* {:name "John" :age 28 :location "New York City, NY"}) + beth (nodes/create *connection* {:name "Elizabeth" :age 30 :location "Chicago, IL"}) + gael (nodes/create *connection* {:name "Gaël" :age 31 :location "Montpellier"}) + rel1 (rel/create *connection* john beth :knows) + rel2 (rel/create *connection* john gael :knows)] (is (thrown? Exception - (nodes/delete (:id john)))) - (is (cy/empty? (cy/query "START n = node({sid}) MATCH n-[r]-() DELETE n, r" {:sid (:id john)}))) + (nodes/delete *connection* (:id john)))) + (is (cy/empty? (cy/query *connection* "START n = node({sid}) MATCH n-[r]-() DELETE n, r" {:sid (:id john)}))) (is (missing? john)) (is (exists? beth)) (is (exists? gael)))) @@ -89,6 +90,6 @@ (let [urls ["http://clojurewerkz.org/" "http://clojurewerkz.org/articles/about.html" "http://clojurewerkz.org/articles/community.html"] - response (cy/tquery "CREATE (n {xs}) RETURN n", {:xs (map #(hash-map :url %) urls)}) + response (cy/tquery *connection* "CREATE (n {xs}) RETURN n", {:xs (map #(hash-map :url %) urls)}) returned-urls (map #(-> (get % "n") :data :url) response)] (is (= urls returned-urls)))) diff --git a/test/clojurewerkz/neocons/rest/test/nodes_test.clj b/test/clojurewerkz/neocons/rest/test/nodes_test.clj index 924929a..e4e30d6 100644 --- a/test/clojurewerkz/neocons/rest/test/nodes_test.clj +++ b/test/clojurewerkz/neocons/rest/test/nodes_test.clj @@ -11,10 +11,11 @@ (ns clojurewerkz.neocons.rest.test.nodes-test (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] - [clojure.test :refer :all] + [clojure.test :refer :all] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojurewerkz.neocons.rest.records :refer [instantiate-node-from]])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) ;; @@ -22,78 +23,78 @@ ;; (deftest test-creating-and-immediately-accessing-a-node-without-properties - (let [created-node (nodes/create) - fetched-node (nodes/get (:id created-node))] + (let [created-node (nodes/create *connection*) + fetched-node (nodes/get *connection* (:id created-node))] (is (= (:id created-node) (:id fetched-node))))) (deftest test-creating-and-immediately-accessing-a-node-with-properties (let [data {:key "value"} - created-node (nodes/create data) - fetched-node (nodes/get (:id created-node))] + created-node (nodes/create *connection* data) + fetched-node (nodes/get *connection* (:id created-node))] (is (= (:id created-node) (:id fetched-node))) (is (= (:data created-node) data)))) (deftest test-creating-and-immediately-accessing-a-unique-node-in-an-index (let [data {:name "Tobias" :value "test"} - created-n1 (nodes/create-unique-in-index "vertices" "name" "Tobias" data) - created-n2 (nodes/create-unique-in-index "vertices" "name" "Tobias" {})] + created-n1 (nodes/create-unique-in-index *connection* "vertices" "name" "Tobias" data) + created-n2 (nodes/create-unique-in-index *connection* "vertices" "name" "Tobias" {})] (is (= (:id created-n1) (:id created-n2))) (is (= (:data created-n1) (:data created-n2))) (is (= (:data created-n1) data)) - (is (nodes/find-one "vertices" "name" "Tobias")) - (is (not (nodes/find-one "vertices" "name" "asd09asud987987"))))) + (is (nodes/find-one *connection* "vertices" "name" "Tobias")) + (is (not (nodes/find-one *connection* "vertices" "name" "asd09asud987987"))))) (deftest test-accessing-a-non-existent-node (is (thrown? Exception - (nodes/get 928398827)))) + (nodes/get *connection* 928398827)))) (deftest test-creating-and-deleting-a-node-with-properties (let [data {:key "value"} - created-node (nodes/create data) - [deleted-id status] (nodes/delete (:id created-node))] + created-node (nodes/create *connection* data) + [deleted-id status] (nodes/delete *connection* (:id created-node))] (is (= 204 status)) (is (= (:id created-node) deleted-id)))) (deftest test-attempting-to-delete-a-non-existent-node (is (thrown? Exception - (nodes/delete 237737737)))) + (nodes/delete *connection* 237737737)))) (deftest test-creating-and-getting-properties-of-one-node (let [data {:key "value"} - created-node (nodes/create data) - fetched-data (nodes/get-properties (:id created-node))] + created-node (nodes/create *connection* data) + fetched-data (nodes/get-properties *connection* (:id created-node))] (is (= data fetched-data)))) (deftest test-creating-and-getting-empty-properties-of-one-node - (let [created-node (nodes/create) - fetched-data (nodes/get-properties (:id created-node))] + (let [created-node (nodes/create *connection*) + fetched-data (nodes/get-properties *connection* (:id created-node))] (is (= {} fetched-data)))) (deftest test-updating-a-single-node-property - (let [node (nodes/create {:age 26}) - fetched-node (nodes/get (:id node)) - new-value (nodes/set-property (:id node) :age 27) - updated-node (nodes/get (:id fetched-node))] + (let [node (nodes/create *connection* {:age 26}) + fetched-node (nodes/get *connection* (:id node)) + new-value (nodes/set-property *connection* (:id node) :age 27) + updated-node (nodes/get *connection* (:id fetched-node))] (is (= new-value (-> updated-node :data :age))))) (deftest test-updating-node-properties - (let [node (nodes/create {:age 26}) - fetched-node (nodes/get (:id node)) - new-data (nodes/update (:id node) {:age 27 :gender "male"}) - updated-node (nodes/get (:id fetched-node))] + (let [node (nodes/create *connection* {:age 26}) + fetched-node (nodes/get *connection* (:id node)) + new-data (nodes/update *connection* (:id node) {:age 27 :gender "male"}) + updated-node (nodes/get *connection* (:id fetched-node))] (is (= new-data (-> updated-node :data))))) (deftest test-deleting-all-properties-from-a-node (let [data {:key "value"} - created-node (nodes/create data) - fetched-data (nodes/get-properties (:id created-node))] + created-node (nodes/create *connection* data) + fetched-data (nodes/get-properties *connection* (:id created-node))] (is (= data fetched-data)) - (nodes/delete-properties (:id created-node)) - (is (= {} (nodes/get-properties (:id created-node)))))) + (nodes/delete-properties *connection* (:id created-node)) + (is (= {} (nodes/get-properties *connection* (:id created-node)))))) diff --git a/test/clojurewerkz/neocons/rest/test/relationships_test.clj b/test/clojurewerkz/neocons/rest/test/relationships_test.clj index e5d0eed..5bac845 100644 --- a/test/clojurewerkz/neocons/rest/test/relationships_test.clj +++ b/test/clojurewerkz/neocons/rest/test/relationships_test.clj @@ -15,42 +15,43 @@ [clojurewerkz.neocons.rest.paths :as paths] [clojure.test :refer :all] [clojure.set :refer [subset?]] - [clojurewerkz.neocons.rest.records :refer [instantiate-node-from instantiate-rel-from]])) - -(neorest/connect! "http://localhost:7474/db/data/") + [clojurewerkz.neocons.rest.records :refer [instantiate-node-from instantiate-rel-from]] + [clojurewerkz.neocons.rest.test.common :refer :all])) (def ^{:private true} ids-from (partial map :id)) +(use-fixtures :once once-fixture) + ;; ;; Working with relationships ;; (deftest test-creating-and-immediately-accessing-a-relationship-without-properties - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links) - fetched-rel (relationships/get (:id created-rel))] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= (:id created-rel) (:id fetched-rel))) (is (= (:type created-rel) (:type fetched-rel))))) (deftest test-creating-the-same-relationship-without-properties-twice - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links) - created-rel2 (relationships/create from-node to-node :links) - fetched-rel (relationships/get (:id created-rel))] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links) + created-rel2 (relationships/create *connection* from-node to-node :links) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= (:id created-rel) (:id fetched-rel))) (is (not (= (:id created-rel) (:id created-rel2)))) (is (= (:type created-rel) (:type fetched-rel))) (is (= (:type created-rel) (:type created-rel2))))) (deftest test-avoiding-creating-the-same-relationship-without-properties-twice - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/maybe-create from-node to-node :links) - created-rel2 (relationships/maybe-create from-node to-node :links) - fetched-rel (relationships/get (:id created-rel))] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/maybe-create *connection* from-node to-node :links) + created-rel2 (relationships/maybe-create *connection* from-node to-node :links) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= created-rel created-rel2)) (is (= (:id created-rel) (:id fetched-rel))) (is (= (:id created-rel) (:id created-rel2))) @@ -58,11 +59,11 @@ (is (= (:type created-rel) (:type created-rel2))))) (deftest test-avoiding-creating-the-same-relationship-with-ids - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/maybe-create (:id from-node) (:id to-node) :links) - created-rel2 (relationships/maybe-create (:id from-node) (:id to-node) :links) - fetched-rel (relationships/get (:id created-rel))] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/maybe-create *connection* (:id from-node) (:id to-node) :links) + created-rel2 (relationships/maybe-create *connection* (:id from-node) (:id to-node) :links) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= created-rel created-rel2)) (is (= (:id created-rel) (:id fetched-rel))) (is (= (:id created-rel) (:id created-rel2))) @@ -70,46 +71,46 @@ (is (= (:type created-rel) (:type created-rel2))))) (deftest test-avoiding-destroying-the-same-relationship-without-properties-twice - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links) + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links) rt {:type "links" :direction "out"}] - (is (relationships/first-outgoing-between from-node to-node [:links])) - (is (nil? (relationships/first-outgoing-between from-node to-node [:loves]))) - (is (= created-rel (relationships/first-outgoing-between from-node to-node [:links]))) - (is (paths/exists-between? (:id from-node) (:id to-node) :relationships [rt] :max-depth 1)) - (relationships/maybe-delete-outgoing from-node to-node [:links]) - (is (nil? (relationships/first-outgoing-between from-node to-node [:links]))) - (is (not (paths/exists-between? (:id from-node) (:id to-node) :relationships [rt] :max-depth 1))) - (relationships/maybe-delete-outgoing from-node to-node [:links]))) + (is (relationships/first-outgoing-between *connection* from-node to-node [:links])) + (is (nil? (relationships/first-outgoing-between *connection* from-node to-node [:loves]))) + (is (= created-rel (relationships/first-outgoing-between *connection* from-node to-node [:links]))) + (is (paths/exists-between? *connection* (:id from-node) (:id to-node) :relationships [rt] :max-depth 1)) + (relationships/maybe-delete-outgoing *connection* from-node to-node [:links]) + (is (nil? (relationships/first-outgoing-between *connection* from-node to-node [:links]))) + (is (not (paths/exists-between? *connection* (:id from-node) (:id to-node) :relationships [rt] :max-depth 1))) + (relationships/maybe-delete-outgoing *connection* from-node to-node [:links]))) (deftest test-creating-and-immediately-accessing-a-relationship-with-properties (let [data {:one "uno" :two "due"} - from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links data) - fetched-rel (relationships/get (:id created-rel))] + from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links data) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= (:id created-rel) (:id fetched-rel))) (is (= (:type created-rel) (:type fetched-rel))) (is (= (:data created-rel) (:data fetched-rel))))) (deftest test-creating-and-immediately-accessing-a-unique-relationship-in-index - (let [from-node (nodes/create) - to-node (nodes/create) - created-r1 (relationships/create-unique-in-index from-node to-node :links "edges" "test" "test-1") - created-r2 (relationships/create-unique-in-index from-node to-node :links "edges" "test" "test-1")] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-r1 (relationships/create-unique-in-index *connection* from-node to-node :links "edges" "test" "test-1") + created-r2 (relationships/create-unique-in-index *connection* from-node to-node :links "edges" "test" "test-1")] (is (= (:id created-r1) (:id created-r2))) (is (= (:type created-r1) (:type created-r2))) - (is (relationships/find-one "edges" "test" "test-1")))) + (is (relationships/find-one *connection* "edges" "test" "test-1")))) (deftest test-creating-and-immediately-accessing-a-unique-relationship-in-index-with-properties (let [data {:one "uno" :two "due"} - from-node (nodes/create) - to-node (nodes/create) - created-r1 (relationships/create-unique-in-index from-node to-node :links "edges" "test" "test-2" data) - created-r2 (relationships/create-unique-in-index from-node to-node :links "edges" "test" "test-2" data) - fetched-r1 (relationships/get (:id created-r1)) - fetched-r2 (relationships/get (:id created-r2))] + from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-r1 (relationships/create-unique-in-index *connection* from-node to-node :links "edges" "test" "test-2" data) + created-r2 (relationships/create-unique-in-index *connection* from-node to-node :links "edges" "test" "test-2" data) + fetched-r1 (relationships/get *connection* (:id created-r1)) + fetched-r2 (relationships/get *connection* (:id created-r2))] (is (= (:id created-r1) (:id created-r2))) (is (= (:type created-r1) (:type created-r2))) (is (= (:data created-r1) (:data created-r2))) @@ -117,109 +118,109 @@ (is (= (:id created-r2) (:id fetched-r1))))) (deftest test-creating-and-deleting-a-relationship-without-properties - (let [from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links) - [deleted-id status] (relationships/delete (:id created-rel))] + (let [from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links) + [deleted-id status] (relationships/delete *connection* (:id created-rel))] (is (= 204 status)))) (deftest test-creating-and-deleting-a-non-existent-relationship ;; this should be slingshot.ExceptionInfo on 1.3 but ;; clojure.lang.ExceptionInfo on 1.4.0+. This Slingshot shit is annoying. MK. (is (thrown? Exception - (relationships/delete 87238467666))) + (relationships/delete *connection* 87238467666))) (try - (relationships/delete 87238467666) + (relationships/delete *connection* 87238467666) (catch Exception e (let [d (.getData e)] (is (= (-> d :object :status) 404)))))) (deftest test-creating-multiple-relationships-at-once - (let [from-node (nodes/create) - to-node1 (nodes/create) - to-node2 (nodes/create) - to-node3 (nodes/create) - created-rels (relationships/create-many from-node [to-node1 to-node2 to-node3] :links)] + (let [from-node (nodes/create *connection*) + to-node1 (nodes/create *connection*) + to-node2 (nodes/create *connection*) + to-node3 (nodes/create *connection*) + created-rels (relationships/create-many *connection* from-node [to-node1 to-node2 to-node3] :links)] (is (= 3 (count created-rels))) ;; give graph DB a moment to be updated, even on less powerful CI VMs. MK. (Thread/sleep 150) (is (= (sort (ids-from created-rels)) - (sort (ids-from (relationships/outgoing-for from-node :types [:links]))))))) + (sort (ids-from (relationships/outgoing-for *connection* from-node :types [:links]))))))) (deftest test-listing-all-relationships-on-a-node-that-doesnt-have-any - (let [node (nodes/create) - result (relationships/all-for node)] + (let [node (nodes/create *connection*) + result (relationships/all-for *connection* node)] (is (empty? result)))) (deftest test-listing-all-relationships-on-a-node-that-has-3-relationships - (let [node (nodes/create) - _ (relationships/create node (nodes/create) :links) - _ (relationships/create node (nodes/create) :links) - _ (relationships/create node (nodes/create) :links) - result (relationships/all-for node)] + (let [node (nodes/create *connection*) + _ (relationships/create *connection* node (nodes/create *connection*) :links) + _ (relationships/create *connection* node (nodes/create *connection*) :links) + _ (relationships/create *connection* node (nodes/create *connection*) :links) + result (relationships/all-for *connection* node)] (is (= 3 (count result))))) (deftest test-listing-all-relationships-of-specific-kind - (let [node (nodes/create) - rel1 (relationships/create node (nodes/create) :likes) - rel2 (relationships/create node (nodes/create) :links) - rel3 (relationships/create node (nodes/create) :follows) - result (relationships/all-for node :types [:follows :likes])] + (let [node (nodes/create *connection*) + rel1 (relationships/create *connection* node (nodes/create *connection*) :likes) + rel2 (relationships/create *connection* node (nodes/create *connection*) :links) + rel3 (relationships/create *connection* node (nodes/create *connection*) :follows) + result (relationships/all-for *connection* node :types [:follows :likes])] (is (= 2 (count result))) (is (= (sort [(:id rel1) (:id rel3)]) (vec (sort (map :id result))))))) (deftest test-listing-incoming-relationships-on-a-node-that-doesnt-have-any - (let [node (nodes/create) - result (relationships/incoming-for node)] + (let [node (nodes/create *connection*) + result (relationships/incoming-for *connection* node)] (is (empty? result)))) (deftest test-listing-incoming-relationships-on-a-node-that-has-2-incoming-relationships - (let [node (nodes/create) - _ (relationships/create (nodes/create) node :friend) - _ (relationships/create (nodes/create) node :relative) - result (relationships/incoming-for node :types [:friend])] + (let [node (nodes/create *connection*) + _ (relationships/create *connection* (nodes/create *connection*) node :friend) + _ (relationships/create *connection* (nodes/create *connection*) node :relative) + result (relationships/incoming-for *connection* node :types [:friend])] (is (= 1 (count result))))) (deftest test-listing-incoming-relationships-of-specific-kind - (let [node (nodes/create) - _ (relationships/create (nodes/create) node :links) - _ (relationships/create (nodes/create) node :links) - result (relationships/incoming-for node)] + (let [node (nodes/create *connection*) + _ (relationships/create *connection* (nodes/create *connection*) node :links) + _ (relationships/create *connection* (nodes/create *connection*) node :links) + result (relationships/incoming-for *connection* node)] (is (= 2 (count result))))) (deftest test-listing-outgoing-relationships-on-a-node-that-doesnt-have-any - (let [node (nodes/create) - result (relationships/outgoing-for node)] + (let [node (nodes/create *connection*) + result (relationships/outgoing-for *connection* node)] (is (empty? result)))) (deftest test-listing-outgoing-relationships-on-a-node-that-has-1-outgoing-relationship - (let [node (nodes/create) - _ (relationships/create node (nodes/create) :links) - result (relationships/outgoing-for node)] + (let [node (nodes/create *connection*) + _ (relationships/create *connection* node (nodes/create *connection*) :links) + result (relationships/outgoing-for *connection* node)] (is (= 1 (count result))))) (deftest test-listing-outgoing-relationships-of-specific-kind - (let [node (nodes/create) - _ (relationships/create node (nodes/create) :friend) - _ (relationships/create node (nodes/create) :relative) - result (relationships/outgoing-for node :types [:relative])] + (let [node (nodes/create *connection*) + _ (relationships/create *connection* node (nodes/create *connection*) :friend) + _ (relationships/create *connection* node (nodes/create *connection*) :relative) + result (relationships/outgoing-for *connection* node :types [:relative])] (is (= 1 (count result))))) (deftest test-listing-of-relationship-types - (let [node (nodes/create) - _ (relationships/create node (nodes/create) :friend) - _ (relationships/create node (nodes/create) :relative)] - (is (subset? #{"friend" "relative"} (set (relationships/all-types)))))) + (let [node (nodes/create *connection*) + _ (relationships/create *connection* node (nodes/create *connection*) :friend) + _ (relationships/create *connection* node (nodes/create *connection*) :relative)] + (is (subset? #{"friend" "relative"} (set (relationships/all-types *connection*)))))) (deftest test-updating-relationship-properties (let [data {:one "uno" :two "due"} - from-node (nodes/create) - to-node (nodes/create) - created-rel (relationships/create from-node to-node :links data) - new-data (relationships/update (:id created-rel) {:one "eine" :two "deux"}) - fetched-rel (relationships/get (:id created-rel))] + from-node (nodes/create *connection*) + to-node (nodes/create *connection*) + created-rel (relationships/create *connection* from-node to-node :links data) + new-data (relationships/update *connection* (:id created-rel) {:one "eine" :two "deux"}) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= (:id created-rel) (:id fetched-rel))) (is (= (:type created-rel) (:type fetched-rel))) (is (= new-data (:data fetched-rel))))) @@ -227,11 +228,11 @@ (deftest test-deleting-a-specific-relationship-property (let [data {:cost "high" :legendary true} - from-node (nodes/create {:name "Romeo"}) - to-node (nodes/create {:name "Juliet"}) - created-rel (relationships/create from-node to-node :loves data) - _ (relationships/delete-property (:id created-rel) :cost) - fetched-rel (relationships/get (:id created-rel))] + from-node (nodes/create *connection* {:name "Romeo"}) + to-node (nodes/create *connection* {:name "Juliet"}) + created-rel (relationships/create *connection* from-node to-node :loves data) + _ (relationships/delete-property *connection* (:id created-rel) :cost) + fetched-rel (relationships/get *connection* (:id created-rel))] (is (= (:id created-rel) (:id fetched-rel))) (is (= (:type created-rel) (:type fetched-rel))) (is (= {:legendary true} (:data fetched-rel))))) @@ -239,16 +240,16 @@ (deftest test-deleting-a-non-existent-relationship-property (let [data {:cost "high" :legendary true} - from-node (nodes/create {:name "Romeo"}) - to-node (nodes/create {:name "Juliet"}) - created-rel (relationships/create from-node to-node :loves data)] + from-node (nodes/create *connection* {:name "Romeo"}) + to-node (nodes/create *connection* {:name "Juliet"}) + created-rel (relationships/create *connection* from-node to-node :loves data)] (is (thrown? Exception - (relationships/delete-property (:id created-rel) :a-non-existent-rel-property))))) + (relationships/delete-property *connection* (:id created-rel) :a-non-existent-rel-property))))) (deftest test-deleting-a-property-on-non-existent-relationship (is (thrown? Exception - (relationships/delete-property 8283787287 :a-non-existent-rel-property)))) + (relationships/delete-property *connection* 8283787287 :a-non-existent-rel-property)))) ;; @@ -256,32 +257,36 @@ ;; (deftest test-deletion-of-nodes-with-relationships - (let [john (nodes/create {:name "John" :age 28 :location "New York City, NY"}) - beth (nodes/create {:name "Elizabeth" :age 30 :location "Chicago, IL"}) - gael (nodes/create {:name "Gaël" :age 31 :location "Montpellier"}) - rel1 (relationships/create john beth :knows) - rel5 (relationships/create beth gael :knows) - rt {:type "knows" :direction "out"}] - (is (paths/exists-between? (:id john) (:id gael) :relationships [rt] :max-depth 3)) - (is (set (nodes/all-connected-out (:id john))) (:id beth)) - (is (nodes/connected-out? (:id john) (:id beth))) - (is (not (nodes/connected-out? (:id john) (:id gael)))) - (is (set (nodes/all-connected-out (:id beth))) (:id gael)) - (is (nodes/connected-out? (:id beth) (:id gael))) + (let [john (nodes/create *connection* {:name "John" :age 28 :location "New York City, NY"}) + beth (nodes/create *connection* {:name "Elizabeth" :age 30 :location "Chicago, IL"}) + gael (nodes/create *connection* {:name "Gaël" :age 31 :location "Montpellier"}) + rel1 (relationships/create *connection* john beth :knows) + rel5 (relationships/create *connection* beth gael :knows) + rt {:type "knows" :direction "out"} + john-know (set (nodes/all-connected-out *connection* (:id john))) + beth-know (set (nodes/all-connected-out *connection* (:id beth)))] + (is (paths/exists-between? *connection* (:id john) (:id gael) :relationships [rt] :max-depth 3)) + (is (= (count john-know) 1)) + (is (= (:id (first john-know)) (:id beth))) + (is (nodes/connected-out? *connection* (:id john) (:id beth))) + (is (not (nodes/connected-out? *connection* (:id john) (:id gael)))) + (is (= (count beth-know) 1)) + (is (= (:id (first beth-know)) (:id gael))) + (is (nodes/connected-out? *connection* (:id beth) (:id gael))) ;; deletion of a node affects reachability of two other nodes. MK. (is (thrown? Exception - (nodes/delete (:id beth)))) - (relationships/purge-all beth) - (nodes/delete (:id beth)) - (is (not (paths/exists-between? (:id john) (:id gael) :relationships [rt] :max-depth 3))))) + (nodes/delete *connection* (:id beth)))) + (relationships/purge-all *connection* beth) + (nodes/delete *connection* (:id beth)) + (is (not (paths/exists-between? *connection* (:id john) (:id gael) :relationships [rt] :max-depth 3))))) (deftest test-purging-of-all-outgoing-relationships - (let [john (nodes/create {:name "John" :age 28 :location "New York City, NY"}) - beth (nodes/create {:name "Elizabeth" :age 30 :location "Chicago, IL"}) - gael (nodes/create {:name "Gaël" :age 31 :location "Montpellier"}) - rel1 (relationships/create john beth :knows) - rel5 (relationships/create beth gael :knows) + (let [john (nodes/create *connection* {:name "John" :age 28 :location "New York City, NY"}) + beth (nodes/create *connection* {:name "Elizabeth" :age 30 :location "Chicago, IL"}) + gael (nodes/create *connection* {:name "Gaël" :age 31 :location "Montpellier"}) + rel1 (relationships/create *connection* john beth :knows) + rel5 (relationships/create *connection* beth gael :knows) rt {:type "knows" :direction "out"}] - (is (paths/exists-between? (:id john) (:id gael) :relationships [rt] :max-depth 3)) - (relationships/purge-outgoing beth) - (is (not (paths/exists-between? (:id john) (:id gael) :relationships [rt] :max-depth 3))))) + (is (paths/exists-between? *connection* (:id john) (:id gael) :relationships [rt] :max-depth 3)) + (relationships/purge-outgoing *connection* beth) + (is (not (paths/exists-between? *connection* (:id john) (:id gael) :relationships [rt] :max-depth 3))))) diff --git a/test/clojurewerkz/neocons/rest/test/spatial_test.clj b/test/clojurewerkz/neocons/rest/test/spatial_test.clj index 0113d42..b850afd 100644 --- a/test/clojurewerkz/neocons/rest/test/spatial_test.clj +++ b/test/clojurewerkz/neocons/rest/test/spatial_test.clj @@ -12,26 +12,27 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.spatial :as sp] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) (deftest ^{:spatial true} test-create-layer - (let [created-layer-1 (sp/add-simple-point-layer "test-layer-1") - created-layer-2 (sp/add-simple-point-layer "test-layer-2" "x" "y")] + (let [created-layer-1 (sp/add-simple-point-layer *connection* "test-layer-1") + created-layer-2 (sp/add-simple-point-layer *connection* "test-layer-2" "x" "y")] (is (= "test-layer-1" (:layer (:data created-layer-1)))) (is (= "test-layer-2" (:layer (:data created-layer-2)))) (is (= "y:x" (:geomencoder_config (:data created-layer-2)))))) (deftest ^{:spatial true} test-add-node-to-layer - (let [created-layer-1 (sp/add-simple-point-layer "test-layer-add") - test-node (nodes/create {:latitude 60.1 :longitude 15.4 :foo "bar"}) - added-node (sp/add-node-to-layer "test-layer-add" test-node)] + (let [created-layer-1 (sp/add-simple-point-layer *connection* "test-layer-add") + test-node (nodes/create *connection* {:latitude 60.1 :longitude 15.4 :foo "bar"}) + added-node (sp/add-node-to-layer *connection* "test-layer-add" test-node)] (is (= [15.4 60.1 15.4 60.1] (:bbox (:data added-node)))))) (deftest ^{:spatial true} test-find-within-distance - (let [created-layer-1 (sp/add-simple-point-layer "test-layer-search") - test-node (nodes/create {:latitude -60.1 :longitude -15.4 :foo "target test node"}) - added-node (sp/add-node-to-layer "test-layer-search" test-node) - found (sp/find-within-distance "test-layer-search" -15.0 -60.0 100)] + (let [created-layer-1 (sp/add-simple-point-layer *connection* "test-layer-search") + test-node (nodes/create *connection* {:latitude -60.1 :longitude -15.4 :foo "target test node"}) + added-node (sp/add-node-to-layer *connection* "test-layer-search" test-node) + found (sp/find-within-distance *connection* "test-layer-search" -15.0 -60.0 100)] (is (= "target test node" (:foo (:data (first found))))))) diff --git a/test/clojurewerkz/neocons/rest/test/transaction_test.clj b/test/clojurewerkz/neocons/rest/test/transaction_test.clj index 795d605..db0a1a7 100644 --- a/test/clojurewerkz/neocons/rest/test/transaction_test.clj +++ b/test/clojurewerkz/neocons/rest/test/transaction_test.clj @@ -12,9 +12,11 @@ (:require [clojurewerkz.neocons.rest :as neorest] [clojurewerkz.neocons.rest.nodes :as nodes] [clojurewerkz.neocons.rest.transaction :as tx] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojure.test :refer :all])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) + (deftest test-converting-from-tx-statement-from (are [x y] (= y (tx/tx-statement-from x)) @@ -29,17 +31,17 @@ :parameters {:props {:name "My Node"}}}]} [] {:statements []})) -(deftest ^{:edge-features true} test-empty-transaction-rollback - (let [[transaction y] (tx/begin)] +(deftest test-empty-transaction-rollback + (let [[transaction y] (tx/begin *connection*)] (are [x] (not (nil? (x transaction))) :commit :location :expires) (is (= [] y)) - (is (= (tx/rollback transaction) [])))) + (is (= (tx/rollback *connection* transaction) [])))) -(deftest ^{:edge-features true} test-transaction-rollback - (let [[transaction [result]] (tx/begin [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] +(deftest test-transaction-rollback + (let [[transaction [result]] (tx/begin *connection* [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] (are [x] (not (nil? (x transaction))) :commit :location @@ -47,10 +49,10 @@ (is (= (:data result) [{:row [{:name "My Node"}]}])) (is (= (:columns result) ["n"])) - (is (= (tx/rollback transaction) [])))) + (is (= (tx/rollback *connection* transaction) [])))) -(deftest ^{:edge-features true} test-transaction-commit-empty - (let [[transaction [result]] (tx/begin [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] +(deftest test-transaction-commit-empty + (let [[transaction [result]] (tx/begin *connection* [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] (are [x] (not (nil? (x transaction))) :commit :location @@ -59,10 +61,10 @@ (is (= (:data result) [{:row [{:name "My Node"}]}])) (is (= (:columns result) ["n"])) - (is (= (tx/commit transaction) [])))) + (is (= (tx/commit *connection* transaction) [])))) -(deftest ^{:edge-features true} test-transaction-commit - (let [[transaction [result]] (tx/begin [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] +(deftest test-transaction-commit + (let [[transaction [result]] (tx/begin *connection* [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] (are [x] (not (nil? (x transaction))) :commit :location @@ -71,12 +73,12 @@ (is (= (:data result) [{:row [{:name "My Node"}]}])) (is (= (:columns result) ["n"])) - (let [[result] (tx/commit transaction [(tx/statement "CREATE n RETURN id(n)" nil)] )] + (let [[result] (tx/commit *connection* transaction [(tx/statement "CREATE n RETURN id(n)" nil)] )] (is (= (:columns result) ["id(n)"])) (is (= (count (:data result)) 1))))) -(deftest ^{:edge-features true} test-transaction-continue-commit - (let [[transaction [result]] (tx/begin [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] +(deftest test-transaction-continue-commit + (let [[transaction [result]] (tx/begin *connection* [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] (are [x] (not (nil? (x transaction))) :commit :location @@ -85,7 +87,7 @@ (is (= (:data result) [{:row [{:name "My Node"}]}])) (is (= (:columns result) ["n"])) - (let [[a [b]] (tx/execute transaction [(tx/statement "CREATE n RETURN id(n)" nil)] )] + (let [[a [b]] (tx/execute *connection* transaction [(tx/statement "CREATE n RETURN id(n)" nil)] )] (are [x] (not (nil? (x a))) :commit :location @@ -93,10 +95,10 @@ (is (= (count (:data b)) 1)) (is (= (:columns b) ["id(n)"]))) - (is (= (tx/commit transaction) [])))) + (is (= (tx/commit *connection* transaction) [])))) -(deftest ^{:edge-features true} test-transaction-fail-rollback - (let [[transaction [result]] (tx/begin [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] +(deftest test-transaction-fail-rollback + (let [[transaction [result]] (tx/begin *connection* [(tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}})])] (are [x] (not (nil? (x transaction))) :commit :location @@ -107,74 +109,84 @@ (is (thrown-with-msg? Exception #"Transaction failed and rolled back" (tx/execute - transaction - [(tx/statement "CREATE n RETURN id(m)" nil)]))))) + *connection* + transaction + [(tx/statement "CREATE n RETURN id(m)" nil)]))))) -(deftest ^{:edge-features true} test-simple-transaction +(deftest test-simple-transaction (let [result (tx/in-transaction - (tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}}) - (tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Another Node"}}))] + *connection* + (tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Node"}}) + (tx/statement "CREATE (n {props}) RETURN n" {:props {:name "My Another Node"}}))] (is (= (count result) 2)) (is (= (:data (first result)) [{:row [{:name "My Node"}]}])) (is (= (:columns (first result)) ["n"] )) (is (= (:data (second result)) [{:row [{:name "My Another Node"}]}])) (is (= (:columns (second result)) ["n"] )))) -(deftest ^{:edge-features true} test-empty-begin-tx - (let [transaction (tx/begin-tx)] +(deftest test-empty-begin-tx + (let [transaction (tx/begin-tx *connection*)] (are [x] (not (nil? (x transaction))) :commit :location :expires))) -(deftest ^{:edge-features true} test-with-transaction-commit-success - (let [transaction (tx/begin-tx)] - (is (= (tx/with-transaction - transaction - true - (let [[_ [r]] (tx/execute - transaction - [(tx/statement "CREATE (n {props}) RETURN n" - {:props {:name "My Node"}})])] - (is (= (count (:data r)) 1)) - (is (= (:data r) [{:row [{:name "My Node"}]}])) - (is (= (:columns r) ["n"]))))) - []))) - - -(deftest ^{:edge-features true} test-with-transaction-rollback-success - (let [transaction (tx/begin-tx)] +(deftest test-with-transaction-commit-success + (let [transaction (tx/begin-tx *connection*)] (tx/with-transaction + *connection* + transaction + true + (let [[_ [r]] (tx/execute + *connection* + transaction + [(tx/statement "CREATE (n {props}) RETURN n" + {:props {:name "My Node"}})])] + (is (= (count (:data r)) 1)) + (is (= (:data r) [{:row [{:name "My Node"}]}])) + (is (= (:columns r) ["n"])))))) + + +(deftest test-with-transaction-rollback-success + (let [transaction (tx/begin-tx *connection*)] + (tx/with-transaction + *connection* transaction false (let [[_ [r]] (tx/execute - transaction - [(tx/statement "CREATE (n {props}) RETURN n" - {:props {:name "My Node"}})])] + *connection* + transaction + [(tx/statement "CREATE (n {props}) RETURN n" + {:props {:name "My Node"}})])] (is (= (count (:data r)) 1)) (is (= (:data r) [{:row [{:name "My Node"}]}])) (is (= (:columns r) ["n"]))) - (is (= (tx/rollback transaction) + (is (= (tx/rollback *connection* transaction) []))))) -(deftest ^{:edge-features true} test-with-transaction-manual-failure - (let [transaction (tx/begin-tx)] +(deftest test-with-transaction-manual-failure + (let [transaction (tx/begin-tx *connection*)] (is (thrown-with-msg? Exception #"Rolling back" (tx/with-transaction + *connection* transaction true (tx/execute - transaction [(tx/statement "CREATE (n) RETURN ID(n)")]) + *connection* + transaction + [(tx/statement "CREATE (n) RETURN ID(n)")]) (throw (Exception. "Rolling back"))))))) -(deftest ^{:edge-features true} test-with-transaction-transaction-failure - (let [transaction (tx/begin-tx)] +(deftest test-with-transaction-transaction-failure + (let [transaction (tx/begin-tx *connection*)] (is (thrown-with-msg? Exception #"InvalidSyntax" (tx/with-transaction + *connection* transaction true (tx/execute - transaction [(tx/statement "CREATE (n) RETURN ID(m)")])))))) + *connection* + transaction [(tx/statement "CREATE (n) RETURN ID(m)")])))))) diff --git a/test/clojurewerkz/neocons/rest/test/traversal_test.clj b/test/clojurewerkz/neocons/rest/test/traversal_test.clj index aea3d72..aa883fa 100644 --- a/test/clojurewerkz/neocons/rest/test/traversal_test.clj +++ b/test/clojurewerkz/neocons/rest/test/traversal_test.clj @@ -15,77 +15,81 @@ [clojurewerkz.neocons.rest.paths :as paths] [clojure.test :refer :all] [clojure.set :refer [subset?]] + [clojurewerkz.neocons.rest.test.common :refer :all] [clojurewerkz.neocons.rest.records :refer [instantiate-node-from instantiate-rel-from instantiate-path-from]])) -(neorest/connect! "http://localhost:7474/db/data/") +(use-fixtures :once once-fixture) ;; ;; Traversal ;; (deftest ^{:traversal true} test-traversing-nodes-using-all-return-filter-all-relationships-and-no-pagination - (let [john (nodes/create {:name "John"}) - adam (nodes/create {:name "Alan"}) - pete (nodes/create {:name "Peter"}) - _ (relationships/create john adam :friend) - _ (relationships/create john pete :friend) - _ (relationships/create adam pete :friend) - xs1 (nodes/traverse (:id john) :relationships [{:direction "all" :type "friend"}]) + (let [john (nodes/create *connection* {:name "John"}) + adam (nodes/create *connection* {:name "Alan"}) + pete (nodes/create *connection* {:name "Peter"}) + _ (relationships/create *connection* john adam :friend) + _ (relationships/create *connection* john pete :friend) + _ (relationships/create *connection* adam pete :friend) + xs1 (nodes/traverse *connection* (:id john) :relationships [{:direction "all" :type "friend"}]) ids1 (vec (map :id xs1)) - xs2 (nodes/traverse (:id john) :relationships [{:direction "all" :type "enemy"}]) + xs2 (nodes/traverse *connection* (:id john) :relationships [{:direction "all" :type "enemy"}]) ids2 (map :id xs2)] (is (= [(:id john) (:id adam) (:id pete)] ids1)) (is (= [(:id john)] ids2)))) (deftest ^{:traversal true} test-traversing-relationships-using-all-return-filter-all-relationships-and-no-pagination - (let [john (nodes/create {:name "John"}) - adam (nodes/create {:name "Alan"}) - pete (nodes/create {:name "Peter"}) - rel1 (relationships/create john adam :friend) - rel2 (relationships/create john pete :friend) - rel3 (relationships/create adam pete :friend) - xs1 (relationships/traverse (:id john) :relationships [{:direction "all" :type "friend"}]) + (let [john (nodes/create *connection* {:name "John"}) + adam (nodes/create *connection* {:name "Alan"}) + pete (nodes/create *connection* {:name "Peter"}) + rel1 (relationships/create *connection* john adam :friend) + rel2 (relationships/create *connection* john pete :friend) + rel3 (relationships/create *connection* adam pete :friend) + xs1 (relationships/traverse *connection* (:id john) :relationships [{:direction "all" :type "friend"}]) ids1 (vec (map :id xs1)) - xs2 (relationships/traverse (:id john) :relationships [{:direction "all" :type "enemy"}]) + xs2 (relationships/traverse *connection* (:id john) :relationships [{:direction "all" :type "enemy"}]) ids2 (map :id xs2)] (is (= [(:id rel1) (:id rel2)] ids1)) (is (empty? ids2)))) (deftest ^{:traversal true} test-traversing-nodes-using-all-but-start-node-return-filter-out-relationships-and-no-pagination - (let [john (nodes/create {:name "John"}) - adam (nodes/create {:name "Alan"}) - pete (nodes/create {:name "Peter"}) - _ (relationships/create john adam :friend) - _ (relationships/create adam pete :friend) - xs1 (nodes/traverse (:id john) :relationships [{:direction "out" :type "friend"}] :return-filter {:language "builtin" :name "all_but_start_node"}) + (let [john (nodes/create *connection* {:name "John"}) + adam (nodes/create *connection* {:name "Alan"}) + pete (nodes/create *connection* {:name "Peter"}) + _ (relationships/create *connection* john adam :friend) + _ (relationships/create *connection* adam pete :friend) + xs1 (nodes/traverse *connection* (:id john) :relationships [{:direction "out" :type "friend"}] + :return-filter {:language "builtin" :name "all_but_start_node"}) ids1 (vec (map :id xs1)) - xs2 (nodes/traverse (:id adam) :relationships [{:direction "out" :type "friend"}] :return-filter {:language "builtin" :name "all_but_start_node"}) + xs2 (nodes/traverse *connection* (:id adam) :relationships [{:direction "out" :type "friend"}] + :return-filter {:language "builtin" :name "all_but_start_node"}) ids2 (vec (map :id xs2))] (is (= [(:id adam) (:id pete)] ids1)) (is (= [(:id pete)] ids2)))) (deftest ^{:traversal true} test-traversing-nodes-using-all-but-start-node-return-filter-in-relationships-and-no-pagination - (let [john (nodes/create {:name "John"}) - adam (nodes/create {:name "Alan"}) - pete (nodes/create {:name "Peter"}) - _ (relationships/create john adam :friend) - _ (relationships/create adam pete :friend) - xs (nodes/traverse (:id john) :relationships [{:direction "in" :type "friend"}] :return-filter {:language "builtin" :name "all_but_start_node"}) + (let [john (nodes/create *connection* {:name "John"}) + adam (nodes/create *connection* {:name "Alan"}) + pete (nodes/create *connection* {:name "Peter"}) + _ (relationships/create *connection* john adam :friend) + _ (relationships/create *connection* adam pete :friend) + xs (nodes/traverse *connection* (:id john) :relationships [{:direction "in" :type "friend"}] + :return-filter {:language "builtin" :name "all_but_start_node"}) ids (vec (map :id xs))] (is (empty? ids)))) (deftest ^{:traversal true} test-traversing-paths-using-all-return-filter-all-relationships-and-no-pagination - (let [john (nodes/create {:name "John"}) - adam (nodes/create {:name "Alan"}) - pete (nodes/create {:name "Peter"}) - rel1 (relationships/create john adam :friend) - rel2 (relationships/create adam pete :friend) - xs1 (paths/traverse (:id john) :relationships [{:direction "all" :type "friend"}]) - xs2 (paths/traverse (:id john) :relationships [{:direction "all" :type "enemy"}])] + (let [john (nodes/create *connection* {:name "John"}) + adam (nodes/create *connection* {:name "Alan"}) + pete (nodes/create *connection* {:name "Peter"}) + rel1 (relationships/create *connection* john adam :friend) + rel2 (relationships/create *connection* adam pete :friend) + xs1 (paths/traverse *connection* (:id john) :relationships [{:direction "all" :type "friend"}]) + xs2 (paths/traverse *connection* (:id john) :relationships [{:direction "all" :type "enemy"}])] (is (= 3 (count xs1))) (is (= 1 (count xs2))) (let [path1 (first xs1) @@ -113,33 +117,33 @@ ;; (deftest ^{:traversal true} test-shortest-path-algorithm-1 - (let [john (nodes/create {:name "John" :age 28 :location "New York City, NY"}) - liz (nodes/create {:name "Liz" :age 27 :location "Buffalo, NY"}) - beth (nodes/create {:name "Elizabeth" :age 30 :location "Chicago, IL"}) - bern (nodes/create {:name "Bernard" :age 33 :location "Zürich"}) - gael (nodes/create {:name "Gaël" :age 31 :location "Montpellier"}) - alex (nodes/create {:name "Alex" :age 24 :location "Toronto, ON"}) - rel1 (relationships/create john liz :knows) - rel2 (relationships/create liz beth :knows) - rel3 (relationships/create liz bern :knows) - rel4 (relationships/create bern gael :knows) - rel5 (relationships/create gael beth :knows) - rel6 (relationships/create beth gael :knows) - rel7 (relationships/create john gael :knows) + (let [john (nodes/create *connection* {:name "John" :age 28 :location "New York City, NY"}) + liz (nodes/create *connection* {:name "Liz" :age 27 :location "Buffalo, NY"}) + beth (nodes/create *connection* {:name "Elizabeth" :age 30 :location "Chicago, IL"}) + bern (nodes/create *connection* {:name "Bernard" :age 33 :location "Zürich"}) + gael (nodes/create *connection* {:name "Gaël" :age 31 :location "Montpellier"}) + alex (nodes/create *connection* {:name "Alex" :age 24 :location "Toronto, ON"}) + rel1 (relationships/create *connection* john liz :knows) + rel2 (relationships/create *connection* liz beth :knows) + rel3 (relationships/create *connection* liz bern :knows) + rel4 (relationships/create *connection* bern gael :knows) + rel5 (relationships/create *connection* gael beth :knows) + rel6 (relationships/create *connection* beth gael :knows) + rel7 (relationships/create *connection* john gael :knows) rt {:type "knows" :direction "out"} - xs1 (paths/all-shortest-between (:id john) (:id liz) :relationships [rt] :max-depth 1) + xs1 (paths/all-shortest-between *connection* (:id john) (:id liz) :relationships [rt] :max-depth 1) path1 (first xs1) - xs2 (paths/all-shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 1) - xs3 (paths/all-shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 2) + xs2 (paths/all-shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 1) + xs3 (paths/all-shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 2) path3 (first xs3) - xs4 (paths/all-shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 3) + xs4 (paths/all-shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 3) path4 (first xs4) - xs5 (paths/all-shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 7) + xs5 (paths/all-shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 7) path5 (first xs5) path6 (last xs5) - path7 (paths/shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 7) - path8 (paths/shortest-between (:id john) (:id beth) :relationships [rt] :max-depth 1) - path9 (paths/shortest-between (:id john) (:id alex) :relationships [rt] :max-depth 1)] + path7 (paths/shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 7) + path8 (paths/shortest-between *connection* (:id john) (:id beth) :relationships [rt] :max-depth 1) + path9 (paths/shortest-between *connection* (:id john) (:id alex) :relationships [rt] :max-depth 1)] (is (empty? xs2)) (is (nil? path8)) (is (= 1 (count xs1))) @@ -163,17 +167,17 @@ (is (= 2 (:length path7))) (is (= (:start path7) (:location-uri john))) (is (= (:end path7) (:location-uri beth))) - (is (paths/node-in? (:id john) path7)) - (is (not (paths/node-in? (:id bern) path7))) - (is (paths/node-in? john path7)) - (is (not (paths/node-in? bern path7))) - (is (paths/included-in? john path7)) - (is (paths/included-in? rel1 path7)) - (is (paths/relationship-in? (:id rel1) path7)) - (is (paths/relationship-in? rel1 path7)) - (is (not (paths/included-in? rel4 path7))) - (is (not (paths/relationship-in? (:id rel4) path7))) - (is (not (paths/relationship-in? rel4 path7))) - (is (paths/exists-between? (:id john) (:id liz) :relationships [rt] :max-depth 7)) - (is (not (paths/exists-between? (:id beth) (:id bern) :relationships [rt] :max-depth 7))) + (is (paths/node-in? *connection* (:id john) path7)) + (is (not (paths/node-in? *connection* (:id bern) path7))) + (is (paths/node-in? *connection* john path7)) + (is (not (paths/node-in? *connection* bern path7))) + (is (paths/included-in? *connection* john path7)) + (is (paths/included-in? *connection* rel1 path7)) + (is (paths/relationship-in? *connection* (:id rel1) path7)) + (is (paths/relationship-in? *connection* rel1 path7)) + (is (not (paths/included-in? *connection* rel4 path7))) + (is (not (paths/relationship-in? *connection* (:id rel4) path7))) + (is (not (paths/relationship-in? *connection* rel4 path7))) + (is (paths/exists-between? *connection* (:id john) (:id liz) :relationships [rt] :max-depth 7)) + (is (not (paths/exists-between? *connection* (:id beth) (:id bern) :relationships [rt] :max-depth 7))) (is (nil? path9))))