Files
tidb/config/config_handler_test.go

250 lines
8.4 KiB
Go

// Copyright 2020 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,
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"context"
"fmt"
"os"
"path"
"reflect"
"sync"
"sync/atomic"
"time"
. "github.com/pingcap/check"
"github.com/pingcap/kvproto/pkg/configpb"
"github.com/pingcap/pd/v4/client"
)
type mockPDConfigClient struct {
status *configpb.Status
version *configpb.Version
confContent atomic.Value
err error
}
var mockPDConfigClient0 = new(mockPDConfigClient)
var newMockPDConfigClientErr error
func newMockPDConfigClient([]string, pd.SecurityOption) (pd.ConfigClient, error) {
return mockPDConfigClient0, newMockPDConfigClientErr
}
func (mc *mockPDConfigClient) GetClusterID(ctx context.Context) uint64 {
return 0
}
func (mc *mockPDConfigClient) Create(ctx context.Context, v *configpb.Version, component, componentID, config string) (*configpb.Status, *configpb.Version, string, error) {
return mc.status, mc.version, mc.confContent.Load().(string), mc.err
}
func (mc *mockPDConfigClient) Get(ctx context.Context, v *configpb.Version, component, componentID string) (*configpb.Status, *configpb.Version, string, error) {
return mc.status, mc.version, mc.confContent.Load().(string), mc.err
}
func (mc *mockPDConfigClient) Update(ctx context.Context, v *configpb.Version, kind *configpb.ConfigKind, entries []*configpb.ConfigEntry) (*configpb.Status, *configpb.Version, error) {
return nil, nil, nil
}
func (mc *mockPDConfigClient) Delete(ctx context.Context, v *configpb.Version, kind *configpb.ConfigKind) (*configpb.Status, error) {
return nil, nil
}
func (mc *mockPDConfigClient) Close() {}
func (s *testConfigSuite) TestConstantConfHandler(c *C) {
conf := defaultConf
conf.Store = "mock"
confPath := path.Join(os.TempDir(), "test-conf-path.toml")
ch, err := NewConfHandler(confPath, &conf, nil, nil)
c.Assert(err, IsNil)
_, ok := ch.(*constantConfHandler)
c.Assert(ok, IsTrue)
c.Assert(ch.GetConfig(), Equals, &conf)
}
func (s *testConfigSuite) TestPDConfHandler(c *C) {
conf := defaultConf
// wrong path
confPath := path.Join(os.TempDir(), "test-conf-path.toml")
conf.Store = "WRONGPATH"
conf.Path = "WRONGPATH"
_, err := newPDConfHandler(confPath, &conf, nil, newMockPDConfigClient)
c.Assert(err, NotNil)
// error when creating PD config client
conf.Store = "tikv"
conf.Path = "node1:2379"
newMockPDConfigClientErr = fmt.Errorf("")
_, err = newPDConfHandler(confPath, &conf, nil, newMockPDConfigClient)
c.Assert(err, NotNil)
// error when registering
newMockPDConfigClientErr = nil
mockPDConfigClient0.err = fmt.Errorf("")
mockPDConfigClient0.confContent.Store("")
ch, err := newPDConfHandler(confPath, &conf, nil, newMockPDConfigClient)
c.Assert(err, IsNil) // the local config will be used
ch.Close()
// wrong response when registering
mockPDConfigClient0.err = nil
mockPDConfigClient0.status = &configpb.Status{Code: configpb.StatusCode_UNKNOWN}
ch, err = newPDConfHandler(confPath, &conf, nil, newMockPDConfigClient)
c.Assert(err, IsNil)
ch.Close()
// create client successfully
mockPDConfigClient0.status.Code = configpb.StatusCode_WRONG_VERSION
content, _ := encodeConfig(&conf)
mockPDConfigClient0.confContent.Store(content)
ch, err = newPDConfHandler(confPath, &conf, nil, newMockPDConfigClient)
c.Assert(err, IsNil)
ch.Close()
// update log level
wg := sync.WaitGroup{}
wg.Add(1)
mockReloadFunc := func(oldConf, newConf *Config) {
c.Assert(oldConf.Performance.MaxMemory, Equals, uint64(233))
c.Assert(newConf.Performance.MaxMemory, Equals, uint64(123))
wg.Done()
}
conf.Performance.MaxMemory = 233
ch, err = newPDConfHandler(confPath, &conf, mockReloadFunc, newMockPDConfigClient)
c.Assert(err, IsNil)
ch.interval = time.Second
newConf := conf
newConf.Performance.MaxMemory = 123
newContent, _ := encodeConfig(&newConf)
mockPDConfigClient0.confContent.Store(newContent)
ch.Start()
wg.Wait()
c.Assert(ch.GetConfig().Performance.MaxMemory, Equals, uint64(123))
ch.Close()
}
func (s *testConfigSuite) TestEnableDynamicConfig(c *C) {
conf := &defaultConf
confPath := path.Join(os.TempDir(), "test-conf-path.toml")
for _, store := range []string{"tikv", "mocktikv"} {
for _, enable := range []bool{true, false} {
conf.Store = store
conf.EnableDynamicConfig = enable
ch, err := NewConfHandler(confPath, conf, nil, newMockPDConfigClient)
c.Assert(err, IsNil)
if store == "tikv" && enable == true {
c.Assert(fmt.Sprintf("%v", reflect.TypeOf(ch)), Equals, "*config.pdConfHandler")
} else {
c.Assert(fmt.Sprintf("%v", reflect.TypeOf(ch)), Equals, "*config.constantConfHandler")
}
}
}
}
func (s *testConfigSuite) TestDynamicConfigItems(c *C) {
tmCh := make(chan time.Time)
tmAfter := func(d time.Duration) <-chan time.Time {
return tmCh
}
initConf, err := CloneConf(&defaultConf)
c.Assert(err, IsNil)
initConf.Store = "tikv"
initConf.Path = "node1:2379"
newMockPDConfigClientErr = nil
initContent, err := encodeConfig(initConf)
c.Assert(err, IsNil)
mockPDConfigClient0.err = nil
mockPDConfigClient0.confContent.Store(initContent)
mockPDConfigClient0.status = &configpb.Status{Code: configpb.StatusCode_WRONG_VERSION}
cnt := 0
var registerWg, reloadWg sync.WaitGroup
registerWg.Add(1)
reloadWg.Add(1)
mockReloadFunc := func(oldConf, newConf *Config) {
if cnt == 0 { // register
newContent, err := encodeConfig(newConf)
c.Assert(err, IsNil)
c.Assert(newContent, Equals, initContent) // no change now
registerWg.Done()
} else if cnt == 1 {
c.Assert(newConf.Performance.MaxProcs, Equals, uint(2333))
c.Assert(newConf.Performance.MaxMemory, Equals, uint64(2333))
c.Assert(newConf.Performance.CrossJoin, Equals, false)
c.Assert(newConf.Performance.FeedbackProbability, Equals, 0.2333)
c.Assert(newConf.Performance.QueryFeedbackLimit, Equals, uint(2333))
c.Assert(newConf.Performance.PseudoEstimateRatio, Equals, 0.2333)
c.Assert(newConf.Performance.StmtCountLimit, Equals, uint(2333))
c.Assert(newConf.Performance.TCPKeepAlive, Equals, true)
c.Assert(newConf.OOMAction, Equals, "cancel")
c.Assert(newConf.MemQuotaQuery, Equals, int64(2333))
c.Assert(newConf.TiKVClient.StoreLimit, Equals, int64(2333))
c.Assert(newConf.Log.Level, Equals, "error")
c.Assert(newConf.Log.SlowThreshold, Equals, uint64(2333))
c.Assert(newConf.Log.QueryLogMaxLen, Equals, uint64(2333))
c.Assert(newConf.Log.ExpensiveThreshold, Equals, uint(2333))
c.Assert(newConf.CheckMb4ValueInUTF8, Equals, false)
c.Assert(newConf.EnableStreaming, Equals, true)
c.Assert(newConf.TxnLocalLatches.Capacity, Equals, uint(2333))
c.Assert(newConf.PreparedPlanCache.Enabled, Equals, true)
c.Assert(newConf.CompatibleKillQuery, Equals, true)
c.Assert(newConf.TreatOldVersionUTF8AsUTF8MB4, Equals, true)
c.Assert(newConf.OpenTracing.Enable, Equals, true)
reloadWg.Done()
}
cnt++
}
ch, err := newPDConfHandler("", initConf, mockReloadFunc, newMockPDConfigClient)
c.Assert(err, IsNil)
ch.timeAfter = tmAfter
ch.Start()
registerWg.Wait() // wait for register
// test all dynamic config items
newConf, err := CloneConf(&defaultConf)
c.Assert(err, IsNil)
newConf.Performance.MaxProcs = 2333
newConf.Performance.MaxMemory = 2333
newConf.Performance.CrossJoin = false
newConf.Performance.FeedbackProbability = 0.2333
newConf.Performance.QueryFeedbackLimit = 2333
newConf.Performance.PseudoEstimateRatio = 0.2333
newConf.Performance.StmtCountLimit = 2333
newConf.Performance.TCPKeepAlive = true
newConf.OOMAction = "cancel"
newConf.MemQuotaQuery = 2333
newConf.TiKVClient.StoreLimit = 2333
newConf.Log.Level = "error"
newConf.Log.SlowThreshold = 2333
newConf.Log.QueryLogMaxLen = 2333
newConf.Log.ExpensiveThreshold = 2333
newConf.CheckMb4ValueInUTF8 = false
newConf.EnableStreaming = true
newConf.TxnLocalLatches.Capacity = 2333
newConf.PreparedPlanCache.Enabled = true
newConf.CompatibleKillQuery = true
newConf.TreatOldVersionUTF8AsUTF8MB4 = true
newConf.OpenTracing.Enable = true
newContent, err := encodeConfig(newConf)
c.Assert(err, IsNil)
mockPDConfigClient0.confContent.Store(newContent)
tmCh <- time.Now()
reloadWg.Wait()
ch.Close()
}