package internalwasm import ( "math" "testing" "github.com/stretchr/testify/require" ) func TestMemoryInstance_HasLen(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string offset uint32 sizeInBytes uint64 expected bool }{ { name: "simple valid arguments", offset: 0, // arbitrary valid offset sizeInBytes: 8, // arbitrary valid size expected: true, }, { name: "maximum valid sizeInBytes", offset: memory.Len() - 8, sizeInBytes: 8, expected: true, }, { name: "sizeInBytes exceeds the valid size by 1", offset: 100, // arbitrary valid offset sizeInBytes: uint64(memory.Len() - 99), expected: false, }, { name: "offset exceeds the memory size", offset: memory.Len(), sizeInBytes: 1, // arbitrary size expected: false, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expected, memory.hasLen(tc.offset, uint32(tc.sizeInBytes))) }) } } func TestMemoryInstance_ReadUint32Le(t *testing.T) { tests := []struct { name string memory []byte offset uint32 expected uint32 expectedOk bool }{ { name: "valid offset with an endian-insensitive v", memory: []byte{0xff, 0xff, 0xff, 0xff}, offset: 0, // arbitrary valid offset. expected: math.MaxUint32, expectedOk: true, }, { name: "valid offset with an endian-sensitive v", memory: []byte{0xfe, 0xff, 0xff, 0xff}, offset: 0, // arbitrary valid offset. expected: math.MaxUint32 - 1, expectedOk: true, }, { name: "maximum boundary valid offset", offset: 1, memory: []byte{0x00, 0x1, 0x00, 0x00, 0x00}, expected: 1, // arbitrary valid v expectedOk: true, }, { name: "offset exceeds the maximum valid offset by 1", memory: []byte{0xff, 0xff, 0xff, 0xff}, offset: 1, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { memory := &MemoryInstance{Buffer: tc.memory} v, ok := memory.ReadUint32Le(tc.offset) require.Equal(t, tc.expectedOk, ok) require.Equal(t, tc.expected, v) }) } } func TestMemoryInstance_ReadUint64Le(t *testing.T) { tests := []struct { name string memory []byte offset uint32 expected uint64 expectedOk bool }{ { name: "valid offset with an endian-insensitive v", memory: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, offset: 0, // arbitrary valid offset. expected: math.MaxUint64, expectedOk: true, }, { name: "valid offset with an endian-sensitive v", memory: []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, offset: 0, // arbitrary valid offset. expected: math.MaxUint64 - 1, expectedOk: true, }, { name: "maximum boundary valid offset", offset: 1, memory: []byte{0x00, 0x1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, expected: 1, // arbitrary valid v expectedOk: true, }, { name: "offset exceeds the maximum valid offset by 1", memory: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, offset: 1, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { memory := &MemoryInstance{Buffer: tc.memory} v, ok := memory.ReadUint64Le(tc.offset) require.Equal(t, tc.expectedOk, ok) require.Equal(t, tc.expected, v) }) } } func TestMemoryInstance_ReadFloat32Le(t *testing.T) { tests := []struct { name string memory []byte offset uint32 expected float32 expectedOk bool }{ { name: "valid offset with an endian-insensitive v", memory: []byte{0xff, 0x00, 0x00, 0xff}, offset: 0, // arbitrary valid offset. expected: math.Float32frombits(uint32(0xff0000ff)), expectedOk: true, }, { name: "valid offset with an endian-sensitive v", memory: []byte{0xfe, 0x00, 0x00, 0xff}, offset: 0, // arbitrary valid offset. expected: math.Float32frombits(uint32(0xff0000fe)), expectedOk: true, }, { name: "maximum boundary valid offset", offset: 1, memory: []byte{0x00, 0xcd, 0xcc, 0xcc, 0x3d}, expected: 0.1, // arbitrary valid v expectedOk: true, }, { name: "offset exceeds the maximum valid offset by 1", memory: []byte{0xff, 0xff, 0xff, 0xff}, offset: 1, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { memory := &MemoryInstance{Buffer: tc.memory} v, ok := memory.ReadFloat32Le(tc.offset) require.Equal(t, tc.expectedOk, ok) require.Equal(t, tc.expected, v) }) } } func TestMemoryInstance_ReadFloat64Le(t *testing.T) { tests := []struct { name string memory []byte offset uint32 expected float64 expectedOk bool }{ { name: "valid offset with an endian-insensitive v", memory: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, offset: 0, // arbitrary valid offset. expected: math.Float64frombits(uint64(0xff000000000000ff)), expectedOk: true, }, { name: "valid offset with an endian-sensitive v", memory: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f}, offset: 0, // arbitrary valid offset. expected: math.MaxFloat64, // arbitrary valid v expectedOk: true, }, { name: "maximum boundary valid offset", offset: 1, memory: []byte{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f}, expected: math.MaxFloat64, // arbitrary valid v expectedOk: true, }, { name: "offset exceeds the maximum valid offset by 1", memory: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, offset: 1, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { memory := &MemoryInstance{Buffer: tc.memory} v, ok := memory.ReadFloat64Le(tc.offset) require.Equal(t, tc.expectedOk, ok) require.Equal(t, tc.expected, v) }) } } func TestMemoryInstance_WriteUint32Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string offset uint32 v uint32 expectedOk bool expectedBytes []byte }{ { name: "valid offset with an endian-insensitive v", offset: 0, // arbitrary valid offset. v: math.MaxUint32, expectedOk: true, expectedBytes: []byte{0xff, 0xff, 0xff, 0xff}, }, { name: "valid offset with an endian-sensitive v", offset: 0, // arbitrary valid offset. v: math.MaxUint32 - 1, expectedOk: true, expectedBytes: []byte{0xfe, 0xff, 0xff, 0xff}, }, { name: "maximum boundary valid offset", offset: memory.Len() - 4, // 4 is the size of uint32 v: 1, // arbitrary valid v expectedOk: true, expectedBytes: []byte{0x1, 0x00, 0x00, 0x00}, }, { name: "offset exceeds the maximum valid offset by 1", offset: memory.Len() - 4 + 1, // 4 is the size of uint32 v: 1, // arbitrary valid v expectedBytes: []byte{0xff, 0xff, 0xff, 0xff}, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectedOk, memory.WriteUint32Le(tc.offset, tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+4]) // 4 is the size of uint32 } }) } } func TestMemoryInstance_WriteUint64Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string offset uint32 v uint64 expectedOk bool expectedBytes []byte }{ { name: "valid offset with an endian-insensitive v", offset: 0, // arbitrary valid offset. v: math.MaxUint64, expectedOk: true, expectedBytes: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, }, { name: "valid offset with an endian-sensitive v", offset: 0, // arbitrary valid offset. v: math.MaxUint64 - 1, expectedOk: true, expectedBytes: []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, }, { name: "maximum boundary valid offset", offset: memory.Len() - 8, // 8 is the size of uint64 v: 1, // arbitrary valid v expectedOk: true, expectedBytes: []byte{0x1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }, { name: "offset exceeds the maximum valid offset by 1", offset: memory.Len() - 8 + 1, // 8 is the size of uint64 v: 1, // arbitrary valid v expectedOk: false, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectedOk, memory.WriteUint64Le(tc.offset, tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+8]) // 8 is the size of uint64 } }) } } func TestMemoryInstance_WriteFloat32Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string offset uint32 v float32 expectedOk bool expectedBytes []byte }{ { name: "valid offset with an endian-insensitive v", offset: 0, // arbitrary valid offset. v: math.Float32frombits(uint32(0xff0000ff)), expectedOk: true, expectedBytes: []byte{0xff, 0x00, 0x00, 0xff}, }, { name: "valid offset with an endian-sensitive v", offset: 0, // arbitrary valid offset. v: math.Float32frombits(uint32(0xff0000fe)), // arbitrary valid v expectedOk: true, expectedBytes: []byte{0xfe, 0x00, 0x00, 0xff}, }, { name: "maximum boundary valid offset", offset: memory.Len() - 4, // 4 is the size of float32 v: 0.1, // arbitrary valid v expectedOk: true, expectedBytes: []byte{0xcd, 0xcc, 0xcc, 0x3d}, }, { name: "offset exceeds the maximum valid offset by 1", offset: memory.Len() - 4 + 1, // 4 is the size of float32 v: math.MaxFloat32, // arbitrary valid v expectedBytes: []byte{0xff, 0xff, 0xff, 0xff}, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectedOk, memory.WriteFloat32Le(tc.offset, tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+4]) // 4 is the size of float32 } }) } } func TestMemoryInstance_WriteFloat64Le(t *testing.T) { memory := &MemoryInstance{Buffer: make([]byte, 100)} tests := []struct { name string offset uint32 v float64 expectedOk bool expectedBytes []byte }{ { name: "valid offset with an endian-insensitive v", offset: 0, // arbitrary valid offset. v: math.Float64frombits(uint64(0xff000000000000ff)), expectedOk: true, expectedBytes: []byte{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, }, { name: "valid offset with an endian-sensitive v", offset: 0, // arbitrary valid offset. v: math.MaxFloat64, // arbitrary valid v expectedOk: true, expectedBytes: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f}, }, { name: "maximum boundary valid offset", offset: memory.Len() - 8, // 8 is the size of float64 v: math.MaxFloat64, // arbitrary valid v expectedOk: true, expectedBytes: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f}, }, { name: "offset exceeds the maximum valid offset by 1", offset: memory.Len() - 8 + 1, // 8 is the size of float64 v: math.MaxFloat64, // arbitrary valid v expectedOk: false, }, } for _, tt := range tests { tc := tt t.Run(tc.name, func(t *testing.T) { require.Equal(t, tc.expectedOk, memory.WriteFloat64Le(tc.offset, tc.v)) if tc.expectedOk { require.Equal(t, tc.expectedBytes, memory.Buffer[tc.offset:tc.offset+8]) // 8 is the size of float64 } }) } }