Files
Erupe/network/mhfpacket/msg_parse_medium_test.go
Houmgaor 46bbb6adf9 fix: resolve all remaining lint errors (errcheck) across 49 files
Fix unchecked error returns on bf.Seek(), db.Exec(), QueryRow().Scan(),
pkt.Build(), logger.Sync(), and binary.Write() calls. The linter now
passes with 0 errors, build compiles, and all tests pass with -race.
2026-02-17 18:07:38 +01:00

777 lines
20 KiB
Go

package mhfpacket
import (
"bytes"
"io"
"testing"
"erupe-ce/common/byteframe"
"erupe-ce/network/clientctx"
)
// --- 5-stmt packets (medium complexity) ---
// TestParseMediumVoteFesta verifies Parse for MsgMhfVoteFesta.
// Fields: AckHandle(u32), FestaID(u32), GuildID(u32), TrialID(u32)
func TestParseMediumVoteFesta(t *testing.T) {
tests := []struct {
name string
ack uint32
festaID uint32
guildID uint32
trialID uint32
}{
{"typical", 0x11223344, 1, 500, 42},
{"zero", 0, 0, 0, 0},
{"max", 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
bf.WriteUint32(tt.festaID)
bf.WriteUint32(tt.guildID)
bf.WriteUint32(tt.trialID)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfVoteFesta{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.FestaID != tt.festaID {
t.Errorf("FestaID = %d, want %d", pkt.FestaID, tt.festaID)
}
if pkt.GuildID != tt.guildID {
t.Errorf("GuildID = %d, want %d", pkt.GuildID, tt.guildID)
}
if pkt.TrialID != tt.trialID {
t.Errorf("TrialID = %d, want %d", pkt.TrialID, tt.trialID)
}
})
}
}
// TestParseMediumAcquireSemaphore verifies Parse for MsgSysAcquireSemaphore.
// Fields: AckHandle(u32), SemaphoreIDLength(u8), SemaphoreID(string via bfutil.UpToNull)
func TestParseMediumAcquireSemaphore(t *testing.T) {
tests := []struct {
name string
ack uint32
semaphoreID string
}{
{"typical", 0xAABBCCDD, "quest_semaphore"},
{"short", 1, "s"},
{"empty", 0, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
// SemaphoreIDLength includes the null terminator in the read
idBytes := []byte(tt.semaphoreID)
idBytes = append(idBytes, 0x00) // null terminator
bf.WriteUint8(uint8(len(idBytes)))
bf.WriteBytes(idBytes)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysAcquireSemaphore{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.SemaphoreID != tt.semaphoreID {
t.Errorf("SemaphoreID = %q, want %q", pkt.SemaphoreID, tt.semaphoreID)
}
})
}
}
// TestParseMediumCheckSemaphore verifies Parse for MsgSysCheckSemaphore.
// Fields: AckHandle(u32), semaphoreIDLength(u8), SemaphoreID(string via bfutil.UpToNull)
func TestParseMediumCheckSemaphore(t *testing.T) {
tests := []struct {
name string
ack uint32
semaphoreID string
}{
{"typical", 0x12345678, "global_semaphore"},
{"short id", 42, "x"},
{"empty id", 0, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
idBytes := []byte(tt.semaphoreID)
idBytes = append(idBytes, 0x00)
bf.WriteUint8(uint8(len(idBytes)))
bf.WriteBytes(idBytes)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysCheckSemaphore{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.SemaphoreID != tt.semaphoreID {
t.Errorf("SemaphoreID = %q, want %q", pkt.SemaphoreID, tt.semaphoreID)
}
})
}
}
// TestParseMediumGetUserBinary verifies Parse for MsgSysGetUserBinary.
// Fields: AckHandle(u32), CharID(u32), BinaryType(u8)
func TestParseMediumGetUserBinary(t *testing.T) {
tests := []struct {
name string
ack uint32
charID uint32
binaryType uint8
}{
{"typical", 0xDEADBEEF, 12345, 1},
{"zero", 0, 0, 0},
{"max", 0xFFFFFFFF, 0xFFFFFFFF, 255},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
bf.WriteUint32(tt.charID)
bf.WriteUint8(tt.binaryType)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysGetUserBinary{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.CharID != tt.charID {
t.Errorf("CharID = %d, want %d", pkt.CharID, tt.charID)
}
if pkt.BinaryType != tt.binaryType {
t.Errorf("BinaryType = %d, want %d", pkt.BinaryType, tt.binaryType)
}
})
}
}
// TestParseMediumSetObjectBinary verifies Parse for MsgSysSetObjectBinary.
// Fields: ObjID(u32), DataSize(u16), RawDataPayload([]byte of DataSize)
func TestParseMediumSetObjectBinary(t *testing.T) {
tests := []struct {
name string
objID uint32
payload []byte
}{
{"typical", 42, []byte{0x01, 0x02, 0x03, 0x04}},
{"empty", 0, []byte{}},
{"large", 0xCAFEBABE, []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.objID)
bf.WriteUint16(uint16(len(tt.payload)))
bf.WriteBytes(tt.payload)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysSetObjectBinary{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.ObjID != tt.objID {
t.Errorf("ObjID = %d, want %d", pkt.ObjID, tt.objID)
}
if pkt.DataSize != uint16(len(tt.payload)) {
t.Errorf("DataSize = %d, want %d", pkt.DataSize, len(tt.payload))
}
if !bytes.Equal(pkt.RawDataPayload, tt.payload) {
t.Errorf("RawDataPayload = %v, want %v", pkt.RawDataPayload, tt.payload)
}
})
}
}
// TestParseMediumSetUserBinary verifies Parse for MsgSysSetUserBinary.
// Fields: BinaryType(u8), DataSize(u16), RawDataPayload([]byte of DataSize)
func TestParseMediumSetUserBinary(t *testing.T) {
tests := []struct {
name string
binaryType uint8
payload []byte
}{
{"typical", 1, []byte{0xDE, 0xAD, 0xBE, 0xEF}},
{"empty", 0, []byte{}},
{"max type", 255, []byte{0x01}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint8(tt.binaryType)
bf.WriteUint16(uint16(len(tt.payload)))
bf.WriteBytes(tt.payload)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysSetUserBinary{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.BinaryType != tt.binaryType {
t.Errorf("BinaryType = %d, want %d", pkt.BinaryType, tt.binaryType)
}
if pkt.DataSize != uint16(len(tt.payload)) {
t.Errorf("DataSize = %d, want %d", pkt.DataSize, len(tt.payload))
}
if !bytes.Equal(pkt.RawDataPayload, tt.payload) {
t.Errorf("RawDataPayload = %v, want %v", pkt.RawDataPayload, tt.payload)
}
})
}
}
// --- 4-stmt packets ---
// TestParseMediumGetUdRanking verifies Parse for MsgMhfGetUdRanking.
// Fields: AckHandle(u32), Unk0(u8)
func TestParseMediumGetUdRanking(t *testing.T) {
tests := []struct {
name string
ack uint32
unk0 uint8
}{
{"typical", 0x11223344, 5},
{"zero", 0, 0},
{"max", 0xFFFFFFFF, 255},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
bf.WriteUint8(tt.unk0)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetUdRanking{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.Unk0 != tt.unk0 {
t.Errorf("Unk0 = %d, want %d", pkt.Unk0, tt.unk0)
}
})
}
}
// TestParseMediumGetUdTacticsRanking verifies Parse for MsgMhfGetUdTacticsRanking.
// Fields: AckHandle(u32), GuildID(u32)
func TestParseMediumGetUdTacticsRanking(t *testing.T) {
tests := []struct {
name string
ack uint32
guildID uint32
}{
{"typical", 0xAABBCCDD, 500},
{"zero", 0, 0},
{"max", 0xFFFFFFFF, 0xFFFFFFFF},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
bf.WriteUint32(tt.guildID)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfGetUdTacticsRanking{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if pkt.GuildID != tt.guildID {
t.Errorf("GuildID = %d, want %d", pkt.GuildID, tt.guildID)
}
})
}
}
// TestParseMediumRegistGuildTresure verifies Parse for MsgMhfRegistGuildTresure.
// Fields: AckHandle(u32), DataLen(u16), Data([]byte), trailing u32 (discarded)
func TestParseMediumRegistGuildTresure(t *testing.T) {
tests := []struct {
name string
ack uint32
data []byte
}{
{"typical", 0x12345678, []byte{0x01, 0x02, 0x03}},
{"empty data", 1, []byte{}},
{"larger data", 0xDEADBEEF, []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(tt.ack)
bf.WriteUint16(uint16(len(tt.data)))
bf.WriteBytes(tt.data)
bf.WriteUint32(0) // trailing uint32 that is read and discarded
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfRegistGuildTresure{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != tt.ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, tt.ack)
}
if !bytes.Equal(pkt.Data, tt.data) {
t.Errorf("Data = %v, want %v", pkt.Data, tt.data)
}
})
}
}
// TestParseMediumUpdateMyhouseInfo verifies Parse for MsgMhfUpdateMyhouseInfo.
// Fields: AckHandle(u32), Unk0([]byte of 0x16A bytes)
func TestParseMediumUpdateMyhouseInfo(t *testing.T) {
t.Run("typical", func(t *testing.T) {
bf := byteframe.NewByteFrame()
ack := uint32(0xCAFEBABE)
bf.WriteUint32(ack)
// 0x16A = 362 bytes
payload := make([]byte, 0x16A)
for i := range payload {
payload[i] = byte(i % 256)
}
bf.WriteBytes(payload)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateMyhouseInfo{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
if len(pkt.Data) != 0x16A {
t.Errorf("Unk0 length = %d, want %d", len(pkt.Data), 0x16A)
}
if !bytes.Equal(pkt.Data, payload) {
t.Error("Unk0 content mismatch")
}
})
t.Run("zero values", func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(0)
bf.WriteBytes(make([]byte, 0x16A))
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgMhfUpdateMyhouseInfo{}
if err := pkt.Parse(bf, nil); err != nil {
t.Fatalf("Parse() error = %v", err)
}
if pkt.AckHandle != 0 {
t.Errorf("AckHandle = 0x%X, want 0", pkt.AckHandle)
}
if len(pkt.Data) != 0x16A {
t.Errorf("Unk0 length = %d, want %d", len(pkt.Data), 0x16A)
}
})
}
// --- 3-stmt packets (AckHandle-only Parse) ---
// TestParseMediumAckHandleOnlyBatch tests Parse for all 3-stmt packets that only
// read a single AckHandle uint32. These are verified to parse correctly and
// return the expected AckHandle value.
func TestParseMediumAckHandleOnlyBatch(t *testing.T) {
packets := []struct {
name string
pkt MHFPacket
// getAck extracts the AckHandle from the parsed packet
getAck func() uint32
}{
{
"MsgMhfGetUdBonusQuestInfo",
&MsgMhfGetUdBonusQuestInfo{},
nil,
},
{
"MsgMhfGetUdDailyPresentList",
&MsgMhfGetUdDailyPresentList{},
nil,
},
{
"MsgMhfGetUdGuildMapInfo",
&MsgMhfGetUdGuildMapInfo{},
nil,
},
{
"MsgMhfGetUdMonsterPoint",
&MsgMhfGetUdMonsterPoint{},
nil,
},
{
"MsgMhfGetUdMyRanking",
&MsgMhfGetUdMyRanking{},
nil,
},
{
"MsgMhfGetUdNormaPresentList",
&MsgMhfGetUdNormaPresentList{},
nil,
},
{
"MsgMhfGetUdRankingRewardList",
&MsgMhfGetUdRankingRewardList{},
nil,
},
{
"MsgMhfGetUdSelectedColorInfo",
&MsgMhfGetUdSelectedColorInfo{},
nil,
},
{
"MsgMhfGetUdShopCoin",
&MsgMhfGetUdShopCoin{},
nil,
},
{
"MsgMhfGetUdTacticsBonusQuest",
&MsgMhfGetUdTacticsBonusQuest{},
nil,
},
{
"MsgMhfGetUdTacticsFirstQuestBonus",
&MsgMhfGetUdTacticsFirstQuestBonus{},
nil,
},
{
"MsgMhfGetUdTacticsFollower",
&MsgMhfGetUdTacticsFollower{},
nil,
},
{
"MsgMhfGetUdTacticsLog",
&MsgMhfGetUdTacticsLog{},
nil,
},
{
"MsgMhfGetUdTacticsPoint",
&MsgMhfGetUdTacticsPoint{},
nil,
},
{
"MsgMhfGetUdTacticsRewardList",
&MsgMhfGetUdTacticsRewardList{},
nil,
},
{
"MsgMhfReceiveCafeDurationBonus",
&MsgMhfReceiveCafeDurationBonus{},
nil,
},
{
"MsgSysDeleteSemaphore",
&MsgSysDeleteSemaphore{},
nil,
},
{
"MsgSysReleaseSemaphore",
&MsgSysReleaseSemaphore{},
nil,
},
}
ctx := &clientctx.ClientContext{}
ackValues := []uint32{0x12345678, 0, 0xFFFFFFFF, 0xDEADBEEF}
for _, tc := range packets {
for _, ackVal := range ackValues {
t.Run(tc.name+"/ack_"+ackHex(ackVal), func(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(ackVal)
_, _ = bf.Seek(0, io.SeekStart)
err := tc.pkt.Parse(bf, ctx)
if err != nil {
t.Fatalf("Parse() error = %v", err)
}
})
}
}
}
// TestParseMediumAckHandleOnlyVerifyValues tests each 3-stmt AckHandle-only
// packet individually, verifying that the AckHandle field is correctly populated.
func TestParseMediumAckHandleOnlyVerifyValues(t *testing.T) {
ctx := &clientctx.ClientContext{}
ack := uint32(0xCAFEBABE)
makeFrame := func() *byteframe.ByteFrame {
bf := byteframe.NewByteFrame()
bf.WriteUint32(ack)
_, _ = bf.Seek(0, io.SeekStart)
return bf
}
t.Run("MsgMhfGetUdBonusQuestInfo", func(t *testing.T) {
pkt := &MsgMhfGetUdBonusQuestInfo{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdDailyPresentList", func(t *testing.T) {
pkt := &MsgMhfGetUdDailyPresentList{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdGuildMapInfo", func(t *testing.T) {
pkt := &MsgMhfGetUdGuildMapInfo{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdMonsterPoint", func(t *testing.T) {
pkt := &MsgMhfGetUdMonsterPoint{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdMyRanking", func(t *testing.T) {
pkt := &MsgMhfGetUdMyRanking{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdNormaPresentList", func(t *testing.T) {
pkt := &MsgMhfGetUdNormaPresentList{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdRankingRewardList", func(t *testing.T) {
pkt := &MsgMhfGetUdRankingRewardList{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdSelectedColorInfo", func(t *testing.T) {
pkt := &MsgMhfGetUdSelectedColorInfo{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdShopCoin", func(t *testing.T) {
pkt := &MsgMhfGetUdShopCoin{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsBonusQuest", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsBonusQuest{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsFirstQuestBonus", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsFirstQuestBonus{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsFollower", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsFollower{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsLog", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsLog{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsPoint", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsPoint{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfGetUdTacticsRewardList", func(t *testing.T) {
pkt := &MsgMhfGetUdTacticsRewardList{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgMhfReceiveCafeDurationBonus", func(t *testing.T) {
pkt := &MsgMhfReceiveCafeDurationBonus{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
t.Run("MsgSysDeleteSemaphore", func(t *testing.T) {
pkt := &MsgSysDeleteSemaphore{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.SemaphoreID != ack {
t.Errorf("SemaphoreID = 0x%X, want 0x%X", pkt.SemaphoreID, ack)
}
})
t.Run("MsgSysReleaseSemaphore", func(t *testing.T) {
pkt := &MsgSysReleaseSemaphore{}
if err := pkt.Parse(makeFrame(), ctx); err != nil {
t.Fatal(err)
}
if pkt.AckHandle != ack {
t.Errorf("AckHandle = 0x%X, want 0x%X", pkt.AckHandle, ack)
}
})
}
// TestParseMediumDeleteUser verifies that MsgSysDeleteUser.Parse returns
// NOT IMPLEMENTED error (Parse is not implemented, only Build is).
func TestParseMediumDeleteUser(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(12345)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysDeleteUser{}
err := pkt.Parse(bf, nil)
if err == nil {
t.Fatal("Parse() should return error for NOT IMPLEMENTED")
}
if err.Error() != "NOT IMPLEMENTED" {
t.Errorf("Parse() error = %q, want %q", err.Error(), "NOT IMPLEMENTED")
}
}
// TestParseMediumInsertUser verifies that MsgSysInsertUser.Parse returns
// NOT IMPLEMENTED error (Parse is not implemented, only Build is).
func TestParseMediumInsertUser(t *testing.T) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(12345)
_, _ = bf.Seek(0, io.SeekStart)
pkt := &MsgSysInsertUser{}
err := pkt.Parse(bf, nil)
if err == nil {
t.Fatal("Parse() should return error for NOT IMPLEMENTED")
}
if err.Error() != "NOT IMPLEMENTED" {
t.Errorf("Parse() error = %q, want %q", err.Error(), "NOT IMPLEMENTED")
}
}
// ackHex returns a hex string for a uint32 ack value, used for test naming.
func ackHex(v uint32) string {
const hex = "0123456789ABCDEF"
buf := make([]byte, 8)
for i := 7; i >= 0; i-- {
buf[i] = hex[v&0xF]
v >>= 4
}
return string(buf)
}