internal/pipewire: store sample iovec continuously
All checks were successful
Test / Create distribution (push) Successful in 39s
Test / Sandbox (push) Successful in 2m22s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m28s
Test / Hakurei (race detector) (push) Successful in 5m14s
Test / Hakurei (push) Successful in 2m26s
Test / Flake checks (push) Successful in 1m39s

This removes the need for manual splitting. The understanding of the format is robust enough to allow this to happen anyway.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-11-28 00:34:32 +09:00
parent 1dab87aaf0
commit 72a2601d74
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
31 changed files with 72 additions and 74 deletions

View File

@ -10,7 +10,7 @@ func TestClientInfo(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.ClientInfo, *pipewire.ClientInfo]{ encodingTestCases[pipewire.ClientInfo, *pipewire.ClientInfo]{
{"sample", []byte(c1r2pod), pipewire.ClientInfo{ {"sample", samplePWContainer[1][2][1], pipewire.ClientInfo{
ID: 34, ID: 34,
ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS,
Props: &pipewire.SPADict{NItems: 9, Items: []pipewire.SPADictItem{ Props: &pipewire.SPADict{NItems: 9, Items: []pipewire.SPADictItem{
@ -25,7 +25,7 @@ func TestClientInfo(t *testing.T) {
{Key: "object.serial", Value: "34"}, {Key: "object.serial", Value: "34"},
}}}, nil}, }}}, nil},
{"sample*", []byte(c1r3pod), pipewire.ClientInfo{ {"sample*", samplePWContainer[1][3][1], pipewire.ClientInfo{
ID: 34, ID: 34,
ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS,
Props: &pipewire.SPADict{NItems: 38, Items: []pipewire.SPADictItem{ Props: &pipewire.SPADict{NItems: 38, Items: []pipewire.SPADictItem{
@ -69,7 +69,7 @@ func TestClientInfo(t *testing.T) {
{Key: "core.version", Value: "1.4.7"}, {Key: "core.version", Value: "1.4.7"},
}}}, nil}, }}}, nil},
{"sample**", []byte(c1r4pod), pipewire.ClientInfo{ {"sample**", samplePWContainer[1][4][1], pipewire.ClientInfo{
ID: 34, ID: 34,
ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS, ChangeMask: pipewire.PW_CLIENT_CHANGE_MASK_PROPS,
Props: &pipewire.SPADict{NItems: 39, Items: []pipewire.SPADictItem{ Props: &pipewire.SPADict{NItems: 39, Items: []pipewire.SPADictItem{
@ -120,7 +120,7 @@ func TestClientUpdateProperties(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.ClientUpdateProperties, *pipewire.ClientUpdateProperties]{ encodingTestCases[pipewire.ClientUpdateProperties, *pipewire.ClientUpdateProperties]{
{"sample", []byte(c0s1pod), pipewire.ClientUpdateProperties{Props: &pipewire.SPADict{NItems: 0x1e, Items: []pipewire.SPADictItem{ {"sample", samplePWContainer[0][1][1], pipewire.ClientUpdateProperties{Props: &pipewire.SPADict{NItems: 0x1e, Items: []pipewire.SPADictItem{
{Key: "remote.intention", Value: "manager"}, {Key: "remote.intention", Value: "manager"},
{Key: "application.name", Value: "pw-container"}, {Key: "application.name", Value: "pw-container"},
{Key: "application.process.binary", Value: "pw-container"}, {Key: "application.process.binary", Value: "pw-container"},

View File

@ -10,12 +10,12 @@ func TestFooterCoreGeneration(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.Footer[pipewire.FooterCoreGeneration], *pipewire.Footer[pipewire.FooterCoreGeneration]]{ encodingTestCases[pipewire.Footer[pipewire.FooterCoreGeneration], *pipewire.Footer[pipewire.FooterCoreGeneration]]{
{"sample", []byte(c1r0footer), pipewire.Footer[pipewire.FooterCoreGeneration]{ {"sample", samplePWContainer[1][0][2], pipewire.Footer[pipewire.FooterCoreGeneration]{
Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION, Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION,
Payload: pipewire.FooterCoreGeneration{RegistryGeneration: 0x22}, Payload: pipewire.FooterCoreGeneration{RegistryGeneration: 0x22},
}, nil}, }, nil},
{"sample*", []byte(c1r5footer), pipewire.Footer[pipewire.FooterCoreGeneration]{ {"sample*", samplePWContainer[1][5][2], pipewire.Footer[pipewire.FooterCoreGeneration]{
Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION, Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION,
Payload: pipewire.FooterCoreGeneration{RegistryGeneration: 0x23}, Payload: pipewire.FooterCoreGeneration{RegistryGeneration: 0x23},
}, nil}, }, nil},
@ -26,7 +26,7 @@ func TestCoreInfo(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreInfo, *pipewire.CoreInfo]{ encodingTestCases[pipewire.CoreInfo, *pipewire.CoreInfo]{
{"sample", []byte(c1r0pod), pipewire.CoreInfo{ {"sample", samplePWContainer[1][0][1], pipewire.CoreInfo{
ID: 0, ID: 0,
Cookie: -2069267610, Cookie: -2069267610,
UserName: "alice", UserName: "alice",
@ -74,7 +74,7 @@ func TestCoreDone(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreDone, *pipewire.CoreDone]{ encodingTestCases[pipewire.CoreDone, *pipewire.CoreDone]{
{"sample", []byte(c1r5pod), pipewire.CoreDone{ {"sample", samplePWContainer[1][5][1], pipewire.CoreDone{
ID: -1, ID: -1,
Sequence: 0, Sequence: 0,
}, nil}, }, nil},
@ -85,7 +85,7 @@ func TestCoreBoundProps(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreBoundProps, *pipewire.CoreBoundProps]{ encodingTestCases[pipewire.CoreBoundProps, *pipewire.CoreBoundProps]{
{"sample", []byte(c1r1pod), pipewire.CoreBoundProps{ {"sample", samplePWContainer[1][1][1], pipewire.CoreBoundProps{
ID: pipewire.PW_ID_CLIENT, ID: pipewire.PW_ID_CLIENT,
GlobalID: 34, GlobalID: 34,
Props: &pipewire.SPADict{NItems: 7, Items: []pipewire.SPADictItem{ Props: &pipewire.SPADict{NItems: 7, Items: []pipewire.SPADictItem{
@ -104,7 +104,7 @@ func TestCoreHello(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreHello, *pipewire.CoreHello]{ encodingTestCases[pipewire.CoreHello, *pipewire.CoreHello]{
{"sample", []byte(c0s0pod), pipewire.CoreHello{ {"sample", samplePWContainer[0][0][1], pipewire.CoreHello{
Version: pipewire.PW_VERSION_CORE, Version: pipewire.PW_VERSION_CORE,
}, nil}, }, nil},
}.run(t) }.run(t)
@ -114,7 +114,7 @@ func TestCoreSync(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreSync, *pipewire.CoreSync]{ encodingTestCases[pipewire.CoreSync, *pipewire.CoreSync]{
{"sample", []byte(c0s3pod), pipewire.CoreSync{ {"sample", samplePWContainer[0][3][1], pipewire.CoreSync{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Sequence: pipewire.CoreSyncSequenceOffset + 3, Sequence: pipewire.CoreSyncSequenceOffset + 3,
}, nil}, }, nil},
@ -125,7 +125,7 @@ func TestCoreGetRegistry(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.CoreGetRegistry, *pipewire.CoreGetRegistry]{ encodingTestCases[pipewire.CoreGetRegistry, *pipewire.CoreGetRegistry]{
{"sample", []byte(c0s2pod), pipewire.CoreGetRegistry{ {"sample", samplePWContainer[0][2][1], pipewire.CoreGetRegistry{
Version: pipewire.PW_VERSION_REGISTRY, Version: pipewire.PW_VERSION_REGISTRY,
NewID: 2, NewID: 2,
}, nil}, }, nil},

View File

@ -11,61 +11,61 @@ func TestHeader(t *testing.T) {
t.Parallel() t.Parallel()
encodingTestCases[pipewire.Header, *pipewire.Header]{ encodingTestCases[pipewire.Header, *pipewire.Header]{
{"PW_CORE_METHOD_HELLO", []byte(c0s0header), pipewire.Header{ {"PW_CORE_METHOD_HELLO", samplePWContainer[0][0][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_METHOD_HELLO, Opcode: pipewire.PW_CORE_METHOD_HELLO,
Size: 0x18, Sequence: 0, FileCount: 0, Size: 0x18, Sequence: 0, FileCount: 0,
}, nil}, }, nil},
{"PW_CLIENT_METHOD_UPDATE_PROPERTIES", []byte(c0s1header), pipewire.Header{ {"PW_CLIENT_METHOD_UPDATE_PROPERTIES", samplePWContainer[0][1][0], pipewire.Header{
ID: pipewire.PW_ID_CLIENT, ID: pipewire.PW_ID_CLIENT,
Opcode: pipewire.PW_CLIENT_METHOD_UPDATE_PROPERTIES, Opcode: pipewire.PW_CLIENT_METHOD_UPDATE_PROPERTIES,
Size: 0x600, Sequence: 1, FileCount: 0, Size: 0x600, Sequence: 1, FileCount: 0,
}, nil}, }, nil},
{"PW_CORE_METHOD_GET_REGISTRY", []byte(c0s2header), pipewire.Header{ {"PW_CORE_METHOD_GET_REGISTRY", samplePWContainer[0][2][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_METHOD_GET_REGISTRY, Opcode: pipewire.PW_CORE_METHOD_GET_REGISTRY,
Size: 0x28, Sequence: 2, FileCount: 0, Size: 0x28, Sequence: 2, FileCount: 0,
}, nil}, }, nil},
{"PW_CORE_METHOD_SYNC", []byte(c0s3header), pipewire.Header{ {"PW_CORE_METHOD_SYNC", samplePWContainer[0][3][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_METHOD_SYNC, Opcode: pipewire.PW_CORE_METHOD_SYNC,
Size: 0x28, Sequence: 3, FileCount: 0, Size: 0x28, Sequence: 3, FileCount: 0,
}, nil}, }, nil},
{"PW_CORE_EVENT_INFO", []byte(c1r0header), pipewire.Header{ {"PW_CORE_EVENT_INFO", samplePWContainer[1][0][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_EVENT_INFO, Opcode: pipewire.PW_CORE_EVENT_INFO,
Size: 0x6b8, Sequence: 0, FileCount: 0, Size: 0x6b8, Sequence: 0, FileCount: 0,
}, nil}, }, nil},
{"PW_CORE_EVENT_BOUND_PROPS", []byte(c1r1header), pipewire.Header{ {"PW_CORE_EVENT_BOUND_PROPS", samplePWContainer[1][1][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_EVENT_BOUND_PROPS, Opcode: pipewire.PW_CORE_EVENT_BOUND_PROPS,
Size: 0x198, Sequence: 1, FileCount: 0, Size: 0x198, Sequence: 1, FileCount: 0,
}, nil}, }, nil},
{"PW_CLIENT_EVENT_INFO", []byte(c1r2header), pipewire.Header{ {"PW_CLIENT_EVENT_INFO", samplePWContainer[1][2][0], pipewire.Header{
ID: pipewire.PW_ID_CLIENT, ID: pipewire.PW_ID_CLIENT,
Opcode: pipewire.PW_CLIENT_EVENT_INFO, Opcode: pipewire.PW_CLIENT_EVENT_INFO,
Size: 0x1f0, Sequence: 2, FileCount: 0, Size: 0x1f0, Sequence: 2, FileCount: 0,
}, nil}, }, nil},
{"PW_CLIENT_EVENT_INFO*", []byte(c1r3header), pipewire.Header{ {"PW_CLIENT_EVENT_INFO*", samplePWContainer[1][3][0], pipewire.Header{
ID: pipewire.PW_ID_CLIENT, ID: pipewire.PW_ID_CLIENT,
Opcode: pipewire.PW_CLIENT_EVENT_INFO, Opcode: pipewire.PW_CLIENT_EVENT_INFO,
Size: 0x7a0, Sequence: 3, FileCount: 0, Size: 0x7a0, Sequence: 3, FileCount: 0,
}, nil}, }, nil},
{"PW_CLIENT_EVENT_INFO**", []byte(c1r4header), pipewire.Header{ {"PW_CLIENT_EVENT_INFO**", samplePWContainer[1][4][0], pipewire.Header{
ID: pipewire.PW_ID_CLIENT, ID: pipewire.PW_ID_CLIENT,
Opcode: pipewire.PW_CLIENT_EVENT_INFO, Opcode: pipewire.PW_CLIENT_EVENT_INFO,
Size: 0x7d0, Sequence: 4, FileCount: 0, Size: 0x7d0, Sequence: 4, FileCount: 0,
}, nil}, }, nil},
{"PW_CORE_EVENT_DONE", []byte(c1r5header), pipewire.Header{ {"PW_CORE_EVENT_DONE", samplePWContainer[1][5][0], pipewire.Header{
ID: pipewire.PW_ID_CORE, ID: pipewire.PW_ID_CORE,
Opcode: pipewire.PW_CORE_EVENT_DONE, Opcode: pipewire.PW_CORE_EVENT_DONE,
Size: 0x58, Sequence: 5, FileCount: 0, Size: 0x58, Sequence: 5, FileCount: 0,

View File

@ -2,60 +2,58 @@ package pipewire_test
import ( import (
_ "embed" _ "embed"
"encoding/binary"
"hakurei.app/internal/pipewire"
) )
var ( var (
//go:embed testdata/c0s0p0 //go:embed testdata/pw-container-00-sendmsg
c0s0header string samplePWContainer00 string
//go:embed testdata/c0s0p1 //go:embed testdata/pw-container-01-recvmsg
c0s0pod string samplePWContainer01 string
//go:embed testdata/pw-container-03-sendmsg
samplePWContainer03 string
//go:embed testdata/pw-container-04-recvmsg
samplePWContainer04 string
//go:embed testdata/pw-container-06-sendmsg
samplePWContainer06 string
//go:embed testdata/pw-container-07-recvmsg
samplePWContainer07 string
//go:embed testdata/c0s1p0 // samplePWContainer is a collection of messages from the pw-container sample.
c0s1header string samplePWContainer = [...][][3][]byte{
//go:embed testdata/c0s1p1 splitMessages(samplePWContainer00),
c0s1pod string splitMessages(samplePWContainer01),
nil,
//go:embed testdata/c0s2p0 splitMessages(samplePWContainer03),
c0s2header string splitMessages(samplePWContainer04),
//go:embed testdata/c0s2p1 nil,
c0s2pod string splitMessages(samplePWContainer06),
splitMessages(samplePWContainer07),
//go:embed testdata/c0s3p0 nil,
c0s3header string }
//go:embed testdata/c0s3p1
c0s3pod string
//go:embed testdata/c1r0p0
c1r0header string
//go:embed testdata/c1r0p1
c1r0pod string
//go:embed testdata/c1r0p2
c1r0footer string
//go:embed testdata/c1r1p0
c1r1header string
//go:embed testdata/c1r1p1
c1r1pod string
//go:embed testdata/c1r2p0
c1r2header string
//go:embed testdata/c1r2p1
c1r2pod string
//go:embed testdata/c1r3p0
c1r3header string
//go:embed testdata/c1r3p1
c1r3pod string
//go:embed testdata/c1r4p0
c1r4header string
//go:embed testdata/c1r4p1
c1r4pod string
//go:embed testdata/c1r5p0
c1r5header string
//go:embed testdata/c1r5p1
c1r5pod string
//go:embed testdata/c1r5p2
c1r5footer string
) )
// splitMessages splits concatenated messages into groups of
// header, payload, footer of each individual message.
// splitMessages panics on any decoding error.
func splitMessages(iovec string) (messages [][3][]byte) {
data := []byte(iovec)
messages = make([][3][]byte, 0, 1<<7)
var header pipewire.Header
for len(data) != 0 {
if err := header.UnmarshalBinary(data[:pipewire.SizeHeader]); err != nil {
panic(err)
}
size := pipewire.SizePrefix + binary.NativeEndian.Uint32(data[pipewire.SizeHeader:])
messages = append(messages, [3][]byte{
data[:pipewire.SizeHeader],
data[pipewire.SizeHeader : pipewire.SizeHeader+size],
data[pipewire.SizeHeader+size : pipewire.SizeHeader+header.Size],
})
data = data[pipewire.SizeHeader+header.Size:]
}
return
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.