123 lines
2.9 KiB
Go
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
|
|
}
|