refactor print_replay to improve unprocessable packet test creation
This commit is contained in:
@@ -4,12 +4,12 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/admin-else/strom/proto_generated/v1_21_8"
|
generated "github.com/admin-else/strom/proto_generated/%v"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error: %v
|
// Error: %v
|
||||||
func TestFailedPacket%10X(t *testing.T) {
|
func TestFailedPacket%10X(t *testing.T) {
|
||||||
p := v1_21_8.Play%vPacket{}
|
p := &generated.%v{}
|
||||||
b := bytes.NewBuffer(%#v)
|
b := bytes.NewBuffer(%#v)
|
||||||
err := p.Decode(b)
|
err := p.Decode(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,13 +5,16 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/data"
|
||||||
"github.com/admin-else/strom/proto"
|
"github.com/admin-else/strom/proto"
|
||||||
"github.com/admin-else/strom/proto_base"
|
"github.com/admin-else/strom/proto_base"
|
||||||
)
|
)
|
||||||
@@ -20,13 +23,13 @@ var (
|
|||||||
cmd = flag.NewFlagSet("print-replay", flag.ContinueOnError)
|
cmd = flag.NewFlagSet("print-replay", flag.ContinueOnError)
|
||||||
FileFlag = cmd.String("file", "", "The tmcpr file to print")
|
FileFlag = cmd.String("file", "", "The tmcpr file to print")
|
||||||
ProtocolVersion = cmd.Int("protocol", -1, "The protocol version")
|
ProtocolVersion = cmd.Int("protocol", -1, "The protocol version")
|
||||||
CreateTestsPath = cmd.String("create-tests", "", "The path to create tests from failed packets, if empty no tests will be created")
|
CreateTestsPath = cmd.String("create-tests", "", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed failed_packet.go.tmpl
|
//go:embed failed_packet.go.tmpl
|
||||||
var TestSrcF string
|
var TestSrcF string
|
||||||
|
|
||||||
func SaveUnCodeAbleAsTest(d proto_base.Direction, packet *proto.UnCodablePacket) {
|
func SaveUnCodeAbleAsTest(packet *proto.UnCodablePacket) {
|
||||||
hUntrimmed := sha256.Sum256(packet.Data)
|
hUntrimmed := sha256.Sum256(packet.Data)
|
||||||
h := hUntrimmed[:8]
|
h := hUntrimmed[:8]
|
||||||
f, err := os.Create(fmt.Sprintf(*CreateTestsPath+"/%v_%10x_test.go", len(packet.Data), h))
|
f, err := os.Create(fmt.Sprintf(*CreateTestsPath+"/%v_%10x_test.go", len(packet.Data), h))
|
||||||
@@ -34,9 +37,15 @@ func SaveUnCodeAbleAsTest(d proto_base.Direction, packet *proto.UnCodablePacket)
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret, err := data.LookUpVersionByProtocolVersion(packet.Info.ProtocolVersion)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
goPackage := "v" + strings.ReplaceAll(ret.MinecraftVersion, ".", "_")
|
||||||
|
|
||||||
//goland:noinspection GoUnhandledErrorResult
|
//goland:noinspection GoUnhandledErrorResult
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
_, err = fmt.Fprintf(f, TestSrcF, packet.Err, h, d.Opposite(), packet.Data)
|
_, err = fmt.Fprintf(f, TestSrcF, goPackage, packet.Err, h, reflect.TypeOf(packet.Info.Type).Elem().Name(), packet.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -55,26 +64,35 @@ func UnpackPacket(r io.Reader) (packet proto_base.EncodeDecodeAble, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
_, err = io.CopyN(b, r, int64(length))
|
// Read the packet data into a byte slice
|
||||||
|
packetData := make([]byte, length)
|
||||||
|
_, err = io.ReadFull(r, packetData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use bytes.Reader instead of bytes.Buffer
|
||||||
|
b := bytes.NewReader(packetData)
|
||||||
|
|
||||||
packetId, err := proto_base.DecodeVarInt(b)
|
packetId, err := proto_base.DecodeVarInt(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate position after reading the packet ID
|
||||||
|
// indexafterid represents how many bytes we've read so far
|
||||||
|
indexafterid := int(b.Size()) - int(b.Len())
|
||||||
|
|
||||||
i, ok := proto.LookUpTypeByPacketInfo(proto_base.ToClient, state, packetId, int32(*ProtocolVersion))
|
i, ok := proto.LookUpTypeByPacketInfo(proto_base.ToClient, state, packetId, int32(*ProtocolVersion))
|
||||||
if !ok {
|
if !ok {
|
||||||
packet = &proto.UnCodablePacket{Err: proto.BadPacketIdErr, Data: b.Bytes(), Direction: proto_base.ToClient}
|
packet = &proto.UnCodablePacket{Err: proto.BadPacketIdErr, Data: packetData, Info: i}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
packet = reflect.New(reflect.TypeOf(i.Type).Elem()).Interface().(proto_base.EncodeDecodeAble)
|
packet = reflect.New(reflect.TypeOf(i.Type).Elem()).Interface().(proto_base.EncodeDecodeAble)
|
||||||
err = packet.Decode(b)
|
err = packet.Decode(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
packet = &proto.UnCodablePacket{Err: err, Data: b.Bytes(), Direction: proto_base.ToClient}
|
packet = &proto.UnCodablePacket{Err: err, Data: packetData[indexafterid:], Info: i}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch i.Name {
|
switch i.Name {
|
||||||
@@ -85,7 +103,6 @@ func UnpackPacket(r io.Reader) (packet proto_base.EncodeDecodeAble, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(args []string) (err error) {
|
func Run(args []string) (err error) {
|
||||||
err = cmd.Parse(args)
|
err = cmd.Parse(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,17 +120,28 @@ func Run(args []string) (err error) {
|
|||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
var totalPackets, failedPackets int
|
||||||
for {
|
for {
|
||||||
var packet proto_base.EncodeDecodeAble
|
var packet proto_base.EncodeDecodeAble
|
||||||
packet, err = UnpackPacket(f)
|
packet, err = UnpackPacket(f)
|
||||||
unCodablePacket, ok := packet.(*proto.UnCodablePacket)
|
unCodablePacket, ok := packet.(*proto.UnCodablePacket)
|
||||||
if ok && *CreateTestsPath != "" {
|
if ok {
|
||||||
SaveUnCodeAbleAsTest(proto_base.ToClient, unCodablePacket)
|
if *CreateTestsPath != "" {
|
||||||
|
SaveUnCodeAbleAsTest(unCodablePacket)
|
||||||
|
}
|
||||||
|
failedPackets++
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
fmt.Println(err)
|
||||||
}
|
} else {
|
||||||
fmt.Printf("Packet: %#v\n", packet)
|
fmt.Printf("Packet: %#v\n", packet)
|
||||||
}
|
}
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
totalPackets++
|
||||||
|
}
|
||||||
|
fmt.Printf("Total packets: %d, failed packets: %d, %%failed: %.2f%%\n", totalPackets, failedPackets, float64(failedPackets)/float64(totalPackets)*100)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -43,7 +43,7 @@ var EarliestVersion = proto_generated.SupportedVersions[0]
|
|||||||
type UnCodablePacket struct {
|
type UnCodablePacket struct {
|
||||||
Err error
|
Err error
|
||||||
Data []byte
|
Data []byte
|
||||||
Direction proto_base.Direction
|
Info proto_base.PacketInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UnCodablePacket) Encode(w io.Writer) (err error) {
|
func (u *UnCodablePacket) Encode(w io.Writer) (err error) {
|
||||||
@@ -242,7 +242,7 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
|
|||||||
|
|
||||||
i, ok := LookUpTypeByPacketInfo(c.Actor.ReceiveDirection(), c.State(), id, c.ProtocolVersion)
|
i, ok := LookUpTypeByPacketInfo(c.Actor.ReceiveDirection(), c.State(), id, c.ProtocolVersion)
|
||||||
if !ok {
|
if !ok {
|
||||||
packet = &UnCodablePacket{Err: BadPacketIdErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
packet = &UnCodablePacket{Err: BadPacketIdErr, Data: packetBytes, Info: i}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
packet = reflect.New(reflect.TypeOf(i.Type).Elem()).Interface().(proto_base.EncodeDecodeAble)
|
packet = reflect.New(reflect.TypeOf(i.Type).Elem()).Interface().(proto_base.EncodeDecodeAble)
|
||||||
@@ -250,18 +250,18 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
|
|||||||
slices.ContainsFunc(c.DebugPrintPackets, func(s string) bool { return strings.Contains(i.Name, s) })
|
slices.ContainsFunc(c.DebugPrintPackets, func(s string) bool { return strings.Contains(i.Name, s) })
|
||||||
isListenerRegistered := c.IsTypeRegistered(reflect.TypeOf(packet))
|
isListenerRegistered := c.IsTypeRegistered(reflect.TypeOf(packet))
|
||||||
if !isListenerRegistered && !debugPrint {
|
if !isListenerRegistered && !debugPrint {
|
||||||
packet = &UnCodablePacket{Err: NoHandlerRegisteredErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
packet = &UnCodablePacket{Err: NoHandlerRegisteredErr, Data: packetBytes, Info: i}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = packet.Decode(b)
|
err = packet.Decode(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
packet = &UnCodablePacket{Err: err, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
packet = &UnCodablePacket{Err: err, Data: packetBytes, Info: i}
|
||||||
err = nil
|
err = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b.Len() != 0 {
|
if b.Len() != 0 {
|
||||||
err = nil
|
err = nil
|
||||||
packet = &UnCodablePacket{Err: PacketNotFullyDecodedErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
packet = &UnCodablePacket{Err: PacketNotFullyDecodedErr, Data: packetBytes, Info: i}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugPrint {
|
if debugPrint {
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ func init() {
|
|||||||
func LookUpTypeByPacketInfo(direction proto_base.Direction, state proto_base.State, pid, version int32) (p proto_base.PacketInfo, ok bool) {
|
func LookUpTypeByPacketInfo(direction proto_base.Direction, state proto_base.State, pid, version int32) (p proto_base.PacketInfo, ok bool) {
|
||||||
pP, ok := pidMap[PidEtc{direction, state, pid, version}]
|
pP, ok := pidMap[PidEtc{direction, state, pid, version}]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
p = proto_base.PacketInfo{
|
||||||
|
Type: nil,
|
||||||
|
Name: "",
|
||||||
|
Direction: direction,
|
||||||
|
State: state,
|
||||||
|
PacketId: pid,
|
||||||
|
ProtocolVersion: version,
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p = *pP
|
p = *pP
|
||||||
@@ -43,7 +51,7 @@ func LookUpTypeByPacketInfoAndCopyType(direction proto_base.Direction, state pro
|
|||||||
func LookupPacketInfoByType(packet proto_base.EncodeDecodeAble) (p proto_base.PacketInfo, ok bool) {
|
func LookupPacketInfoByType(packet proto_base.EncodeDecodeAble) (p proto_base.PacketInfo, ok bool) {
|
||||||
undecodedPacket, isUndecoable := packet.(*UnCodablePacket)
|
undecodedPacket, isUndecoable := packet.(*UnCodablePacket)
|
||||||
if isUndecoable {
|
if isUndecoable {
|
||||||
p = proto_base.PacketInfo{Type: &UnCodablePacket{}, Name: "un_codable", Direction: undecodedPacket.Direction, State: proto_base.Handshaking, PacketId: -1, ProtocolVersion: -1}
|
p = undecodedPacket.Info
|
||||||
ok = true
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,23 @@ const (
|
|||||||
Play
|
Play
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (s State) String() string {
|
||||||
|
switch s {
|
||||||
|
case Handshaking:
|
||||||
|
return "Handshaking"
|
||||||
|
case Status:
|
||||||
|
return "Status"
|
||||||
|
case Login:
|
||||||
|
return "Login"
|
||||||
|
case Configuration:
|
||||||
|
return "Configuration"
|
||||||
|
case Play:
|
||||||
|
return "Play"
|
||||||
|
default:
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Actor int
|
type Actor int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
Reference in New Issue
Block a user