-
-
Notifications
You must be signed in to change notification settings - Fork 89
/
connection_test.clj
204 lines (191 loc) · 10.2 KB
/
connection_test.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
;; copyright (c) 2019-2021 Sean Corfield, all rights reserved
(ns next.jdbc.connection-test
"Tests for the main hash map spec to JDBC URL logic and the get-datasource
and get-connection protocol implementations.
At some point, the datasource/connection tests should probably be extended
to accept EDN specs from an external source (environment variables?)."
(:require [clojure.string :as str]
[clojure.test :refer [deftest is testing]]
[next.jdbc.connection :as c]
[next.jdbc.protocols :as p])
(:import (com.zaxxer.hikari HikariDataSource)
(com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)))
(set! *warn-on-reflection* true)
(def ^:private db-name "clojure_test")
(deftest test-aliases-and-defaults
(testing "aliases"
(is (= (#'c/spec->url+etc {:dbtype "hsql" :dbname db-name})
(#'c/spec->url+etc {:dbtype "hsqldb" :dbname db-name})))
(is (= (#'c/spec->url+etc {:dbtype "jtds" :dbname db-name})
(#'c/spec->url+etc {:dbtype "jtds:sqlserver" :dbname db-name})))
(is (= (#'c/spec->url+etc {:dbtype "mssql" :dbname db-name})
(#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name})))
(is (= (#'c/spec->url+etc {:dbtype "oracle" :dbname db-name})
(#'c/spec->url+etc {:dbtype "oracle:thin" :dbname db-name})))
(is (= (#'c/spec->url+etc {:dbtype "oracle:sid" :dbname db-name})
(-> (#'c/spec->url+etc {:dbtype "oracle:thin" :dbname db-name})
;; oracle:sid uses : before DB name, not /
(update 0 str/replace (re-pattern (str "/" db-name)) (str ":" db-name)))))
(is (= (#'c/spec->url+etc {:dbtype "oracle:oci" :dbname db-name})
(-> (#'c/spec->url+etc {:dbtype "oracle:thin" :dbname db-name})
;; oracle:oci and oracle:thin only differ in the protocol
(update 0 str/replace #":thin" ":oci"))))
(is (= (#'c/spec->url+etc {:dbtype "postgres" :dbname db-name})
(#'c/spec->url+etc {:dbtype "postgresql" :dbname db-name}))))
(testing "default ports"
(is (= (#'c/spec->url+etc {:dbtype "jtds:sqlserver" :dbname db-name})
(#'c/spec->url+etc {:dbtype "jtds:sqlserver" :dbname db-name :port 1433})))
(is (= (#'c/spec->url+etc {:dbtype "mysql" :dbname db-name})
(#'c/spec->url+etc {:dbtype "mysql" :dbname db-name :port 3306})))
(is (= (#'c/spec->url+etc {:dbtype "oracle:oci" :dbname db-name})
(#'c/spec->url+etc {:dbtype "oracle:oci" :dbname db-name :port 1521})))
(is (= (#'c/spec->url+etc {:dbtype "oracle:sid" :dbname db-name})
(#'c/spec->url+etc {:dbtype "oracle:sid" :dbname db-name :port 1521})))
(is (= (#'c/spec->url+etc {:dbtype "oracle:thin" :dbname db-name})
(#'c/spec->url+etc {:dbtype "oracle:thin" :dbname db-name :port 1521})))
(is (= (#'c/spec->url+etc {:dbtype "postgresql" :dbname db-name})
(#'c/spec->url+etc {:dbtype "postgresql" :dbname db-name :port 5432})))
(is (= (#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name})
(#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name :port 1433})))))
(deftest custom-dbtypes
(is (= ["jdbc:acme:my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none})))
(is (= ["jdbc:acme://127.0.0.1/my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db"})))
(is (= ["jdbc:acme://12.34.56.70:1234/my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host "12.34.56.70" :port 1234})))
(is (= ["jdbc:acme:dsn=my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none
:dbname-separator ":dsn="})))
(is (= ["jdbc:acme:(*)127.0.0.1/my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db"
:host-prefix "(*)"})))
(is (= ["jdbc:acme:(*)12.34.56.70:1234/my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host "12.34.56.70" :port 1234
:host-prefix "(*)"})))
(is (= ["jdbc:acme:(*)12.34.56.70/my-db" {} nil]
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host "12.34.56.70" :port :none
:host-prefix "(*)"}))))
(deftest jdbc-url-tests
(testing "basic URLs work"
(is (= "jdbc:acme:my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none})))
(is (= "jdbc:acme://127.0.0.1/my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db"})))
(is (= "jdbc:acme://12.34.56.70:1234/my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host "12.34.56.70" :port 1234})))
(is (= "jdbc:acme:dsn=my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none
:dbname-separator ":dsn="})))
(is (= "jdbc:acme:(*)127.0.0.1/my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db"
:host-prefix "(*)"})))
(is (= "jdbc:acme:(*)12.34.56.70:1234/my-db"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host "12.34.56.70" :port 1234
:host-prefix "(*)"}))))
(testing "URLs with properties work"
(is (= "jdbc:acme:my-db?useSSL=true"
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none
:useSSL true})))
(is (boolean (#{"jdbc:acme:my-db?useSSL=true&user=dba"
"jdbc:acme:my-db?user=dba&useSSL=true"}
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
:dbname "my-db" :host :none
:useSSL true :user "dba"}))))
(is (= "jdbc:jtds:sqlserver:my-db;useSSL=true"
(c/jdbc-url {:dbtype "jtds"
:dbname "my-db" :host :none
:useSSL true})))
(is (boolean (#{"jdbc:jtds:sqlserver:my-db;useSSL=true;user=dba"
"jdbc:jtds:sqlserver:my-db;user=dba;useSSL=true"}
(c/jdbc-url {:dbtype "jtds"
:dbname "my-db" :host :none
:useSSL true :user "dba"}))))))
;; these are the 'local' databases that we can always test against
(def test-db-type ["derby" "h2" "h2:mem" "hsqldb" "sqlite"])
(def test-dbs
(for [db test-db-type]
(cond-> {:dbtype db :dbname (str db-name "_" (str/replace db #":" "_"))}
(= "derby" db)
(assoc :create true))))
(deftest test-sourceable-via-metadata
(doseq [db test-dbs]
(let [ds (p/get-datasource
^{`p/get-datasource (fn [v] (p/get-datasource (first v)))} [db])]
(is (instance? javax.sql.DataSource ds)))))
(deftest test-get-connection
(doseq [db test-dbs]
(println 'test-get-connection (:dbtype db))
(testing "datasource via Associative"
(let [ds (p/get-datasource db)]
(is (instance? javax.sql.DataSource ds))
(is (str/index-of (pr-str ds) (str "jdbc:" (:dbtype db))))
;; checks get-datasource on a DataSource is identity
(is (identical? ds (p/get-datasource ds)))
(with-open [con (p/get-connection ds {})]
(is (instance? java.sql.Connection con)))))
(testing "datasource via String"
(let [[url _] (#'c/spec->url+etc db)
ds (p/get-datasource url)]
(is (instance? javax.sql.DataSource ds))
(is (str/index-of (pr-str ds) url))
(.setLoginTimeout ds 0)
(is (= 0 (.getLoginTimeout ds)))
(with-open [con (p/get-connection ds {})]
(is (instance? java.sql.Connection con)))))
(testing "datasource via jdbcUrl"
(let [[url etc] (#'c/spec->url+etc db)
ds (p/get-datasource (assoc etc :jdbcUrl url))]
(if (= "derby" (:dbtype db))
(is (= {:create true} etc))
(is (= {} etc)))
(is (instance? javax.sql.DataSource ds))
(is (str/index-of (pr-str ds) (str "jdbc:" (:dbtype db))))
;; checks get-datasource on a DataSource is identity
(is (identical? ds (p/get-datasource ds)))
(.setLoginTimeout ds 1)
(is (= 1 (.getLoginTimeout ds)))
(with-open [con (p/get-connection ds {})]
(is (instance? java.sql.Connection con)))))
(testing "datasource via HikariCP"
;; the type hint is only needed because we want to call .close
(with-open [^HikariDataSource ds (c/->pool HikariDataSource db)]
(is (instance? javax.sql.DataSource ds))
;; checks get-datasource on a DataSource is identity
(is (identical? ds (p/get-datasource ds)))
(with-open [con (p/get-connection ds {})]
(is (instance? java.sql.Connection con)))))
(testing "datasource via c3p0"
;; the type hint is only needed because we want to call .close
(with-open [^PooledDataSource ds (c/->pool ComboPooledDataSource db)]
(is (instance? javax.sql.DataSource ds))
;; checks get-datasource on a DataSource is identity
(is (identical? ds (p/get-datasource ds)))
(with-open [con (p/get-connection ds {})]
(is (instance? java.sql.Connection con)))))
(testing "connection via map (Object)"
(with-open [con (p/get-connection db {})]
(is (instance? java.sql.Connection con))))))
(deftest issue-243-uri->db-spec
(is (= {:dbtype "mysql" :dbname "mydb"
:host "myserver" :port 1234
:user "foo" :password "bar"}
(c/uri->db-spec "mysql://foo:bar@myserver:1234/mydb")))
(is (= {:dbtype "mysql" :dbname "mydb"
:host "myserver" :port 1234
:user "foo" :password "bar"}
(c/uri->db-spec "jdbc:mysql://myserver:1234/mydb?user=foo&password=bar"))))