Files
tidb/br/pkg/task/show/cmd_test.go
2024-01-29 07:21:29 +00:00

212 lines
5.8 KiB
Go

// Copyright 2023 PingCAP, Inc. Licensed under Apache-2.0.
package show_test
import (
"bytes"
"context"
"embed"
"fmt"
"io"
"io/fs"
"os"
"path"
"strconv"
"strings"
"testing"
"github.com/pingcap/errors"
backuppb "github.com/pingcap/kvproto/pkg/brpb"
"github.com/pingcap/kvproto/pkg/encryptionpb"
"github.com/pingcap/tidb/br/pkg/task/show"
"github.com/pingcap/tidb/pkg/testkit"
"github.com/stretchr/testify/require"
)
var (
//go:embed testdata/full-schema.meta
FullMeta []byte
//go:embed testdata/v2/*
V2ManyTables embed.FS
//go:embed testdata/v2-enc/*
V2Encrypted embed.FS
)
func tempBackupDir(t *testing.T) string {
req := require.New(t)
tempBackup := path.Join(os.TempDir(), strconv.Itoa(os.Getpid()), t.Name())
err := os.MkdirAll(tempBackup, 0o755)
req.NoError(err)
t.Cleanup(func() { _ = os.RemoveAll(tempBackup) })
return tempBackup
}
func TestFull(t *testing.T) {
req := require.New(t)
tempBackup := tempBackupDir(t)
metaPath := path.Join(tempBackup, "backupmeta")
err := os.WriteFile(metaPath, FullMeta, 0o444)
req.NoError(err)
cfg := show.Config{
Storage: fmt.Sprintf("local://%s", tempBackup),
Cipher: backuppb.CipherInfo{
CipherType: encryptionpb.EncryptionMethod_PLAINTEXT,
},
}
ctx := context.Background()
exec, err := show.CreateExec(ctx, cfg)
req.NoError(err)
items, err := exec.Read(ctx)
req.NoError(err)
req.EqualValues(items.ClusterID, 7211076907329653533)
req.EqualValues(items.ClusterVersion, "\"7.1.0-alpha\"\n")
req.EqualValues(items.EndVersion, 440689413714870273)
tableNames := make([]string, 0, len(items.Tables))
for _, tbl := range items.Tables {
req.Equal(tbl.DBName, "tpcc")
tableNames = append(tableNames, tbl.TableName)
}
req.ElementsMatch(tableNames, []string{
"customer",
"district",
"history",
"item",
"new_order",
"order_line",
"orders",
"stock",
"warehouse",
})
}
func TestV2AndSmallTables(t *testing.T) {
req := require.New(t)
tempBackup := tempBackupDir(t)
req.NoError(cloneFS(V2ManyTables, "testdata/v2", tempBackup))
cfg := show.Config{
Storage: fmt.Sprintf("local://%s", tempBackup),
Cipher: backuppb.CipherInfo{
CipherType: encryptionpb.EncryptionMethod_PLAINTEXT,
},
}
ctx := context.Background()
exec, err := show.CreateExec(ctx, cfg)
req.NoError(err)
items, err := exec.Read(ctx)
req.NoError(err)
req.Len(items.Tables, 500)
req.EqualValues(items.ClusterID, 7211076907329653533)
req.EqualValues(items.EndVersion, 440691270926467074)
}
func TestV2Encrypted(t *testing.T) {
req := require.New(t)
tempBackup := tempBackupDir(t)
req.NoError(cloneFS(V2Encrypted, "testdata/v2-enc", tempBackup))
cfg := show.Config{
Storage: fmt.Sprintf("local://%s", tempBackup),
Cipher: backuppb.CipherInfo{
CipherType: encryptionpb.EncryptionMethod_AES256_CTR,
CipherKey: bytes.Repeat([]byte{0x42}, 32),
},
}
ctx := context.Background()
exec, err := show.CreateExec(ctx, cfg)
req.NoError(err)
items, err := exec.Read(ctx)
req.NoError(err)
req.EqualValues(items.ClusterID, 7211076907329653533)
req.EqualValues(items.ClusterVersion, "\"7.1.0-alpha\"\n")
tableNames := make([]string, 0, len(items.Tables))
for _, tbl := range items.Tables {
req.Equal(tbl.DBName, "tpcc")
tableNames = append(tableNames, tbl.TableName)
}
req.ElementsMatch(tableNames, []string{
"customer",
"district",
"history",
"item",
"new_order",
"order_line",
"orders",
"stock",
"warehouse",
})
}
func cloneFS(f fs.FS, base string, target string) error {
return fs.WalkDir(f, base, func(p string, d fs.DirEntry, err error) error {
rel := strings.TrimPrefix(p, base)
if err != nil {
return errors.Trace(err)
}
if d.IsDir() {
return nil
}
tgt := path.Join(target, rel)
dst, err := os.Create(tgt)
if err != nil {
return errors.Annotatef(err, "failed to create target item %s", tgt)
}
src, err := f.Open(p)
if err != nil {
return errors.Annotatef(err, "failed to open %s", p)
}
_, err = io.Copy(dst, src)
return errors.Annotate(err, "failed to copy")
})
}
func TestShowViaSQL(t *testing.T) {
req := require.New(t)
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tempBackup := tempBackupDir(t)
metaPath := path.Join(tempBackup, "backupmeta")
err := os.WriteFile(metaPath, FullMeta, 0o444)
req.NoError(err)
tk.MustExec("set @@time_zone='+08:00'")
res := tk.MustQuery(fmt.Sprintf("SHOW BACKUP METADATA FROM 'local://%s'", tempBackup))
fmt.Printf("%#v", res.Sort().Rows())
res.Sort().Check([][]any{
{"tpcc", "customer", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "district", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "history", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "item", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "new_order", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "order_line", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "orders", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "stock", "0", "0", "<nil>", "2023-04-10 11:18:21"},
{"tpcc", "warehouse", "0", "0", "<nil>", "2023-04-10 11:18:21"},
})
// Test result in different time_zone
tk.MustExec("set @@time_zone='-08:00'")
res = tk.MustQuery(fmt.Sprintf("SHOW BACKUP METADATA FROM 'local://%s'", tempBackup))
fmt.Printf("%#v", res.Sort().Rows())
res.Sort().Check([][]any{
{"tpcc", "customer", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "district", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "history", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "item", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "new_order", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "order_line", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "orders", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "stock", "0", "0", "<nil>", "2023-04-09 19:18:21"},
{"tpcc", "warehouse", "0", "0", "<nil>", "2023-04-09 19:18:21"},
})
}