584 lines
20 KiB
Go
584 lines
20 KiB
Go
// Copyright 2021 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pingcap/failpoint"
|
|
"github.com/pingcap/log"
|
|
"github.com/pingcap/tidb/config"
|
|
ddlutil "github.com/pingcap/tidb/ddl/util"
|
|
"github.com/pingcap/tidb/kv"
|
|
"github.com/pingcap/tidb/parser/model"
|
|
"github.com/pingcap/tidb/parser/mysql"
|
|
"github.com/pingcap/tidb/session"
|
|
"github.com/pingcap/tidb/sessionctx/variable"
|
|
"github.com/pingcap/tidb/testkit"
|
|
"github.com/pingcap/tidb/util/deadlockhistory"
|
|
"github.com/pingcap/tidb/util/versioninfo"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestPostSettings(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
ts.prepareData(t)
|
|
defer ts.stopServer(t)
|
|
se, err := session.CreateSession(ts.store)
|
|
require.NoError(t, err)
|
|
|
|
form := make(url.Values)
|
|
form.Set("log_level", "error")
|
|
form.Set("tidb_general_log", "1")
|
|
form.Set("tidb_enable_async_commit", "1")
|
|
form.Set("tidb_enable_1pc", "1")
|
|
resp, err := ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, zap.ErrorLevel, log.GetLevel())
|
|
require.Equal(t, "error", config.GetGlobalConfig().Log.Level)
|
|
require.True(t, variable.ProcessGeneralLog.Load())
|
|
val, err := se.GetSessionVars().GetGlobalSystemVar(context.Background(), variable.TiDBEnableAsyncCommit)
|
|
require.NoError(t, err)
|
|
require.Equal(t, variable.On, val)
|
|
val, err = se.GetSessionVars().GetGlobalSystemVar(context.Background(), variable.TiDBEnable1PC)
|
|
require.NoError(t, err)
|
|
require.Equal(t, variable.On, val)
|
|
|
|
form = make(url.Values)
|
|
form.Set("log_level", "fatal")
|
|
form.Set("tidb_general_log", "0")
|
|
form.Set("tidb_enable_async_commit", "0")
|
|
form.Set("tidb_enable_1pc", "0")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.False(t, variable.ProcessGeneralLog.Load())
|
|
require.Equal(t, zap.FatalLevel, log.GetLevel())
|
|
require.Equal(t, "fatal", config.GetGlobalConfig().Log.Level)
|
|
val, err = se.GetSessionVars().GetGlobalSystemVar(context.Background(), variable.TiDBEnableAsyncCommit)
|
|
require.NoError(t, err)
|
|
require.Equal(t, variable.Off, val)
|
|
val, err = se.GetSessionVars().GetGlobalSystemVar(context.Background(), variable.TiDBEnable1PC)
|
|
require.NoError(t, err)
|
|
require.Equal(t, variable.Off, val)
|
|
form.Set("log_level", os.Getenv("log_level"))
|
|
|
|
// test ddl_slow_threshold
|
|
form = make(url.Values)
|
|
form.Set("ddl_slow_threshold", "200")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, uint32(200), atomic.LoadUint32(&variable.DDLSlowOprThreshold))
|
|
|
|
// test check_mb4_value_in_utf8
|
|
db, err := sql.Open("mysql", ts.getDSN())
|
|
require.NoError(t, err)
|
|
defer func() {
|
|
err := db.Close()
|
|
require.NoError(t, err)
|
|
}()
|
|
dbt := testkit.NewDBTestKit(t, db)
|
|
|
|
dbt.MustExec("create database tidb_test;")
|
|
dbt.MustExec("use tidb_test;")
|
|
dbt.MustExec("drop table if exists t2;")
|
|
dbt.MustExec("create table t2(a varchar(100) charset utf8);")
|
|
form.Set("check_mb4_value_in_utf8", "1")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, true, config.GetGlobalConfig().Instance.CheckMb4ValueInUTF8.Load())
|
|
txn1, err := dbt.GetDB().Begin()
|
|
require.NoError(t, err)
|
|
_, err = txn1.Exec("insert t2 values (unhex('F0A48BAE'));")
|
|
require.Error(t, err)
|
|
err = txn1.Commit()
|
|
require.NoError(t, err)
|
|
|
|
// Disable CheckMb4ValueInUTF8.
|
|
form = make(url.Values)
|
|
form.Set("check_mb4_value_in_utf8", "0")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, false, config.GetGlobalConfig().Instance.CheckMb4ValueInUTF8.Load())
|
|
dbt.MustExec("insert t2 values (unhex('f09f8c80'));")
|
|
|
|
// test deadlock_history_capacity
|
|
deadlockhistory.GlobalDeadlockHistory.Resize(10)
|
|
for i := 0; i < 10; i++ {
|
|
deadlockhistory.GlobalDeadlockHistory.Push(dummyRecord())
|
|
}
|
|
form = make(url.Values)
|
|
form.Set("deadlock_history_capacity", "5")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 5, len(deadlockhistory.GlobalDeadlockHistory.GetAll()))
|
|
require.Equal(t, uint64(6), deadlockhistory.GlobalDeadlockHistory.GetAll()[0].ID)
|
|
require.Equal(t, uint64(10), deadlockhistory.GlobalDeadlockHistory.GetAll()[4].ID)
|
|
deadlockhistory.GlobalDeadlockHistory.Push(dummyRecord())
|
|
require.Equal(t, 5, len(deadlockhistory.GlobalDeadlockHistory.GetAll()))
|
|
require.Equal(t, uint64(7), deadlockhistory.GlobalDeadlockHistory.GetAll()[0].ID)
|
|
require.Equal(t, uint64(11), deadlockhistory.GlobalDeadlockHistory.GetAll()[4].ID)
|
|
form = make(url.Values)
|
|
form.Set("deadlock_history_capacity", "6")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
deadlockhistory.GlobalDeadlockHistory.Push(dummyRecord())
|
|
require.Equal(t, 6, len(deadlockhistory.GlobalDeadlockHistory.GetAll()))
|
|
require.Equal(t, uint64(7), deadlockhistory.GlobalDeadlockHistory.GetAll()[0].ID)
|
|
require.Equal(t, uint64(12), deadlockhistory.GlobalDeadlockHistory.GetAll()[5].ID)
|
|
|
|
// test deadlock_history_collect_retryable
|
|
form = make(url.Values)
|
|
form.Set("deadlock_history_collect_retryable", "true")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.True(t, config.GetGlobalConfig().PessimisticTxn.DeadlockHistoryCollectRetryable)
|
|
form = make(url.Values)
|
|
form.Set("deadlock_history_collect_retryable", "false")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.False(t, config.GetGlobalConfig().PessimisticTxn.DeadlockHistoryCollectRetryable)
|
|
form = make(url.Values)
|
|
form.Set("deadlock_history_collect_retryable", "123")
|
|
resp, err = ts.formStatus("/settings", form)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 400, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
|
|
// restore original value.
|
|
config.GetGlobalConfig().Instance.CheckMb4ValueInUTF8.Store(true)
|
|
}
|
|
|
|
func TestAllServerInfo(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
defer ts.stopServer(t)
|
|
resp, err := ts.fetchStatus("/info/all")
|
|
require.NoError(t, err)
|
|
defer func() { require.NoError(t, resp.Body.Close()) }()
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
decoder := json.NewDecoder(resp.Body)
|
|
|
|
clusterInfo := clusterServerInfo{}
|
|
err = decoder.Decode(&clusterInfo)
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, clusterInfo.IsAllServerVersionConsistent)
|
|
require.Equal(t, 1, clusterInfo.ServersNum)
|
|
|
|
store := ts.server.newTikvHandlerTool().Store.(kv.Storage)
|
|
do, err := session.GetDomain(store)
|
|
require.NoError(t, err)
|
|
ddl := do.DDL()
|
|
require.Equal(t, ddl.GetID(), clusterInfo.OwnerID)
|
|
serverInfo, ok := clusterInfo.AllServersInfo[ddl.GetID()]
|
|
require.Equal(t, true, ok)
|
|
|
|
cfg := config.GetGlobalConfig()
|
|
require.Equal(t, cfg.AdvertiseAddress, serverInfo.IP)
|
|
require.Equal(t, cfg.Status.StatusPort, serverInfo.StatusPort)
|
|
require.Equal(t, cfg.Lease, serverInfo.Lease)
|
|
require.Equal(t, mysql.ServerVersion, serverInfo.Version)
|
|
require.Equal(t, versioninfo.TiDBGitHash, serverInfo.GitHash)
|
|
require.Equal(t, ddl.GetID(), serverInfo.ID)
|
|
}
|
|
|
|
func TestRegionsFromMeta(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
defer ts.stopServer(t)
|
|
resp, err := ts.fetchStatus("/regions/meta")
|
|
require.NoError(t, err)
|
|
defer func() { require.NoError(t, resp.Body.Close()) }()
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
// Verify the resp body.
|
|
decoder := json.NewDecoder(resp.Body)
|
|
metas := make([]RegionMeta, 0)
|
|
err = decoder.Decode(&metas)
|
|
require.NoError(t, err)
|
|
for _, m := range metas {
|
|
require.True(t, m.ID != 0)
|
|
}
|
|
|
|
// test no panic
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/errGetRegionByIDEmpty", `return(true)`))
|
|
defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/errGetRegionByIDEmpty")) }()
|
|
resp1, err := ts.fetchStatus("/regions/meta")
|
|
require.NoError(t, err)
|
|
defer func() { require.NoError(t, resp1.Body.Close()) }()
|
|
}
|
|
|
|
func TestTiFlashReplica(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
ts.prepareData(t)
|
|
defer ts.stopServer(t)
|
|
|
|
db, err := sql.Open("mysql", ts.getDSN())
|
|
require.NoError(t, err)
|
|
defer func() {
|
|
err := db.Close()
|
|
require.NoError(t, err)
|
|
}()
|
|
dbt := testkit.NewDBTestKit(t, db)
|
|
|
|
defer func(originGC bool) {
|
|
if originGC {
|
|
ddlutil.EmulatorGCEnable()
|
|
} else {
|
|
ddlutil.EmulatorGCDisable()
|
|
}
|
|
}(ddlutil.IsEmulatorGCEnable())
|
|
|
|
// Disable emulator GC.
|
|
// Otherwise emulator GC will delete table record as soon as possible after execute drop table DDL.
|
|
ddlutil.EmulatorGCDisable()
|
|
gcTimeFormat := "20060102-15:04:05 -0700 MST"
|
|
timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat)
|
|
safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', ''),('tikv_gc_enable','true','')
|
|
ON DUPLICATE KEY
|
|
UPDATE variable_value = '%[1]s'`
|
|
// Set GC safe point and enable GC.
|
|
dbt.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop))
|
|
|
|
resp, err := ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder := json.NewDecoder(resp.Body)
|
|
var data []tableFlashReplicaInfo
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 0, len(data))
|
|
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount", `return(true)`))
|
|
defer func() {
|
|
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/infoschema/mockTiFlashStoreCount"))
|
|
}()
|
|
|
|
dbt.MustExec("use tidb")
|
|
dbt.MustExec("alter table test set tiflash replica 2 location labels 'a','b';")
|
|
|
|
resp, err = ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 1, len(data))
|
|
require.Equal(t, uint64(2), data[0].ReplicaCount)
|
|
require.Equal(t, "a,b", strings.Join(data[0].LocationLabels, ","))
|
|
require.Equal(t, false, data[0].Available)
|
|
|
|
resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(`{"id":184,"region_count":3,"flash_region_count":3}`)))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
body, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, "[schema:1146]Table which ID = 184 does not exist.", string(body))
|
|
|
|
tbl, err := ts.domain.InfoSchema().TableByName(model.NewCIStr("tidb"), model.NewCIStr("test"))
|
|
require.NoError(t, err)
|
|
req := fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, tbl.Meta().ID)
|
|
resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req)))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
body, err = io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, "", string(body))
|
|
|
|
resp, err = ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 1, len(data))
|
|
require.Equal(t, uint64(2), data[0].ReplicaCount)
|
|
require.Equal(t, "a,b", strings.Join(data[0].LocationLabels, ","))
|
|
require.Equal(t, true, data[0].Available)
|
|
|
|
// Should not take effect.
|
|
dbt.MustExec("alter table test set tiflash replica 2 location labels 'a','b';")
|
|
checkFunc := func() {
|
|
resp, err := ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 1, len(data))
|
|
require.Equal(t, uint64(2), data[0].ReplicaCount)
|
|
require.Equal(t, "a,b", strings.Join(data[0].LocationLabels, ","))
|
|
require.Equal(t, true, data[0].Available)
|
|
}
|
|
|
|
// Test for get dropped table tiflash replica info.
|
|
dbt.MustExec("drop table test")
|
|
checkFunc()
|
|
|
|
// Test unique table id replica info.
|
|
dbt.MustExec("flashback table test")
|
|
checkFunc()
|
|
dbt.MustExec("drop table test")
|
|
checkFunc()
|
|
dbt.MustExec("flashback table test")
|
|
checkFunc()
|
|
|
|
// Test for partition table.
|
|
dbt.MustExec("alter table pt set tiflash replica 2 location labels 'a','b';")
|
|
dbt.MustExec("alter table test set tiflash replica 0;")
|
|
resp, err = ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, 3, len(data))
|
|
require.Equal(t, uint64(2), data[0].ReplicaCount)
|
|
require.Equal(t, "a,b", strings.Join(data[0].LocationLabels, ","))
|
|
require.Equal(t, false, data[0].Available)
|
|
|
|
pid0 := data[0].ID
|
|
pid1 := data[1].ID
|
|
pid2 := data[2].ID
|
|
|
|
// Mock for partition 1 replica was available.
|
|
req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid1)
|
|
resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req)))
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
resp, err = ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 3, len(data))
|
|
require.Equal(t, false, data[0].Available)
|
|
require.Equal(t, true, data[1].Available)
|
|
require.Equal(t, false, data[2].Available)
|
|
|
|
// Mock for partition 0,2 replica was available.
|
|
req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid0)
|
|
resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req)))
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
req = fmt.Sprintf(`{"id":%d,"region_count":3,"flash_region_count":3}`, pid2)
|
|
resp, err = ts.postStatus("/tiflash/replica-deprecated", "application/json", bytes.NewBuffer([]byte(req)))
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
checkFunc = func() {
|
|
resp, err := ts.fetchStatus("/tiflash/replica-deprecated")
|
|
require.NoError(t, err)
|
|
decoder = json.NewDecoder(resp.Body)
|
|
err = decoder.Decode(&data)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Equal(t, 3, len(data))
|
|
require.Equal(t, true, data[0].Available)
|
|
require.Equal(t, true, data[1].Available)
|
|
require.Equal(t, true, data[2].Available)
|
|
}
|
|
|
|
// Test for get truncated table tiflash replica info.
|
|
dbt.MustExec("truncate table pt")
|
|
dbt.MustExec("alter table pt set tiflash replica 0;")
|
|
checkFunc()
|
|
}
|
|
|
|
func TestFailpointHandler(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
|
|
// start server without enabling failpoint integration
|
|
ts.startServer(t)
|
|
defer ts.stopServer(t)
|
|
resp, err := ts.fetchStatus("/fail/")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
ts.stopServer(t)
|
|
|
|
// enable failpoint integration and start server
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/enableTestAPI", "return"))
|
|
defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/enableTestAPI")) }()
|
|
ts.startServer(t)
|
|
resp, err = ts.fetchStatus("/fail/")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
b, err := io.ReadAll(resp.Body)
|
|
require.NoError(t, err)
|
|
require.True(t, strings.Contains(string(b), "github.com/pingcap/tidb/server/enableTestAPI=return"))
|
|
require.NoError(t, resp.Body.Close())
|
|
}
|
|
|
|
func TestTestHandler(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
|
|
// start server without enabling failpoint integration
|
|
ts.startServer(t)
|
|
defer ts.stopServer(t)
|
|
resp, err := ts.fetchStatus("/test")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
require.NoError(t, resp.Body.Close())
|
|
ts.stopServer(t)
|
|
|
|
// enable failpoint integration and start server
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/server/enableTestAPI", "return"))
|
|
defer func() { require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/server/enableTestAPI")) }()
|
|
ts.startServer(t)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/gc")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/resolvelock")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/resolvelock?safepoint=a")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/resolvelock?physical=1")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/resolvelock?physical=true")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
|
|
resp, err = ts.fetchStatus("/test/gc/resolvelock?safepoint=10000&physical=true")
|
|
require.NoError(t, err)
|
|
err = resp.Body.Close()
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
}
|
|
|
|
func TestServerInfo(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
defer ts.stopServer(t)
|
|
resp, err := ts.fetchStatus("/info")
|
|
require.NoError(t, err)
|
|
defer func() { require.NoError(t, resp.Body.Close()) }()
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
decoder := json.NewDecoder(resp.Body)
|
|
|
|
info := serverInfo{}
|
|
err = decoder.Decode(&info)
|
|
require.NoError(t, err)
|
|
|
|
cfg := config.GetGlobalConfig()
|
|
require.True(t, info.IsOwner)
|
|
require.Equal(t, cfg.AdvertiseAddress, info.IP)
|
|
require.Equal(t, cfg.Status.StatusPort, info.StatusPort)
|
|
require.Equal(t, cfg.Lease, info.Lease)
|
|
require.Equal(t, mysql.ServerVersion, info.Version)
|
|
require.Equal(t, versioninfo.TiDBGitHash, info.GitHash)
|
|
|
|
store := ts.server.newTikvHandlerTool().Store.(kv.Storage)
|
|
do, err := session.GetDomain(store)
|
|
require.NoError(t, err)
|
|
d := do.DDL()
|
|
require.Equal(t, d.GetID(), info.ID)
|
|
}
|
|
|
|
func TestGetSchemaStorage(t *testing.T) {
|
|
ts := createBasicHTTPHandlerTestSuite()
|
|
ts.startServer(t)
|
|
ts.prepareData(t)
|
|
defer ts.stopServer(t)
|
|
|
|
do := ts.domain
|
|
h := do.StatsHandle()
|
|
do.SetStatsUpdating(true)
|
|
|
|
tk := testkit.NewTestKit(t, ts.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t")
|
|
tk.MustExec("create table t (c int, d int, e char(5), index idx(e))")
|
|
tk.MustExec(`insert into t(c, d, e) values(1, 2, "c"), (2, 3, "d"), (3, 4, "e")`)
|
|
h.FlushStats()
|
|
|
|
resp, err := ts.fetchStatus("/schema_storage/test")
|
|
require.NoError(t, err)
|
|
decoder := json.NewDecoder(resp.Body)
|
|
var tables []*schemaTableStorage
|
|
err = decoder.Decode(&tables)
|
|
require.NoError(t, err)
|
|
require.NoError(t, resp.Body.Close())
|
|
require.Len(t, tables, 1)
|
|
expects := []string{`t`}
|
|
names := make([]string, len(tables))
|
|
for i, v := range tables {
|
|
names[i] = v.TableName
|
|
}
|
|
|
|
sort.Strings(names)
|
|
require.Equal(t, expects, names)
|
|
require.Equal(t, []int64{3, 18, 54, 0, 6, 0}, []int64{
|
|
tables[0].TableRows,
|
|
tables[0].AvgRowLength,
|
|
tables[0].DataLength,
|
|
tables[0].MaxDataLength,
|
|
tables[0].IndexLength,
|
|
tables[0].DataFree,
|
|
})
|
|
}
|