blob: 06e44be03291d6812fe265b1cf83bb86f33ec849 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package fidlgen
import (
"github.com/google/go-cmp/cmp"
"testing"
)
func TestBuildPaddingMarkersWithoutFlattening(t *testing.T) {
type testCase struct {
name string
in Struct
out []PaddingMarker
}
testCases := []testCase{
{
name: "empty",
in: Struct{},
out: nil,
},
{
name: "no padding 8-bytes",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 8,
Alignment: 8,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 4,
Padding: 0,
},
},
},
},
out: nil,
},
{
name: "no padding 4-bytes",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 4,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 2,
Padding: 0,
},
},
},
},
out: nil,
},
{
name: "no padding 2-bytes",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 2,
Alignment: 2,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 1,
Padding: 0,
},
},
},
},
out: nil,
},
{
name: "no padding 1-byte",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 1,
Alignment: 1,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
},
},
out: nil,
},
{
name: "8-byte struct with 2 bytes of padding at end",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 8,
Alignment: 8,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 4,
Padding: 2,
},
},
},
},
out: []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
},
},
},
{
name: "4-byte struct with 1 byte of padding at end",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 4,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 2,
Padding: 1,
},
},
},
},
out: []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0x00, 0x00, 0xff},
},
},
},
{
name: "2-byte struct with 1 byte padding at end",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 2,
Alignment: 2,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 1,
},
},
},
},
out: []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0xff},
},
},
},
{
name: "padding at end of 8-byte chunk, before next chunk",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 16,
Alignment: 8,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 4,
Padding: 2,
},
},
{
FieldShapeV1: FieldShape{
Offset: 8,
Padding: 0,
},
},
},
},
out: []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
},
},
},
{
name: "padding in middle of 4-byte block",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 4,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 1,
},
},
{
FieldShapeV1: FieldShape{
Offset: 2,
Padding: 0,
},
},
},
},
out: []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0xff, 0x00, 0x00},
},
},
},
{
name: "8 byte mask with non-zero offset",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 16,
Alignment: 8,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 8,
Padding: 4,
},
},
},
},
out: []PaddingMarker{
{
Offset: 8,
Mask: []byte{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
},
},
},
{
name: "4 byte mask with non-zero offset",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 12,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 8,
Padding: 2,
},
},
},
},
out: []PaddingMarker{
{
Offset: 8,
Mask: []byte{0x00, 0x00, 0xff, 0xff},
},
},
},
{
name: "2 byte mask with non-zero offset",
in: Struct{
TypeShapeV1: TypeShape{
InlineSize: 10,
Alignment: 2,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
},
{
FieldShapeV1: FieldShape{
Offset: 8,
Padding: 1,
},
},
},
},
out: []PaddingMarker{
{
Offset: 8,
Mask: []byte{0x00, 0xff},
},
},
},
}
for _, testCase := range testCases {
out := testCase.in.BuildPaddingMarkers(WireFormatVersionV1)
if diff := cmp.Diff(testCase.out, out); diff != "" {
t.Errorf("%s:\nexpected != actual (-want +got)\n%s", testCase.name, diff)
}
}
}
func TestBuildPaddingMarkersFlatteningStruct(t *testing.T) {
var innerStructIdentifier EncodedCompoundIdentifier = "abcd"
innerStruct := Struct{
TypeShapeV1: TypeShape{
InlineSize: 4,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 3,
},
},
},
}
input := Struct{
TypeShapeV1: TypeShape{
InlineSize: 8,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 4,
},
Type: Type{
Kind: IdentifierType,
Identifier: innerStructIdentifier,
},
},
},
}
out := input.BuildFlattenedPaddingMarkers(WireFormatVersionV1, func(identifier EncodedCompoundIdentifier) *Struct {
if identifier == innerStructIdentifier {
return &innerStruct
}
return nil
})
expected := []PaddingMarker{
{
Offset: 0,
Mask: []byte{0x00, 0xff, 0xff, 0xff},
},
{
Offset: 4,
Mask: []byte{0xff, 0xff, 0xff, 0xff},
},
}
if diff := cmp.Diff(expected, out); diff != "" {
t.Errorf("expected != actual (-want +got)\n%s", diff)
}
}
func TestBuildPaddingMarkersFlatteningArray(t *testing.T) {
var innerStructIdentifier EncodedCompoundIdentifier = "abcd"
innerStruct := Struct{
TypeShapeV1: TypeShape{
InlineSize: 4,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 3,
},
},
},
}
count := 3
input := Struct{
TypeShapeV1: TypeShape{
InlineSize: 12,
Alignment: 4,
},
Members: []StructMember{
{
FieldShapeV1: FieldShape{
Offset: 0,
Padding: 0,
},
Type: Type{
Kind: ArrayType,
ElementCount: &count,
ElementType: &Type{
Kind: IdentifierType,
Identifier: innerStructIdentifier,
},
},
},
},
}
out := input.BuildFlattenedPaddingMarkers(WireFormatVersionV1, func(identifier EncodedCompoundIdentifier) *Struct {
if identifier == innerStructIdentifier {
return &innerStruct
}
return nil
})
expected := []PaddingMarker{
{
Offset: 0,
Mask: []uint8{0x00, 0x0ff, 0xff, 0xff},
},
{
Offset: 4,
Mask: []uint8{0x00, 0xff, 0xff, 0xff},
},
{
Offset: 8,
Mask: []byte{0x00, 0xff, 0xff, 0xff},
},
}
if diff := cmp.Diff(expected, out); diff != "" {
t.Errorf("expected != actual (-want +got)\n%s", diff)
}
}