github.com/netdata/go.d.plugin@v0.58.1/modules/mysql/mysql_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package mysql 4 5 import ( 6 "bufio" 7 "bytes" 8 "database/sql/driver" 9 "errors" 10 "fmt" 11 "os" 12 "strings" 13 "testing" 14 15 "github.com/netdata/go.d.plugin/agent/module" 16 17 "github.com/DATA-DOG/go-sqlmock" 18 "github.com/blang/semver/v4" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 ) 22 23 var ( 24 dataMySQLV8030Version, _ = os.ReadFile("testdata/mysql/v8.0.30/version.txt") 25 dataMySQLV8030GlobalStatus, _ = os.ReadFile("testdata/mysql/v8.0.30/global_status.txt") 26 dataMySQLV8030GlobalVariables, _ = os.ReadFile("testdata/mysql/v8.0.30/global_variables.txt") 27 dataMySQLV8030ReplicaStatusMultiSource, _ = os.ReadFile("testdata/mysql/v8.0.30/replica_status_multi_source.txt") 28 dataMySQLV8030ProcessList, _ = os.ReadFile("testdata/mysql/v8.0.30/process_list.txt") 29 30 dataPerconaV8029Version, _ = os.ReadFile("testdata/percona/v8.0.29/version.txt") 31 dataPerconaV8029GlobalStatus, _ = os.ReadFile("testdata/percona/v8.0.29/global_status.txt") 32 dataPerconaV8029GlobalVariables, _ = os.ReadFile("testdata/percona/v8.0.29/global_variables.txt") 33 dataPerconaV8029UserStatistics, _ = os.ReadFile("testdata/percona/v8.0.29/user_statistics.txt") 34 dataPerconaV8029ProcessList, _ = os.ReadFile("testdata/percona/v8.0.29/process_list.txt") 35 36 dataMariaV5564Version, _ = os.ReadFile("testdata/mariadb/v5.5.64/version.txt") 37 dataMariaV5564GlobalStatus, _ = os.ReadFile("testdata/mariadb/v5.5.64/global_status.txt") 38 dataMariaV5564GlobalVariables, _ = os.ReadFile("testdata/mariadb/v5.5.64/global_variables.txt") 39 dataMariaV5564ProcessList, _ = os.ReadFile("testdata/mariadb/v5.5.64/process_list.txt") 40 41 dataMariaV1084Version, _ = os.ReadFile("testdata/mariadb/v10.8.4/version.txt") 42 dataMariaV1084GlobalStatus, _ = os.ReadFile("testdata/mariadb/v10.8.4/global_status.txt") 43 dataMariaV1084GlobalVariables, _ = os.ReadFile("testdata/mariadb/v10.8.4/global_variables.txt") 44 dataMariaV1084AllSlavesStatusSingleSource, _ = os.ReadFile("testdata/mariadb/v10.8.4/all_slaves_status_single_source.txt") 45 dataMariaV1084AllSlavesStatusMultiSource, _ = os.ReadFile("testdata/mariadb/v10.8.4/all_slaves_status_multi_source.txt") 46 dataMariaV1084UserStatistics, _ = os.ReadFile("testdata/mariadb/v10.8.4/user_statistics.txt") 47 dataMariaV1084ProcessList, _ = os.ReadFile("testdata/mariadb/v10.8.4/process_list.txt") 48 49 dataMariaGaleraClusterV1084Version, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/version.txt") 50 dataMariaGaleraClusterV1084GlobalStatus, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/global_status.txt") 51 dataMariaGaleraClusterV1084GlobalVariables, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/global_variables.txt") 52 dataMariaGaleraClusterV1084UserStatistics, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/user_statistics.txt") 53 dataMariaGaleraClusterV1084ProcessList, _ = os.ReadFile("testdata/mariadb/v10.8.4-galera-cluster/process_list.txt") 54 ) 55 56 func Test_testDataIsValid(t *testing.T) { 57 for name, data := range map[string][]byte{ 58 "dataMySQLV8030Version": dataMySQLV8030Version, 59 "dataMySQLV8030GlobalStatus": dataMySQLV8030GlobalStatus, 60 "dataMySQLV8030GlobalVariables": dataMySQLV8030GlobalVariables, 61 "dataMySQLV8030ReplicaStatusMultiSource": dataMySQLV8030ReplicaStatusMultiSource, 62 "dataMySQLV8030ProcessList": dataMySQLV8030ProcessList, 63 64 "dataPerconaV8029Version": dataPerconaV8029Version, 65 "dataPerconaV8029GlobalStatus": dataPerconaV8029GlobalStatus, 66 "dataPerconaV8029GlobalVariables": dataPerconaV8029GlobalVariables, 67 "dataPerconaV8029UserStatistics": dataPerconaV8029UserStatistics, 68 "dataPerconaV8029ProcessList": dataPerconaV8029ProcessList, 69 70 "dataMariaV5564Version": dataMariaV5564Version, 71 "dataMariaV5564GlobalStatus": dataMariaV5564GlobalStatus, 72 "dataMariaV5564GlobalVariables": dataMariaV5564GlobalVariables, 73 "dataMariaV5564ProcessList": dataMariaV5564ProcessList, 74 75 "dataMariaV1084Version": dataMariaV1084Version, 76 "dataMariaV1084GlobalStatus": dataMariaV1084GlobalStatus, 77 "dataMariaV1084GlobalVariables": dataMariaV1084GlobalVariables, 78 "dataMariaV1084AllSlavesStatusSingleSource": dataMariaV1084AllSlavesStatusSingleSource, 79 "dataMariaV1084AllSlavesStatusMultiSource": dataMariaV1084AllSlavesStatusMultiSource, 80 "dataMariaV1084UserStatistics": dataMariaV1084UserStatistics, 81 "dataMariaV1084ProcessList": dataMariaV1084ProcessList, 82 83 "dataMariaGaleraClusterV1084Version": dataMariaGaleraClusterV1084Version, 84 "dataMariaGaleraClusterV1084GlobalStatus": dataMariaGaleraClusterV1084GlobalStatus, 85 "dataMariaGaleraClusterV1084GlobalVariables": dataMariaGaleraClusterV1084GlobalVariables, 86 "dataMariaGaleraClusterV1084UserStatistics": dataMariaGaleraClusterV1084UserStatistics, 87 "dataMariaGaleraClusterV1084ProcessList": dataMariaGaleraClusterV1084ProcessList, 88 } { 89 require.NotNilf(t, data, fmt.Sprintf("read data: %s", name)) 90 _, err := prepareMockRows(data) 91 require.NoErrorf(t, err, fmt.Sprintf("prepare mock rows: %s", name)) 92 } 93 } 94 95 func TestNew(t *testing.T) { 96 assert.Implements(t, (*module.Module)(nil), New()) 97 } 98 99 func TestMySQL_Init(t *testing.T) { 100 tests := map[string]struct { 101 config Config 102 wantFail bool 103 }{ 104 "empty DSN": { 105 config: Config{DSN: ""}, 106 wantFail: true, 107 }, 108 } 109 110 for name, test := range tests { 111 t.Run(name, func(t *testing.T) { 112 mySQL := New() 113 mySQL.Config = test.config 114 115 if test.wantFail { 116 assert.False(t, mySQL.Init()) 117 } else { 118 assert.True(t, mySQL.Init()) 119 } 120 }) 121 } 122 } 123 124 func TestMySQL_Cleanup(t *testing.T) { 125 tests := map[string]func(t *testing.T) (mySQL *MySQL, cleanup func()){ 126 "db connection not initialized": func(t *testing.T) (mySQL *MySQL, cleanup func()) { 127 return New(), func() {} 128 }, 129 "db connection initialized": func(t *testing.T) (mySQL *MySQL, cleanup func()) { 130 db, mock, err := sqlmock.New() 131 require.NoError(t, err) 132 133 mock.ExpectClose() 134 mySQL = New() 135 mySQL.db = db 136 cleanup = func() { _ = db.Close() } 137 138 return mySQL, cleanup 139 }, 140 } 141 142 for name, prepare := range tests { 143 t.Run(name, func(t *testing.T) { 144 mySQL, cleanup := prepare(t) 145 defer cleanup() 146 147 assert.NotPanics(t, mySQL.Cleanup) 148 assert.Nil(t, mySQL.db) 149 }) 150 } 151 } 152 153 func TestMySQL_Charts(t *testing.T) { 154 assert.NotNil(t, New().Charts()) 155 } 156 157 func TestMySQL_Check(t *testing.T) { 158 tests := map[string]struct { 159 prepareMock func(t *testing.T, m sqlmock.Sqlmock) 160 wantFail bool 161 }{ 162 "success on all queries": { 163 wantFail: false, 164 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 165 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 166 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 167 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 168 mockExpect(t, m, queryShowAllSlavesStatus, dataMariaV1084AllSlavesStatusMultiSource) 169 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 170 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 171 }, 172 }, 173 "fails when error on querying version": { 174 wantFail: true, 175 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 176 mockExpectErr(m, queryShowVersion) 177 }, 178 }, 179 "fails when error on querying global status": { 180 wantFail: true, 181 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 182 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 183 mockExpectErr(m, queryShowGlobalStatus) 184 }, 185 }, 186 "fails when error on querying global variables": { 187 wantFail: true, 188 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 189 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 190 mockExpectErr(m, queryShowGlobalStatus) 191 }, 192 }, 193 "success when error on querying slave status": { 194 wantFail: false, 195 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 196 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 197 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 198 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 199 mockExpectErr(m, queryShowAllSlavesStatus) 200 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 201 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 202 }, 203 }, 204 "success when error on querying user statistics": { 205 wantFail: false, 206 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 207 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 208 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 209 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 210 mockExpect(t, m, queryShowAllSlavesStatus, dataMariaV1084AllSlavesStatusMultiSource) 211 mockExpectErr(m, queryShowUserStatistics) 212 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 213 }, 214 }, 215 "success when error on querying process list": { 216 wantFail: false, 217 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 218 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 219 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 220 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 221 mockExpect(t, m, queryShowAllSlavesStatus, dataMariaV1084AllSlavesStatusMultiSource) 222 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 223 mockExpectErr(m, queryShowProcessList) 224 }, 225 }, 226 } 227 228 for name, test := range tests { 229 t.Run(name, func(t *testing.T) { 230 db, mock, err := sqlmock.New( 231 sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual), 232 ) 233 require.NoError(t, err) 234 my := New() 235 my.db = db 236 defer func() { _ = db.Close() }() 237 238 require.True(t, my.Init()) 239 240 test.prepareMock(t, mock) 241 242 if test.wantFail { 243 assert.False(t, my.Check()) 244 } else { 245 assert.True(t, my.Check()) 246 } 247 assert.NoError(t, mock.ExpectationsWereMet()) 248 }) 249 } 250 } 251 252 func TestMySQL_Collect(t *testing.T) { 253 type testCaseStep struct { 254 prepareMock func(t *testing.T, m sqlmock.Sqlmock) 255 check func(t *testing.T, my *MySQL) 256 } 257 tests := map[string][]testCaseStep{ 258 "MariaDB-Standalone[v5.5.46]: success on all queries": { 259 { 260 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 261 mockExpect(t, m, queryShowVersion, dataMariaV5564Version) 262 mockExpect(t, m, queryShowGlobalStatus, dataMariaV5564GlobalStatus) 263 mockExpect(t, m, queryShowGlobalVariables, dataMariaV5564GlobalVariables) 264 mockExpect(t, m, queryShowSlaveStatus, nil) 265 mockExpect(t, m, queryShowProcessList, dataMariaV5564ProcessList) 266 }, 267 check: func(t *testing.T, my *MySQL) { 268 mx := my.Collect() 269 270 expected := map[string]int64{ 271 "aborted_connects": 0, 272 "binlog_cache_disk_use": 0, 273 "binlog_cache_use": 0, 274 "binlog_stmt_cache_disk_use": 0, 275 "binlog_stmt_cache_use": 0, 276 "bytes_received": 639, 277 "bytes_sent": 41620, 278 "com_delete": 0, 279 "com_insert": 0, 280 "com_replace": 0, 281 "com_select": 4, 282 "com_update": 0, 283 "connections": 4, 284 "created_tmp_disk_tables": 0, 285 "created_tmp_files": 6, 286 "created_tmp_tables": 5, 287 "handler_commit": 0, 288 "handler_delete": 0, 289 "handler_prepare": 0, 290 "handler_read_first": 0, 291 "handler_read_key": 0, 292 "handler_read_next": 0, 293 "handler_read_prev": 0, 294 "handler_read_rnd": 0, 295 "handler_read_rnd_next": 1264, 296 "handler_rollback": 0, 297 "handler_savepoint": 0, 298 "handler_savepoint_rollback": 0, 299 "handler_update": 0, 300 "handler_write": 0, 301 "innodb_buffer_pool_bytes_data": 2342912, 302 "innodb_buffer_pool_bytes_dirty": 0, 303 "innodb_buffer_pool_pages_data": 143, 304 "innodb_buffer_pool_pages_dirty": 0, 305 "innodb_buffer_pool_pages_flushed": 0, 306 "innodb_buffer_pool_pages_free": 16240, 307 "innodb_buffer_pool_pages_misc": 0, 308 "innodb_buffer_pool_pages_total": 16383, 309 "innodb_buffer_pool_read_ahead": 0, 310 "innodb_buffer_pool_read_ahead_evicted": 0, 311 "innodb_buffer_pool_read_ahead_rnd": 0, 312 "innodb_buffer_pool_read_requests": 459, 313 "innodb_buffer_pool_reads": 144, 314 "innodb_buffer_pool_wait_free": 0, 315 "innodb_buffer_pool_write_requests": 0, 316 "innodb_data_fsyncs": 3, 317 "innodb_data_pending_fsyncs": 0, 318 "innodb_data_pending_reads": 0, 319 "innodb_data_pending_writes": 0, 320 "innodb_data_read": 4542976, 321 "innodb_data_reads": 155, 322 "innodb_data_writes": 3, 323 "innodb_data_written": 1536, 324 "innodb_deadlocks": 0, 325 "innodb_log_waits": 0, 326 "innodb_log_write_requests": 0, 327 "innodb_log_writes": 1, 328 "innodb_os_log_fsyncs": 3, 329 "innodb_os_log_pending_fsyncs": 0, 330 "innodb_os_log_pending_writes": 0, 331 "innodb_os_log_written": 512, 332 "innodb_row_lock_current_waits": 0, 333 "innodb_rows_deleted": 0, 334 "innodb_rows_inserted": 0, 335 "innodb_rows_read": 0, 336 "innodb_rows_updated": 0, 337 "key_blocks_not_flushed": 0, 338 "key_blocks_unused": 107171, 339 "key_blocks_used": 0, 340 "key_read_requests": 0, 341 "key_reads": 0, 342 "key_write_requests": 0, 343 "key_writes": 0, 344 "max_connections": 100, 345 "max_used_connections": 1, 346 "open_files": 21, 347 "open_tables": 26, 348 "opened_files": 84, 349 "opened_tables": 0, 350 "process_list_fetch_query_duration": 0, 351 "process_list_longest_query_duration": 9, 352 "process_list_queries_count_system": 0, 353 "process_list_queries_count_user": 2, 354 "qcache_free_blocks": 1, 355 "qcache_free_memory": 67091120, 356 "qcache_hits": 0, 357 "qcache_inserts": 0, 358 "qcache_lowmem_prunes": 0, 359 "qcache_not_cached": 4, 360 "qcache_queries_in_cache": 0, 361 "qcache_total_blocks": 1, 362 "queries": 12, 363 "questions": 11, 364 "select_full_join": 0, 365 "select_full_range_join": 0, 366 "select_range": 0, 367 "select_range_check": 0, 368 "select_scan": 5, 369 "slow_queries": 0, 370 "sort_merge_passes": 0, 371 "sort_range": 0, 372 "sort_scan": 0, 373 "table_locks_immediate": 36, 374 "table_locks_waited": 0, 375 "table_open_cache": 400, 376 "thread_cache_misses": 2500, 377 "threads_cached": 0, 378 "threads_connected": 1, 379 "threads_created": 1, 380 "threads_running": 1, 381 } 382 383 copyProcessListQueryDuration(mx, expected) 384 require.Equal(t, expected, mx) 385 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 386 }, 387 }, 388 }, 389 "MariaDB-Standalone[v10.8.4]: success on all queries": { 390 { 391 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 392 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 393 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 394 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 395 mockExpect(t, m, queryShowAllSlavesStatus, nil) 396 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 397 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 398 }, 399 check: func(t *testing.T, my *MySQL) { 400 mx := my.Collect() 401 402 expected := map[string]int64{ 403 404 "aborted_connects": 2, 405 "binlog_cache_disk_use": 0, 406 "binlog_cache_use": 0, 407 "binlog_stmt_cache_disk_use": 0, 408 "binlog_stmt_cache_use": 0, 409 "bytes_received": 81392, 410 "bytes_sent": 56794, 411 "com_delete": 0, 412 "com_insert": 0, 413 "com_replace": 0, 414 "com_select": 6, 415 "com_update": 0, 416 "connection_errors_accept": 0, 417 "connection_errors_internal": 0, 418 "connection_errors_max_connections": 0, 419 "connection_errors_peer_address": 0, 420 "connection_errors_select": 0, 421 "connection_errors_tcpwrap": 0, 422 "connections": 12, 423 "created_tmp_disk_tables": 0, 424 "created_tmp_files": 5, 425 "created_tmp_tables": 2, 426 "handler_commit": 30, 427 "handler_delete": 0, 428 "handler_prepare": 0, 429 "handler_read_first": 7, 430 "handler_read_key": 7, 431 "handler_read_next": 3, 432 "handler_read_prev": 0, 433 "handler_read_rnd": 0, 434 "handler_read_rnd_next": 626, 435 "handler_rollback": 0, 436 "handler_savepoint": 0, 437 "handler_savepoint_rollback": 0, 438 "handler_update": 3, 439 "handler_write": 13, 440 "innodb_buffer_pool_bytes_data": 5062656, 441 "innodb_buffer_pool_bytes_dirty": 475136, 442 "innodb_buffer_pool_pages_data": 309, 443 "innodb_buffer_pool_pages_dirty": 29, 444 "innodb_buffer_pool_pages_flushed": 0, 445 "innodb_buffer_pool_pages_free": 7755, 446 "innodb_buffer_pool_pages_misc": 0, 447 "innodb_buffer_pool_pages_total": 8064, 448 "innodb_buffer_pool_read_ahead": 0, 449 "innodb_buffer_pool_read_ahead_evicted": 0, 450 "innodb_buffer_pool_read_ahead_rnd": 0, 451 "innodb_buffer_pool_read_requests": 1911, 452 "innodb_buffer_pool_reads": 171, 453 "innodb_buffer_pool_wait_free": 0, 454 "innodb_buffer_pool_write_requests": 148, 455 "innodb_data_fsyncs": 17, 456 "innodb_data_pending_fsyncs": 0, 457 "innodb_data_pending_reads": 0, 458 "innodb_data_pending_writes": 0, 459 "innodb_data_read": 2801664, 460 "innodb_data_reads": 185, 461 "innodb_data_writes": 16, 462 "innodb_data_written": 0, 463 "innodb_deadlocks": 0, 464 "innodb_log_waits": 0, 465 "innodb_log_write_requests": 109, 466 "innodb_log_writes": 15, 467 "innodb_os_log_written": 6097, 468 "innodb_row_lock_current_waits": 0, 469 "innodb_rows_deleted": 0, 470 "innodb_rows_inserted": 0, 471 "innodb_rows_read": 0, 472 "innodb_rows_updated": 0, 473 "key_blocks_not_flushed": 0, 474 "key_blocks_unused": 107163, 475 "key_blocks_used": 0, 476 "key_read_requests": 0, 477 "key_reads": 0, 478 "key_write_requests": 0, 479 "key_writes": 0, 480 "max_connections": 151, 481 "max_used_connections": 1, 482 "open_files": 29, 483 "open_tables": 10, 484 "opened_files": 100, 485 "opened_tables": 16, 486 "process_list_fetch_query_duration": 0, 487 "process_list_longest_query_duration": 9, 488 "process_list_queries_count_system": 0, 489 "process_list_queries_count_user": 2, 490 "qcache_free_blocks": 1, 491 "qcache_free_memory": 1031272, 492 "qcache_hits": 0, 493 "qcache_inserts": 0, 494 "qcache_lowmem_prunes": 0, 495 "qcache_not_cached": 0, 496 "qcache_queries_in_cache": 0, 497 "qcache_total_blocks": 1, 498 "queries": 33, 499 "questions": 24, 500 "select_full_join": 0, 501 "select_full_range_join": 0, 502 "select_range": 0, 503 "select_range_check": 0, 504 "select_scan": 2, 505 "slow_queries": 0, 506 "sort_merge_passes": 0, 507 "sort_range": 0, 508 "sort_scan": 0, 509 "table_locks_immediate": 60, 510 "table_locks_waited": 0, 511 "table_open_cache": 2000, 512 "table_open_cache_overflows": 0, 513 "thread_cache_misses": 1666, 514 "threads_cached": 0, 515 "threads_connected": 1, 516 "threads_created": 2, 517 "threads_running": 3, 518 "userstats_netdata_access_denied": 33, 519 "userstats_netdata_binlog_bytes_written": 0, 520 "userstats_netdata_commit_transactions": 0, 521 "userstats_netdata_cpu_time": 77, 522 "userstats_netdata_denied_connections": 49698, 523 "userstats_netdata_empty_queries": 66, 524 "userstats_netdata_lost_connections": 0, 525 "userstats_netdata_other_commands": 0, 526 "userstats_netdata_rollback_transactions": 0, 527 "userstats_netdata_rows_deleted": 0, 528 "userstats_netdata_rows_inserted": 0, 529 "userstats_netdata_rows_read": 0, 530 "userstats_netdata_rows_sent": 99, 531 "userstats_netdata_rows_updated": 0, 532 "userstats_netdata_select_commands": 33, 533 "userstats_netdata_total_connections": 1, 534 "userstats_netdata_update_commands": 0, 535 "userstats_root_access_denied": 0, 536 "userstats_root_binlog_bytes_written": 0, 537 "userstats_root_commit_transactions": 0, 538 "userstats_root_cpu_time": 0, 539 "userstats_root_denied_connections": 0, 540 "userstats_root_empty_queries": 0, 541 "userstats_root_lost_connections": 0, 542 "userstats_root_other_commands": 0, 543 "userstats_root_rollback_transactions": 0, 544 "userstats_root_rows_deleted": 0, 545 "userstats_root_rows_inserted": 0, 546 "userstats_root_rows_read": 0, 547 "userstats_root_rows_sent": 2, 548 "userstats_root_rows_updated": 0, 549 "userstats_root_select_commands": 0, 550 "userstats_root_total_connections": 1, 551 "userstats_root_update_commands": 0, 552 "wsrep_cluster_size": 0, 553 "wsrep_cluster_status_disconnected": 1, 554 "wsrep_cluster_status_non_primary": 0, 555 "wsrep_cluster_status_primary": 0, 556 "wsrep_connected": 0, 557 "wsrep_local_bf_aborts": 0, 558 "wsrep_ready": 0, 559 "wsrep_thread_count": 0, 560 } 561 562 copyProcessListQueryDuration(mx, expected) 563 require.Equal(t, expected, mx) 564 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 565 }, 566 }, 567 }, 568 "MariaDB-SingleSourceReplication[v10.8.4]: success on all queries": { 569 { 570 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 571 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 572 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 573 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 574 mockExpect(t, m, queryShowAllSlavesStatus, dataMariaV1084AllSlavesStatusSingleSource) 575 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 576 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 577 }, 578 check: func(t *testing.T, my *MySQL) { 579 mx := my.Collect() 580 581 expected := map[string]int64{ 582 "aborted_connects": 2, 583 "binlog_cache_disk_use": 0, 584 "binlog_cache_use": 0, 585 "binlog_stmt_cache_disk_use": 0, 586 "binlog_stmt_cache_use": 0, 587 "bytes_received": 81392, 588 "bytes_sent": 56794, 589 "com_delete": 0, 590 "com_insert": 0, 591 "com_replace": 0, 592 "com_select": 6, 593 "com_update": 0, 594 "connection_errors_accept": 0, 595 "connection_errors_internal": 0, 596 "connection_errors_max_connections": 0, 597 "connection_errors_peer_address": 0, 598 "connection_errors_select": 0, 599 "connection_errors_tcpwrap": 0, 600 "connections": 12, 601 "created_tmp_disk_tables": 0, 602 "created_tmp_files": 5, 603 "created_tmp_tables": 2, 604 "handler_commit": 30, 605 "handler_delete": 0, 606 "handler_prepare": 0, 607 "handler_read_first": 7, 608 "handler_read_key": 7, 609 "handler_read_next": 3, 610 "handler_read_prev": 0, 611 "handler_read_rnd": 0, 612 "handler_read_rnd_next": 626, 613 "handler_rollback": 0, 614 "handler_savepoint": 0, 615 "handler_savepoint_rollback": 0, 616 "handler_update": 3, 617 "handler_write": 13, 618 "innodb_buffer_pool_bytes_data": 5062656, 619 "innodb_buffer_pool_bytes_dirty": 475136, 620 "innodb_buffer_pool_pages_data": 309, 621 "innodb_buffer_pool_pages_dirty": 29, 622 "innodb_buffer_pool_pages_flushed": 0, 623 "innodb_buffer_pool_pages_free": 7755, 624 "innodb_buffer_pool_pages_misc": 0, 625 "innodb_buffer_pool_pages_total": 8064, 626 "innodb_buffer_pool_read_ahead": 0, 627 "innodb_buffer_pool_read_ahead_evicted": 0, 628 "innodb_buffer_pool_read_ahead_rnd": 0, 629 "innodb_buffer_pool_read_requests": 1911, 630 "innodb_buffer_pool_reads": 171, 631 "innodb_buffer_pool_wait_free": 0, 632 "innodb_buffer_pool_write_requests": 148, 633 "innodb_data_fsyncs": 17, 634 "innodb_data_pending_fsyncs": 0, 635 "innodb_data_pending_reads": 0, 636 "innodb_data_pending_writes": 0, 637 "innodb_data_read": 2801664, 638 "innodb_data_reads": 185, 639 "innodb_data_writes": 16, 640 "innodb_data_written": 0, 641 "innodb_deadlocks": 0, 642 "innodb_log_waits": 0, 643 "innodb_log_write_requests": 109, 644 "innodb_log_writes": 15, 645 "innodb_os_log_written": 6097, 646 "innodb_row_lock_current_waits": 0, 647 "innodb_rows_deleted": 0, 648 "innodb_rows_inserted": 0, 649 "innodb_rows_read": 0, 650 "innodb_rows_updated": 0, 651 "key_blocks_not_flushed": 0, 652 "key_blocks_unused": 107163, 653 "key_blocks_used": 0, 654 "key_read_requests": 0, 655 "key_reads": 0, 656 "key_write_requests": 0, 657 "key_writes": 0, 658 "max_connections": 151, 659 "max_used_connections": 1, 660 "open_files": 29, 661 "open_tables": 10, 662 "opened_files": 100, 663 "opened_tables": 16, 664 "process_list_fetch_query_duration": 0, 665 "process_list_longest_query_duration": 9, 666 "process_list_queries_count_system": 0, 667 "process_list_queries_count_user": 2, 668 "qcache_free_blocks": 1, 669 "qcache_free_memory": 1031272, 670 "qcache_hits": 0, 671 "qcache_inserts": 0, 672 "qcache_lowmem_prunes": 0, 673 "qcache_not_cached": 0, 674 "qcache_queries_in_cache": 0, 675 "qcache_total_blocks": 1, 676 "queries": 33, 677 "questions": 24, 678 "seconds_behind_master": 0, 679 "select_full_join": 0, 680 "select_full_range_join": 0, 681 "select_range": 0, 682 "select_range_check": 0, 683 "select_scan": 2, 684 "slave_io_running": 1, 685 "slave_sql_running": 1, 686 "slow_queries": 0, 687 "sort_merge_passes": 0, 688 "sort_range": 0, 689 "sort_scan": 0, 690 "table_locks_immediate": 60, 691 "table_locks_waited": 0, 692 "table_open_cache": 2000, 693 "table_open_cache_overflows": 0, 694 "thread_cache_misses": 1666, 695 "threads_cached": 0, 696 "threads_connected": 1, 697 "threads_created": 2, 698 "threads_running": 3, 699 "userstats_netdata_access_denied": 33, 700 "userstats_netdata_binlog_bytes_written": 0, 701 "userstats_netdata_commit_transactions": 0, 702 "userstats_netdata_cpu_time": 77, 703 "userstats_netdata_denied_connections": 49698, 704 "userstats_netdata_empty_queries": 66, 705 "userstats_netdata_lost_connections": 0, 706 "userstats_netdata_other_commands": 0, 707 "userstats_netdata_rollback_transactions": 0, 708 "userstats_netdata_rows_deleted": 0, 709 "userstats_netdata_rows_inserted": 0, 710 "userstats_netdata_rows_read": 0, 711 "userstats_netdata_rows_sent": 99, 712 "userstats_netdata_rows_updated": 0, 713 "userstats_netdata_select_commands": 33, 714 "userstats_netdata_total_connections": 1, 715 "userstats_netdata_update_commands": 0, 716 "userstats_root_access_denied": 0, 717 "userstats_root_binlog_bytes_written": 0, 718 "userstats_root_commit_transactions": 0, 719 "userstats_root_cpu_time": 0, 720 "userstats_root_denied_connections": 0, 721 "userstats_root_empty_queries": 0, 722 "userstats_root_lost_connections": 0, 723 "userstats_root_other_commands": 0, 724 "userstats_root_rollback_transactions": 0, 725 "userstats_root_rows_deleted": 0, 726 "userstats_root_rows_inserted": 0, 727 "userstats_root_rows_read": 0, 728 "userstats_root_rows_sent": 2, 729 "userstats_root_rows_updated": 0, 730 "userstats_root_select_commands": 0, 731 "userstats_root_total_connections": 1, 732 "userstats_root_update_commands": 0, 733 "wsrep_cluster_size": 0, 734 "wsrep_cluster_status_disconnected": 1, 735 "wsrep_cluster_status_non_primary": 0, 736 "wsrep_cluster_status_primary": 0, 737 "wsrep_connected": 0, 738 "wsrep_local_bf_aborts": 0, 739 "wsrep_ready": 0, 740 "wsrep_thread_count": 0, 741 } 742 743 copyProcessListQueryDuration(mx, expected) 744 require.Equal(t, expected, mx) 745 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 746 }, 747 }, 748 }, 749 "MariaDB-MultiSourceReplication[v10.8.4]: success on all queries": { 750 { 751 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 752 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 753 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 754 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 755 mockExpect(t, m, queryShowAllSlavesStatus, dataMariaV1084AllSlavesStatusMultiSource) 756 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 757 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 758 }, 759 check: func(t *testing.T, my *MySQL) { 760 mx := my.Collect() 761 762 expected := map[string]int64{ 763 "aborted_connects": 2, 764 "binlog_cache_disk_use": 0, 765 "binlog_cache_use": 0, 766 "binlog_stmt_cache_disk_use": 0, 767 "binlog_stmt_cache_use": 0, 768 "bytes_received": 81392, 769 "bytes_sent": 56794, 770 "com_delete": 0, 771 "com_insert": 0, 772 "com_replace": 0, 773 "com_select": 6, 774 "com_update": 0, 775 "connection_errors_accept": 0, 776 "connection_errors_internal": 0, 777 "connection_errors_max_connections": 0, 778 "connection_errors_peer_address": 0, 779 "connection_errors_select": 0, 780 "connection_errors_tcpwrap": 0, 781 "connections": 12, 782 "created_tmp_disk_tables": 0, 783 "created_tmp_files": 5, 784 "created_tmp_tables": 2, 785 "handler_commit": 30, 786 "handler_delete": 0, 787 "handler_prepare": 0, 788 "handler_read_first": 7, 789 "handler_read_key": 7, 790 "handler_read_next": 3, 791 "handler_read_prev": 0, 792 "handler_read_rnd": 0, 793 "handler_read_rnd_next": 626, 794 "handler_rollback": 0, 795 "handler_savepoint": 0, 796 "handler_savepoint_rollback": 0, 797 "handler_update": 3, 798 "handler_write": 13, 799 "innodb_buffer_pool_bytes_data": 5062656, 800 "innodb_buffer_pool_bytes_dirty": 475136, 801 "innodb_buffer_pool_pages_data": 309, 802 "innodb_buffer_pool_pages_dirty": 29, 803 "innodb_buffer_pool_pages_flushed": 0, 804 "innodb_buffer_pool_pages_free": 7755, 805 "innodb_buffer_pool_pages_misc": 0, 806 "innodb_buffer_pool_pages_total": 8064, 807 "innodb_buffer_pool_read_ahead": 0, 808 "innodb_buffer_pool_read_ahead_evicted": 0, 809 "innodb_buffer_pool_read_ahead_rnd": 0, 810 "innodb_buffer_pool_read_requests": 1911, 811 "innodb_buffer_pool_reads": 171, 812 "innodb_buffer_pool_wait_free": 0, 813 "innodb_buffer_pool_write_requests": 148, 814 "innodb_data_fsyncs": 17, 815 "innodb_data_pending_fsyncs": 0, 816 "innodb_data_pending_reads": 0, 817 "innodb_data_pending_writes": 0, 818 "innodb_data_read": 2801664, 819 "innodb_data_reads": 185, 820 "innodb_data_writes": 16, 821 "innodb_data_written": 0, 822 "innodb_deadlocks": 0, 823 "innodb_log_waits": 0, 824 "innodb_log_write_requests": 109, 825 "innodb_log_writes": 15, 826 "innodb_os_log_written": 6097, 827 "innodb_row_lock_current_waits": 0, 828 "innodb_rows_deleted": 0, 829 "innodb_rows_inserted": 0, 830 "innodb_rows_read": 0, 831 "innodb_rows_updated": 0, 832 "key_blocks_not_flushed": 0, 833 "key_blocks_unused": 107163, 834 "key_blocks_used": 0, 835 "key_read_requests": 0, 836 "key_reads": 0, 837 "key_write_requests": 0, 838 "key_writes": 0, 839 "max_connections": 151, 840 "max_used_connections": 1, 841 "open_files": 29, 842 "open_tables": 10, 843 "opened_files": 100, 844 "opened_tables": 16, 845 "process_list_fetch_query_duration": 0, 846 "process_list_longest_query_duration": 9, 847 "process_list_queries_count_system": 0, 848 "process_list_queries_count_user": 2, 849 "qcache_free_blocks": 1, 850 "qcache_free_memory": 1031272, 851 "qcache_hits": 0, 852 "qcache_inserts": 0, 853 "qcache_lowmem_prunes": 0, 854 "qcache_not_cached": 0, 855 "qcache_queries_in_cache": 0, 856 "qcache_total_blocks": 1, 857 "queries": 33, 858 "questions": 24, 859 "seconds_behind_master_master1": 0, 860 "seconds_behind_master_master2": 0, 861 "select_full_join": 0, 862 "select_full_range_join": 0, 863 "select_range": 0, 864 "select_range_check": 0, 865 "select_scan": 2, 866 "slave_io_running_master1": 1, 867 "slave_io_running_master2": 1, 868 "slave_sql_running_master1": 1, 869 "slave_sql_running_master2": 1, 870 "slow_queries": 0, 871 "sort_merge_passes": 0, 872 "sort_range": 0, 873 "sort_scan": 0, 874 "table_locks_immediate": 60, 875 "table_locks_waited": 0, 876 "table_open_cache": 2000, 877 "table_open_cache_overflows": 0, 878 "thread_cache_misses": 1666, 879 "threads_cached": 0, 880 "threads_connected": 1, 881 "threads_created": 2, 882 "threads_running": 3, 883 "userstats_netdata_access_denied": 33, 884 "userstats_netdata_binlog_bytes_written": 0, 885 "userstats_netdata_commit_transactions": 0, 886 "userstats_netdata_cpu_time": 77, 887 "userstats_netdata_denied_connections": 49698, 888 "userstats_netdata_empty_queries": 66, 889 "userstats_netdata_lost_connections": 0, 890 "userstats_netdata_other_commands": 0, 891 "userstats_netdata_rollback_transactions": 0, 892 "userstats_netdata_rows_deleted": 0, 893 "userstats_netdata_rows_inserted": 0, 894 "userstats_netdata_rows_read": 0, 895 "userstats_netdata_rows_sent": 99, 896 "userstats_netdata_rows_updated": 0, 897 "userstats_netdata_select_commands": 33, 898 "userstats_netdata_total_connections": 1, 899 "userstats_netdata_update_commands": 0, 900 "userstats_root_access_denied": 0, 901 "userstats_root_binlog_bytes_written": 0, 902 "userstats_root_commit_transactions": 0, 903 "userstats_root_cpu_time": 0, 904 "userstats_root_denied_connections": 0, 905 "userstats_root_empty_queries": 0, 906 "userstats_root_lost_connections": 0, 907 "userstats_root_other_commands": 0, 908 "userstats_root_rollback_transactions": 0, 909 "userstats_root_rows_deleted": 0, 910 "userstats_root_rows_inserted": 0, 911 "userstats_root_rows_read": 0, 912 "userstats_root_rows_sent": 2, 913 "userstats_root_rows_updated": 0, 914 "userstats_root_select_commands": 0, 915 "userstats_root_total_connections": 1, 916 "userstats_root_update_commands": 0, 917 "wsrep_cluster_size": 0, 918 "wsrep_cluster_status_disconnected": 1, 919 "wsrep_cluster_status_non_primary": 0, 920 "wsrep_cluster_status_primary": 0, 921 "wsrep_connected": 0, 922 "wsrep_local_bf_aborts": 0, 923 "wsrep_ready": 0, 924 "wsrep_thread_count": 0, 925 } 926 927 copyProcessListQueryDuration(mx, expected) 928 require.Equal(t, expected, mx) 929 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 930 }, 931 }, 932 }, 933 "MariaDB-MultiSourceReplication[v10.8.4]: error on slaves status (no permissions)": { 934 { 935 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 936 mockExpect(t, m, queryShowVersion, dataMariaV1084Version) 937 mockExpect(t, m, queryShowGlobalStatus, dataMariaV1084GlobalStatus) 938 mockExpect(t, m, queryShowGlobalVariables, dataMariaV1084GlobalVariables) 939 mockExpectErr(m, queryShowAllSlavesStatus) 940 mockExpect(t, m, queryShowUserStatistics, dataMariaV1084UserStatistics) 941 mockExpect(t, m, queryShowProcessList, dataMariaV1084ProcessList) 942 }, 943 check: func(t *testing.T, my *MySQL) { 944 mx := my.Collect() 945 946 expected := map[string]int64{ 947 "aborted_connects": 2, 948 "binlog_cache_disk_use": 0, 949 "binlog_cache_use": 0, 950 "binlog_stmt_cache_disk_use": 0, 951 "binlog_stmt_cache_use": 0, 952 "bytes_received": 81392, 953 "bytes_sent": 56794, 954 "com_delete": 0, 955 "com_insert": 0, 956 "com_replace": 0, 957 "com_select": 6, 958 "com_update": 0, 959 "connection_errors_accept": 0, 960 "connection_errors_internal": 0, 961 "connection_errors_max_connections": 0, 962 "connection_errors_peer_address": 0, 963 "connection_errors_select": 0, 964 "connection_errors_tcpwrap": 0, 965 "connections": 12, 966 "created_tmp_disk_tables": 0, 967 "created_tmp_files": 5, 968 "created_tmp_tables": 2, 969 "handler_commit": 30, 970 "handler_delete": 0, 971 "handler_prepare": 0, 972 "handler_read_first": 7, 973 "handler_read_key": 7, 974 "handler_read_next": 3, 975 "handler_read_prev": 0, 976 "handler_read_rnd": 0, 977 "handler_read_rnd_next": 626, 978 "handler_rollback": 0, 979 "handler_savepoint": 0, 980 "handler_savepoint_rollback": 0, 981 "handler_update": 3, 982 "handler_write": 13, 983 "innodb_buffer_pool_bytes_data": 5062656, 984 "innodb_buffer_pool_bytes_dirty": 475136, 985 "innodb_buffer_pool_pages_data": 309, 986 "innodb_buffer_pool_pages_dirty": 29, 987 "innodb_buffer_pool_pages_flushed": 0, 988 "innodb_buffer_pool_pages_free": 7755, 989 "innodb_buffer_pool_pages_misc": 0, 990 "innodb_buffer_pool_pages_total": 8064, 991 "innodb_buffer_pool_read_ahead": 0, 992 "innodb_buffer_pool_read_ahead_evicted": 0, 993 "innodb_buffer_pool_read_ahead_rnd": 0, 994 "innodb_buffer_pool_read_requests": 1911, 995 "innodb_buffer_pool_reads": 171, 996 "innodb_buffer_pool_wait_free": 0, 997 "innodb_buffer_pool_write_requests": 148, 998 "innodb_data_fsyncs": 17, 999 "innodb_data_pending_fsyncs": 0, 1000 "innodb_data_pending_reads": 0, 1001 "innodb_data_pending_writes": 0, 1002 "innodb_data_read": 2801664, 1003 "innodb_data_reads": 185, 1004 "innodb_data_writes": 16, 1005 "innodb_data_written": 0, 1006 "innodb_deadlocks": 0, 1007 "innodb_log_waits": 0, 1008 "innodb_log_write_requests": 109, 1009 "innodb_log_writes": 15, 1010 "innodb_os_log_written": 6097, 1011 "innodb_row_lock_current_waits": 0, 1012 "innodb_rows_deleted": 0, 1013 "innodb_rows_inserted": 0, 1014 "innodb_rows_read": 0, 1015 "innodb_rows_updated": 0, 1016 "key_blocks_not_flushed": 0, 1017 "key_blocks_unused": 107163, 1018 "key_blocks_used": 0, 1019 "key_read_requests": 0, 1020 "key_reads": 0, 1021 "key_write_requests": 0, 1022 "key_writes": 0, 1023 "max_connections": 151, 1024 "max_used_connections": 1, 1025 "open_files": 29, 1026 "open_tables": 10, 1027 "opened_files": 100, 1028 "opened_tables": 16, 1029 "process_list_fetch_query_duration": 0, 1030 "process_list_longest_query_duration": 9, 1031 "process_list_queries_count_system": 0, 1032 "process_list_queries_count_user": 2, 1033 "qcache_free_blocks": 1, 1034 "qcache_free_memory": 1031272, 1035 "qcache_hits": 0, 1036 "qcache_inserts": 0, 1037 "qcache_lowmem_prunes": 0, 1038 "qcache_not_cached": 0, 1039 "qcache_queries_in_cache": 0, 1040 "qcache_total_blocks": 1, 1041 "queries": 33, 1042 "questions": 24, 1043 "select_full_join": 0, 1044 "select_full_range_join": 0, 1045 "select_range": 0, 1046 "select_range_check": 0, 1047 "select_scan": 2, 1048 "slow_queries": 0, 1049 "sort_merge_passes": 0, 1050 "sort_range": 0, 1051 "sort_scan": 0, 1052 "table_locks_immediate": 60, 1053 "table_locks_waited": 0, 1054 "table_open_cache": 2000, 1055 "table_open_cache_overflows": 0, 1056 "thread_cache_misses": 1666, 1057 "threads_cached": 0, 1058 "threads_connected": 1, 1059 "threads_created": 2, 1060 "threads_running": 3, 1061 "userstats_netdata_access_denied": 33, 1062 "userstats_netdata_binlog_bytes_written": 0, 1063 "userstats_netdata_commit_transactions": 0, 1064 "userstats_netdata_cpu_time": 77, 1065 "userstats_netdata_denied_connections": 49698, 1066 "userstats_netdata_empty_queries": 66, 1067 "userstats_netdata_lost_connections": 0, 1068 "userstats_netdata_other_commands": 0, 1069 "userstats_netdata_rollback_transactions": 0, 1070 "userstats_netdata_rows_deleted": 0, 1071 "userstats_netdata_rows_inserted": 0, 1072 "userstats_netdata_rows_read": 0, 1073 "userstats_netdata_rows_sent": 99, 1074 "userstats_netdata_rows_updated": 0, 1075 "userstats_netdata_select_commands": 33, 1076 "userstats_netdata_total_connections": 1, 1077 "userstats_netdata_update_commands": 0, 1078 "userstats_root_access_denied": 0, 1079 "userstats_root_binlog_bytes_written": 0, 1080 "userstats_root_commit_transactions": 0, 1081 "userstats_root_cpu_time": 0, 1082 "userstats_root_denied_connections": 0, 1083 "userstats_root_empty_queries": 0, 1084 "userstats_root_lost_connections": 0, 1085 "userstats_root_other_commands": 0, 1086 "userstats_root_rollback_transactions": 0, 1087 "userstats_root_rows_deleted": 0, 1088 "userstats_root_rows_inserted": 0, 1089 "userstats_root_rows_read": 0, 1090 "userstats_root_rows_sent": 2, 1091 "userstats_root_rows_updated": 0, 1092 "userstats_root_select_commands": 0, 1093 "userstats_root_total_connections": 1, 1094 "userstats_root_update_commands": 0, 1095 "wsrep_cluster_size": 0, 1096 "wsrep_cluster_status_disconnected": 1, 1097 "wsrep_cluster_status_non_primary": 0, 1098 "wsrep_cluster_status_primary": 0, 1099 "wsrep_connected": 0, 1100 "wsrep_local_bf_aborts": 0, 1101 "wsrep_ready": 0, 1102 "wsrep_thread_count": 0, 1103 } 1104 1105 copyProcessListQueryDuration(mx, expected) 1106 require.Equal(t, expected, mx) 1107 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 1108 }, 1109 }, 1110 }, 1111 "MariaDB-GaleraCluster[v10.8.4]: success on all queries": { 1112 { 1113 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 1114 mockExpect(t, m, queryShowVersion, dataMariaGaleraClusterV1084Version) 1115 mockExpect(t, m, queryShowGlobalStatus, dataMariaGaleraClusterV1084GlobalStatus) 1116 mockExpect(t, m, queryShowGlobalVariables, dataMariaGaleraClusterV1084GlobalVariables) 1117 mockExpect(t, m, queryShowAllSlavesStatus, nil) 1118 mockExpect(t, m, queryShowUserStatistics, dataMariaGaleraClusterV1084UserStatistics) 1119 mockExpect(t, m, queryShowProcessList, dataMariaGaleraClusterV1084ProcessList) 1120 }, 1121 check: func(t *testing.T, my *MySQL) { 1122 mx := my.Collect() 1123 1124 expected := map[string]int64{ 1125 "aborted_connects": 0, 1126 "binlog_cache_disk_use": 0, 1127 "binlog_cache_use": 0, 1128 "binlog_stmt_cache_disk_use": 0, 1129 "binlog_stmt_cache_use": 0, 1130 "bytes_received": 3009, 1131 "bytes_sent": 228856, 1132 "com_delete": 6, 1133 "com_insert": 0, 1134 "com_replace": 0, 1135 "com_select": 12, 1136 "com_update": 0, 1137 "connection_errors_accept": 0, 1138 "connection_errors_internal": 0, 1139 "connection_errors_max_connections": 0, 1140 "connection_errors_peer_address": 0, 1141 "connection_errors_select": 0, 1142 "connection_errors_tcpwrap": 0, 1143 "connections": 15, 1144 "created_tmp_disk_tables": 4, 1145 "created_tmp_files": 5, 1146 "created_tmp_tables": 17, 1147 "handler_commit": 37, 1148 "handler_delete": 7, 1149 "handler_prepare": 0, 1150 "handler_read_first": 3, 1151 "handler_read_key": 9, 1152 "handler_read_next": 1, 1153 "handler_read_prev": 0, 1154 "handler_read_rnd": 0, 1155 "handler_read_rnd_next": 6222, 1156 "handler_rollback": 0, 1157 "handler_savepoint": 0, 1158 "handler_savepoint_rollback": 0, 1159 "handler_update": 0, 1160 "handler_write": 9, 1161 "innodb_buffer_pool_bytes_data": 5193728, 1162 "innodb_buffer_pool_bytes_dirty": 2260992, 1163 "innodb_buffer_pool_pages_data": 317, 1164 "innodb_buffer_pool_pages_dirty": 138, 1165 "innodb_buffer_pool_pages_flushed": 0, 1166 "innodb_buffer_pool_pages_free": 7747, 1167 "innodb_buffer_pool_pages_misc": 0, 1168 "innodb_buffer_pool_pages_total": 8064, 1169 "innodb_buffer_pool_read_ahead": 0, 1170 "innodb_buffer_pool_read_ahead_evicted": 0, 1171 "innodb_buffer_pool_read_ahead_rnd": 0, 1172 "innodb_buffer_pool_read_requests": 2298, 1173 "innodb_buffer_pool_reads": 184, 1174 "innodb_buffer_pool_wait_free": 0, 1175 "innodb_buffer_pool_write_requests": 203, 1176 "innodb_data_fsyncs": 15, 1177 "innodb_data_pending_fsyncs": 0, 1178 "innodb_data_pending_reads": 0, 1179 "innodb_data_pending_writes": 0, 1180 "innodb_data_read": 3014656, 1181 "innodb_data_reads": 201, 1182 "innodb_data_writes": 14, 1183 "innodb_data_written": 0, 1184 "innodb_deadlocks": 0, 1185 "innodb_log_waits": 0, 1186 "innodb_log_write_requests": 65, 1187 "innodb_log_writes": 13, 1188 "innodb_os_log_written": 4785, 1189 "innodb_row_lock_current_waits": 0, 1190 "innodb_rows_deleted": 0, 1191 "innodb_rows_inserted": 0, 1192 "innodb_rows_read": 0, 1193 "innodb_rows_updated": 0, 1194 "key_blocks_not_flushed": 0, 1195 "key_blocks_unused": 107163, 1196 "key_blocks_used": 0, 1197 "key_read_requests": 0, 1198 "key_reads": 0, 1199 "key_write_requests": 0, 1200 "key_writes": 0, 1201 "max_connections": 151, 1202 "max_used_connections": 1, 1203 "open_files": 7, 1204 "open_tables": 0, 1205 "opened_files": 125, 1206 "opened_tables": 24, 1207 "process_list_fetch_query_duration": 0, 1208 "process_list_longest_query_duration": 9, 1209 "process_list_queries_count_system": 0, 1210 "process_list_queries_count_user": 2, 1211 "qcache_free_blocks": 1, 1212 "qcache_free_memory": 1031272, 1213 "qcache_hits": 0, 1214 "qcache_inserts": 0, 1215 "qcache_lowmem_prunes": 0, 1216 "qcache_not_cached": 0, 1217 "qcache_queries_in_cache": 0, 1218 "qcache_total_blocks": 1, 1219 "queries": 75, 1220 "questions": 62, 1221 "select_full_join": 0, 1222 "select_full_range_join": 0, 1223 "select_range": 0, 1224 "select_range_check": 0, 1225 "select_scan": 17, 1226 "slow_queries": 0, 1227 "sort_merge_passes": 0, 1228 "sort_range": 0, 1229 "sort_scan": 0, 1230 "table_locks_immediate": 17, 1231 "table_locks_waited": 0, 1232 "table_open_cache": 2000, 1233 "table_open_cache_overflows": 0, 1234 "thread_cache_misses": 4000, 1235 "threads_cached": 0, 1236 "threads_connected": 1, 1237 "threads_created": 6, 1238 "threads_running": 1, 1239 "userstats_netdata_access_denied": 33, 1240 "userstats_netdata_binlog_bytes_written": 0, 1241 "userstats_netdata_commit_transactions": 0, 1242 "userstats_netdata_cpu_time": 77, 1243 "userstats_netdata_denied_connections": 49698, 1244 "userstats_netdata_empty_queries": 66, 1245 "userstats_netdata_lost_connections": 0, 1246 "userstats_netdata_other_commands": 0, 1247 "userstats_netdata_rollback_transactions": 0, 1248 "userstats_netdata_rows_deleted": 0, 1249 "userstats_netdata_rows_inserted": 0, 1250 "userstats_netdata_rows_read": 0, 1251 "userstats_netdata_rows_sent": 99, 1252 "userstats_netdata_rows_updated": 0, 1253 "userstats_netdata_select_commands": 33, 1254 "userstats_netdata_total_connections": 1, 1255 "userstats_netdata_update_commands": 0, 1256 "userstats_root_access_denied": 0, 1257 "userstats_root_binlog_bytes_written": 0, 1258 "userstats_root_commit_transactions": 0, 1259 "userstats_root_cpu_time": 0, 1260 "userstats_root_denied_connections": 0, 1261 "userstats_root_empty_queries": 0, 1262 "userstats_root_lost_connections": 0, 1263 "userstats_root_other_commands": 0, 1264 "userstats_root_rollback_transactions": 0, 1265 "userstats_root_rows_deleted": 0, 1266 "userstats_root_rows_inserted": 0, 1267 "userstats_root_rows_read": 0, 1268 "userstats_root_rows_sent": 2, 1269 "userstats_root_rows_updated": 0, 1270 "userstats_root_select_commands": 0, 1271 "userstats_root_total_connections": 1, 1272 "userstats_root_update_commands": 0, 1273 "wsrep_cluster_size": 3, 1274 "wsrep_cluster_status_disconnected": 0, 1275 "wsrep_cluster_status_non_primary": 0, 1276 "wsrep_cluster_status_primary": 1, 1277 "wsrep_cluster_weight": 3, 1278 "wsrep_connected": 1, 1279 "wsrep_flow_control_paused_ns": 0, 1280 "wsrep_local_bf_aborts": 0, 1281 "wsrep_local_cert_failures": 0, 1282 "wsrep_local_recv_queue": 0, 1283 "wsrep_local_send_queue": 0, 1284 "wsrep_local_state_donor": 0, 1285 "wsrep_local_state_error": 0, 1286 "wsrep_local_state_joined": 0, 1287 "wsrep_local_state_joiner": 0, 1288 "wsrep_local_state_synced": 1, 1289 "wsrep_local_state_undefined": 0, 1290 "wsrep_open_transactions": 0, 1291 "wsrep_ready": 1, 1292 "wsrep_received": 11, 1293 "wsrep_received_bytes": 1410, 1294 "wsrep_replicated": 0, 1295 "wsrep_replicated_bytes": 0, 1296 "wsrep_thread_count": 5, 1297 } 1298 1299 copyProcessListQueryDuration(mx, expected) 1300 require.Equal(t, expected, mx) 1301 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 1302 }, 1303 }, 1304 }, 1305 "MySQL-MultiSourceReplication[v8.0.30]: success on all queries": { 1306 { 1307 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 1308 mockExpect(t, m, queryShowVersion, dataMySQLV8030Version) 1309 mockExpect(t, m, queryShowGlobalStatus, dataMySQLV8030GlobalStatus) 1310 mockExpect(t, m, queryShowGlobalVariables, dataMySQLV8030GlobalVariables) 1311 mockExpect(t, m, queryShowReplicaStatus, dataMySQLV8030ReplicaStatusMultiSource) 1312 mockExpect(t, m, queryShowProcessListPS, dataMySQLV8030ProcessList) 1313 }, 1314 check: func(t *testing.T, my *MySQL) { 1315 mx := my.Collect() 1316 1317 expected := map[string]int64{ 1318 "aborted_connects": 0, 1319 "binlog_cache_disk_use": 0, 1320 "binlog_cache_use": 6, 1321 "binlog_stmt_cache_disk_use": 0, 1322 "binlog_stmt_cache_use": 0, 1323 "bytes_received": 5584, 1324 "bytes_sent": 70700, 1325 "com_delete": 0, 1326 "com_insert": 0, 1327 "com_replace": 0, 1328 "com_select": 2, 1329 "com_update": 0, 1330 "connection_errors_accept": 0, 1331 "connection_errors_internal": 0, 1332 "connection_errors_max_connections": 0, 1333 "connection_errors_peer_address": 0, 1334 "connection_errors_select": 0, 1335 "connection_errors_tcpwrap": 0, 1336 "connections": 25, 1337 "created_tmp_disk_tables": 0, 1338 "created_tmp_files": 5, 1339 "created_tmp_tables": 6, 1340 "handler_commit": 720, 1341 "handler_delete": 8, 1342 "handler_prepare": 24, 1343 "handler_read_first": 50, 1344 "handler_read_key": 1914, 1345 "handler_read_next": 4303, 1346 "handler_read_prev": 0, 1347 "handler_read_rnd": 0, 1348 "handler_read_rnd_next": 4723, 1349 "handler_rollback": 1, 1350 "handler_savepoint": 0, 1351 "handler_savepoint_rollback": 0, 1352 "handler_update": 373, 1353 "handler_write": 1966, 1354 "innodb_buffer_pool_bytes_data": 17121280, 1355 "innodb_buffer_pool_bytes_dirty": 0, 1356 "innodb_buffer_pool_pages_data": 1045, 1357 "innodb_buffer_pool_pages_dirty": 0, 1358 "innodb_buffer_pool_pages_flushed": 361, 1359 "innodb_buffer_pool_pages_free": 7143, 1360 "innodb_buffer_pool_pages_misc": 4, 1361 "innodb_buffer_pool_pages_total": 8192, 1362 "innodb_buffer_pool_read_ahead": 0, 1363 "innodb_buffer_pool_read_ahead_evicted": 0, 1364 "innodb_buffer_pool_read_ahead_rnd": 0, 1365 "innodb_buffer_pool_read_requests": 16723, 1366 "innodb_buffer_pool_reads": 878, 1367 "innodb_buffer_pool_wait_free": 0, 1368 "innodb_buffer_pool_write_requests": 2377, 1369 "innodb_data_fsyncs": 255, 1370 "innodb_data_pending_fsyncs": 0, 1371 "innodb_data_pending_reads": 0, 1372 "innodb_data_pending_writes": 0, 1373 "innodb_data_read": 14453760, 1374 "innodb_data_reads": 899, 1375 "innodb_data_writes": 561, 1376 "innodb_data_written": 6128128, 1377 "innodb_log_waits": 0, 1378 "innodb_log_write_requests": 1062, 1379 "innodb_log_writes": 116, 1380 "innodb_os_log_fsyncs": 69, 1381 "innodb_os_log_pending_fsyncs": 0, 1382 "innodb_os_log_pending_writes": 0, 1383 "innodb_os_log_written": 147968, 1384 "innodb_row_lock_current_waits": 0, 1385 "innodb_rows_deleted": 0, 1386 "innodb_rows_inserted": 0, 1387 "innodb_rows_read": 0, 1388 "innodb_rows_updated": 0, 1389 "key_blocks_not_flushed": 0, 1390 "key_blocks_unused": 6698, 1391 "key_blocks_used": 0, 1392 "key_read_requests": 0, 1393 "key_reads": 0, 1394 "key_write_requests": 0, 1395 "key_writes": 0, 1396 "max_connections": 151, 1397 "max_used_connections": 2, 1398 "open_files": 8, 1399 "open_tables": 127, 1400 "opened_files": 8, 1401 "opened_tables": 208, 1402 "process_list_fetch_query_duration": 0, 1403 "process_list_longest_query_duration": 9, 1404 "process_list_queries_count_system": 0, 1405 "process_list_queries_count_user": 2, 1406 "queries": 27, 1407 "questions": 15, 1408 "seconds_behind_master_master1": 0, 1409 "seconds_behind_master_master2": 0, 1410 "select_full_join": 0, 1411 "select_full_range_join": 0, 1412 "select_range": 0, 1413 "select_range_check": 0, 1414 "select_scan": 12, 1415 "slave_io_running_master1": 1, 1416 "slave_io_running_master2": 1, 1417 "slave_sql_running_master1": 1, 1418 "slave_sql_running_master2": 1, 1419 "slow_queries": 0, 1420 "sort_merge_passes": 0, 1421 "sort_range": 0, 1422 "sort_scan": 0, 1423 "table_locks_immediate": 6, 1424 "table_locks_waited": 0, 1425 "table_open_cache": 4000, 1426 "table_open_cache_overflows": 0, 1427 "thread_cache_misses": 800, 1428 "threads_cached": 1, 1429 "threads_connected": 1, 1430 "threads_created": 2, 1431 "threads_running": 2, 1432 } 1433 1434 copyProcessListQueryDuration(mx, expected) 1435 require.Equal(t, expected, mx) 1436 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 1437 }, 1438 }, 1439 }, 1440 "Percona-Standalone[v8.0.29]: success on all queries": { 1441 { 1442 prepareMock: func(t *testing.T, m sqlmock.Sqlmock) { 1443 mockExpect(t, m, queryShowVersion, dataPerconaV8029Version) 1444 mockExpect(t, m, queryShowGlobalStatus, dataPerconaV8029GlobalStatus) 1445 mockExpect(t, m, queryShowGlobalVariables, dataPerconaV8029GlobalVariables) 1446 mockExpect(t, m, queryShowReplicaStatus, nil) 1447 mockExpect(t, m, queryShowUserStatistics, dataPerconaV8029UserStatistics) 1448 mockExpect(t, m, queryShowProcessListPS, dataPerconaV8029ProcessList) 1449 }, 1450 check: func(t *testing.T, my *MySQL) { 1451 mx := my.Collect() 1452 1453 expected := map[string]int64{ 1454 "aborted_connects": 1, 1455 "binlog_cache_disk_use": 0, 1456 "binlog_cache_use": 0, 1457 "binlog_stmt_cache_disk_use": 0, 1458 "binlog_stmt_cache_use": 0, 1459 "bytes_received": 682970, 1460 "bytes_sent": 33668405, 1461 "com_delete": 0, 1462 "com_insert": 0, 1463 "com_replace": 0, 1464 "com_select": 1687, 1465 "com_update": 0, 1466 "connection_errors_accept": 0, 1467 "connection_errors_internal": 0, 1468 "connection_errors_max_connections": 0, 1469 "connection_errors_peer_address": 0, 1470 "connection_errors_select": 0, 1471 "connection_errors_tcpwrap": 0, 1472 "connections": 13, 1473 "created_tmp_disk_tables": 1683, 1474 "created_tmp_files": 5, 1475 "created_tmp_tables": 5054, 1476 "handler_commit": 576, 1477 "handler_delete": 0, 1478 "handler_prepare": 0, 1479 "handler_read_first": 1724, 1480 "handler_read_key": 3439, 1481 "handler_read_next": 4147, 1482 "handler_read_prev": 0, 1483 "handler_read_rnd": 0, 1484 "handler_read_rnd_next": 2983285, 1485 "handler_rollback": 0, 1486 "handler_savepoint": 0, 1487 "handler_savepoint_rollback": 0, 1488 "handler_update": 317, 1489 "handler_write": 906501, 1490 "innodb_buffer_pool_bytes_data": 18399232, 1491 "innodb_buffer_pool_bytes_dirty": 49152, 1492 "innodb_buffer_pool_pages_data": 1123, 1493 "innodb_buffer_pool_pages_dirty": 3, 1494 "innodb_buffer_pool_pages_flushed": 205, 1495 "innodb_buffer_pool_pages_free": 7064, 1496 "innodb_buffer_pool_pages_misc": 5, 1497 "innodb_buffer_pool_pages_total": 8192, 1498 "innodb_buffer_pool_read_ahead": 0, 1499 "innodb_buffer_pool_read_ahead_evicted": 0, 1500 "innodb_buffer_pool_read_ahead_rnd": 0, 1501 "innodb_buffer_pool_read_requests": 109817, 1502 "innodb_buffer_pool_reads": 978, 1503 "innodb_buffer_pool_wait_free": 0, 1504 "innodb_buffer_pool_write_requests": 77412, 1505 "innodb_data_fsyncs": 50, 1506 "innodb_data_pending_fsyncs": 0, 1507 "innodb_data_pending_reads": 0, 1508 "innodb_data_pending_writes": 0, 1509 "innodb_data_read": 16094208, 1510 "innodb_data_reads": 1002, 1511 "innodb_data_writes": 288, 1512 "innodb_data_written": 3420160, 1513 "innodb_log_waits": 0, 1514 "innodb_log_write_requests": 651, 1515 "innodb_log_writes": 47, 1516 "innodb_os_log_fsyncs": 13, 1517 "innodb_os_log_pending_fsyncs": 0, 1518 "innodb_os_log_pending_writes": 0, 1519 "innodb_os_log_written": 45568, 1520 "innodb_row_lock_current_waits": 0, 1521 "innodb_rows_deleted": 0, 1522 "innodb_rows_inserted": 5055, 1523 "innodb_rows_read": 5055, 1524 "innodb_rows_updated": 0, 1525 "key_blocks_not_flushed": 0, 1526 "key_blocks_unused": 6698, 1527 "key_blocks_used": 0, 1528 "key_read_requests": 0, 1529 "key_reads": 0, 1530 "key_write_requests": 0, 1531 "key_writes": 0, 1532 "max_connections": 151, 1533 "max_used_connections": 3, 1534 "open_files": 2, 1535 "open_tables": 77, 1536 "opened_files": 2, 1537 "opened_tables": 158, 1538 "process_list_fetch_query_duration": 0, 1539 "process_list_longest_query_duration": 9, 1540 "process_list_queries_count_system": 0, 1541 "process_list_queries_count_user": 2, 1542 "queries": 6748, 1543 "questions": 6746, 1544 "select_full_join": 0, 1545 "select_full_range_join": 0, 1546 "select_range": 0, 1547 "select_range_check": 0, 1548 "select_scan": 8425, 1549 "slow_queries": 0, 1550 "sort_merge_passes": 0, 1551 "sort_range": 0, 1552 "sort_scan": 1681, 1553 "table_locks_immediate": 3371, 1554 "table_locks_waited": 0, 1555 "table_open_cache": 4000, 1556 "table_open_cache_overflows": 0, 1557 "thread_cache_misses": 2307, 1558 "threads_cached": 1, 1559 "threads_connected": 2, 1560 "threads_created": 3, 1561 "threads_running": 2, 1562 "userstats_netdata_access_denied": 0, 1563 "userstats_netdata_binlog_bytes_written": 0, 1564 "userstats_netdata_commit_transactions": 0, 1565 "userstats_netdata_cpu_time": 0, 1566 "userstats_netdata_denied_connections": 0, 1567 "userstats_netdata_empty_queries": 0, 1568 "userstats_netdata_lost_connections": 0, 1569 "userstats_netdata_other_commands": 1, 1570 "userstats_netdata_rollback_transactions": 0, 1571 "userstats_netdata_rows_fetched": 1, 1572 "userstats_netdata_rows_updated": 0, 1573 "userstats_netdata_select_commands": 1, 1574 "userstats_netdata_total_connections": 1, 1575 "userstats_netdata_update_commands": 0, 1576 "userstats_root_access_denied": 0, 1577 "userstats_root_binlog_bytes_written": 0, 1578 "userstats_root_commit_transactions": 0, 1579 "userstats_root_cpu_time": 151, 1580 "userstats_root_denied_connections": 1, 1581 "userstats_root_empty_queries": 36, 1582 "userstats_root_lost_connections": 0, 1583 "userstats_root_other_commands": 110, 1584 "userstats_root_rollback_transactions": 0, 1585 "userstats_root_rows_fetched": 1, 1586 "userstats_root_rows_updated": 0, 1587 "userstats_root_select_commands": 37, 1588 "userstats_root_total_connections": 2, 1589 "userstats_root_update_commands": 0, 1590 } 1591 1592 copyProcessListQueryDuration(mx, expected) 1593 require.Equal(t, expected, mx) 1594 ensureCollectedHasAllChartsDimsVarsIDs(t, my, mx) 1595 }, 1596 }, 1597 }, 1598 } 1599 1600 for name, test := range tests { 1601 t.Run(name, func(t *testing.T) { 1602 db, mock, err := sqlmock.New( 1603 sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual), 1604 ) 1605 require.NoError(t, err) 1606 my := New() 1607 my.db = db 1608 defer func() { _ = db.Close() }() 1609 1610 require.True(t, my.Init()) 1611 1612 for i, step := range test { 1613 t.Run(fmt.Sprintf("step[%d]", i), func(t *testing.T) { 1614 step.prepareMock(t, mock) 1615 step.check(t, my) 1616 }) 1617 } 1618 assert.NoError(t, mock.ExpectationsWereMet()) 1619 }) 1620 } 1621 } 1622 1623 func ensureCollectedHasAllChartsDimsVarsIDs(t *testing.T, mySQL *MySQL, collected map[string]int64) { 1624 for _, chart := range *mySQL.Charts() { 1625 if mySQL.isMariaDB { 1626 // https://mariadb.com/kb/en/server-status-variables/#connection_errors_accept 1627 if mySQL.version.LT(semver.Version{Major: 10, Minor: 0, Patch: 4}) && chart.ID == "connection_errors" { 1628 continue 1629 } 1630 } 1631 for _, dim := range chart.Dims { 1632 _, ok := collected[dim.ID] 1633 assert.Truef(t, ok, "collected metrics has no data for dim '%s' chart '%s'", dim.ID, chart.ID) 1634 } 1635 for _, v := range chart.Vars { 1636 _, ok := collected[v.ID] 1637 assert.Truef(t, ok, "collected metrics has no data for var '%s' chart '%s'", v.ID, chart.ID) 1638 } 1639 } 1640 } 1641 1642 func copyProcessListQueryDuration(dst, src map[string]int64) { 1643 if _, ok := dst["process_list_fetch_query_duration"]; !ok { 1644 return 1645 } 1646 if _, ok := src["process_list_fetch_query_duration"]; !ok { 1647 return 1648 } 1649 dst["process_list_fetch_query_duration"] = src["process_list_fetch_query_duration"] 1650 } 1651 1652 func mustMockRows(t *testing.T, data []byte) *sqlmock.Rows { 1653 rows, err := prepareMockRows(data) 1654 require.NoError(t, err) 1655 return rows 1656 } 1657 1658 func mockExpect(t *testing.T, mock sqlmock.Sqlmock, query string, rows []byte) { 1659 mock.ExpectQuery(query).WillReturnRows(mustMockRows(t, rows)).RowsWillBeClosed() 1660 } 1661 1662 func mockExpectErr(mock sqlmock.Sqlmock, query string) { 1663 mock.ExpectQuery(query).WillReturnError(fmt.Errorf("mock error (%s)", query)) 1664 } 1665 1666 func prepareMockRows(data []byte) (*sqlmock.Rows, error) { 1667 if len(data) == 0 { 1668 return sqlmock.NewRows(nil), nil 1669 } 1670 1671 r := bytes.NewReader(data) 1672 sc := bufio.NewScanner(r) 1673 1674 var numColumns int 1675 var rows *sqlmock.Rows 1676 1677 for sc.Scan() { 1678 s := strings.TrimSpace(strings.Trim(sc.Text(), "|")) 1679 switch { 1680 case s == "", 1681 strings.HasPrefix(s, "+"), 1682 strings.HasPrefix(s, "ft_boolean_syntax"): 1683 continue 1684 } 1685 1686 parts := strings.Split(s, "|") 1687 for i, v := range parts { 1688 parts[i] = strings.TrimSpace(v) 1689 } 1690 1691 if rows == nil { 1692 numColumns = len(parts) 1693 rows = sqlmock.NewRows(parts) 1694 continue 1695 } 1696 1697 if len(parts) != numColumns { 1698 return nil, fmt.Errorf("prepareMockRows(): columns != values (%d/%d)", numColumns, len(parts)) 1699 } 1700 1701 values := make([]driver.Value, len(parts)) 1702 for i, v := range parts { 1703 values[i] = v 1704 } 1705 rows.AddRow(values...) 1706 } 1707 1708 if rows == nil { 1709 return nil, errors.New("prepareMockRows(): nil rows result") 1710 } 1711 1712 return rows, sc.Err() 1713 }