mysql_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package sql
  2. import (
  3. "context"
  4. "database/sql"
  5. "os"
  6. "testing"
  7. "time"
  8. "go-common/library/net/netutil/breaker"
  9. xtime "go-common/library/time"
  10. )
  11. func TestMySQL(t *testing.T) {
  12. bc := &breaker.Config{
  13. Window: xtime.Duration(10 * time.Second),
  14. Sleep: xtime.Duration(10 * time.Second),
  15. Bucket: 10,
  16. Ratio: 0.5,
  17. Request: 100,
  18. }
  19. dsn := os.Getenv("TEST_MYSQL_DSN")
  20. if dsn == "" {
  21. t.Skipf("TEST_MYSQL_DSN is empty, sql test skipped")
  22. }
  23. dsn = dsn + "?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8"
  24. c := &Config{
  25. Addr: "test",
  26. DSN: dsn,
  27. Active: 10,
  28. Idle: 5,
  29. IdleTimeout: xtime.Duration(time.Minute),
  30. QueryTimeout: xtime.Duration(time.Minute),
  31. ExecTimeout: xtime.Duration(time.Minute),
  32. TranTimeout: xtime.Duration(time.Minute),
  33. Breaker: bc,
  34. }
  35. db := NewMySQL(c)
  36. defer db.Close()
  37. testPing(t, db)
  38. testTable(t, db)
  39. testExec(t, db)
  40. testQuery(t, db)
  41. testQueryRow(t, db)
  42. testPrepare(t, db)
  43. testPrepared(t, db)
  44. testTransaction(t, db)
  45. testMaster(t, db)
  46. testMasterPanic(t, db)
  47. }
  48. func testMaster(t *testing.T, db *DB) {
  49. master := db.Master()
  50. if len(master.read) != 0 {
  51. t.Errorf("expect master read conn is 0, get %d", len(master.read))
  52. }
  53. if master.write != db.write {
  54. t.Errorf("expect master write conn equal to origin db write conn")
  55. }
  56. }
  57. func testMasterPanic(t *testing.T, db *DB) {
  58. defer func() {
  59. err := recover()
  60. if err == nil || err != ErrNoMaster {
  61. t.Errorf("expect panic err=ErrNoMaster get %v", err)
  62. }
  63. }()
  64. db.Master().Master()
  65. }
  66. func testTransaction(t *testing.T, db *DB) {
  67. var (
  68. tx *Tx
  69. err error
  70. execSQL = "INSERT INTO test(name) VALUES(?)"
  71. selSQL = "SELECT name FROM test WHERE name=?"
  72. txstmt *Stmt
  73. )
  74. if tx, err = db.Begin(context.TODO()); err != nil {
  75. t.Errorf("MySQL: db transaction Begin err(%v)", err)
  76. tx.Rollback()
  77. return
  78. }
  79. t.Log("MySQL: db transaction begin")
  80. if txstmt, err = tx.Prepare(execSQL); err != nil {
  81. t.Errorf("MySQL: tx.Prepare err(%v)", err)
  82. }
  83. if stmt := tx.Stmt(txstmt); stmt == nil {
  84. t.Errorf("MySQL:tx.Stmt err(%v)", err)
  85. }
  86. // exec
  87. if _, err = tx.Exec(execSQL, "tx1"); err != nil {
  88. t.Errorf("MySQL: tx.Exec err(%v)", err)
  89. tx.Rollback()
  90. return
  91. }
  92. t.Logf("MySQL:tx.Exec tx1")
  93. if _, err = tx.Exec(execSQL, "tx1"); err != nil {
  94. t.Errorf("MySQL: tx.Exec err(%v)", err)
  95. tx.Rollback()
  96. return
  97. }
  98. t.Logf("MySQL:tx.Exec tx1")
  99. // query
  100. rows, err := tx.Query(selSQL, "tx2")
  101. if err != nil {
  102. t.Errorf("MySQL:tx.Query err(%v)", err)
  103. tx.Rollback()
  104. return
  105. }
  106. rows.Close()
  107. t.Log("MySQL: tx.Query tx2")
  108. // queryrow
  109. var name string
  110. row := tx.QueryRow(selSQL, "noexist")
  111. if err = row.Scan(&name); err != sql.ErrNoRows {
  112. t.Errorf("MySQL: queryRow name: noexist")
  113. }
  114. if err = tx.Commit(); err != nil {
  115. t.Errorf("MySQL:tx.Commit err(%v)", err)
  116. }
  117. if err = tx.Commit(); err != nil {
  118. t.Logf("MySQL:tx.Commit err(%v)", err)
  119. }
  120. if err = tx.Rollback(); err != nil {
  121. t.Logf("MySQL:tx Rollback err(%v)", err)
  122. }
  123. }
  124. func testPing(t *testing.T, db *DB) {
  125. if err := db.Ping(context.TODO()); err != nil {
  126. t.Errorf("MySQL: ping error(%v)", err)
  127. t.FailNow()
  128. } else {
  129. t.Log("MySQL: ping ok")
  130. }
  131. }
  132. func testTable(t *testing.T, db *DB) {
  133. table := "CREATE TABLE IF NOT EXISTS `test` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID', `name` varchar(16) NOT NULL DEFAULT '' COMMENT '名称', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8"
  134. if _, err := db.Exec(context.TODO(), table); err != nil {
  135. t.Errorf("MySQL: create table error(%v)", err)
  136. } else {
  137. t.Log("MySQL: create table ok")
  138. }
  139. }
  140. func testExec(t *testing.T, db *DB) {
  141. sql := "INSERT INTO test(name) VALUES(?)"
  142. if _, err := db.Exec(context.TODO(), sql, "test"); err != nil {
  143. t.Errorf("MySQL: insert error(%v)", err)
  144. } else {
  145. t.Log("MySQL: insert ok")
  146. }
  147. }
  148. func testQuery(t *testing.T, db *DB) {
  149. sql := "SELECT name FROM test WHERE name=?"
  150. rows, err := db.Query(context.TODO(), sql, "test")
  151. if err != nil {
  152. t.Errorf("MySQL: query error(%v)", err)
  153. }
  154. defer rows.Close()
  155. for rows.Next() {
  156. name := ""
  157. if err := rows.Scan(&name); err != nil {
  158. t.Errorf("MySQL: query scan error(%v)", err)
  159. } else {
  160. t.Logf("MySQL: query name: %s", name)
  161. }
  162. }
  163. }
  164. func testQueryRow(t *testing.T, db *DB) {
  165. sql := "SELECT name FROM test WHERE name=?"
  166. name := ""
  167. row := db.QueryRow(context.TODO(), sql, "test")
  168. if err := row.Scan(&name); err != nil {
  169. t.Errorf("MySQL: queryRow error(%v)", err)
  170. } else {
  171. t.Logf("MySQL: queryRow name: %s", name)
  172. }
  173. }
  174. func testPrepared(t *testing.T, db *DB) {
  175. sql := "SELECT name FROM test WHERE name=?"
  176. name := ""
  177. stmt := db.Prepared(sql)
  178. row := stmt.QueryRow(context.TODO(), "test")
  179. if err := row.Scan(&name); err != nil {
  180. t.Errorf("MySQL: prepared query error(%v)", err)
  181. } else {
  182. t.Logf("MySQL: prepared query name: %s", name)
  183. }
  184. if err := stmt.Close(); err != nil {
  185. t.Errorf("MySQL:stmt.Close err(%v)", err)
  186. }
  187. }
  188. func testPrepare(t *testing.T, db *DB) {
  189. var (
  190. selsql = "SELECT name FROM test WHERE name=?"
  191. execsql = "INSERT INTO test(name) VALUES(?)"
  192. name = ""
  193. )
  194. selstmt, err := db.Prepare(selsql)
  195. if err != nil {
  196. t.Errorf("MySQL:Prepare err(%v)", err)
  197. return
  198. }
  199. row := selstmt.QueryRow(context.TODO(), "noexit")
  200. if err = row.Scan(&name); err == sql.ErrNoRows {
  201. t.Logf("MySQL: prepare query error(%v)", err)
  202. } else {
  203. t.Errorf("MySQL: prepared query name: noexist")
  204. }
  205. rows, err := selstmt.Query(context.TODO(), "test")
  206. if err != nil {
  207. t.Errorf("MySQL:stmt.Query err(%v)", err)
  208. }
  209. rows.Close()
  210. execstmt, err := db.Prepare(execsql)
  211. if err != nil {
  212. t.Errorf("MySQL:Prepare err(%v)", err)
  213. return
  214. }
  215. if _, err := execstmt.Exec(context.TODO(), "test"); err != nil {
  216. t.Errorf("MySQL: stmt.Exec(%v)", err)
  217. }
  218. }
  219. func BenchmarkMySQL(b *testing.B) {
  220. c := &Config{
  221. Addr: "test",
  222. DSN: "test:test@tcp(172.16.0.148:3306)/test?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8",
  223. Active: 10,
  224. Idle: 5,
  225. IdleTimeout: xtime.Duration(time.Minute),
  226. }
  227. db := NewMySQL(c)
  228. defer db.Close()
  229. b.RunParallel(func(pb *testing.PB) {
  230. for pb.Next() {
  231. sql := "SELECT name FROM test WHERE name=?"
  232. rows, err := db.Query(context.TODO(), sql, "test")
  233. if err == nil {
  234. for rows.Next() {
  235. var name string
  236. if err = rows.Scan(&name); err != nil {
  237. break
  238. }
  239. }
  240. rows.Close()
  241. }
  242. }
  243. })
  244. }