/connection/connection_test.go

https://github.com/knocknote/octillery · Go · 486 lines · 437 code · 49 blank · 0 comment · 103 complexity · b52ceef38a0750fa12c44f0ba43ed6aa MD5 · raw file

  1. package connection
  2. import (
  3. "context"
  4. "database/sql"
  5. "database/sql/driver"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. "go.knocknote.io/octillery/config"
  10. "go.knocknote.io/octillery/connection/adapter"
  11. "go.knocknote.io/octillery/path"
  12. )
  13. type TestAdapter struct {
  14. }
  15. func (t *TestAdapter) CurrentSequenceID(conn *sql.DB, tableName string) (int64, error) {
  16. return 1, nil
  17. }
  18. func (t *TestAdapter) NextSequenceID(conn *sql.DB, tableName string) (int64, error) {
  19. return 2, nil
  20. }
  21. func (t *TestAdapter) ExecDDL(config *config.DatabaseConfig) error {
  22. return nil
  23. }
  24. func (t *TestAdapter) OpenConnection(config *config.DatabaseConfig, queryValues string) (*sql.DB, error) {
  25. return sql.Open("sqlite3", "")
  26. }
  27. func (t *TestAdapter) CreateSequencerTableIfNotExists(conn *sql.DB, tableName string) error {
  28. return nil
  29. }
  30. func (t *TestAdapter) InsertRowToSequencerIfNotExists(conn *sql.DB, tableName string) error {
  31. return nil
  32. }
  33. type TestDriver struct {
  34. }
  35. func (t *TestDriver) Open(name string) (driver.Conn, error) {
  36. return &TestConn{}, nil
  37. }
  38. type TestConn struct {
  39. }
  40. func (t *TestConn) Prepare(query string) (driver.Stmt, error) {
  41. return &TestStmt{}, nil
  42. }
  43. func (t *TestConn) Begin() (driver.Tx, error) {
  44. return &TestTx{}, nil
  45. }
  46. func (t *TestConn) Close() error {
  47. return nil
  48. }
  49. func (t *TestConn) Query(query string, args []driver.Value) (driver.Rows, error) {
  50. return &TestRows{}, nil
  51. }
  52. type TestStmt struct {
  53. }
  54. func (t *TestStmt) Close() error {
  55. return nil
  56. }
  57. func (t *TestStmt) NumInput() int {
  58. return 0
  59. }
  60. func (t *TestStmt) Exec(args []driver.Value) (driver.Result, error) {
  61. return &TestResult{}, nil
  62. }
  63. func (t *TestStmt) Query(args []driver.Value) (driver.Rows, error) {
  64. return &TestRows{}, nil
  65. }
  66. type TestResult struct {
  67. }
  68. func (t *TestResult) LastInsertId() (int64, error) {
  69. return 0, nil
  70. }
  71. func (t *TestResult) RowsAffected() (int64, error) {
  72. return 0, nil
  73. }
  74. type TestRows struct {
  75. }
  76. func (t *TestRows) Columns() []string {
  77. return []string{}
  78. }
  79. func (t *TestRows) Close() error {
  80. return nil
  81. }
  82. func (t *TestRows) Next(dest []driver.Value) error {
  83. return nil
  84. }
  85. type TestTx struct {
  86. }
  87. func (t *TestTx) Commit() error {
  88. return nil
  89. }
  90. func (t *TestTx) Rollback() error {
  91. return nil
  92. }
  93. func checkErr(t *testing.T, err error) {
  94. if err != nil {
  95. t.Fatalf("%+v\n", err)
  96. }
  97. }
  98. func init() {
  99. adapter.Register("sqlite3", &TestAdapter{})
  100. sql.Register("sqlite3", &TestDriver{})
  101. confPath := filepath.Join(path.ThisDirPath(), "..", "test_databases.yml")
  102. cfg, err := config.Load(confPath)
  103. if err != nil {
  104. panic(err)
  105. }
  106. if err := SetConfig(cfg); err != nil {
  107. panic(err)
  108. }
  109. }
  110. func TestSetQueryString(t *testing.T) {
  111. mgr, err := NewConnectionManager()
  112. checkErr(t, err)
  113. defer mgr.Close()
  114. if err := mgr.SetQueryString("?#%"); err == nil {
  115. t.Fatal("cannot handle error")
  116. }
  117. checkErr(t, mgr.SetQueryString(""))
  118. checkErr(t, mgr.SetQueryString("?parseTime=true&loc=Asia%2FTokyo"))
  119. }
  120. func TestGetConnection(t *testing.T) {
  121. mgr, err := NewConnectionManager()
  122. checkErr(t, err)
  123. defer mgr.Close()
  124. t.Run("connection by users table", func(t *testing.T) {
  125. conn, err := mgr.ConnectionByTableName("users")
  126. checkErr(t, err)
  127. if c, _ := mgr.ConnectionByTableName("users"); c != conn {
  128. t.Fatal("cannot fetch same instance")
  129. }
  130. if conn.ShardConnections.ShardNum() != 2 {
  131. t.Fatal("cannot get shard num")
  132. }
  133. if len(conn.ShardConnections.AllShard()) != 2 {
  134. t.Fatal("cannot get all shard")
  135. }
  136. shardConn := conn.ShardConnections.ShardConnectionByName("user_shard_1")
  137. if shardConn == nil {
  138. t.Fatal("cannot get shard connection by name")
  139. }
  140. shardConnByIndex := conn.ShardConnections.ShardConnectionByIndex(0)
  141. if shardConnByIndex == nil {
  142. t.Fatal("cannot get shard connection by index")
  143. }
  144. if _, err := mgr.SequencerConnectionByTableName("users"); err != nil {
  145. t.Fatalf("%+v\n", err)
  146. }
  147. })
  148. t.Run("connection by user_stages table", func(t *testing.T) {
  149. if _, err := mgr.ConnectionByTableName("user_stages"); err != nil {
  150. t.Fatalf("%+v\n", err)
  151. }
  152. })
  153. }
  154. func TestSetSettings(t *testing.T) {
  155. mgr, err := NewConnectionManager()
  156. checkErr(t, err)
  157. defer mgr.Close()
  158. mgr.SetMaxIdleConns(10)
  159. mgr.SetMaxOpenConns(10)
  160. mgr.SetConnMaxLifetime(10 * time.Second)
  161. }
  162. func TestCurrentSequenceID(t *testing.T) {
  163. mgr, err := NewConnectionManager()
  164. checkErr(t, err)
  165. defer mgr.Close()
  166. id, err := mgr.CurrentSequenceID("users")
  167. checkErr(t, err)
  168. if id != 1 {
  169. t.Fatal("cannot get current sequence id")
  170. }
  171. }
  172. func TestNextSequenceID(t *testing.T) {
  173. mgr, err := NewConnectionManager()
  174. checkErr(t, err)
  175. defer mgr.Close()
  176. id, err := mgr.NextSequenceID("users")
  177. checkErr(t, err)
  178. if id != 2 {
  179. t.Fatal("cannot get next sequence id")
  180. }
  181. {
  182. conn, err := mgr.ConnectionByTableName("users")
  183. checkErr(t, err)
  184. id, err := conn.NextSequenceID("users")
  185. checkErr(t, err)
  186. if id != 2 {
  187. t.Fatal("cannot get next sequence id")
  188. }
  189. }
  190. }
  191. func TestIsShardTable(t *testing.T) {
  192. mgr, err := NewConnectionManager()
  193. checkErr(t, err)
  194. defer mgr.Close()
  195. if !mgr.IsShardTable("users") {
  196. t.Fatal("cannot set is_shard configuration")
  197. }
  198. if mgr.IsShardTable("user_stages") {
  199. t.Fatal("cannot set is_shard configuration")
  200. }
  201. }
  202. func TestEqualDSN(t *testing.T) {
  203. mgr, err := NewConnectionManager()
  204. checkErr(t, err)
  205. defer mgr.Close()
  206. conn, err := mgr.ConnectionByTableName("users")
  207. checkErr(t, err)
  208. t.Run("same instance", func(t *testing.T) {
  209. if !conn.EqualDSN(conn) {
  210. t.Fatal("cannot work equal dsn")
  211. }
  212. })
  213. t.Run("another instance", func(t *testing.T) {
  214. mgr, err := NewConnectionManager()
  215. checkErr(t, err)
  216. defer mgr.Close()
  217. anotherConn, err := mgr.ConnectionByTableName("users")
  218. checkErr(t, err)
  219. if !conn.EqualDSN(anotherConn) {
  220. t.Fatal("cannot work equal dsn")
  221. }
  222. })
  223. }
  224. func TestIsEqualShardColumnToShardKeyColumn(t *testing.T) {
  225. mgr, err := NewConnectionManager()
  226. checkErr(t, err)
  227. defer mgr.Close()
  228. if !mgr.IsEqualShardColumnToShardKeyColumn("users") {
  229. t.Fatal("cannot set shard_column and shard_key")
  230. }
  231. if mgr.IsEqualShardColumnToShardKeyColumn("user_items") {
  232. t.Fatal("cannot set shard_column and shard_key")
  233. }
  234. if mgr.IsEqualShardColumnToShardKeyColumn("user_decks") {
  235. t.Fatal("cannot set shard_column and shard_key")
  236. }
  237. if !mgr.IsEqualShardColumnToShardKeyColumn("user_stages") {
  238. t.Fatal("cannot set shard_column and shard_key")
  239. }
  240. conn, err := mgr.ConnectionByTableName("users")
  241. checkErr(t, err)
  242. if !conn.IsEqualShardColumnToShardKeyColumn() {
  243. t.Fatal("cannot set shard_column and shard_key")
  244. }
  245. }
  246. func TestShardConnectionByID(t *testing.T) {
  247. mgr, err := NewConnectionManager()
  248. checkErr(t, err)
  249. defer mgr.Close()
  250. conn, err := mgr.ConnectionByTableName("users")
  251. checkErr(t, err)
  252. {
  253. shardConn, err := conn.ShardConnectionByID(1)
  254. checkErr(t, err)
  255. if shardConn.ShardName != "user_shard_2" {
  256. t.Fatal("invalid shard connection by id")
  257. }
  258. }
  259. {
  260. shardConn, err := conn.ShardConnectionByID(2)
  261. checkErr(t, err)
  262. if shardConn.ShardName != "user_shard_1" {
  263. t.Fatal("invalid shard connection by id")
  264. }
  265. }
  266. }
  267. func TestShardColumnName(t *testing.T) {
  268. mgr, err := NewConnectionManager()
  269. checkErr(t, err)
  270. defer mgr.Close()
  271. if mgr.ShardColumnName("users") != "id" {
  272. t.Fatal("cannot get shard_column name")
  273. }
  274. if mgr.ShardColumnName("user_items") != "" {
  275. t.Fatal("cannot get shard_column name")
  276. }
  277. if mgr.ShardColumnName("user_decks") != "id" {
  278. t.Fatal("cannot get shard_column name")
  279. }
  280. if mgr.ShardColumnName("user_stages") != "" {
  281. t.Fatal("cannot get shard_column name")
  282. }
  283. }
  284. func TestShardKeyColumnName(t *testing.T) {
  285. mgr, err := NewConnectionManager()
  286. checkErr(t, err)
  287. defer mgr.Close()
  288. if mgr.ShardKeyColumnName("users") != "id" {
  289. t.Fatal("cannot get shard_key name")
  290. }
  291. if mgr.ShardKeyColumnName("user_items") != "user_id" {
  292. t.Fatal("cannot get shard_key name")
  293. }
  294. if mgr.ShardKeyColumnName("user_decks") != "user_id" {
  295. t.Fatal("cannot get shard_key name")
  296. }
  297. if mgr.ShardKeyColumnName("user_stages") != "" {
  298. t.Fatal("cannot get shard_key name")
  299. }
  300. }
  301. func TestQuery(t *testing.T) {
  302. mgr, err := NewConnectionManager()
  303. checkErr(t, err)
  304. defer mgr.Close()
  305. ctx, cancel := context.WithCancel(context.Background())
  306. defer cancel()
  307. t.Run("not sharding table", func(t *testing.T) {
  308. conn, err := mgr.ConnectionByTableName("user_stages")
  309. checkErr(t, err)
  310. t.Run("without context", func(t *testing.T) {
  311. rows, err := conn.Query(nil, "select * from user_stages")
  312. checkErr(t, err)
  313. if columns, _ := rows.Columns(); len(columns) != 0 {
  314. t.Fatal("unknown rows")
  315. }
  316. })
  317. t.Run("with context", func(t *testing.T) {
  318. rows, err := conn.Query(ctx, "select * from user_stages")
  319. checkErr(t, err)
  320. if columns, _ := rows.Columns(); len(columns) != 0 {
  321. t.Fatal("unknown rows")
  322. }
  323. })
  324. })
  325. }
  326. func TestQueryRow(t *testing.T) {
  327. mgr, err := NewConnectionManager()
  328. checkErr(t, err)
  329. defer mgr.Close()
  330. ctx, cancel := context.WithCancel(context.Background())
  331. defer cancel()
  332. t.Run("not sharding table", func(t *testing.T) {
  333. conn, err := mgr.ConnectionByTableName("user_stages")
  334. checkErr(t, err)
  335. t.Run("without context", func(t *testing.T) {
  336. conn.QueryRow(nil, "select * from user_stages where user_id = 1")
  337. })
  338. t.Run("with context", func(t *testing.T) {
  339. conn.QueryRow(ctx, "select * from user_stages where user_id = 1")
  340. })
  341. })
  342. }
  343. func TestPrepare(t *testing.T) {
  344. mgr, err := NewConnectionManager()
  345. checkErr(t, err)
  346. defer mgr.Close()
  347. ctx, cancel := context.WithCancel(context.Background())
  348. defer cancel()
  349. t.Run("not sharding table", func(t *testing.T) {
  350. conn, err := mgr.ConnectionByTableName("user_stages")
  351. checkErr(t, err)
  352. t.Run("without context", func(t *testing.T) {
  353. stmt, err := conn.Prepare(nil, "select * from user_stages where user_id = ?")
  354. checkErr(t, err)
  355. checkErr(t, stmt.Close())
  356. })
  357. t.Run("with context", func(t *testing.T) {
  358. stmt, err := conn.Prepare(ctx, "select * from user_stages where user_id = ?")
  359. checkErr(t, err)
  360. checkErr(t, stmt.Close())
  361. })
  362. })
  363. }
  364. func TestExec(t *testing.T) {
  365. mgr, err := NewConnectionManager()
  366. checkErr(t, err)
  367. defer mgr.Close()
  368. ctx, cancel := context.WithCancel(context.Background())
  369. defer cancel()
  370. t.Run("not sharding table", func(t *testing.T) {
  371. conn, err := mgr.ConnectionByTableName("user_stages")
  372. checkErr(t, err)
  373. t.Run("without context", func(t *testing.T) {
  374. result, err := conn.Exec(nil, "update user_stages set name = 'alice' where user_id = ?")
  375. checkErr(t, err)
  376. affected, err := result.RowsAffected()
  377. checkErr(t, err)
  378. if affected != 0 {
  379. t.Fatal("cannot get rows affected")
  380. }
  381. })
  382. t.Run("with context", func(t *testing.T) {
  383. result, err := conn.Exec(ctx, "update user_stages set name = 'alice' where user_id = ?")
  384. checkErr(t, err)
  385. affected, err := result.RowsAffected()
  386. checkErr(t, err)
  387. if affected != 0 {
  388. t.Fatal("cannot get rows affected")
  389. }
  390. })
  391. })
  392. }
  393. func TestTransaction(t *testing.T) {
  394. mgr, err := NewConnectionManager()
  395. checkErr(t, err)
  396. defer mgr.Close()
  397. conn, err := mgr.ConnectionByTableName("user_stages")
  398. checkErr(t, err)
  399. ctx, cancel := context.WithCancel(context.Background())
  400. defer cancel()
  401. t.Run("without context", func(t *testing.T) {
  402. tx := conn.Begin(nil, nil)
  403. stmt, err := tx.Prepare(nil, conn, "select * from user_stages where id = ?")
  404. checkErr(t, err)
  405. if _, err := tx.Stmt(nil, conn, stmt); err != nil {
  406. t.Fatalf("%+v\n", err)
  407. }
  408. if _, err := tx.QueryRow(nil, conn, "select * from user_stages where id = 1"); err != nil {
  409. t.Fatalf("%+v\n", err)
  410. }
  411. if _, err := tx.Query(nil, conn, "select * from user_stages"); err != nil {
  412. t.Fatalf("%+v\n", err)
  413. }
  414. if _, err := tx.Exec(nil, conn, "delete from user_stages where id = 1"); err != nil {
  415. t.Fatalf("%+v\n", err)
  416. }
  417. checkErr(t, tx.Commit())
  418. })
  419. t.Run("with context", func(t *testing.T) {
  420. tx := conn.Begin(ctx, nil)
  421. stmt, err := tx.Prepare(ctx, conn, "select * from user_stages where id = ?")
  422. checkErr(t, err)
  423. if _, err := tx.Stmt(ctx, conn, stmt); err != nil {
  424. t.Fatalf("%+v\n", err)
  425. }
  426. if _, err := tx.QueryRow(ctx, conn, "select * from user_stages where id = 1"); err != nil {
  427. t.Fatalf("%+v\n", err)
  428. }
  429. if _, err := tx.Query(ctx, conn, "select * from user_stages"); err != nil {
  430. t.Fatalf("%+v\n", err)
  431. }
  432. if _, err := tx.Exec(ctx, conn, "delete from user_stages where id = 1"); err != nil {
  433. t.Fatalf("%+v\n", err)
  434. }
  435. checkErr(t, tx.Rollback())
  436. })
  437. }