Files
2026-09-21 16:46:55 +08:00

123 lines
2.9 KiB
Go

package mysqlserver
import (
"bytes"
"testing"
"mysql-tunnel/internal/navicat"
)
func TestLenencInt(t *testing.T) {
cases := []uint64{0, 1, 250, 251, 0xffff, 0x10000, 1 << 32}
for _, n := range cases {
enc := appendLenencInt(nil, n)
got, _, err := readLenencInt(enc, 0)
if err != nil || got != n {
t.Fatalf("n=%d got=%d err=%v", n, got, err)
}
}
}
func TestOKERRPackets(t *testing.T) {
ok := encodeOK(3, 9, serverStatusAutocommit, 0)
if ok[0] != markerOK {
t.Fatal("ok header")
}
n, off, err := readLenencInt(ok, 1)
if err != nil || n != 3 {
t.Fatal(n, err)
}
id, _, err := readLenencInt(ok, off)
if err != nil || id != 9 {
t.Fatal(id, err)
}
er := encodeERR(1064, "syntax")
if er[0] != markerERR || er[1] != 0x28 || er[2] != 0x04 {
t.Fatalf("%x", er)
}
if !bytes.Contains(er, []byte("syntax")) {
t.Fatal(string(er))
}
}
func TestNativePasswordRoundtrip(t *testing.T) {
scramble := bytes.Repeat([]byte{3}, 20)
tok := nativePasswordToken("123456", scramble)
if !verifyNativePassword("123456", scramble, tok) {
t.Fatal("should match")
}
if verifyNativePassword("wrong", scramble, tok) {
t.Fatal("should fail")
}
if !verifyNativePassword("", scramble, nil) {
t.Fatal("empty")
}
}
func TestHandshakeBuildParseResponse(t *testing.T) {
scramble := bytes.Repeat([]byte{7}, 20)
hs := buildHandshake(42, scramble)
if hs[0] != ProtocolVersion {
t.Fatal("proto")
}
if !bytes.Contains(hs, []byte(ServerVersion)) {
t.Fatal("version")
}
if !bytes.Contains(hs, []byte(AuthPluginNative)) {
t.Fatal("plugin")
}
token := nativePasswordToken("p", scramble)
resp := buildClientAuth("root", token, "app", clientProtocol41|clientSecureConnection|clientPluginAuth|clientConnectWithDB|clientPluginAuthLenencClientData)
hr, err := parseHandshakeResponse(resp)
if err != nil {
t.Fatal(err)
}
if hr.Username != "root" || hr.Database != "app" || !bytes.Equal(hr.Auth, token) {
t.Fatalf("%+v", hr)
}
}
func TestTextRowNULLAndBigint(t *testing.T) {
row := encodeTextRow([]navicat.Cell{
{Null: true},
{Bytes: []byte("18446744073709551615")},
{Bytes: []byte("1.50")},
{Bytes: []byte("你好")},
})
if row[0] != markerNull {
t.Fatal("null marker")
}
off := 1
b, off, err := readLenencString(row, off)
if err != nil || string(b) != "18446744073709551615" {
t.Fatal(string(b), err)
}
b, off, err = readLenencString(row, off)
if string(b) != "1.50" {
t.Fatal(string(b))
}
b, _, err = readLenencString(row, off)
if string(b) != "你好" {
t.Fatal(string(b))
}
}
func buildClientAuth(user string, token []byte, db string, caps uint32) []byte {
b := appendU32(nil, caps)
b = appendU32(b, MaxPacketSize)
b = append(b, charsetUTF8MB4)
b = append(b, make([]byte, 23)...)
b = appendNUL(b, user)
b = appendLenencInt(b, uint64(len(token)))
b = append(b, token...)
if caps&clientConnectWithDB != 0 {
b = appendNUL(b, db)
}
if caps&clientPluginAuth != 0 {
b = appendNUL(b, AuthPluginNative)
}
return b
}